Repository: flex-falcon Updated Branches: refs/heads/develop 3ee42de4b -> 3971196a4
FLEX-34990 Calling new on the result of a function call was not parsed correctly Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/3971196a Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/3971196a Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/3971196a Branch: refs/heads/develop Commit: 3971196a4478853e1fd443e21e011ee1b8ea14c8 Parents: 3ee42de Author: Alex Harui <[email protected]> Authored: Tue Dec 22 22:02:18 2015 -0800 Committer: Alex Harui <[email protected]> Committed: Tue Dec 22 22:02:18 2015 -0800 ---------------------------------------------------------------------- .../js/flexjs/TestFlexJSExpressions.java | 27 +++++++++++++++++ .../feature-tests/as/ASKeywordTests.java | 32 ++++++++++++++++++++ .../compiler/internal/parsing/as/ASParser.g | 24 ++++++++++++--- .../internal/tree/as/FunctionCallNode.java | 7 +++++ 4 files changed, 85 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/3971196a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java ---------------------------------------------------------------------- diff --git a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java index 21d65a1..3ae3c4b 100644 --- a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java +++ b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java @@ -901,6 +901,33 @@ public class TestFlexJSExpressions extends TestGoogExpressions assertOut("\"\\u2028\""); } + @Test + public void testVisitCallFunctionReturnedFromFunction() + { + IFunctionCallNode node = (IFunctionCallNode) getNode("function foo(a:String, b:String):Function { return null }; return foo(3, 4)(1, 2);", + IFunctionCallNode.class); + asBlockWalker.visitFunctionCall(node); + assertOut("foo(3, 4)(1, 2)"); + } + + @Test + public void testVisitNewSimple() + { + IFunctionCallNode node = (IFunctionCallNode) getNode("return new Fn(1, 2);", + IFunctionCallNode.class); + asBlockWalker.visitFunctionCall(node); + assertOut("new Fn(1, 2)"); + } + + @Test + public void testVisitNewComplex() + { + IFunctionCallNode node = (IFunctionCallNode) getNode("return new Fn(\"a\", \"b\", \"return a + b;\")(1, 2);", + IFunctionCallNode.class); + asBlockWalker.visitFunctionCall(node); + assertOut("new (Fn(\"a\", \"b\", \"return a + b;\"))(1, 2)"); + } + protected IBackend createBackend() { return new FlexJSBackend(); http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/3971196a/compiler.tests/feature-tests/as/ASKeywordTests.java ---------------------------------------------------------------------- diff --git a/compiler.tests/feature-tests/as/ASKeywordTests.java b/compiler.tests/feature-tests/as/ASKeywordTests.java index e81e360..c1a5fb4 100644 --- a/compiler.tests/feature-tests/as/ASKeywordTests.java +++ b/compiler.tests/feature-tests/as/ASKeywordTests.java @@ -286,4 +286,36 @@ public class ASKeywordTests extends ASFeatureTestsBase compileAndRun(source); } + @Test + public void AS_new_function_returned_from_function() + { + // all tests can assume that flash.display.Sprite + // flash.system.System and flash.events.Event have been imported + String[] imports = new String[] + { + }; + String[] declarations = new String[] + { + }; + String[] testCode = new String[] + { + "function getClass(index:Number):Class {", + " if (index == 0) return Inner;", + " return Number;", + "}", + "var foo:Inner = new getClass(0)('foo');", + "assertEqual('foo.value', foo.value, 'foo');", + }; + String[] extra = new String[] + { + "class Inner {", + " public function Inner(value:String) {", + " this.value = value;", + " }", + " public var value:String;", + "}", + }; + String source = getAS(imports, declarations, testCode, extra); + compileAndRun(source); + } } http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/3971196a/compiler/src/org/apache/flex/compiler/internal/parsing/as/ASParser.g ---------------------------------------------------------------------- diff --git a/compiler/src/org/apache/flex/compiler/internal/parsing/as/ASParser.g b/compiler/src/org/apache/flex/compiler/internal/parsing/as/ASParser.g index 32e0135..9b21966 100644 --- a/compiler/src/org/apache/flex/compiler/internal/parsing/as/ASParser.g +++ b/compiler/src/org/apache/flex/compiler/internal/parsing/as/ASParser.g @@ -3074,10 +3074,21 @@ arguments[ExpressionNodeBase root] returns[ExpressionNodeBase n] final boolean isNewExpression = (n instanceof FunctionCallNode) && ((FunctionCallNode)n).isNewExpression(); - - if (n == null || !isNewExpression) + final boolean newFunctionCallAlreadyHasArgs = isNewExpression && + ((FunctionCallNode)n).getArgumentsNode().getStart() != -1; + // the above line is a hack to try to catch "new" expressions + // where the class to instantiate is the result of a function + // call: new someFunction(someArgs)(constructorParams) + // we check to see if the arg node as a start() value which + // means that the first argument list (someargs) was already + // processed. + final FunctionCallNode oldNode = newFunctionCallAlreadyHasArgs ? (FunctionCallNode)n : null; + if (n == null || !isNewExpression || newFunctionCallAlreadyHasArgs ) n = new FunctionCallNode(n); - + if (newFunctionCallAlreadyHasArgs) { + ((FunctionCallNode)n).setNewKeywordNode(oldNode.getNewKeywordNode()); + oldNode.setNewKeywordNode(null); + } args = ((FunctionCallNode)n).getArgumentsNode(); args.startAfter(lpT); args.endAfter(lpT); @@ -3086,8 +3097,6 @@ arguments[ExpressionNodeBase root] returns[ExpressionNodeBase n] ( argumentList[args] ) - rpT:TOKEN_PAREN_CLOSE - { args.endAfter(rpT); enableSemicolonInsertion(); } ; exception catch [RecognitionException ex] { @@ -3158,7 +3167,12 @@ argumentList[ContainerNode args] args.addItem(n); } } + | rpT:TOKEN_PAREN_CLOSE + { args.endAfter(rpT); enableSemicolonInsertion(); break;} + )* + + ; /** http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/3971196a/compiler/src/org/apache/flex/compiler/internal/tree/as/FunctionCallNode.java ---------------------------------------------------------------------- diff --git a/compiler/src/org/apache/flex/compiler/internal/tree/as/FunctionCallNode.java b/compiler/src/org/apache/flex/compiler/internal/tree/as/FunctionCallNode.java index b3f887f..45b2a07 100644 --- a/compiler/src/org/apache/flex/compiler/internal/tree/as/FunctionCallNode.java +++ b/compiler/src/org/apache/flex/compiler/internal/tree/as/FunctionCallNode.java @@ -301,6 +301,13 @@ public class FunctionCallNode extends ExpressionNodeBase implements IFunctionCal { return newKeywordNode; } + + public void setNewKeywordNode(KeywordNode newNode) + { + newKeywordNode = newNode; + if (newKeywordNode != null) + newKeywordNode.setParent(this); + } @Override public boolean isCallToSuper()
