flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aha...@apache.org
Subject [1/3] git commit: [flex-falcon] [refs/heads/develop] - add support for e4x syntax, including cheap filters where we assume that the first tokens apply to the node
Date Fri, 13 Nov 2015 05:34:12 GMT
Repository: flex-falcon
Updated Branches:
  refs/heads/develop cc85f5032 -> 6b74cd0eb


add support for e4x syntax, including cheap filters where we assume that the first tokens
apply to the node


Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/20bd41a8
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/20bd41a8
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/20bd41a8

Branch: refs/heads/develop
Commit: 20bd41a8e9935197827d17277333efdacbd43f86
Parents: 0a9e4a9
Author: Alex Harui <aharui@apache.org>
Authored: Thu Nov 12 20:11:06 2015 -0800
Committer: Alex Harui <aharui@apache.org>
Committed: Thu Nov 12 21:33:33 2015 -0800

----------------------------------------------------------------------
 .../js/flexjs/TestFlexJSGlobalClasses.java      | 130 +++++++++++++++++++
 .../flex/compiler/internal/test/TestBase.java   |   1 +
 .../codegen/js/flexjs/JSFlexJSEmitter.java      |  96 +++++++++++++-
 .../internal/codegen/js/goog/JSGoogEmitter.java |   7 +
 .../codegen/js/jx/FunctionCallEmitter.java      |  19 ++-
 .../internal/codegen/js/jx/LiteralEmitter.java  |   5 +-
 .../codegen/js/jx/MemberAccessEmitter.java      |  60 ++++-----
 7 files changed, 283 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/20bd41a8/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalClasses.java
----------------------------------------------------------------------
diff --git a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalClasses.java
b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalClasses.java
index cfec38e..af0b8f7 100644
--- a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalClasses.java
+++ b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalClasses.java
@@ -22,9 +22,12 @@ package org.apache.flex.compiler.internal.codegen.js.flexjs;
 import org.apache.flex.compiler.driver.IBackend;
 import org.apache.flex.compiler.internal.codegen.js.goog.TestGoogGlobalClasses;
 import org.apache.flex.compiler.internal.driver.js.flexjs.FlexJSBackend;
+import org.apache.flex.compiler.tree.as.IASNode;
 import org.apache.flex.compiler.tree.as.IFunctionNode;
+import org.apache.flex.compiler.tree.as.IUnaryOperatorNode;
 import org.apache.flex.compiler.tree.as.IVariableNode;
 import org.junit.Test;
+import org.junit.Ignore;
 
 /**
  * @author Erik de Bruin
@@ -170,4 +173,131 @@ public class TestFlexJSGlobalClasses extends TestGoogGlobalClasses
         assertOut("var /** @type {Array} */ a = new Array(['Hello', 'World'])");
     }
 
