handle complex static initializers especially when the initializer is defined after the variable
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/73fd82c7 Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/73fd82c7 Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/73fd82c7 Branch: refs/heads/feature-autobuild/maven-archetypes Commit: 73fd82c7ce826857fd30d4201459c64d856ff7c7 Parents: ecd8e1c Author: Alex Harui <aha...@apache.org> Authored: Thu Oct 6 21:21:51 2016 -0700 Committer: Alex Harui <aha...@apache.org> Committed: Thu Oct 6 21:22:03 2016 -0700 ---------------------------------------------------------------------- .../codegen/js/flexjs/JSFlexJSEmitter.java | 5 ++ .../internal/codegen/js/jx/ClassEmitter.java | 19 +++++ .../internal/codegen/js/jx/FieldEmitter.java | 78 +++++++++++++++++--- .../internal/codegen/js/utils/EmitterUtils.java | 12 +++ .../codegen/js/flexjs/TestFlexJSClass.java | 9 +++ .../js/flexjs/TestFlexJSFieldMembers.java | 2 +- 6 files changed, 114 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/73fd82c7/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java index 443bbbd..a74b346 100644 --- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java +++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java @@ -293,6 +293,11 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter return bindableEmitter; } + public FieldEmitter getFieldEmitter() + { + return fieldEmitter; + } + public ClassEmitter getClassEmitter() { return classEmitter; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/73fd82c7/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/ClassEmitter.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/ClassEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/ClassEmitter.java index fe0bc7e..3b28e5f 100644 --- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/ClassEmitter.java +++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/ClassEmitter.java @@ -146,6 +146,25 @@ public class ClassEmitter extends JSSubEmitter implements fjs.getBindableEmitter().emit(definition); fjs.getAccessorEmitter().emit(definition); + if (fjs.getFieldEmitter().hasComplexStaticInitializers) + { + writeNewline(); + + for (IDefinitionNode dnode : dnodes) + { + if (dnode.getNodeID() == ASTNodeID.VariableID) + { + writeNewline(); + fjs.getFieldEmitter().emitFieldInitializer((IVariableNode) dnode); + } + else if (dnode.getNodeID() == ASTNodeID.BindableVariableID) + { + writeNewline(); + fjs.getFieldEmitter().emitFieldInitializer((IVariableNode) dnode); + } + } + } + fjs.getPackageFooterEmitter().emitClassInfo(node); getEmitter().popSourceMapName(); http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/73fd82c7/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/FieldEmitter.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/FieldEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/FieldEmitter.java index 1906b21..23459c4 100644 --- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/FieldEmitter.java +++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/FieldEmitter.java @@ -51,6 +51,8 @@ public class FieldEmitter extends JSSubEmitter implements super(emitter); } + public boolean hasComplexStaticInitializers = false; + @Override public void emit(IVariableNode node) { @@ -71,13 +73,15 @@ public class FieldEmitter extends JSSubEmitter implements IDefinition ndef = node.getDefinition(); + String className = null; String root = ""; IVariableDefinition.VariableClassification classification = node.getVariableClassification(); boolean isPackageOrFileMember = classification == IVariableDefinition.VariableClassification.PACKAGE_MEMBER || classification == IVariableDefinition.VariableClassification.FILE_MEMBER; if (isPackageOrFileMember) { - write(getEmitter().formatQualifiedName(node.getQualifiedName())); + className = getEmitter().formatQualifiedName(node.getQualifiedName()); + write(className); } else { @@ -92,7 +96,8 @@ public class FieldEmitter extends JSSubEmitter implements definition = ndef.getContainingScope().getDefinition(); startMapping(node.getNameExpressionNode()); - write(getEmitter().formatQualifiedName(definition.getQualifiedName()) + className = getEmitter().formatQualifiedName(definition.getQualifiedName()); + write(className + ASEmitterTokens.MEMBER_ACCESS.getToken() + root); write(node.getName()); endMapping(node.getNameExpressionNode()); @@ -105,15 +110,24 @@ public class FieldEmitter extends JSSubEmitter implements write("_"); } IExpressionNode vnode = node.getAssignedValueNode(); - if (vnode != null && - (ndef.isStatic() || EmitterUtils.isScalar(vnode) || isPackageOrFileMember)) + if (vnode != null) { - startMapping(node); - write(ASEmitterTokens.SPACE); - writeToken(ASEmitterTokens.EQUAL); - endMapping(node); - getEmitter().getWalker().walk(vnode); - } + String vnodeString = getEmitter().stringifyNode(vnode); + if ((ndef.isStatic() && !EmitterUtils.needsStaticInitializer(vnodeString, className)) || + (!ndef.isStatic() && EmitterUtils.isScalar(vnode)) || + isPackageOrFileMember) + { + startMapping(node); + write(ASEmitterTokens.SPACE); + writeToken(ASEmitterTokens.EQUAL); + endMapping(node); + write(vnodeString); + } + else if (ndef.isStatic() && EmitterUtils.needsStaticInitializer(vnodeString, className)) + { + hasComplexStaticInitializers = true; + } + } if (vnode == null && def != null) { String defName = def.getQualifiedName(); @@ -157,4 +171,48 @@ public class FieldEmitter extends JSSubEmitter implements } } + public void emitFieldInitializer(IVariableNode node) + { + IDefinition definition = EmitterUtils.getClassDefinition(node); + + IDefinition def = null; + IExpressionNode enode = node.getVariableTypeNode();//getAssignedValueNode(); + if (enode != null) + { + def = enode.resolveType(getProject()); + } + + IDefinition ndef = node.getDefinition(); + String className = null; + + IVariableDefinition.VariableClassification classification = node.getVariableClassification(); + boolean isPackageOrFileMember = classification == IVariableDefinition.VariableClassification.PACKAGE_MEMBER || + classification == IVariableDefinition.VariableClassification.FILE_MEMBER; + IExpressionNode vnode = node.getAssignedValueNode(); + if (vnode != null) + { + String vnodeString = getEmitter().stringifyNode(vnode); + if (definition == null) + definition = ndef.getContainingScope().getDefinition(); + className = getEmitter().formatQualifiedName(definition.getQualifiedName()); + if (ndef.isStatic() && EmitterUtils.needsStaticInitializer(vnodeString, className) && !isPackageOrFileMember) + { + write(className + + ASEmitterTokens.MEMBER_ACCESS.getToken()); + write(node.getName()); + + if (node.getNodeID() == ASTNodeID.BindableVariableID) + { + // add an underscore to convert this var to be the + // backing var for the get/set pair that will be generated later. + write("_"); + } + write(ASEmitterTokens.SPACE); + writeToken(ASEmitterTokens.EQUAL); + write(vnodeString); + write(ASEmitterTokens.SEMICOLON); + + } + } + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/73fd82c7/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/utils/EmitterUtils.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/utils/EmitterUtils.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/utils/EmitterUtils.java index 9ca2829..635c6c0 100644 --- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/utils/EmitterUtils.java +++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/utils/EmitterUtils.java @@ -464,6 +464,18 @@ public class EmitterUtils return false; } + // return true if the node is an expression that may not work + // as the initial value of a static var at + // static initialization time. Such as a function call to + // another static method in the class. + // Non-static initializers have different rules: even simple object + // and arrays need to be created for each instance, but for statics + // simple objects and arras are ok. + public static boolean needsStaticInitializer(String node, String className) + { + return node.contains(className); + } + public static IContainerNode insertArgumentsBefore(IContainerNode argumentsNode, IASNode... nodes) { int originalLength = argumentsNode.getChildCount(); http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/73fd82c7/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java index f03414d..8b91070 100644 --- a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java +++ b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java @@ -224,6 +224,15 @@ public class TestFlexJSClass extends TestGoogClass assertOut("/**\n * @constructor\n */\norg.apache.flex.A = function() {\n};\n\n\n/**\n * @export\n * @type {Object}\n */\norg.apache.flex.A.prototype.a;\n\n\n/**\n * @protected\n * @type {string}\n */\norg.apache.flex.A.prototype.b;\n\n\n/**\n * @private\n * @type {number}\n */\norg.apache.flex.A.prototype.c = 0;\n\n\n/**\n * @export\n * @type {number}\n */\norg.apache.flex.A.prototype.d = 0;\n\n\n/**\n * @export\n * @type {number}\n */\norg.apache.flex.A.prototype.e;"); } + @Test + public void testFieldsWithStaticInitializers() + { + IClassNode node = getClassNode("public class A {public static var a:int = 10;public static var b:String = initStatic(); " + + "private static function initStatic():String { return \"foo\"; }}"); + asBlockWalker.visitClass(node); + assertOut("/**\n * @constructor\n */\norg.apache.flex.A = function() {\n};\n\n\n/**\n * @export\n * @type {number}\n */\norg.apache.flex.A.a = 10;\n\n\n/**\n * @export\n * @type {string}\n */\norg.apache.flex.A.b;\n\n\n/**\n * @private\n * @return {string}\n */\norg.apache.flex.A.initStatic = function() {\n return \"foo\";\n};\n\n\norg.apache.flex.A.b = org.apache.flex.A.initStatic();"); + } + @Override @Test public void testConstants() http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/73fd82c7/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSFieldMembers.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSFieldMembers.java b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSFieldMembers.java index cee8429..dddfab6 100644 --- a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSFieldMembers.java +++ b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSFieldMembers.java @@ -185,7 +185,7 @@ public class TestFlexJSFieldMembers extends TestGoogFieldMembers IClassNode node = (IClassNode) getNode("import flash.utils.flash_proxy;use namespace flash_proxy;public static var foo:Object = initFoo(); flash_proxy static function initFoo():Object { return null; }", IClassNode.class, WRAP_LEVEL_CLASS); asBlockWalker.visitClass(node); - assertOut("/**\n * @constructor\n */\nFalconTest_A = function() {\n};\n\n\n/**\n * @export\n * @type {Object}\n */\nFalconTest_A.foo = FalconTest_A[\"http://www.adobe.com/2006/actionscript/flash/proxy::initFoo\"]();\n\n\n/**\n * @export\n * @return {Object}\n */\nFalconTest_A[\"http://www.adobe.com/2006/actionscript/flash/proxy::initFoo\"] = function() {\n return null;\n};"); + assertOut("/**\n * @constructor\n */\nFalconTest_A = function() {\n};\n\n\n/**\n * @export\n * @type {Object}\n */\nFalconTest_A.foo;\n\n\n/**\n * @export\n * @return {Object}\n */\nFalconTest_A[\"http://www.adobe.com/2006/actionscript/flash/proxy::initFoo\"] = function() {\n return null;\n};\n\nFalconTest_A.foo = FalconTest_A[\"http://www.adobe.com/2006/actionscript/flash/proxy::initFoo\"]();"); } @Test