You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by er...@apache.org on 2013/04/19 13:55:08 UTC
[09/10] git commit: [flex-falcon] - [FalconJX] JS emitter update
[FalconJX] JS emitter update
Updated FlexJS JS emitter with reformatted (improved?) 'this' logic and various minor changes.
Signed-off-by: Erik de Bruin <er...@ixsoftware.nl>
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/ea079e9a
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/ea079e9a
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/ea079e9a
Branch: refs/heads/develop
Commit: ea079e9a1a92e254bb098bf5752d83dd5af147ff
Parents: 2966d11
Author: Erik de Bruin <er...@ixsoftware.nl>
Authored: Fri Apr 19 13:54:04 2013 +0200
Committer: Erik de Bruin <er...@ixsoftware.nl>
Committed: Fri Apr 19 13:54:04 2013 +0200
----------------------------------------------------------------------
.../codegen/js/flexjs/JSFlexJSEmitter.java | 361 +++++++--------
1 files changed, 174 insertions(+), 187 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/ea079e9a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java
index 6871b4a..df36212 100644
--- a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java
@@ -21,14 +21,18 @@ package org.apache.flex.compiler.internal.codegen.js.flexjs;
import java.io.FilterWriter;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
import org.apache.flex.compiler.codegen.IDocEmitter;
import org.apache.flex.compiler.codegen.js.flexjs.IJSFlexJSEmitter;
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.IDefinition;
import org.apache.flex.compiler.definitions.IFunctionDefinition;
+import org.apache.flex.compiler.definitions.INamespaceDefinition;
import org.apache.flex.compiler.definitions.IPackageDefinition;
import org.apache.flex.compiler.definitions.ITypeDefinition;
import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
@@ -37,13 +41,13 @@ 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.definitions.AccessorDefinition;
import org.apache.flex.compiler.internal.definitions.ClassDefinition;
-import org.apache.flex.compiler.internal.definitions.ClassTraitsDefinition;
import org.apache.flex.compiler.internal.definitions.FunctionDefinition;
-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;
@@ -88,6 +92,8 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
public IDefinition thisClass;
+ private ICompilerProject project;
+
@Override
protected void emitMemberName(IDefinitionNode node)
{
@@ -99,20 +105,25 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
{
thisClass = node.getDefinition();
+ project = getWalker().getProject();
+
super.emitClass(node);
}
@Override
public void emitField(IVariableNode node)
{
- ICompilerProject project = getWalker().getProject();
-
IDefinition definition = getClassDefinition(node);
IDefinition def = null;
IExpressionNode enode = node.getVariableTypeNode();//getAssignedValueNode();
if (enode != null)
+ {
+ if (project == null)
+ project = getWalker().getProject();
+
def = enode.resolveType(project);
+ }
getDoc().emitFieldDoc(node, def);
@@ -192,7 +203,9 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
}
else
{
- project = getWalker().getProject();
+ if (project == null)
+ project = getWalker().getProject();
+
def = node.getNameNode().resolve(project);
isClassCast = def instanceof ClassDefinition
@@ -201,7 +214,10 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
if (node.isNewExpression())
{
- def = node.resolveCalledExpression(getWalker().getProject());
+ 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(def.getQualifiedName());
@@ -232,134 +248,145 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
}
}
- private boolean isSameClass(IDefinition pdef, IDefinition thisClass2,
- ICompilerProject project)
- {
- if (pdef == thisClass2)
- return true;
-
- // needs to be a loop
- if (((ClassDefinition) thisClass2).resolveBaseClass(project) == pdef)
- return true;
-
- return false;
- }
+ //--------------------------------------------------------------------------
@Override
- public void emitIdentifier(IIdentifierNode node)
+ protected void emitSelfReference(IFunctionNode node)
{
- ICompilerProject project = getWalker().getProject();
+ // we don't want 'var self = this;' in FlexJS
+ }
- IClassNode cnode = (IClassNode) node
+ private boolean writeThis(IIdentifierNode node)
+ {
+ IClassNode classNode = (IClassNode) node
.getAncestorOfType(IClassNode.class);
- IDefinition def = ((IIdentifierNode) node).resolve(project);
+ IDefinition nodeDef = ((IIdentifierNode) node).resolve(project);
- ITypeDefinition type = ((IIdentifierNode) node).resolveType(project);
+ IASNode parentNode = node.getParent();
+ ASTNodeID parentNodeId = parentNode.getNodeID();
- IASNode pnode = node.getParent();
- ASTNodeID inode = pnode.getNodeID();
+ IASNode firstChild = parentNode.getChild(0);
- boolean writeSelf = false;
- boolean writeThis = false;
- if (cnode != null && !(def instanceof ParameterDefinition))
+ boolean identifierIsMemberAccess = parentNodeId == ASTNodeID.MemberAccessExpressionID;
+
+ if (classNode == null) // script in MXML and AS interface definitions
{
- IDefinitionNode[] members = cnode.getAllMemberNodes();
- for (IDefinitionNode mnode : members)
+ if (nodeDef instanceof VariableDefinition)
{
- if ((type != null && type.getQualifiedName().equalsIgnoreCase(
- IASLanguageConstants.Function))
- || (def != null && (!def.isInternal()) && def.getQualifiedName()
- .equalsIgnoreCase(mnode.getQualifiedName())))
- {
- if (!(pnode instanceof FunctionNode)
- && inode != ASTNodeID.MemberAccessExpressionID)
- {
- if (def instanceof FunctionDefinition)
- {
- if (((FunctionDefinition) def)
- .getFunctionClassification() == IFunctionDefinition.FunctionClassification.CLASS_MEMBER)
- writeSelf = true;
- }
- else
- writeSelf = true;
- break;
- }
- else if (inode == ASTNodeID.MemberAccessExpressionID
- && !def.isStatic()
- && (pnode.getChild(0) == node || (pnode.getChild(0) instanceof ILanguageIdentifierNode && ((ILanguageIdentifierNode) pnode
- .getChild(0)).getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.THIS)))
- {
- // we are in a member access expression and it isn't a static
- // and we are the left node, or the left node is 'this'
- //String tname = type.getQualifiedName();
- writeSelf = true; /*!tname.equalsIgnoreCase(cnode
- .getQualifiedName())
- && !tname.equals(IASLanguageConstants.Function);*/
- break;
- }
- }
+ 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 (parentNodeId == ASTNodeID.ContainerID
+ && nodeDef instanceof FunctionDefinition)
+ {
+ return true; // for 'goog.bind'
+ }
+ else
+ {
+ return parentNodeId == ASTNodeID.FunctionCallID
+ && !(nodeDef instanceof AccessorDefinition)
+ && !identifierIsMemberAccess;
}
}
- else if (cnode == null && !(type instanceof ClassTraitsDefinition))
+ else
{
- // (erikdebruin) the sequence of these conditions matters, leave
- // well enough alone!
- if (def instanceof VariableDefinition)
+ if (nodeDef != null
+ && !nodeDef.isInternal()
+ && isClassMember(nodeDef, classNode))
{
- VariableDefinition vardef = (VariableDefinition) def;
- IDefinition pdef = vardef.getParent();
- if (inode == ASTNodeID.MemberAccessExpressionID)
+ if (identifierIsMemberAccess)
{
- if (pdef == thisClass && pnode.getChild(0) == node)
- writeSelf = true;
- }
- else if (inode == ASTNodeID.ContainerID)
- {
- if (isSameClass(pdef, thisClass, project))
- {
- writeSelf = true;
- writeThis = true;
- }
- }
- else if (!(pnode instanceof ParameterNode))
- {
- if (pdef == thisClass)
- writeSelf = true;
+ boolean parentIsThis = firstChild instanceof ILanguageIdentifierNode
+ && ((ILanguageIdentifierNode) firstChild).getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.THIS;
+
+ return node == firstChild || parentIsThis;
}
- }
- else if (inode == ASTNodeID.ContainerID)
- {
- if (def instanceof FunctionDefinition)
+ else
{
- if (((FunctionDefinition) def).getFunctionClassification() != IFunctionDefinition.FunctionClassification.LOCAL)
- writeSelf = true;
+ boolean identifierIsLocalFunction = nodeDef instanceof FunctionDefinition
+ && !(nodeDef instanceof AccessorDefinition)
+ && ((FunctionDefinition) nodeDef)
+ .getFunctionClassification() == IFunctionDefinition.FunctionClassification.LOCAL;
+
+ return !identifierIsLocalFunction;
}
- else
- writeSelf = true;
- }
- else if (inode == ASTNodeID.FunctionCallID
- && !(def instanceof AccessorDefinition)
- && inode != ASTNodeID.MemberAccessExpressionID)
- {
- writeSelf = true;
- writeThis = true;
}
}
- boolean emitName = true;
+ return false;
+ }
+
+ private boolean isClassMember(IDefinition nodeDef, IClassNode classNode)
+ {
+ TypeScope cscope = (TypeScope) classNode.getDefinition()
+ .getContainedScope();
- // FIXME (erikdebruin) I desperately needed a way to bypass the addition
- // of the 'self' prefix when running the tests... Or
- // I'd have to put the prefix in ~150 asserts!
- boolean isRunningInTestMode = cnode != null
- && cnode.getQualifiedName().equalsIgnoreCase("FalconTest_A");
+ Set<INamespaceDefinition> nsSet = cscope.getNamespaceSet(project);
+ Collection<IDefinition> defs = new HashSet<IDefinition>();
- if (writeSelf && !isRunningInTestMode)
+ cscope.getAllPropertiesForMemberAccess((CompilerProject) project, defs,
+ nsSet);
+
+ Iterator<IDefinition> visiblePropertiesIterator = defs.iterator();
+ while (visiblePropertiesIterator.hasNext())
{
- boolean useGoogBind = inode == ASTNodeID.ContainerID
- && !writeThis && def instanceof FunctionDefinition
- && !def.isStatic();
+ if (nodeDef.getQualifiedName().equals(
+ visiblePropertiesIterator.next().getQualifiedName()))
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean isSameClass(IDefinition pdef, IDefinition thisClass,
+ ICompilerProject project)
+ {
+ if (pdef == thisClass)
+ return true;
+
+ // needs to be a loop
+ if (((ClassDefinition) thisClass).resolveBaseClass(project) == pdef)
+ return true;
+
+ return false;
+ }
+
+ @Override
+ public void emitIdentifier(IIdentifierNode node)
+ {
+ if (project == null)
+ project = getWalker().getProject();
+
+ IDefinition nodeDef = ((IIdentifierNode) 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())
+ {
+ String sname = nodeDef.getParent().getQualifiedName();
+ write(sname);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ }
+ else if (!NativeUtils.isNative(node.getName()) && writeThis(node))
+ {
+ boolean useGoogBind = parentNodeId == ASTNodeID.ContainerID
+ && identifierIsPlainFunction;
if (useGoogBind)
{
@@ -367,15 +394,8 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
write(ASEmitterTokens.PAREN_OPEN);
}
- if (writeThis)
- write(ASEmitterTokens.THIS);
- else if (def.isStatic())
- {
- String sname = def.getParent().getQualifiedName();
- write(sname);
- }
- else
- write(JSGoogEmitterTokens.SELF);
+ write(ASEmitterTokens.THIS);
+
write(ASEmitterTokens.MEMBER_ACCESS);
if (useGoogBind)
@@ -383,24 +403,18 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
write(node.getName());
writeToken(ASEmitterTokens.COMMA);
- write(JSGoogEmitterTokens.SELF);
+ write(ASEmitterTokens.THIS);
write(ASEmitterTokens.PAREN_CLOSE);
emitName = false;
}
}
- else if (def != null && def.isStatic())
- {
- String sname = def.getParent().getQualifiedName();
- write(sname);
- write(ASEmitterTokens.MEMBER_ACCESS);
- }
- IDefinition parentDef = (def != null) ? def.getParent() : null;
+ IDefinition parentDef = (nodeDef != null) ? nodeDef.getParent() : null;
boolean isNative = (parentDef != null)
&& NativeUtils.isNative(parentDef.getBaseName());
- if ((def instanceof AccessorDefinition && !isNative)
- || (def instanceof VariableDefinition && ((VariableDefinition) def)
+ if ((identifierIsAccessorFunction && !isNative)
+ || (nodeDef instanceof VariableDefinition && ((VariableDefinition) nodeDef)
.isBindable()))
{
IASNode anode = node
@@ -410,39 +424,40 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
if (anode != null)
{
IASNode leftNode = anode.getChild(0);
- if (anode == pnode)
+ if (anode == parentNode)
{
if (node == leftNode)
isAssignment = true;
}
else
{
- IASNode parentNode = pnode;
+ IASNode pnode = parentNode;
IASNode thisNode = node;
- while (anode != parentNode)
+ while (anode != pnode)
{
- if (parentNode instanceof IMemberAccessExpressionNode)
+ if (pnode instanceof IMemberAccessExpressionNode)
{
- if (thisNode != parentNode.getChild(1))
+ if (thisNode != pnode.getChild(1))
{
// can't be an assignment because
// we're on the left side of a memberaccessexpression
break;
}
}
- if (parentNode == leftNode)
+ if (pnode == leftNode)
{
isAssignment = true;
}
- thisNode = parentNode;
- parentNode = parentNode.getParent();
+ thisNode = pnode;
+ pnode = pnode.getParent();
}
}
- String op = ((IBinaryOperatorNode) anode).getOperator().getOperatorText();
+ String op = ((IBinaryOperatorNode) anode).getOperator()
+ .getOperatorText();
if (op.contains("==") || !op.contains("="))
isAssignment = false;
- }
-
+ }
+
writeGetSetPrefix(!isAssignment);
write(node.getName());
write(ASEmitterTokens.PAREN_OPEN);
@@ -460,13 +475,12 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
}
else
{
- rightSide = ((IBinaryOperatorNode) pnode)
+ rightSide = ((IBinaryOperatorNode) parentNode)
.getRightOperandNode();
}
}
write(ASEmitterTokens.PAREN_CLOSE);
-
}
else if (emitName)
{
@@ -474,6 +488,8 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
}
}
+ //--------------------------------------------------------------------------
+
@Override
protected void emitSuperCall(IASNode node, String type)
{
@@ -494,7 +510,7 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
fnode = (IFunctionNode) fcnode
.getAncestorOfType(IFunctionNode.class);
}
-
+
if (fnode.isConstructor() && !hasSuperClass(fnode))
return;
@@ -617,7 +633,9 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
{
IASNode leftNode = node.getLeftOperandNode();
- ICompilerProject project = getWalker().getProject();
+ if (project == null)
+ project = getWalker().getProject();
+
IDefinition def = node.resolve(project);
boolean isStatic = false;
if (def != null && def.isStatic())
@@ -636,19 +654,15 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
@Override
protected void emitObjectDefineProperty(IAccessorNode node)
{
- /*
- Class.prototype.get_property = function()
- {
- // body;
- };
- */
- ICompilerProject project = getWalker().getProject();
-
FunctionNode fn = (FunctionNode) node;
fn.parseFunctionBody(problems);
IFunctionDefinition definition = node.getDefinition();
ITypeDefinition type = (ITypeDefinition) definition.getParent();
+
+ if (project == null)
+ project = getWalker().getProject();
+
getDoc().emitMethodDoc(fn, project);
write(type.getQualifiedName());
if (!node.hasModifier(ASModifier.STATIC))
@@ -679,7 +693,7 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
@Override
public IDocEmitter getDocEmitter()
{
- return new JSFlexJSGoogDocEmitter(this);
+ return new JSFlexJSDocEmitter(this);
}
@Override
@@ -692,11 +706,14 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
if (type == null)
return;
- FlexJSProject project = (FlexJSProject) getWalker().getProject();
- ASProjectScope projectScope = (ASProjectScope) project.getScope();
+ if (project == null)
+ project = getWalker().getProject();
+
+ FlexJSProject flexProject = (FlexJSProject) project;
+ ASProjectScope projectScope = (ASProjectScope) flexProject.getScope();
ICompilationUnit cu = projectScope
.getCompilationUnitForDefinition(type);
- ArrayList<String> list = project.getRequires(cu);
+ ArrayList<String> list = flexProject.getRequires(cu);
String cname = type.getQualifiedName();
ArrayList<String> writtenInstances = new ArrayList<String>();
@@ -712,37 +729,7 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
if (imp.equals(cname))
continue;
- if (imp.equals("Array"))
- continue;
- if (imp.equals("Boolean"))
- continue;
- if (imp.equals("decodeURI"))
- continue;
- if (imp.equals("decodeURIComponent"))
- continue;
- if (imp.equals("encodeURI"))
- continue;
- if (imp.equals("encodeURIComponent"))
- continue;
- if (imp.equals("Error"))
- continue;
- if (imp.equals("Function"))
- continue;
- if (imp.equals("JSON"))
- continue;
- if (imp.equals("Number"))
- continue;
- if (imp.equals("int"))
- continue;
- if (imp.equals("Object"))
- continue;
- if (imp.equals("RegExp"))
- continue;
- if (imp.equals("String"))
- continue;
- if (imp.equals("uint"))
- continue;
- if (imp.equals("Date"))
+ if (NativeUtils.isNative(imp))
continue;
if (writtenInstances.indexOf(imp) == -1)