You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by he...@apache.org on 2024/02/16 22:20:02 UTC

(commons-jexl) branch JEXL-418 updated: JEXL-418: fixing reserved names, preparing for feature flag;

This is an automated email from the ASF dual-hosted git repository.

henrib pushed a commit to branch JEXL-418
in repository https://gitbox.apache.org/repos/asf/commons-jexl.git


The following commit(s) were added to refs/heads/JEXL-418 by this push:
     new d2d2ff57 JEXL-418: fixing reserved names, preparing for feature flag;
d2d2ff57 is described below

commit d2d2ff57adf991e639c4b218fd714a769bdd53aa
Author: Henri Biestro <hb...@cloudera.com>
AuthorDate: Fri Feb 16 23:19:52 2024 +0100

    JEXL-418: fixing reserved names, preparing for feature flag;
---
 .../org/apache/commons/jexl3/JexlFeatures.java     |  4 +-
 .../apache/commons/jexl3/internal/Interpreter.java |  3 +-
 .../org/apache/commons/jexl3/parser/Parser.jjt     | 20 +++++++--
 .../org/apache/commons/jexl3/FeaturesTest.java     |  2 +-
 .../java/org/apache/commons/jexl3/LexicalTest.java |  4 +-
 .../apache/commons/jexl3/TryCatchFinallyTest.java  | 49 +++++++++++++++++-----
 6 files changed, 61 insertions(+), 21 deletions(-)

