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 2022/05/21 10:02:32 UTC
[commons-jexl] branch master updated: JEXL-369: named function declarations are statements, not expressions; made debugger properly recode let/const parameters; tests shuffling;
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 c1ec13b4 JEXL-369: named function declarations are statements, not expressions; made debugger properly recode let/const parameters; tests shuffling;
c1ec13b4 is described below
commit c1ec13b41469f36a95d9ecac100ccf17beb56ce7
Author: henrib <he...@apache.org>
AuthorDate: Sat May 21 12:02:25 2022 +0200
JEXL-369: named function declarations are statements, not expressions;
made debugger properly recode let/const parameters;
tests shuffling;
---
.../apache/commons/jexl3/internal/Debugger.java | 20 ++++--
.../org/apache/commons/jexl3/parser/Parser.jjt | 9 ++-
.../java/org/apache/commons/jexl3/LambdaTest.java | 76 +++++-----------------
.../java/org/apache/commons/jexl3/LexicalTest.java | 63 ++++++++++++++++++
4 files changed, 102 insertions(+), 66 deletions(-)
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 6617c3db..ca3dacdb 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
@@ -731,11 +731,21 @@ public class Debugger extends ParserVisitor implements JexlInfo.Detail {
}
builder.append('(');
final String[] params = lambda.getParameters();
- if (params != null && params.length > 0) {
- builder.append(visitParameter(params[0], data));
- for (int p = 1; p < params.length; ++p) {
- builder.append(", ");
- builder.append(visitParameter(params[p], data));
+ if (params != null ) {
+ Scope scope = lambda.getScope();
+ LexicalScope lexicalScope = lambda.getLexicalScope();
+ for (int p = 0; p < params.length; ++p) {
+ if (p > 0) {
+ builder.append(", ");
+ }
+ String param = params[p];
+ int symbol = scope.getSymbol(param);
+ if (lexicalScope.isConstant(symbol)) {
+ builder.append("const ");
+ } else if (scope.isLexical(symbol)) {
+ builder.append("let ");
+ }
+ builder.append(visitParameter(param, data));
}
}
builder.append(')');
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 753bad00..865ccc8c 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
+++ b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
@@ -352,6 +352,8 @@ void Statement() #void : {}
{
LOOKAHEAD(<LET>|<CONST>|<VAR>) Var()
|
+ LOOKAHEAD(<FUNCTION> <IDENTIFIER>) FunctionStatement()
+ |
StatementNoVar()
}
@@ -367,7 +369,6 @@ void StatementNoVar() #void : {}
| LOOKAHEAD(<RETURN>) ReturnStatement()
| LOOKAHEAD(<CONTINUE>) Continue()
| LOOKAHEAD(<BREAK>) Break()
- | LOOKAHEAD(<FUNCTION> <IDENTIFIER> <LPAREN>) Lambda()
| LOOKAHEAD(Expression()) ExpressionStatement()
| Block()
| LOOKAHEAD(<VAR>, {!getFeatures().isLexical()} ) Var()
@@ -378,6 +379,10 @@ void Block() #Block : {}
<LCURLY> { pushUnit(jjtThis); } ( Statement() )* { popUnit(jjtThis); } <RCURLY>
}
+void FunctionStatement() #JexlLambda : {}
+{
+<FUNCTION> DeclareFunction() { pushScope(); pushUnit(jjtThis); } Parameters() ( LOOKAHEAD(3) Block() | Expression()) { popUnit(jjtThis); popScope(); }
+}
void ExpressionStatement() #void : {}
{
@@ -887,7 +892,7 @@ void ParametersLookahead() #void : {}
void LambdaLookahead() #void : {}
{
- <FUNCTION> (<IDENTIFIER>)? ParametersLookahead()
+ <FUNCTION> ParametersLookahead()
|
ParametersLookahead() (<LAMBDA> | <FATARROW>)
|
diff --git a/src/test/java/org/apache/commons/jexl3/LambdaTest.java b/src/test/java/org/apache/commons/jexl3/LambdaTest.java
index 31f27401..fb9a5dfb 100644
--- a/src/test/java/org/apache/commons/jexl3/LambdaTest.java
+++ b/src/test/java/org/apache/commons/jexl3/LambdaTest.java
@@ -428,7 +428,7 @@ public class LambdaTest extends JexlTestCase {
}
@Test public void testNamedFunc() {
- String src = "(a)->{ function fact(x) { x <= 1? 1 : x * fact(x - 1); } fact(a); }";
+ String src = "(let a)->{ function fact(const x) { x <= 1? 1 : x * fact(x - 1); } fact(a); }";
JexlEngine jexl = createEngine();
JexlScript script = jexl.createScript(src);
Object result = script.execute(null, 6);
@@ -437,77 +437,35 @@ public class LambdaTest extends JexlTestCase {
Assert.assertEquals(simpleWhitespace(src), parsed);
}
- @Test
- public void testConst0a() {
- final JexlFeatures f = new JexlFeatures();
- final JexlEngine jexl = new JexlBuilder().strict(true).create();
- final JexlScript script = jexl.createScript(
- "{ const x = 10; x + 1 }; { let x = 20; x = 22}");
- final JexlContext jc = new MapContext();
- final Object result = script.execute(jc);
- Assert.assertEquals(22, result);
- }
-
- @Test
- public void testConstb0() {
- final JexlFeatures f = new JexlFeatures();
- final JexlEngine jexl = new JexlBuilder().strict(true).create();
- final JexlScript script = jexl.createScript(
- "{ const x = 10; }{ const x = 20; }");
- final JexlContext jc = new MapContext();
- final Object result = script.execute(jc);
- Assert.assertEquals(20, result);
- }
-
- @Test
- public void testConst1() {
- final JexlFeatures f = new JexlFeatures();
- final JexlEngine jexl = new JexlBuilder().strict(true).create();
+ @Test public void testNamedFuncIsConst() {
+ String src = "function foo(x) { x + x }; var foo ='nonononon'";
+ JexlEngine jexl = createEngine();
try {
- final JexlScript script = jexl.createScript(
- "const foo; foo");
- Assert.fail("should fail, const foo must be followed by assign.");
+ JexlScript script = jexl.createScript(src);
+ Assert.fail("should fail, foo is already defined");
} catch(JexlException.Parsing xparse) {
- Assert.assertTrue(xparse.getMessage().contains("const"));
+ Assert.assertTrue(xparse.getMessage().contains("foo"));
}
}
-
@Test
- public void testConst2a() {
- final JexlFeatures f = new JexlFeatures();
- final JexlEngine jexl = new JexlBuilder().strict(true).create();
- for(String op : Arrays.asList("=", "+=", "-=", "/=", "*=", "%=", "<<=", ">>=", ">>>=", "^=", "&=", "|=")) {
- try {
- final JexlScript script = jexl.createScript("const foo = 42; foo "+op+" 1;");
- Assert.fail("should fail, const precludes assignment");
- } catch (JexlException.Parsing xparse) {
- Assert.assertTrue(xparse.getMessage().contains("foo"));
- }
+ public void testFailParseFunc0() {
+ String src = "if (false) function foo(x) { x + x }; var foo = 1";
+ JexlEngine jexl = createEngine();
+ try {
+ JexlScript script = jexl.createScript(src);
+ } catch(JexlException.Parsing xparse) {
+ Assert.assertTrue(xparse.getMessage().contains("function"));
}
}
@Test
- public void testConst2b() {
- final JexlFeatures f = new JexlFeatures();
- final JexlEngine jexl = new JexlBuilder().strict(true).create();
- for(String op : Arrays.asList("=", "+=", "-=", "/=", "*=", "%=", "<<=", ">>=", ">>>=", "^=", "&=", "|=")) {
- try {
- final JexlScript script = jexl.createScript("{ const foo = 42; } { let foo = 0; foo " + op + " 1; }");
- Assert.assertNotNull(script);
- } catch(JexlException.Parsing xparse) {
- Assert.fail(xparse.toString());
- }
- }
- }
-
- @Test public void testNamedFuncIsConst() {
- String src = "function foo(x) { x + x }; var foo ='nonononon'";
+ public void testFailParseFunc1() {
+ String src = "if (false) let foo = (x) { x + x }; var foo = 1";
JexlEngine jexl = createEngine();
try {
JexlScript script = jexl.createScript(src);
- Assert.fail("should fail, foo is already defined");
} catch(JexlException.Parsing xparse) {
- Assert.assertTrue(xparse.getMessage().contains("foo"));
+ Assert.assertTrue(xparse.getMessage().contains("let"));
}
}
diff --git a/src/test/java/org/apache/commons/jexl3/LexicalTest.java b/src/test/java/org/apache/commons/jexl3/LexicalTest.java
index 9271c554..90f7a9b8 100644
--- a/src/test/java/org/apache/commons/jexl3/LexicalTest.java
+++ b/src/test/java/org/apache/commons/jexl3/LexicalTest.java
@@ -884,6 +884,69 @@ public class LexicalTest {
checkParse(srcs, false);
}
+ @Test
+ public void testConst0a() {
+ final JexlFeatures f = new JexlFeatures();
+ final JexlEngine jexl = new JexlBuilder().strict(true).create();
+ final JexlScript script = jexl.createScript(
+ "{ const x = 10; x + 1 }; { let x = 20; x = 22}");
+ final JexlContext jc = new MapContext();
+ final Object result = script.execute(jc);
+ Assert.assertEquals(22, result);
+ }
+
+ @Test
+ public void testConstb0() {
+ final JexlFeatures f = new JexlFeatures();
+ final JexlEngine jexl = new JexlBuilder().strict(true).create();
+ final JexlScript script = jexl.createScript(
+ "{ const x = 10; }{ const x = 20; }");
+ final JexlContext jc = new MapContext();
+ final Object result = script.execute(jc);
+ Assert.assertEquals(20, result);
+ }
+
+ @Test
+ public void testConst1() {
+ final JexlFeatures f = new JexlFeatures();
+ final JexlEngine jexl = new JexlBuilder().strict(true).create();
+ try {
+ final JexlScript script = jexl.createScript(
+ "const foo; foo");
+ Assert.fail("should fail, const foo must be followed by assign.");
+ } catch(JexlException.Parsing xparse) {
+ Assert.assertTrue(xparse.getMessage().contains("const"));
+ }
+ }
+
+ @Test
+ public void testConst2a() {
+ final JexlFeatures f = new JexlFeatures();
+ final JexlEngine jexl = new JexlBuilder().strict(true).create();
+ for(String op : Arrays.asList("=", "+=", "-=", "/=", "*=", "%=", "<<=", ">>=", ">>>=", "^=", "&=", "|=")) {
+ try {
+ final JexlScript script = jexl.createScript("const foo = 42; foo "+op+" 1;");
+ Assert.fail("should fail, const precludes assignment");
+ } catch (JexlException.Parsing xparse) {
+ Assert.assertTrue(xparse.getMessage().contains("foo"));
+ }
+ }
+ }
+
+ @Test
+ public void testConst2b() {
+ final JexlFeatures f = new JexlFeatures();
+ final JexlEngine jexl = new JexlBuilder().strict(true).create();
+ for(String op : Arrays.asList("=", "+=", "-=", "/=", "*=", "%=", "<<=", ">>=", ">>>=", "^=", "&=", "|=")) {
+ try {
+ final JexlScript script = jexl.createScript("{ const foo = 42; } { let foo = 0; foo " + op + " 1; }");
+ Assert.assertNotNull(script);
+ } catch(JexlException.Parsing xparse) {
+ Assert.fail(xparse.toString());
+ }
+ }
+ }
+
@Test
public void testSingleStatementDeclFail() {
List<String> srcs = Arrays.asList(