You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by gr...@apache.org on 2020/04/02 09:50:42 UTC

[royale-compiler] 07/08: Additions to XML and XML list to support more e4X conformance. Aligned with framework classes (extra unit tests)

This is an automated email from the ASF dual-hosted git repository.

gregdove pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git

commit 4c1b2f4aa1b11b58cad648c912ac633ebecf0590
Author: greg-dove <gr...@gmail.com>
AuthorDate: Thu Apr 2 22:38:12 2020 +1300

    Additions to XML and XML list to support more e4X conformance. Aligned with framework classes (extra unit tests)
---
 .../codegen/js/jx/BinaryOperatorEmitter.java       | 40 ++++++++++++++++------
 .../codegen/js/jx/DynamicAccessEmitter.java        |  2 +-
 .../internal/codegen/js/jx/ForEachEmitter.java     |  2 +-
 .../codegen/js/jx/MemberAccessEmitter.java         |  2 +-
 .../codegen/js/royale/JSRoyaleEmitter.java         | 23 +++++++++----
 .../internal/codegen/js/utils/EmitterUtils.java    | 12 ++++---
 .../codegen/js/royale/TestRoyaleGlobalClasses.java |  2 +-
 7 files changed, 57 insertions(+), 26 deletions(-)

diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
index 2aa2e77..2138d61 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
@@ -192,19 +192,35 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
                 	MemberAccessExpressionNode xmlNode = (MemberAccessExpressionNode)leftSide;
                 	if (node.getNodeID() == ASTNodeID.Op_AssignId)
                 	{
+                		boolean wrapQuotes = true;
 	                    getWalker().walk(xmlNode.getLeftOperandNode());
 	                    IExpressionNode rightSide = xmlNode.getRightOperandNode();
 	                    if (rightSide instanceof UnaryOperatorAtNode)
 	                    {
 		                    write(".setAttribute('");
-		                    getWalker().walk(((UnaryOperatorAtNode)rightSide).getChild(0));
+		                    getWalker().walk(rightSide.getChild(0));
 	                    }
+	                    else if (rightSide instanceof IDynamicAccessNode && ((IDynamicAccessNode) rightSide).getLeftOperandNode().getNodeID() == ASTNodeID.Op_AtID) {
+							write(".setAttribute(");
+							wrapQuotes = false;
+							getWalker().walk(((IDynamicAccessNode)rightSide).getRightOperandNode());
+						}
+	                    else if (rightSide instanceof INamespaceAccessExpressionNode) {
+							write(".setChild(");
+							write("new QName(");
+							getWalker().walk(((INamespaceAccessExpressionNode) rightSide).getLeftOperandNode());
+							write(",'");
+							getWalker().walk(((INamespaceAccessExpressionNode) rightSide).getRightOperandNode());
+							write("')");
+							wrapQuotes = false;
+						}
 	                    else
 	                    {
 		                    write(".setChild('");
 		                    getWalker().walk(rightSide);
 	                    }
-	                    write("', ");
+	                    if (wrapQuotes) write("'");
+	                    write(", ");
 	                    getWalker().walk(node.getRightOperandNode());
 	                    write(ASEmitterTokens.PAREN_CLOSE);
 	                    return;
@@ -240,7 +256,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
 	                    return;
                 	}
                 }
