You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by cd...@apache.org on 2016/04/13 20:56:29 UTC
[37/51] [partial] git commit: [flex-falcon]
[refs/heads/feature/maven-migration-test] - - Check-In of the migrated
project to make error analysis easier
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/c3dce49f/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/vf2js/JSVF2JSDocEmitter.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/vf2js/JSVF2JSDocEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/vf2js/JSVF2JSDocEmitter.java
new file mode 100644
index 0000000..3147c20
--- /dev/null
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/vf2js/JSVF2JSDocEmitter.java
@@ -0,0 +1,270 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.flex.compiler.internal.codegen.js.vf2js;
+
+import org.apache.flex.compiler.asdoc.flexjs.ASDocComment;
+import org.apache.flex.compiler.clients.MXMLJSC;
+import org.apache.flex.compiler.codegen.js.IJSEmitter;
+import org.apache.flex.compiler.common.ASModifier;
+import org.apache.flex.compiler.common.DependencyType;
+import org.apache.flex.compiler.constants.IASKeywordConstants;
+import org.apache.flex.compiler.constants.IASLanguageConstants;
+import org.apache.flex.compiler.definitions.IClassDefinition;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.definitions.IFunctionDefinition;
+import org.apache.flex.compiler.definitions.ITypeDefinition;
+import org.apache.flex.compiler.definitions.references.IReference;
+import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.JSEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogDocEmitter;
+import org.apache.flex.compiler.internal.definitions.InterfaceDefinition;
+import org.apache.flex.compiler.internal.scopes.ASScope;
+import org.apache.flex.compiler.projects.ICompilerProject;
+import org.apache.flex.compiler.tree.as.IDefinitionNode;
+import org.apache.flex.compiler.tree.as.IExpressionNode;
+import org.apache.flex.compiler.tree.as.IFunctionNode;
+import org.apache.flex.compiler.tree.as.IParameterNode;
+import org.apache.flex.compiler.tree.as.IVariableNode;
+
+public class JSVF2JSDocEmitter extends JSGoogDocEmitter
+{
+
+ public JSVF2JSDocEmitter(IJSEmitter emitter)
+ {
+ super(emitter);
+ }
+
+ @Override
+ public void emitMethodDoc(IFunctionNode node, ICompilerProject project)
+ {
+ IClassDefinition classDefinition = resolveClassDefinition(node);
+
+ ASDocComment asDoc = (ASDocComment) node.getASDocComment();
+
+ if (node instanceof IFunctionNode)
+ {
+ boolean hasDoc = false;
+
+ if (node.isConstructor())
+ {
+ if (asDoc != null && MXMLJSC.keepASDoc)
+ write(asDoc.commentNoEnd());
+ else
+ begin();
+ hasDoc = true;
+
+ emitJSDocLine(JSEmitterTokens.CONSTRUCTOR);
+
+ IClassDefinition parent = (IClassDefinition) node
+ .getDefinition().getParent();
+ IClassDefinition superClass = parent.resolveBaseClass(project);
+ String qname = (superClass != null) ? superClass.getQualifiedName() : null;
+
+ if (superClass != null
+ && !qname.equals(IASLanguageConstants.Object))
+ emitExtends(superClass, superClass.getPackageName());
+
+ IReference[] references = classDefinition
+ .getImplementedInterfaceReferences();
+ for (IReference iReference : references)
+ {
+ ITypeDefinition type = (ITypeDefinition) iReference
+ .resolve(project, (ASScope) classDefinition
+ .getContainingScope(),
+ DependencyType.INHERITANCE, true);
+ if (type == null)
+ System.out.println(iReference.getDisplayString() + " not resolved in " + classDefinition.getQualifiedName());
+ emitImplements(type, type.getPackageName());
+ }
+ }
+ else
+ {
+ String ns = node.getNamespace();
+ if (ns != null)
+ {
+ if (asDoc != null && MXMLJSC.keepASDoc)
+ write(asDoc.commentNoEnd());
+ else
+ begin();
+ emitMethodAccess(node);
+ hasDoc = true;
+ }
+ }
+
+ // @param
+ IParameterNode[] parameters = node.getParameterNodes();
+ for (IParameterNode pnode : parameters)
+ {
+ if (!hasDoc)
+ {
+ if (asDoc != null && MXMLJSC.keepASDoc)
+ write(asDoc.commentNoEnd());
+ else
+ begin();
+ emitMethodAccess(node);
+ hasDoc = true;
+ }
+
+ IExpressionNode enode = pnode.getNameExpressionNode();
+
+ // ToDo (erikdebruin): add VF2JS conditional -> only use check during full SDK compilation
+ ITypeDefinition tdef = enode.resolveType(project);
+ if (tdef == null)
+ continue;
+
+ emitParam(pnode, tdef.getPackageName());
+ }
+
+ if (!node.isConstructor())
+ {
+ // @return
+ String returnType = node.getReturnType();
+ if (returnType != ""
+ && returnType != ASEmitterTokens.VOID.getToken())
+ {
+ if (!hasDoc)
+ {
+ if (asDoc != null && MXMLJSC.keepASDoc)
+ write(asDoc.commentNoEnd());
+ else
+ begin();
+ emitMethodAccess(node);
+ hasDoc = true;
+ }
+
+ ITypeDefinition tdef = ((IFunctionDefinition)node.getDefinition())
+ .resolveReturnType(project);
+
+ String packageName = "";
+ if (tdef instanceof InterfaceDefinition)
+ packageName = tdef.getPackageName();
+ else
+ packageName = node.getPackageName();
+
+ emitReturn(node, packageName);
+ }
+
+ // @override
+ Boolean override = node.hasModifier(ASModifier.OVERRIDE);
+ if (override)
+ {
+ if (!hasDoc)
+ {
+ if (asDoc != null && MXMLJSC.keepASDoc)
+ write(asDoc.commentNoEnd());
+ else
+ begin();
+ emitMethodAccess(node);
+ hasDoc = true;
+ }
+
+ emitOverride(node);
+ }
+ }
+
+ if (hasDoc)
+ end();
+ }
+ }
+
+ @Override
+ public void emitVarDoc(IVariableNode node, IDefinition def, ICompilerProject project)
+ {
+ String packageName = "";
+ if (def != null)
+ packageName = def.getPackageName();
+
+ if (!node.isConst())
+ {
+ IDefinition ndef = node.getDefinition();
+ if (emitter != null && emitter instanceof JSVF2JSEmitter)
+ {
+ if (project != null)
+ {
+ packageName = ((ITypeDefinition)ndef.resolveType(project))
+ .getPackageName();
+ }
+ }
+ }
+
+ emitTypeShort(node, packageName);
+ }
+
+
+ public void emitInterfaceMemberDoc(IDefinitionNode node, ICompilerProject project)
+ {
+ boolean hasDoc = false;
+
+ ASDocComment asDoc = (ASDocComment) ((IFunctionNode) node).getASDocComment();
+
+ String returnType = ((IFunctionNode) node).getReturnType();
+ if (returnType != ""
+ && returnType != ASEmitterTokens.VOID.getToken()) // has return
+ {
+ if (asDoc != null && MXMLJSC.keepASDoc)
+ write(asDoc.commentNoEnd());
+ else
+ begin();
+ hasDoc = true;
+
+ ITypeDefinition tdef = ((IFunctionDefinition)node.getDefinition())
+ .resolveReturnType(project);
+
+ emitReturn((IFunctionNode) node, tdef.getPackageName());
+ }
+
+ IParameterNode[] parameters = ((IFunctionNode) node).getParameterNodes();
+ for (IParameterNode pnode : parameters)
+ {
+ if (!hasDoc)
+ {
+ if (asDoc != null && MXMLJSC.keepASDoc)
+ write(asDoc.commentNoEnd());
+ else
+ begin();
+ hasDoc = true;
+ }
+
+ IExpressionNode enode = pnode.getNameExpressionNode();
+ emitParam(pnode, enode.resolveType(project).getPackageName());
+ }
+
+ if (hasDoc)
+ end();
+ }
+
+ @Override
+ public void emitMethodAccess(IFunctionNode node)
+ {
+ String ns = node.getNamespace();
+ if (ns == IASKeywordConstants.PRIVATE)
+ {
+ emitPrivate(node);
+ }
+ else if (ns == IASKeywordConstants.PROTECTED)
+ {
+ emitProtected(node);
+ }
+ else if (ns == IASKeywordConstants.PUBLIC)
+ {
+ emitPublic(node);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/c3dce49f/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/vf2js/JSVF2JSEmitter.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/vf2js/JSVF2JSEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/vf2js/JSVF2JSEmitter.java
new file mode 100644
index 0000000..4f9d5f2
--- /dev/null
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/vf2js/JSVF2JSEmitter.java
@@ -0,0 +1,1950 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.flex.compiler.internal.codegen.js.vf2js;
+
+import java.io.FilterWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.flex.compiler.codegen.IASGlobalFunctionConstants;
+import org.apache.flex.compiler.codegen.js.goog.IJSGoogDocEmitter;
+import org.apache.flex.compiler.codegen.js.vf2js.IJSVF2JSEmitter;
+import org.apache.flex.compiler.common.ASModifier;
+import org.apache.flex.compiler.common.ModifiersSet;
+import org.apache.flex.compiler.constants.IASLanguageConstants;
+import org.apache.flex.compiler.definitions.IClassDefinition;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.definitions.IFunctionDefinition;
+import org.apache.flex.compiler.definitions.IFunctionDefinition.FunctionClassification;
+import org.apache.flex.compiler.definitions.INamespaceDefinition;
+import org.apache.flex.compiler.definitions.IPackageDefinition;
+import org.apache.flex.compiler.definitions.IParameterDefinition;
+import org.apache.flex.compiler.definitions.ITypeDefinition;
+import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.JSEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.JSSessionModel;
+import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitter;
+import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.utils.EmitterUtils;
+import org.apache.flex.compiler.internal.definitions.AccessorDefinition;
+import org.apache.flex.compiler.internal.definitions.ClassDefinition;
+import org.apache.flex.compiler.internal.definitions.FunctionDefinition;
+import org.apache.flex.compiler.internal.definitions.InterfaceDefinition;
+import org.apache.flex.compiler.internal.definitions.ParameterDefinition;
+import org.apache.flex.compiler.internal.definitions.VariableDefinition;
+import org.apache.flex.compiler.internal.projects.CompilerProject;
+import org.apache.flex.compiler.internal.projects.FlexJSProject;
+import org.apache.flex.compiler.internal.scopes.ASProjectScope;
+import org.apache.flex.compiler.internal.scopes.PackageScope;
+import org.apache.flex.compiler.internal.scopes.TypeScope;
+import org.apache.flex.compiler.internal.tree.as.BinaryOperatorAssignmentNode;
+import org.apache.flex.compiler.internal.tree.as.ChainedVariableNode;
+import org.apache.flex.compiler.internal.tree.as.FunctionCallNode;
+import org.apache.flex.compiler.internal.tree.as.FunctionNode;
+import org.apache.flex.compiler.internal.tree.as.NonResolvingIdentifierNode;
+import org.apache.flex.compiler.internal.tree.as.ParameterNode;
+import org.apache.flex.compiler.internal.tree.as.RegExpLiteralNode;
+import org.apache.flex.compiler.internal.tree.as.UnaryOperatorAtNode;
+import org.apache.flex.compiler.projects.ICompilerProject;
+import org.apache.flex.compiler.scopes.IASScope;
+import org.apache.flex.compiler.tree.ASTNodeID;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.as.IAccessorNode;
+import org.apache.flex.compiler.tree.as.IBinaryOperatorNode;
+import org.apache.flex.compiler.tree.as.IClassNode;
+import org.apache.flex.compiler.tree.as.IContainerNode;
+import org.apache.flex.compiler.tree.as.IDefinitionNode;
+import org.apache.flex.compiler.tree.as.IEmbedNode;
+import org.apache.flex.compiler.tree.as.IExpressionNode;
+import org.apache.flex.compiler.tree.as.IForLoopNode;
+import org.apache.flex.compiler.tree.as.IFunctionCallNode;
+import org.apache.flex.compiler.tree.as.IFunctionNode;
+import org.apache.flex.compiler.tree.as.IGetterNode;
+import org.apache.flex.compiler.tree.as.IIdentifierNode;
+import org.apache.flex.compiler.tree.as.IInterfaceNode;
+import org.apache.flex.compiler.tree.as.IKeywordNode;
+import org.apache.flex.compiler.tree.as.ILanguageIdentifierNode;
+import org.apache.flex.compiler.tree.as.ILiteralNode;
+import org.apache.flex.compiler.tree.as.ILiteralNode.LiteralType;
+import org.apache.flex.compiler.tree.as.IMemberAccessExpressionNode;
+import org.apache.flex.compiler.tree.as.IParameterNode;
+import org.apache.flex.compiler.tree.as.ISetterNode;
+import org.apache.flex.compiler.tree.as.ITypeNode;
+import org.apache.flex.compiler.tree.as.ITypedExpressionNode;
+import org.apache.flex.compiler.tree.as.IVariableExpressionNode;
+import org.apache.flex.compiler.tree.as.IVariableNode;
+import org.apache.flex.compiler.units.ICompilationUnit;
+import org.apache.flex.compiler.utils.ASNodeUtils;
+import org.apache.flex.compiler.utils.NativeUtils;
+
+/**
+ * Concrete implementation of the 'vf2js' JavaScript production.
+ *
+ * @author Erik de Bruin
+ */
+public class JSVF2JSEmitter extends JSGoogEmitter implements IJSVF2JSEmitter
+{
+
+ public JSVF2JSEmitter(FilterWriter out)
+ {
+ super(out);
+ }
+
+ @Override
+ protected String getIndent(int numIndent)
+ {
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < numIndent; i++)
+ sb.append(JSFlexJSEmitterTokens.INDENT.getToken());
+ return sb.toString();
+ }
+
+ @Override
+ protected void emitMemberName(IDefinitionNode node)
+ {
+ write(node.getName());
+ }
+
+ @Override
+ public void emitClass(IClassNode node)
+ {
+ IClassDefinition definition = node.getDefinition();
+ getModel().setCurrentClass(definition);
+
+ project = getWalker().getProject();
+
+ IFunctionDefinition ctorDefinition = definition.getConstructor();
+
+ // Static-only (Singleton) classes may not have a constructor
+ if (ctorDefinition != null)
+ {
+ IFunctionNode ctorNode = (IFunctionNode) ctorDefinition.getNode();
+ if (ctorNode != null)
+ {
+ // constructor
+ emitMethod(ctorNode);
+ write(ASEmitterTokens.SEMICOLON);
+ }
+ else
+ {
+ String qname = parseQualifiedName(definition);
+ if (qname != null && !qname.equals(""))
+ {
+ write(qname);
+ write(ASEmitterTokens.SPACE);
+ writeToken(ASEmitterTokens.EQUAL);
+ write(ASEmitterTokens.FUNCTION);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ write(ASEmitterTokens.SPACE);
+ write(ASEmitterTokens.BLOCK_OPEN);
+ writeNewline();
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ write(ASEmitterTokens.SEMICOLON);
+ }
+ }
+ }
+
+ IDefinitionNode[] dnodes = node.getAllMemberNodes();
+ for (IDefinitionNode dnode : dnodes)
+ {
+ if (dnode.getNodeID() == ASTNodeID.VariableID)
+ {
+ writeNewline();
+ writeNewline();
+ writeNewline();
+ emitField((IVariableNode) dnode);
+ write(ASEmitterTokens.SEMICOLON);
+ }
+ else if (dnode.getNodeID() == ASTNodeID.FunctionID)
+ {
+ if (!((IFunctionNode) dnode).isConstructor())
+ {
+ writeNewline();
+ writeNewline();
+ writeNewline();
+ emitMethod((IFunctionNode) dnode);
+ write(ASEmitterTokens.SEMICOLON);
+ }
+ }
+ else if (dnode.getNodeID() == ASTNodeID.GetterID
+ || dnode.getNodeID() == ASTNodeID.SetterID)
+ {
+ writeNewline();
+ writeNewline();
+ writeNewline();
+ emitAccessors((IAccessorNode) dnode);
+ write(ASEmitterTokens.SEMICOLON);
+ }
+ }
+ }
+
+ @Override
+ public void emitInterface(IInterfaceNode node)
+ {
+ ICompilerProject project = getWalker().getProject();
+
+ getDocEmitter().emitInterfaceDoc(node, project);
+
+ String qname = parseQualifiedName(node);
+ if (qname != null && !qname.equals(""))
+ {
+ write(qname);
+ write(ASEmitterTokens.SPACE);
+ writeToken(ASEmitterTokens.EQUAL);
+ write(ASEmitterTokens.FUNCTION);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ write(ASEmitterTokens.SPACE);
+ write(ASEmitterTokens.BLOCK_OPEN);
+ writeNewline();
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ write(ASEmitterTokens.SEMICOLON);
+ }
+
+ final IDefinitionNode[] members = node.getAllMemberDefinitionNodes();
+ for (IDefinitionNode mnode : members)
+ {
+ boolean isAccessor = mnode.getNodeID() == ASTNodeID.GetterID
+ || mnode.getNodeID() == ASTNodeID.SetterID;
+
+ writeNewline();
+ writeNewline();
+ writeNewline();
+
+ getDocEmitter().emitInterfaceMemberDoc(mnode, project);
+
+ write(qname);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(JSEmitterTokens.PROTOTYPE);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ if (isAccessor)
+ {
+ writeGetSetPrefix(mnode.getNodeID() == ASTNodeID.GetterID);
+ }
+ write(parseQualifiedName(mnode));
+ write(ASEmitterTokens.SPACE);
+ writeToken(ASEmitterTokens.EQUAL);
+ write(ASEmitterTokens.FUNCTION);
+ emitParameters(((IFunctionNode) mnode).getParametersContainerNode());
+ write(ASEmitterTokens.SPACE);
+ write(ASEmitterTokens.BLOCK_OPEN);
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ write(ASEmitterTokens.SEMICOLON);
+ }
+ }
+
+ @Override
+ public void emitFunctionBlockHeader(IFunctionNode node)
+ {
+ IDefinition def = node.getDefinition();
+ boolean isStatic = false;
+ if (def != null && def.isStatic())
+ isStatic = true;
+ boolean isLocal = false;
+ if (node.getFunctionClassification() == IFunctionDefinition.FunctionClassification.LOCAL)
+ isLocal = true;
+ if (EmitterUtils.hasBody(node) && !isStatic && !isLocal)
+ emitSelfReference(node);
+
+ emitRestParameterCodeBlock(node);
+
+ emitDefaultParameterCodeBlock(node);
+
+ if (node.isConstructor())
+ {
+ emitVarNonLiteralAssignments();
+ }
+
+ if (node.isConstructor() && hasSuperClass(node)
+ && !EmitterUtils.hasSuperCall(node.getScopedNode()))
+ emitSuperCall(node, JSSessionModel.CONSTRUCTOR_FULL);
+ }
+
+ private void emitVarNonLiteralAssignments()
+ {
+ // (erikdebruin): If the initial value of a variable is set using
+ // a method, JS needs this initialization to be done
+ // in the constructor
+ IClassNode cdnode = (IClassNode) getModel().getCurrentClass().getNode();
+ IDefinitionNode[] dnodes = cdnode.getAllMemberNodes();
+ for (IDefinitionNode dnode : dnodes)
+ {
+ if (dnode.getNodeID() == ASTNodeID.VariableID)
+ {
+ IVariableNode vnode = (IVariableNode) dnode;
+ IExpressionNode avnode = vnode.getAssignedValueNode();
+ if (avnode != null && !(avnode instanceof ILiteralNode)
+ && !(avnode instanceof IEmbedNode))
+ {
+ writeNewline("", true);
+ if (vnode.hasModifier(ASModifier.STATIC))
+ {
+ write(parseQualifiedName(cdnode));
+ }
+ else
+ {
+ write(ASEmitterTokens.THIS);
+ }
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ writeToken(vnode.getName());
+ writeToken(ASEmitterTokens.EQUAL);
+ getWalker().walk(avnode);
+ indentPop();
+ writeNewline(ASEmitterTokens.SEMICOLON);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void emitVarDeclaration(IVariableNode node)
+ {
+ if (!(node instanceof ChainedVariableNode))
+ {
+ // (erikdebruin): check for 'var i:int = 0, j:int = 0' containers
+ IASNode pnode = node.getParent();
+ if (!(pnode instanceof IVariableExpressionNode)
+ || node.getChild(0) instanceof IKeywordNode)
+ {
+ emitMemberKeyword(node);
+ }
+ }
+
+ IExpressionNode avnode = node.getAssignedValueNode();
+ if (avnode != null)
+ {
+ IDefinition def = avnode.resolveType(getWalker().getProject());
+
+ String opcode = avnode.getNodeID().getParaphrase();
+ if (opcode != "AnonymousFunction")
+ getDocEmitter().emitVarDoc(node, def, getWalker().getProject());
+ }
+ else
+ {
+ getDocEmitter().emitVarDoc(node, null, getWalker().getProject());
+ }
+
+ emitDeclarationName(node);
+ if (avnode != null && !(avnode instanceof IEmbedNode))
+ {
+ write(ASEmitterTokens.SPACE);
+ writeToken(ASEmitterTokens.EQUAL);
+ emitAssignedValue(avnode);
+ }
+
+ if (!(node instanceof ChainedVariableNode))
+ {
+ // check for chained variables
+ int len = node.getChildCount();
+ for (int i = 0; i < len; i++)
+ {
+ IASNode child = node.getChild(i);
+ if (child instanceof ChainedVariableNode)
+ {
+ writeToken(ASEmitterTokens.COMMA);
+ emitVarDeclaration((IVariableNode) child);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void emitMemberKeyword(IDefinitionNode node)
+ {
+ if (node instanceof IFunctionNode)
+ {
+ writeToken(ASEmitterTokens.FUNCTION);
+ }
+ else if (node instanceof IVariableNode)
+ {
+ writeToken(ASEmitterTokens.VAR);
+ }
+ }
+
+ @Override
+ public void emitField(IVariableNode node)
+ {
+ IDefinition definition = EmitterUtils.getClassDefinition(node);
+
+ IDefinition def = null;
+ IExpressionNode enode = node.getVariableTypeNode();//getAssignedValueNode();
+ if (enode != null)
+ {
+ if (project == null)
+ project = getWalker().getProject();
+
+ def = enode.resolveType(project);
+ }
+
+ getDocEmitter().emitFieldDoc(node, def, project);
+
+ IDefinition ndef = node.getDefinition();
+
+ ModifiersSet modifierSet = ndef.getModifiers();
+ String root = "";
+ if (modifierSet != null && !modifierSet.hasModifier(ASModifier.STATIC))
+ {
+ root = JSEmitterTokens.PROTOTYPE.getToken();
+ root += ASEmitterTokens.MEMBER_ACCESS.getToken();
+ }
+
+ if (definition == null)
+ definition = ndef.getContainingScope().getDefinition();
+
+ write(parseQualifiedName(definition)
+ + ASEmitterTokens.MEMBER_ACCESS.getToken() + root
+ + node.getName());
+
+ IExpressionNode vnode = node.getAssignedValueNode();
+ if (vnode != null && vnode instanceof ILiteralNode)
+ {
+ write(ASEmitterTokens.SPACE);
+ writeToken(ASEmitterTokens.EQUAL);
+ getWalker().walk(vnode);
+ }
+
+ 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();
+ emitField((IVariableNode) child);
+ }
+ }
+ }
+ if (node.getNodeID() == ASTNodeID.BindableVariableID)
+ {
+ // [Bindable]
+ writeNewline(ASEmitterTokens.SEMICOLON.getToken());
+ writeNewline();
+ writeNewline("/**");
+ writeNewline("@export");
+ writeNewline(" */");
+ writeNewline(parseQualifiedName(definition)
+ + ASEmitterTokens.MEMBER_ACCESS.getToken() + root + "get_"
+ + node.getName() + ASEmitterTokens.SPACE.getToken()
+ + ASEmitterTokens.EQUAL.getToken()
+ + ASEmitterTokens.SPACE.getToken()
+ + ASEmitterTokens.FUNCTION.getToken()
+ + ASEmitterTokens.PAREN_OPEN.getToken()
+ + ASEmitterTokens.PAREN_CLOSE.getToken()
+ + ASEmitterTokens.SPACE.getToken()
+ + ASEmitterTokens.BLOCK_OPEN.getToken());
+ writeNewline(ASEmitterTokens.RETURN.getToken()
+ + ASEmitterTokens.SPACE.getToken()
+ + ASEmitterTokens.THIS.getToken()
+ + ASEmitterTokens.MEMBER_ACCESS.getToken() + node.getName()
+ + ASEmitterTokens.SEMICOLON.getToken());
+ writeNewline(ASEmitterTokens.BLOCK_CLOSE.getToken()
+ + ASEmitterTokens.SEMICOLON.getToken());
+ writeNewline();
+ writeNewline("/**");
+ writeNewline("@export");
+ writeNewline(" */");
+ writeNewline(parseQualifiedName(definition)
+ + ASEmitterTokens.MEMBER_ACCESS.getToken() + root + "set_"
+ + node.getName() + ASEmitterTokens.SPACE.getToken()
+ + ASEmitterTokens.EQUAL.getToken()
+ + ASEmitterTokens.SPACE.getToken()
+ + ASEmitterTokens.FUNCTION.getToken()
+ + ASEmitterTokens.PAREN_OPEN.getToken() + "value"
+ + ASEmitterTokens.PAREN_CLOSE.getToken()
+ + ASEmitterTokens.SPACE.getToken()
+ + ASEmitterTokens.BLOCK_OPEN.getToken());
+ writeNewline("if (value != " + ASEmitterTokens.THIS.getToken()
+ + ASEmitterTokens.MEMBER_ACCESS.getToken() + node.getName()
+ + ") {");
+ writeNewline(" var oldValue = "
+ + ASEmitterTokens.THIS.getToken()
+ + ASEmitterTokens.MEMBER_ACCESS.getToken() + node.getName()
+ + ASEmitterTokens.SEMICOLON.getToken());
+ writeNewline(" " + ASEmitterTokens.THIS.getToken()
+ + ASEmitterTokens.MEMBER_ACCESS.getToken() + node.getName()
+ + " = value;");
+ writeNewline(" this.dispatchEvent(org.apache.flex.events.ValueChangeEvent.createUpdateEvent(");
+ writeNewline(" this, \"" + node.getName()
+ + "\", oldValue, value));");
+ writeNewline("}");
+ write(ASEmitterTokens.BLOCK_CLOSE.getToken());
+
+ }
+ }
+
+ @Override
+ public void emitAccessors(IAccessorNode node)
+ {
+ if (node.getNodeID() == ASTNodeID.GetterID)
+ {
+ emitGetAccessor((IGetterNode) node);
+ }
+ else if (node.getNodeID() == ASTNodeID.SetterID)
+ {
+ emitSetAccessor((ISetterNode) node);
+ }
+ }
+
+ @Override
+ public void emitMethod(IFunctionNode node)
+ {
+ FunctionNode fn = (FunctionNode) node;
+ fn.parseFunctionBody(getProblems());
+
+ ICompilerProject project = getWalker().getProject();
+
+ getDocEmitter().emitMethodDoc(node, project);
+
+ boolean isConstructor = node.isConstructor();
+
+ String qname = parseQualifiedName(getTypeDefinition(node));
+ if (qname != null && !qname.equals(""))
+ {
+ write(qname);
+ if (!isConstructor)
+ {
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ if (!fn.hasModifier(ASModifier.STATIC))
+ {
+ write(JSEmitterTokens.PROTOTYPE);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ }
+ }
+ }
+
+ if (!isConstructor)
+ emitMemberName(node);
+
+ write(ASEmitterTokens.SPACE);
+ writeToken(ASEmitterTokens.EQUAL);
+ write(ASEmitterTokens.FUNCTION);
+
+ emitParameters(node.getParametersContainerNode());
+
+ boolean hasSuperClass = hasSuperClass(node);
+
+ if (isConstructor && node.getScopedNode().getChildCount() == 0)
+ {
+ write(ASEmitterTokens.SPACE);
+ write(ASEmitterTokens.BLOCK_OPEN);
+ emitVarNonLiteralAssignments();
+ if (hasSuperClass)
+ {
+ emitSuperCall(node, JSSessionModel.CONSTRUCTOR_EMPTY);
+ writeNewline();
+ }
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ }
+
+ if (!isConstructor || node.getScopedNode().getChildCount() > 0)
+ emitMethodScope(node.getScopedNode());
+
+ if (isConstructor && hasSuperClass)
+ {
+ writeNewline(ASEmitterTokens.SEMICOLON);
+ write(JSGoogEmitterTokens.GOOG_INHERITS);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(qname);
+ writeToken(ASEmitterTokens.COMMA);
+ String sname = parseQualifiedName(getSuperClassDefinition(node,
+ project));
+ if (sname.equals(IASLanguageConstants.Object))
+ sname = IASLanguageConstants.Class;
+ write(sname);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+ }
+
+ protected boolean hasSuperClass(IDefinitionNode node)
+ {
+ ICompilerProject project = getWalker().getProject();
+ IClassDefinition superClassDefinition = getSuperClassDefinition(node,
+ project);
+
+ if (superClassDefinition == null)
+ return false;
+
+ String qname = parseQualifiedName(superClassDefinition);
+
+ // ToDo (erikdebruin): need this to get the JS version of the SDK in
+ // shape?
+ boolean useClassAsSuperClass = !qname
+ .equals(IASLanguageConstants.Object);
+ if (!useClassAsSuperClass)
+ {
+ if (parseQualifiedName(node).equals("mx.core.EmbeddedFontRegistry")
+ || parseQualifiedName(node).equals(
+ "mx.managers.HistoryManagerImpl")
+ || parseQualifiedName(node).equals(
+ "mx.core.TextFieldFactory"))
+ {
+ useClassAsSuperClass = true;
+ }
+ }
+
+ return superClassDefinition != null && useClassAsSuperClass;
+ }
+
+ @Override
+ public void emitFunctionCall(IFunctionCallNode node)
+ {
+ IASNode cnode = node.getChild(0);
+
+ if (cnode.getNodeID() == ASTNodeID.MemberAccessExpressionID)
+ cnode = cnode.getChild(0);
+
+ ASTNodeID id = cnode.getNodeID();
+ if (id != ASTNodeID.SuperID)
+ {
+ ICompilerProject project = null;
+ IDefinition def = null;
+
+ boolean isClassCast = false;
+
+ if (node.isNewExpression())
+ {
+ writeToken(ASEmitterTokens.NEW);
+ }
+ else
+ {
+ if (project == null)
+ project = getWalker().getProject();
+
+ def = node.getNameNode().resolve(project);
+
+ isClassCast = (def instanceof ClassDefinition || def instanceof InterfaceDefinition)
+ && !(NativeUtils.isJSNative(def.getBaseName()));
+ }
+
+ if (node.isNewExpression())
+ {
+ if (project == null)
+ project = getWalker().getProject();
+
+ def = node.resolveCalledExpression(project);
+ // all new calls to a class should be fully qualified names
+ if (def instanceof ClassDefinition)
+ write(parseQualifiedName(def));
+ else
+ // I think we still need this for "new someVarOfTypeClass"
+ getWalker().walk(node.getNameNode());
+ emitArguments(node.getArgumentsNode());
+ }
+ else if (!isClassCast)
+ {
+ if (def != null)
+ {
+ boolean isInt = def.getBaseName().equals(
+ IASGlobalFunctionConstants._int);
+ if (isInt
+ || def.getBaseName().equals(
+ IASGlobalFunctionConstants.trace)
+ || def.getBaseName().equals(
+ IASGlobalFunctionConstants.uint))
+ {
+ write(JSFlexJSEmitterTokens.LANGUAGE_QNAME);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ if (isInt)
+ write(JSFlexJSEmitterTokens.UNDERSCORE);
+ }
+ }
+ getWalker().walk(node.getNameNode());
+ emitArguments(node.getArgumentsNode());
+ }
+ else
+ {
+ emitIsAs(node.getArgumentNodes()[0], node.getNameNode(),
+ ASTNodeID.Op_AsID, true);
+ }
+ }
+ else
+ {
+ emitSuperCall(node, JSSessionModel.SUPER_FUNCTION_CALL);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+
+ @Override
+ protected void emitSelfReference(IFunctionNode node)
+ {
+ // we don't want 'var self = this;' in FlexJS
+ }
+
+ private boolean writeThis(IIdentifierNode node)
+ {
+ if (node instanceof NonResolvingIdentifierNode)
+ return false;
+
+ IClassNode classNode = (IClassNode) node
+ .getAncestorOfType(IClassNode.class);
+
+ IDefinition nodeDef = node.resolve(project);
+
+ IASNode parentNode = node.getParent();
+ ASTNodeID parentNodeId = parentNode.getNodeID();
+
+ IASNode firstChild = parentNode.getChild(0);
+ IClassDefinition thisClass = getModel().getCurrentClass();
+
+ boolean identifierIsMemberAccess = parentNodeId == ASTNodeID.MemberAccessExpressionID;
+
+ if (classNode == null) // script in MXML and AS interface definitions
+ {
+ if (nodeDef instanceof ParameterDefinition)
+ return false;
+
+ if (nodeDef instanceof VariableDefinition)
+ {
+ IDefinition pdef = ((VariableDefinition) nodeDef).getParent();
+
+ if (thisClass == null || !isSameClass(pdef, thisClass, project))
+ return false;
+
+ if (identifierIsMemberAccess)
+ return node == firstChild;
+
+ return parentNodeId == ASTNodeID.ContainerID
+ || !(parentNode instanceof ParameterNode);
+ }
+ else if (nodeDef instanceof AccessorDefinition)
+ {
+ IDefinition pdef = ((AccessorDefinition) nodeDef).getParent();
+
+ if (thisClass == null || !isSameClass(pdef, thisClass, project))
+ return false;
+
+ if (identifierIsMemberAccess)
+ return node == firstChild;
+
+ return true;
+ }
+ else if (parentNodeId == ASTNodeID.ContainerID
+ && nodeDef instanceof FunctionDefinition)
+ {
+ return ((FunctionDefinition) nodeDef)
+ .getFunctionClassification() == FunctionClassification.CLASS_MEMBER; // for 'goog.bind'
+ }
+ else
+ {
+ return parentNodeId == ASTNodeID.FunctionCallID
+ && !(nodeDef instanceof AccessorDefinition)
+ && !identifierIsMemberAccess;
+ }
+ }
+ else
+ {
+ if (nodeDef != null && !nodeDef.isInternal()
+ && isClassMember(nodeDef, classNode))
+ {
+ if (identifierIsMemberAccess)
+ {
+ if (parentNode.getNodeID() == ASTNodeID.MemberAccessExpressionID
+ && parentNode.getChild(0).getNodeID() == ASTNodeID.SuperID
+ && !isSuperCallForOverride(node))
+ {
+ return true;
+ }
+
+ return node == firstChild;
+ }
+ else
+ {
+ boolean identifierIsLocalFunction = nodeDef instanceof FunctionDefinition
+ && !(nodeDef instanceof AccessorDefinition)
+ && ((FunctionDefinition) nodeDef)
+ .getFunctionClassification() == IFunctionDefinition.FunctionClassification.LOCAL;
+
+ if (nodeDef instanceof IParameterDefinition)
+ return false;
+
+ return !identifierIsLocalFunction;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private boolean isClassMember(IDefinition nodeDef, IClassNode classNode)
+ {
+ TypeScope cscope = (TypeScope) classNode.getDefinition()
+ .getContainedScope();
+
+ Set<INamespaceDefinition> nsSet = cscope.getNamespaceSet(project);
+ Collection<IDefinition> defs = new HashSet<IDefinition>();
+
+ cscope.getAllPropertiesForMemberAccess((CompilerProject) project, defs,
+ nsSet);
+
+ Iterator<IDefinition> visiblePropertiesIterator = defs.iterator();
+ while (visiblePropertiesIterator.hasNext())
+ {
+ if (parseQualifiedName(nodeDef).equals(
+ parseQualifiedName(visiblePropertiesIterator.next())))
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean isSameClass(IDefinition pdef, IDefinition thisClass,
+ ICompilerProject project)
+ {
+ if (pdef == thisClass)
+ return true;
+
+ IDefinition cdef = ((ClassDefinition) thisClass)
+ .resolveBaseClass(project);
+ while (cdef != null)
+ {
+ // needs to be a loop
+ if (cdef == pdef)
+ return true;
+ cdef = ((ClassDefinition) cdef).resolveBaseClass(project);
+ }
+ return false;
+ }
+
+ @Override
+ public void emitIdentifier(IIdentifierNode node)
+ {
+ if (project == null)
+ project = getWalker().getProject();
+
+ IDefinition nodeDef = node.resolve(project);
+
+ IASNode parentNode = node.getParent();
+ ASTNodeID parentNodeId = parentNode.getNodeID();
+
+ boolean identifierIsAccessorFunction = nodeDef instanceof AccessorDefinition;
+ boolean identifierIsPlainFunction = nodeDef instanceof FunctionDefinition
+ && !identifierIsAccessorFunction;
+
+ boolean emitName = true;
+
+ if (nodeDef != null && nodeDef.isStatic()
+ && nodeDef.getParent() != null)
+ {
+ String sname = parseQualifiedName(nodeDef.getParent());
+ if (sname.length() > 0)
+ {
+ write(sname);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ }
+ }
+ else if (!NativeUtils.isNative(node.getName()))
+ {
+ // an instance method as a parameter or
+ // a local function
+ boolean useGoogBind = (parentNodeId == ASTNodeID.ContainerID
+ && identifierIsPlainFunction && ((FunctionDefinition) nodeDef)
+ .getFunctionClassification() == FunctionClassification.CLASS_MEMBER)
+ || (identifierIsPlainFunction && ((FunctionDefinition) nodeDef)
+ .getFunctionClassification() == FunctionClassification.LOCAL);
+
+ if (useGoogBind)
+ {
+ write(JSGoogEmitterTokens.GOOG_BIND);
+ write(ASEmitterTokens.PAREN_OPEN);
+ }
+
+ if (writeThis(node))
+ {
+ write(ASEmitterTokens.THIS);
+
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ }
+
+ if (useGoogBind)
+ {
+ write(node.getName());
+
+ writeToken(ASEmitterTokens.COMMA);
+ write(ASEmitterTokens.THIS);
+ write(ASEmitterTokens.PAREN_CLOSE);
+
+ emitName = false;
+ }
+ }
+
+ IDefinition parentDef = (nodeDef != null) ? nodeDef.getParent() : null;
+ boolean isNative = (parentDef != null)
+ && NativeUtils.isNative(parentDef.getBaseName());
+ if ((identifierIsAccessorFunction && !isNative)
+ || (nodeDef instanceof VariableDefinition && ((VariableDefinition) nodeDef)
+ .isBindable()))
+ {
+ IASNode anode = node
+ .getAncestorOfType(BinaryOperatorAssignmentNode.class);
+
+ boolean isAssignment = false;
+ if (anode != null)
+ {
+ IASNode leftNode = anode.getChild(0);
+ if (anode == parentNode)
+ {
+ if (node == leftNode)
+ isAssignment = true;
+ }
+ else
+ {
+ IASNode pnode = parentNode;
+ IASNode thisNode = node;
+ while (anode != pnode)
+ {
+ if (pnode instanceof IMemberAccessExpressionNode)
+ {
+ if (thisNode != pnode.getChild(1))
+ {
+ // can't be an assignment because
+ // we're on the left side of a memberaccessexpression
+ break;
+ }
+ }
+ if (pnode == leftNode)
+ {
+ isAssignment = true;
+ }
+ thisNode = pnode;
+ pnode = pnode.getParent();
+ }
+ }
+ String op = ((IBinaryOperatorNode) anode).getOperator()
+ .getOperatorText();
+ if (op.contains("==") || !op.contains("="))
+ isAssignment = false;
+ }
+
+ if (parentNode.getNodeID() == ASTNodeID.MemberAccessExpressionID
+ && parentNode.getChild(0).getNodeID() == ASTNodeID.SuperID
+ && isSuperCallForOverride(node))
+ {
+ IClassNode cnode = (IClassNode) node
+ .getAncestorOfType(IClassNode.class);
+
+ // ToDo (erikdebruin): add VF2JS conditional -> only use check during full SDK compilation
+ if (cnode == null)
+ return;
+
+ write(parseQualifiedName(cnode));
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(JSGoogEmitterTokens.GOOG_BASE);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.THIS);
+ writeToken(ASEmitterTokens.COMMA);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ writeGetSetPrefix(!isAssignment);
+ write(parseQualifiedName(nodeDef));
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ if (isAssignment)
+ {
+ writeToken(ASEmitterTokens.COMMA);
+ }
+ }
+ else if (node instanceof NonResolvingIdentifierNode)
+ {
+ write(node.getName());
+ }
+ else
+ {
+ writeGetSetPrefix(!isAssignment);
+ write(node.getName());
+ write(ASEmitterTokens.PAREN_OPEN);
+ }
+
+ if (anode != null && isAssignment)
+ {
+ getWalker().walk(
+ ((BinaryOperatorAssignmentNode) anode)
+ .getRightOperandNode());
+ }
+
+ if (!(node instanceof NonResolvingIdentifierNode))
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+ else if (emitName)
+ {
+ if (nodeDef != null)
+ write(parseQualifiedName(nodeDef));
+ else
+ write(node.getName());
+ }
+ }
+
+ private boolean isSuperCallForOverride(IIdentifierNode node)
+ {
+ IFunctionNode pfnode = (IFunctionNode) node
+ .getAncestorOfType(FunctionNode.class);
+
+ if (pfnode == null)
+ return false;
+
+ return pfnode.getName().equals(node.getName());
+ }
+
+ //--------------------------------------------------------------------------
+
+ @Override
+ protected void emitSuperCall(IASNode node, String type)
+ {
+ IFunctionNode fnode = (node instanceof IFunctionNode) ? (IFunctionNode) node
+ : null;
+ IFunctionCallNode fcnode = (node instanceof IFunctionCallNode) ? (FunctionCallNode) node
+ : null;
+
+ if (type == JSSessionModel.CONSTRUCTOR_EMPTY)
+ {
+ indentPush();
+ writeNewline();
+ indentPop();
+ }
+ else if (type == JSSessionModel.SUPER_FUNCTION_CALL)
+ {
+ if (fnode == null)
+ fnode = (IFunctionNode) fcnode
+ .getAncestorOfType(IFunctionNode.class);
+ }
+
+ if (fnode != null && fnode.isConstructor() && !hasSuperClass(fnode))
+ return;
+
+ IClassNode cnode = (IClassNode) node
+ .getAncestorOfType(IClassNode.class);
+
+ if (cnode == null)
+ return;
+
+ // (erikdebruin): Catch when a 'super' call does NOT match the enclosing
+ // function call. The GCC only allows '.base()' calls
+ // to matching super methods, so we need to use
+ // 'goog.base' for these ...
+ boolean isCallToOtherSuperMethod = false;
+ try
+ {
+ IExpressionNode d = fcnode.getNameNode();
+ if (d != null && d instanceof IMemberAccessExpressionNode)
+ {
+ IIdentifierNode b = (IIdentifierNode) ((IMemberAccessExpressionNode) d)
+ .getRightOperandNode();
+
+ isCallToOtherSuperMethod = b != null
+ && !b.getName().equals(fnode.getName());
+ }
+ }
+ catch (Exception e)
+ { /* Eat it! */
+ }
+
+ if (isCallToOtherSuperMethod)
+ {
+ write(ASEmitterTokens.THIS);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(JSGoogEmitterTokens.SUPERCLASS);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ }
+ else
+ {
+ write(parseQualifiedName(cnode));
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(JSGoogEmitterTokens.GOOG_BASE);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.THIS);
+ }
+
+ if (fnode != null && fnode.isConstructor())
+ {
+ writeToken(ASEmitterTokens.COMMA);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(JSGoogEmitterTokens.GOOG_CONSTRUCTOR);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ }
+
+ if (fnode != null && !fnode.isConstructor())
+ {
+ if (!isCallToOtherSuperMethod)
+ {
+ writeToken(ASEmitterTokens.COMMA);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ }
+
+ if (fnode.getNodeID() == ASTNodeID.GetterID
+ || fnode.getNodeID() == ASTNodeID.SetterID)
+ writeGetSetPrefix(fnode.getNodeID() == ASTNodeID.GetterID);
+
+ // (erikdebruin): write(fnode.getName());
+ IMemberAccessExpressionNode aenode = (IMemberAccessExpressionNode) fcnode
+ .getNameNode();
+ write(((IIdentifierNode) aenode.getRightOperandNode()).getName());
+
+ if (!isCallToOtherSuperMethod)
+ {
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ }
+ else
+ {
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(JSGoogEmitterTokens.GOOG_CALL);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.THIS);
+ }
+ }
+
+ IASNode[] anodes = null;
+ boolean writeArguments = false;
+ if (fcnode != null)
+ {
+ anodes = fcnode.getArgumentNodes();
+
+ writeArguments = anodes.length > 0;
+ }
+ else if (fnode != null && fnode.isConstructor())
+ {
+ anodes = fnode.getParameterNodes();
+
+ writeArguments = (anodes != null && anodes.length > 0);
+ }
+ else if (fnode == null && node instanceof BinaryOperatorAssignmentNode)
+ {
+ BinaryOperatorAssignmentNode bnode = (BinaryOperatorAssignmentNode) node;
+
+ IFunctionNode pnode = (IFunctionNode) bnode
+ .getAncestorOfType(IFunctionNode.class);
+
+ if (pnode.getNodeID() == ASTNodeID.SetterID)
+ {
+ writeToken(ASEmitterTokens.COMMA);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ writeGetSetPrefix(false);
+ getWalker().walk(bnode.getLeftOperandNode());
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ writeToken(ASEmitterTokens.COMMA);
+ getWalker().walk(bnode.getRightOperandNode());
+ }
+ }
+
+ if (writeArguments)
+ {
+ int len = anodes.length;
+ for (int i = 0; i < len; i++)
+ {
+ writeToken(ASEmitterTokens.COMMA);
+
+ getWalker().walk(anodes[i]);
+ }
+ }
+
+ write(ASEmitterTokens.PAREN_CLOSE);
+
+ if (type == JSSessionModel.CONSTRUCTOR_FULL)
+ {
+ write(ASEmitterTokens.SEMICOLON);
+ writeNewline();
+ }
+ else if (type == JSSessionModel.CONSTRUCTOR_EMPTY)
+ {
+ write(ASEmitterTokens.SEMICOLON);
+ }
+ }
+
+ @Override
+ protected void emitDefaultParameterCodeBlock(IFunctionNode node)
+ {
+ IParameterNode[] pnodes = node.getParameterNodes();
+ if (pnodes.length == 0)
+ return;
+
+ Map<Integer, IParameterNode> defaults = EmitterUtils
+ .getDefaults(pnodes);
+
+ if (defaults != null)
+ {
+ final StringBuilder code = new StringBuilder();
+
+ if (!EmitterUtils.hasBody(node))
+ {
+ indentPush();
+ write(JSFlexJSEmitterTokens.INDENT);
+ }
+
+ List<IParameterNode> parameters = new ArrayList<IParameterNode>(
+ defaults.values());
+
+ for (int i = 0, n = parameters.size(); i < n; i++)
+ {
+ IParameterNode pnode = parameters.get(i);
+
+ if (pnode != null)
+ {
+ code.setLength(0);
+
+ /* x = typeof y !== 'undefined' ? y : z;\n */
+ code.append(pnode.getName());
+ code.append(ASEmitterTokens.SPACE.getToken());
+ code.append(ASEmitterTokens.EQUAL.getToken());
+ code.append(ASEmitterTokens.SPACE.getToken());
+ code.append(ASEmitterTokens.TYPEOF.getToken());
+ code.append(ASEmitterTokens.SPACE.getToken());
+ code.append(pnode.getName());
+ code.append(ASEmitterTokens.SPACE.getToken());
+ code.append(ASEmitterTokens.STRICT_NOT_EQUAL.getToken());
+ code.append(ASEmitterTokens.SPACE.getToken());
+ code.append(ASEmitterTokens.SINGLE_QUOTE.getToken());
+ code.append(ASEmitterTokens.UNDEFINED.getToken());
+ code.append(ASEmitterTokens.SINGLE_QUOTE.getToken());
+ code.append(ASEmitterTokens.SPACE.getToken());
+ code.append(ASEmitterTokens.TERNARY.getToken());
+ code.append(ASEmitterTokens.SPACE.getToken());
+ code.append(pnode.getName());
+ code.append(ASEmitterTokens.SPACE.getToken());
+ code.append(ASEmitterTokens.COLON.getToken());
+ code.append(ASEmitterTokens.SPACE.getToken());
+ code.append(pnode.getDefaultValue());
+ code.append(ASEmitterTokens.SEMICOLON.getToken());
+
+ write(code.toString());
+
+ if (i == n - 1 && !EmitterUtils.hasBody(node))
+ indentPop();
+
+ writeNewline();
+ }
+ }
+ }
+ }
+
+ @Override
+ public void emitBinaryOperator(IBinaryOperatorNode node)
+ {
+ ASTNodeID id = node.getNodeID();
+ if (id == ASTNodeID.Op_InID || id == ASTNodeID.Op_LogicalAndAssignID
+ || id == ASTNodeID.Op_LogicalOrAssignID)
+ {
+ super.emitBinaryOperator(node);
+ }
+ else if (id == ASTNodeID.Op_IsID || id == ASTNodeID.Op_AsID)
+ {
+ emitIsAs(node.getLeftOperandNode(), node.getRightOperandNode(), id,
+ false);
+ }
+ else if (id == ASTNodeID.Op_InstanceOfID)
+ {
+ getWalker().walk(node.getLeftOperandNode());
+
+ write(ASEmitterTokens.SPACE);
+ writeToken(ASEmitterTokens.INSTANCEOF);
+
+ IDefinition dnode = (node.getRightOperandNode()).resolve(project);
+ if (dnode != null)
+ write(parseQualifiedName(dnode));
+ else
+ getWalker().walk(node.getRightOperandNode());
+ }
+ else
+ {
+ IExpressionNode leftSide = node.getLeftOperandNode();
+
+ IExpressionNode property = null;
+ int leftSideChildCount = leftSide.getChildCount();
+ if (leftSideChildCount > 0)
+ {
+ IASNode childNode = leftSide.getChild(leftSideChildCount - 1);
+ if (childNode instanceof IExpressionNode)
+ property = (IExpressionNode) childNode;
+ else
+ property = leftSide;
+ }
+ else
+ property = leftSide;
+
+ IDefinition def = null;
+ if (property instanceof IIdentifierNode)
+ def = ((IIdentifierNode) property).resolve(getWalker()
+ .getProject());
+
+ boolean isSuper = false;
+ if (leftSide.getNodeID() == ASTNodeID.MemberAccessExpressionID)
+ {
+ IASNode cnode = leftSide.getChild(0);
+ ASTNodeID cId = cnode.getNodeID();
+
+ isSuper = cId == ASTNodeID.SuperID;
+ }
+
+ String op = node.getOperator().getOperatorText();
+ boolean isAssignment = !(op.contains("==") || !op.contains("="));
+
+ if (def instanceof AccessorDefinition && isAssignment)
+ {
+ getWalker().walk(leftSide);
+ }
+ else if (isSuper)
+ {
+ emitSuperCall(node, "");
+ }
+ else
+ {
+ if (ASNodeUtils.hasParenOpen(node))
+ write(ASEmitterTokens.PAREN_OPEN);
+
+ getWalker().walk(leftSide);
+
+ if (node.getNodeID() != ASTNodeID.Op_CommaID)
+ write(ASEmitterTokens.SPACE);
+
+ writeToken(node.getOperator().getOperatorText());
+
+ getWalker().walk(node.getRightOperandNode());
+
+ if (ASNodeUtils.hasParenClose(node))
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+ }
+ }
+
+ private void emitIsAs(IExpressionNode left, IExpressionNode right,
+ ASTNodeID id, boolean coercion)
+ {
+ write(JSFlexJSEmitterTokens.LANGUAGE_QNAME);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ if (id == ASTNodeID.Op_IsID)
+ write(ASEmitterTokens.IS);
+ else
+ write(ASEmitterTokens.AS);
+ write(ASEmitterTokens.PAREN_OPEN);
+ getWalker().walk(left);
+ writeToken(ASEmitterTokens.COMMA);
+
+ IDefinition dnode = (right).resolve(project);
+ if (dnode != null)
+ write(parseQualifiedName(dnode));
+ else
+ getWalker().walk(right);
+
+ if (coercion)
+ {
+ writeToken(ASEmitterTokens.COMMA);
+ write(ASEmitterTokens.TRUE);
+ }
+
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+
+ @Override
+ public void emitMemberAccessExpression(IMemberAccessExpressionNode node)
+ {
+ IASNode leftNode = node.getLeftOperandNode();
+ IASNode rightNode = node.getRightOperandNode();
+
+ if (project == null)
+ project = getWalker().getProject();
+
+ IDefinition def = node.resolve(project);
+ boolean isStatic = false;
+ if (def != null && def.isStatic())
+ isStatic = true;
+
+ boolean continueWalk = true;
+ if (!isStatic)
+ {
+ if (!(leftNode instanceof ILanguageIdentifierNode && ((ILanguageIdentifierNode) leftNode)
+ .getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.THIS))
+ {
+ if (rightNode instanceof UnaryOperatorAtNode)
+ {
+ // ToDo (erikdebruin): properly handle E4X
+
+ write(ASEmitterTokens.THIS);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ getWalker().walk(node.getLeftOperandNode());
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write("E4XOperator");
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ continueWalk = false;
+ }
+ else if (node.getNodeID() == ASTNodeID.Op_DescendantsID)
+ {
+ // ToDo (erikdebruin): properly handle E4X
+
+ write(ASEmitterTokens.THIS);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ getWalker().walk(node.getLeftOperandNode());
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write("E4XSelector");
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ continueWalk = false;
+ }
+ else if (leftNode.getNodeID() != ASTNodeID.SuperID)
+ {
+ getWalker().walk(node.getLeftOperandNode());
+ write(node.getOperator().getOperatorText());
+ }
+ }
+ else
+ {
+ write(ASEmitterTokens.THIS);
+ write(node.getOperator().getOperatorText());
+ }
+
+ }
+
+ if (continueWalk)
+ getWalker().walk(node.getRightOperandNode());
+ }
+
+ private static ITypeDefinition getTypeDefinition(IDefinitionNode node)
+ {
+ ITypeNode tnode = (ITypeNode) node.getAncestorOfType(ITypeNode.class);
+ return (ITypeDefinition) tnode.getDefinition();
+ }
+
+ private static IClassDefinition getSuperClassDefinition(
+ IDefinitionNode node, ICompilerProject project)
+ {
+ IClassDefinition parent = (IClassDefinition) node.getDefinition()
+ .getParent();
+ IClassDefinition superClass = parent.resolveBaseClass(project);
+ return superClass;
+ }
+
+ @Override
+ protected void emitObjectDefineProperty(IAccessorNode node)
+ {
+ FunctionNode fn = (FunctionNode) node;
+ fn.parseFunctionBody(getProblems());
+
+ IFunctionDefinition definition = node.getDefinition();
+ ITypeDefinition type = (ITypeDefinition) definition.getParent();
+
+ // ToDo (erikdebruin): add VF2JS conditional -> only use check during full SDK compilation
+ if (type == null)
+ return;
+
+ if (project == null)
+ project = getWalker().getProject();
+
+ getDocEmitter().emitMethodDoc(fn, project);
+ write(parseQualifiedName(type));
+ if (!node.hasModifier(ASModifier.STATIC))
+ {
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(JSEmitterTokens.PROTOTYPE);
+ }
+
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ writeGetSetPrefix(node instanceof IGetterNode);
+ writeToken(node.getName());
+ writeToken(ASEmitterTokens.EQUAL);
+ write(ASEmitterTokens.FUNCTION);
+ emitParameters(node.getParametersContainerNode());
+ //writeNewline();
+ emitMethodScope(node.getScopedNode());
+ }
+
+ private void writeGetSetPrefix(boolean isGet)
+ {
+ if (isGet)
+ write(ASEmitterTokens.GET);
+ else
+ write(ASEmitterTokens.SET);
+ write("_");
+ }
+
+ @Override
+ public IJSGoogDocEmitter getDocEmitter()
+ {
+ return new JSVF2JSDocEmitter(this);
+ }
+
+ @Override
+ public void emitPackageHeader(IPackageDefinition definition)
+ {
+ IASScope containedScope = definition.getContainedScope();
+ ITypeDefinition type = findType(containedScope.getAllLocalDefinitions());
+ if (type == null)
+ return;
+
+ writeNewline("/**");
+ writeNewline(" * " + parseQualifiedName(type));
+ writeNewline(" *");
+ writeNewline(" * @fileoverview");
+ writeNewline(" *");
+ writeNewline(" * @suppress {checkTypes}");
+ writeNewline(" */");
+ writeNewline();
+
+ /* goog.provide('x');\n\n */
+ write(JSGoogEmitterTokens.GOOG_PROVIDE);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(parseQualifiedName(type));
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ writeNewline(ASEmitterTokens.SEMICOLON);
+ writeNewline();
+ }
+
+ @Override
+ public void emitPackageHeaderContents(IPackageDefinition definition)
+ {
+ PackageScope containedScope = (PackageScope) definition
+ .getContainedScope();
+
+ ITypeDefinition type = findType(containedScope.getAllLocalDefinitions());
+ if (type == null)
+ return;
+
+ if (project == null)
+ project = getWalker().getProject();
+
+ FlexJSProject flexProject = (FlexJSProject) project;
+ ASProjectScope projectScope = flexProject.getScope();
+ ICompilationUnit cu = projectScope
+ .getCompilationUnitForDefinition(type);
+ ArrayList<String> requiresList = flexProject.getRequires(cu);
+ ArrayList<String> interfacesList = flexProject.getInterfaces(cu);
+
+ String cname = parseQualifiedName(type);
+ ArrayList<String> writtenInstances = new ArrayList<String>();
+ writtenInstances.add(cname); // make sure we don't add ourselves
+
+ boolean emitsRequires = false;
+ if (requiresList != null)
+ {
+ Collections.sort(requiresList);
+ for (String imp : requiresList)
+ {
+ if (imp.indexOf(JSGoogEmitterTokens.AS3.getToken()) != -1)
+ continue;
+
+ if (imp.equals(cname))
+ continue;
+
+ if (NativeUtils.isNative(imp))
+ continue;
+
+ if (writtenInstances.indexOf(imp) == -1)
+ {
+
+ /* goog.require('x');\n */
+ write(JSGoogEmitterTokens.GOOG_REQUIRE);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(imp);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ writeNewline(ASEmitterTokens.SEMICOLON);
+
+ writtenInstances.add(imp);
+
+ emitsRequires = true;
+ }
+ }
+ }
+
+ boolean emitsInterfaces = false;
+ if (interfacesList != null)
+ {
+ Collections.sort(interfacesList);
+ for (String imp : interfacesList)
+ {
+ write(JSGoogEmitterTokens.GOOG_REQUIRE);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(imp);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ writeNewline(ASEmitterTokens.SEMICOLON);
+
+ emitsInterfaces = true;
+ }
+ }
+
+ // erikdebruin: Add missing language feature support, with e.g. 'is' and
+ // 'as' operators. We don't need to worry about requiring
+ // this in every project: ADVANCED_OPTIMISATIONS will NOT
+ // include any of the code if it is not used in the project.
+ boolean isMainCU = flexProject.mainCU != null
+ && cu.getName().equals(flexProject.mainCU.getName());
+ if (isMainCU)
+ {
+ write(JSGoogEmitterTokens.GOOG_REQUIRE);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(JSFlexJSEmitterTokens.LANGUAGE_QNAME);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ writeNewline(ASEmitterTokens.SEMICOLON);
+ }
+
+ if (emitsRequires || emitsInterfaces || isMainCU)
+ {
+ writeNewline();
+ }
+
+ writeNewline();
+ writeNewline();
+ }
+
+ @Override
+ public void emitPackageFooter(IPackageDefinition definition)
+ {
+ IASScope containedScope = definition.getContainedScope();
+ ITypeDefinition type = findType(containedScope.getAllLocalDefinitions());
+ if (type == null)
+ return;
+
+ ITypeNode tnode = findTypeNode(definition.getNode());
+ if (tnode != null)
+ {
+ /*
+ * Metadata
+ *
+ * @type {Object.<string, Array.<Object>>}
+ */
+ writeNewline();
+ writeNewline();
+ writeNewline();
+ getDocEmitter().begin();
+ writeNewline(" * Metadata");
+ writeNewline(" *");
+ writeNewline(" * @type {Object.<string, Array.<Object>>}");
+ getDocEmitter().end();
+
+ // a.B.prototype.AFJS_CLASS_INFO = { };
+ write(parseQualifiedName(type));
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(JSEmitterTokens.PROTOTYPE);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ writeToken(JSFlexJSEmitterTokens.FLEXJS_CLASS_INFO);
+ writeToken(ASEmitterTokens.EQUAL);
+ writeToken(ASEmitterTokens.BLOCK_OPEN);
+
+ // names: [{ name: '', qName: '' }]
+ write(JSFlexJSEmitterTokens.NAMES);
+ writeToken(ASEmitterTokens.COLON);
+ write(ASEmitterTokens.SQUARE_OPEN);
+ writeToken(ASEmitterTokens.BLOCK_OPEN);
+ write(JSFlexJSEmitterTokens.NAME);
+ writeToken(ASEmitterTokens.COLON);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(tnode.getName());
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ writeToken(ASEmitterTokens.COMMA);
+ write(JSFlexJSEmitterTokens.QNAME);
+ writeToken(ASEmitterTokens.COLON);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(parseQualifiedName(tnode));
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ write(ASEmitterTokens.SQUARE_CLOSE);
+
+ IExpressionNode[] enodes;
+ if (tnode instanceof IClassNode)
+ enodes = ((IClassNode) tnode).getImplementedInterfaceNodes();
+ else
+ enodes = ((IInterfaceNode) tnode).getExtendedInterfaceNodes();
+
+ if (enodes.length > 0)
+ {
+ writeToken(ASEmitterTokens.COMMA);
+
+ // interfaces: [a.IC, a.ID]
+ write(JSFlexJSEmitterTokens.INTERFACES);
+ writeToken(ASEmitterTokens.COLON);
+ write(ASEmitterTokens.SQUARE_OPEN);
+ int i = 0;
+ for (IExpressionNode enode : enodes)
+ {
+ write(parseQualifiedName(enode.resolve(project)));
+ if (i < enodes.length - 1)
+ writeToken(ASEmitterTokens.COMMA);
+ i++;
+ }
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ }
+
+ write(ASEmitterTokens.SPACE);
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ writeNewline(ASEmitterTokens.SEMICOLON);
+ }
+ }
+
+ private int foreachLoopCounter = 0;
+
+ @Override
+ public void emitForEachLoop(IForLoopNode node)
+ {
+ IBinaryOperatorNode bnode = (IBinaryOperatorNode) node
+ .getConditionalsContainerNode().getChild(0);
+ IASNode childNode = bnode.getChild(0);
+
+ String iterName = "foreachiter"
+ + new Integer(foreachLoopCounter).toString();
+ foreachLoopCounter++;
+
+ write(ASEmitterTokens.FOR);
+ write(ASEmitterTokens.SPACE);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.VAR);
+ write(ASEmitterTokens.SPACE);
+ write(iterName);
+ write(ASEmitterTokens.SPACE);
+ write(ASEmitterTokens.IN);
+ write(ASEmitterTokens.SPACE);
+ getWalker().walk(bnode.getChild(1));
+ writeToken(ASEmitterTokens.PAREN_CLOSE);
+ writeNewline();
+ write(ASEmitterTokens.BLOCK_OPEN);
+ writeNewline();
+ if (childNode instanceof IVariableExpressionNode)
+ {
+ write(ASEmitterTokens.VAR);
+ write(ASEmitterTokens.SPACE);
+ write(((IVariableNode) childNode.getChild(0)).getName());
+ }
+ else
+ write(((IIdentifierNode) childNode).getName());
+ write(ASEmitterTokens.SPACE);
+ write(ASEmitterTokens.EQUAL);
+ write(ASEmitterTokens.SPACE);
+ getWalker().walk(bnode.getChild(1));
+ write(ASEmitterTokens.SQUARE_OPEN);
+ write(iterName);
+ write(ASEmitterTokens.SQUARE_CLOSE);
+ write(ASEmitterTokens.SEMICOLON);
+ writeNewline();
+ getWalker().walk(node.getStatementContentsNode());
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ writeNewline();
+
+ }
+
+ /*
+ @Override
+ public void emitForEachLoop(IForLoopNode node)
+ {
+ IContainerNode xnode = (IContainerNode) node.getChild(1);
+ IBinaryOperatorNode bnode = (IBinaryOperatorNode) node
+ .getConditionalsContainerNode().getChild(0);
+ IASNode childNode = bnode.getChild(0);
+
+ write(ASEmitterTokens.TRY);
+ write(ASEmitterTokens.BLOCK_OPEN);
+ writeNewline();
+
+ write(JSGoogEmitterTokens.GOOG_ARRAY_FOREACH);
+ write(ASEmitterTokens.PAREN_OPEN);
+ getWalker().walk(bnode.getChild(1));
+ writeToken(ASEmitterTokens.COMMA);
+ writeToken(ASEmitterTokens.FUNCTION);
+ write(ASEmitterTokens.PAREN_OPEN);
+ if (childNode instanceof IVariableExpressionNode)
+ write(((IVariableNode) childNode.getChild(0)).getName());
+ else
+ write(((IIdentifierNode) childNode).getName());
+ writeToken(ASEmitterTokens.PAREN_CLOSE);
+ if (isImplicit(xnode))
+ write(ASEmitterTokens.BLOCK_OPEN);
+ getWalker().walk(node.getStatementContentsNode());
+ if (isImplicit(xnode))
+ {
+ writeNewline();
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ }
+ write(ASEmitterTokens.PAREN_CLOSE);
+ writeNewline();
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ writeNewline();
+ write(ASEmitterTokens.CATCH);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write("foreachbreakerror");
+ write(ASEmitterTokens.PAREN_CLOSE);
+ write(ASEmitterTokens.SPACE);
+ write(ASEmitterTokens.BLOCK_OPEN);
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ writeNewline();
+
+ }
+
+ @Override
+ public void emitIterationFlow(IIterationFlowNode node)
+ {
+ // look for break in foreach and throw error instead
+ if (node.getKind() == IIterationFlowNode.IterationFlowKind.BREAK)
+ {
+ IASNode pNode = node.getParent();
+ while (pNode != null)
+ {
+ ASTNodeID id = pNode.getNodeID();
+ if (id == ASTNodeID.ForEachLoopID)
+ {
+ write(ASEmitterTokens.THROW);
+ write(ASEmitterTokens.SPACE);
+ write(ASEmitterTokens.NEW);
+ write(ASEmitterTokens.SPACE);
+ write(JSGoogEmitterTokens.ERROR);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ write(ASEmitterTokens.SEMICOLON);
+ return;
+ }
+ else if (id == ASTNodeID.ForLoopID ||
+ id == ASTNodeID.DoWhileLoopID ||
+ id == ASTNodeID.WhileLoopID)
+ break;
+ pNode = pNode.getParent();
+ }
+ }
+ write(node.getKind().toString().toLowerCase());
+ IIdentifierNode lnode = node.getLabelNode();
+ if (lnode != null)
+ {
+ write(ASEmitterTokens.SPACE);
+ getWalker().walk(lnode);
+ }
+ }
+ */
+
+ @Override
+ public void emitTypedExpression(ITypedExpressionNode node)
+ {
+ write(JSGoogEmitterTokens.ARRAY);
+ }
+
+ @Override
+ public void emitLiteral(ILiteralNode node)
+ {
+ boolean isWritten = false;
+
+ String s = node.getValue(true);
+ if (!(node instanceof RegExpLiteralNode))
+ {
+ if (node.getLiteralType() == LiteralType.XML)
+ {
+ // ToDo (erikdebruin): VF2JS -> handle XML output properly...
+
+ write("'" + s + "'");
+
+ isWritten = true;
+ }
+ s = s.replaceAll("\n", "__NEWLINE_PLACEHOLDER__");
+ s = s.replaceAll("\r", "__CR_PLACEHOLDER__");
+ s = s.replaceAll("\t", "__TAB_PLACEHOLDER__");
+ s = s.replaceAll("\f", "__FORMFEED_PLACEHOLDER__");
+ s = s.replaceAll("\b", "__BACKSPACE_PLACEHOLDER__");
+ s = s.replaceAll("\\\\\"", "__QUOTE_PLACEHOLDER__");
+ s = s.replaceAll("\\\\", "__ESCAPE_PLACEHOLDER__");
+ //s = "\'" + s.replaceAll("\'", "\\\\\'") + "\'";
+ s = s.replaceAll("__ESCAPE_PLACEHOLDER__", "\\\\\\\\");
+ s = s.replaceAll("__QUOTE_PLACEHOLDER__", "\\\\\"");
+ s = s.replaceAll("__BACKSPACE_PLACEHOLDER__", "\\\\b");
+ s = s.replaceAll("__FORMFEED_PLACEHOLDER__", "\\\\f");
+ s = s.replaceAll("__TAB_PLACEHOLDER__", "\\\\t");
+ s = s.replaceAll("__CR_PLACEHOLDER__", "\\\\r");
+ s = s.replaceAll("__NEWLINE_PLACEHOLDER__", "\\\\n");
+
+ Character c = s.charAt(0);
+ if (c.equals('"'))
+ {
+ s = s.substring(1, s.length() - 1);
+ s = s.replaceAll("\"", "\\\\\"");
+ s = "\"" + s + "\"";
+ }
+ if (s.length() == 3)
+ {
+ c = s.charAt(1);
+ if (c.equals('\\'))
+ {
+ s = "\"\\\\\"";
+ }
+ }
+ }
+
+ if (!isWritten)
+ {
+ write(s);
+ }
+ }
+
+ @Override
+ public void emitE4XFilter(IMemberAccessExpressionNode node)
+ {
+ // ToDo (erikdebruin): implement E4X replacement !?!
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write("E4XFilter");
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ }
+
+ @Override
+ public void emitContainer(IContainerNode node)
+ {
+ int nodeCount = node.getChildCount();
+ for (int i = 0; i < nodeCount; i++)
+ {
+ getWalker().walk(node.getChild(i));
+
+ if (i < nodeCount - 1)
+ writeToken(ASEmitterTokens.COMMA);
+ }
+ }
+
+ private String parseQualifiedName(IDefinitionNode def)
+ {
+ return parseQualifiedNameString(def.getQualifiedName());
+ }
+
+ private String parseQualifiedName(IDefinition def)
+ {
+ return parseQualifiedNameString(def.getQualifiedName());
+ }
+
+ private String parseQualifiedNameString(String qNameString)
+ {
+ // ToDo (erikdebruin): Ugly hacks for VF2JS ...
+ if (qNameString.equals(IASLanguageConstants._int))
+ {
+ qNameString = qNameString.toUpperCase();
+ }
+
+ if (qNameString.equals("byte"))
+ {
+ qNameString = "$" + qNameString;
+ }
+
+ return qNameString;
+ }
+
+}