switch XML member access to child() calls
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/1fb6f371 Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/1fb6f371 Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/1fb6f371 Branch: refs/heads/develop Commit: 1fb6f371f836f4871f6afbecf8ec31332f555ccc Parents: f6e619c Author: Alex Harui <[email protected]> Authored: Wed Nov 18 14:44:15 2015 -0800 Committer: Alex Harui <[email protected]> Committed: Wed Nov 18 14:44:15 2015 -0800 ---------------------------------------------------------------------- .../js/flexjs/TestFlexJSGlobalClasses.java | 48 +++++++++++++--- .../codegen/js/flexjs/JSFlexJSEmitter.java | 8 +-- .../codegen/js/jx/MemberAccessEmitter.java | 58 +++++++++++++------- 3 files changed, 81 insertions(+), 33 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/1fb6f371/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 ffe44b1..c837390 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 @@ -190,6 +190,26 @@ public class TestFlexJSGlobalClasses extends TestGoogGlobalClasses } @Test + public void testXMLSingleDot() + { + 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.child('child')"); + } + + @Test + public void testXMLSingleDotChain() + { + 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.grandchild;"); + IASNode parentNode = node.getParent(); + node = (IVariableNode) parentNode.getChild(1); + asBlockWalker.visitVariable(node); + assertOut("var /** @type {XMLList} */ b = a.child('child').child('grandchild')"); + } + + @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;"); @@ -202,7 +222,7 @@ public class TestFlexJSGlobalClasses extends TestGoogGlobalClasses { IUnaryOperatorNode node = getUnaryNode("var a:XML = new XML(\"<top attr1='cat'><child attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");delete a.child.grandchild;"); asBlockWalker.visitUnaryOperator(node); - assertOut("a.child.removeChild('grandchild')"); + assertOut("a.child('child').removeChild('grandchild')"); } @Test @@ -211,7 +231,7 @@ public class TestFlexJSGlobalClasses extends TestGoogGlobalClasses IUnaryOperatorNode node = getUnaryNode("public var a:XML = new XML(\"<top attr1='cat'><child attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");private function foo() { delete this.a.child.grandchild;}", WRAP_LEVEL_CLASS); asBlockWalker.visitUnaryOperator(node); - assertOut("this.a.child.removeChild('grandchild')"); + assertOut("this.a.child('child').removeChild('grandchild')"); } @Test @@ -219,7 +239,7 @@ public class TestFlexJSGlobalClasses extends TestGoogGlobalClasses { IUnaryOperatorNode node = getUnaryNode("var a:XML = new XML(\"<top attr1='cat'><child attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");var b:Object = { xml: a};delete XML(b.xml).child.grandchild;"); asBlockWalker.visitUnaryOperator(node); - assertOut("org.apache.flex.utils.Language.as(b.xml, XML, true).child.removeChild('grandchild')"); + assertOut("org.apache.flex.utils.Language.as(b.xml, XML, true).child('child').removeChild('grandchild')"); } @Test @@ -227,7 +247,7 @@ public class TestFlexJSGlobalClasses extends TestGoogGlobalClasses { IUnaryOperatorNode node = getUnaryNode("var a:XML = new XML(\"<top attr1='cat'><child attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");var b:Object = { xml: a};delete (b.xml as XML).child.grandchild;"); asBlockWalker.visitUnaryOperator(node); - assertOut("org.apache.flex.utils.Language.as(b.xml, XML).child.removeChild('grandchild')"); + assertOut("org.apache.flex.utils.Language.as(b.xml, XML).child('child').removeChild('grandchild')"); } @Test @@ -235,7 +255,7 @@ public class TestFlexJSGlobalClasses extends TestGoogGlobalClasses { 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.removeChildAt(0)"); + assertOut("a.child('child').removeChildAt(0)"); } @Test @@ -243,7 +263,7 @@ public class TestFlexJSGlobalClasses extends TestGoogGlobalClasses { IUnaryOperatorNode node = getUnaryNode("var a:XML = new XML(\"<top attr1='cat'><child attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");delete a.child.grandchild[0];"); asBlockWalker.visitUnaryOperator(node); - assertOut("a.child.grandchild.removeChildAt(0)"); + assertOut("a.child('child').child('grandchild').removeChildAt(0)"); } @Test @@ -252,7 +272,7 @@ public class TestFlexJSGlobalClasses extends TestGoogGlobalClasses IUnaryOperatorNode node = getUnaryNode("public var a:XML = new XML(\"<top attr1='cat'><child attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");private function foo() { delete this.a.child.grandchild[0];}", WRAP_LEVEL_CLASS); asBlockWalker.visitUnaryOperator(node); - assertOut("this.a.child.grandchild.removeChildAt(0)"); + assertOut("this.a.child('child').child('grandchild').removeChildAt(0)"); } @Test @@ -260,7 +280,7 @@ public class TestFlexJSGlobalClasses extends TestGoogGlobalClasses { IUnaryOperatorNode node = getUnaryNode("var a:XML = new XML(\"<top attr1='cat'><child attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");var b:Object = { xml: a};delete XML(b.xml).child.grandchild[0];"); asBlockWalker.visitUnaryOperator(node); - assertOut("org.apache.flex.utils.Language.as(b.xml, XML, true).child.grandchild.removeChildAt(0)"); + assertOut("org.apache.flex.utils.Language.as(b.xml, XML, true).child('child').child('grandchild').removeChildAt(0)"); } @Test @@ -268,7 +288,7 @@ public class TestFlexJSGlobalClasses extends TestGoogGlobalClasses { IUnaryOperatorNode node = getUnaryNode("var a:XML = new XML(\"<top attr1='cat'><child attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");var b:Object = { xml: a};delete (b.xml as XML).child.grandchild[0];"); asBlockWalker.visitUnaryOperator(node); - assertOut("org.apache.flex.utils.Language.as(b.xml, XML).child.grandchild.removeChildAt(0)"); + assertOut("org.apache.flex.utils.Language.as(b.xml, XML).child('child').child('grandchild').removeChildAt(0)"); } @Test @@ -282,6 +302,16 @@ public class TestFlexJSGlobalClasses extends TestGoogGlobalClasses } @Test + public void testXMLListLengthFunction() + { + IVariableNode node = getVariable("var a:XML = new XML(\"<top attr1='cat'><child attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");var b:int = a.child.length();"); + IASNode parentNode = node.getParent(); + node = (IVariableNode) parentNode.getChild(1); + asBlockWalker.visitVariable(node); + assertOut("var /** @type {number} */ b = a.child('child').length()"); + } + + @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;"); http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/1fb6f371/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 2677035..c87cadc 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 @@ -495,11 +495,11 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter if (ASNodeUtils.hasParenOpen(node)) write(ASEmitterTokens.PAREN_OPEN); - String s = stringifyNode(node.getChild(0)); - int c = s.lastIndexOf("."); - write(s.substring(0, c)); + String s = stringifyNode(obj.getLeftOperandNode()); + write(s); write(".removeChild('"); - write(s.substring(c + 1)); + s = stringifyNode(obj.getRightOperandNode()); + write(s); write("')"); if (ASNodeUtils.hasParenClose(node)) write(ASEmitterTokens.PAREN_CLOSE); http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/1fb6f371/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 b572e8d..2f5aa55 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 @@ -29,7 +29,10 @@ 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; import org.apache.flex.compiler.internal.projects.FlexJSProject; +import org.apache.flex.compiler.internal.tree.as.FunctionCallNode; import org.apache.flex.compiler.internal.tree.as.GetterNode; +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.UnaryOperatorAtNode; import org.apache.flex.compiler.projects.ICompilerProject; import org.apache.flex.compiler.tree.ASTNodeID; @@ -63,29 +66,44 @@ public class MemberAccessEmitter extends JSSubEmitter implements IDefinition def = node.resolve(getProject()); if (def == null) { + IASNode parentNode = node.getParent(); // could be XML JSFlexJSEmitter fjs = (JSFlexJSEmitter)getEmitter(); - if (fjs.isXML((IExpressionNode) leftNode) && - node.getOperator() == OperatorType.DESCENDANT_ACCESS) + boolean isXML = false; + if (leftNode instanceof MemberAccessExpressionNode) + isXML = fjs.isXMLList((MemberAccessExpressionNode)leftNode); + else if (leftNode instanceof IExpressionNode) + isXML = fjs.isXML((IExpressionNode)leftNode); + if (isXML) { - 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 descendant = (node.getOperator() == OperatorType.DESCENDANT_ACCESS); + boolean child = (node.getOperator() == OperatorType.MEMBER_ACCESS) && + (!(parentNode instanceof FunctionCallNode)) && + rightNode.getNodeID() != ASTNodeID.Op_AtID; + if (descendant || child) + { + writeLeftSide(node, leftNode, rightNode); + if (descendant) + write(".descendants('"); + if (child) + write(".child('"); + 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;
