diff --git a/CHANGELOG.md b/CHANGELOG.md index cc7f2f134..df6f4cb63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - Fixed security issue which allowed to execute shell command (by having access to Java's Class object) (#329) - Throw ParserException when endBlock not found (#308) - For tag : add enumeration support (#292) +- Fix operator precedence (#290) ## v2.4.0 (2017-06-04) - Add arrays support for iterable test (#254) diff --git a/src/main/java/com/mitchellbosecke/pebble/extension/core/CoreExtension.java b/src/main/java/com/mitchellbosecke/pebble/extension/core/CoreExtension.java index 8e2f36e9d..be323c8c9 100644 --- a/src/main/java/com/mitchellbosecke/pebble/extension/core/CoreExtension.java +++ b/src/main/java/com/mitchellbosecke/pebble/extension/core/CoreExtension.java @@ -8,10 +8,51 @@ ******************************************************************************/ package com.mitchellbosecke.pebble.extension.core; -import com.mitchellbosecke.pebble.extension.*; -import com.mitchellbosecke.pebble.node.expression.*; -import com.mitchellbosecke.pebble.operator.*; -import com.mitchellbosecke.pebble.tokenParser.*; +import com.mitchellbosecke.pebble.extension.AbstractExtension; +import com.mitchellbosecke.pebble.extension.Filter; +import com.mitchellbosecke.pebble.extension.Function; +import com.mitchellbosecke.pebble.extension.NodeVisitorFactory; +import com.mitchellbosecke.pebble.extension.Test; +import com.mitchellbosecke.pebble.node.expression.AddExpression; +import com.mitchellbosecke.pebble.node.expression.AndExpression; +import com.mitchellbosecke.pebble.node.expression.ConcatenateExpression; +import com.mitchellbosecke.pebble.node.expression.ContainsExpression; +import com.mitchellbosecke.pebble.node.expression.DivideExpression; +import com.mitchellbosecke.pebble.node.expression.EqualsExpression; +import com.mitchellbosecke.pebble.node.expression.FilterExpression; +import com.mitchellbosecke.pebble.node.expression.GreaterThanEqualsExpression; +import com.mitchellbosecke.pebble.node.expression.GreaterThanExpression; +import com.mitchellbosecke.pebble.node.expression.LessThanEqualsExpression; +import com.mitchellbosecke.pebble.node.expression.LessThanExpression; +import com.mitchellbosecke.pebble.node.expression.ModulusExpression; +import com.mitchellbosecke.pebble.node.expression.MultiplyExpression; +import com.mitchellbosecke.pebble.node.expression.NegativeTestExpression; +import com.mitchellbosecke.pebble.node.expression.NotEqualsExpression; +import com.mitchellbosecke.pebble.node.expression.OrExpression; +import com.mitchellbosecke.pebble.node.expression.PositiveTestExpression; +import com.mitchellbosecke.pebble.node.expression.RangeExpression; +import com.mitchellbosecke.pebble.node.expression.SubtractExpression; +import com.mitchellbosecke.pebble.node.expression.UnaryMinusExpression; +import com.mitchellbosecke.pebble.node.expression.UnaryNotExpression; +import com.mitchellbosecke.pebble.node.expression.UnaryPlusExpression; +import com.mitchellbosecke.pebble.operator.Associativity; +import com.mitchellbosecke.pebble.operator.BinaryOperator; +import com.mitchellbosecke.pebble.operator.BinaryOperatorImpl; +import com.mitchellbosecke.pebble.operator.UnaryOperator; +import com.mitchellbosecke.pebble.operator.UnaryOperatorImpl; +import com.mitchellbosecke.pebble.tokenParser.BlockTokenParser; +import com.mitchellbosecke.pebble.tokenParser.CacheTokenParser; +import com.mitchellbosecke.pebble.tokenParser.ExtendsTokenParser; +import com.mitchellbosecke.pebble.tokenParser.FilterTokenParser; +import com.mitchellbosecke.pebble.tokenParser.FlushTokenParser; +import com.mitchellbosecke.pebble.tokenParser.ForTokenParser; +import com.mitchellbosecke.pebble.tokenParser.IfTokenParser; +import com.mitchellbosecke.pebble.tokenParser.ImportTokenParser; +import com.mitchellbosecke.pebble.tokenParser.IncludeTokenParser; +import com.mitchellbosecke.pebble.tokenParser.MacroTokenParser; +import com.mitchellbosecke.pebble.tokenParser.ParallelTokenParser; +import com.mitchellbosecke.pebble.tokenParser.SetTokenParser; +import com.mitchellbosecke.pebble.tokenParser.TokenParser; import java.util.ArrayList; import java.util.HashMap; @@ -43,7 +84,7 @@ public List getTokenParsers() { @Override public List getUnaryOperators() { ArrayList operators = new ArrayList<>(); - operators.add(new UnaryOperatorImpl("not", 5, UnaryNotExpression.class)); + operators.add(new UnaryOperatorImpl("not", 10, UnaryNotExpression.class)); operators.add(new UnaryOperatorImpl("+", 500, UnaryPlusExpression.class)); operators.add(new UnaryOperatorImpl("-", 500, UnaryMinusExpression.class)); return operators; @@ -52,8 +93,8 @@ public List getUnaryOperators() { @Override public List getBinaryOperators() { ArrayList operators = new ArrayList<>(); - operators.add(new BinaryOperatorImpl("or", 10, OrExpression.class, Associativity.LEFT)); - operators.add(new BinaryOperatorImpl("and", 15, AndExpression.class, Associativity.LEFT)); + operators.add(new BinaryOperatorImpl("or", 1, OrExpression.class, Associativity.LEFT)); + operators.add(new BinaryOperatorImpl("and", 5, AndExpression.class, Associativity.LEFT)); operators.add(new BinaryOperatorImpl("is", 20, PositiveTestExpression.class, Associativity.LEFT)); operators.add(new BinaryOperatorImpl("is not", 20, NegativeTestExpression.class, Associativity.LEFT)); operators.add(new BinaryOperatorImpl("contains", 20, ContainsExpression.class, Associativity.LEFT)); diff --git a/src/test/java/com/mitchellbosecke/pebble/CoreOperatorsTest.java b/src/test/java/com/mitchellbosecke/pebble/CoreOperatorsTest.java index b18e66e8d..5c8bd6ffc 100644 --- a/src/test/java/com/mitchellbosecke/pebble/CoreOperatorsTest.java +++ b/src/test/java/com/mitchellbosecke/pebble/CoreOperatorsTest.java @@ -8,7 +8,12 @@ ******************************************************************************/ package com.mitchellbosecke.pebble; -import static org.junit.Assert.assertEquals; +import com.mitchellbosecke.pebble.error.PebbleException; +import com.mitchellbosecke.pebble.loader.StringLoader; +import com.mitchellbosecke.pebble.template.PebbleTemplate; +import com.mitchellbosecke.pebble.utils.Pair; + +import org.junit.Test; import java.io.IOException; import java.io.StringWriter; @@ -21,12 +26,7 @@ import java.util.List; import java.util.Map; -import org.junit.Test; - -import com.mitchellbosecke.pebble.error.PebbleException; -import com.mitchellbosecke.pebble.loader.StringLoader; -import com.mitchellbosecke.pebble.template.PebbleTemplate; -import com.mitchellbosecke.pebble.utils.Pair; +import static org.junit.Assert.assertEquals; public class CoreOperatorsTest extends AbstractTest { @@ -221,6 +221,34 @@ public void testLogicOperatorOnAttributes() throws PebbleException, IOException assertEquals("noyes", writer.toString()); } + @Test + public void testNotOperatorPrecedence() throws IOException { + PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build(); + + String source = "{% if not item.falsy and not item.truthy %}This should not be displayed{% else %}All's good{% endif %}"; + PebbleTemplate template = pebble.getTemplate(source); + Map context = new HashMap<>(); + context.put("item", new Item()); + + Writer writer = new StringWriter(); + template.evaluate(writer, context); + assertEquals("All's good", writer.toString()); + } + + @Test + public void testNotOperatorWithParenthesisPrecedence() throws IOException { + PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false).build(); + + String source = "{% if (not item.falsy) and (not item.truthy) %}This should not be displayed{% else %}All's good{% endif %}"; + PebbleTemplate template = pebble.getTemplate(source); + Map context = new HashMap<>(); + context.put("item", new Item()); + + Writer writer = new StringWriter(); + template.evaluate(writer, context); + assertEquals("All's good", writer.toString()); + } + @Test public void testTernary() throws PebbleException, IOException {