Repository: flex-falcon Updated Branches: refs/heads/develop 50626db13 -> aac9a3864
fix more implicit type conversion scenarios Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/aac9a386 Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/aac9a386 Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/aac9a386 Branch: refs/heads/develop Commit: aac9a3864df6580302c35cf2db6870fe2ac45c09 Parents: 50626db Author: Alex Harui <[email protected]> Authored: Fri Aug 5 07:42:17 2016 -0700 Committer: Alex Harui <[email protected]> Committed: Fri Aug 5 07:42:17 2016 -0700 ---------------------------------------------------------------------- .../codegen/js/jx/BinaryOperatorEmitter.java | 61 +++++++++++++++++--- .../codegen/js/jx/VarDeclarationEmitter.java | 29 +++++++++- .../js/flexjs/TestFlexJSExpressions.java | 11 ++++ .../js/flexjs/TestFlexJSGlobalClasses.java | 25 ++++++++ .../codegen/js/flexjs/TestFlexJSStatements.java | 10 ++-- .../js/sourcemaps/TestSourceMapStatements.java | 4 +- 6 files changed, 124 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/aac9a386/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java index 29e58a9..1ac5e37 100644 --- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java +++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java @@ -21,6 +21,7 @@ package org.apache.flex.compiler.internal.codegen.js.jx; import org.apache.flex.compiler.codegen.ISubEmitter; import org.apache.flex.compiler.codegen.js.IJSEmitter; +import org.apache.flex.compiler.constants.IASLanguageConstants; 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; @@ -28,6 +29,7 @@ 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.projects.FlexJSProject; +import org.apache.flex.compiler.internal.tree.as.FunctionCallNode; 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; @@ -55,6 +57,11 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements // TODO (mschmalle) will remove this cast as more things get abstracted JSFlexJSEmitter fjs = (JSFlexJSEmitter) getEmitter(); + String op = node.getOperator().getOperatorText(); + boolean isAssignment = op.contains("=") + && !op.contains("==") + && !(op.startsWith("<") || op.startsWith(">") || op + .startsWith("!")); ASTNodeID id = node.getNodeID(); /* if (id == ASTNodeID.Op_InID @@ -88,6 +95,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements else { IExpressionNode leftSide = node.getLeftOperandNode(); + IDefinition leftDef = leftSide.resolveType(getWalker().getProject()); if (leftSide.getNodeID() == ASTNodeID.MemberAccessExpressionID) { IASNode lnode = leftSide.getChild(0); @@ -98,11 +106,6 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements if (lnode.getNodeID() == ASTNodeID.SuperID && rnodeDef instanceof AccessorDefinition) { - String op = node.getOperator().getOperatorText(); - boolean isAssignment = op.contains("=") - && !op.contains("==") - && !(op.startsWith("<") || op.startsWith(">") || op - .startsWith("!")); if (isAssignment) { ICompilerProject project = this.getProject(); @@ -247,7 +250,6 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements } else if (leftSide.getNodeID() == ASTNodeID.IdentifierID) { - IDefinition leftDef = leftSide.resolveType(getWalker().getProject()); if ((leftDef != null) && IdentifierNode.isXMLish(leftDef, getWalker().getProject())) { @@ -264,7 +266,46 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements } } - super_emitBinaryOperator(node); + boolean leftIsNumber = (leftDef != null && (leftDef.getQualifiedName().equals(IASLanguageConstants.Number) || + leftDef.getQualifiedName().equals(IASLanguageConstants._int) || + leftDef.getQualifiedName().equals(IASLanguageConstants.uint))); + IExpressionNode rNode = node.getRightOperandNode(); + IDefinition rightDef = rNode.resolveType(getWalker().getProject()); + boolean rightIsNumber = (rightDef != null && (rightDef.getQualifiedName().equals(IASLanguageConstants.Number) || + rightDef.getQualifiedName().equals(IASLanguageConstants._int) || + rightDef.getQualifiedName().equals(IASLanguageConstants.uint))); + if (leftIsNumber && !rightIsNumber && (rightDef == null || rightDef.getQualifiedName().equals(IASLanguageConstants.ANY_TYPE)) + && rNode.getNodeID() == ASTNodeID.FunctionCallID) + { + IExpressionNode fnNameNode = ((FunctionCallNode)rNode).getNameNode(); + if (fnNameNode.getNodeID() == ASTNodeID.MemberAccessExpressionID) + { + MemberAccessExpressionNode mae = (MemberAccessExpressionNode)fnNameNode; + IExpressionNode rightNode = mae.getRightOperandNode(); + rightIsNumber = rightNode.getNodeID() == ASTNodeID.IdentifierID && + ((IdentifierNode)rightNode).getName().equals("length") && + fjs.isXMLList(mae); + } + } + super_emitBinaryOperator(node, leftIsNumber, rightIsNumber); + if (leftDef != null && leftDef.getQualifiedName().equals(IASLanguageConstants.String) || (leftIsNumber && !rightIsNumber)) + { + if (rNode.getNodeID() != ASTNodeID.LiteralStringID && + rNode.getNodeID() != ASTNodeID.LiteralNullID) + { + if (rightDef == null || + (!(rightDef.getQualifiedName().equals(IASLanguageConstants.String) || + // if not an assignment we don't need to coerce numbers + (!isAssignment && rightIsNumber) || + rightDef.getQualifiedName().equals(IASLanguageConstants.Null)))) + { + write(".toString()"); + } + } + } + if (leftIsNumber && !rightIsNumber) + write(")"); + /* IExpressionNode leftSide = node.getLeftOperandNode(); @@ -331,7 +372,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements } } - private void super_emitBinaryOperator(IBinaryOperatorNode node) + private void super_emitBinaryOperator(IBinaryOperatorNode node, boolean leftIsNumber, boolean rightIsNumber) { if (ASNodeUtils.hasParenOpen(node)) write(ASEmitterTokens.PAREN_OPEN); @@ -400,6 +441,8 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements write(ASEmitterTokens.SPACE); endMapping(node); + if (leftIsNumber && !rightIsNumber) + write("Number("); /* IDefinition definition = node.getRightOperandNode().resolve(getProject()); if (definition instanceof FunctionDefinition && @@ -417,7 +460,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements ((JSFlexJSEmitter)getEmitter()).isProxy(node.getRightOperandNode())) { write(".propertyNames()"); - } + } } if (ASNodeUtils.hasParenOpen(node)) http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/aac9a386/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/VarDeclarationEmitter.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/VarDeclarationEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/VarDeclarationEmitter.java index c9311fd..d1a3ed2 100644 --- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/VarDeclarationEmitter.java +++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/VarDeclarationEmitter.java @@ -27,7 +27,9 @@ 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.tree.as.ChainedVariableNode; +import org.apache.flex.compiler.internal.tree.as.FunctionCallNode; import org.apache.flex.compiler.internal.tree.as.IdentifierNode; +import org.apache.flex.compiler.internal.tree.as.MemberAccessExpressionNode; import org.apache.flex.compiler.tree.ASTNodeID; import org.apache.flex.compiler.tree.as.IASNode; import org.apache.flex.compiler.tree.as.IEmbedNode; @@ -110,12 +112,37 @@ public class VarDeclarationEmitter extends JSSubEmitter implements write(ASEmitterTokens.SPACE); writeToken(ASEmitterTokens.EQUAL); endMapping(node); + boolean varIsNumber = (variableTypeNode.getNodeID() == ASTNodeID.IdentifierID && + (((IdentifierNode)variableTypeNode).getName().equals(IASLanguageConstants.Number) || + ((IdentifierNode)variableTypeNode).getName().equals(IASLanguageConstants._int) || + ((IdentifierNode)variableTypeNode).getName().equals(IASLanguageConstants.uint))); + boolean valIsNumber = (avdef != null && (avdef.getQualifiedName().equals(IASLanguageConstants.Number) || + avdef.getQualifiedName().equals(IASLanguageConstants._int) || + avdef.getQualifiedName().equals(IASLanguageConstants.uint))); + if (varIsNumber && !valIsNumber && (avdef == null || avdef.getQualifiedName().equals(IASLanguageConstants.ANY_TYPE)) + && avnode.getNodeID() == ASTNodeID.FunctionCallID) + { + IExpressionNode fnNameNode = ((FunctionCallNode)avnode).getNameNode(); + if (fnNameNode.getNodeID() == ASTNodeID.MemberAccessExpressionID) + { + MemberAccessExpressionNode mae = (MemberAccessExpressionNode)fnNameNode; + IExpressionNode rightNode = mae.getRightOperandNode(); + valIsNumber = rightNode.getNodeID() == ASTNodeID.IdentifierID && + ((IdentifierNode)rightNode).getName().equals("length") && + fjs.isXMLList(mae); + } + } + if (varIsNumber && !valIsNumber) + write("Number("); fjs.emitAssignedValue(avnode); if (variableTypeNode.getNodeID() == ASTNodeID.IdentifierID && ((IdentifierNode)variableTypeNode).getName().equals(IASLanguageConstants.String) && (avdef == null || (!avdef.getQualifiedName().equals(IASLanguageConstants.String) && - !avdef.getQualifiedName().equals(IASLanguageConstants.Null)))) + !avdef.getQualifiedName().equals(IASLanguageConstants.Null))) || + (varIsNumber && !valIsNumber)) write(".toString()"); + if (varIsNumber && !valIsNumber) + write(")"); } if (!(node instanceof ChainedVariableNode)) http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/aac9a386/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java index 62d4d46..0bd3440 100644 --- a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java +++ b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java @@ -34,6 +34,7 @@ import org.apache.flex.compiler.tree.as.IFileNode; import org.apache.flex.compiler.tree.as.IFunctionCallNode; import org.apache.flex.compiler.tree.as.IFunctionNode; import org.apache.flex.compiler.tree.as.IMemberAccessExpressionNode; +import org.apache.flex.compiler.tree.as.IVariableNode; import org.junit.Ignore; import org.junit.Test; @@ -915,6 +916,16 @@ public class TestFlexJSExpressions extends TestGoogExpressions assertOut("org.apache.flex.utils.Language.is(a, b)"); } + @Override + @Test + public void testParentheses_3() + { + IVariableNode node = (IVariableNode) getNode( + "var a = ((a + b) - (c + d)) * e;", IVariableNode.class); + asBlockWalker.visitVariable(node); + assertOut("var /** @type {*} */ a = ((a + b) - (c + d)) * Number(e.toString())"); + } + @Test public void testVisitStringLiteralEmbeddedDoubleQuote() { http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/aac9a386/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalClasses.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalClasses.java b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalClasses.java index e2a4e71..c60768e 100644 --- a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalClasses.java +++ b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalClasses.java @@ -524,6 +524,31 @@ public class TestFlexJSGlobalClasses extends TestGoogGlobalClasses } @Test + public void testXMLAttributeToStringAsExpression() + { + IBinaryOperatorNode node = (IBinaryOperatorNode)getNode("var a:XML = new XML(\"<top attr1='cat'><child attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");var b:String; b = a.@attr1;", IBinaryOperatorNode.class); + asBlockWalker.visitBinaryOperator(node); + assertOut("b = a.attribute('attr1').toString()"); + } + + public void testXMLAttributeToNumber() + { + IVariableNode node = getVariable("var a:XML = new XML(\"<top attr1='cat'><child attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");var b:Number = a.@attr1;"); + IASNode parentNode = node.getParent(); + node = (IVariableNode) parentNode.getChild(1); + asBlockWalker.visitVariable(node); + assertOut("var /** @type {number} */ b = Number(a.attribute('attr1').toString())"); + } + + @Test + public void testXMLAttributeToNumberAsExpression() + { + IBinaryOperatorNode node = (IBinaryOperatorNode)getNode("var a:XML = new XML(\"<top attr1='cat'><child attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");var b:Number; b = a.@attr1;", IBinaryOperatorNode.class); + asBlockWalker.visitBinaryOperator(node); + assertOut("b = Number(a.attribute('attr1').toString())"); + } + + @Test public void testStringSetToNull() { IVariableNode node = getVariable("var a:XML = new XML(\"<top attr1='cat'><child attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");var b:String = null;"); http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/aac9a386/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSStatements.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSStatements.java b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSStatements.java index f2022b3..d8e4db8 100644 --- a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSStatements.java +++ b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSStatements.java @@ -108,7 +108,7 @@ public class TestFlexJSStatements extends TestGoogStatements public void testVisitFor_1a() { IForLoopNode node = (IForLoopNode) getNode( - "for (var i:int = 0; i < len; i++) { break; }", + "var len:int;for (var i:int = 0; i < len; i++) { break; }", IForLoopNode.class); asBlockWalker.visitForLoop(node); assertOut("for (var /** @type {number} */ i = 0; i < len; i++) {\n break;\n}"); @@ -119,7 +119,7 @@ public class TestFlexJSStatements extends TestGoogStatements public void testVisitFor_1b() { IForLoopNode node = (IForLoopNode) getNode( - "for (var i:int = 0; i < len; i++) break;", IForLoopNode.class); + "var len:int;for (var i:int = 0; i < len; i++) break;", IForLoopNode.class); asBlockWalker.visitForLoop(node); assertOut("for (var /** @type {number} */ i = 0; i < len; i++)\n break;"); } @@ -466,7 +466,7 @@ public class TestFlexJSStatements extends TestGoogStatements { IFileNode node = (IFileNode) getNode( "try { a; } catch (e:Error) { if (a) { if (b) { if (c) b; else if (f) a; else e; }} } finally { }" - + "if (d) for (var i:int = 0; i < len; i++) break;" + + "if (d) { var len:int; for (var i:int = 0; i < len; i++) break; }" + "if (a) { with (ab) { c(); } " + "do {a++;do a++; while(a > b);} while(c > d); }" + "if (b) { try { a; throw new Error('foo'); } catch (e:Error) { " @@ -513,9 +513,11 @@ public class TestFlexJSStatements extends TestGoogStatements " }\n" + " } finally {\n" + " }\n" + - " if (d)\n" + + " if (d) {\n" + + " var /** @type {number} */ len;\n" + " for (var /** @type {number} */ i = 0; i < len; i++)\n" + " break;\n" + + " }\n" + " if (a) {\n" + " with (ab) {\n" + " c();\n" + http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/aac9a386/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java index fc3dea7..dc391dc 100644 --- a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java +++ b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/sourcemaps/TestSourceMapStatements.java @@ -140,7 +140,7 @@ public class TestSourceMapStatements extends SourceMapTestBase public void testVisitFor_1a() { IForLoopNode node = (IForLoopNode) getNode( - "for (var i:int = 0; i < len; i++) { break; }", + "var len:int;for (var i:int = 0; i < len; i++) { break; }", IForLoopNode.class); asBlockWalker.visitForLoop(node); //for (var /** @type {number} */ i = 0; i < len; i++) {\n break;\n} @@ -156,7 +156,7 @@ public class TestSourceMapStatements extends SourceMapTestBase public void testVisitFor_1b() { IForLoopNode node = (IForLoopNode) getNode( - "for (var i:int = 0; i < len; i++) break;", IForLoopNode.class); + "var len:int;for (var i:int = 0; i < len; i++) break;", IForLoopNode.class); asBlockWalker.visitForLoop(node); //for (var /** @type {number} */ i = 0; i < len; i++)\n break; assertMapping(node, 0, 0, 0, 0, 0, 5); // for (
