Repository: PebbleTemplates/pebble
Pull request #405 (2018-09-25 05:46:16)

Implement to boolean smart-casting in OR and AND operators


Patch:
diff --git a/pebble/src/main/java/com/mitchellbosecke/pebble/node/expression/AndExpression.java b/pebble/src/main/java/com/mitchellbosecke/pebble/node/expression/AndExpression.java
index d3ee7b1a..0c0a9fd2 100644
--- a/pebble/src/main/java/com/mitchellbosecke/pebble/node/expression/AndExpression.java
+++ b/pebble/src/main/java/com/mitchellbosecke/pebble/node/expression/AndExpression.java
@@ -12,6 +12,8 @@ import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
+import static com.mitchellbosecke.pebble.utils.TypeUtils.compatibleCast;
+
 public class AndExpression extends BinaryExpression<Boolean> {
 
   @SuppressWarnings("unchecked")
@@ -28,7 +30,7 @@ public class AndExpression extends BinaryExpression<Boolean> {
 
   private boolean evaluateExpression(PebbleTemplateImpl self, EvaluationContextImpl context,
       Expression<Boolean> expression) {
-    Boolean evaluatedExpression = expression.evaluate(self, context);
+    Boolean evaluatedExpression = compatibleCast(expression.evaluate(self, context), Boolean.class);
 
     if (evaluatedExpression == null) {
       if (context.isStrictVariables()) {
diff --git a/pebble/src/main/java/com/mitchellbosecke/pebble/node/expression/OrExpression.java b/pebble/src/main/java/com/mitchellbosecke/pebble/node/expression/OrExpression.java
index eab37bd3..54db660d 100644
--- a/pebble/src/main/java/com/mitchellbosecke/pebble/node/expression/OrExpression.java
+++ b/pebble/src/main/java/com/mitchellbosecke/pebble/node/expression/OrExpression.java
@@ -12,6 +12,8 @@ import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
 import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
 
+import static com.mitchellbosecke.pebble.utils.TypeUtils.compatibleCast;
+
 public class OrExpression extends BinaryExpression<Boolean> {
 
   @SuppressWarnings("unchecked")
@@ -28,7 +30,7 @@ public class OrExpression extends BinaryExpression<Boolean> {
 
   private boolean evaluateExpression(PebbleTemplateImpl self, EvaluationContextImpl context,
       Expression<Boolean> expression) {
-    Boolean evaluatedExpression = expression.evaluate(self, context);
+    Boolean evaluatedExpression = compatibleCast(expression.evaluate(self, context), Boolean.class);
 
     if (evaluatedExpression == null) {
       if (context.isStrictVariables()) {


Test patch:
diff --git a/pebble/src/test/java/com/mitchellbosecke/pebble/node/expression/AndExpressionTest.java b/pebble/src/test/java/com/mitchellbosecke/pebble/node/expression/AndExpressionTest.java
new file mode 100644
index 00000000..e3147102
--- /dev/null
+++ b/pebble/src/test/java/com/mitchellbosecke/pebble/node/expression/AndExpressionTest.java
@@ -0,0 +1,32 @@
+package com.mitchellbosecke.pebble.node.expression;
+
+import java.io.IOException;
+import org.junit.Test;
+
+
+public class AndExpressionTest extends ExpressionTest {
+
+  @Test
+  public void testIntExpressionPartFalse() throws IOException {
+    this.testExpression("{{ 0 and true }}", "false");
+    this.testExpression("{{ false or 0 }}", "false");
+  }
+
+  @Test
+  public void testIntExpressionPartTrue() throws IOException {
+    this.testExpression("{{ 1 and false }}", "false");
+    this.testExpression("{{ true or 1 }}", "true");
+  }
+
+  @Test
+  public void testStringExpressionPartFalse() throws IOException {
+    this.testExpression("{{ '' and true }}", "false");
+    this.testExpression("{{ true and '' }}", "false");
+  }
+
+  @Test
+  public void testStringExpressionPartTrue() throws IOException {
+    this.testExpression("{{ 'true' and false }}", "false");
+    this.testExpression("{{ true or 'true' }}", "true");
+  }
+}
diff --git a/pebble/src/test/java/com/mitchellbosecke/pebble/node/expression/ExpressionTest.java b/pebble/src/test/java/com/mitchellbosecke/pebble/node/expression/ExpressionTest.java
new file mode 100644
index 00000000..383ccaff
--- /dev/null
+++ b/pebble/src/test/java/com/mitchellbosecke/pebble/node/expression/ExpressionTest.java
@@ -0,0 +1,22 @@
+package com.mitchellbosecke.pebble.node.expression;
+
+import static org.junit.Assert.assertEquals;
+
+import com.mitchellbosecke.pebble.PebbleEngine;
+import com.mitchellbosecke.pebble.loader.StringLoader;
+import com.mitchellbosecke.pebble.template.PebbleTemplate;
+import java.io.IOException;
+import java.io.StringWriter;
+
+public abstract class ExpressionTest {
+
+  private PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader())
+      .strictVariables(false).build();
+
+  protected void testExpression(String templateName, String expected) throws IOException {
+    PebbleTemplate template = this.pebble.getTemplate(templateName);
+    StringWriter writer = new StringWriter();
+    template.evaluate(writer);
+    assertEquals(expected, writer.toString());
+  }
+}
diff --git a/pebble/src/test/java/com/mitchellbosecke/pebble/node/expression/OrExpressionTest.java b/pebble/src/test/java/com/mitchellbosecke/pebble/node/expression/OrExpressionTest.java
new file mode 100644
index 00000000..4bb25388
--- /dev/null
+++ b/pebble/src/test/java/com/mitchellbosecke/pebble/node/expression/OrExpressionTest.java
@@ -0,0 +1,31 @@
+package com.mitchellbosecke.pebble.node.expression;
+
+import java.io.IOException;
+import org.junit.Test;
+
+public class OrExpressionTest extends ExpressionTest {
+
+  @Test
+  public void testIntExpressionPartFalse() throws IOException {
+    this.testExpression("{{ 0 or false }}", "false");
+    this.testExpression("{{ true or 0 }}", "true");
+  }
+
+  @Test
+  public void testIntExpressionPartTrue() throws IOException {
+    this.testExpression("{{ 1 or false }}", "true");
+    this.testExpression("{{ true or 1 }}", "true");
+  }
+
+  @Test
+  public void testStringExpressionPartFalse() throws IOException {
+    this.testExpression("{{ '' or false }}", "false");
+    this.testExpression("{{ true or '' }}", "true");
+  }
+
+  @Test
+  public void testStringExpressionPartTrue() throws IOException {
+    this.testExpression("{{ 'true' or false }}", "true");
+    this.testExpression("{{ true or 'true' }}", "true");
+  }
+}