From 58289f203899a4bcc5f71972f53b64882c71d453 Mon Sep 17 00:00:00 2001
From: Vasyl Khrystiuk
Date: Wed, 2 Aug 2023 02:59:28 +0300
Subject: [PATCH] default error modes set per specification of flavours
---
src/main/java/liqp/TemplateContext.java | 2 +-
src/main/java/liqp/nodes/OutputNode.java | 13 ++++++--
src/main/java/liqp/parser/Flavor.java | 2 +-
src/main/java/liqp/parser/v4/NodeVisitor.java | 8 +++--
src/test/java/liqp/nodes/GtNodeTest.java | 32 +++++++++++++++++++
5 files changed, 50 insertions(+), 7 deletions(-)
diff --git a/src/main/java/liqp/TemplateContext.java b/src/main/java/liqp/TemplateContext.java
index b6e56fff..fd89ca0c 100644
--- a/src/main/java/liqp/TemplateContext.java
+++ b/src/main/java/liqp/TemplateContext.java
@@ -30,7 +30,7 @@ public class TemplateContext {
private Map environmentMap;
private Map registry;
- private List errors;
+ private final List errors;
private final Template template;
public TemplateContext() {
diff --git a/src/main/java/liqp/nodes/OutputNode.java b/src/main/java/liqp/nodes/OutputNode.java
index d712bf42..2ea9be05 100644
--- a/src/main/java/liqp/nodes/OutputNode.java
+++ b/src/main/java/liqp/nodes/OutputNode.java
@@ -2,6 +2,7 @@
import liqp.TemplateContext;
import liqp.TemplateParser;
+import liqp.exceptions.LiquidException;
import org.jsoup.internal.StringUtil;
import java.util.ArrayList;
@@ -11,12 +12,14 @@ public class OutputNode implements LNode {
private LNode expression;
private String unparsed;
+ private Integer unparsedline;
private Integer unparsedPosition;
private List filters;
- public OutputNode(LNode expression, String unparsed, Integer unparsedPosition) {
+ public OutputNode(LNode expression, String unparsed, Integer unparsedline, Integer unparsedPosition) {
this.expression = expression;
this.unparsed = unparsed;
+ this.unparsedline = unparsedline;
this.unparsedPosition = unparsedPosition;
this.filters = new ArrayList<>();
}
@@ -39,7 +42,13 @@ public Object render(TemplateContext context) {
if (localUnparsed.length() > 30) {
localUnparsed = localUnparsed.substring(0, 30) + "...";
}
- context.addError(new RuntimeException("unexpected output: " + localUnparsed + " at position " + unparsedPosition));
+ if (unparsedline == null) {
+ unparsedline = -1;
+ }
+ if (unparsedPosition == null) {
+ unparsedPosition = -1;
+ }
+ context.addError(new LiquidException("unexpected output: " + localUnparsed, unparsedline, unparsedPosition, null));
}
}
diff --git a/src/main/java/liqp/parser/Flavor.java b/src/main/java/liqp/parser/Flavor.java
index a29f1e0f..a18963e7 100644
--- a/src/main/java/liqp/parser/Flavor.java
+++ b/src/main/java/liqp/parser/Flavor.java
@@ -8,7 +8,7 @@ public enum Flavor {
LIQUID("snippets",
Filters.DEFAULT_FILTERS,
Insertions.STANDARD_INSERTIONS,
- TemplateParser.ErrorMode.LAX,
+ TemplateParser.ErrorMode.STRICT,
true,
true,
false
diff --git a/src/main/java/liqp/parser/v4/NodeVisitor.java b/src/main/java/liqp/parser/v4/NodeVisitor.java
index 582d37a6..4873346b 100644
--- a/src/main/java/liqp/parser/v4/NodeVisitor.java
+++ b/src/main/java/liqp/parser/v4/NodeVisitor.java
@@ -532,15 +532,17 @@ public LNode visitFilename(FilenameContext ctx) {
public LNode visitOutput(OutputContext ctx) {
OutputNode node;
if (ctx.evaluate != null) {
- node = new OutputNode(visit(ctx.expr()), null, null);
+ node = new OutputNode(visit(ctx.expr()), null, null, null);
} else {
String unparsed = null;
+ Integer unparsedLine = null;
Integer unparsedStart = null;
if (ctx.unparsed != null) {
unparsed = ctx.unparsed.getText();
- unparsedStart = ctx.unparsed.getStart().getStartIndex();
+ unparsedLine = ctx.unparsed.getStart().getLine();
+ unparsedStart = ctx.unparsed.getStart().getCharPositionInLine();
}
- node = new OutputNode(visit(ctx.term()), unparsed, unparsedStart);
+ node = new OutputNode(visit(ctx.term()), unparsed, unparsedLine, unparsedStart);
}
for (FilterContext child : ctx.filter()) {
diff --git a/src/test/java/liqp/nodes/GtNodeTest.java b/src/test/java/liqp/nodes/GtNodeTest.java
index 8c0b20fb..40a4b837 100644
--- a/src/test/java/liqp/nodes/GtNodeTest.java
+++ b/src/test/java/liqp/nodes/GtNodeTest.java
@@ -3,6 +3,8 @@
import static junit.framework.TestCase.assertEquals;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.time.Instant;
import java.time.LocalDateTime;
@@ -10,8 +12,11 @@
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import liqp.exceptions.LiquidException;
+import liqp.parser.Flavor;
import org.antlr.v4.runtime.RecognitionException;
import org.junit.Test;
@@ -80,4 +85,31 @@ public void testComparableTypes() {
value = TemplateParser.DEFAULT.parse("{% if a >= c %}yes{% else %}no{% endif %}").render(data);
assertEquals("no", value);
}
+
+ @Test
+ public void testBug267AsLiquid() {
+ try {
+ new TemplateParser.Builder().withFlavor(Flavor.LIQUID).build().parse("{{ 98 > 97 }}").render();
+ fail();
+ } catch (LiquidException e) {
+ assertTrue(e.getMessage().contains("parser error"));
+ } catch (Exception e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void testBug267AsJekyll() {
+ Template.ContextHolder contextHolder = new Template.ContextHolder();
+ String res = new TemplateParser.Builder()
+ .withFlavor(Flavor.JEKYLL)
+ .build()
+ .parse("{{ 98 > 97 }}")
+ .withContextHolder(contextHolder)
+ .render();
+ assertEquals("98", res);
+ List errors = contextHolder.getContext().errors();
+ assertEquals(1, errors.size());
+ assertTrue(errors.get(0).getMessage().contains("unexpected output"));
+ }
}