You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by ah...@apache.org on 2019/11/05 21:53:26 UTC
[royale-compiler] 02/03: static initializers that reference
external classes are now generated as get/set to reduce issues with
dependency order
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 <ah...@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["