You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by jo...@apache.org on 2023/12/04 23:53:49 UTC
(royale-compiler) 02/02: AccessorEmitter: extract some more code into smaller methods
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 6b7f16670b61faf84877491600cbdda398d6ca01
Author: Josh Tynjala <jo...@apache.org>
AuthorDate: Mon Dec 4 15:50:37 2023 -0800
AccessorEmitter: extract some more code into smaller methods
---
.../internal/codegen/js/jx/AccessorEmitter.java | 800 +++++++++++----------
1 file changed, 428 insertions(+), 372 deletions(-)
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java
index d84cf8f19..78b369158 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java
@@ -98,7 +98,7 @@ public class AccessorEmitter extends JSSubEmitter implements
}
if (!getModel().getStaticPropertyMap().isEmpty() && !getModel().isExterns)
{
- writeStaticDefinePropreties(definition);
+ writeStaticDefineProperties(definition);
}
}
@@ -298,193 +298,40 @@ public class AccessorEmitter extends JSSubEmitter implements
private void writeProperties(IClassDefinition definition, boolean emitExports)
{
- JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
- String qname = definition.getQualifiedName();
Set<String> propertyNames = getModel().getPropertyMap().keySet();
for (String propName : propertyNames)
{
PropertyNodes p = getModel().getPropertyMap().get(propName);
- IGetterNode getterNode = p.getter;
- ISetterNode setterNode = p.setter;
- String baseName = p.name;
if (getModel().isExterns)
{
- IAccessorNode node = (getterNode != null) ? getterNode : setterNode;
- writeNewline();
- writeNewline();
- writeNewline();
- writeNewline("/**");
- if (emitExports)
- writeNewline(" * @export");
- if (p.type != null)
- writeNewline(" * @type {"+ JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "}");
- writeNewline(" */");
- write(getEmitter().formatQualifiedName(qname));
- write(ASEmitterTokens.MEMBER_ACCESS);
- write(JSEmitterTokens.PROTOTYPE);
- if (p.uri != null)
- {
- INamespaceDecorationNode ns = ((FunctionNode)node).getActualNamespaceNode();
- INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
- fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
- write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, baseName, true));
- }
- else
- {
- write(ASEmitterTokens.MEMBER_ACCESS);
- write(baseName);
- }
- write(ASEmitterTokens.SEMICOLON);
+ writeExternPropertyNodes(p, definition, emitExports);
}
else
{
- IAccessorNode accessorNode = (getterNode != null) ? getterNode : setterNode;
- if(!accessorNode.getDefinition().isOverride())
- {
- // start by writing out the instance accessors as regular variables
- // because Closure Compiler doesn't properly analyze calls to
- // defineProperties() alone.
- // since there's no analysis, Closure assumes that getters/setters
- // have no side effects, which results in important get/set calls
- // being removed as dead code.
- // defining the accessors as variables first convinces Closure to
- // handle them more intelligently while not preventing them from
- // being real accessors.
- // Source: https://developers.google.com/closure/compiler/docs/limitations
- writeNewline();
- writeNewline();
- writeNewline();
- writeNewline("/**");
- if (p.preventRename)
- writeNewline(" * @nocollapse");
- if (p.resolvedExport && !p.suppressExport)
- writeNewline(" * @export");
- if (p.type != null)
- writeNewline(" * @type {" + JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "}");
- writeNewline(" */");
- write(getEmitter().formatQualifiedName(qname));
- write(ASEmitterTokens.MEMBER_ACCESS);
- write(JSEmitterTokens.PROTOTYPE);
- write(ASEmitterTokens.MEMBER_ACCESS);
- if (p.uri != null)
- {
- INamespaceDecorationNode ns = ((FunctionNode) accessorNode).getActualNamespaceNode();
- INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
- fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
- write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, baseName, false));
- }
- else
- write(baseName);
- write(ASEmitterTokens.SEMICOLON);
- }
-
- if (getterNode != null)
- {
- writeGetterNode(p, definition);
- }
- if (setterNode != null)
- {
- writeSetterNode(p, definition);
- }
+ writePropertyNodes(p, definition);
}
}
}
private void writeStaticProperties(IClassDefinition definition, boolean emitExports)
{
- JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
- String qname = definition.getQualifiedName();
Set<String> propertyNames = getModel().getStaticPropertyMap().keySet();
for (String propName : propertyNames)
{
PropertyNodes p = getModel().getStaticPropertyMap().get(propName);
- IGetterNode getterNode = p.getter;
- ISetterNode setterNode = p.setter;
- String baseName = p.name;
if (getModel().isExterns)
{
- IAccessorNode node = (getterNode != null) ? getterNode : setterNode;
- writeNewline();
- writeNewline();
- writeNewline();
- writeNewline("/**");
- if (emitExports)
- writeNewline(" * @export");
- if (p.type != null)
- writeNewline(" * @type {" + JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "}");
- writeNewline(" */");
- write(getEmitter().formatQualifiedName(qname));
- if (p.uri != null)
- {
- INamespaceDecorationNode ns = ((FunctionNode)node).getActualNamespaceNode();
- INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
- fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
- write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, baseName, true));
- }
- else
- {
- write(ASEmitterTokens.MEMBER_ACCESS);
- write(baseName);
- }
- write(ASEmitterTokens.SEMICOLON);
+ writeExternPropertyNodesStatic(p, definition, emitExports);
}
else
{
- // start by writing out the static accessors as regular variables
- // because Closure Compiler doesn't properly analyze calls to
- // defineProperties() alone.
- // since there's no analysis, Closure assumes that getters/setters
- // have no side effects, which results in important get/set calls
- // being removed as dead code.
- // defining the accessors as variables first convinces Closure to
- // handle them more intelligently while not preventing them from
- // being real accessors.
- // Source: https://developers.google.com/closure/compiler/docs/limitations
- writeNewline();
- writeNewline();
- writeNewline();
- writeNewline("/**");
- // like instance accessors, we should have if (p.preventRename)
- // here, but while Closure compiler seems to properly handle
- // renaming of instance accessors, it fails when we try the same
- // trick with static accessors, unless there's a nocollapse.
- // when we allow renaming, we don't want to break anything that
- // isn't dynamic access, so we always need nocollapse here.
- writeNewline(" * @nocollapse");
- if (p.resolvedExport && !p.suppressExport)
- writeNewline(" * @export");
- if (p.type != null)
- writeNewline(" * @type {" + JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "}");
- writeNewline(" */");
- write(getEmitter().formatQualifiedName(qname));
- write(ASEmitterTokens.MEMBER_ACCESS);
- if (p.uri != null)
- {
- IAccessorNode node = (getterNode != null) ? getterNode : setterNode;
- INamespaceDecorationNode ns = ((FunctionNode)node).getActualNamespaceNode();
- INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
- fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
- write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, baseName, false));
- }
- else
- write(baseName);
- write(ASEmitterTokens.SEMICOLON);
-
- if (getterNode != null)
- {
- writeStaticGetterNode(p, definition);
- }
- if (setterNode != null)
- {
- writeStaticSetterNode(p, definition);
- }
+ writePropertyNodesStatic(p, definition);
}
}
}
private void writeDefineProperties(IClassDefinition definition)
{
- JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
writeNewline();
writeNewline();
writeNewline();
@@ -511,160 +358,16 @@ public class AccessorEmitter extends JSSubEmitter implements
else
writeNewline(ASEmitterTokens.COMMA);
- boolean wroteGetter = false;
PropertyNodes p = getModel().getPropertyMap().get(propName);
- String baseName = p.name;
- IGetterNode getterNode = p.getter;
- ISetterNode setterNode = p.setter;
- writeNewline("/**");
- if (p.type != null)
- {
- String typeName = p.type.getBaseName();
- if (getModel().isInternalClass(typeName))
- typeName = getModel().getInternalClasses().get(typeName);
- writeNewline(" * @type {" + JSRoyaleDocEmitter.convertASTypeToJSType(typeName, p.type.getPackageName()) + "}");
- }
- writeNewline(" */");
- FunctionNode fnNode = getterNode != null ? (FunctionNode) getterNode : (FunctionNode) setterNode;
- if (p.uri != null)
- {
- INamespaceDecorationNode ns = fnNode.getActualNamespaceNode();
- INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
- fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
- //String s = nsDef.getURI();
- write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, baseName, false));
- }
- else
- write(baseName);
- write(ASEmitterTokens.COLON);
- write(ASEmitterTokens.SPACE);
- write(ASEmitterTokens.BLOCK_OPEN);
- writeNewline();
- if (getterNode != null)
- {
- write(ASEmitterTokens.GET);
- write(ASEmitterTokens.COLON);
- write(ASEmitterTokens.SPACE);
- write(getEmitter().formatQualifiedName(qname));
- write(ASEmitterTokens.MEMBER_ACCESS);
- write(JSEmitterTokens.PROTOTYPE);
- if (p.uri != null)
- {
- INamespaceDecorationNode ns = ((FunctionNode)getterNode).getActualNamespaceNode();
- INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
- fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
- //String s = nsDef.getURI();
- write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, fjs.formatGetter(baseName), true));
- }
- else
- {
- write(ASEmitterTokens.MEMBER_ACCESS);
- write(fjs.formatGetter(baseName));
- }
- wroteGetter = true;
- }
- else if (setterNode != null /* && setterNode.getDefinition().isOverride()*/)
- {
- // see if there is a getter on a base class. If so, we have to
- // generate a call to the super from this class because
- // Object.defineProperty doesn't allow overriding just the setter.
- // If there is no getter defineProp'd the property will seen as
- // write-only.
- IAccessorDefinition other = (IAccessorDefinition)SemanticUtils.resolveCorrespondingAccessor(p.setter.getDefinition(), getProject());
- if (other != null)
- {
- write(ASEmitterTokens.GET);
- write(ASEmitterTokens.COLON);
- write(ASEmitterTokens.SPACE);
-
- write(getEmitter().formatQualifiedName(other.getParent().getQualifiedName()));
- write(ASEmitterTokens.MEMBER_ACCESS);
- write(JSEmitterTokens.PROTOTYPE);
- if (p.uri != null)
- {
- INamespaceDecorationNode ns = ((FunctionNode)setterNode).getActualNamespaceNode();
- INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
- fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
- //String s = nsDef.getURI();
- write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, fjs.formatGetter(baseName), true));
- }
- else
- {
- write(ASEmitterTokens.MEMBER_ACCESS);
- write(fjs.formatGetter(baseName));
- }
- wroteGetter = true;
- }
- }
- if (setterNode != null)
- {
- if (wroteGetter)
- writeNewline(ASEmitterTokens.COMMA);
-
- write(ASEmitterTokens.SET);
- write(ASEmitterTokens.COLON);
- write(ASEmitterTokens.SPACE);
- write(getEmitter().formatQualifiedName(qname));
- write(ASEmitterTokens.MEMBER_ACCESS);
- write(JSEmitterTokens.PROTOTYPE);
- if (p.uri != null)
- {
- INamespaceDecorationNode ns = ((FunctionNode)setterNode).getActualNamespaceNode();
- INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
- fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
- //String s = nsDef.getURI();
- write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, fjs.formatSetter(baseName), true));
- }
- else
- {
- write(ASEmitterTokens.MEMBER_ACCESS);
- write(fjs.formatSetter(baseName));
- }
- }
- else if (getterNode != null/* && getterNode.getDefinition().isOverride()*/)
- {
- // see if there is a getter on a base class. If so, we have to
- // generate a call to the super from this class because
- // Object.defineProperty doesn't allow overriding just the getter.
- // If there is no setter defineProp'd the property will seen as
- // read-only.
- IAccessorDefinition other = (IAccessorDefinition)SemanticUtils.resolveCorrespondingAccessor(p.getter.getDefinition(), getProject());
- if (other != null)
- {
- if (wroteGetter)
- writeNewline(ASEmitterTokens.COMMA);
-
- write(ASEmitterTokens.SET);
- write(ASEmitterTokens.COLON);
- write(ASEmitterTokens.SPACE);
- write(getEmitter().formatQualifiedName(other.getParent().getQualifiedName()));
- write(ASEmitterTokens.MEMBER_ACCESS);
- write(JSEmitterTokens.PROTOTYPE);
- if (p.uri != null)
- {
- INamespaceDecorationNode ns = ((FunctionNode)getterNode).getActualNamespaceNode();
- INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
- fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
- //String s = nsDef.getURI();
- write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, fjs.formatSetter(baseName), true));
- }
- else
- {
- write(ASEmitterTokens.MEMBER_ACCESS);
- write(fjs.formatSetter(baseName));
- }
- }
- }
- write(ASEmitterTokens.BLOCK_CLOSE);
+ writeDefinePropertyNodes(p, definition);
}
writeNewline(ASEmitterTokens.BLOCK_CLOSE);
write(ASEmitterTokens.PAREN_CLOSE);
write(ASEmitterTokens.SEMICOLON);
}
- private void writeStaticDefinePropreties(IClassDefinition definition) {
- JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
-
+ private void writeStaticDefineProperties(IClassDefinition definition)
+ {
writeNewline();
writeNewline();
writeNewline();
@@ -692,79 +395,15 @@ public class AccessorEmitter extends JSSubEmitter implements
PropertyNodes p = getModel().getStaticPropertyMap().get(
propName);
- IGetterNode getterNode = p.getter;
- ISetterNode setterNode = p.setter;
- String baseName = p.name;
- writeNewline("/**");
- if (p.type != null)
- writeNewline(" * @type {" + JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "}");
- writeNewline(" */");
- FunctionNode fnNode = getterNode != null ? (FunctionNode) getterNode : (FunctionNode) setterNode;
- if (p.uri != null)
- {
- INamespaceDecorationNode ns = fnNode.getActualNamespaceNode();
- INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
- fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
- //String s = nsDef.getURI();
- write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, baseName, false));
- }
- else
- write(baseName);
- write(ASEmitterTokens.COLON);
- write(ASEmitterTokens.SPACE);
- write(ASEmitterTokens.BLOCK_OPEN);
- writeNewline();
- if (getterNode != null)
- {
- write(ASEmitterTokens.GET);
- write(ASEmitterTokens.COLON);
- write(ASEmitterTokens.SPACE);
- write(getEmitter().formatQualifiedName(qname));
- if (p.uri != null)
- {
- INamespaceDecorationNode ns = ((FunctionNode)getterNode).getActualNamespaceNode();
- INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
- fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
- //String s = nsDef.getURI();
- write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, fjs.formatGetter(baseName), true));
- }
- else
- {
- write(ASEmitterTokens.MEMBER_ACCESS);
- write(fjs.formatGetter(baseName));
- }
- }
- if (setterNode != null)
- {
- if (p.getter != null)
- writeNewline(ASEmitterTokens.COMMA);
-
- write(ASEmitterTokens.SET);
- write(ASEmitterTokens.COLON);
- write(ASEmitterTokens.SPACE);
- write(getEmitter().formatQualifiedName(qname));
- if (p.uri != null)
- {
- INamespaceDecorationNode ns = ((FunctionNode)setterNode).getActualNamespaceNode();
- INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
- fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
- //String s = nsDef.getURI();
- write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, fjs.formatSetter(baseName), true));
- }
- else
- {
- write(ASEmitterTokens.MEMBER_ACCESS);
- write(fjs.formatSetter(baseName));
- }
- }
- write(ASEmitterTokens.BLOCK_CLOSE);
+ writeDefinePropertyNodesStatic(p, definition);
}
writeNewline(ASEmitterTokens.BLOCK_CLOSE);
write(ASEmitterTokens.PAREN_CLOSE);
write(ASEmitterTokens.SEMICOLON);
}
- private void writeGetterNode(PropertyNodes p, IClassDefinition definition) {
+ private void writeGetterNode(PropertyNodes p, IClassDefinition definition)
+ {
JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
String qname = definition.getQualifiedName();
String baseName = p.name;
@@ -988,4 +627,421 @@ public class AccessorEmitter extends JSSubEmitter implements
write(ASEmitterTokens.SEMICOLON);
}
+
+ private void writePropertyNodes(PropertyNodes p, IClassDefinition definition)
+ {
+ JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
+
+ IGetterNode getterNode = p.getter;
+ ISetterNode setterNode = p.setter;
+ String baseName = p.name;
+ String qname = definition.getQualifiedName();
+
+ IAccessorNode accessorNode = (getterNode != null) ? getterNode : setterNode;
+ if(!accessorNode.getDefinition().isOverride())
+ {
+ // start by writing out the instance accessors as regular variables
+ // because Closure Compiler doesn't properly analyze calls to
+ // defineProperties() alone.
+ // since there's no analysis, Closure assumes that getters/setters
+ // have no side effects, which results in important get/set calls
+ // being removed as dead code.
+ // defining the accessors as variables first convinces Closure to
+ // handle them more intelligently while not preventing them from
+ // being real accessors.
+ // Source: https://developers.google.com/closure/compiler/docs/limitations
+ writeNewline();
+ writeNewline();
+ writeNewline();
+ writeNewline("/**");
+ if (p.preventRename)
+ writeNewline(" * @nocollapse");
+ if (p.resolvedExport && !p.suppressExport)
+ writeNewline(" * @export");
+ if (p.type != null)
+ writeNewline(" * @type {" + JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "}");
+ writeNewline(" */");
+ write(getEmitter().formatQualifiedName(qname));
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(JSEmitterTokens.PROTOTYPE);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ if (p.uri != null)
+ {
+ INamespaceDecorationNode ns = ((FunctionNode) accessorNode).getActualNamespaceNode();
+ INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
+ fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
+ write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, baseName, false));
+ }
+ else
+ write(baseName);
+ write(ASEmitterTokens.SEMICOLON);
+ }
+
+ if (getterNode != null)
+ {
+ writeGetterNode(p, definition);
+ }
+ if (setterNode != null)
+ {
+ writeSetterNode(p, definition);
+ }
+ }
+
+ private void writeExternPropertyNodes(PropertyNodes p, IClassDefinition definition, boolean emitExports)
+ {
+ JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
+
+ IGetterNode getterNode = p.getter;
+ ISetterNode setterNode = p.setter;
+ String baseName = p.name;
+ String qname = definition.getQualifiedName();
+
+ IAccessorNode node = (getterNode != null) ? getterNode : setterNode;
+ writeNewline();
+ writeNewline();
+ writeNewline();
+ writeNewline("/**");
+ if (emitExports)
+ writeNewline(" * @export");
+ if (p.type != null)
+ writeNewline(" * @type {"+ JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "}");
+ writeNewline(" */");
+ write(getEmitter().formatQualifiedName(qname));
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(JSEmitterTokens.PROTOTYPE);
+ if (p.uri != null)
+ {
+ INamespaceDecorationNode ns = ((FunctionNode)node).getActualNamespaceNode();
+ INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
+ fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
+ write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, baseName, true));
+ }
+ else
+ {
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(baseName);
+ }
+ write(ASEmitterTokens.SEMICOLON);
+ }
+
+ private void writePropertyNodesStatic(PropertyNodes p, IClassDefinition definition)
+ {
+ JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
+
+ IGetterNode getterNode = p.getter;
+ ISetterNode setterNode = p.setter;
+ String baseName = p.name;
+ String qname = definition.getQualifiedName();
+
+ // start by writing out the static accessors as regular variables
+ // because Closure Compiler doesn't properly analyze calls to
+ // defineProperties() alone.
+ // since there's no analysis, Closure assumes that getters/setters
+ // have no side effects, which results in important get/set calls
+ // being removed as dead code.
+ // defining the accessors as variables first convinces Closure to
+ // handle them more intelligently while not preventing them from
+ // being real accessors.
+ // Source: https://developers.google.com/closure/compiler/docs/limitations
+ writeNewline();
+ writeNewline();
+ writeNewline();
+ writeNewline("/**");
+ // like instance accessors, we should have if (p.preventRename)
+ // here, but while Closure compiler seems to properly handle
+ // renaming of instance accessors, it fails when we try the same
+ // trick with static accessors, unless there's a nocollapse.
+ // when we allow renaming, we don't want to break anything that
+ // isn't dynamic access, so we always need nocollapse here.
+ writeNewline(" * @nocollapse");
+ if (p.resolvedExport && !p.suppressExport)
+ writeNewline(" * @export");
+ if (p.type != null)
+ writeNewline(" * @type {" + JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "}");
+ writeNewline(" */");
+ write(getEmitter().formatQualifiedName(qname));
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ if (p.uri != null)
+ {
+ IAccessorNode node = (getterNode != null) ? getterNode : setterNode;
+ INamespaceDecorationNode ns = ((FunctionNode)node).getActualNamespaceNode();
+ INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
+ fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
+ write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, baseName, false));
+ }
+ else
+ write(baseName);
+ write(ASEmitterTokens.SEMICOLON);
+
+ if (getterNode != null)
+ {
+ writeStaticGetterNode(p, definition);
+ }
+ if (setterNode != null)
+ {
+ writeStaticSetterNode(p, definition);
+ }
+ }
+
+ private void writeExternPropertyNodesStatic(PropertyNodes p, IClassDefinition definition, boolean emitExports)
+ {
+ JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
+
+ IGetterNode getterNode = p.getter;
+ ISetterNode setterNode = p.setter;
+ String baseName = p.name;
+ String qname = definition.getQualifiedName();
+
+ IAccessorNode node = (getterNode != null) ? getterNode : setterNode;
+ writeNewline();
+ writeNewline();
+ writeNewline();
+ writeNewline("/**");
+ if (emitExports)
+ writeNewline(" * @export");
+ if (p.type != null)
+ writeNewline(" * @type {" + JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "}");
+ writeNewline(" */");
+ write(getEmitter().formatQualifiedName(qname));
+ if (p.uri != null)
+ {
+ INamespaceDecorationNode ns = ((FunctionNode)node).getActualNamespaceNode();
+ INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
+ fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
+ write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, baseName, true));
+ }
+ else
+ {
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(baseName);
+ }
+ write(ASEmitterTokens.SEMICOLON);
+ }
+
+ private void writeDefinePropertyNodes(PropertyNodes p, IClassDefinition definition)
+ {
+ JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
+
+ String baseName = p.name;
+ IGetterNode getterNode = p.getter;
+ ISetterNode setterNode = p.setter;
+ String qname = definition.getQualifiedName();
+
+ boolean wroteGetter = false;
+
+ writeNewline("/**");
+ if (p.type != null)
+ {
+ String typeName = p.type.getBaseName();
+ if (getModel().isInternalClass(typeName))
+ typeName = getModel().getInternalClasses().get(typeName);
+ writeNewline(" * @type {" + JSRoyaleDocEmitter.convertASTypeToJSType(typeName, p.type.getPackageName()) + "}");
+ }
+ writeNewline(" */");
+ FunctionNode fnNode = getterNode != null ? (FunctionNode) getterNode : (FunctionNode) setterNode;
+ if (p.uri != null)
+ {
+ INamespaceDecorationNode ns = fnNode.getActualNamespaceNode();
+ INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
+ fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
+ //String s = nsDef.getURI();
+ write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, baseName, false));
+ }
+ else
+ write(baseName);
+ write(ASEmitterTokens.COLON);
+ write(ASEmitterTokens.SPACE);
+ write(ASEmitterTokens.BLOCK_OPEN);
+ writeNewline();
+ if (getterNode != null)
+ {
+ write(ASEmitterTokens.GET);
+ write(ASEmitterTokens.COLON);
+ write(ASEmitterTokens.SPACE);
+ write(getEmitter().formatQualifiedName(qname));
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(JSEmitterTokens.PROTOTYPE);
+ if (p.uri != null)
+ {
+ INamespaceDecorationNode ns = ((FunctionNode)getterNode).getActualNamespaceNode();
+ INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
+ fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
+ //String s = nsDef.getURI();
+ write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, fjs.formatGetter(baseName), true));
+ }
+ else
+ {
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(fjs.formatGetter(baseName));
+ }
+ wroteGetter = true;
+ }
+ else if (setterNode != null /* && setterNode.getDefinition().isOverride()*/)
+ {
+ // see if there is a getter on a base class. If so, we have to
+ // generate a call to the super from this class because
+ // Object.defineProperty doesn't allow overriding just the setter.
+ // If there is no getter defineProp'd the property will seen as
+ // write-only.
+ IAccessorDefinition other = (IAccessorDefinition)SemanticUtils.resolveCorrespondingAccessor(p.setter.getDefinition(), getProject());
+ if (other != null)
+ {
+ write(ASEmitterTokens.GET);
+ write(ASEmitterTokens.COLON);
+ write(ASEmitterTokens.SPACE);
+
+ write(getEmitter().formatQualifiedName(other.getParent().getQualifiedName()));
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(JSEmitterTokens.PROTOTYPE);
+ if (p.uri != null)
+ {
+ INamespaceDecorationNode ns = ((FunctionNode)setterNode).getActualNamespaceNode();
+ INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
+ fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
+ //String s = nsDef.getURI();
+ write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, fjs.formatGetter(baseName), true));
+ }
+ else
+ {
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(fjs.formatGetter(baseName));
+ }
+ wroteGetter = true;
+ }
+ }
+ if (setterNode != null)
+ {
+ if (wroteGetter)
+ writeNewline(ASEmitterTokens.COMMA);
+
+ write(ASEmitterTokens.SET);
+ write(ASEmitterTokens.COLON);
+ write(ASEmitterTokens.SPACE);
+ write(getEmitter().formatQualifiedName(qname));
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(JSEmitterTokens.PROTOTYPE);
+ if (p.uri != null)
+ {
+ INamespaceDecorationNode ns = ((FunctionNode)setterNode).getActualNamespaceNode();
+ INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
+ fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
+ //String s = nsDef.getURI();
+ write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, fjs.formatSetter(baseName), true));
+ }
+ else
+ {
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(fjs.formatSetter(baseName));
+ }
+ }
+ else if (getterNode != null/* && getterNode.getDefinition().isOverride()*/)
+ {
+ // see if there is a getter on a base class. If so, we have to
+ // generate a call to the super from this class because
+ // Object.defineProperty doesn't allow overriding just the getter.
+ // If there is no setter defineProp'd the property will seen as
+ // read-only.
+ IAccessorDefinition other = (IAccessorDefinition)SemanticUtils.resolveCorrespondingAccessor(p.getter.getDefinition(), getProject());
+ if (other != null)
+ {
+ if (wroteGetter)
+ writeNewline(ASEmitterTokens.COMMA);
+
+ write(ASEmitterTokens.SET);
+ write(ASEmitterTokens.COLON);
+ write(ASEmitterTokens.SPACE);
+ write(getEmitter().formatQualifiedName(other.getParent().getQualifiedName()));
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(JSEmitterTokens.PROTOTYPE);
+ if (p.uri != null)
+ {
+ INamespaceDecorationNode ns = ((FunctionNode)getterNode).getActualNamespaceNode();
+ INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
+ fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
+ //String s = nsDef.getURI();
+ write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, fjs.formatSetter(baseName), true));
+ }
+ else
+ {
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(fjs.formatSetter(baseName));
+ }
+ }
+ }
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ }
+
+ private void writeDefinePropertyNodesStatic(PropertyNodes p, IClassDefinition definition)
+ {
+ JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
+
+ IGetterNode getterNode = p.getter;
+ ISetterNode setterNode = p.setter;
+ String baseName = p.name;
+ String qname = definition.getQualifiedName();
+
+ writeNewline("/**");
+ if (p.type != null)
+ writeNewline(" * @type {" + JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), p.type.getPackageName()) + "}");
+ writeNewline(" */");
+ FunctionNode fnNode = getterNode != null ? (FunctionNode) getterNode : (FunctionNode) setterNode;
+ if (p.uri != null)
+ {
+ INamespaceDecorationNode ns = fnNode.getActualNamespaceNode();
+ INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
+ fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
+ //String s = nsDef.getURI();
+ write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, baseName, false));
+ }
+ else
+ write(baseName);
+ write(ASEmitterTokens.COLON);
+ write(ASEmitterTokens.SPACE);
+ write(ASEmitterTokens.BLOCK_OPEN);
+ writeNewline();
+ if (getterNode != null)
+ {
+ write(ASEmitterTokens.GET);
+ write(ASEmitterTokens.COLON);
+ write(ASEmitterTokens.SPACE);
+ write(getEmitter().formatQualifiedName(qname));
+ if (p.uri != null)
+ {
+ INamespaceDecorationNode ns = ((FunctionNode)getterNode).getActualNamespaceNode();
+ INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
+ fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
+ //String s = nsDef.getURI();
+ write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, fjs.formatGetter(baseName), true));
+ }
+ else
+ {
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(fjs.formatGetter(baseName));
+ }
+ }
+ if (setterNode != null)
+ {
+ if (p.getter != null)
+ writeNewline(ASEmitterTokens.COMMA);
+
+ write(ASEmitterTokens.SET);
+ write(ASEmitterTokens.COLON);
+ write(ASEmitterTokens.SPACE);
+ write(getEmitter().formatQualifiedName(qname));
+ if (p.uri != null)
+ {
+ INamespaceDecorationNode ns = ((FunctionNode)setterNode).getActualNamespaceNode();
+ INamespaceDefinition nsDef = (INamespaceDefinition)ns.resolve(getWalker().getProject());
+ fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
+ //String s = nsDef.getURI();
+ write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, fjs.formatSetter(baseName), true));
+ }
+ else
+ {
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(fjs.formatSetter(baseName));
+ }
+ }
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ }
}