This is an automated email from the ASF dual-hosted git repository. joshtynjala pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/royale-compiler.git
commit 65c1e78e19ecddfc8cbbf32bea4dd4fef8520421 Author: Josh Tynjala <[email protected]> AuthorDate: Tue Mar 19 16:02:25 2019 -0700 compiler-jx: fixes issue where variables that need default initializers were not hoisted to the top of the function body --- .../codegen/js/royale/JSRoyaleEmitter.java | 107 ++++++++++++++++----- .../internal/codegen/js/utils/EmitterUtils.java | 46 +++++++++ .../codegen/js/royale/TestDefaultInitializers.java | 57 +++++------ .../codegen/js/royale/TestRoyaleExpressions.java | 18 ++-- .../codegen/js/royale/TestRoyaleStatements.java | 24 +++-- 5 files changed, 185 insertions(+), 67 deletions(-) diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java index d1b9dc6..8f9cc44 100644 --- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java +++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java @@ -23,6 +23,7 @@ import java.io.File; import java.io.FilterWriter; import java.io.IOException; import java.util.ArrayList; +import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -38,6 +39,7 @@ import org.apache.royale.compiler.definitions.IDefinition; import org.apache.royale.compiler.definitions.INamespaceDefinition; import org.apache.royale.compiler.definitions.IPackageDefinition; import org.apache.royale.compiler.definitions.ITypeDefinition; +import org.apache.royale.compiler.definitions.IVariableDefinition; import org.apache.royale.compiler.definitions.metadata.IMetaTagAttribute; import org.apache.royale.compiler.definitions.references.INamespaceResolvedReference; import org.apache.royale.compiler.embedding.EmbedAttribute; @@ -156,8 +158,8 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter public ArrayList<String> usedNames = new ArrayList<String>(); public ArrayList<String> staticUsedNames = new ArrayList<String>(); private boolean needNamespace; - - private Set<IFunctionNode> emittingLocalFunctions = new HashSet<IFunctionNode>(); + + private Set<IFunctionNode> emittingHoistedNodes = new HashSet<IFunctionNode>(); @Override public String postProcess(String output) @@ -408,34 +410,34 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter public void emitLocalNamedFunction(IFunctionNode node) { IFunctionNode parentFnNode = (IFunctionNode) node.getAncestorOfType(IFunctionNode.class); - if (parentFnNode == null || isEmittingLocalFunctions(parentFnNode)) + if (parentFnNode == null || isEmittingHoistedNodes(parentFnNode)) { // emit named functions only when allowed super.emitLocalNamedFunction(node); } } - protected Boolean isEmittingLocalFunctions(IFunctionNode node) + protected Boolean isEmittingHoistedNodes(IFunctionNode node) { - return emittingLocalFunctions.contains(node); + return emittingHoistedNodes.contains(node); } - protected void setEmittingLocalFunctions(IFunctionNode node, boolean emit) + protected void setEmittingHoistedNodes(IFunctionNode node, boolean emit) { if (emit) { - emittingLocalFunctions.add(node); + emittingHoistedNodes.add(node); } else { - emittingLocalFunctions.remove(node); + emittingHoistedNodes.remove(node); } } @Override public void emitFunctionBlockHeader(IFunctionNode node) { - setEmittingLocalFunctions(node, true); + setEmittingHoistedNodes(node, true); super.emitFunctionBlockHeader(node); if (node.isConstructor()) { @@ -449,25 +451,57 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter } emitComplexInitializers(cnode); } - if (node.containsLocalFunctions()) + + emitHoistedFunctionsCodeBlock(node); + + if (!getModel().isExterns) + emitHoistedVariablesCodeBlock(node); + + setEmittingHoistedNodes(node, false); + } + + protected void emitHoistedFunctionsCodeBlock(IFunctionNode node) + { + if (!node.containsLocalFunctions()) + { + return; + } + List<IFunctionNode> localFns = node.getLocalFunctions(); + int n = localFns.size(); + for (int i = 0; i < n; i++) + { + IFunctionNode localFn = localFns.get(i); + // named functions need to be declared at the top level to + // comply with JS strict mode. + // anonymous functions can be emitted inline, so we'll do that. + if (localFn.getName().length() > 0) + { + getWalker().walk(localFn); + write(ASEmitterTokens.SEMICOLON); + this.writeNewline(); + } + } + } + + protected void emitHoistedVariablesCodeBlock(IFunctionNode node) + { + Collection<IDefinition> localDefs = node.getScopedNode().getScope().getAllLocalDefinitions(); + for (IDefinition localDef : localDefs) { - List<IFunctionNode> localFns = node.getLocalFunctions(); - int n = localFns.size(); - for (int i = 0; i < n; i++) + if (localDef instanceof IVariableDefinition) { - IFunctionNode localFn = localFns.get(i); - // named functions need to be declared at the top level to - // comply with JS strict mode. - // anonymous functions can be emitted inline, so we'll do that. - if (localFn.getName().length() > 0) + IVariableDefinition varDef = (IVariableDefinition) localDef; + IVariableNode varNode = varDef.getVariableNode(); + if (!EmitterUtils.needsDefaultValue(varNode, getWalker().getProject())) { - getWalker().walk(localFn); - write(ASEmitterTokens.SEMICOLON); - this.writeNewline(); + //already has a default value. no need to hoist. + continue; } + getWalker().walk(varNode); + write(ASEmitterTokens.SEMICOLON); + writeNewline(); } } - setEmittingLocalFunctions(node, false); } @Override @@ -475,7 +509,7 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter { IFunctionNode parentFnNode = (IFunctionNode) node.getAncestorOfType(IFunctionNode.class); IFunctionNode localFnNode = node.getFunctionNode(); - if (parentFnNode == null || isEmittingLocalFunctions(parentFnNode)) + if (parentFnNode == null || isEmittingHoistedNodes(parentFnNode)) { // emit named functions only when allowed super.emitFunctionObject(node); @@ -766,6 +800,33 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter @Override public void emitVarDeclaration(IVariableNode node) { + if (EmitterUtils.needsDefaultValue(node, getWalker().getProject())) + { + boolean defaultInitializers = false; + ICompilerProject project = getWalker().getProject(); + if(project instanceof RoyaleJSProject) + { + RoyaleJSProject fjsProject = (RoyaleJSProject) project; + if(fjsProject.config != null) + { + defaultInitializers = fjsProject.config.getJsDefaultInitializers(); + } + } + + IExpressionNode avnode = node.getAssignedValueNode(); + if (avnode == null && defaultInitializers) + { + IFunctionNode parentFunction = (IFunctionNode) node.getAncestorOfType(IFunctionNode.class); + if (!isEmittingHoistedNodes(parentFunction)) + { + write("//"); + writeToken(ASEmitterTokens.VAR); + write(node.getName()); + return; + } + } + } + varDeclarationEmitter.emit(node); } diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/EmitterUtils.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/EmitterUtils.java index 8adcbb8..079ea94 100644 --- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/EmitterUtils.java +++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/EmitterUtils.java @@ -46,6 +46,7 @@ import org.apache.royale.compiler.internal.tree.as.ParameterNode; import org.apache.royale.compiler.projects.ICompilerProject; import org.apache.royale.compiler.tree.ASTNodeID; import org.apache.royale.compiler.tree.as.IASNode; +import org.apache.royale.compiler.tree.as.IAccessorNode; import org.apache.royale.compiler.tree.as.IClassNode; import org.apache.royale.compiler.tree.as.IContainerNode; import org.apache.royale.compiler.tree.as.IDefinitionNode; @@ -58,6 +59,7 @@ import org.apache.royale.compiler.tree.as.IParameterNode; import org.apache.royale.compiler.tree.as.IScopedNode; import org.apache.royale.compiler.tree.as.ITypeNode; import org.apache.royale.compiler.tree.as.IUnaryOperatorNode; +import org.apache.royale.compiler.tree.as.IVariableExpressionNode; import org.apache.royale.compiler.tree.as.IVariableNode; import org.apache.royale.compiler.utils.NativeUtils; @@ -595,4 +597,48 @@ public class EmitterUtils || node.getContainerType() == IContainerNode.ContainerType.SYNTHESIZED; } + public static boolean needsDefaultValue(IVariableNode node, ICompilerProject project) + { + if (node == null) + { + return false; + } + if (node instanceof IParameterNode) + { + return false; + } + if (node instanceof IAccessorNode) + { + return false; + } + IExpressionNode assignedValueNode = node.getAssignedValueNode(); + if (assignedValueNode != null) + { + //already has an assigned value, so it doesn't need to be + //hoisted + return false; + } + IASNode parentNode = node.getParent(); + if (parentNode instanceof IVariableExpressionNode) + { + //ignore for-in loops + return false; + } + IExpressionNode variableTypeNode = node.getVariableTypeNode(); + if (variableTypeNode == null) + { + return false; + } + IDefinition varTypeDef = variableTypeNode.resolve(project); + if (varTypeDef == null) + { + return false; + } + if (IASLanguageConstants.ANY_TYPE.equals(varTypeDef.getQualifiedName())) + { + return false; + } + return true; + } + } diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestDefaultInitializers.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestDefaultInitializers.java index 6b10627..d51246d 100644 --- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestDefaultInitializers.java +++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestDefaultInitializers.java @@ -25,6 +25,7 @@ import org.apache.royale.compiler.internal.driver.js.goog.JSGoogConfiguration; import org.apache.royale.compiler.internal.driver.js.royale.RoyaleBackend; import org.apache.royale.compiler.internal.projects.RoyaleJSProject; import org.apache.royale.compiler.internal.test.ASTestBase; +import org.apache.royale.compiler.tree.as.IFunctionNode; import org.apache.royale.compiler.tree.as.IVariableNode; import org.junit.Test; @@ -59,10 +60,10 @@ public class TestDefaultInitializers extends ASTestBase public void testVarDeclaration_defaultInitializers_withNumberType() { createConfig(true); - IVariableNode node = (IVariableNode) getNode("var a:Number;", - IVariableNode.class); - asBlockWalker.visitVariable(node); - assertOut("var /** @type {number} */ a = NaN"); + IFunctionNode node = (IFunctionNode) getNode("var a:Number;", + IFunctionNode.class); + asBlockWalker.visitFunction(node); + assertOut("RoyaleTest_A.prototype.royaleTest_a = function() {\n var /** @type {number} */ a = NaN;\n //var a;\n}"); } @Test @@ -79,10 +80,10 @@ public class TestDefaultInitializers extends ASTestBase public void testVarDeclaration_defaultInitializers_withBooleanType() { createConfig(true); - IVariableNode node = (IVariableNode) getNode("var a:Boolean;", - IVariableNode.class); - asBlockWalker.visitVariable(node); - assertOut("var /** @type {boolean} */ a = false"); + IFunctionNode node = (IFunctionNode) getNode("var a:Boolean;", + IFunctionNode.class); + asBlockWalker.visitFunction(node); + assertOut("RoyaleTest_A.prototype.royaleTest_a = function() {\n var /** @type {boolean} */ a = false;\n //var a;\n}"); } @Test @@ -99,10 +100,10 @@ public class TestDefaultInitializers extends ASTestBase public void testVarDeclaration_defaultInitializers_withIntType() { createConfig(true); - IVariableNode node = (IVariableNode) getNode("var a:int;", - IVariableNode.class); - asBlockWalker.visitVariable(node); - assertOut("var /** @type {number} */ a = 0"); + IFunctionNode node = (IFunctionNode) getNode("var a:int;", + IFunctionNode.class); + asBlockWalker.visitFunction(node); + assertOut("RoyaleTest_A.prototype.royaleTest_a = function() {\n var /** @type {number} */ a = 0;\n //var a;\n}"); } @Test @@ -120,10 +121,10 @@ public class TestDefaultInitializers extends ASTestBase public void testVarDeclaration_defaultInitializers_withUintType() { createConfig(true); - IVariableNode node = (IVariableNode) getNode("var a:uint;", - IVariableNode.class); - asBlockWalker.visitVariable(node); - assertOut("var /** @type {number} */ a = 0"); + IFunctionNode node = (IFunctionNode) getNode("var a:uint;", + IFunctionNode.class); + asBlockWalker.visitFunction(node); + assertOut("RoyaleTest_A.prototype.royaleTest_a = function() {\n var /** @type {number} */ a = 0;\n //var a;\n}"); } @Test @@ -141,10 +142,10 @@ public class TestDefaultInitializers extends ASTestBase public void testVarDeclaration_defaultInitializers_withStringType() { createConfig(true); - IVariableNode node = (IVariableNode) getNode("var a:String;", - IVariableNode.class); - asBlockWalker.visitVariable(node); - assertOut("var /** @type {string} */ a = null"); + IFunctionNode node = (IFunctionNode) getNode("var a:String;", + IFunctionNode.class); + asBlockWalker.visitFunction(node); + assertOut("RoyaleTest_A.prototype.royaleTest_a = function() {\n var /** @type {string} */ a = null;\n //var a;\n}"); } @Test @@ -161,10 +162,10 @@ public class TestDefaultInitializers extends ASTestBase public void testVarDeclaration_defaultInitializers_withObjectType() { createConfig(true); - IVariableNode node = (IVariableNode) getNode("var a:Object;", - IVariableNode.class); - asBlockWalker.visitVariable(node); - assertOut("var /** @type {Object} */ a = null"); + IFunctionNode node = (IFunctionNode) getNode("var a:Object;", + IFunctionNode.class); + asBlockWalker.visitFunction(node); + assertOut("RoyaleTest_A.prototype.royaleTest_a = function() {\n var /** @type {Object} */ a = null;\n //var a;\n}"); } @Test @@ -181,10 +182,10 @@ public class TestDefaultInitializers extends ASTestBase public void testVarDeclaration_defaultInitializers_withArrayType() { createConfig(true); - IVariableNode node = (IVariableNode) getNode("var a:Array;", - IVariableNode.class); - asBlockWalker.visitVariable(node); - assertOut("var /** @type {Array} */ a = null"); + IFunctionNode node = (IFunctionNode) getNode("var a:Array;", + IFunctionNode.class); + asBlockWalker.visitFunction(node); + assertOut("RoyaleTest_A.prototype.royaleTest_a = function() {\n var /** @type {Array} */ a = null;\n //var a;\n}"); } @Test diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java index 57276c7..24a0101 100644 --- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java +++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java @@ -178,7 +178,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions @Test public void testVisitLanguageIdentifierNode_SuperMethodAsVarFunctionReference() { - IFileNode node = (IFileNode)getNode("package { public class RoyaleTest_A extends Base { override public function foo() {var f:Function; f = super.foo;} } }\n" + + IFileNode node = (IFileNode)getNode("package { public class RoyaleTest_A extends Base { override public function foo() {var f:Function = null; f = super.foo;} } }\n" + "class Base { public function foo(){} }", IFileNode.class, 0, false); IFunctionNode fnode = (IFunctionNode) findFirstDescendantOfType( node, IFunctionNode.class); @@ -1197,7 +1197,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions public void testMethodAsAssign() { IFunctionNode node = (IFunctionNode) getNode( - "public class B {public function b() { function c(f:Function):void {}; var f:Function; f = b; c(f); }}", + "public class B {public function b() { function c(f:Function):void {}; var f:Function = null; f = b; c(f); }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE); asBlockWalker.visitFunction(node); assertOut("/**\n * @export\n */\nB.prototype.b = function() {\n var self = this;\n function c(f) {\n };\n var /** @type {Function} */ f = null;\n f = org.apache.royale.utils.Language.closure(this.b, this, 'b');\n c(f);\n}"); @@ -1207,7 +1207,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions public void testStaticMethodAsAssign() { IFunctionNode node = (IFunctionNode) getNode( - "public class B {static public function b() { function c(f:Function):void {}; var f:Function; f = b; c(f); }}", + "public class B {static public function b() { function c(f:Function):void {}; var f:Function = null; f = b; c(f); }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE, true); asBlockWalker.visitFunction(node); assertOut("/**\n * @export\n */\nfoo.bar.B.b = function() {\n function c(f) {\n };\n var /** @type {Function} */ f = null;\n f = foo.bar.B.b;\n c(f);\n}"); @@ -1257,7 +1257,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions public void testNativeGetter() { IFunctionNode node = (IFunctionNode) getNode( - "public class B {public function b():Number { var s:String; return s.length; }}", + "public class B {public function b():Number { var s:String = null; return s.length; }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE, true); asBlockWalker.visitFunction(node); // String.length is a getter but is a property in JS, so don't generate set_length() call. @@ -1268,7 +1268,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions public void testNativeVectorGetter() { IFunctionNode node = (IFunctionNode) getNode( - "public class B {public function b():Number { var a:Vector.<String>; return a.length; }}", + "public class B {public function b():Number { var a:Vector.<String> = null; return a.length; }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE, true); asBlockWalker.visitFunction(node); // String.length is a getter but is a property in JS, so don't generate set_length() call. @@ -1326,7 +1326,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions @Test public void testComplexBooleanExpression() { - IFunctionNode node = getMethod("function foo(b:Boolean):Boolean {var c:String; var d:String; if (!(b ? c : d)) { return b;}}"); + IFunctionNode node = getMethod("function foo(b:Boolean):Boolean {var c:String = null; var d:String = null; if (!(b ? c : d)) { return b;}}"); asBlockWalker.visitFunction(node); assertOut("/**\n * @export\n * @param {boolean} b\n * @return {boolean}\n */\nRoyaleTest_A.prototype.foo = function(b) {\n var /** @type {string} */ c = null;\n var /** @type {string} */ d = null;\n if (!(b ? c : d)) {\n return b;\n }\n}"); } @@ -1491,7 +1491,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions public void testVisitAs2() { IFunctionNode node = (IFunctionNode) getNode( - "public class B {public function b(o:Object):int { var a:B; a = o as B; }}", + "public class B {public function b(o:Object):int { var a:B = null; a = o as B; }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE, true); asBlockWalker.visitFunction(node); assertOut("/**\n * @export\n * @param {Object} o\n * @return {number}\n */\nfoo.bar.B.prototype.b = function(o) {\n var /** @type {foo.bar.B} */ a = null;\n a = org.apache.royale.utils.Language.as(o, foo.bar.B);\n}"); @@ -1517,7 +1517,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions public void testVisitAsMemberVariable() { IFunctionNode node = (IFunctionNode) getNode( - "public class B {private var memberVar:Class; public function b(o:Object):int { var a:B; a = o as memberVar; }}", + "public class B {private var memberVar:Class; public function b(o:Object):int { var a:B = null; a = o as memberVar; }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE, true); asBlockWalker.visitFunction(node); assertOut("/**\n * @export\n * @param {Object} o\n * @return {number}\n */\nfoo.bar.B.prototype.b = function(o) {\n var /** @type {foo.bar.B} */ a = null;\n a = org.apache.royale.utils.Language.as(o, this.memberVar);\n}"); @@ -1527,7 +1527,7 @@ public class TestRoyaleExpressions extends TestGoogExpressions public void testVisitJSDoc() { IFunctionNode node = (IFunctionNode) getNode( - "public class LinkableString {public function b(o:Object):int { var a:LinkableString; a = o as LinkableString; }}", + "public class LinkableString {public function b(o:Object):int { var a:LinkableString = null; a = o as LinkableString; }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE, true); asBlockWalker.visitFunction(node); assertOut("/**\n * @export\n * @param {Object} o\n * @return {number}\n */\nfoo.bar.LinkableString.prototype.b = function(o) {\n var /** @type {foo.bar.LinkableString} */ a = null;\n a = org.apache.royale.utils.Language.as(o, foo.bar.LinkableString);\n}"); diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleStatements.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleStatements.java index e7b6695..a3f8c9f 100644 --- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleStatements.java +++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleStatements.java @@ -21,11 +21,13 @@ package org.apache.royale.compiler.internal.codegen.js.royale; import org.apache.royale.compiler.driver.IBackend; import org.apache.royale.compiler.internal.codegen.js.goog.TestGoogStatements; +import org.apache.royale.compiler.internal.driver.js.goog.JSGoogConfiguration; import org.apache.royale.compiler.internal.driver.js.royale.RoyaleBackend; import org.apache.royale.compiler.internal.projects.RoyaleJSProject; import org.apache.royale.compiler.internal.tree.as.LabeledStatementNode; import org.apache.royale.compiler.tree.as.IFileNode; import org.apache.royale.compiler.tree.as.IForLoopNode; +import org.apache.royale.compiler.tree.as.IFunctionNode; import org.apache.royale.compiler.tree.as.IIfNode; import org.apache.royale.compiler.tree.as.IImportNode; import org.apache.royale.compiler.tree.as.ILiteralNode; @@ -47,6 +49,7 @@ public class TestRoyaleStatements extends TestGoogStatements { backend = createBackend(); project = new RoyaleJSProject(workspace, backend); + project.config = new JSGoogConfiguration(); super.setUp(); } @@ -90,10 +93,10 @@ public class TestRoyaleStatements extends TestGoogStatements @Test public void testVarDeclaration_withType() { - IVariableNode node = (IVariableNode) getNode("var a:int;", - IVariableNode.class); - asBlockWalker.visitVariable(node); - assertOut("var /** @type {number} */ a = 0"); + IFunctionNode node = (IFunctionNode) getNode("var a:int;", + IFunctionNode.class); + asBlockWalker.visitFunction(node); + assertOut("RoyaleTest_A.prototype.royaleTest_a = function() {\n var /** @type {number} */ a = 0;\n //var a;\n}"); } @Test @@ -717,7 +720,8 @@ public class TestRoyaleStatements extends TestGoogStatements "RoyaleTest_A = function() {\n" + "};\n\n\n/**\n * Prevent renaming of class. Needed for reflection.\n */\ngoog.exportSymbol('RoyaleTest_A', RoyaleTest_A);\n\n\n" + "RoyaleTest_A.prototype.royaleTest_a = function() {\n" + - " var self = this;\n" + + " var self = this;\n" + + " var /** @type {number} */ len = 0;\n" + " try {\n" + " a;\n" + " } catch (e) {\n" + @@ -734,7 +738,7 @@ public class TestRoyaleStatements extends TestGoogStatements " } finally {\n" + " }\n" + " if (d) {\n" + - " var /** @type {number} */ len = 0;\n" + + " //var len;\n" + " for (var /** @type {number} */ i = 0; i < len; i++)\n" + " break;\n" + " }\n" + @@ -798,7 +802,13 @@ public class TestRoyaleStatements extends TestGoogStatements " accessors: function () {return {};},\n" + " methods: function () {return {};}\n" + "};\n" + - "};\n"); + "};\n" + + "/**\n" + + " * @export\n" + + " * @const\n" + + " * @type {number}\n" + + " */\n" + + "RoyaleTest_A.prototype.ROYALE_REFLECTION_INFO.compileFlags = 9;\n"); } @Override