-                else if (isDynamicAccess && ((JSRoyaleEmitter)getEmitter()).isXML((IExpressionNode)lnode))
+                else if (isDynamicAccess && ((JSRoyaleEmitter)getEmitter()).isXMLish((IExpressionNode)lnode))
                 {
                 	DynamicAccessNode dyn = (DynamicAccessNode)rnode;
                 	ITypeDefinition type = dyn.getRightOperandNode().resolveType(getProject());
@@ -368,7 +384,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
             	DynamicAccessNode dyn = (DynamicAccessNode)leftSide;
             	IExpressionNode dynLeft = dyn.getLeftOperandNode();
             	ITypeDefinition type = dyn.getRightOperandNode().resolveType(getProject());
-            	if (((JSRoyaleEmitter)getEmitter()).isXML(dynLeft) && type.isInstanceOf("String", getProject()))
+            	if (((JSRoyaleEmitter)getEmitter()).isXMLish(dynLeft)/* && !SemanticUtils.isNumericType(type, getProject())*/) //type.isInstanceOf("String", getProject())
     			{
             		String field;
                 	if (node.getNodeID() == ASTNodeID.Op_AssignId)
@@ -377,17 +393,19 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
 	                    IExpressionNode rightSide = dyn.getRightOperandNode();
 	                    if (rightSide instanceof UnaryOperatorAtNode)
 	                    {
-		                    write(".setAttribute('");
-							field = fjs.stringifyNode(((UnaryOperatorAtNode)rightSide).getChild(0));
-							field = field.replace("\"", ""); // remove wrapping double-quotes
+		                    write(".setAttribute(");
+							field = fjs.stringifyNode((rightSide).getChild(0));
 	                    }
 	                    else
 	                    {
-		                    write(".setChild('");
+							write(".setChild(");
 							field = fjs.stringifyNode(rightSide);
-							field = field.replace("\"", ""); // remove wrapping double-quotes
 	                    }
-	                    write(field + "', ");
+						if (field.startsWith("\"") && field.endsWith("\"")) {
+							// remove wrapping double-quotes and swap to single quotes
+							field = "'" + field.substring(1, field.length() - 1) + "'";
+						}
+	                    write(field + ", ");
 	                    getWalker().walk(node.getRightOperandNode());
 	                    write(ASEmitterTokens.PAREN_CLOSE);
 	                    return;
@@ -576,7 +594,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
 				getWalker().walk(node.getRightOperandNode());
 				
 				if (node.getNodeID() == ASTNodeID.Op_InID &&
-						((JSRoyaleEmitter)getEmitter()).isXML(node.getRightOperandNode()))
+						((JSRoyaleEmitter)getEmitter()).isXMLish(node.getRightOperandNode()))
 				{
 					write(".elementNames()");
 				}
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java
index bdcb9c6..878b69a 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java
@@ -72,7 +72,7 @@ public class DynamicAccessEmitter extends JSSubEmitter implements
 	    	if (leftOperandNode instanceof MemberAccessExpressionNode)
 	    		isXML = fjs.isLeftNodeXMLish((MemberAccessExpressionNode)leftOperandNode);
 	    	else if (leftOperandNode instanceof IExpressionNode)
-	    		isXML = fjs.isXML((IExpressionNode)leftOperandNode);
+	    		isXML = fjs.isXMLish((IExpressionNode)leftOperandNode);
         	if (leftOperandNode instanceof MemberAccessExpressionNode)
         		isProxy = fjs.isProxy((MemberAccessExpressionNode)leftOperandNode);
         	else if (leftOperandNode instanceof IExpressionNode)
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ForEachEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ForEachEmitter.java
index 2994707..4920604 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ForEachEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ForEachEmitter.java
@@ -104,7 +104,7 @@ public class ForEachEmitter extends JSSubEmitter implements
         boolean isProxy = false;
         if (obj.getNodeID() == ASTNodeID.IdentifierID)
         {
-        	if (((JSRoyaleEmitter)getEmitter()).isXML((IdentifierNode)obj))
+        	if (((JSRoyaleEmitter)getEmitter()).isXMLish((IdentifierNode)obj))
         	{
         		write(".elementNames()");
         		isXML = true;
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MemberAccessEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MemberAccessEmitter.java
index 51d45b5..274cd4f 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MemberAccessEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/MemberAccessEmitter.java
@@ -108,7 +108,7 @@ public class MemberAccessEmitter extends JSSubEmitter implements
         	if (leftNode instanceof MemberAccessExpressionNode)
         		isXML = fjs.isLeftNodeXMLish(leftNode);
         	else if (leftNode != null)
-        		isXML = fjs.isXML(leftNode);
+        		isXML = fjs.isXMLish(leftNode);
 
 			if (!isXML) {
 				if (leftNode instanceof MemberAccessExpressionNode)
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java
index 0a05318..0626e79 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java
@@ -709,7 +709,7 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
     	{
         	if (getModel().inStaticInitializer)
         		if (!staticUsedNames.contains(name) && !NativeUtils.isJSNative(name)
-        				&& isGoogProvided(name) && !getModel().getCurrentClass().getQualifiedName().equals(name)
+        				&& isGoogProvided(name) && (getModel().getCurrentClass() == null || !getModel().getCurrentClass().getQualifiedName().equals(name))
         				&& (getModel().primaryDefinitionQName == null
         					|| !getModel().primaryDefinitionQName.equals(name)))
         			staticUsedNames.add(name);
@@ -1245,7 +1245,7 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
         		}
         		else if (node.getChild(0).getChild(0).getNodeID() == ASTNodeID.IdentifierID)
         		{
-        			if (isXML((IdentifierNode)(node.getChild(0).getChild(0))))
+        			if (isXMLish((IdentifierNode)(node.getChild(0).getChild(0))))
         			{
         		        if (ASNodeUtils.hasParenOpen(node))
         		            write(ASEmitterTokens.PAREN_OPEN);
@@ -1288,13 +1288,15 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
 
     		        IExpressionNode rightNode = obj.getRightOperandNode();
     	            String s = stringifyNode(obj.getLeftOperandNode());
-    	            boolean needsQuotes = rightNode.getNodeID() != ASTNodeID.Op_AtID;
+    	            boolean avoidMethodAccess = (rightNode instanceof IDynamicAccessNode && ((IDynamicAccessNode) rightNode).getLeftOperandNode().getNodeID() == ASTNodeID.Op_AtID);
+    	            boolean needsQuotes = rightNode.getNodeID() != ASTNodeID.Op_AtID
+                             && !avoidMethodAccess;
     	            write(s);
     	            write(".removeChild(");
     	            if (needsQuotes)
     	            	write("'");
     	            else
-    	            	write(s + ".");
+    	            	if (!avoidMethodAccess) write(s + ".");
     	            s = stringifyNode(rightNode);
     	            write(s);
     	            if (needsQuotes)
@@ -1353,6 +1355,15 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
         		DynamicAccessNode parentNode = (DynamicAccessNode)node.getParent();
         		if (EmitterUtils.writeE4xFilterNode(getWalker().getProject(), getModel(), node))
         			write("node.");
+        		if (node.getParent().getParent() != null
+                        && node.getParent().getParent().getParent() != null
+                        && node.getParent().getParent().getParent().getNodeID() == ASTNodeID.Op_DeleteID) {
+        		    write ("'@' + ");
+        		    //example : delete myXML.@[MyConst];
+        		    //output myXML.removeChild('@' + MyConst) <-- variant is handled in emulation class
+                    getWalker().walk(parentNode.getRightOperandNode());
+                    return;
+                }
             	write("attribute(");
         		getWalker().walk(parentNode.getRightOperandNode());
             	write(")");
@@ -1474,9 +1485,9 @@ public class JSRoyaleEmitter extends JSGoogEmitter implements IJSRoyaleEmitter
      * @param obj
      * @return
      */
-    public boolean isXML(IExpressionNode obj)
+    public boolean isXMLish(IExpressionNode obj)
     {
-		return EmitterUtils.isXML(obj, getWalker().getProject());
+		return EmitterUtils.isXMLish(obj, getWalker().getProject());
     }
 
     public MemberAccessExpressionNode getLastMAEInChain(MemberAccessExpressionNode node)
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/EmitterUtils.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/EmitterUtils.java
index 2e03bf2..0be6c74 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/EmitterUtils.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/EmitterUtils.java
@@ -751,16 +751,16 @@ public class EmitterUtils
      * @param obj
      * @return
      */
-    public static boolean isXML(IExpressionNode obj, ICompilerProject project )
+    public static boolean isXMLish(IExpressionNode obj, ICompilerProject project )
     {
         // See if the left side is XML or XMLList
         IDefinition leftDef = obj.resolveType(project);
         if (leftDef == null && obj.getNodeID() == ASTNodeID.MemberAccessExpressionID)
         {
-            return isXML(((MemberAccessExpressionNode)obj).getLeftOperandNode(), project);
+            return isXMLish(((MemberAccessExpressionNode)obj).getLeftOperandNode(), project);
         }
         else if (leftDef != null && leftDef.getBaseName().equals("*") && obj instanceof DynamicAccessNode) {
-            return isXML(((DynamicAccessNode)obj).getLeftOperandNode(), project);
+            return isXMLish(((DynamicAccessNode)obj).getLeftOperandNode(), project);
         }
         return SemanticUtils.isXMLish(leftDef, project);
     }
@@ -785,7 +785,7 @@ public class EmitterUtils
         IExpressionNode leftNode = obj.getLeftOperandNode();
         IExpressionNode rightNode = obj.getRightOperandNode();
         ASTNodeID rightID = rightNode.getNodeID();
-        if (rightID == ASTNodeID.IdentifierID)
+        if (rightID == ASTNodeID.IdentifierID || (rightID == ASTNodeID.NamespaceAccessExpressionID && rightNode.getChild(1).getNodeID() == ASTNodeID.IdentifierID))
         {
             IDefinition rightDef = rightNode.resolveType(project);
             if (rightDef != null)
@@ -800,6 +800,8 @@ public class EmitterUtils
         }
         else if (rightID == ASTNodeID.Op_AtID)
             return true;
+        else if (rightNode instanceof IDynamicAccessNode && ((IDynamicAccessNode) rightNode).getLeftOperandNode().getNodeID() == ASTNodeID.Op_AtID)
+            return true;
         return false;
     }
 
@@ -904,7 +906,7 @@ public class EmitterUtils
                 boolean isXML = leftNode instanceof MemberAccessExpressionNode
                         && isLeftNodeXMLish((MemberAccessExpressionNode) leftNode, project);
                 if (!isXML) {
-                    isXML = leftNode instanceof IExpressionNode && isXML((IExpressionNode)leftNode, project);
+                    isXML = leftNode instanceof IExpressionNode && isXMLish((IExpressionNode)leftNode, project);
                 }
                 if (isXML) {
                     //check argumentsNode
diff --git a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalClasses.java b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalClasses.java
index d090658..bae6cd4 100644
--- a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalClasses.java
+++ b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleGlobalClasses.java
@@ -1098,7 +1098,7 @@ public class TestRoyaleGlobalClasses extends TestGoogGlobalClasses
     {
     		IBinaryOperatorNode node = (IBinaryOperatorNode)getNode("var a:XMLList = new XMLList();a[a.length()] = <foo/>;a[a.length()] = <baz/>;", IBinaryOperatorNode.class);
         asBlockWalker.visitBinaryOperator(node);
-        assertOut("a[a.length()] = new XML( '<foo/>')");
+        assertOut("a.setChild(a.length(), new XML( '<foo/>'))");
     }
 
     @Test