diff --git a/src/main/java/org/apache/commons/jexl3/JexlFeatures.java b/src/main/java/org/apache/commons/jexl3/JexlFeatures.java
index 4cee5a7d..be45f9b5 100644
--- a/src/main/java/org/apache/commons/jexl3/JexlFeatures.java
+++ b/src/main/java/org/apache/commons/jexl3/JexlFeatures.java
@@ -227,13 +227,13 @@ public final class JexlFeatures {
 
     /**
      * Protected future syntactic elements.
-     * <p><em>try, catch, throw, finally, switch, case, default, class, instanceof, jexl, $jexl</em></p>
+     * <p><em>throw, switch, case, default, class, instanceof, jexl, $jexl</em></p>
      * @since 3.3.1
      */
     private static final Set<String> RESERVED_WORDS =
         Collections.unmodifiableSet(
             new HashSet<>((Arrays.asList(
-                "try", "catch", "throw", "finally", "switch", "case", "default", "class", "instanceof", "jexl", "$jexl"))));
+                "switch", "case", "default", "class", "instanceof", "jexl", "$jexl"))));
 
     /**
      * The modern scripting features set.
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
index c2553001..82a77edf 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
@@ -695,10 +695,10 @@ public class Interpreter extends InterpreterBase {
      */
     private Object evalTry(JexlNode tryVar, JexlNode tryExpression, JexlNode tryBody, final Object data) {
         boolean lexical = false;
+        Object tryResult = null;
         try {
             final ASTIdentifier tryVariable;
             final int symbol;
-            Object tryResult = null;
             /* Capture try variable if any. */
             if (tryVar instanceof ASTReference) {
                 tryVariable = (ASTIdentifier) tryVar.jjtGetChild(0);
@@ -734,6 +734,7 @@ public class Interpreter extends InterpreterBase {
             // evaluate the body
             return tryBody.jjtAccept(this, data);
         } finally {
+            closeIfSupported(tryResult);
             // restore lexical frame
             if (lexical) {
                 block = block.pop();
diff --git a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
index 7dbcebaa..a09f2f21 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
+++ b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
@@ -82,6 +82,7 @@ PARSER_END(Parser)
 
 TOKEN_MGR_DECLS : {
     boolean comparatorNames = false;
+    boolean jexl331 = true;
 }
 
 /***************************************
@@ -219,11 +220,14 @@ TOKEN_MGR_DECLS : {
     | < NULL : "null" >
     | < TRUE : "true" >
     | < FALSE : "false" >
-    | < THROW : "throw" >
+}
+
+<NEVER> TOKEN : /* Exception handling. */
+{
+      < THROW : "throw" >
     | < TRY : "try" >
     | < CATCH : "catch" >
     | < FINALLY : "finally" >
-
 }
 
 /***************************************
@@ -249,7 +253,8 @@ TOKEN_MGR_DECLS : {
   < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>|<ESCAPE>)* >
   {
       matchedToken.image = StringParser.unescapeIdentifier(matchedToken.image);
-      if (comparatorNames && matchedToken.image.length() == 2) {
+      final int length = matchedToken.image.length();
+      if (comparatorNames && length == 2) {
           switch (matchedToken.image) {
              case "ne" : matchedToken.kind = NE; break;
              case "eq" : matchedToken.kind = EQ; break;
@@ -258,6 +263,13 @@ TOKEN_MGR_DECLS : {
              case "gt" : matchedToken.kind = GT; break;
              case "ge" : matchedToken.kind = GE; break;
           }
+      } else if (jexl331 && length >= 3 && length <= 7) {
+          switch (matchedToken.image) {
+             case "try" : matchedToken.kind = TRY; break;
+             case "catch" : matchedToken.kind = CATCH; break;
+             case "finally" : matchedToken.kind = FINALLY; break;
+             case "throw" : matchedToken.kind = THROW; break;
+          }
       }
   }
 |
@@ -420,7 +432,7 @@ void TryStatement() : {
     {
         pushUnit(jjtThis);
     }
-    <TRY> (<LPAREN> (LOOKAHEAD(3) InlineVar() <assign> { tryForm |= 1; })? Expression() <RPAREN> { tryForm |= 2; })?
+     <TRY> (LOOKAHEAD(2) <LPAREN> (LOOKAHEAD(3) InlineVar() <assign> { tryForm |= 1; })? Expression() <RPAREN> { tryForm |= 2; })?
      ((LOOKAHEAD(1) Block() | StatementNoVar())  { tryForm |= 4; })
      (LOOKAHEAD(1) <CATCH> <LPAREN> InlineVar() <RPAREN>  (LOOKAHEAD(1) Block() | StatementNoVar()) { tryForm |= 8; })?
      (LOOKAHEAD(1) <FINALLY>  (LOOKAHEAD(1) Block() | StatementNoVar()) { tryForm |= 16; })?
diff --git a/src/test/java/org/apache/commons/jexl3/FeaturesTest.java b/src/test/java/org/apache/commons/jexl3/FeaturesTest.java
index a125a389..ce7e49c4 100644
--- a/src/test/java/org/apache/commons/jexl3/FeaturesTest.java
+++ b/src/test/java/org/apache/commons/jexl3/FeaturesTest.java
@@ -97,7 +97,7 @@ public class FeaturesTest extends JexlTestCase {
         for(String varName : reserved) {
             String src = "var " + varName;
             //JexlScript script = jexl.createScript(src);
-            Assert.assertThrows(JexlException.Feature.class, () -> jexl.createScript(src));
+            Assert.assertThrows(src, JexlException.Feature.class, () -> jexl.createScript(src));
         }
         final String[] cmpNameScripts = {
             "1 eq 1",
diff --git a/src/test/java/org/apache/commons/jexl3/LexicalTest.java b/src/test/java/org/apache/commons/jexl3/LexicalTest.java
index 6a5549a8..a657a5f0 100644
--- a/src/test/java/org/apache/commons/jexl3/LexicalTest.java
+++ b/src/test/java/org/apache/commons/jexl3/LexicalTest.java
@@ -550,8 +550,8 @@ public class LexicalTest {
         ctxt.set("options", options);
         final JexlScript runner = jexl.createScript(
                 "options.lexical = flag; options.lexicalShade = flag;"
-              + "tryCatch(test, catch, 42);",
-                "flag", "test", "catch");
+              + "tryCatch(test, catcher, 42);",
+                "flag", "test", "catcher");
         final JexlScript tested = jexl.createScript("(y)->{ {var x = y;} x }");
         final JexlScript catchFn = jexl.createScript("(xany)-> { xany }");
         Object result;
diff --git a/src/test/java/org/apache/commons/jexl3/TryCatchFinallyTest.java b/src/test/java/org/apache/commons/jexl3/TryCatchFinallyTest.java
index 38535f64..7732b1c5 100644
--- a/src/test/java/org/apache/commons/jexl3/TryCatchFinallyTest.java
+++ b/src/test/java/org/apache/commons/jexl3/TryCatchFinallyTest.java
@@ -19,6 +19,9 @@ package org.apache.commons.jexl3;
 import org.junit.Assert;
 import org.junit.Test;
 
+import java.io.Closeable;
+import java.io.IOException;
+
 public class TryCatchFinallyTest extends JexlTestCase {
   public TryCatchFinallyTest() {
     super(TryCatchFinallyTest.class.getSimpleName());
@@ -32,6 +35,7 @@ public class TryCatchFinallyTest extends JexlTestCase {
     Object result = script.execute(null);
     Assert.assertEquals(42, result);
   }
+
   @Test
   public void testForm0x17() {
     String src = "try(let x = 42) { x; } finally { 169; }";
@@ -41,18 +45,41 @@ public class TryCatchFinallyTest extends JexlTestCase {
     Assert.assertEquals(42, result);
   }
 
+  public static class Circuit implements Closeable {
+    boolean opened = true;
 
-  @Test
-  public void testEdgeTry() {
-    int i = 0;
-    while(i++ < 5) {
-      System.out.println("i: " + i);
-      try {
-        throw new JexlException.Continue(null);
-      } finally {
-        continue;
-      }
+    public boolean isOpened() {
+      return opened;
+    }
+    @Override
+    public void close() throws IOException {
+      opened = false;
     }
-    System.out.println("iii: " + i);
   }
+
+  @Test
+  public void testForm0x17a() {
+    String src = "try(let x = c) { c.isOpened()? 42 : -42; } finally { 169; }";
+    JexlScript script = JEXL.createScript(src, "c");
+    Circuit circuit = new Circuit();
+    Assert.assertNotNull(script);
+    Object result = script.execute(null, circuit);
+    Assert.assertEquals(42, result);
+    Assert.assertFalse(circuit.isOpened());
+  }
+
+
+//  @Test
+//  public void testEdgeTry() {
+//    int i = 0;
+//    while(i++ < 5) {
+//      System.out.println("i: " + i);
+//      try {
+//        throw new JexlException.Continue(null);
+//      } finally {
+//        continue;
+//      }
+//    }
+//    System.out.println("iii: " + i);
+//  }
 }