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 (

Reply via email to