in compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/FieldEmitter.java [110:319]
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();
if (enode != null)
{
def = enode.resolveType(getProject());
}
IExpressionNode nameNode = node.getNameExpressionNode();
// TODO (mschmalle)
if (getEmitter().getDocEmitter() instanceof IJSRoyaleDocEmitter && !isComplexInitializedStatic)
{
((IJSRoyaleDocEmitter) getEmitter().getDocEmitter()).emitFieldDoc(node, def, getProject());
}
String className = null;
String root = "";
IVariableDefinition.VariableClassification classification = node.getVariableClassification();
boolean isPackageOrFileMember = classification == IVariableDefinition.VariableClassification.PACKAGE_MEMBER ||
classification == IVariableDefinition.VariableClassification.FILE_MEMBER;
if (isPackageOrFileMember)
{
String qualifiedName = node.getQualifiedName();
if (fjs.getModel().isExterns && node.getName().equals(qualifiedName))
{
writeToken(ASEmitterTokens.VAR);
}
write(fjs.formatQualifiedName(qualifiedName));
}
else
{
ModifiersSet modifierSet = ndef.getModifiers();
if (modifierSet != null && !modifierSet.hasModifier(ASModifier.STATIC))
{
root = JSEmitterTokens.PROTOTYPE.getToken();
root += ASEmitterTokens.MEMBER_ACCESS.getToken();
}
if (definition == null)
definition = ndef.getContainingScope().getDefinition();
className = getEmitter().formatQualifiedName(definition.getQualifiedName());
if (isComplexInitializedStatic)
{
emitComplexInitializedStatic(node, className, def);
}
else
{
startMapping(nameNode);
write(className);
write(ASEmitterTokens.MEMBER_ACCESS.getToken());
write(root);
endMapping(nameNode);
String nodeName = node.getName();
String qname = nodeName;
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();
startMapping(nameNode, node.getName());
write(JSRoyaleEmitter.formatNamespacedProperty(s, qname, false));
endMapping(nameNode);
}
else
{
String symbolName = null;
if (!qname.equals(nodeName))
{
symbolName = nodeName;
}
startMapping(nameNode, symbolName);
write(qname);
endMapping(nameNode);
}
}
}
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("_");
}
if (vnode != null && !isComplexInitializedStatic)
{
getModel().inStaticInitializer = ndef.isStatic() || isPackageOrFileMember;
String vnodeString = getEmitter().stringifyNode(vnode);
if (ndef.isStatic() && vnode instanceof FunctionCallNode)
{
FunctionCallNode fcn = (FunctionCallNode)vnode;
if (fcn.getNameNode() instanceof IdentifierNode)
{
IDefinition d = fcn.getNameNode().resolve(getProject());
// assume this is a call to static method in the class
// otherwise it would be a memberaccessexpression?
if (d instanceof FunctionDefinition)
{
FunctionDefinition fd = (FunctionDefinition)d;
IASNode m = fd.getNode();
if (m != null)
{
// re-emit it to collect static initializer class references in usedNames
getEmitter().stringifyNode(m);
}
}
//it could also be a constructor
else if (d instanceof IClassDefinition)
{
IClassDefinition classDef = (IClassDefinition) d;
IFunctionDefinition constructorDef = classDef.getConstructor();
if (constructorDef != null)
{
IASNode m = constructorDef.getNode();
if (m != null)
{
// re-emit it to collect static initializer class references in usedNames
getEmitter().stringifyNode(m);
}
}
}
}
}
getModel().inStaticInitializer = false;
if ((ndef.isStatic() && !EmitterUtils.needsStaticInitializer(vnodeString, className)) ||
(!ndef.isStatic() && EmitterUtils.isScalar(vnode)) ||
isPackageOrFileMember)
{
IExpressionNode beforeNode = enode;
if (beforeNode.getAbsoluteStart() == -1)
{
beforeNode = nameNode;
}
startMapping(node, beforeNode);
write(ASEmitterTokens.SPACE);
writeToken(ASEmitterTokens.EQUAL);
endMapping(node);
getEmitter().emitAssignmentCoercion(vnode, node.getVariableTypeNode().resolve(getProject()));
}
else if (ndef.isStatic() && EmitterUtils.needsStaticInitializer(vnodeString, className))
{
hasComplexStaticInitializers = true;
}
if (!isPackageOrFileMember && !ndef.isStatic() && !EmitterUtils.isScalar(vnode)
&& getProject() instanceof RoyaleJSProject
&& ((RoyaleJSProject) getProject()).config != null
&& ((RoyaleJSProject) getProject()).config.getJsDefaultInitializers()
)
{
//this value will actually be initialized inside the constructor.
//but if default initializers is set, we define it on the prototype with null value first.
//Why?: this needs to be defined on the prototype to support reflection
//otherwise the constructor initializers will create the new property value on 'this' and
//there is no runtime clue to separate what is 'dynamic' and what is 'inherited'
//these clues throughout the prototype chain are important for runtime identification
//of dynamic fields.
//runtime checks will only work accurately using this technique if the entire inheritance chain
//for the reflection target is compiled with default js initializers, because it permits
//inspection of the prototype chain to determine all the sealed members, and isolate them
//from whatever else is defined as 'own' properties on the instance (which can be assumed to be
// 'dynamic' properties).
write(ASEmitterTokens.SPACE);
writeToken(ASEmitterTokens.EQUAL);
write(ASEmitterTokens.NULL);
}
}
if (vnode == null && def != null)
{
emitDefaultInitializerForDefinition(def);
}
if (!(node instanceof ChainedVariableNode))
{
int len = node.getChildCount();
for (int i = 0; i < len; i++)
{
IASNode child = node.getChild(i);
if (child instanceof ChainedVariableNode)
{
writeNewline(ASEmitterTokens.SEMICOLON);
writeNewline();
getEmitter().emitField((IVariableNode) child);
}
}
}
if (node.getNodeID() == ASTNodeID.BindableVariableID && !node.isConst())
{
putBindableVariable(node, def);
}
}