fix more bugs in compiler and add more tests for them
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/a82dbc12 Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/a82dbc12 Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/a82dbc12 Branch: refs/heads/develop Commit: a82dbc12b06e564fc28bbb4cdf5e73b68a4383ec Parents: 123afb7 Author: Alex Harui <[email protected]> Authored: Fri Apr 19 17:17:38 2013 -0700 Committer: Alex Harui <[email protected]> Committed: Fri Apr 19 17:17:38 2013 -0700 ---------------------------------------------------------------------- .../codegen/js/flexjs/TestFlexJSClass.java | 14 +++- .../codegen/js/flexjs/TestFlexJSExpressions.java | 46 ++++++++++- .../js/flexjs/TestFlexJSGlobalFunctions.java | 62 ++++++++++++++- .../flexjs/files/FlexJSTest_again_result.js | 1 - .../flexjs/files/MyInitialView_result.js | 4 - .../flexjs/files/wildcard_import_result.js | 1 - .../codegen/js/flexjs/JSFlexJSEmitter.java | 35 ++++++--- .../apache/flex/compiler/utils/NativeUtils.java | 49 +++++++++++- 8 files changed, 187 insertions(+), 25 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/a82dbc12/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java ---------------------------------------------------------------------- diff --git a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java index 794d180..ca98a71 100644 --- a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java +++ b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java @@ -121,7 +121,19 @@ public class TestFlexJSClass extends TestGoogClass + "public function foo2():Object{function bar2(param1:Object):Object {return null;}; return bar2('foo');}" + "}"); asBlockWalker.visitClass(node); - assertOut("/**\n * @constructor\n */\norg.apache.flex.B = function() {\n};\n\n/**\n * @expose\n * @return {Object}\n */\norg.apache.flex.B.prototype.foo1 = function() {\n\tfunction bar1() {\n\t\treturn null;\n\t};\n\treturn bar1();\n};\n\n/**\n * @expose\n * @return {Object}\n */\norg.apache.flex.B.prototype.foo2 = function() {\n\tfunction bar2(param1) {\n\t\treturn null;\n\t};\n\treturn bar2('foo');\n};"); + assertOut("/**\n * @constructor\n */\norg.apache.flex.B = function() {\n};\n\n/**\n * @expose\n * @return {Object}\n */\norg.apache.flex.B.prototype.foo1 = function() {\n\tfunction bar1() {\n\t\treturn null;\n\t};\n\treturn goog.bind(bar1, this)();\n};\n\n/**\n * @expose\n * @return {Object}\n */\norg.apache.flex.B.prototype.foo2 = function() {\n\tfunction bar2(param1) {\n\t\treturn null;\n\t};\n\treturn goog.bind(bar2, this)('foo');\n};"); + } + + @Test + public void testMethodsWithLocalFunctions2() + { + IClassNode node = getClassNode("public class B {" + + "public var baz1:String;" + + "public function foo1():String{function bar1():String {return baz1;}; return bar1()}" + + "public function foo2():String{function bar2(param1:String):String {return param1 + baz1;}; return bar2('foo');}" + + "}"); + asBlockWalker.visitClass(node); + assertOut("/**\n * @constructor\n */\norg.apache.flex.B = function() {\n};\n\n/**\n * @type {string}\n */\norg.apache.flex.B.prototype.baz1;\n\n/**\n * @expose\n * @return {string}\n */\norg.apache.flex.B.prototype.foo1 = function() {\n\tfunction bar1() {\n\t\treturn this.baz1;\n\t};\n\treturn goog.bind(bar1, this)();\n};\n\n/**\n * @expose\n * @return {string}\n */\norg.apache.flex.B.prototype.foo2 = function() {\n\tfunction bar2(param1) {\n\t\treturn param1 + this.baz1;\n\t};\n\treturn goog.bind(bar2, this)('foo');\n};"); } @Test http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/a82dbc12/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java ---------------------------------------------------------------------- diff --git a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java index 8e6bd86..33c5e99 100644 --- a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java +++ b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSExpressions.java @@ -470,7 +470,37 @@ public class TestFlexJSExpressions extends TestGoogExpressions "public class B {public function b() { function c(f:Function):void {}; function d():void {}; c(d); }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE); asBlockWalker.visitFunction(node); - assertOut("/**\n * @expose\n */\nB.prototype.b = function() {\n\tfunction c(f) {\n\t};\n\tfunction d() {\n\t};\n\tc(d);\n}"); + assertOut("/**\n * @expose\n */\nB.prototype.b = function() {\n\tfunction c(f) {\n\t};\n\tfunction d() {\n\t};\n\tgoog.bind(c, this)(goog.bind(d, this));\n}"); + } + + @Test + public void testNamedFunctionAsArgument2() + { + IFunctionNode node = (IFunctionNode) getNode( + "public class B {public function b() { function c(s:String, f:Function):void {}; function d():void {}; c('foo', d); }}", + IFunctionNode.class, WRAP_LEVEL_PACKAGE); + asBlockWalker.visitFunction(node); + assertOut("/**\n * @expose\n */\nB.prototype.b = function() {\n\tfunction c(s, f) {\n\t};\n\tfunction d() {\n\t};\n\tgoog.bind(c, this)('foo', goog.bind(d, this));\n}"); + } + + @Test + public void testNamedFunctionAsArgument3() + { + IFunctionNode node = (IFunctionNode) getNode( + "public class B {public function b() { c('foo', d); function c(s:String, f:Function):void {}; function d():void {};}}", + IFunctionNode.class, WRAP_LEVEL_PACKAGE); + asBlockWalker.visitFunction(node); + assertOut("/**\n * @expose\n */\nB.prototype.b = function() {\n\tgoog.bind(c, this)('foo', goog.bind(d, this));\n\tfunction c(s, f) {\n\t};\n\tfunction d() {\n\t};\n}"); + } + + @Test + public void testNamedFunctionAsArgument4() + { + IFunctionNode node = (IFunctionNode) getNode( + "public class B {public function b() { function d():void {}; c('foo', d); } public function c(s:String, f:Function):void {};}", + IFunctionNode.class, WRAP_LEVEL_PACKAGE); + asBlockWalker.visitFunction(node); + assertOut("/**\n * @expose\n */\nB.prototype.b = function() {\n\tfunction d() {\n\t};\n\tthis.c('foo', goog.bind(d, this));\n}"); } @Test @@ -480,7 +510,7 @@ public class TestFlexJSExpressions extends TestGoogExpressions "public class B {public function b() { function c(f:Function):void {}; c(b); }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE); asBlockWalker.visitFunction(node); - assertOut("/**\n * @expose\n */\nB.prototype.b = function() {\n\tfunction c(f) {\n\t};\n\tc(goog.bind(this.b, this));\n}"); + assertOut("/**\n * @expose\n */\nB.prototype.b = function() {\n\tfunction c(f) {\n\t};\n\tgoog.bind(c, this)(goog.bind(this.b, this));\n}"); } @Test @@ -490,7 +520,7 @@ public class TestFlexJSExpressions extends TestGoogExpressions "public class B {static public function b() { function c(f:Function):void {}; c(b); }}", IFunctionNode.class, WRAP_LEVEL_PACKAGE, true); asBlockWalker.visitFunction(node); - assertOut("/**\n * @expose\n */\nfoo.bar.B.b = function() {\n\tfunction c(f) {\n\t};\n\tc(foo.bar.B.b);\n}"); + assertOut("/**\n * @expose\n */\nfoo.bar.B.b = function() {\n\tfunction c(f) {\n\t};\n\tgoog.bind(c, this)(foo.bar.B.b);\n}"); } @Test @@ -552,6 +582,16 @@ public class TestFlexJSExpressions extends TestGoogExpressions assertOut("(is(a, b) ? a : null)"); } + @Test + public void testVisitAs2() + { + IFunctionNode node = (IFunctionNode) getNode( + "public class B {public function b(o:Object):int { var a:B; a = o as B; }}", + IFunctionNode.class, WRAP_LEVEL_PACKAGE, true); + asBlockWalker.visitFunction(node); + assertOut("/**\n * @expose\n * @param {Object} o\n * @return {number}\n */\nfoo.bar.B.prototype.b = function(o) {\n\tvar /** @type {B} */ a;\n\ta = (is(o, foo.bar.B) ? o : null);\n}"); + } + @Override @Test public void testVisitBinaryOperator_Is() http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/a82dbc12/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalFunctions.java ---------------------------------------------------------------------- diff --git a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalFunctions.java b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalFunctions.java index 8d8bce5..a3f6207 100644 --- a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalFunctions.java +++ b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalFunctions.java @@ -24,6 +24,7 @@ import org.apache.flex.compiler.internal.codegen.js.goog.TestGoogGlobalFunctions import org.apache.flex.compiler.internal.driver.js.flexjs.FlexJSBackend; import org.apache.flex.compiler.tree.as.IBinaryOperatorNode; import org.apache.flex.compiler.tree.as.IVariableNode; +import org.junit.Ignore; import org.junit.Test; /** @@ -31,6 +32,37 @@ import org.junit.Test; */ public class TestFlexJSGlobalFunctions extends TestGoogGlobalFunctions { + @Ignore + @Override + @Test + public void testArray() + { + IVariableNode node = getVariable("var a:Array = Array(1);"); + asBlockWalker.visitVariable(node); + // TODO (aharui) claims this is not valid and someday needs to result in: + // a = new Array() + // I cannot find any reference to creating an array of a particular + // size in JS. + assertOut("var /** @type {Array} */ a = Array(1)"); + } + + @Override + @Test + public void testInt() + { + IVariableNode node = getVariable("var a:int = int(1.8);"); + asBlockWalker.visitVariable(node); + assertOut("var /** @type {number} */ a = 1.8/** Cast to int */"); + } + + @Override + @Test + public void testObject() + { + IVariableNode node = getVariable("var a:Object = Object(\"1\");"); + asBlockWalker.visitVariable(node); + assertOut("var /** @type {Object} */ a = \"1\"/** Cast to Object */"); + } @Override @Test @@ -50,6 +82,34 @@ public class TestFlexJSGlobalFunctions extends TestGoogGlobalFunctions assertOut("var /** @type {Vector.<string>} */ a = Array(['Hello', 'World'])"); } + @Ignore + @Override + @Test + public void testXML() + { + IVariableNode node = getVariable("var a:XML = XML('@');"); + asBlockWalker.visitVariable(node); + // TODO (aharui) claims this is not valid and someday needs to result in: + // <@/> or something like that? + // I cannot find any reference to creating an XML object via a + // global function + assertOut("var /** @type {XML} */ a = XML('@')"); + } + + @Ignore + @Override + @Test + public void testXMLList() + { + IVariableNode node = getVariable("var a:XMLList = XMLList('<!-- comment -->');"); + asBlockWalker.visitVariable(node); + // TODO (aharui) claims this is not valid and someday needs to result in: + // <@/> or something like that? + // I cannot find any reference to creating an XML object via a + // global function + assertOut("var /** @type {XMLList} */ a = XMLList('<!-- comment -->')"); + } + @Test public void testGlobalFunctionInClass() { @@ -65,5 +125,5 @@ public class TestFlexJSGlobalFunctions extends TestGoogGlobalFunctions { return new FlexJSBackend(); } - + } http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/a82dbc12/compiler.jx.tests/test-files/flexjs/files/FlexJSTest_again_result.js ---------------------------------------------------------------------- diff --git a/compiler.jx.tests/test-files/flexjs/files/FlexJSTest_again_result.js b/compiler.jx.tests/test-files/flexjs/files/FlexJSTest_again_result.js index 0e9dc85..f7e4e47 100644 --- a/compiler.jx.tests/test-files/flexjs/files/FlexJSTest_again_result.js +++ b/compiler.jx.tests/test-files/flexjs/files/FlexJSTest_again_result.js @@ -9,7 +9,6 @@ goog.require('org.apache.flex.net.HTTPService'); goog.require('org.apache.flex.net.dataConverters.LazyCollection'); goog.require('org.apache.flex.net.JSONInputParser'); goog.require('StockDataJSONItemConverter'); -goog.require('org.apache.flex.events.Event'); /** * @constructor http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/a82dbc12/compiler.jx.tests/test-files/flexjs/files/MyInitialView_result.js ---------------------------------------------------------------------- diff --git a/compiler.jx.tests/test-files/flexjs/files/MyInitialView_result.js b/compiler.jx.tests/test-files/flexjs/files/MyInitialView_result.js index a546188..5bcf47d 100644 --- a/compiler.jx.tests/test-files/flexjs/files/MyInitialView_result.js +++ b/compiler.jx.tests/test-files/flexjs/files/MyInitialView_result.js @@ -12,10 +12,6 @@ goog.require('org.apache.flex.html.staticControls.CheckBox'); goog.require('org.apache.flex.html.staticControls.RadioButton'); goog.require('org.apache.flex.html.staticControls.DropDownList'); goog.require('org.apache.flex.html.staticControls.ComboBox'); -goog.require('org.apache.flex.events.Event'); -goog.require('flash.events.Event'); -goog.require('org.apache.flex.utils.Timer'); -goog.require('org.apache.flex.events.CustomEvent'); /** * @constructor http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/a82dbc12/compiler.jx.tests/test-files/flexjs/files/wildcard_import_result.js ---------------------------------------------------------------------- diff --git a/compiler.jx.tests/test-files/flexjs/files/wildcard_import_result.js b/compiler.jx.tests/test-files/flexjs/files/wildcard_import_result.js index 9c7c4c9..eb17f8a 100644 --- a/compiler.jx.tests/test-files/flexjs/files/wildcard_import_result.js +++ b/compiler.jx.tests/test-files/flexjs/files/wildcard_import_result.js @@ -1,7 +1,6 @@ goog.provide('wildcard_import'); goog.require('org.apache.flex.core.Application'); -goog.require('org.apache.flex.html.staticControls.Button'); /** * @constructor http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/a82dbc12/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 df36212..a60643e 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 @@ -32,6 +32,7 @@ import org.apache.flex.compiler.common.ASModifier; import org.apache.flex.compiler.common.ModifiersSet; import org.apache.flex.compiler.definitions.IDefinition; import org.apache.flex.compiler.definitions.IFunctionDefinition; +import org.apache.flex.compiler.definitions.IFunctionDefinition.FunctionClassification; import org.apache.flex.compiler.definitions.INamespaceDefinition; import org.apache.flex.compiler.definitions.IPackageDefinition; import org.apache.flex.compiler.definitions.ITypeDefinition; @@ -209,7 +210,7 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter def = node.getNameNode().resolve(project); isClassCast = def instanceof ClassDefinition - && !(NativeUtils.isNative(def.getBaseName())); + && !(NativeUtils.isJSNative(def.getBaseName())); } if (node.isNewExpression()) @@ -288,7 +289,8 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter else if (parentNodeId == ASTNodeID.ContainerID && nodeDef instanceof FunctionDefinition) { - return true; // for 'goog.bind' + return ((FunctionDefinition) nodeDef) + .getFunctionClassification() == FunctionClassification.CLASS_MEMBER; // for 'goog.bind' } else { @@ -377,16 +379,26 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter boolean emitName = true; - if (nodeDef != null && nodeDef.isStatic()) + if (nodeDef != null + && (nodeDef.isStatic() || (nodeDef instanceof ClassDefinition && nodeDef + .getParent() != null))) { String sname = nodeDef.getParent().getQualifiedName(); - write(sname); - write(ASEmitterTokens.MEMBER_ACCESS); + if (sname.length() > 0) + { + write(sname); + write(ASEmitterTokens.MEMBER_ACCESS); + } } - else if (!NativeUtils.isNative(node.getName()) && writeThis(node)) + else if (!NativeUtils.isNative(node.getName())) { - boolean useGoogBind = parentNodeId == ASTNodeID.ContainerID - && identifierIsPlainFunction; + // an instance method as a parameter or + // a local function + boolean useGoogBind = (parentNodeId == ASTNodeID.ContainerID + && identifierIsPlainFunction && ((FunctionDefinition) nodeDef) + .getFunctionClassification() == FunctionClassification.CLASS_MEMBER) + || (identifierIsPlainFunction && ((FunctionDefinition) nodeDef) + .getFunctionClassification() == FunctionClassification.LOCAL); if (useGoogBind) { @@ -394,9 +406,12 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter write(ASEmitterTokens.PAREN_OPEN); } - write(ASEmitterTokens.THIS); + if (writeThis(node)) + { + write(ASEmitterTokens.THIS); - write(ASEmitterTokens.MEMBER_ACCESS); + write(ASEmitterTokens.MEMBER_ACCESS); + } if (useGoogBind) { http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/a82dbc12/compiler.jx/src/org/apache/flex/compiler/utils/NativeUtils.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/utils/NativeUtils.java b/compiler.jx/src/org/apache/flex/compiler/utils/NativeUtils.java index c56812e..361f178 100644 --- a/compiler.jx/src/org/apache/flex/compiler/utils/NativeUtils.java +++ b/compiler.jx/src/org/apache/flex/compiler/utils/NativeUtils.java @@ -24,7 +24,7 @@ package org.apache.flex.compiler.utils; */ public class NativeUtils { - public enum NativeType + public enum NativeASType { Any("*"), // not JS but use full in the context of native @@ -38,6 +38,7 @@ public class NativeUtils Function("Function"), Infinity("Infinity"), Math("Math"), + JSON("JSON"), NaN("NaN"), Namespace("Namespace"), Number("Number"), @@ -66,13 +67,13 @@ public class NativeUtils parseFloat("parseFloat"), parseInt("parseInt"), trace("trace"), - unit("unit"), + uint("uint"), undefined("undefined"), unescape("unescape"); private final String value; - NativeType(String value) + NativeASType(String value) { this.value = value; } @@ -83,9 +84,38 @@ public class NativeUtils } } + public enum NativeJSType + { + Boolean("Boolean"), + Number("Number"), + String("String"), + decodeURI("decodeURI"), + decodeURIComponent("decodeURIComponent"), + encodeURI("encodeURI"), + encodeURIComponent("encodeURIComponent"), + escape("escape"), + isFinite("isFinite"), + isNaN("isNaN"), + parseFloat("parseFloat"), + parseInt("parseInt"), + unescape("unescape"); + + private final String value; + + NativeJSType(String value) + { + this.value = value; + } + + public String getValue() + { + return value; + } + } + public static boolean isNative(String type) { - for (NativeType test : NativeType.values()) + for (NativeASType test : NativeASType.values()) { if (test.getValue().equals(type)) return true; @@ -94,4 +124,15 @@ public class NativeUtils return true; return false; } + + public static boolean isJSNative(String type) + { + for (NativeJSType test : NativeJSType.values()) + { + if (test.getValue().equals(type)) + return true; + } + return false; + } + }