+    @Test
+    public void testXML()
+    {
+        IVariableNode node = getVariable("var a:XML = new XML(\"<top attr1='cat'><child
attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");");
+        asBlockWalker.visitVariable(node);
+        assertOut("var /** @type {XML} */ a = new XML(\"<top attr1='cat'><child
attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\")");
+    }
+    
+    @Test
+    public void testXMLLiteral()
+    {
+        IVariableNode node = getVariable("var a:XML = <top attr1='cat'><child attr2='dog'><grandchild
attr3='fish'>text</grandchild></child></top>");
+        asBlockWalker.visitVariable(node);
+        assertOut("var /** @type {XML} */ a = new XML( \"<top attr1='cat'><child
attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\")
");
+    }
+    
+    @Test
+    public void testXMLDelete()
+    {
+        IUnaryOperatorNode node = getUnaryNode("var a:XML = new XML(\"<top attr1='cat'><child
attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");delete
a.child;");
+        asBlockWalker.visitUnaryOperator(node);
+        assertOut("delete a.child");
+    }
+    
+    @Test
+    public void testXMLListDelete()
+    {
+        IUnaryOperatorNode node = getUnaryNode("var a:XML = new XML(\"<top attr1='cat'><child
attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");delete
a.child[0];");
+        asBlockWalker.visitUnaryOperator(node);
+        assertOut("a.child._as3_removeChildAt(0)");
+    }
+    
+    @Test
+    public void testXMLNameFunction()
+    {
+    	IVariableNode node = getVariable("var a:XML = new XML(\"<top attr1='cat'><child
attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");var
b:String = a.name();");
+        IASNode parentNode = node.getParent();
+        node = (IVariableNode) parentNode.getChild(1);
+        asBlockWalker.visitVariable(node);
+        assertOut("var /** @type {string} */ b = a._as3_name()");
+    }
+    
+    @Test
+    public void testXMLDoubleDot()
+    {
+        IVariableNode node = getVariable("var a:XML = new XML(\"<top attr1='cat'><child
attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");var
b:XMLList = a..child;");
+        IASNode parentNode = node.getParent();
+        node = (IVariableNode) parentNode.getChild(1);
+        asBlockWalker.visitVariable(node);
+        assertOut("var /** @type {XMLList} */ b = a.descendants('child')");
+    }
+    
+    @Test
+    public void testXMLAttribute()
+    {
+        IVariableNode node = getVariable("var a:XML = new XML(\"<top attr1='cat'><child
attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");var
b:XMLList = a.@attr1;");
+        IASNode parentNode = node.getParent();
+        node = (IVariableNode) parentNode.getChild(1);
+        asBlockWalker.visitVariable(node);
+        assertOut("var /** @type {XMLList} */ b = a.attribute('attr1')");
+    }
+    
+    @Test
+    public void testXMLFilter()
+    {
+        IVariableNode node = getVariable("var a:XML = new XML(\"<top attr1='cat'><child
attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");var
b:XMLList = a..grandchild.(@attr2 == 'fish');");
+        IASNode parentNode = node.getParent();
+        node = (IVariableNode) parentNode.getChild(1);
+        asBlockWalker.visitVariable(node);
+        assertOut("var /** @type {XMLList} */ b = a.descendants('grandchild').filter(function(node){node.attribute('attr2')
== 'fish'})");
+    }
+    
+    @Ignore
+    public void testNamespaceNoArg()
+    {
+        IVariableNode node = getVariable("var a:Namespace = new Namespace();");
+        asBlockWalker.visitVariable(node);
+        assertOut("var /** @type {Array} */ a = new Array(['Hello', 'World'])");
+    }
+    
+    @Ignore
+    public void testNamespaceOneArg()
+    {
+        IVariableNode node = getVariable("var a:Namespace = new Namespace('foo');");
+        asBlockWalker.visitVariable(node);
+        assertOut("var /** @type {Array} */ a = new Array(['Hello', 'World'])");
+    }
+    
+    @Ignore
+    public void testNamespaceTwoArg()
+    {
+        IVariableNode node = getVariable("var a:Namespace = new Namespace('foo', 'bar');");
+        asBlockWalker.visitVariable(node);
+        assertOut("var /** @type {Array} */ a = new Array(['Hello', 'World'])");
+    }
+    
+    @Ignore
+    public void testNamespaceThreeArg()
+    {
+        IVariableNode node = getVariable("var a:Namespace = new Namespace('foo', 'bar', 'baz');");
+        asBlockWalker.visitVariable(node);
+        assertOut("var /** @type {Array} */ a = new Array(['Hello', 'World'])");
+    }
+    
+    @Ignore
+    public void testQNameNoArg()
+    {
+        IVariableNode node = getVariable("var a:QName = new QName();");
+        asBlockWalker.visitVariable(node);
+        assertOut("var /** @type {Array} */ a = new Array(['Hello', 'World'])");
+    }
+    
+    @Ignore
+    public void testQNameTwoArg()
+    {
+        IVariableNode node = getVariable("var a:QName = new QName(new Namespace('foo'), 'bar');");
+        asBlockWalker.visitVariable(node);
+        assertOut("var /** @type {Array} */ a = new Array(['Hello', 'World'])");
+    }
+
+    @Ignore
+    public void testQNameOneArg()
+    {
+        IVariableNode node = getVariable("var a:QName = new QName(new QName(new Namespace('foo'),
'bar'));");
+        asBlockWalker.visitVariable(node);
+        assertOut("var /** @type {Array} */ a = new Array(['Hello', 'World'])");
+    }
 }

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/20bd41a8/compiler.jx.tests/src/org/apache/flex/compiler/internal/test/TestBase.java
----------------------------------------------------------------------
diff --git a/compiler.jx.tests/src/org/apache/flex/compiler/internal/test/TestBase.java b/compiler.jx.tests/src/org/apache/flex/compiler/internal/test/TestBase.java
index 3d1cb20..7894d85 100644
--- a/compiler.jx.tests/src/org/apache/flex/compiler/internal/test/TestBase.java
+++ b/compiler.jx.tests/src/org/apache/flex/compiler/internal/test/TestBase.java
@@ -111,6 +111,7 @@ public class TestBase implements ITestBase
 
         if (project == null)
         	project = new FlexProject(workspace);
+        project.setProblems(errors);
         FlexProjectConfigurator.configure(project);
 
         backend = createBackend();

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/20bd41a8/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 24d35d5..feea0c7 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
@@ -24,7 +24,9 @@ import java.io.FilterWriter;
 import org.apache.flex.compiler.codegen.js.flexjs.IJSFlexJSEmitter;
 import org.apache.flex.compiler.codegen.js.goog.IJSGoogDocEmitter;
 import org.apache.flex.compiler.definitions.IClassDefinition;
+import org.apache.flex.compiler.definitions.IDefinition;
 import org.apache.flex.compiler.definitions.IPackageDefinition;
+import org.apache.flex.compiler.definitions.ITypeDefinition;
 import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
 import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitter;
 import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
@@ -49,7 +51,10 @@ import org.apache.flex.compiler.internal.codegen.js.jx.SelfReferenceEmitter;
 import org.apache.flex.compiler.internal.codegen.js.jx.SuperCallEmitter;
 import org.apache.flex.compiler.internal.codegen.js.jx.VarDeclarationEmitter;
 import org.apache.flex.compiler.internal.projects.FlexJSProject;
+import org.apache.flex.compiler.internal.tree.as.DynamicAccessNode;
 import org.apache.flex.compiler.internal.tree.as.IdentifierNode;
+import org.apache.flex.compiler.internal.tree.as.MemberAccessExpressionNode;
+import org.apache.flex.compiler.internal.tree.as.TernaryOperatorNode;
 import org.apache.flex.compiler.projects.ICompilerProject;
 import org.apache.flex.compiler.tree.ASTNodeID;
 import org.apache.flex.compiler.tree.as.IASNode;
@@ -69,7 +74,9 @@ import org.apache.flex.compiler.tree.as.ILiteralNode;
 import org.apache.flex.compiler.tree.as.IMemberAccessExpressionNode;
 import org.apache.flex.compiler.tree.as.ISetterNode;
 import org.apache.flex.compiler.tree.as.ITypedExpressionNode;
+import org.apache.flex.compiler.tree.as.IUnaryOperatorNode;
 import org.apache.flex.compiler.tree.as.IVariableNode;
+import org.apache.flex.compiler.utils.ASNodeUtils;
 
 /**
  * Concrete implementation of the 'FlexJS' JavaScript production.
@@ -343,10 +350,13 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
     @Override
     public void emitE4XFilter(IMemberAccessExpressionNode node)
     {
-        // ToDo (erikdebruin): implement E4X replacement !?!
-        write(ASEmitterTokens.SINGLE_QUOTE);
-        write("E4XFilter");
-        write(ASEmitterTokens.SINGLE_QUOTE);
+    	getWalker().walk(node.getLeftOperandNode());
+    	write(".filter(function(node){node.");
+    	String s = stringifyNode(node.getRightOperandNode());
+    	if (s.startsWith("(") && s.endsWith(")"))
+    		s = s.substring(1, s.length() - 1);
+    	write(s);
+    	write("})");
     }
 
     @Override
@@ -447,4 +457,82 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
     	else
     		System.out.println("unexpected node in emitClosureEnd");
     }
+    
+    @Override
+    public void emitUnaryOperator(IUnaryOperatorNode node)
+    {
+        if (node.getNodeID() == ASTNodeID.Op_DeleteID)
+        {
+        	if (node.getChild(0).getNodeID() == ASTNodeID.ArrayIndexExpressionID)
+        	{
+        		if (node.getChild(0).getChild(0).getNodeID() == ASTNodeID.MemberAccessExpressionID)
+        		{
+        			MemberAccessExpressionNode obj = (MemberAccessExpressionNode)(node.getChild(0).getChild(0));
+        			if (isXMLList(obj))
+        			{
+        		        if (ASNodeUtils.hasParenOpen(node))
+        		            write(ASEmitterTokens.PAREN_OPEN);
+        		        
+        	            getWalker().walk(obj);
+        	            DynamicAccessNode dan = (DynamicAccessNode)(node.getChild(0));
+        	            IASNode indexNode = dan.getChild(1);
+        	            write("._as3_removeChildAt(");
+        	            getWalker().walk(indexNode);
+        	            write(")");
+        		        if (ASNodeUtils.hasParenClose(node))
+        		            write(ASEmitterTokens.PAREN_CLOSE);
+        		        return;
+        			}
+        		}
+        	}
+        }
+        else if (node.getNodeID() == ASTNodeID.Op_AtID)
+        {
+        	write("attribute('");
+            getWalker().walk(node.getOperandNode());
+        	write("')");
+        	return;
+        }
+
+        super.emitUnaryOperator(node);
+
+    }
+
+    /**
+     * resolveType on an XML expression returns null
+     * (see IdentiferNode.resolveType).
+     * So, we have to walk the tree ourselves and resolve
+     * individual pieces.
+     * @param obj
+     * @return
+     */
+    public boolean isXMLList(MemberAccessExpressionNode obj)
+    {
+    	IExpressionNode leftNode = obj.getLeftOperandNode();
+    	IExpressionNode rightNode = obj.getRightOperandNode();
+    	ASTNodeID rightID = rightNode.getNodeID();
+    	if (rightID == ASTNodeID.IdentifierID)
+    	{
+    		if (isXML(leftNode))
+    			return true;
+    	}
+    	else if (rightID == ASTNodeID.MemberAccessExpressionID)
+    		return isXMLList((MemberAccessExpressionNode) rightNode);
+    	return false;
+    }
+    
+    /**
+     * resolveType on an XML expression returns null
+     * (see IdentiferNode.resolveType).
+     * So, we have to walk the tree ourselves and resolve
+     * individual pieces.
+     * @param obj
+     * @return
+     */
+    public boolean isXML(IExpressionNode obj)
+    {
+		// See if the left side is XML or XMLList
+		IDefinition leftDef = obj.resolveType(getWalker().getProject());
+		return IdentifierNode.isXMLish(leftDef, getWalker().getProject());
+    }
 }

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/20bd41a8/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/goog/JSGoogEmitter.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/goog/JSGoogEmitter.java
b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/goog/JSGoogEmitter.java
index 2250e40..7354ef6 100644
--- a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/goog/JSGoogEmitter.java
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/goog/JSGoogEmitter.java
@@ -880,6 +880,13 @@ public class JSGoogEmitter extends JSEmitter implements IJSGoogEmitter
             		getWalker().walk(((MemberAccessExpressionNode)node).getLeftOperandNode());
                     emitClosureEnd(((MemberAccessExpressionNode)node).getLeftOperandNode());
             	}
+            	else if (node.getNodeID() == ASTNodeID.XMLContentID)
+            	{
+            		write("new XML");
+            		writeToken(ASEmitterTokens.PAREN_OPEN);
+            		getWalker().walk(node);
+            		writeToken(ASEmitterTokens.PAREN_CLOSE);
+            	}
             	else
             		getWalker().walk(node);
             }

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/20bd41a8/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/FunctionCallEmitter.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/FunctionCallEmitter.java
b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/FunctionCallEmitter.java
index a3d6910..f4431af 100644
--- a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/FunctionCallEmitter.java
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/FunctionCallEmitter.java
@@ -66,6 +66,7 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
             IDefinition def = null;
 
             boolean isClassCast = false;
+            boolean isXMLMethod = false;
 
             if (node.isNewExpression())
             {
@@ -95,6 +96,13 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
             {
                 def = node.getNameNode().resolve(getProject());
 
+                if (def == null)
+                {
+                	IExpressionNode nameNode = node.getNameNode();
+                	if (nameNode.getNodeID() == ASTNodeID.MemberAccessExpressionID)
+                		if (fjs.isXML((IExpressionNode) nameNode.getChild(0)))
+                			isXMLMethod = true;
+                }
                 isClassCast = (def instanceof ClassDefinition || def instanceof InterfaceDefinition)
                         && !(NativeUtils.isJSNative(def.getBaseName()));
             }
@@ -146,7 +154,16 @@ public class FunctionCallEmitter extends JSSubEmitter implements ISubEmitter<IFu
                         return;
                     }
                 }
-                getWalker().walk(node.getNameNode());
+                if (isXMLMethod)
+                {
+                	String s = fjs.stringifyNode(node.getNameNode());
+                	int lastDot = s.lastIndexOf('.');
+                	String name = s.substring(lastDot + 1);
+                	s = s.substring(0, lastDot + 1) + "_as3_" + name;
+                	write(s);
+                }
+                else
+                	getWalker().walk(node.getNameNode());
                 write(ASEmitterTokens.PAREN_OPEN);
                 fjs.walkArguments(node.getArgumentNodes());
                 write(ASEmitterTokens.PAREN_CLOSE);

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/20bd41a8/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/LiteralEmitter.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/LiteralEmitter.java
b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/LiteralEmitter.java
index 8f26374..45c8966 100644
--- a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/LiteralEmitter.java
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/LiteralEmitter.java
@@ -45,7 +45,10 @@ public class LiteralEmitter extends JSSubEmitter implements
         {
             if (node.getLiteralType() == LiteralType.XML)
             {
-                write("'" + s + "'");
+            	if (s.contains("'"))
+            		write("\"" + s + "\"");
+            	else
+            		write("'" + s + "'");
 
                 isWritten = true;
             }

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/20bd41a8/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/MemberAccessEmitter.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/MemberAccessEmitter.java
b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/MemberAccessEmitter.java
index 8b5fd3b..b572e8d 100644
--- a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/MemberAccessEmitter.java
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/MemberAccessEmitter.java
@@ -24,6 +24,7 @@ import org.apache.flex.compiler.codegen.js.IJSEmitter;
 import org.apache.flex.compiler.definitions.IDefinition;
 import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
 import org.apache.flex.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitter;
 import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitterTokens;
 import org.apache.flex.compiler.internal.definitions.AccessorDefinition;
 import org.apache.flex.compiler.internal.definitions.FunctionDefinition;
@@ -34,9 +35,11 @@ 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.IClassNode;
+import org.apache.flex.compiler.tree.as.IExpressionNode;
 import org.apache.flex.compiler.tree.as.IIdentifierNode;
 import org.apache.flex.compiler.tree.as.ILanguageIdentifierNode;
 import org.apache.flex.compiler.tree.as.IMemberAccessExpressionNode;
+import org.apache.flex.compiler.tree.as.IOperatorNode.OperatorType;
 import org.apache.flex.compiler.utils.ASNodeUtils;
 
 public class MemberAccessEmitter extends JSSubEmitter implements
@@ -58,6 +61,33 @@ public class MemberAccessEmitter extends JSSubEmitter implements
         IASNode rightNode = node.getRightOperandNode();
 
         IDefinition def = node.resolve(getProject());
+        if (def == null)
+        {
+        	// could be XML
+        	JSFlexJSEmitter fjs = (JSFlexJSEmitter)getEmitter();
+        	if (fjs.isXML((IExpressionNode) leftNode) &&
+        			node.getOperator() == OperatorType.DESCENDANT_ACCESS)
+        	{
+        		writeLeftSide(node, leftNode, rightNode);
+        		write(".descendants('");
+        		String s = fjs.stringifyNode(rightNode);
+        		int dot = s.indexOf('.');
+        		if (dot != -1)
+        		{
+        			String name = s.substring(0, dot);
+        			String afterDot = s.substring(dot);
+        			write(name);
+        			write("')");
+        			write(afterDot);
+        		}
+        		else
+        		{
+        			write(s);
+        			write("')");
+        		}
+        		return;
+        	}
+        }
         boolean isStatic = false;
         if (def != null && def.isStatic())
             isStatic = true;
@@ -116,35 +146,7 @@ public class MemberAccessEmitter extends JSSubEmitter implements
                 rightDef = ((IIdentifierNode) rightNode)
                         .resolve(getProject());
 
-            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);
-                return 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);
-                return false;
-            }
-            else if (leftNode.getNodeID() != ASTNodeID.SuperID)
+            if (leftNode.getNodeID() != ASTNodeID.SuperID)
             {
                 getWalker().walk(node.getLeftOperandNode());
             }


Mime
View raw message