Repository: PebbleTemplates/pebble
Pull request #499 (2020-02-28 17:47:20)

Custom operator can use external context !
Allow completely control the instantiation of the binary expression class


Patch:
diff --git a/docs/src/orchid/resources/wiki/guide/installation.md b/docs/src/orchid/resources/wiki/guide/installation.md
index d922580c..cee1b813 100644
--- a/docs/src/orchid/resources/wiki/guide/installation.md
+++ b/docs/src/orchid/resources/wiki/guide/installation.md
@@ -86,4 +86,5 @@ All the settings are set during the construction of the `PebbleEngine` object.
 | `strictVariables` | If set to true, Pebble will throw an exception if you try to access a variable or attribute that does not exist (or an attribute of a null variable). If set to false, your template will treat non-existing variables/attributes as null without ever skipping a beat. | `false` |
 | `allowUnsafeMethods` | If set to false, Pebble will throw an exception if you try to access unsafe methods. Unsafe methods are defined [here](https://github.com/PebbleTemplates/pebble/tree/master/pebble/src/main/resources/unsafeMethods.properties) | `true` in 2.x, 'false' in v3.x |
 | `literalDecimalTreatedAsInteger` | option for toggling to enable/disable literal decimal treated as integer | `false` |
+| `literalNumbersAsBigDecimals` | option for toggling to enable/disable literal numbers treated as BigDecimals | `false` |
 | `greedyMatchMethod` | option for toggling to enable/disable greedy matching mode for finding java method. Reduce the limit of the parameter type, try to find other method which has compatible parameter types. | `false` |
diff --git a/pebble/src/main/java/com/mitchellbosecke/pebble/PebbleEngine.java b/pebble/src/main/java/com/mitchellbosecke/pebble/PebbleEngine.java
index 276588c6..55b15c1f 100644
--- a/pebble/src/main/java/com/mitchellbosecke/pebble/PebbleEngine.java
+++ b/pebble/src/main/java/com/mitchellbosecke/pebble/PebbleEngine.java
@@ -164,7 +164,7 @@ public class PebbleEngine {
       
       Parser parser = new ParserImpl(this.extensionRegistry.getUnaryOperators(),
           this.extensionRegistry.getBinaryOperators(), this.extensionRegistry.getTokenParsers(),
-          this.parserOptions);
+              this.parserOptions);
       RootNode root = parser.parse(tokenStream);
 
       PebbleTemplateImpl instance = new PebbleTemplateImpl(this, root, templateName);
@@ -291,6 +291,8 @@ public class PebbleEngine {
 
     private boolean allowOverrideCoreOperators = false;
 
+    private boolean literalNumbersAsBigDecimals = false;
+
     /**
      * Creates the builder.
      */
@@ -499,6 +501,18 @@ public class PebbleEngine {
       return this;
     }
 
+    /**
+     * Enable/disable treat literal numbers as BigDecimals. Default is disabled, treated as Long/Double.
+     *
+     * @param literalNumbersAsBigDecimals toggle to enable/disable literal numbers treated as
+     * BigDecimals
+     * @return This builder object
+     */
+    public Builder literalNumbersAsBigDecimals(boolean literalNumbersAsBigDecimals) {
+      this.literalNumbersAsBigDecimals = literalNumbersAsBigDecimals;
+      return this;
+    }
+
     /**
      * Enable/disable greedy matching mode for finding java method. Default is disabled. If enabled,
      * when can not find perfect method (method name, parameter length and parameter type are all
@@ -568,6 +582,7 @@ public class PebbleEngine {
 
       ParserOptions parserOptions = new ParserOptions();
       parserOptions.setLiteralDecimalTreatedAsInteger(this.literalDecimalTreatedAsInteger);
+      parserOptions.setLiteralNumbersAsBigDecimals(this.literalNumbersAsBigDecimals);
 
       EvaluationOptions evaluationOptions = new EvaluationOptions();
       evaluationOptions.setAllowUnsafeMethods(this.allowUnsafeMethods);
diff --git a/pebble/src/main/java/com/mitchellbosecke/pebble/extension/core/CoreExtension.java b/pebble/src/main/java/com/mitchellbosecke/pebble/extension/core/CoreExtension.java
index a443f580..d69f5600 100644
--- a/pebble/src/main/java/com/mitchellbosecke/pebble/extension/core/CoreExtension.java
+++ b/pebble/src/main/java/com/mitchellbosecke/pebble/extension/core/CoreExtension.java
@@ -8,6 +8,10 @@
  */
 package com.mitchellbosecke.pebble.extension.core;
 
+import static com.mitchellbosecke.pebble.operator.BinaryOperatorType.FILTER;
+import static com.mitchellbosecke.pebble.operator.BinaryOperatorType.NORMAL;
+import static com.mitchellbosecke.pebble.operator.BinaryOperatorType.TEST;
+
 import com.mitchellbosecke.pebble.extension.AbstractExtension;
 import com.mitchellbosecke.pebble.extension.Filter;
 import com.mitchellbosecke.pebble.extension.Function;
@@ -55,7 +59,6 @@ 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;
 import java.util.List;
@@ -97,26 +100,26 @@ public class CoreExtension extends AbstractExtension {
   @Override
   public List<BinaryOperator> getBinaryOperators() {
     List<BinaryOperator> 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("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));
-    operators.add(new BinaryOperatorImpl("==", 30, EqualsExpression.class, Associativity.LEFT));
-    operators.add(new BinaryOperatorImpl("equals", 30, EqualsExpression.class, Associativity.LEFT));
-    operators.add(new BinaryOperatorImpl("!=", 30, NotEqualsExpression.class, Associativity.LEFT));
-    operators.add(new BinaryOperatorImpl(">", 30, GreaterThanExpression.class, Associativity.LEFT));
-    operators.add(new BinaryOperatorImpl("<", 30, LessThanExpression.class, Associativity.LEFT));
-    operators.add(new BinaryOperatorImpl(">=", 30, GreaterThanEqualsExpression.class, Associativity.LEFT));
-    operators.add(new BinaryOperatorImpl("<=", 30, LessThanEqualsExpression.class, Associativity.LEFT));
-    operators.add(new BinaryOperatorImpl("+", 40, AddExpression.class, Associativity.LEFT));
-    operators.add(new BinaryOperatorImpl("-", 40, SubtractExpression.class, Associativity.LEFT));
-    operators.add(new BinaryOperatorImpl("*", 60, MultiplyExpression.class, Associativity.LEFT));
-    operators.add(new BinaryOperatorImpl("/", 60, DivideExpression.class, Associativity.LEFT));
-    operators.add(new BinaryOperatorImpl("%", 60, ModulusExpression.class, Associativity.LEFT));
-    operators.add(new BinaryOperatorImpl("|", 100, FilterExpression.class, Associativity.LEFT));
-    operators.add(new BinaryOperatorImpl("~", 110, ConcatenateExpression.class, Associativity.LEFT));
-    operators.add(new BinaryOperatorImpl("..", 120, RangeExpression.class, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl("or", 10, OrExpression::new, NORMAL, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl("and", 15, AndExpression::new, NORMAL, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl("is", 20, PositiveTestExpression::new, TEST, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl("is not", 20, NegativeTestExpression::new, TEST, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl("contains", 20, ContainsExpression::new, NORMAL, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl("==", 30, EqualsExpression::new, NORMAL, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl("equals", 30, EqualsExpression::new, NORMAL, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl("!=", 30, NotEqualsExpression::new, NORMAL, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl(">", 30, GreaterThanExpression::new, NORMAL, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl("<", 30, LessThanExpression::new, NORMAL, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl(">=", 30, GreaterThanEqualsExpression::new, NORMAL, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl("<=", 30, LessThanEqualsExpression::new, NORMAL, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl("+", 40, AddExpression::new, NORMAL, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl("-", 40, SubtractExpression::new, NORMAL, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl("*", 60, MultiplyExpression::new, NORMAL, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl("/", 60, DivideExpression::new, NORMAL, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl("%", 60, ModulusExpression::new, NORMAL, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl("|", 100, FilterExpression::new, FILTER, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl("~", 110, ConcatenateExpression::new, NORMAL, Associativity.LEFT));
+    operators.add(new BinaryOperatorImpl("..", 120, RangeExpression::new, NORMAL, Associativity.LEFT));
 
     return operators;
   }
diff --git a/pebble/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralBigDecimalExpression.java b/pebble/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralBigDecimalExpression.java
new file mode 100644
index 00000000..37a0a44b
--- /dev/null
+++ b/pebble/src/main/java/com/mitchellbosecke/pebble/node/expression/LiteralBigDecimalExpression.java
@@ -0,0 +1,47 @@
+/*
+ * This file is part of Pebble.
+ *
+ * Copyright (c) 2014 by Mitchell Bösecke
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+package com.mitchellbosecke.pebble.node.expression;
+
+import com.mitchellbosecke.pebble.extension.NodeVisitor;
+import com.mitchellbosecke.pebble.template.EvaluationContextImpl;
+import com.mitchellbosecke.pebble.template.PebbleTemplateImpl;
+
+import java.math.BigDecimal;
+
+public class LiteralBigDecimalExpression implements Expression<BigDecimal> {
+
+  private final BigDecimal value;
+  private final int lineNumber;
+
+  public LiteralBigDecimalExpression(BigDecimal value, int lineNumber) {
+    this.value = value;
+    this.lineNumber = lineNumber;
+  }
+
+  @Override
+  public void accept(NodeVisitor visitor) {
+    visitor.visit(this);
+  }
+
+  @Override
+  public BigDecimal evaluate(PebbleTemplateImpl self, EvaluationContextImpl context) {
+    return this.value;
+  }
+
+  @Override
+  public int getLineNumber() {
+    return this.lineNumber;
+  }
+
+  @Override
+  public String toString() {
+    return this.value.toString();
+  }
+
+}
diff --git a/pebble/src/main/java/com/mitchellbosecke/pebble/operator/BinaryOperator.java b/pebble/src/main/java/com/mitchellbosecke/pebble/operator/BinaryOperator.java
index a69d5f7b..c9f28ad6 100644
--- a/pebble/src/main/java/com/mitchellbosecke/pebble/operator/BinaryOperator.java
+++ b/pebble/src/main/java/com/mitchellbosecke/pebble/operator/BinaryOperator.java
@@ -16,7 +16,9 @@ public interface BinaryOperator {
 
   String getSymbol();
 
-  Class<? extends BinaryExpression<?>> getNodeClass();
+  BinaryExpression<?> getInstance();
+
+  BinaryOperatorType getType();
 
   Associativity getAssociativity();
 
diff --git a/pebble/src/main/java/com/mitchellbosecke/pebble/operator/BinaryOperatorImpl.java b/pebble/src/main/java/com/mitchellbosecke/pebble/operator/BinaryOperatorImpl.java
index 15cbafc2..114ce731 100644
--- a/pebble/src/main/java/com/mitchellbosecke/pebble/operator/BinaryOperatorImpl.java
+++ b/pebble/src/main/java/com/mitchellbosecke/pebble/operator/BinaryOperatorImpl.java
@@ -8,7 +8,12 @@
  */
 package com.mitchellbosecke.pebble.operator;
 
+import com.mitchellbosecke.pebble.error.PebbleException;
 import com.mitchellbosecke.pebble.node.expression.BinaryExpression;
+import com.mitchellbosecke.pebble.node.expression.FilterExpression;
+import com.mitchellbosecke.pebble.node.expression.NegativeTestExpression;
+import com.mitchellbosecke.pebble.node.expression.PositiveTestExpression;
+import java.util.function.Supplier;
 
 public class BinaryOperatorImpl implements BinaryOperator {
 
@@ -16,16 +21,38 @@ public class BinaryOperatorImpl implements BinaryOperator {
 
   private final String symbol;
 
-  private final Class<? extends BinaryExpression<?>> nodeClass;
+  private final Supplier<? extends BinaryExpression<?>> nodeSupplier;
+
+  private final BinaryOperatorType type;
 
   private final Associativity associativity;
 
+  /**
+   * This constuctor left for backward compatibility with custom extensions
+   */
   public BinaryOperatorImpl(String symbol, int precedence,
       Class<? extends BinaryExpression<?>> nodeClass,
       Associativity associativity) {
+    this(symbol, precedence, () -> {
+      try {
+        return nodeClass.newInstance();
+      } catch (InstantiationException | IllegalAccessException e) {
+        throw new PebbleException(e, "Error instantiating class " + nodeClass.getName());
+      }
+    }, getDefaultType(nodeClass), associativity);
+  }
+
+  /**
+   * This constuctor allows you to completely control the instantiation of the expression class
+   */
+  public BinaryOperatorImpl(String symbol, int precedence,
+      Supplier<? extends BinaryExpression<?>> nodeSupplier,
+      BinaryOperatorType type,
+      Associativity associativity) {
     this.symbol = symbol;
     this.precedence = precedence;
-    this.nodeClass = nodeClass;
+    this.nodeSupplier = nodeSupplier;
+    this.type = type;
     this.associativity = associativity;
   }
 
@@ -40,12 +67,28 @@ public class BinaryOperatorImpl implements BinaryOperator {
   }
 
   @Override
-  public Class<? extends BinaryExpression<?>> getNodeClass() {
-    return this.nodeClass;
+  public BinaryExpression<?> getInstance() {
+    return this.nodeSupplier.get();
+  }
+
+  @Override
+  public BinaryOperatorType getType() {
+    return this.type;
   }
 
   @Override
   public Associativity getAssociativity() {
     return this.associativity;
   }
+
+  private static BinaryOperatorType getDefaultType(Class<? extends BinaryExpression<?>> nodeClass) {
+    if (FilterExpression.class.equals(nodeClass)) {
+      return BinaryOperatorType.FILTER;
+    } else if (PositiveTestExpression.class.equals(nodeClass) || NegativeTestExpression.class
+        .equals(nodeClass)) {
+      return BinaryOperatorType.TEST;
+    } else {
+      return BinaryOperatorType.NORMAL;
+    }
+  }
 }
diff --git a/pebble/src/main/java/com/mitchellbosecke/pebble/operator/BinaryOperatorType.java b/pebble/src/main/java/com/mitchellbosecke/pebble/operator/BinaryOperatorType.java
new file mode 100644
index 00000000..c6eef3f2
--- /dev/null
+++ b/pebble/src/main/java/com/mitchellbosecke/pebble/operator/BinaryOperatorType.java
@@ -0,0 +1,5 @@
+package com.mitchellbosecke.pebble.operator;
+
+public enum BinaryOperatorType {
+  NORMAL, FILTER, TEST
+}
diff --git a/pebble/src/main/java/com/mitchellbosecke/pebble/parser/ExpressionParser.java b/pebble/src/main/java/com/mitchellbosecke/pebble/parser/ExpressionParser.java
index bcf8f9a0..9c2c7d35 100644
--- a/pebble/src/main/java/com/mitchellbosecke/pebble/parser/ExpressionParser.java
+++ b/pebble/src/main/java/com/mitchellbosecke/pebble/parser/ExpressionParser.java
@@ -22,10 +22,10 @@ import com.mitchellbosecke.pebble.node.expression.BlockFunctionExpression;
 import com.mitchellbosecke.pebble.node.expression.ConcatenateExpression;
 import com.mitchellbosecke.pebble.node.expression.ContextVariableExpression;
 import com.mitchellbosecke.pebble.node.expression.Expression;
-import com.mitchellbosecke.pebble.node.expression.FilterExpression;
 import com.mitchellbosecke.pebble.node.expression.FilterInvocationExpression;
 import com.mitchellbosecke.pebble.node.expression.FunctionOrMacroInvocationExpression;
 import com.mitchellbosecke.pebble.node.expression.GetAttributeExpression;
+import com.mitchellbosecke.pebble.node.expression.LiteralBigDecimalExpression;
 import com.mitchellbosecke.pebble.node.expression.LiteralBooleanExpression;
 import com.mitchellbosecke.pebble.node.expression.LiteralDoubleExpression;
 import com.mitchellbosecke.pebble.node.expression.LiteralIntegerExpression;
@@ -33,14 +33,15 @@ import com.mitchellbosecke.pebble.node.expression.LiteralLongExpression;
 import com.mitchellbosecke.pebble.node.expression.LiteralNullExpression;
 import com.mitchellbosecke.pebble.node.expression.LiteralStringExpression;
 import com.mitchellbosecke.pebble.node.expression.MapExpression;
-import com.mitchellbosecke.pebble.node.expression.NegativeTestExpression;
 import com.mitchellbosecke.pebble.node.expression.ParentFunctionExpression;
-import com.mitchellbosecke.pebble.node.expression.PositiveTestExpression;
 import com.mitchellbosecke.pebble.node.expression.TernaryExpression;
 import com.mitchellbosecke.pebble.node.expression.UnaryExpression;
 import com.mitchellbosecke.pebble.operator.Associativity;
 import com.mitchellbosecke.pebble.operator.BinaryOperator;
+import com.mitchellbosecke.pebble.operator.BinaryOperatorType;
 import com.mitchellbosecke.pebble.operator.UnaryOperator;
+
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -177,13 +178,12 @@ public class ExpressionParser {
 
       // the right hand expression of the FILTER operator is handled in a
       // unique way
-      if (FilterExpression.class.equals(operator.getNodeClass())) {
+      if (operator.getType() == BinaryOperatorType.FILTER) {
         expressionRight = this.parseFilterInvocationExpression();
       }
       // the right hand expression of TEST operators is handled in a
       // unique way
-      else if (PositiveTestExpression.class.equals(operator.getNodeClass())
-          || NegativeTestExpression.class.equals(operator.getNodeClass())) {
+      else if (operator.getType() == BinaryOperatorType.TEST) {
         expressionRight = this.parseTestInvocationExpression();
       } else {
         /*
@@ -201,16 +201,16 @@ public class ExpressionParser {
        * expression we are creating.
        */
       BinaryExpression<?> finalExpression;
-      Class<? extends BinaryExpression<?>> operatorNodeClass = operator.getNodeClass();
+
       try {
-        finalExpression = operatorNodeClass.newInstance();
-        finalExpression.setLineNumber(this.stream.current().getLineNumber());
-      } catch (InstantiationException | IllegalAccessException e) {
+        finalExpression = operator.getInstance();
+      } catch (RuntimeException e) {
         throw new ParserException(e,
-            "Error instantiating operator node [" + operatorNodeClass.getName() + "]",
+            "Error instantiating operator node",
             token.getLineNumber(), this.stream.getFilename());
       }
 
+      finalExpression.setLineNumber(this.stream.current().getLineNumber());
       finalExpression.setLeft(expression);
       finalExpression.setRight(expressionRight);
 
@@ -306,14 +306,18 @@ public class ExpressionParser {
 
       case NUMBER:
         final String numberValue = token.getValue();
-        if (numberValue.contains(".")) {
-          node = new LiteralDoubleExpression(Double.valueOf(numberValue), token.getLineNumber());
+        if (this.parserOptions.isLiteralNumbersAsBigDecimals()) {
+          node = new LiteralBigDecimalExpression(new BigDecimal(numberValue), token.getLineNumber());
         } else {
-          if (this.parserOptions.isLiteralDecimalTreatedAsInteger()) {
-            node = new LiteralIntegerExpression(Integer.valueOf(numberValue),
-                token.getLineNumber());
+          if (numberValue.contains(".")) {
+            node = new LiteralDoubleExpression(Double.valueOf(numberValue), token.getLineNumber());
           } else {
-            node = new LiteralLongExpression(Long.valueOf(numberValue), token.getLineNumber());
+            if (this.parserOptions.isLiteralDecimalTreatedAsInteger()) {
+              node = new LiteralIntegerExpression(Integer.valueOf(numberValue),
+                      token.getLineNumber());
+            } else {
+              node = new LiteralLongExpression(Long.valueOf(numberValue), token.getLineNumber());
+            }
           }
         }
         this.stream.next();
@@ -571,7 +575,7 @@ public class ExpressionParser {
           throw new ParserException(null,
               "Positional arguments must be declared before any named arguments.",
               this.stream.current()
-              .getLineNumber(),
+                  .getLineNumber(),
               this.stream.getFilename());
         }
         positionalArgs.add(new PositionalArgumentNode(argumentValue));
diff --git a/pebble/src/main/java/com/mitchellbosecke/pebble/parser/ParserOptions.java b/pebble/src/main/java/com/mitchellbosecke/pebble/parser/ParserOptions.java
index ce7d7ae5..ec0ca278 100644
--- a/pebble/src/main/java/com/mitchellbosecke/pebble/parser/ParserOptions.java
+++ b/pebble/src/main/java/com/mitchellbosecke/pebble/parser/ParserOptions.java
@@ -9,6 +9,8 @@ public class ParserOptions {
 
   private boolean literalDecimalTreatedAsInteger;
 
+  private boolean literalNumbersAsBigDecimals;
+
   public boolean isLiteralDecimalTreatedAsInteger() {
     return literalDecimalTreatedAsInteger;
   }
@@ -17,4 +19,15 @@ public class ParserOptions {
     this.literalDecimalTreatedAsInteger = literalDecimalTreatedAsInteger;
     return this;
   }
+
+  public boolean isLiteralNumbersAsBigDecimals() {
+    return literalNumbersAsBigDecimals;
+  }
+
+  public ParserOptions setLiteralNumbersAsBigDecimals(boolean literalNumbersAsBigDecimals) {
+    this.literalNumbersAsBigDecimals = literalNumbersAsBigDecimals;
+    return this;
+  }
+
+
 }


Test patch:
diff --git a/pebble/src/test/java/com/mitchellbosecke/pebble/GetAttributeTest.java b/pebble/src/test/java/com/mitchellbosecke/pebble/GetAttributeTest.java
index ce2e338e..61c4fab0 100644
--- a/pebble/src/test/java/com/mitchellbosecke/pebble/GetAttributeTest.java
+++ b/pebble/src/test/java/com/mitchellbosecke/pebble/GetAttributeTest.java
@@ -568,6 +568,35 @@ class GetAttributeTest {
     assertEquals("hello 2 2", writer.toString());
   }
 
+  @Test
+  void testBeanMethodWithNumberLiteralsAsBigDecimals() throws PebbleException, IOException {
+    PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader())
+            .strictVariables(true).literalNumbersAsBigDecimals(true)
+            .build();
+
+    PebbleTemplate template = pebble.getTemplate("hello {{ 1234567890123456789012345678901234567890 }}");
+    Map<String, Object> context = new HashMap<>();
+
+    Writer writer = new StringWriter();
+    template.evaluate(writer, context);
+    assertEquals("hello 1234567890123456789012345678901234567890", writer.toString());
+  }
+
+  @Test
+  void testBeanMethodWithoutNumberLiteralsAsBigDecimals() throws PebbleException, IOException {
+    assertThrows(NumberFormatException.class, () -> {
+      PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader())
+              .strictVariables(true).literalNumbersAsBigDecimals(false)
+              .build();
+
+      PebbleTemplate template = pebble.getTemplate("hello {{ 1234567890123456789012345678901234567890 }}");
+      Map<String, Object> context = new HashMap<>();
+
+      Writer writer = new StringWriter();
+      template.evaluate(writer, context);
+    });
+  }
+
   @Test
   void testBeanMethodWithOverloadedArgument() throws PebbleException, IOException {
     PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader())