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

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


The following commit(s) were added to refs/heads/master by this push:
     new 1934f2bd JEXL-431: try statement must be a lexical statement (local 
variable declaration in catach); - nitpicking on formatting 
(if/while/for/try/catch + space); - try and improve precision for error 
messages; - unrelated, use signum to invert sign in compare method
1934f2bd is described below

commit 1934f2bd3a392382ee525bd649da10eda0e9ef2d
Author: Henrib <hbies...@gmail.com>
AuthorDate: Sun Dec 8 18:49:45 2024 +0100

    JEXL-431: try statement must be a lexical statement (local variable 
declaration in catach);
    - nitpicking on formatting (if/while/for/try/catch + space);
    - try and improve precision for error messages;
    - unrelated, use signum to invert sign in compare method
---
 .../org/apache/commons/jexl3/JexlArithmetic.java   |  2 +-
 .../org/apache/commons/jexl3/JexlException.java    |  2 +-
 .../apache/commons/jexl3/internal/Debugger.java    |  6 ++---
 .../org/apache/commons/jexl3/internal/Engine.java  |  7 ++----
 .../apache/commons/jexl3/internal/Operator.java    |  2 +-
 .../commons/jexl3/parser/ASTTryStatement.java      |  2 +-
 .../org/apache/commons/jexl3/parser/JexlNode.java  | 12 +++++++++-
 .../apache/commons/jexl3/parser/JexlParser.java    | 11 +++++----
 .../org/apache/commons/jexl3/parser/Parser.jjt     |  6 +++++
 .../java/org/apache/commons/jexl3/ForEachTest.java | 26 +++++++++++-----------
 .../org/apache/commons/jexl3/Issues400Test.java    | 10 +++++++++
 .../java/org/apache/commons/jexl3/JXLTTest.java    |  2 +-
 .../jexl3/parser/FeatureControllerTest.java        |  6 ++---
 13 files changed, 58 insertions(+), 36 deletions(-)

