This is an automated email from the ASF dual-hosted git repository. aharui pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/royale-compiler.git
commit e473fc65acc2266f06fa8e7f39746de1bcaedada Author: Alex Harui <aha...@apache.org> AuthorDate: Tue Nov 5 13:14:11 2019 -0800 static initializers that reference external classes are now generated as get/set to reduce issues with dependency order --- .../internal/codegen/js/jx/FieldEmitter.java | 226 ++++++++++- .../codegen/mxml/royale/TestRoyaleMXMLScript.java | 416 +++++++++++++++++++++ 2 files changed, 622 insertions(+), 20 deletions(-) diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FieldEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FieldEmitter.java index 1271863..6cf5dd2 100644 --- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FieldEmitter.java +++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FieldEmitter.java @@ -25,12 +25,14 @@ import org.apache.royale.compiler.codegen.js.goog.IJSGoogDocEmitter; import org.apache.royale.compiler.common.ASModifier; import org.apache.royale.compiler.common.ModifiersSet; import org.apache.royale.compiler.constants.IASKeywordConstants; +import org.apache.royale.compiler.constants.IASLanguageConstants; import org.apache.royale.compiler.definitions.*; import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens; import org.apache.royale.compiler.internal.codegen.js.JSEmitterTokens; import org.apache.royale.compiler.internal.codegen.js.JSSessionModel.BindableVarInfo; import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter; import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter; +import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens; import org.apache.royale.compiler.internal.codegen.js.utils.EmitterUtils; import org.apache.royale.compiler.internal.definitions.FunctionDefinition; import org.apache.royale.compiler.internal.projects.RoyaleJSProject; @@ -46,6 +48,7 @@ import org.apache.royale.compiler.tree.as.INamespaceDecorationNode; import org.apache.royale.compiler.tree.as.IVariableNode; import org.apache.royale.compiler.tree.metadata.IMetaTagNode; import org.apache.royale.compiler.tree.metadata.IMetaTagsNode; +import org.apache.royale.compiler.utils.NativeUtils; /** * Static or member variables of a class. For local variables in a function, see @@ -61,10 +64,62 @@ public class FieldEmitter extends JSSubEmitter implements public boolean hasComplexStaticInitializers = false; + private boolean isComplex(IExpressionNode vnode, IDefinition definition) + { + if (EmitterUtils.isScalar(vnode)) + return false; + + IClassDefinition cdef = (IClassDefinition)definition; + + // walk the tree of nodes looking for IdentifierNodes + // and see if they resolve to external dependencies + return isExternalReference(vnode, cdef); + } + + private boolean isExternalReference(IExpressionNode vnode, IClassDefinition cdef) + { + if (vnode.getNodeID() == ASTNodeID.IdentifierID) + { + IDefinition def = vnode.resolve(getProject()); + if (def == null) // saw this for a package reference (org in org.apache) + return false; + String qname = def.getQualifiedName(); + if (NativeUtils.isJSNative(qname)) + return false; + if (def instanceof IClassDefinition) + return !(qname.contentEquals(cdef.getQualifiedName())); + def = def.getParent(); + if (def != null) + { + qname = def.getQualifiedName(); + return !(qname.contentEquals(cdef.getQualifiedName())); + } + } + int n = vnode.getChildCount(); + for (int i = 0; i < n; i++) + { + IASNode childNode = vnode.getChild(i); + if (childNode instanceof IExpressionNode) + { + if (isExternalReference((IExpressionNode)childNode, cdef)) + return true; + } + } + return false; + } + @Override public void emit(IVariableNode node) { + IExpressionNode vnode = node.getAssignedValueNode();; + boolean isBindable = (node.getNodeID() == ASTNodeID.BindableVariableID && !node.isConst()); + IDefinition ndef = node.getDefinition(); IDefinition definition = EmitterUtils.getClassDefinition(node); + if (definition == null && ndef != null) + { + definition = ndef.getParent(); + } + boolean isComplexInitializedStatic = vnode != null && ndef.isStatic() && !isBindable && isComplex(vnode, definition); JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter(); IDefinition def = null; IExpressionNode enode = node.getVariableTypeNode();//getAssignedValueNode(); @@ -74,12 +129,11 @@ public class FieldEmitter extends JSSubEmitter implements } // TODO (mschmalle) - if (getEmitter().getDocEmitter() instanceof IJSGoogDocEmitter) + if (getEmitter().getDocEmitter() instanceof IJSGoogDocEmitter && !isComplexInitializedStatic) { ((IJSGoogDocEmitter) getEmitter().getDocEmitter()).emitFieldDoc(node, def, getProject()); } - IDefinition ndef = node.getDefinition(); String className = null; String root = ""; @@ -105,35 +159,149 @@ public class FieldEmitter extends JSSubEmitter implements startMapping(node.getNameExpressionNode()); className = getEmitter().formatQualifiedName(definition.getQualifiedName()); - write(className - + ASEmitterTokens.MEMBER_ACCESS.getToken() + root); - String qname = node.getName(); - IDefinition nodeDef = node.getDefinition(); - if (nodeDef != null && !nodeDef.isStatic() && nodeDef.isPrivate() && getProject().getAllowPrivateNameConflicts()) - qname = getEmitter().formatPrivateName(nodeDef.getParent().getQualifiedName(), qname); - - if (EmitterUtils.isCustomNamespace(node.getNamespace())) { - INamespaceDecorationNode ns = ((VariableNode) node).getNamespaceNode(); - INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getProject()); - fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names - String s = nsDef.getURI(); - write(JSRoyaleEmitter.formatNamespacedProperty(s, qname, false)); + if (isComplexInitializedStatic) + { + write(className + + ASEmitterTokens.MEMBER_ACCESS.getToken() + JSRoyaleEmitterTokens.GETTER_PREFIX.getToken()); + writeFieldName(node, fjs); + endMapping(node.getNameExpressionNode()); + write(ASEmitterTokens.SPACE); + writeToken(ASEmitterTokens.EQUAL); + write(ASEmitterTokens.FUNCTION); + write(ASEmitterTokens.PAREN_OPEN); + writeToken(ASEmitterTokens.PAREN_CLOSE); + writeNewline(ASEmitterTokens.BLOCK_OPEN, true); + String vnodeString = getEmitter().stringifyNode(vnode); + writeToken(ASEmitterTokens.VAR); + writeToken("value"); + writeToken(ASEmitterTokens.EQUAL); + write(vnodeString); + writeNewline(ASEmitterTokens.SEMICOLON); + write(IASLanguageConstants.Object); + write(ASEmitterTokens.MEMBER_ACCESS); + write(JSEmitterTokens.DEFINE_PROPERTY); + write(ASEmitterTokens.PAREN_OPEN); + write(className); + writeToken(ASEmitterTokens.COMMA); + write(ASEmitterTokens.SINGLE_QUOTE); + writeFieldName(node, fjs); + write(ASEmitterTokens.SINGLE_QUOTE); + writeToken(ASEmitterTokens.COMMA); + if (node.isConst()) + write("{ value: value, writable: false }"); + else + write("{ value: value, writable: true }"); + write(ASEmitterTokens.PAREN_CLOSE); + writeNewline(ASEmitterTokens.SEMICOLON); + writeToken(ASEmitterTokens.RETURN); + write("value"); + indentPop(); + writeNewline(ASEmitterTokens.SEMICOLON); + write(ASEmitterTokens.BLOCK_CLOSE); + writeNewline(ASEmitterTokens.SEMICOLON); + if (!node.isConst()) + { + write(className + + ASEmitterTokens.MEMBER_ACCESS.getToken() + JSRoyaleEmitterTokens.SETTER_PREFIX.getToken()); + writeFieldName(node, fjs); + write(ASEmitterTokens.SPACE); + writeToken(ASEmitterTokens.EQUAL); + write(ASEmitterTokens.FUNCTION); + write(ASEmitterTokens.PAREN_OPEN); + write("value"); + writeToken(ASEmitterTokens.PAREN_CLOSE); + writeNewline(ASEmitterTokens.BLOCK_OPEN, true); + write(IASLanguageConstants.Object); + write(ASEmitterTokens.MEMBER_ACCESS); + write(JSEmitterTokens.DEFINE_PROPERTY); + write(ASEmitterTokens.PAREN_OPEN); + write(className); + writeToken(ASEmitterTokens.COMMA); + write(ASEmitterTokens.SINGLE_QUOTE); + writeFieldName(node, fjs); + write(ASEmitterTokens.SINGLE_QUOTE); + writeToken(ASEmitterTokens.COMMA); + write("{ value: value, writable: true }"); + write(ASEmitterTokens.PAREN_CLOSE); + indentPop(); + writeNewline(ASEmitterTokens.SEMICOLON); + write(ASEmitterTokens.BLOCK_CLOSE); + writeNewline(ASEmitterTokens.SEMICOLON); + } + write(IASLanguageConstants.Object); + write(ASEmitterTokens.MEMBER_ACCESS); + write(JSEmitterTokens.DEFINE_PROPERTIES); + write(ASEmitterTokens.PAREN_OPEN); + write(className); + writeToken(ASEmitterTokens.COMMA); + write("/** @lends {" + className + + "} */ "); + writeNewline(ASEmitterTokens.BLOCK_OPEN); + // TODO (mschmalle) + if (getEmitter().getDocEmitter() instanceof IJSGoogDocEmitter) + { + ((IJSGoogDocEmitter) getEmitter().getDocEmitter()).emitFieldDoc(node, def, getProject()); + } + writeFieldName(node, fjs); + writeToken(ASEmitterTokens.COLON); + writeNewline(ASEmitterTokens.BLOCK_OPEN, true); + write(ASEmitterTokens.GET); + write(ASEmitterTokens.COLON); + write(ASEmitterTokens.SPACE); + write(className); + write(ASEmitterTokens.MEMBER_ACCESS); + write(JSRoyaleEmitterTokens.GETTER_PREFIX); + writeFieldName(node, fjs); + if (!node.isConst()) + { + writeNewline(ASEmitterTokens.COMMA); + write(ASEmitterTokens.SET); + write(ASEmitterTokens.COLON); + write(ASEmitterTokens.SPACE); + write(className); + write(ASEmitterTokens.MEMBER_ACCESS); + write(JSRoyaleEmitterTokens.SETTER_PREFIX); + writeFieldName(node, fjs); + } + writeNewline(ASEmitterTokens.COMMA); + write("configurable: true"); + write(ASEmitterTokens.BLOCK_CLOSE); + write(ASEmitterTokens.BLOCK_CLOSE); + write(ASEmitterTokens.PAREN_CLOSE); + indentPop(); + } + else + { + write(className + + ASEmitterTokens.MEMBER_ACCESS.getToken() + root); + String qname = node.getName(); + IDefinition nodeDef = node.getDefinition(); + if (nodeDef != null && !nodeDef.isStatic() && nodeDef.isPrivate() && getProject().getAllowPrivateNameConflicts()) + qname = getEmitter().formatPrivateName(nodeDef.getParent().getQualifiedName(), qname); + + if (EmitterUtils.isCustomNamespace(node.getNamespace())) { + INamespaceDecorationNode ns = ((VariableNode) node).getNamespaceNode(); + INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getProject()); + fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names + String s = nsDef.getURI(); + write(JSRoyaleEmitter.formatNamespacedProperty(s, qname, false)); + } + else write(qname); + endMapping(node.getNameExpressionNode()); } - else write(qname); - endMapping(node.getNameExpressionNode()); } - if (node.getNodeID() == ASTNodeID.BindableVariableID && !node.isConst()) + if (isBindable) { // add an underscore to convert this var to be the // backing var for the get/set pair that will be generated later. write("_"); } - IExpressionNode vnode = node.getAssignedValueNode(); - if (vnode != null) + if (vnode != null && !isComplexInitializedStatic) { getModel().inStaticInitializer = ndef.isStatic(); String vnodeString = getEmitter().stringifyNode(vnode); + /* if (ndef.isStatic() && vnode instanceof FunctionCallNode) { FunctionCallNode fcn = (FunctionCallNode)vnode; @@ -169,6 +337,7 @@ public class FieldEmitter extends JSSubEmitter implements } } } + */ getModel().inStaticInitializer = false; if ((ndef.isStatic() && !EmitterUtils.needsStaticInitializer(vnodeString, className)) || (!ndef.isStatic() && EmitterUtils.isScalar(vnode)) || @@ -297,6 +466,23 @@ public class FieldEmitter extends JSSubEmitter implements } } } + + private void writeFieldName(IVariableNode node, JSRoyaleEmitter fjs) + { + String qname = node.getName(); + IDefinition nodeDef = node.getDefinition(); + if (nodeDef != null && !nodeDef.isStatic() && nodeDef.isPrivate() && getProject().getAllowPrivateNameConflicts()) + qname = getEmitter().formatPrivateName(nodeDef.getParent().getQualifiedName(), qname); + + if (EmitterUtils.isCustomNamespace(node.getNamespace())) { + INamespaceDecorationNode ns = ((VariableNode) node).getNamespaceNode(); + INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getProject()); + fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names + String s = nsDef.getURI(); + write(JSRoyaleEmitter.formatNamespacedProperty(s, qname, false)); + } + else write(qname); + } public boolean emitFieldInitializer(IVariableNode node) { diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/mxml/royale/TestRoyaleMXMLScript.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/mxml/royale/TestRoyaleMXMLScript.java index 02b9bd9..eb5713b 100644 --- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/mxml/royale/TestRoyaleMXMLScript.java +++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/mxml/royale/TestRoyaleMXMLScript.java @@ -332,6 +332,422 @@ public class TestRoyaleMXMLScript extends RoyaleTestBase } @Test + public void testComplexExpressionStaticInitializersInScript() + { + String code = "" + "<fx:Script><![CDATA[" + + " import org.apache.royale.events.CloseEvent;" + + " public static var foo:String = CloseEvent.CLOSE;" + + "]]></fx:Script>"; + + IMXMLScriptNode node = (IMXMLScriptNode) getNode(code, + IMXMLScriptNode.class, RoyaleTestBase.WRAP_LEVEL_DOCUMENT); + + IMXMLDocumentNode dnode = (IMXMLDocumentNode) node + .getAncestorOfType(IMXMLDocumentNode.class); + ((JSRoyaleEmitter)(mxmlBlockWalker.getASEmitter())).getModel().setCurrentClass(dnode.getDefinition()); + mxmlBlockWalker.visitDocument(dnode); + String appName = dnode.getQualifiedName(); + String outTemplate = "/**\n" + + " * AppName\n" + + " *\n" + + " * @fileoverview\n" + + " *\n" + + " * @suppress {checkTypes|accessControls}\n" + + " */\n" + + "\n" + + "goog.provide('AppName');\n" + + "\n" + + "goog.require('org.apache.royale.core.Application');\n" + + "goog.require('org.apache.royale.events.CloseEvent');\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @constructor\n" + + " * @extends {org.apache.royale.core.Application}\n" + + " */\n" + + "AppName = function() {\n" + + " AppName.base(this, 'constructor');\n" + + " \n" + + " /**\n" + + " * @private\n" + + " * @type {Array}\n" + + " */\n" + + " this.mxmldd;\n" + + " \n" + + " /**\n" + + " * @private\n" + + " * @type {Array}\n" + + " */\n" + + " this.mxmldp;\n" + + "};\n" + + "goog.inherits(AppName, org.apache.royale.core.Application);\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('AppName', AppName);\n" + + "\n" + + "\n" + + "\n" + + "AppName.get__foo = function() {\n" + + " var value = org.apache.royale.events.CloseEvent.CLOSE;\n" + + " Object.defineProperty(AppName, 'foo', { value: value, writable: true });\n" + + " return value;\n" + + "};\n" + + "AppName.set__foo = function(value) {\n" + + " Object.defineProperty(AppName, 'foo', { value: value, writable: true });\n" + + "};\n" + + "Object.defineProperties(AppName, /** @lends {AppName} */ {\n" + + "/**\n" + + " * @export\n" + + " * @type {string}\n" + + " */\n" + + "foo: {\n" + + " get: AppName.get__foo,\n" + + " set: AppName.set__foo,\n" + + " configurable: true}});\n" + + "\n" + + "\n" + + "/**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "AppName.prototype.ROYALE_CLASS_INFO = { names: [{ name: 'AppName', qName: 'AppName', kind: 'class' }] };\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "AppName.prototype.ROYALE_REFLECTION_INFO = function () {\n" + + " return {\n" + + " variables: function () {\n" + + " return {\n" + + " '|foo': { type: 'String', get_set: function (/** * */ v) {return v !== undefined ? AppName.foo = v : AppName.foo;}}\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " 'AppName': { type: '', declaredBy: 'AppName'}\n" + + " };\n" + + " }\n" + + " };\n" + + "};\n" + + "\n" + + "\n" ; + + assertOutWithMetadata(outTemplate.replaceAll("AppName", appName)); + } + + @Test + public void testSimpleStaticInitializersInScript() + { + String code = "" + "<fx:Script><![CDATA[" + + " public static var foo:String = 'foo';" + + "]]></fx:Script>"; + + IMXMLScriptNode node = (IMXMLScriptNode) getNode(code, + IMXMLScriptNode.class, RoyaleTestBase.WRAP_LEVEL_DOCUMENT); + + IMXMLDocumentNode dnode = (IMXMLDocumentNode) node + .getAncestorOfType(IMXMLDocumentNode.class); + ((JSRoyaleEmitter)(mxmlBlockWalker.getASEmitter())).getModel().setCurrentClass(dnode.getDefinition()); + mxmlBlockWalker.visitDocument(dnode); + String appName = dnode.getQualifiedName(); + String outTemplate = "/**\n" + + " * AppName\n" + + " *\n" + + " * @fileoverview\n" + + " *\n" + + " * @suppress {checkTypes|accessControls}\n" + + " */\n" + + "\n" + + "goog.provide('AppName');\n" + + "\n" + + "goog.require('org.apache.royale.core.Application');\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @constructor\n" + + " * @extends {org.apache.royale.core.Application}\n" + + " */\n" + + "AppName = function() {\n" + + " AppName.base(this, 'constructor');\n" + + " \n" + + " /**\n" + + " * @private\n" + + " * @type {Array}\n" + + " */\n" + + " this.mxmldd;\n" + + " \n" + + " /**\n" + + " * @private\n" + + " * @type {Array}\n" + + " */\n" + + " this.mxmldp;\n" + + "};\n" + + "goog.inherits(AppName, org.apache.royale.core.Application);\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('AppName', AppName);\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @export\n" + + " * @type {string}\n" + + " */\n" + + "AppName.foo = 'foo';\n" + + "\n" + + "\n" + + "/**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "AppName.prototype.ROYALE_CLASS_INFO = { names: [{ name: 'AppName', qName: 'AppName', kind: 'class' }] };\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "AppName.prototype.ROYALE_REFLECTION_INFO = function () {\n" + + " return {\n" + + " variables: function () {\n" + + " return {\n" + + " '|foo': { type: 'String', get_set: function (/** * */ v) {return v !== undefined ? AppName.foo = v : AppName.foo;}}\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " 'AppName': { type: '', declaredBy: 'AppName'}\n" + + " };\n" + + " }\n" + + " };\n" + + "};\n" + + "\n" + + "\n" ; + + assertOutWithMetadata(outTemplate.replaceAll("AppName", appName)); + } + + @Test + public void testComplexStaticInitializersInScript() + { + String code = "" + "<fx:Script><![CDATA[" + + " public static var foo:Array = ['foo'];" + + "]]></fx:Script>"; + + IMXMLScriptNode node = (IMXMLScriptNode) getNode(code, + IMXMLScriptNode.class, RoyaleTestBase.WRAP_LEVEL_DOCUMENT); + + IMXMLDocumentNode dnode = (IMXMLDocumentNode) node + .getAncestorOfType(IMXMLDocumentNode.class); + ((JSRoyaleEmitter)(mxmlBlockWalker.getASEmitter())).getModel().setCurrentClass(dnode.getDefinition()); + mxmlBlockWalker.visitDocument(dnode); + String appName = dnode.getQualifiedName(); + String outTemplate = "/**\n" + + " * AppName\n" + + " *\n" + + " * @fileoverview\n" + + " *\n" + + " * @suppress {checkTypes|accessControls}\n" + + " */\n" + + "\n" + + "goog.provide('AppName');\n" + + "\n" + + "goog.require('org.apache.royale.core.Application');\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @constructor\n" + + " * @extends {org.apache.royale.core.Application}\n" + + " */\n" + + "AppName = function() {\n" + + " AppName.base(this, 'constructor');\n" + + " \n" + + " /**\n" + + " * @private\n" + + " * @type {Array}\n" + + " */\n" + + " this.mxmldd;\n" + + " \n" + + " /**\n" + + " * @private\n" + + " * @type {Array}\n" + + " */\n" + + " this.mxmldp;\n" + + "};\n" + + "goog.inherits(AppName, org.apache.royale.core.Application);\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('AppName', AppName);\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @export\n" + + " * @type {Array}\n" + + " */\n" + + "AppName.foo = ['foo'];\n" + + "\n" + + "\n" + + "/**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "AppName.prototype.ROYALE_CLASS_INFO = { names: [{ name: 'AppName', qName: 'AppName', kind: 'class' }] };\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "AppName.prototype.ROYALE_REFLECTION_INFO = function () {\n" + + " return {\n" + + " variables: function () {\n" + + " return {\n" + + " '|foo': { type: 'Array', get_set: function (/** * */ v) {return v !== undefined ? AppName.foo = v : AppName.foo;}}\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " 'AppName': { type: '', declaredBy: 'AppName'}\n" + + " };\n" + + " }\n" + + " };\n" + + "};\n" + + "\n" + + "\n" ; + + assertOutWithMetadata(outTemplate.replaceAll("AppName", appName)); + } + + @Test + public void testConstComplexExpressionStaticInitializersInScript() + { + String code = "" + "<fx:Script><![CDATA[" + + " import org.apache.royale.events.CloseEvent;" + + " public static const foo:String = CloseEvent.CLOSE;" + + "]]></fx:Script>"; + + IMXMLScriptNode node = (IMXMLScriptNode) getNode(code, + IMXMLScriptNode.class, RoyaleTestBase.WRAP_LEVEL_DOCUMENT); + + IMXMLDocumentNode dnode = (IMXMLDocumentNode) node + .getAncestorOfType(IMXMLDocumentNode.class); + ((JSRoyaleEmitter)(mxmlBlockWalker.getASEmitter())).getModel().setCurrentClass(dnode.getDefinition()); + mxmlBlockWalker.visitDocument(dnode); + String appName = dnode.getQualifiedName(); + String outTemplate = "/**\n" + + " * AppName\n" + + " *\n" + + " * @fileoverview\n" + + " *\n" + + " * @suppress {checkTypes|accessControls}\n" + + " */\n" + + "\n" + + "goog.provide('AppName');\n" + + "\n" + + "goog.require('org.apache.royale.core.Application');\n" + + "goog.require('org.apache.royale.events.CloseEvent');\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @constructor\n" + + " * @extends {org.apache.royale.core.Application}\n" + + " */\n" + + "AppName = function() {\n" + + " AppName.base(this, 'constructor');\n" + + " \n" + + " /**\n" + + " * @private\n" + + " * @type {Array}\n" + + " */\n" + + " this.mxmldd;\n" + + " \n" + + " /**\n" + + " * @private\n" + + " * @type {Array}\n" + + " */\n" + + " this.mxmldp;\n" + + "};\n" + + "goog.inherits(AppName, org.apache.royale.core.Application);\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('AppName', AppName);\n" + + "\n" + + "\n" + + "\n" + + "AppName.get__foo = function() {\n" + + " var value = org.apache.royale.events.CloseEvent.CLOSE;\n" + + " Object.defineProperty(AppName, 'foo', { value: value, writable: false });\n" + + " return value;\n" + + "};\n" + + "Object.defineProperties(AppName, /** @lends {AppName} */ {\n" + + "/**\n" + + " * @export\n" + + " * @const\n" + + " * @type {string}\n" + + " */\n" + + "foo: {\n" + + " get: AppName.get__foo,\n" + + " configurable: true}});\n" + + "\n" + + "\n" + + "/**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "AppName.prototype.ROYALE_CLASS_INFO = { names: [{ name: 'AppName', qName: 'AppName', kind: 'class' }] };\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "AppName.prototype.ROYALE_REFLECTION_INFO = function () {\n" + + " return {\n" + + " methods: function () {\n" + + " return {\n" + + " 'AppName': { type: '', declaredBy: 'AppName'}\n" + + " };\n" + + " }\n" + + " };\n" + + "};\n" + + "\n" + + "\n" ; + + assertOutWithMetadata(outTemplate.replaceAll("AppName", appName)); + } + + @Test public void testComplexCustomNamespaceInitializersInScript() { String code = "" + "<fx:Script><![CDATA["