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:35 UTC
[43/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/amd/ExportWriter.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/amd/ExportWriter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/amd/ExportWriter.java
new file mode 100644
index 0000000..92244db
--- /dev/null
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/amd/ExportWriter.java
@@ -0,0 +1,230 @@
+/*
+ *
+ * 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.amd;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.flex.compiler.definitions.ITypeDefinition;
+
+/**
+ * @author Michael Schmalle
+ */
+public class ExportWriter
+{
+ private static final String CLASSES_TYPES = "__CLASSES$TYPES__";
+
+ private static final String CLASSES_STRINGS = "__CLASSES$STRINGS__";
+
+ private static final String RUNTIME_TYPES = "__RUNTIME$TYPES__";
+
+ private static final String RUNTIME_STRINGS = "__RUNTIME$STRINGS__";
+
+ private final JSAMDEmitter emitter;
+
+ private List<Dependency> runtime = new ArrayList<Dependency>();
+
+ private List<Dependency> types = new ArrayList<Dependency>();
+
+ public ExportWriter(JSAMDEmitter emitter)
+ {
+ this.emitter = emitter;
+ }
+
+ public void queueExports(ITypeDefinition type, boolean outputString)
+ {
+ if (outputString)
+ {
+ emitter.write("[");
+ emitter.write("\"exports\"");
+ }
+
+ emitter.write(", ");
+
+ if (outputString)
+ emitter.write(RUNTIME_STRINGS);
+ else
+ emitter.write(RUNTIME_TYPES);
+
+ //emitter.write(", ");
+
+ if (outputString)
+ emitter.write(CLASSES_STRINGS);
+ else
+ emitter.write(CLASSES_TYPES);
+
+ if (outputString)
+ {
+ emitter.write("]");
+ }
+ }
+
+ public void writeExports(ITypeDefinition type, boolean outputString)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ int i = 0;
+ int len = runtime.size();
+
+ for (Dependency dependency : runtime)
+ {
+ sb.append(dependency.output(outputString, "runtime", outputString));
+
+ if (i < len - 1)
+ sb.append(", ");
+ i++;
+ }
+
+ if (outputString)
+ {
+ int start = emitter.builder().indexOf(RUNTIME_STRINGS);
+ int end = start + RUNTIME_STRINGS.length();
+ emitter.builder().replace(start, end, sb.toString());
+ }
+ else
+ {
+ int start = emitter.builder().indexOf(RUNTIME_TYPES);
+ int end = start + RUNTIME_TYPES.length();
+ emitter.builder().replace(start, end, sb.toString());
+ }
+
+ sb = new StringBuilder();
+
+ i = 0;
+ len = types.size();
+ if (len > 0)
+ sb.append(", "); // trailing comma
+
+ for (Dependency dependency : types)
+ {
+ sb.append(dependency.output(outputString, "classes", outputString));
+
+ if (i < len - 1)
+ sb.append(", ");
+ i++;
+ }
+
+ if (outputString)
+ {
+ int start = emitter.builder().indexOf(CLASSES_STRINGS);
+ int end = start + CLASSES_STRINGS.length();
+ emitter.builder().replace(start, end, sb.toString());
+ }
+ else
+ {
+ int start = emitter.builder().indexOf(CLASSES_TYPES);
+ int end = start + CLASSES_TYPES.length();
+ emitter.builder().replace(start, end, sb.toString());
+ }
+ }
+
+ void addImports(ITypeDefinition type)
+ {
+ Collection<String> imports = new ArrayList<String>();
+ type.getContainedScope().getScopeNode().getAllImports(imports);
+ for (String imp : imports)
+ {
+ String name = toBaseName(imp);
+ if (!isExcludedImport(imp))
+ addDependency(name, imp, false, false);
+ }
+ }
+
+ void addFrameworkDependencies()
+ {
+ runtime.add(new Dependency("AS3", "AS3", false, false));
+ }
+
+ protected boolean isExcludedImport(String imp)
+ {
+ return imp.startsWith("__AS3__");
+ }
+
+ public void addDependency(String baseName, String qualifiedName,
+ boolean isNative, boolean isPlugin)
+ {
+ types.add(new Dependency(baseName, qualifiedName, isNative, isPlugin));
+ }
+
+ static String toBaseName(String name)
+ {
+ if (!name.contains("."))
+ return name;
+ final String basename = name.substring(name.lastIndexOf(".") + 1);
+ return basename;
+ }
+
+ static class Dependency
+ {
+ private final String baseName;
+
+ private final String qualifiedName;
+
+ public String getQualifiedName()
+ {
+ return qualifiedName;
+ }
+
+ private final boolean isNative;
+
+ public boolean isNative()
+ {
+ return isNative;
+ }
+
+ @SuppressWarnings("unused")
+ private final boolean isPlugin;
+
+ public Dependency(String baseName, String qualifiedName,
+ boolean isNative, boolean isPlugin)
+ {
+ this.baseName = baseName;
+ this.qualifiedName = qualifiedName;
+ this.isNative = isNative;
+ this.isPlugin = isPlugin;
+ }
+
+ @Override
+ public String toString()
+ {
+ return qualifiedName; // TODO (mschmalle|AMD) native
+ }
+
+ public String output(boolean outputString, String base,
+ boolean qualified)
+ {
+ StringBuilder sb = new StringBuilder();
+ if (outputString)
+ {
+ sb.append("\"" + base + "/"
+ + qualifiedName.replaceAll("\\.", "/") + "\"");
+ }
+ else
+ {
+ if (qualified)
+ sb.append(qualifiedName);
+ else
+ sb.append(baseName);
+ }
+ return sb.toString();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/c3dce49f/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/amd/JSAMDDocEmitter.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/amd/JSAMDDocEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/amd/JSAMDDocEmitter.java
new file mode 100644
index 0000000..c79dd3d
--- /dev/null
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/amd/JSAMDDocEmitter.java
@@ -0,0 +1,37 @@
+/*
+ *
+ * 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.amd;
+
+import org.apache.flex.compiler.codegen.js.IJSEmitter;
+import org.apache.flex.compiler.codegen.js.amd.IJSAMDDocEmitter;
+import org.apache.flex.compiler.internal.codegen.js.JSDocEmitter;
+
+/**
+ * @author Michael Schmalle
+ */
+public class JSAMDDocEmitter extends JSDocEmitter implements IJSAMDDocEmitter
+{
+
+ public JSAMDDocEmitter(IJSEmitter emitter)
+ {
+ super(emitter);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/c3dce49f/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/amd/JSAMDEmitter.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/amd/JSAMDEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/amd/JSAMDEmitter.java
new file mode 100644
index 0000000..fd19e42
--- /dev/null
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/amd/JSAMDEmitter.java
@@ -0,0 +1,971 @@
+/*
+ *
+ * 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.amd;
+
+import java.io.FilterWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.flex.compiler.codegen.js.amd.IJSAMDDocEmitter;
+import org.apache.flex.compiler.codegen.js.amd.IJSAMDEmitter;
+import org.apache.flex.compiler.definitions.IAccessorDefinition;
+import org.apache.flex.compiler.definitions.IClassDefinition;
+import org.apache.flex.compiler.definitions.IConstantDefinition;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.definitions.IFunctionDefinition;
+import org.apache.flex.compiler.definitions.IInterfaceDefinition;
+import org.apache.flex.compiler.definitions.IPackageDefinition;
+import org.apache.flex.compiler.definitions.ITypeDefinition;
+import org.apache.flex.compiler.definitions.IVariableDefinition;
+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.JSEmitter;
+import org.apache.flex.compiler.internal.codegen.js.JSEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.utils.EmitterUtils;
+import org.apache.flex.compiler.internal.definitions.ClassTraitsDefinition;
+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.IdentifierNode;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+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.IBlockNode;
+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.IExpressionNode;
+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.ILanguageIdentifierNode;
+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.IVariableNode;
+import org.apache.flex.compiler.utils.NativeUtils;
+
+/**
+ * Concrete implementation of the 'AMD' JavaScript production.
+ *
+ * @author Michael Schmalle
+ */
+public class JSAMDEmitter extends JSEmitter implements IJSAMDEmitter
+{
+
+ private Map<String, IDefinitionNode> foundAccessors = new HashMap<String, IDefinitionNode>();
+
+ private int inheritenceLevel = -1;
+
+ private ExportWriter exportWriter;
+
+ private boolean initializingFieldsInConstructor;
+
+ private List<IDefinition> baseClassCalls = new ArrayList<IDefinition>();
+
+ StringBuilder builder()
+ {
+ return getBuilder();
+ }
+
+ IJSAMDDocEmitter getDoc()
+ {
+ return (IJSAMDDocEmitter) getDocEmitter();
+ }
+
+ public JSAMDEmitter(FilterWriter out)
+ {
+ super(out);
+
+ exportWriter = new ExportWriter(this);
+ }
+
+ @Override
+ public void emitPackageHeader(IPackageDefinition definition)
+ {
+ // TODO (mschmalle|AMD) this is a hack but I know no other way to do replacements in a Writer
+ setBufferWrite(true);
+
+ write(JSAMDEmitterTokens.DEFINE);
+ write(ASEmitterTokens.PAREN_OPEN);
+
+ IASScope containedScope = definition.getContainedScope();
+ ITypeDefinition type = findType(containedScope.getAllLocalDefinitions());
+ if (type == null)
+ return;
+
+ exportWriter.addFrameworkDependencies();
+ exportWriter.addImports(type);
+
+ exportWriter.queueExports(type, true);
+
+ writeToken(ASEmitterTokens.COMMA);
+ }
+
+ @Override
+ public void emitPackageHeaderContents(IPackageDefinition definition)
+ {
+ // nothing
+ }
+
+ @Override
+ public void emitPackageContents(IPackageDefinition definition)
+ {
+ IASScope containedScope = definition.getContainedScope();
+ ITypeDefinition type = findType(containedScope.getAllLocalDefinitions());
+ if (type == null)
+ return;
+
+ write("function($exports");
+
+ exportWriter.queueExports(type, false);
+
+ write(") {");
+ indentPush();
+ writeNewline();
+ write("\"use strict\"; ");
+ writeNewline();
+
+ ITypeNode tnode = findTypeNode(definition.getNode());
+ if (tnode != null)
+ {
+ getWalker().walk(tnode); // IClassNode | IInterfaceNode
+ }
+
+ indentPop();
+ writeNewline();
+ write("}"); // end returned function
+ }
+
+ @Override
+ public void emitPackageFooter(IPackageDefinition definition)
+ {
+ IASScope containedScope = definition.getContainedScope();
+ ITypeDefinition type = findType(containedScope.getAllLocalDefinitions());
+ if (type == null)
+ return;
+
+ exportWriter.writeExports(type, true);
+ exportWriter.writeExports(type, false);
+
+ write(");"); // end define()
+
+ // flush the buffer, writes the builder to out
+ flushBuilder();
+ }
+
+ private void emitConstructor(IFunctionNode node)
+ {
+ FunctionNode fn = (FunctionNode) node;
+ fn.parseFunctionBody(getProblems());
+
+ //IFunctionDefinition definition = node.getDefinition();
+
+ write("function ");
+ write(node.getName());
+ emitParameters(node.getParametersContainerNode());
+ if (!isImplicit((IContainerNode) node.getScopedNode()))
+ {
+ emitMethodScope(node.getScopedNode());
+ }
+ else
+ {
+ // we have a synthesized constructor, implict
+ }
+ }
+
+ @Override
+ public void emitInterface(IInterfaceNode node)
+ {
+ final IInterfaceDefinition definition = node.getDefinition();
+ final String interfaceName = definition.getBaseName();
+
+ write("AS3.interface_($exports, {");
+ indentPush();
+ writeNewline();
+
+ write("package_: \"");
+ write(definition.getPackageName());
+ write("\",");
+ writeNewline();
+
+ write("interface_: \"");
+ write(interfaceName);
+ write("\"");
+
+ IReference[] references = definition.getExtendedInterfaceReferences();
+ final int len = references.length;
+ if (len > 0)
+ {
+ writeNewline();
+ write("extends_: [");
+ indentPush();
+ writeNewline();
+ int i = 0;
+ for (IReference reference : references)
+ {
+ write(reference.getName());
+ if (i < len - 1)
+ {
+ write(",");
+ writeNewline();
+ }
+ i++;
+ }
+ indentPop();
+ writeNewline();
+ write("]");
+ }
+
+ indentPop();
+ writeNewline();
+ write("});"); // end compilation unit
+ }
+
+ @Override
+ public void emitClass(IClassNode node)
+ {
+ //ICompilerProject project = getWalker().getProject();
+
+ IClassDefinition definition = node.getDefinition();
+ getModel().setCurrentClass(definition);
+
+ final String className = definition.getBaseName();
+
+ write("AS3.compilationUnit($exports, function($primaryDeclaration){");
+ indentPush();
+ writeNewline();
+
+ // write constructor
+ emitConstructor((IFunctionNode) definition.getConstructor().getNode());
+ writeNewline();
+
+ // base class
+ IReference baseClassReference = definition.getBaseClassReference();
+ boolean hasSuper = baseClassReference != null
+ && !baseClassReference.getName().equals("Object");
+ if (hasSuper)
+ {
+ String baseName = baseClassReference.getName();
+ write("var Super = (" + baseName + "._ || " + baseName
+ + "._$get());");
+ writeNewline();
+ write("var super$ = Super.prototype;");
+ writeNewline();
+ }
+
+ write("$primaryDeclaration(AS3.class_({");
+ indentPush();
+ writeNewline();
+
+ // write out package
+ write("package_: \"" + definition.getPackageName() + "\",");
+ writeNewline();
+ // write class
+ write("class_: \"" + definition.getBaseName() + "\",");
+ writeNewline();
+ if (hasSuper)
+ {
+ write("extends_: Super,");
+ writeNewline();
+ }
+
+ IReference[] references = definition
+ .getImplementedInterfaceReferences();
+ int len = references.length;
+
+ // write implements
+ write("implements_:");
+ write(" [");
+
+ if (len > 0)
+ {
+ indentPush();
+ writeNewline();
+ }
+
+ int i = 0;
+ for (IReference reference : references)
+ {
+ write(reference.getName());
+ exportWriter.addDependency(reference.getName(),
+ reference.getDisplayString(), false, false);
+ if (i < len - 1)
+ {
+ write(",");
+ writeNewline();
+ }
+ i++;
+ }
+
+ if (len > 0)
+ {
+ indentPop();
+ writeNewline();
+ }
+
+ write("],");
+ writeNewline();
+
+ // write members
+ final IDefinitionNode[] members = node.getAllMemberNodes();
+
+ write("members: {");
+
+ indentPush();
+ writeNewline();
+
+ // constructor
+ write("constructor: " + className);
+ if (members.length > 0)
+ {
+ write(",");
+ writeNewline();
+ }
+
+ List<IDefinitionNode> instanceMembers = new ArrayList<IDefinitionNode>();
+ List<IDefinitionNode> staticMembers = new ArrayList<IDefinitionNode>();
+ List<IASNode> staticStatements = new ArrayList<IASNode>();
+
+ TempTools.fillInstanceMembers(members, instanceMembers);
+ TempTools.fillStaticMembers(members, staticMembers, true, false);
+ TempTools.fillStaticStatements(node, staticStatements, false);
+
+ len = instanceMembers.size();
+ i = 0;
+ for (IDefinitionNode mnode : instanceMembers)
+ {
+ if (mnode instanceof IAccessorNode)
+ {
+ if (foundAccessors.containsKey(mnode.getName()))
+ {
+ len--;
+ continue;
+ }
+
+ getWalker().walk(mnode);
+ }
+ else if (mnode instanceof IFunctionNode)
+ {
+ getWalker().walk(mnode);
+ }
+ else if (mnode instanceof IVariableNode)
+ {
+ getWalker().walk(mnode);
+ }
+ else
+ {
+ write(mnode.getName());
+ }
+
+ if (i < len - 1)
+ {
+ write(",");
+ writeNewline();
+ }
+ i++;
+ }
+
+ // base class super calls
+ len = baseClassCalls.size();
+ i = 0;
+ if (len > 0)
+ {
+ write(",");
+ writeNewline();
+ }
+
+ for (IDefinition baseCall : baseClassCalls)
+ {
+ write(baseCall.getBaseName() + "$" + inheritenceLevel + ": super$."
+ + baseCall.getBaseName());
+
+ if (i < len - 1)
+ {
+ write(",");
+ writeNewline();
+ }
+ }
+
+ // end members
+ indentPop();
+ writeNewline();
+ write("},");
+ writeNewline();
+
+ len = staticMembers.size();
+
+ write("staticMembers: {");
+
+ indentPush();
+ writeNewline();
+
+ i = 0;
+ for (IDefinitionNode mnode : staticMembers)
+ {
+ if (mnode instanceof IAccessorNode)
+ {
+ // TODO (mschmalle|AMD) havn't taken care of static accessors
+ if (foundAccessors.containsKey(mnode.getName()))
+ continue;
+
+ foundAccessors.put(mnode.getName(), mnode);
+
+ getWalker().walk(mnode);
+ }
+ else if (mnode instanceof IFunctionNode)
+ {
+ getWalker().walk(mnode);
+ }
+ else if (mnode instanceof IVariableNode)
+ {
+ getWalker().walk(mnode);
+ }
+
+ if (i < len - 1)
+ {
+ write(",");
+ writeNewline();
+ }
+ i++;
+ }
+ indentPop();
+ if (len > 0)
+ writeNewline();
+ write("}");
+
+ indentPop();
+ writeNewline();
+ write("}));");
+
+ // static statements
+ len = staticStatements.size();
+ if (len > 0)
+ writeNewline();
+
+ i = 0;
+ for (IASNode statement : staticStatements)
+ {
+ getWalker().walk(statement);
+ if (!(statement instanceof IBlockNode))
+ write(";");
+
+ if (i < len - 1)
+ writeNewline();
+
+ i++;
+ }
+
+ indentPop();
+ writeNewline();
+ write("});"); // end compilation unit
+
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitField(IVariableNode node)
+ {
+ IVariableDefinition definition = (IVariableDefinition) node
+ .getDefinition();
+
+ if (definition.isStatic())
+ {
+ IClassDefinition parent = (IClassDefinition) definition.getParent();
+ write(parent.getBaseName());
+ write(".");
+ write(definition.getBaseName());
+ write(" = ");
+ emitFieldInitialValue(node);
+ return;
+ }
+
+ String name = toPrivateName(definition);
+ write(name);
+ write(": ");
+ write("{");
+ indentPush();
+ writeNewline();
+ // field value
+ write("value:");
+ emitFieldInitialValue(node);
+ write(",");
+ writeNewline();
+ // writable
+ write("writable:");
+ write(!(definition instanceof IConstantDefinition) ? "true" : "false");
+ indentPop();
+ writeNewline();
+ write("}");
+ }
+
+ private void emitFieldInitialValue(IVariableNode node)
+ {
+ ICompilerProject project = getWalker().getProject();
+ IVariableDefinition definition = (IVariableDefinition) node
+ .getDefinition();
+
+ IExpressionNode valueNode = node.getAssignedValueNode();
+ if (valueNode != null)
+ getWalker().walk(valueNode);
+ else
+ write(TempTools.toInitialValue(definition, project));
+ }
+
+ @Override
+ public void emitGetAccessor(IGetterNode node)
+ {
+ if (foundAccessors.containsKey(node.getName()))
+ return;
+
+ foundAccessors.put(node.getName(), node);
+
+ ICompilerProject project = getWalker().getProject();
+ IAccessorDefinition getter = (IAccessorDefinition) node.getDefinition();
+ IAccessorDefinition setter = getter
+ .resolveCorrespondingAccessor(project);
+
+ emitGetterSetterPair(getter, setter);
+ }
+
+ @Override
+ public void emitSetAccessor(ISetterNode node)
+ {
+ if (foundAccessors.containsKey(node.getName()))
+ return;
+
+ foundAccessors.put(node.getName(), node);
+
+ ICompilerProject project = getWalker().getProject();
+ IAccessorDefinition setter = (IAccessorDefinition) node.getDefinition();
+ IAccessorDefinition getter = setter
+ .resolveCorrespondingAccessor(project);
+
+ emitGetterSetterPair(getter, setter);
+ }
+
+ private void emitGetterSetterPair(IAccessorDefinition getter,
+ IAccessorDefinition setter)
+ {
+ write(getter.getBaseName());
+ write(": {");
+ indentPush();
+ writeNewline();
+
+ if (getter != null)
+ {
+ emitAccessor("get", getter);
+ }
+ if (setter != null)
+ {
+ write(",");
+ writeNewline();
+ emitAccessor("set", setter);
+ }
+
+ indentPop();
+ writeNewline();
+ write("}");
+
+ }
+
+ protected void emitAccessor(String kind, IAccessorDefinition definition)
+ {
+ IFunctionNode fnode = definition.getFunctionNode();
+
+ FunctionNode fn = (FunctionNode) fnode;
+ fn.parseFunctionBody(new ArrayList<ICompilerProblem>());
+
+ write(kind + ": function ");
+ write(definition.getBaseName() + "$" + kind);
+ emitParameters(fnode.getParametersContainerNode());
+ emitMethodScope(fnode.getScopedNode());
+ }
+
+ @Override
+ public void emitMethod(IFunctionNode node)
+ {
+ if (node.isConstructor())
+ {
+ emitConstructor(node);
+ return;
+ }
+
+ FunctionNode fn = (FunctionNode) node;
+ fn.parseFunctionBody(new ArrayList<ICompilerProblem>());
+ IFunctionDefinition definition = node.getDefinition();
+
+ String name = toPrivateName(definition);
+ write(name);
+ write(":");
+ write(" function ");
+ write(node.getName());
+ emitParameters(node.getParametersContainerNode());
+ emitMethodScope(node.getScopedNode());
+ }
+
+ @Override
+ public void emitFunctionBlockHeader(IFunctionNode node)
+ {
+ IFunctionDefinition definition = node.getDefinition();
+
+ if (node.isConstructor())
+ {
+ initializingFieldsInConstructor = true;
+ IClassDefinition type = (IClassDefinition) definition
+ .getAncestorOfType(IClassDefinition.class);
+ // emit public fields init values
+ List<IVariableDefinition> fields = TempTools.getFields(type, true);
+ for (IVariableDefinition field : fields)
+ {
+ if (TempTools.isVariableAParameter(field,
+ definition.getParameters()))
+ continue;
+ write("this.");
+ write(field.getBaseName());
+ write(" = ");
+ emitFieldInitialValue((IVariableNode) field.getNode());
+ write(";");
+ writeNewline();
+ }
+ initializingFieldsInConstructor = false;
+ }
+
+ emitDefaultParameterCodeBlock(node);
+ }
+
+ private void emitDefaultParameterCodeBlock(IFunctionNode node)
+ {
+ // TODO (mschmalle|AMD) test for ... rest
+ // if default parameters exist, produce the init code
+ IParameterNode[] pnodes = node.getParameterNodes();
+ Map<Integer, IParameterNode> defaults = TempTools.getDefaults(pnodes);
+ if (pnodes.length == 0)
+ return;
+
+ if (defaults != null)
+ {
+ boolean hasBody = node.getScopedNode().getChildCount() > 0;
+
+ if (!hasBody)
+ {
+ indentPush();
+ write(ASEmitterTokens.INDENT);
+ }
+
+ final StringBuilder code = new StringBuilder();
+
+ List<IParameterNode> parameters = new ArrayList<IParameterNode>(
+ defaults.values());
+ Collections.reverse(parameters);
+
+ int len = defaults.size();
+ // make the header in reverse order
+ for (IParameterNode pnode : parameters)
+ {
+ if (pnode != null)
+ {
+ code.setLength(0);
+
+ code.append(ASEmitterTokens.IF.getToken());
+ code.append(ASEmitterTokens.SPACE.getToken());
+ code.append(ASEmitterTokens.PAREN_OPEN.getToken());
+ code.append(JSEmitterTokens.ARGUMENTS.getToken());
+ code.append(ASEmitterTokens.MEMBER_ACCESS.getToken());
+ code.append(JSAMDEmitterTokens.LENGTH.getToken());
+ code.append(ASEmitterTokens.SPACE.getToken());
+ code.append(ASEmitterTokens.LESS_THAN.getToken());
+ code.append(ASEmitterTokens.SPACE.getToken());
+ code.append(len);
+ code.append(ASEmitterTokens.PAREN_CLOSE.getToken());
+ code.append(ASEmitterTokens.SPACE.getToken());
+ code.append(ASEmitterTokens.BLOCK_OPEN.getToken());
+
+ write(code.toString());
+
+ indentPush();
+ writeNewline();
+ }
+ len--;
+ }
+
+ Collections.reverse(parameters);
+ for (int i = 0, n = parameters.size(); i < n; i++)
+ {
+ IParameterNode pnode = parameters.get(i);
+
+ if (pnode != null)
+ {
+ code.setLength(0);
+
+ code.append(pnode.getName());
+ code.append(ASEmitterTokens.SPACE.getToken());
+ code.append(ASEmitterTokens.EQUAL.getToken());
+ code.append(ASEmitterTokens.SPACE.getToken());
+ code.append(pnode.getDefaultValue());
+ code.append(ASEmitterTokens.SEMICOLON.getToken());
+ write(code.toString());
+
+ indentPop();
+ writeNewline();
+
+ write(ASEmitterTokens.BLOCK_CLOSE);
+
+ if (i == n - 1 && !hasBody)
+ indentPop();
+
+ writeNewline();
+ }
+ }
+ }
+ }
+
+ @Override
+ public void emitParameter(IParameterNode node)
+ {
+ getWalker().walk(node.getNameExpressionNode());
+ }
+
+ @Override
+ public void emitMemberAccessExpression(IMemberAccessExpressionNode node)
+ {
+ getWalker().walk(node.getLeftOperandNode());
+ if (!(node.getLeftOperandNode() instanceof ILanguageIdentifierNode))
+ write(node.getOperator().getOperatorText());
+ getWalker().walk(node.getRightOperandNode());
+ }
+
+ @Override
+ public void emitFunctionCall(IFunctionCallNode node)
+ {
+ if (node.isNewExpression())
+ {
+ write(ASEmitterTokens.NEW);
+ write(ASEmitterTokens.SPACE);
+ }
+ // IDefinition resolve = node.resolveType(project);
+ // if (NativeUtils.isNative(resolve.getBaseName()))
+ // {
+ //
+ // }
+
+ getWalker().walk(node.getNameNode());
+
+ emitArguments(node.getArgumentsNode());
+ }
+
+ @Override
+ public void emitArguments(IContainerNode node)
+ {
+ IContainerNode newNode = node;
+ FunctionCallNode fnode = (FunctionCallNode) node.getParent();
+ if (TempTools.injectThisArgument(fnode, false))
+ {
+ IdentifierNode thisNode = new IdentifierNode("this");
+ newNode = EmitterUtils.insertArgumentsBefore(node, thisNode);
+ }
+
+ int len = newNode.getChildCount();
+ write(ASEmitterTokens.PAREN_OPEN);
+ for (int i = 0; i < len; i++)
+ {
+ IExpressionNode inode = (IExpressionNode) newNode.getChild(i);
+ if (inode.getNodeID() == ASTNodeID.IdentifierID)
+ {
+ emitArgumentIdentifier((IIdentifierNode) inode);
+ }
+ else
+ {
+ getWalker().walk(inode);
+ }
+
+ if (i < len - 1)
+ {
+ writeToken(ASEmitterTokens.COMMA);
+ }
+ }
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+
+ private void emitArgumentIdentifier(IIdentifierNode node)
+ {
+ ITypeDefinition type = node.resolveType(getWalker().getProject());
+ if (type instanceof ClassTraitsDefinition)
+ {
+ String qualifiedName = type.getQualifiedName();
+ write(qualifiedName);
+ }
+ else
+ {
+ // XXX A problem?
+ getWalker().walk(node);
+ }
+ }
+
+ @Override
+ public void emitIdentifier(IIdentifierNode node)
+ {
+ ICompilerProject project = getWalker().getProject();
+
+ IDefinition resolve = node.resolve(project);
+ if (TempTools.isBinding(node, project))
+ {
+ // AS3.bind( this,"secret$1");
+ // this will happen on the right side of the = sign to bind a methof/function
+ // to a variable
+
+ write("AS3.bind(this, \"" + toPrivateName(resolve) + "\")");
+ }
+ else
+ {
+ IExpressionNode leftBase = TempTools.getNode(node, false, project);
+ if (leftBase == node)
+ {
+ if (TempTools.isValidThis(node, project))
+ write("this.");
+ // in constructor and a type
+ if (initializingFieldsInConstructor
+ && resolve instanceof IClassDefinition)
+ {
+ String name = resolve.getBaseName();
+ write("(" + name + "._ || " + name + "._$get())");
+ return;
+ }
+ }
+
+ if (resolve != null)
+ {
+ // TODO (mschmalle|AMD) optimize
+ String name = toPrivateName(resolve);
+ if (NativeUtils.isNative(name))
+ exportWriter.addDependency(name, name, true, false);
+
+ if (node.getParent() instanceof IMemberAccessExpressionNode)
+ {
+ IMemberAccessExpressionNode mnode = (IMemberAccessExpressionNode) node
+ .getParent();
+ if (mnode.getLeftOperandNode().getNodeID() == ASTNodeID.SuperID)
+ {
+ IIdentifierNode lnode = (IIdentifierNode) mnode
+ .getRightOperandNode();
+
+ IClassNode cnode = (IClassNode) node
+ .getAncestorOfType(IClassNode.class);
+
+ initializeInheritenceLevel(cnode.getDefinition());
+
+ // super.foo();
+ write("this.");
+
+ write(lnode.getName() + "$" + inheritenceLevel);
+
+ baseClassCalls.add(resolve);
+
+ return;
+ }
+ }
+ write(name);
+ }
+ else
+ {
+ // no definition, just plain ole identifer
+ write(node.getName());
+ }
+ }
+ }
+
+ @Override
+ protected void emitType(IExpressionNode node)
+ {
+ }
+
+ @Override
+ public void emitLanguageIdentifier(ILanguageIdentifierNode node)
+ {
+ if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.ANY_TYPE)
+ {
+ write("");
+ }
+ else if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.REST)
+ {
+ write("");
+ }
+ else if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.SUPER)
+ {
+ IIdentifierNode inode = (IIdentifierNode) node;
+ if (inode.getParent() instanceof IMemberAccessExpressionNode)
+ {
+
+ }
+ else
+ {
+ write("Super.call");
+ }
+ }
+ else if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.THIS)
+ {
+ write("");
+ }
+ else if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.VOID)
+ {
+ write("");
+ }
+ }
+
+ private String toPrivateName(IDefinition definition)
+ {
+ if (definition instanceof ITypeDefinition)
+ return definition.getBaseName();
+ if (!definition.isPrivate())
+ return definition.getBaseName();
+
+ initializeInheritenceLevel(definition);
+
+ return definition.getBaseName() + "$" + inheritenceLevel;
+ }
+
+ void initializeInheritenceLevel(IDefinition definition)
+ {
+ if (inheritenceLevel != -1)
+ return;
+
+ IClassDefinition cdefinition = null;
+ if (definition instanceof IClassDefinition)
+ cdefinition = (IClassDefinition) definition;
+ else
+ cdefinition = (IClassDefinition) definition
+ .getAncestorOfType(IClassDefinition.class);
+
+ ICompilerProject project = getWalker().getProject();
+ IClassDefinition[] ancestry = cdefinition.resolveAncestry(project);
+ inheritenceLevel = ancestry.length - 1;
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/c3dce49f/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/amd/JSAMDEmitterTokens.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/amd/JSAMDEmitterTokens.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/amd/JSAMDEmitterTokens.java
new file mode 100644
index 0000000..122f711
--- /dev/null
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/amd/JSAMDEmitterTokens.java
@@ -0,0 +1,38 @@
+/*
+ *
+ * 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.amd;
+
+import org.apache.flex.compiler.codegen.IEmitterTokens;
+
+public enum JSAMDEmitterTokens implements IEmitterTokens
+{
+ DEFINE("define"), LENGTH("length"), ;
+
+ private String token;
+
+ private JSAMDEmitterTokens(String value)
+ {
+ token = value;
+ }
+
+ public String getToken()
+ {
+ return token;
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/c3dce49f/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/amd/TempTools.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/amd/TempTools.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/amd/TempTools.java
new file mode 100644
index 0000000..4d0d6f2
--- /dev/null
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/amd/TempTools.java
@@ -0,0 +1,451 @@
+/*
+ *
+ * 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.amd;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.flex.compiler.common.ASModifier;
+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.IParameterDefinition;
+import org.apache.flex.compiler.definitions.ITypeDefinition;
+import org.apache.flex.compiler.definitions.IVariableDefinition;
+import org.apache.flex.compiler.definitions.references.IReference;
+import org.apache.flex.compiler.internal.definitions.ClassTraitsDefinition;
+import org.apache.flex.compiler.internal.tree.as.ExpressionNodeBase;
+import org.apache.flex.compiler.internal.tree.as.FunctionCallNode;
+import org.apache.flex.compiler.internal.tree.as.MemberAccessExpressionNode;
+import org.apache.flex.compiler.projects.ICompilerProject;
+import org.apache.flex.compiler.tree.ASTNodeID;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.as.IBinaryOperatorNode;
+import org.apache.flex.compiler.tree.as.IClassNode;
+import org.apache.flex.compiler.tree.as.IDefinitionNode;
+import org.apache.flex.compiler.tree.as.IDynamicAccessNode;
+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.IIdentifierNode;
+import org.apache.flex.compiler.tree.as.ILanguageIdentifierNode;
+import org.apache.flex.compiler.tree.as.ILanguageIdentifierNode.LanguageIdentifierKind;
+import org.apache.flex.compiler.tree.as.IMemberAccessExpressionNode;
+import org.apache.flex.compiler.tree.as.IParameterNode;
+import org.apache.flex.compiler.tree.as.IUnaryOperatorNode;
+import org.apache.flex.compiler.tree.as.IVariableNode;
+
+/**
+ * These tools need to be refactored into utility classes.
+ *
+ * @author Michael Schmalle
+ */
+public class TempTools
+{
+
+ public static void fillStaticStatements(IClassNode node,
+ List<IASNode> list, boolean excludeFields)
+ {
+ int len = node.getScopedNode().getChildCount();
+ for (int i = 0; i < len; i++)
+ {
+ IASNode child = node.getScopedNode().getChild(i);
+ if (child instanceof IExpressionNode)
+ list.add(child);
+ else if (child instanceof IDefinitionNode)
+ {
+ if (!excludeFields
+ && ((IDefinitionNode) child)
+ .hasModifier(ASModifier.STATIC)
+ && child instanceof IVariableNode)
+ list.add(child);
+ }
+ }
+ }
+
+ public static void fillInstanceMembers(IDefinitionNode[] members,
+ List<IDefinitionNode> list)
+ {
+ for (IDefinitionNode node : members)
+ {
+ if (node instanceof IFunctionNode
+ && ((IFunctionNode) node).isConstructor())
+ continue;
+
+ if (!node.hasModifier(ASModifier.STATIC))
+ {
+ list.add(node);
+ }
+ }
+ }
+
+ public static void fillStaticMembers(IDefinitionNode[] members,
+ List<IDefinitionNode> list, boolean excludeFields,
+ boolean excludeFunctions)
+ {
+ for (IDefinitionNode node : members)
+ {
+ if (node.hasModifier(ASModifier.STATIC))
+ {
+ if (!excludeFields && node instanceof IVariableNode)
+ list.add(node);
+ else if (!excludeFunctions && node instanceof IFunctionNode)
+ list.add(node);
+ }
+ }
+ }
+
+ public static List<IVariableDefinition> getFields(
+ IClassDefinition definition, boolean excludePrivate)
+ {
+ ArrayList<IVariableDefinition> result = new ArrayList<IVariableDefinition>();
+ Collection<IDefinition> definitions = definition.getContainedScope()
+ .getAllLocalDefinitions();
+ for (IDefinition member : definitions)
+ {
+ if (!member.isImplicit() && member instanceof IVariableDefinition)
+ {
+ IVariableDefinition vnode = (IVariableDefinition) member;
+ if (!member.isStatic()
+ && (member.isPublic() || member.isProtected()))
+ result.add(vnode);
+ // TODO FIX the logic here, this won't add twice though
+ if (!excludePrivate && member.isPrivate())
+ result.add(vnode);
+ }
+ }
+ return result;
+ }
+
+ public static boolean isVariableAParameter(IVariableDefinition node,
+ IParameterDefinition[] parameters)
+ {
+ for (IParameterDefinition parameter : parameters)
+ {
+ if (node.getBaseName().equals(parameter.getBaseName()))
+ return true;
+ }
+ return false;
+ }
+
+ public static Map<Integer, IParameterNode> getDefaults(
+ IParameterNode[] nodes)
+ {
+ Map<Integer, IParameterNode> result = new HashMap<Integer, IParameterNode>();
+ int i = 0;
+ boolean hasDefaults = false;
+ for (IParameterNode node : nodes)
+ {
+ if (node.hasDefaultValue())
+ {
+ hasDefaults = true;
+ result.put(i, node);
+ }
+ else
+ {
+ result.put(i, null);
+ }
+ i++;
+ }
+
+ if (!hasDefaults)
+ return null;
+
+ return result;
+ }
+
+ public static boolean injectThisArgument(FunctionCallNode node,
+ boolean allowMembers)
+ {
+ // if super isSuper checks the nameNode
+ if (node.isSuperExpression() && !node.isNewExpression())
+ return true;
+
+ ExpressionNodeBase base = node.getNameNode();
+ if (base.getNodeID() == ASTNodeID.IdentifierID)
+ return false;
+
+ if (allowMembers && base instanceof IMemberAccessExpressionNode)
+ {
+ // foo.super()
+ IMemberAccessExpressionNode mnode = (IMemberAccessExpressionNode) base;
+ if (mnode.getLeftOperandNode().getNodeID() == ASTNodeID.SuperID)
+ return true;
+ }
+
+ return false;
+ }
+
+ public static String toInitialValue(IVariableDefinition field,
+ ICompilerProject project)
+ {
+ Object value = field.resolveInitialValue(project);
+ if (value != null)
+ return value.toString();
+ IReference reference = field.getTypeReference();
+ if (reference == null)
+ return "undefined";
+ if (reference.getName().equals("int")
+ || reference.getName().equals("uint")
+ || reference.getName().equals("Number"))
+ return "0";
+ return "null";
+ }
+
+ public static boolean isBinding(IIdentifierNode node,
+ ICompilerProject project)
+ {
+ IDefinition resolve = node.resolve(project);
+
+ if (resolve != null && resolve.isPrivate() && !isField(resolve))
+ {
+ //if (resolve instanceof IFunctionDefinition)
+ IExpressionNode rightSide = getNode(node, true, project);
+ IBinaryOperatorNode parent = (IBinaryOperatorNode) node
+ .getAncestorOfType(IBinaryOperatorNode.class);
+ if (isThisLeftOf(node))
+ parent = (IBinaryOperatorNode) parent
+ .getAncestorOfType(IBinaryOperatorNode.class);
+
+ IVariableNode vparent = (IVariableNode) node
+ .getAncestorOfType(IVariableNode.class);
+ if (vparent != null)
+ {
+ IExpressionNode indentFromThis = getIndentFromThis(node);
+ if (vparent.getAssignedValueNode() == node
+ || ((IBinaryOperatorNode) vparent
+ .getAssignedValueNode()).getRightOperandNode() == indentFromThis)
+ return true;
+ }
+
+ if (rightSide == node && parent != null/*|| isThisLeftOf(node)*/)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private static boolean isField(IDefinition node)
+ {
+ return !(node instanceof IFunctionDefinition);
+ }
+
+ public static boolean isValidThis(IIdentifierNode node,
+ ICompilerProject project)
+ {
+ // added super.foo(), wanted to 'this' behind foo
+ if (node.getParent() instanceof IMemberAccessExpressionNode)
+ {
+ IMemberAccessExpressionNode mnode = (IMemberAccessExpressionNode) node
+ .getParent();
+ if (mnode.getLeftOperandNode().getNodeID() == ASTNodeID.SuperID)
+ return false;
+
+ IExpressionNode indentFromThis = getIndentFromThis(node);
+ if (node == indentFromThis)
+ return true;
+
+ // test that this is the base expression
+ ExpressionNodeBase enode = (ExpressionNodeBase) node;
+ ExpressionNodeBase baseExpression = enode.getBaseExpression();
+ if (indentFromThis == null && baseExpression != null
+ && baseExpression != node)
+ return false;
+
+ // check to see if the left is a type
+ ITypeDefinition type = mnode.getLeftOperandNode().resolveType(
+ project);
+
+ // A.{foo} : Left is a Type
+ // XXX going to have to test packgeName to com.acme.A
+ if (type instanceof ClassTraitsDefinition
+ && mnode.getLeftOperandNode() == node)
+ {
+ return false;
+ }
+ // this.{foo} : explicit 'this', in js we are ignoring explicit this identifiers
+ // because we are inserting all of them with the emitter
+ else if (indentFromThis == null)
+ {
+ //return false;
+ }
+
+ }
+
+ IDefinition definition = node.resolve(project);
+ if (definition == null)
+ return false; // Is this correct?
+ if (definition instanceof IParameterDefinition)
+ return false;
+ if (definition.getParent() instanceof IMemberAccessExpressionNode)
+ return false;
+ if (!(definition.getParent() instanceof IClassDefinition))
+ return false;
+
+ if (definition instanceof IVariableDefinition)
+ {
+ IVariableDefinition variable = (IVariableDefinition) definition;
+ if (variable.isStatic())
+ return false;
+ }
+ if (definition instanceof IFunctionDefinition)
+ {
+ IFunctionDefinition function = (IFunctionDefinition) definition;
+ if (function.isStatic())
+ return false;
+ }
+
+ return true;
+ }
+
+ private static boolean isThisLeftOf(IIdentifierNode node)
+ {
+ if (node.getParent() instanceof IMemberAccessExpressionNode)
+ {
+ IMemberAccessExpressionNode parent = (IMemberAccessExpressionNode) node
+ .getParent();
+ if (parent.getLeftOperandNode() instanceof ILanguageIdentifierNode
+ && ((ILanguageIdentifierNode) parent.getLeftOperandNode())
+ .getKind() == LanguageIdentifierKind.THIS)
+ return true;
+ }
+ return false;
+ }
+
+ public static IExpressionNode getNode(IASNode iNode, Boolean toRight,
+ ICompilerProject project)
+ {
+ try
+ {
+ IASNode node = iNode;
+ while (node != null)
+ {
+ if (node instanceof IBinaryOperatorNode
+ && !(node instanceof MemberAccessExpressionNode))
+ {
+ if (toRight)
+ node = ((IBinaryOperatorNode) node)
+ .getRightOperandNode();
+ else
+ node = ((IBinaryOperatorNode) node)
+ .getLeftOperandNode();
+ }
+ else if (node instanceof IFunctionCallNode)
+ node = ((IFunctionCallNode) node).getNameNode();
+ else if (node instanceof IDynamicAccessNode)
+ node = ((IDynamicAccessNode) node).getLeftOperandNode();
+ else if (node instanceof IUnaryOperatorNode)
+ node = ((IUnaryOperatorNode) node).getOperandNode();
+ else if (node instanceof IForLoopNode)
+ node = ((IForLoopNode) node).getChild(0).getChild(0);
+ else if (node instanceof IVariableNode)
+ {
+ if (toRight)
+ node = ((IVariableNode) node).getAssignedValueNode();
+ else
+ node = ((IVariableNode) node).getVariableTypeNode();
+ }
+ else if (node instanceof IExpressionNode)
+ {
+ // IDefinition def = ((IExpressionNode) node).resolve(project);
+ // if (def instanceof VariableDefinition)
+ // {
+ // final VariableDefinition variable = (VariableDefinition) def;
+ // def = variable.resolveType(project);
+ // }
+ // else if (def instanceof FunctionDefinition)
+ // {
+ // final FunctionDefinition functionDef = (FunctionDefinition) def;
+ // final IReference typeRef = functionDef
+ // .getReturnTypeReference();
+ // if (typeRef != null)
+ // def = typeRef.resolve(project,
+ // (ASScope) getScopeFromNode(iNode),
+ // DependencyType.INHERITANCE, false);
+ // }
+ // else if (def instanceof IGetterDefinition)
+ // {
+ // final ITypeDefinition returnType = ((IGetterDefinition) def)
+ // .resolveReturnType(project);
+ // // def = m_sharedData.getDefinition(returnType
+ // // .getQualifiedName());
+ // def = returnType; // XXX figure out
+ // }
+ //
+ // if (def != null && def instanceof ClassDefinition)
+ // {
+ // return def;
+ // }
+ return (IExpressionNode) node;
+ }
+ else
+ {
+ node = null;
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ // getDefinitionForNode(iNode,toRight);
+
+ // getDefinition() sometimes crashes, e.g. when looking at a cast to an interface in some cases,
+ // FunctionDefinition.getParameters() returns null and ExpressionNodeBase.determineIfFunction() chokes on it
+ // printWarning(iNode, "getDefinitionForNode() failed for" + iNode);
+ }
+ return null;
+ }
+
+ private static IExpressionNode getIndentFromThis(IIdentifierNode node)
+ {
+ if (node.getParent() instanceof IMemberAccessExpressionNode)
+ {
+ IMemberAccessExpressionNode parent = (IMemberAccessExpressionNode) node
+ .getParent();
+ if (parent.getLeftOperandNode() instanceof ILanguageIdentifierNode
+ && ((ILanguageIdentifierNode) parent.getLeftOperandNode())
+ .getKind() == LanguageIdentifierKind.THIS)
+ return parent.getRightOperandNode();
+ }
+ return null;
+ }
+
+ public static String toPackageName(String name)
+ {
+ if (!name.contains("."))
+ return name;
+ final String stem = name.substring(0, name.lastIndexOf("."));
+ return stem;
+ }
+
+ public static String toBaseName(String name)
+ {
+ if (!name.contains("."))
+ return name;
+ final String basename = name.substring(name.lastIndexOf(".") + 1);
+ return basename;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/c3dce49f/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSDocEmitter.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSDocEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSDocEmitter.java
new file mode 100644
index 0000000..057bcf1
--- /dev/null
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSDocEmitter.java
@@ -0,0 +1,391 @@
+/*
+ *
+ * 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.flexjs;
+
+import java.util.ArrayList;
+import java.util.List;
+
+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.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 JSFlexJSDocEmitter extends JSGoogDocEmitter
+{
+ private List<String> classIgnoreList;
+ private List<String> ignoreList;
+ private List<String> coercionList;
+
+ public JSFlexJSDocEmitter(IJSEmitter emitter)
+ {
+ super(emitter);
+ }
+
+ public List<String> getClassIgnoreList()
+ {
+ return classIgnoreList;
+ }
+
+ public void setClassIgnoreList(List<String> value)
+ {
+ this.classIgnoreList = value;
+ }
+
+ @Override
+ protected String convertASTypeToJS(String name, String pname)
+ {
+ if (ignoreList != null)
+ {
+ if (ignoreList.contains(pname + "." + name))
+ return IASLanguageConstants.Object;
+ }
+ if (coercionList != null)
+ {
+ if (!coercionList.contains(pname + "." + name))
+ return IASLanguageConstants.Object;
+ }
+ if (classIgnoreList != null)
+ {
+ if (classIgnoreList.contains(pname + "." + name))
+ return IASLanguageConstants.Object;
+ }
+ if (name.matches("Vector\\.<.*>"))
+ return IASLanguageConstants.Array;
+
+ name = super.convertASTypeToJS(name, pname);
+ return formatQualifiedName(name);
+ }
+
+ @Override
+ protected String formatQualifiedName(String name)
+ {
+ return ((JSFlexJSEmitter)emitter).formatQualifiedName(name, true);
+ }
+
+ @Override
+ public void emitMethodDoc(IFunctionNode node, ICompilerProject project)
+ {
+ coercionList = null;
+ ignoreList = null;
+
+ IClassDefinition classDefinition = resolveClassDefinition(node);
+
+ ASDocComment asDoc = (ASDocComment) node.getASDocComment();
+
+ if (node instanceof IFunctionNode)
+ {
+ boolean hasDoc = false;
+ Boolean override = false;
+
+ if (node.isConstructor())
+ {
+ if (asDoc != null && MXMLJSC.keepASDoc)
+ write(changeAnnotations(asDoc.commentNoEnd()));
+ else
+ begin();
+ hasDoc = true;
+
+ emitJSDocLine(JSEmitterTokens.CONSTRUCTOR);
+
+ IClassDefinition parent = (IClassDefinition) node
+ .getDefinition().getParent();
+ IClassDefinition superClass = parent.resolveBaseClass(project);
+ String qname = (superClass != null) ? project.getActualPackageName(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());
+ } else {
+ emitImplements(type, project.getActualPackageName(type.getPackageName()));
+ }
+ }
+ }
+ else
+ {
+ // @override
+ override = node.hasModifier(ASModifier.OVERRIDE);
+
+ String ns = node.getNamespace();
+ if (ns != null)
+ {
+ if (asDoc != null && MXMLJSC.keepASDoc)
+ {
+ String docText = asDoc.commentNoEnd();
+ String keepToken = JSFlexJSEmitterTokens.EMIT_COERCION
+ .getToken();
+ if (docText.contains(keepToken))
+ loadKeepers(docText);
+ String ignoreToken = JSFlexJSEmitterTokens.IGNORE_COERCION
+ .getToken();
+ if (docText.contains(ignoreToken))
+ loadIgnores(docText);
+ write(changeAnnotations(asDoc.commentNoEnd()));
+ }
+ else
+ begin();
+ emitMethodAccess(node);
+ hasDoc = true;
+ }
+ }
+
+ if (!override)
+ {
+ // @param
+ IParameterNode[] parameters = node.getParameterNodes();
+ for (IParameterNode pnode : parameters)
+ {
+ if (!hasDoc)
+ {
+ if (asDoc != null && MXMLJSC.keepASDoc)
+ write(changeAnnotations(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, project.getActualPackageName(tdef.getPackageName()));
+ }
+ }
+
+ if (!node.isConstructor())
+ {
+ if (!override)
+ {
+ // @return
+ String returnType = node.getReturnType();
+ if (returnType != ""
+ && returnType != ASEmitterTokens.VOID.getToken())
+ {
+ if (!hasDoc)
+ {
+ if (asDoc != null && MXMLJSC.keepASDoc)
+ write(changeAnnotations(asDoc.commentNoEnd()));
+ else
+ begin();
+ emitMethodAccess(node);
+ hasDoc = true;
+ }
+
+ ITypeDefinition tdef = ((IFunctionDefinition) node
+ .getDefinition()).resolveReturnType(project);
+
+ String packageName = "";
+ packageName = tdef != null ? tdef.getPackageName() : "";
+
+ emitReturn(node, project.getActualPackageName(packageName));
+ }
+ }
+
+ if (override)
+ {
+ if (!hasDoc)
+ {
+ if (asDoc != null && MXMLJSC.keepASDoc)
+ write(changeAnnotations(asDoc.commentNoEnd()));
+ else
+ begin();
+ emitMethodAccess(node);
+ hasDoc = true;
+ }
+
+ emitOverride(node);
+ }
+ }
+
+ if (hasDoc)
+ end();
+ }
+ }
+
+ private void loadIgnores(String doc)
+ {
+ ignoreList = new ArrayList<String>();
+ String ignoreToken = JSFlexJSEmitterTokens.IGNORE_COERCION.getToken();
+ int index = doc.indexOf(ignoreToken);
+ while (index != -1)
+ {
+ String ignore = doc.substring(index + ignoreToken.length());
+ int endIndex = ignore.indexOf("\n");
+ ignore = ignore.substring(0, endIndex);
+ ignore = ignore.trim();
+ ignoreList.add(ignore);
+ index = doc.indexOf(ignoreToken, index + endIndex);
+ }
+ }
+
+ private void loadKeepers(String doc)
+ {
+ coercionList = new ArrayList<String>();
+ String keepToken = JSFlexJSEmitterTokens.EMIT_COERCION.getToken();
+ int index = doc.indexOf(keepToken);
+ while (index != -1)
+ {
+ String keeper = doc.substring(index + keepToken.length());
+ int endIndex = keeper.indexOf("\n");
+ keeper = keeper.substring(0, endIndex);
+ keeper = keeper.trim();
+ coercionList.add(keeper);
+ index = doc.indexOf(keepToken, index + endIndex);
+ }
+ }
+
+ private String changeAnnotations(String doc)
+ {
+ // rename these tags so they don't conflict with generated
+ // jsdoc tags
+ String pass1 = doc.replaceAll("@param", "@asparam");
+ String pass2 = pass1.replaceAll("@return", "@asreturn");
+ String pass3 = pass2.replaceAll("@private", "@asprivate");
+ return pass3;
+ }
+
+ 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(changeAnnotations(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(changeAnnotations(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);
+ }
+ }
+
+ @Override
+ public void emitFieldDoc(IVariableNode node, IDefinition def, ICompilerProject project)
+ {
+ begin();
+
+ String ns = node.getNamespace();
+ if (ns == IASKeywordConstants.PRIVATE)
+ {
+ emitPrivate(node);
+ }
+ else if (ns == IASKeywordConstants.PROTECTED)
+ {
+ emitProtected(node);
+ }
+ else
+ {
+ emitPublic(node);
+ }
+
+ if (node.isConst())
+ emitConst(node);
+
+ String packageName = "";
+ if (def != null)
+ packageName = def.getPackageName();
+
+ emitType(node, project.getActualPackageName(packageName));
+
+ end();
+ }
+
+}