diff --git a/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java 
b/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
index 8f731996..f9c2472e 100644
--- a/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
+++ b/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
@@ -804,7 +804,7 @@ public class JexlArithmetic {
                 @SuppressWarnings("unchecked") // OK because of instanceof 
check above
                 final Comparable<Object> comparable = (Comparable<Object>) 
right;
                 try {
-                    return -comparable.compareTo(left);
+                    return -Integer.signum(comparable.compareTo(left));
                 } catch (final ClassCastException castException) {
                     // ignore it, continue in sequence
                 }
diff --git a/src/main/java/org/apache/commons/jexl3/JexlException.java 
b/src/main/java/org/apache/commons/jexl3/JexlException.java
index 086630e5..640f0ef3 100644
--- a/src/main/java/org/apache/commons/jexl3/JexlException.java
+++ b/src/main/java/org/apache/commons/jexl3/JexlException.java
@@ -658,7 +658,7 @@ public class JexlException extends RuntimeException {
     private static final long serialVersionUID = 20210606123900L;
 
     /** Maximum number of characters around exception location. */
-    private static final int MAX_EXCHARLOC = 42;
+    private static final int MAX_EXCHARLOC = 128;
 
     /** Used 3 times. */
     private static final String VARQUOTE = "variable '";
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Debugger.java 
b/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
index 508d61da..6d6e3bab 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
@@ -876,7 +876,7 @@ public class Debugger extends ParserVisitor implements 
JexlInfo.Detail {
     @Override
     protected Object visit(final ASTForeachStatement node, final Object data) {
         final int form = node.getLoopForm();
-        builder.append("for(");
+        builder.append("for (");
         final JexlNode body;
         if (form == 0) {
             // for( .. : ...)
@@ -1411,7 +1411,7 @@ public class Debugger extends ParserVisitor implements 
JexlInfo.Detail {
     @Override
     protected Object visit(final ASTTryResources node, final Object data) {
         final int tryBody = node.jjtGetNumChildren() - 1;
-        builder.append('(');
+        builder.append(" (");
         accept(node.jjtGetChild(0), data);
         for(int c = 1; c < tryBody; ++c) {
             builder.append("; ");
@@ -1430,7 +1430,7 @@ public class Debugger extends ParserVisitor implements 
JexlInfo.Detail {
         accept(node.jjtGetChild(nc++), data);
         // catch-body
         if (node.hasCatchClause()) {
-            builder.append("catch(");
+            builder.append("catch (");
             accept(node.jjtGetChild(nc++), data);
             builder.append(") ");
             accept(node.jjtGetChild(nc++), data);
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Engine.java 
b/src/main/java/org/apache/commons/jexl3/internal/Engine.java
index 96d1b2c4..a9671363 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Engine.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Engine.java
@@ -796,11 +796,8 @@ public class Engine extends JexlEngine {
         ASTJexlScript script;
         if (source != null) {
             script = cache.get(source);
-            if (script != null) {
-                final Scope f = script.getScope();
-                if (f == null && scope == null || f != null && 
f.equals(scope)) {
-                    return script;
-                }
+            if (script != null && (scope == null || 
scope.equals(script.getScope()))) {
+                return script;
             }
         }
         final JexlInfo ninfo = info == null && debug ? createInfo() : info;
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Operator.java 
b/src/main/java/org/apache/commons/jexl3/internal/Operator.java
index faa755f6..c31ccd1b 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Operator.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Operator.java
@@ -645,7 +645,7 @@ public final class Operator implements 
JexlOperator.Uberspect {
         @Override
         public Object tryInvoke(String name, Object arithmetic, Object... 
params) throws JexlException.TryFailed {
             final Object cmp = 
compare.tryInvoke(JexlOperator.COMPARE.getMethodName(), arithmetic, params[1], 
params[0]);
-            return cmp instanceof Integer? operate(-(int) cmp) : 
JexlEngine.TRY_FAILED;
+            return cmp instanceof Integer? operate(-Integer.signum((Integer) 
cmp)) : JexlEngine.TRY_FAILED;
         }
     }
 }
diff --git a/src/main/java/org/apache/commons/jexl3/parser/ASTTryStatement.java 
b/src/main/java/org/apache/commons/jexl3/parser/ASTTryStatement.java
index aa8d0d13..f01de8fb 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/ASTTryStatement.java
+++ b/src/main/java/org/apache/commons/jexl3/parser/ASTTryStatement.java
@@ -19,7 +19,7 @@ package org.apache.commons.jexl3.parser;
 /**
  * Declares a try/catch/finally statement.
  */
-public class ASTTryStatement extends JexlNode {
+public class ASTTryStatement extends JexlLexicalNode {
     private static final long serialVersionUID = 1L;
     /** catch() &= 1, finally &= 2. */
     private int tryForm;
diff --git a/src/main/java/org/apache/commons/jexl3/parser/JexlNode.java 
b/src/main/java/org/apache/commons/jexl3/parser/JexlNode.java
index 3154081f..5b30c413 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/JexlNode.java
+++ b/src/main/java/org/apache/commons/jexl3/parser/JexlNode.java
@@ -313,6 +313,16 @@ public abstract class JexlNode extends SimpleNode 
implements JexlCache.Reference
      * @return the info
      */
     public JexlInfo jexlInfo() {
+        return jexlInfo(null);
+    }
+
+    /**
+     * Gets the associated JexlInfo instance.
+     *
+     * @param name the source name
+     * @return the info
+     */
+    public JexlInfo jexlInfo(String name) {
         JexlInfo info = null;
         JexlNode node = this;
         while (node != null) {
@@ -326,7 +336,7 @@ public abstract class JexlNode extends SimpleNode 
implements JexlCache.Reference
             final int c = lc & 0xfff;
             final int l = lc >> 0xc;
             // at least an info with line/column number
-            return info != null ? info.at(info.getLine() + l - 1, c) : new 
JexlInfo(null, l, c);
+            return info != null ? info.at(info.getLine() + l - 1, c) : new 
JexlInfo(name, l, c);
         }
         // weird though; no jjSetFirstToken(...) ever called?
         return info;
diff --git a/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java 
b/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
index c360bf7e..340036d2 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
+++ b/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
@@ -502,7 +502,8 @@ public abstract class JexlParser extends StringParser {
         // if not the first time we declare this symbol...
         if (!declareSymbol(symbol)) {
             if (lexical || scope.isLexical(symbol) || 
getFeatures().isLexical()) {
-                throw new JexlException.Parsing(variable.jexlInfo(), name + ": 
variable is already declared").clean();
+                final JexlInfo location = info.at(token.beginLine, 
token.beginColumn);
+                throw new JexlException.Parsing(location, name + ": variable 
is already declared").clean();
             }
             // not lexical, redefined nevertheless
             variable.setRedefined(true);
@@ -555,6 +556,7 @@ public abstract class JexlParser extends StringParser {
     protected void Identifier(final boolean top) throws ParseException {
         // Overridden by generated code
     }
+
     /**
      * Checks whether a symbol has been declared as a const in the current 
stack of lexical units.
      * @param symbol the symbol
@@ -603,10 +605,7 @@ public abstract class JexlParser extends StringParser {
             return true;
         }
         // declared through engine features ?
-        if (getFeatures().namespaceTest().test(name)) {
-            return true;
-        }
-        return false;
+        return getFeatures().namespaceTest().test(name);
     }
 
     /**
@@ -814,7 +813,7 @@ public abstract class JexlParser extends StringParser {
      * @throws JexlException.Ambiguous in all cases
      */
     protected void throwAmbiguousException(final JexlNode node) {
-        final JexlInfo begin = node.jexlInfo();
+        final JexlInfo begin = node.jexlInfo(info.getName());
         final Token t = getToken(0);
         final JexlInfo end = info.at(t.beginLine, t.endColumn);
         final String msg = readSourceLine(source, end.getLine());
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 4dd4fee6..9eeac794 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
+++ b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
@@ -444,9 +444,15 @@ void IfStatement() : {}
 
 void TryStatement() : {}
 {
+    {
+         pushUnit(jjtThis);
+     }
      <TRY> (LOOKAHEAD(1) (TryResources() ) | Block())
      (LOOKAHEAD(1) <CATCH> <LPAREN> InlineVar() <RPAREN> Block() { 
jjtThis.catchClause(); })?
      (LOOKAHEAD(1) <FINALLY>  Block() { jjtThis.finallyClause(); })?
+    {
+         popUnit(jjtThis);
+     }
 }
 
 void TryResources() : {}
diff --git a/src/test/java/org/apache/commons/jexl3/ForEachTest.java 
b/src/test/java/org/apache/commons/jexl3/ForEachTest.java
index 624507de..d3c65341 100644
--- a/src/test/java/org/apache/commons/jexl3/ForEachTest.java
+++ b/src/test/java/org/apache/commons/jexl3/ForEachTest.java
@@ -53,7 +53,7 @@ public class ForEachTest extends JexlTestCase {
     @Test
     public void testForEachBreakMethod() throws Exception {
         final JexlScript e = JEXL.createScript(
-                "var rr = -1; for(var item : [1, 2, 3 ,4 ,5, 6]) { if (item == 
3) { rr = item; break; }} rr"
+                "var rr = -1; for (var item : [1, 2, 3 ,4 ,5, 6]) { if (item 
== 3) { rr = item; break; }} rr"
         );
         final JexlContext jc = new MapContext();
         jc.set("list", new Foo());
@@ -71,7 +71,7 @@ public class ForEachTest extends JexlTestCase {
     @Test
     public void testForEachContinueMethod() throws Exception {
         final JexlScript e = JEXL.createScript(
-                "var rr = 0; for(var item : [1, 2, 3 ,4 ,5, 6]) { if (item <= 
3) continue; rr = rr + item;}"
+                "var rr = 0; for (var item : [1, 2, 3 ,4 ,5, 6]) { if (item <= 
3) continue; rr = rr + item;}"
         );
         final JexlContext jc = new MapContext();
         jc.set("list", new Foo());
@@ -81,7 +81,7 @@ public class ForEachTest extends JexlTestCase {
 
     @Test
     public void testForEachWithArray() throws Exception {
-        final JexlScript e = JEXL.createScript("for(item : list) item");
+        final JexlScript e = JEXL.createScript("for (item : list) item");
         final JexlContext jc = new MapContext();
         jc.set("list", new Object[]{"Hello", "World"});
         final Object o = e.execute(jc);
@@ -90,7 +90,7 @@ public class ForEachTest extends JexlTestCase {
 
     @Test
     public void testForEachWithBlock() throws Exception {
-        final JexlScript exs0 = JEXL.createScript("for(var in : list) { x = x 
+ in; }");
+        final JexlScript exs0 = JEXL.createScript("for (var in : list) { x = x 
+ in; }");
         final JexlContext jc = new MapContext();
         jc.set("list", new Object[]{2, 3});
             jc.set("x", Integer.valueOf(1));
@@ -101,7 +101,7 @@ public class ForEachTest extends JexlTestCase {
 
     @Test
     public void testForEachWithCollection() throws Exception {
-        final JexlScript e = JEXL.createScript("for(var item : list) item");
+        final JexlScript e = JEXL.createScript("for (var item : list) item");
         final JexlContext jc = new MapContext();
         jc.set("list", Arrays.asList("Hello", "World"));
         final Object o = e.execute(jc);
@@ -110,7 +110,7 @@ public class ForEachTest extends JexlTestCase {
 
     @Test
     public void testForEachWithEmptyList() throws Exception {
-        final JexlScript e = JEXL.createScript("for(item : list) 1+1");
+        final JexlScript e = JEXL.createScript("for (item : list) 1+1");
         final JexlContext jc = new MapContext();
         jc.set("list", Collections.emptyList());
 
@@ -120,7 +120,7 @@ public class ForEachTest extends JexlTestCase {
 
     @Test
     public void testForEachWithEmptyStatement() throws Exception {
-        final JexlScript e = JEXL.createScript("for(item : list) ;");
+        final JexlScript e = JEXL.createScript("for (item : list) ;");
         final JexlContext jc = new MapContext();
         jc.set("list", Collections.emptyList());
 
@@ -130,7 +130,7 @@ public class ForEachTest extends JexlTestCase {
 
     @Test
     public void testForEachWithEnumeration() throws Exception {
-        final JexlScript e = JEXL.createScript("for(var item : list) item");
+        final JexlScript e = JEXL.createScript("for (var item : list) item");
         final JexlContext jc = new MapContext();
         jc.set("list", new StringTokenizer("Hello,World", ","));
         final Object o = e.execute(jc);
@@ -139,7 +139,7 @@ public class ForEachTest extends JexlTestCase {
 
     @Test
     public void testForEachWithIterator() throws Exception {
-        final JexlScript e = JEXL.createScript("for(var item : list) item");
+        final JexlScript e = JEXL.createScript("for (var item : list) item");
         final JexlContext jc = new MapContext();
         jc.set("list", Arrays.asList("Hello", "World").iterator());
         final Object o = e.execute(jc);
@@ -148,7 +148,7 @@ public class ForEachTest extends JexlTestCase {
 
     @Test
     public void testForEachWithIteratorMethod() throws Exception {
-        final JexlScript e = JEXL.createScript("for(var item : list.cheezy) 
item");
+        final JexlScript e = JEXL.createScript("for (var item : list.cheezy) 
item");
         final JexlContext jc = new MapContext();
         jc.set("list", new Foo());
         final Object o = e.execute(jc);
@@ -157,7 +157,7 @@ public class ForEachTest extends JexlTestCase {
 
     @Test
     public void testForEachWithListExpression() throws Exception {
-        final JexlScript e = JEXL.createScript("for(var item : list.keySet()) 
item");
+        final JexlScript e = JEXL.createScript("for (var item : list.keySet()) 
item");
         final JexlContext jc = new MapContext();
         final Map<?, ?> map = System.getProperties();
         final String lastKey = (String) new 
ArrayList<Object>(map.keySet()).get(System.getProperties().size() - 1);
@@ -187,7 +187,7 @@ public class ForEachTest extends JexlTestCase {
     }
 
     @Test public void testForLoop0a() {
-        final String src = "(l)->{ for(let x = 0; x < 4; ++x) { l.add(x); } }";
+        final String src = "(l)->{ for (let x = 0; x < 4; ++x) { l.add(x); } 
}";
         final JexlEngine jexl = new JexlBuilder().safe(false).create();
         final JexlScript script = jexl.createScript(src);
         final List<Integer> l = new ArrayList<>();
@@ -199,7 +199,7 @@ public class ForEachTest extends JexlTestCase {
     }
 
     @Test public void testForLoop0b0() {
-        final String src = "(l)->{ for(let x = 0, y = 0; x < 4; ++x) l.add(x) 
}";
+        final String src = "(l)->{ for (let x = 0, y = 0; x < 4; ++x) l.add(x) 
}";
         final JexlEngine jexl = new JexlBuilder().safe(false).create();
         final JexlScript script = jexl.createScript(src);
         final List<Integer> l = new ArrayList<>();
diff --git a/src/test/java/org/apache/commons/jexl3/Issues400Test.java 
b/src/test/java/org/apache/commons/jexl3/Issues400Test.java
index 81e7cd55..f599fbc8 100644
--- a/src/test/java/org/apache/commons/jexl3/Issues400Test.java
+++ b/src/test/java/org/apache/commons/jexl3/Issues400Test.java
@@ -493,4 +493,14 @@ public class Issues400Test {
         script = jexl.createScript(src);
         assertEquals(20042, (int) script.execute(ctxt));
     }
+
+    @Test
+    void test431() {
+        JexlEngine jexl = new JexlBuilder().create();
+        final String src = "let x = 0; try { x += 19 } catch (let error) { 
return 169 } try { x += 23 } catch (let error) { return 169 }";
+        final JexlScript script = jexl.createScript(src);
+        assertNotNull(script);
+        final Object result = script.execute(null);
+        assertEquals(42, result);
+    }
 }
diff --git a/src/test/java/org/apache/commons/jexl3/JXLTTest.java 
b/src/test/java/org/apache/commons/jexl3/JXLTTest.java
index 0a30af3e..9869bb62 100644
--- a/src/test/java/org/apache/commons/jexl3/JXLTTest.java
+++ b/src/test/java/org/apache/commons/jexl3/JXLTTest.java
@@ -420,7 +420,7 @@ public class JXLTTest extends JexlTestCase {
         init(builder);
         // @formatter:off
         final String test42
-                = "$$ for(var x : list) {\n"
+                = "$$ for (var x : list) {\n"
                 + "$$   if (x == 42) {\n"
                 + "Life, the universe, and everything\n"
                 + "$$   } else if (x > 42) {\n"
diff --git 
a/src/test/java/org/apache/commons/jexl3/parser/FeatureControllerTest.java 
b/src/test/java/org/apache/commons/jexl3/parser/FeatureControllerTest.java
index d804b93b..72ffd62a 100644
--- a/src/test/java/org/apache/commons/jexl3/parser/FeatureControllerTest.java
+++ b/src/test/java/org/apache/commons/jexl3/parser/FeatureControllerTest.java
@@ -53,7 +53,7 @@ public class FeatureControllerTest extends JexlTestCase {
         offAsserter.setVariable("cond", true);
         offAsserter.setVariable("i", 0);
         String matchException = "@1:1 loop error in 'while (...) ...'";
-        final String whileExpr = "while(cond) { i++;  cond = false; }; i;";
+        final String whileExpr = "while (cond) { i++;  cond = false; }; i;";
         onAsserter.assertExpression(whileExpr, 1);
         offAsserter.failExpression(whileExpr, matchException, String::equals);
 
@@ -64,7 +64,7 @@ public class FeatureControllerTest extends JexlTestCase {
         onAsserter.assertExpression(doWhileExpr, 1);
         offAsserter.failExpression(doWhileExpr, matchException, 
String::equals);
 
-        matchException = "@1:1 loop error in 'for(... : ...) ...'";
+        matchException = "@1:1 loop error in 'for (... : ...) ...'";
         onAsserter.setVariable("i", 0);
         offAsserter.setVariable("i", 0);
         String forExpr = "for (let j : [1, 2]) { i = i + j; }; i;";
@@ -76,7 +76,7 @@ public class FeatureControllerTest extends JexlTestCase {
         offAsserter.setVariable("a", a);
         onAsserter.setVariable("i", 0);
         offAsserter.setVariable("i", 0);
-        forExpr = "for(let j = 0; j < 2; ++j) { i = i + a[j]; } i;";
+        forExpr = "for (let j = 0; j < 2; ++j) { i = i + a[j]; } i;";
         onAsserter.assertExpression(forExpr, 3);
         offAsserter.failExpression(forExpr, matchException, String::equals);
     }

Reply via email to