http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/c3dce49f/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSPackage.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSPackage.java b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSPackage.java new file mode 100644 index 0000000..e6ab1e4 --- /dev/null +++ b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSPackage.java @@ -0,0 +1,1177 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.flex.compiler.internal.codegen.js.flexjs; + +import java.util.ArrayList; + +import org.apache.flex.compiler.driver.IBackend; +import org.apache.flex.compiler.internal.codegen.js.goog.TestGoogPackage; +import org.apache.flex.compiler.internal.driver.js.flexjs.FlexJSBackend; +import org.apache.flex.compiler.internal.driver.js.goog.JSGoogConfiguration; +import org.apache.flex.compiler.internal.projects.FlexJSProject; +import org.apache.flex.compiler.tree.as.IFileNode; +import org.junit.Test; + +/** + * @author Erik de Bruin + */ +public class TestFlexJSPackage extends TestGoogPackage +{ + @Override + public void setUp() + { + project = new FlexJSProject(workspace); + JSGoogConfiguration config = new JSGoogConfiguration(); + ArrayList<String> values = new ArrayList<String>(); + values.add("Event"); + config.setCompilerKeepAs3Metadata(null, values); + ((FlexJSProject)project).config = config; + super.setUp(); + } + + @Override + @Test + public void testPackageSimple_Class() + { + // does JS need a implicit constructor function? ... always? + // All class nodes in AST get either an implicit or explicit constructor + // this is an implicit and the way I have the before/after handler working + // with block disallows implicit blocks from getting { } + + // (erikdebruin) the constuctor IS the class definition, in 'goog' JS, + // therefor we need to write out implicit constructors + // (if I understand the term correctly) + + IFileNode node = compileAS("package {public class A{}}"); + asBlockWalker.visitFile(node); + assertOutWithMetadata("/**\n" + + " * A\n" + + " *\n" + + " * @fileoverview\n" + + " *\n" + + " * @suppress {checkTypes|accessControls}\n" + + " */\n" + + "\n" + + "goog.provide('A');\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @constructor\n" + + " */\n" + + "A = function() {\n" + + "};\n" + + "\n" + + "\n" + + "/**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "A.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'A', qName: 'A'}] };\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('A', A);\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "A.prototype.FLEXJS_REFLECTION_INFO = function () {\n" + + " return {\n" + + " variables: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " accessors: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " };\n" + + " }\n" + + " };\n" + + "};\n"); + } + + @Override + @Test + public void testPackageQualified_Class() + { + IFileNode node = compileAS("package foo.bar.baz {public class A{}}"); + asBlockWalker.visitFile(node); + assertOutWithMetadata("/**\n" + + " * foo.bar.baz.A\n" + + " *\n" + + " * @fileoverview\n" + + " *\n" + + " * @suppress {checkTypes|accessControls}\n" + + " */\n" + + "\n" + + "goog.provide('foo.bar.baz.A');\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @constructor\n" + + " */\n" + + "foo.bar.baz.A = function() {\n" + + "};\n" + + "\n" + + "\n" + + "/**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'A', qName: 'foo.bar.baz.A'}] };\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('foo.bar.baz.A', foo.bar.baz.A);\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_REFLECTION_INFO = function () {\n" + + " return {\n" + + " variables: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " accessors: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " };\n" + + " }\n" + + " };\n" + + "};\n"); + } + + @Override + @Test + public void testPackageQualified_ClassBody() + { + IFileNode node = compileAS("package foo.bar.baz {public class A{public function A(){}}}"); + asBlockWalker.visitFile(node); + assertOutWithMetadata("/**\n" + + " * foo.bar.baz.A\n" + + " *\n" + + " * @fileoverview\n" + + " *\n" + + " * @suppress {checkTypes|accessControls}\n" + + " */\n" + + "\n" + + "goog.provide('foo.bar.baz.A');\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @constructor\n" + + " */\n" + + "foo.bar.baz.A = function() {\n" + + "};\n" + + "\n" + + "\n" + + "/**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'A', qName: 'foo.bar.baz.A'}] };\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('foo.bar.baz.A', foo.bar.baz.A);\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_REFLECTION_INFO = function () {\n" + + " return {\n" + + " variables: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " accessors: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " 'A': { type: '', declaredBy: 'foo.bar.baz.A'}\n" + + " };\n" + + " }\n" + + " };\n" + + "};\n"); + } + + @Override + @Test + public void testPackageQualified_ClassBodyMethodContents() + { + IFileNode node = compileAS("package foo.bar.baz {public class A{public function A(){if (a){for (var i:Object in obj){doit();}}}}}"); + asBlockWalker.visitFile(node); + assertOutWithMetadata("/**\n" + + " * foo.bar.baz.A\n" + + " *\n" + + " * @fileoverview\n" + + " *\n" + + " * @suppress {checkTypes|accessControls}\n" + + " */\n" + + "\n" + + "goog.provide('foo.bar.baz.A');\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @constructor\n" + + " */\n" + + "foo.bar.baz.A = function() {\n" + + " if (a) {\n" + + " for (var /** @type {Object} */ i in obj) {\n" + + " doit();\n" + + " }\n" + + " }\n" + + "};\n" + + "\n" + + "\n" + + "/**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'A', qName: 'foo.bar.baz.A'}] };\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('foo.bar.baz.A', foo.bar.baz.A);\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_REFLECTION_INFO = function () {\n" + + " return {\n" + + " variables: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " accessors: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " 'A': { type: '', declaredBy: 'foo.bar.baz.A'}\n" + + " };\n" + + " }\n" + + " };\n" + + "};\n"); + } + + @Test + public void testPackageQualified_ClassBodyMetaData() + { + IFileNode node = compileAS("package foo.bar.baz {[Event(name='add', type='mx.events.FlexEvent')]\npublic class A{public function A(){}}}"); + asBlockWalker.visitFile(node); + assertOutWithMetadata("/**\n" + + " * foo.bar.baz.A\n" + + " *\n" + + " * @fileoverview\n" + + " *\n" + + " * @suppress {checkTypes|accessControls}\n" + + " */\n" + + "\n" + + "goog.provide('foo.bar.baz.A');\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @constructor\n" + + " */\n" + + "foo.bar.baz.A = function() {\n" + + "};\n" + + "\n" + + "\n" + + "/**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'A', qName: 'foo.bar.baz.A'}] };\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('foo.bar.baz.A', foo.bar.baz.A);\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_REFLECTION_INFO = function () {\n" + + " return {\n" + + " variables: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " accessors: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " 'A': { type: '', declaredBy: 'foo.bar.baz.A'}\n" + + " };\n" + + " },\n" + + " metadata: function () { return [ { name: 'Event', args: [ { key: 'name', value: 'add'}, { key: 'type', value: 'mx.events.FlexEvent'}]}]; }\n" + + " };\n" + + "};\n"); + } + + @Test + public void testPackageQualified_ClassAndInternalClass() + { + IFileNode node = compileAS("package foo.bar.baz {\n" + + "public class A {\n" + + "public function A(){\n" + + "var internalClass:InternalClass = new InternalClass();\n" + + "}}}\n" + + "class InternalClass {\n" + + "public function InternalClass(){}\n" + + "}"); + asBlockWalker.visitFile(node); + assertOutWithMetadata("/**\n" + + " * foo.bar.baz.A\n" + + " *\n" + + " * @fileoverview\n" + + " *\n" + + " * @suppress {checkTypes|accessControls}\n" + + " */\n" + + "\n" + + "goog.provide('foo.bar.baz.A');\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @constructor\n" + + " */\n" + + "foo.bar.baz.A = function() {\n" + + " var /** @type {foo.bar.baz.A.InternalClass} */ internalClass = new foo.bar.baz.A.InternalClass();\n" + + "};\n" + + "\n" + + "\n/" + + "**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'A', qName: 'foo.bar.baz.A'}] };\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('foo.bar.baz.A', foo.bar.baz.A);\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_REFLECTION_INFO = function () {\n" + + " return {\n" + + " variables: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " accessors: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " 'A': { type: '', declaredBy: 'foo.bar.baz.A'}\n" + + " };\n" + + " }\n" + + " };\n" + + "};\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @constructor\n" + + " */\n" + + "foo.bar.baz.A.InternalClass = function() {\n" + + "};\n" + + "\n" + + "\n" + + "/**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "foo.bar.baz.A.InternalClass.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'InternalClass', qName: 'foo.bar.baz.A.InternalClass'}] };\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('foo.bar.baz.A.InternalClass', foo.bar.baz.A.InternalClass);\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "foo.bar.baz.A.InternalClass.prototype.FLEXJS_REFLECTION_INFO = function () {\n" + + " return {\n" + + " variables: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " accessors: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " 'InternalClass': { type: '', declaredBy: 'foo.bar.baz.A.InternalClass'}\n" + + " };\n" + + " }\n" + + " };\n" + + "};\n"); + } + + @Test + public void testPackageQualified_ClassAndInternalFunction() + { + IFileNode node = compileAS("package foo.bar.baz {\n" + + "public class A {\n" + + "public function A(){\n" + + "internalFunction();\n" + + "}}}\n" + + "function internalFunction(){}"); + asBlockWalker.visitFile(node); + assertOutWithMetadata("/**\n" + + " * foo.bar.baz.A\n" + + " *\n" + + " * @fileoverview\n" + + " *\n" + + " * @suppress {checkTypes|accessControls}\n" + + " */\n" + + "\n" + + "goog.provide('foo.bar.baz.A');\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @constructor\n" + + " */\n" + + "foo.bar.baz.A = function() {\n" + + " foo.bar.baz.A.internalFunction();\n" + + "};\n" + + "\n" + + "\n/" + + "**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'A', qName: 'foo.bar.baz.A'}] };\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('foo.bar.baz.A', foo.bar.baz.A);\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_REFLECTION_INFO = function () {\n" + + " return {\n" + + " variables: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " accessors: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " 'A': { type: '', declaredBy: 'foo.bar.baz.A'}\n" + + " };\n" + + " }\n" + + " };\n" + + "};\n" + + "\n" + + "\n" + + "\n" + + "foo.bar.baz.A.internalFunction = function() {\n" + + "}"); + } + + @Test + public void testPackageQualified_ClassAndInternalVariable() + { + IFileNode node = compileAS("package foo.bar.baz {\n" + + "public class A {\n" + + "public function A(){\n" + + "internalVar = 3;\n" + + "}}}\n" + + "var internalVar:Number = 2;"); + asBlockWalker.visitFile(node); + assertOutWithMetadata("/**\n" + + " * foo.bar.baz.A\n" + + " *\n" + + " * @fileoverview\n" + + " *\n" + + " * @suppress {checkTypes|accessControls}\n" + + " */\n" + + "\n" + + "goog.provide('foo.bar.baz.A');\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @constructor\n" + + " */\n" + + "foo.bar.baz.A = function() {\n" + + " foo.bar.baz.A.internalVar = 3;\n" + + "};\n" + + "\n" + + "\n/" + + "**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'A', qName: 'foo.bar.baz.A'}] };\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('foo.bar.baz.A', foo.bar.baz.A);\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_REFLECTION_INFO = function () {\n" + + " return {\n" + + " variables: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " accessors: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " 'A': { type: '', declaredBy: 'foo.bar.baz.A'}\n" + + " };\n" + + " }\n" + + " };\n" + + "};\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @export\n" + + " * @type {number}\n" + + " */\n" + + "foo.bar.baz.A.internalVar = 2"); + } + + @Test + public void testPackageQualified_ClassAndInternalClassMethods() + { + IFileNode node = compileAS("package foo.bar.baz {\n" + + "public class A {\n" + + "public function A(){\n" + + "var internalClass:InternalClass = new InternalClass();\n" + + "var myString:String = InternalClass.someString;\n" + + "myString = InternalClass.someStaticFunction();\n" + + "myString = internalClass.someMethod();\n" + + "}}}\n" + + "class InternalClass {\n" + + "public function InternalClass(){\n" + + "}\n" + + "public static var someString:String = \"foo\";\n" + + "public static function someStaticFunction():String { return \"bar\";}\n" + + "public function someMethod():String { return \"baz\";}\n" + + "}"); + asBlockWalker.visitFile(node); + assertOutWithMetadata("/**\n" + + " * foo.bar.baz.A\n" + + " *\n" + + " * @fileoverview\n" + + " *\n" + + " * @suppress {checkTypes|accessControls}\n" + + " */\n" + + "\n" + + "goog.provide('foo.bar.baz.A');\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @constructor\n" + + " */\n" + + "foo.bar.baz.A = function() {\n" + + " var /** @type {foo.bar.baz.A.InternalClass} */ internalClass = new foo.bar.baz.A.InternalClass();\n" + + " var /** @type {string} */ myString = foo.bar.baz.A.InternalClass.someString;\n" + + " myString = foo.bar.baz.A.InternalClass.someStaticFunction();\n" + + " myString = internalClass.someMethod();\n" + + "};\n" + + "\n" + + "\n" + + "/**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'A', qName: 'foo.bar.baz.A'}] };\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('foo.bar.baz.A', foo.bar.baz.A);\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_REFLECTION_INFO = function () {\n" + + " return {\n" + + " variables: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " accessors: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " 'A': { type: '', declaredBy: 'foo.bar.baz.A'}\n" + + " };\n" + + " }\n" + + " };\n" + + "};\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @constructor\n" + + " */\n" + + "foo.bar.baz.A.InternalClass = function() {\n" + + "};\n" + + "\n" + + "\n" + + "/**\n" + + " * @export\n" + + " * @type {string}\n" + + " */\n" + + "foo.bar.baz.A.InternalClass.someString = \"foo\";\n" + + "\n" + + "\n" + + "/**\n" + + " * @export\n" + + " * @return {string}\n" + + " */\n" + + "foo.bar.baz.A.InternalClass.someStaticFunction = function() {\n" + + " return \"bar\";\n" + + "};\n" + + "\n" + + "\n" + + "/**\n" + + " * @export\n" + + " * @return {string}\n" + + " */\n" + + "foo.bar.baz.A.InternalClass.prototype.someMethod = function() {\n" + + " return \"baz\";\n" + + "};\n" + + "\n" + + "\n" + + "/**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "foo.bar.baz.A.InternalClass.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'InternalClass', qName: 'foo.bar.baz.A.InternalClass'}] };\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('foo.bar.baz.A.InternalClass', foo.bar.baz.A.InternalClass);\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "foo.bar.baz.A.InternalClass.prototype.FLEXJS_REFLECTION_INFO = function () {\n" + + " return {\n" + + " variables: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " accessors: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " 'InternalClass': { type: '', declaredBy: 'foo.bar.baz.A.InternalClass'},\n" + + " 'someMethod': { type: 'String', declaredBy: 'foo.bar.baz.A.InternalClass'}\n" + + " };\n" + + " }\n" + + " };\n" + + "};\n"); + } + + @Test + public void testPackageQualified_ClassAndInternalGettersAndSetters() + { + IFileNode node = compileAS("package foo.bar.baz {\n" + + "public class A {\n" + + "public function A(){\n" + + "var internalClass:InternalClass = new InternalClass();\n" + + "myString = internalClass.someString;\n" + + "internalClass.someString = myString;\n" + + "}\n" + + "public function get myString():String {\n" + + " return null;\n" + + "}\n" + + "public function set myString(value:String):void {}\n" + + "}}\n" + + "class InternalClass {\n" + + "public function InternalClass(){\n" + + "}\n" + + "public function get someString():String {\n" + + " return null;\n" + + "}\n" + + "public function set someString(value:String):void {}\n" + + "}"); + asBlockWalker.visitFile(node); + assertOutWithMetadata("/**\n" + + " * foo.bar.baz.A\n" + + " *\n" + + " * @fileoverview\n" + + " *\n" + + " * @suppress {checkTypes|accessControls}\n" + + " */\n" + + "\n" + + "goog.provide('foo.bar.baz.A');\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @constructor\n" + + " */\n" + + "foo.bar.baz.A = function() {\n" + + " var /** @type {foo.bar.baz.A.InternalClass} */ internalClass = new foo.bar.baz.A.InternalClass();\n" + + " this.myString = internalClass.someString;\n" + + " internalClass.someString = this.myString;\n" + + "};\n" + + "\n" + + "\n" + + "Object.defineProperties(foo.bar.baz.A.prototype, /** @lends {foo.bar.baz.A.prototype} */ {\n" + + "/** @export */\n" + + "myString: {\n" + + "get: /** @this {foo.bar.baz.A} */ function() {\n" + + " return null;\n" + + "},\n" + + "set: /** @this {foo.bar.baz.A} */ function(value) {\n" + + "}}}\n" + + ");\n" + + "\n" + + "\n" + + "/**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'A', qName: 'foo.bar.baz.A'}] };\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('foo.bar.baz.A', foo.bar.baz.A);\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_REFLECTION_INFO = function () {\n" + + " return {\n" + + " variables: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " accessors: function () {\n" + + " return {\n" + + " 'myString': { type: 'String', declaredBy: 'foo.bar.baz.A'}\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " 'A': { type: '', declaredBy: 'foo.bar.baz.A'}\n" + + " };\n" + + " }\n" + + " };\n" + + "};\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @constructor\n" + + " */\n" + + "foo.bar.baz.A.InternalClass = function() {\n" + + "};\n" + + "\n" + + "\n" + + "Object.defineProperties(foo.bar.baz.A.InternalClass.prototype, /** @lends {foo.bar.baz.A.InternalClass.prototype} */ {\n" + + "/** @export */\n" + + "someString: {\n" + + "get: /** @this {foo.bar.baz.A.InternalClass} */ function() {\n" + + " return null;\n" + + "},\n" + + "set: /** @this {foo.bar.baz.A.InternalClass} */ function(value) {\n" + + "}}}\n" + + ");\n" + + "\n" + + "\n" + + "/**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "foo.bar.baz.A.InternalClass.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'InternalClass', qName: 'foo.bar.baz.A.InternalClass'}] };\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('foo.bar.baz.A.InternalClass', foo.bar.baz.A.InternalClass);\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "foo.bar.baz.A.InternalClass.prototype.FLEXJS_REFLECTION_INFO = function () {\n" + + " return {\n" + + " variables: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " accessors: function () {\n" + + " return {\n" + + " 'someString': { type: 'String', declaredBy: 'foo.bar.baz.A.InternalClass'}\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " 'InternalClass': { type: '', declaredBy: 'foo.bar.baz.A.InternalClass'}\n" + + " };\n" + + " }\n" + + " };\n" + + "};\n"); + } + + @Test + public void testPackageQualified_ClassAndInternalFLEXJS_CLASS_INFO() + { + IFileNode node = compileAS("package foo.bar.baz {\n" + + "public class A {\n" + + "public function A(){\n" + + "var internalClass:ITestInterface = new InternalClass() as ITestInterface;\n" + + "internalClass.test();\n" + + "}\n" + + "}}\n" + + "interface ITestInterface {\n" + + "function test():void;\n" + + "}\n" + + "class InternalClass implements ITestInterface {\n" + + "public function InternalClass(){\n" + + "}\n" + + "public function test():void {}\n" + + "}"); + asBlockWalker.visitFile(node); + assertOutWithMetadata("/**\n" + + " * foo.bar.baz.A\n" + + " *\n" + + " * @fileoverview\n" + + " *\n" + + " * @suppress {checkTypes|accessControls}\n" + + " */\n" + + "\n" + + "goog.provide('foo.bar.baz.A');\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @constructor\n" + + " */\n" + + "foo.bar.baz.A = function() {\n" + + " var /** @type {foo.bar.baz.A.ITestInterface} */ internalClass = org.apache.flex.utils.Language.as(new foo.bar.baz.A.InternalClass(), foo.bar.baz.A.ITestInterface);\n" + + " internalClass.test();\n" + + "};\n" + + "\n" + + "\n" + + "/**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'A', qName: 'foo.bar.baz.A'}] };\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('foo.bar.baz.A', foo.bar.baz.A);\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "foo.bar.baz.A.prototype.FLEXJS_REFLECTION_INFO = function () {\n" + + " return {\n" + + " variables: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " accessors: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " 'A': { type: '', declaredBy: 'foo.bar.baz.A'}\n" + + " };\n" + + " }\n" + + " };\n" + + "};\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @interface\n" + + " */\n" + + "foo.bar.baz.A.ITestInterface = function() {\n" + + "};\n" + + "foo.bar.baz.A.ITestInterface.prototype.test = function() {\n" + + "};\n" + + "\n" + + "\n" + + "/**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "foo.bar.baz.A.ITestInterface.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'ITestInterface', qName: 'foo.bar.baz.A.ITestInterface'}] };\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "foo.bar.baz.A.ITestInterface.prototype.FLEXJS_REFLECTION_INFO = function () {\n" + + " return {\n" + + " variables: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " accessors: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " 'test': { type: 'void', declaredBy: 'foo.bar.baz.A.ITestInterface'}\n" + + " };\n" + + " }\n" + + " };\n" + + "};\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * @constructor\n" + + " * @implements {foo.bar.baz.A.ITestInterface}\n" + + " */\n" + + "foo.bar.baz.A.InternalClass = function() {\n" + + "};\n" + + "\n" + + "\n" + + "/**\n" + + " * @export\n" + + " */\n" + + "foo.bar.baz.A.InternalClass.prototype.test = function() {\n" + + "};\n" + + "\n" + + "\n" + + "/**\n" + + " * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "foo.bar.baz.A.InternalClass.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'InternalClass', qName: 'foo.bar.baz.A.InternalClass'}], interfaces: [foo.bar.baz.A.ITestInterface] };\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('foo.bar.baz.A.InternalClass', foo.bar.baz.A.InternalClass);\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "foo.bar.baz.A.InternalClass.prototype.FLEXJS_REFLECTION_INFO = function () {\n" + + " return {\n" + + " variables: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " accessors: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " 'InternalClass': { type: '', declaredBy: 'foo.bar.baz.A.InternalClass'},\n" + + " 'test': { type: 'void', declaredBy: 'foo.bar.baz.A.InternalClass'}\n" + + " };\n" + + " }\n" + + " };\n" + + "};\n" + ); + } + + @Test + public void testPackageSimple_Function() + { + IFileNode node = compileAS("package {public function A(){}}"); + asBlockWalker.visitFile(node); + assertOutWithMetadata("/**\n * A\n *\n * @fileoverview\n *\n * @suppress {checkTypes|accessControls}\n */\n\ngoog.provide('A');\n\n\n\n/**\n * @export\n */\nA = function() {\n}"); + } + + @Test + public void testPackageQualified_Function() + { + IFileNode node = compileAS("package foo.bar.baz {public function A(){}}"); + asBlockWalker.visitFile(node); + assertOutWithMetadata("/**\n * foo.bar.baz.A\n *\n * @fileoverview\n *\n * @suppress {checkTypes|accessControls}\n */\n\ngoog.provide('foo.bar.baz.A');\n\n\n\n/**\n * @export\n */\nfoo.bar.baz.A = function() {\n}"); + } + + @Test + public void testPackageSimple_Variable() + { + IFileNode node = compileAS("package {public var A:String = \"Hello\";"); + asBlockWalker.visitFile(node); + assertOutWithMetadata("/**\n * A\n *\n * @fileoverview\n *\n * @suppress {checkTypes|accessControls}\n */\n\ngoog.provide('A');\n\n\n\n/**\n * @export\n * @type {string}\n */\nA = \"Hello\""); + } + + @Test + public void testPackageQualified_Variable() + { + IFileNode node = compileAS("package foo.bar.baz {public var A:String = \"Hello\";"); + asBlockWalker.visitFile(node); + assertOutWithMetadata("/**\n * foo.bar.baz.A\n *\n * @fileoverview\n *\n * @suppress {checkTypes|accessControls}\n */\n\ngoog.provide('foo.bar.baz.A');\n\n\n\n/**\n * @export\n * @type {string}\n */\nfoo.bar.baz.A = \"Hello\""); + } + + @Override + protected IBackend createBackend() + { + return new FlexJSBackend(); + } + +}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/c3dce49f/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSProject.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSProject.java b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSProject.java new file mode 100644 index 0000000..c057f92 --- /dev/null +++ b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSProject.java @@ -0,0 +1,339 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.flex.compiler.internal.codegen.js.flexjs; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import junit.framework.Assert; +import org.apache.flex.compiler.driver.IBackend; +import org.apache.flex.compiler.exceptions.ConfigurationException; +import org.apache.flex.compiler.internal.codegen.js.goog.TestGoogProject; +import org.apache.flex.compiler.internal.config.TargetSettings; +import org.apache.flex.compiler.internal.driver.js.flexjs.FlexJSBackend; +import org.apache.flex.compiler.internal.driver.js.goog.JSGoogConfiguration; +import org.apache.flex.compiler.internal.projects.FlexJSProject; +import org.apache.flex.utils.FilenameNormalization; +import org.apache.flex.utils.ITestAdapter; +import org.apache.flex.utils.TestAdapterFactory; +import org.junit.Ignore; +import org.junit.Test; + +/** + * This class tests the production of valid 'flexjs' JS code from an external + * project. + * + * @author Erik de Bruin + */ +public class TestFlexJSProject extends TestGoogProject +{ + private static ITestAdapter testAdapter = TestAdapterFactory.getTestAdapter(); + + private static String projectDirPath = "flexjs/projects"; + private String sourcePath; + private Collection<String> externs = new ArrayList<String>(); + + @Override + public void setUp() + { + project = new FlexJSProject(workspace); + ((FlexJSProject)project).config = new JSGoogConfiguration(); + super.setUp(); + } + + @Ignore + @Test + public void test_imports() + { + // crude bypass to allow for successful inheritance + } + + @Test + public void test_Test() + { + String testDirPath = projectDirPath + "/interfaces"; + + String fileName = "Test"; + + sourcePath = new File(TestAdapterFactory.getTestAdapter().getUnitTestBaseDir(), + projectDirPath + "/interfaces").getPath(); + + List<String> compiledFileNames = compileProject(fileName, testDirPath); + + assertProjectOut(compiledFileNames, testDirPath); + } + + @Test + public void test_Super() + { + String testDirPath = projectDirPath + "/super"; + + String fileName = "Base"; + + sourcePath = new File(TestAdapterFactory.getTestAdapter().getUnitTestBaseDir(), + projectDirPath + "/super").getPath(); + + List<String> compiledFileNames = compileProject(fileName, testDirPath); + + assertProjectOut(compiledFileNames, testDirPath); + } + + @Test + public void test_InternalAndSamePackageRequires() + { + String testDirPath = projectDirPath + "/internal"; + + String fileName = "MainClass"; + + sourcePath = new File(TestAdapterFactory.getTestAdapter().getUnitTestBaseDir(), + projectDirPath + "/internal").getPath(); + + List<String> compiledFileNames = compileProject(fileName, testDirPath); + + assertProjectOut(compiledFileNames, testDirPath); + } + + @Test + public void test_IsItCircular() + { + String testDirPath = projectDirPath + "/circular"; + + String fileName = "Base"; + + sourcePath = new File(TestAdapterFactory.getTestAdapter().getUnitTestBaseDir(), + projectDirPath + "/circular").getPath(); + + List<String> compiledFileNames = compileProject(fileName, testDirPath); + + assertProjectOut(compiledFileNames, testDirPath); + } + + @Test + public void test_XMLRequires() + { + String testDirPath = projectDirPath + "/xml_requires"; + + String fileName = "XMLRequire"; + + sourcePath = new File(TestAdapterFactory.getTestAdapter().getUnitTestBaseDir(), + projectDirPath + "/xml_requires").getPath(); + + List<String> compiledFileNames = compileProject(fileName, testDirPath); + + assertProjectOut(compiledFileNames, testDirPath); + } + + @Test + public void test_Overrides() + { + String testDirPath = projectDirPath + "/overrides"; + + String fileName = "Test"; + + try { + ((FlexJSProject)project).config.setCompilerAllowSubclassOverrides(null, true); + } catch (ConfigurationException e) { + Assert.fail(e.getMessage()); + } + project.setTargetSettings(new TargetSettings(((FlexJSProject)project).config)); + + sourcePath = new File(TestAdapterFactory.getTestAdapter().getUnitTestBaseDir(), + projectDirPath + "/overrides").getPath(); + + StringBuilder sb = new StringBuilder(); + List<String> compiledFileNames = compileProject(fileName, testDirPath, sb, false); + + assertProjectOut(compiledFileNames, testDirPath); + } + + @Test + public void test_Bad_Overrides() + { + String testDirPath = projectDirPath + "/bad_overrides"; + + String fileName = "Test"; + + try { + ((FlexJSProject)project).config.setCompilerAllowSubclassOverrides(null, true); + } catch (ConfigurationException e) { + Assert.fail(e.getMessage()); + } + project.setTargetSettings(new TargetSettings(((FlexJSProject)project).config)); + + sourcePath = new File(TestAdapterFactory.getTestAdapter().getUnitTestBaseDir(), + projectDirPath + "/bad_overrides").getPath(); + + StringBuilder sb = new StringBuilder(); + compileProject(fileName, testDirPath, sb, false); + + String out = sb.toString(); + out = out.replace("\\", "/"); + + String expected = testAdapter.getUnitTestBaseDir().getPath() + "/flexjs/projects/bad_overrides/Test.as(31:29)\n" + + "interface method someFunction in interface IA is implemented with an incompatible signature in class Test\n" + + testAdapter.getUnitTestBaseDir().getPath() + "/flexjs/projects/bad_overrides/Test.as(36:26)\n" + + "interface method someOtherFunction in interface IA is implemented with an incompatible signature in class Test\n" + + testAdapter.getUnitTestBaseDir().getPath() + "/flexjs/projects/bad_overrides/Test.as(31:29)\n" + + "Incompatible override.\n" + + testAdapter.getUnitTestBaseDir().getPath() + "/flexjs/projects/bad_overrides/Test.as(36:26)\n" + + "Incompatible override.\n"; + assertThat(out, is(expected)); + } + + @Test + public void test_PackageConflict_AmbiguousDefinition() + { + String testDirPath = projectDirPath + "/package_conflicts_ambiguous_definition"; + + String fileName = "AmbiguousDefinition"; + + externs.add("Event"); + + sourcePath = new File(TestAdapterFactory.getTestAdapter().getUnitTestBaseDir(), + projectDirPath + "/package_conflicts_ambiguous_definition").getPath(); + + StringBuilder sb = new StringBuilder(); + compileProject(fileName, testDirPath, sb, false); + + externs.clear(); + + String out = sb.toString(); + out = out.replace("\\", "/"); + + assertThat(out, is(testAdapter.getUnitTestBaseDir().getPath() + + "/flexjs/projects/package_conflicts_ambiguous_definition/mypackage/TestClass.as(29:20)\nAmbiguous reference to Event\n" + + testAdapter.getUnitTestBaseDir().getPath() + + "/flexjs/projects/package_conflicts_ambiguous_definition/mypackage/TestClass.as(30:41)\nAmbiguous reference to Event\n")); + } + + @Test + public void test_PackageConflict_SamePackageAsConflict() + { + String testDirPath = projectDirPath + "/package_conflicts_same_package_as_conflict"; + + String fileName = "SamePackageAsConflict"; + + externs.add("Event"); + + sourcePath = new File(TestAdapterFactory.getTestAdapter().getUnitTestBaseDir(), + projectDirPath + "/package_conflicts_same_package_as_conflict").getPath(); + + List<String> compiledFileNames = compileProject(fileName, testDirPath); + + externs.clear(); + + assertProjectOut(compiledFileNames, testDirPath); + } + + @Test + public void test_PackageConflict_DifferentPackageAsConflict() + { + String testDirPath = projectDirPath + "/package_conflicts_different_package_as_conflict"; + + String fileName = "DifferentPackageAsConflict"; + + externs.add("Event"); + + sourcePath = new File(TestAdapterFactory.getTestAdapter().getUnitTestBaseDir(), + projectDirPath + "/package_conflicts_different_package_as_conflict").getPath(); + + List<String> compiledFileNames = compileProject(fileName, testDirPath); + + externs.clear(); + + assertProjectOut(compiledFileNames, testDirPath); + } + + @Test + public void test_PackageConflict_UseWindow() + { + String testDirPath = projectDirPath + "/package_conflicts_use_window"; + + String fileName = "UseWindow"; + + externs.add("Event"); + + sourcePath = new File(TestAdapterFactory.getTestAdapter().getUnitTestBaseDir(), + projectDirPath + "/package_conflicts_use_window").getPath(); + + List<String> compiledFileNames = compileProject(fileName, testDirPath); + + externs.clear(); + + assertProjectOut(compiledFileNames, testDirPath); + } + + @Test + public void test_PackageConflict_NoConflictNoWindow() + { + String testDirPath = projectDirPath + "/package_conflicts_no_conflict_no_window"; + + String fileName = "NoConflictNoWindow"; + + externs.add("Event"); + + sourcePath = new File(TestAdapterFactory.getTestAdapter().getUnitTestBaseDir(), + projectDirPath + "/package_conflicts_no_conflict_no_window").getPath(); + + List<String> compiledFileNames = compileProject(fileName, testDirPath); + + externs.clear(); + + assertProjectOut(compiledFileNames, testDirPath); + } + + @Test + public void test_PackageConflict_NoConflictUseWindow() + { + String testDirPath = projectDirPath + "/package_conflicts_no_conflict_use_window"; + + String fileName = "NoConflictUseWindow"; + + externs.add("Event"); + + sourcePath = new File(TestAdapterFactory.getTestAdapter().getUnitTestBaseDir(), + projectDirPath + "/package_conflicts_no_conflict_use_window").getPath(); + + List<String> compiledFileNames = compileProject(fileName, testDirPath); + + externs.clear(); + + assertProjectOut(compiledFileNames, testDirPath); + } + + @Override + protected void addSourcePaths(List<File> sourcePaths) + { + sourcePaths.add(new File(FilenameNormalization.normalize(sourcePath))); + ((FlexJSProject)project).unitTestExterns = externs; + } + + @Override + protected IBackend createBackend() + { + return new FlexJSBackend(); + } + +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/c3dce49f/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 new file mode 100644 index 0000000..f2022b3 --- /dev/null +++ b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSStatements.java @@ -0,0 +1,600 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.flex.compiler.internal.codegen.js.flexjs; + +import org.apache.flex.compiler.driver.IBackend; +import org.apache.flex.compiler.internal.codegen.js.goog.TestGoogStatements; +import org.apache.flex.compiler.internal.driver.js.flexjs.FlexJSBackend; +import org.apache.flex.compiler.internal.projects.FlexJSProject; +import org.apache.flex.compiler.internal.tree.as.LabeledStatementNode; +import org.apache.flex.compiler.tree.as.IFileNode; +import org.apache.flex.compiler.tree.as.IForLoopNode; +import org.apache.flex.compiler.tree.as.IIfNode; +import org.apache.flex.compiler.tree.as.ILiteralNode; +import org.apache.flex.compiler.tree.as.ISwitchNode; +import org.apache.flex.compiler.tree.as.ITryNode; +import org.apache.flex.compiler.tree.as.IVariableNode; +import org.apache.flex.compiler.tree.as.IWhileLoopNode; +import org.apache.flex.compiler.tree.as.IWithNode; +import org.junit.Test; + +/** + * @author Erik de Bruin + */ +public class TestFlexJSStatements extends TestGoogStatements +{ + @Override + public void setUp() + { + project = new FlexJSProject(workspace); + super.setUp(); + } + + @Test + public void testObjectListeral_withPropertyNameMatchingConst() + { + ILiteralNode node = (ILiteralNode) getNode("static const myConst:int; function falconTest_a():Object { return { myConst : myConst } }", + ILiteralNode.class, WRAP_LEVEL_CLASS); + asBlockWalker.visitLiteral(node); + assertOut("{myConst:FalconTest_A.myConst}"); + } + + @Test + public void testVarDeclaration_withTypeAssignedStringWithNewLine() + { + IVariableNode node = (IVariableNode) getNode("var a:String = \"\\n\"", + IVariableNode.class); + asBlockWalker.visitVariable(node); + assertOut("var /** @type {string} */ a = \"\\n\""); + } + + //---------------------------------- + // const declaration + //---------------------------------- + + @Override + @Test + public void testConstDeclaration() + { + IVariableNode node = (IVariableNode) getNode("const a = 42;", + IVariableNode.class); + asBlockWalker.visitVariable(node); + assertOut("\n/**\n * @const\n * @type {*}\n */\nvar a = 42"); + } + + @Override + @Test + public void testConstDeclaration_withType() + { + IVariableNode node = (IVariableNode) getNode("const a:int = 42;", + IVariableNode.class); + asBlockWalker.visitVariable(node); + assertOut("\n/**\n * @const\n * @type {number}\n */\nvar a = 42"); + } + + @Override + @Test + public void testConstDeclaration_withList() + { + IVariableNode node = (IVariableNode) getNode( + "const a:int = 4, b:int = 11, c:int = 42;", IVariableNode.class); + asBlockWalker.visitVariable(node); + assertOut("\n/**\n * @const\n * @type {number}\n */\nvar a = 4, \n/**\n * @const\n * @type {number}\n */\nb = 11, \n/**\n * @const\n * @type {number}\n */\nc = 42"); + } + + //---------------------------------- + // for () { } + //---------------------------------- + + @Override + @Test + public void testVisitFor_1a() + { + IForLoopNode node = (IForLoopNode) getNode( + "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}"); + } + + @Override + @Test + public void testVisitFor_1b() + { + IForLoopNode node = (IForLoopNode) getNode( + "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;"); + } + + @Override + @Test + public void testVisitForIn_1() + { + IForLoopNode node = (IForLoopNode) getNode( + "for (var i:int in obj) { break; }", IForLoopNode.class); + asBlockWalker.visitForLoop(node); + assertOut("for (var /** @type {number} */ i in obj) {\n break;\n}"); + } + + @Override + @Test + public void testVisitForIn_1a() + { + IForLoopNode node = (IForLoopNode) getNode( + "for (var i:int in obj) break; ", IForLoopNode.class); + asBlockWalker.visitForLoop(node); + assertOut("for (var /** @type {number} */ i in obj)\n break;"); + } + + @Override + @Test + public void testVisitForEach_1() + { + IForLoopNode node = (IForLoopNode) getNode( + "for each(var i:int in obj) { break; }", IForLoopNode.class); + asBlockWalker.visitForLoop(node); + assertOut("var foreachiter0_target = obj;\nfor (var foreachiter0 in foreachiter0_target) \n{\nvar i = foreachiter0_target[foreachiter0];\n{\n break;\n}}\n"); + } + + @Override + @Test + public void testVisitForEach_1a() + { + IForLoopNode node = (IForLoopNode) getNode( + "for each(var i:int in obj) break; ", IForLoopNode.class); + asBlockWalker.visitForLoop(node); + assertOut("var foreachiter0_target = obj;\nfor (var foreachiter0 in foreachiter0_target) \n{\nvar i = foreachiter0_target[foreachiter0];\n\n break;}\n"); + } + + @Test + public void testVisitForEach_2() + { + IForLoopNode node = (IForLoopNode) getNode( + "for each(var i:int in obj.foo()) { break; }", IForLoopNode.class); + asBlockWalker.visitForLoop(node); + assertOut("var foreachiter0_target = obj.foo();\nfor (var foreachiter0 in foreachiter0_target) \n{\nvar i = foreachiter0_target[foreachiter0];\n{\n break;\n}}\n"); + } + + @Test + public void testVisitForEach_HoistedVar() + { + IForLoopNode node = (IForLoopNode) getNode( + "var i:int; for each(i in obj) break; ", IForLoopNode.class); + asBlockWalker.visitForLoop(node); + assertOut("var foreachiter0_target = obj;\nfor (var foreachiter0 in foreachiter0_target) \n{\ni = foreachiter0_target[foreachiter0];\n\n break;}\n"); + } + + //---------------------------------- + // try {} catch () {} finally {} + //---------------------------------- + + @Override + @Test + public void testVisitTry_Catch() + { + ITryNode node = (ITryNode) getNode("try { a; } catch (e:Error) { b; }", + ITryNode.class); + asBlockWalker.visitTry(node); + assertOut("try {\n a;\n} catch (e) {\n b;\n}"); + } + + @Override + @Test + public void testVisitTry_Catch_Finally() + { + ITryNode node = (ITryNode) getNode( + "try { a; } catch (e:Error) { b; } finally { c; }", + ITryNode.class); + asBlockWalker.visitTry(node); + assertOut("try {\n a;\n} catch (e) {\n b;\n} finally {\n c;\n}"); + } + + @Override + @Test + public void testVisitTry_Catch_Catch_Finally() + { + // TODO (erikdebruin) handle multiple 'catch' statements (FW in Wiki) + ITryNode node = (ITryNode) getNode( + "try { a; } catch (e:Error) { b; } catch (f:Error) { c; } finally { d; }", + ITryNode.class); + asBlockWalker.visitTry(node); + assertOut("try {\n a;\n} catch (e) {\n b;\n} catch (f) {\n c;\n} finally {\n d;\n}"); + } + + @Override + @Test + public void testVisitTry_CatchEmpty_FinallyEmpty_() + { + ITryNode node = (ITryNode) getNode( + "try { a; } catch (e:Error) { } finally { }", ITryNode.class); + asBlockWalker.visitTry(node); + assertOut("try {\n a;\n} catch (e) {\n} finally {\n}"); + } + + //---------------------------------- + // switch {} + //---------------------------------- + + @Override + @Test + public void testVisitSwitch_1() + { + ISwitchNode node = (ISwitchNode) getNode("switch(i){case 1: break;}", + ISwitchNode.class); + asBlockWalker.visitSwitch(node); + assertOut("switch (i) {\n case 1:\n break;\n}"); + } + + @Override + @Test + public void testVisitSwitch_1a() + { + ISwitchNode node = (ISwitchNode) getNode( + "switch(i){case 1: { break; }}", ISwitchNode.class); + asBlockWalker.visitSwitch(node); + // (erikdebruin) the code is valid without the extra braces, + // i.e. we're good, we "don't care" + assertOut("switch (i) {\n case 1:\n break;\n}"); + } + + @Override + @Test + public void testVisitSwitch_2() + { + ISwitchNode node = (ISwitchNode) getNode( + "switch(i){case 1: break; default: return;}", ISwitchNode.class); + asBlockWalker.visitSwitch(node); + assertOut("switch (i) {\n case 1:\n break;\n default:\n return;\n}"); + } + + @Override + @Test + public void testVisitSwitch_3() + { + ISwitchNode node = (ISwitchNode) getNode( + "switch(i){case 1: { var x:int = 42; break; }; case 2: { var y:int = 66; break; }}", ISwitchNode.class); + asBlockWalker.visitSwitch(node); + assertOut("switch (i) {\n case 1:\n var /** @type {number} */ x = 42;\n break;\n case 2:\n var /** @type {number} */ y = 66;\n break;\n}"); + } + + //---------------------------------- + // if () + //---------------------------------- + + @Override + @Test + public void testVisitIf_1() + { + IIfNode node = (IIfNode) getNode("if (a) b++;", IIfNode.class); + asBlockWalker.visitIf(node); + assertOut("if (a)\n b++;"); + } + + @Override + @Test + public void testVisitIf_2() + { + IIfNode node = (IIfNode) getNode("if (a) b++; else c++;", IIfNode.class); + asBlockWalker.visitIf(node); + assertOut("if (a)\n b++;\nelse\n c++;"); + } + + @Override + @Test + public void testVisitIf_4() + { + IIfNode node = (IIfNode) getNode( + "if (a) b++; else if (c) d++; else if(e) --f;", IIfNode.class); + asBlockWalker.visitIf(node); + assertOut("if (a)\n b++;\nelse if (c)\n d++;\nelse if (e)\n --f;"); + } + + //---------------------------------- + // if () { } + //---------------------------------- + + @Override + @Test + public void testVisitIf_1a() + { + IIfNode node = (IIfNode) getNode("if (a) { b++; }", IIfNode.class); + asBlockWalker.visitIf(node); + assertOut("if (a) {\n b++;\n}"); + } + + @Override + @Test + public void testVisitIf_1b() + { + IIfNode node = (IIfNode) getNode("if (a) { b++; } else { c++; }", + IIfNode.class); + asBlockWalker.visitIf(node); + assertOut("if (a) {\n b++;\n} else {\n c++;\n}"); + } + + @Override + @Test + public void testVisitIf_1c() + { + IIfNode node = (IIfNode) getNode( + "if (a) { b++; } else if (b) { c++; } else { d++; }", + IIfNode.class); + asBlockWalker.visitIf(node); + assertOut("if (a) {\n b++;\n} else if (b) {\n c++;\n} else {\n d++;\n}"); + } + + @Override + @Test + public void testVisitIf_3() + { + IIfNode node = (IIfNode) getNode( + "if (a) b++; else if (c) d++; else --e;", IIfNode.class); + asBlockWalker.visitIf(node); + assertOut("if (a)\n b++;\nelse if (c)\n d++;\nelse\n --e;"); + } + + //---------------------------------- + // label : for () {} + //---------------------------------- + + @Override + @Test + public void testVisitFor_2() + { + IForLoopNode node = (IForLoopNode) getNode("for (;;) { break; }", + IForLoopNode.class); + asBlockWalker.visitForLoop(node); + assertOut("for (;;) {\n break;\n}"); + } + + //---------------------------------- + // while () { } + //---------------------------------- + + @Override + @Test + public void testVisitWhileLoop_1() + { + IWhileLoopNode node = (IWhileLoopNode) getNode( + "while(a > b){a++;--b;}", IWhileLoopNode.class); + asBlockWalker.visitWhileLoop(node); + assertOut("while (a > b) {\n a++;\n --b;\n}"); + } + + @Override + @Test + public void testVisitWhileLoop_1a() + { + IWhileLoopNode node = (IWhileLoopNode) getNode("while(a > b) a++;", + IWhileLoopNode.class); + asBlockWalker.visitWhileLoop(node); + assertOut("while (a > b)\n a++;"); + } + + //---------------------------------- + // do {} while () + //---------------------------------- + + @Override + @Test + public void testVisitWhileLoop_Do_1() + { + IWhileLoopNode node = (IWhileLoopNode) getNode( + "do {a++;--b;} while(a > b);", IWhileLoopNode.class); + asBlockWalker.visitWhileLoop(node); + assertOut("do {\n a++;\n --b;\n} while (a > b);"); + } + + @Override + @Test + public void testVisitWhileLoop_Do_1a() + { + IWhileLoopNode node = (IWhileLoopNode) getNode("do a++; while(a > b);", + IWhileLoopNode.class); + asBlockWalker.visitWhileLoop(node); + assertOut("do\n a++;\nwhile (a > b);"); + } + + //---------------------------------- + // label : for () {} + //---------------------------------- + + @Override + @Test + public void testVisitLabel_1() + { + LabeledStatementNode node = (LabeledStatementNode) getNode( + "foo: for each(var i:int in obj) { break foo; }", + LabeledStatementNode.class); + asBlockWalker.visitLabeledStatement(node); + assertOut("var foreachiter0_target = obj;\nfoo : for (var foreachiter0 in foreachiter0_target) \n{\nvar i = foreachiter0_target[foreachiter0];\n{\n break foo;\n}}\n"); + } + + @Override + @Test + public void testVisitLabel_1a() + { + // TODO (mschmalle) LabelStatement messes up in finally{} block, something is wrong there + LabeledStatementNode node = (LabeledStatementNode) getNode( + "foo: for each(var i:int in obj) break foo;", + LabeledStatementNode.class); + asBlockWalker.visitLabeledStatement(node); + assertOut("var foreachiter0_target = obj;\nfoo : for (var foreachiter0 in foreachiter0_target) \n{\nvar i = foreachiter0_target[foreachiter0];\n\n break foo;}\n"); + } + + //---------------------------------- + // with () {} + //---------------------------------- + + @Test + public void testVisitWith() + { + IWithNode node = (IWithNode) getNode("with (a) { b; }", IWithNode.class); + asBlockWalker.visitWith(node); + assertOut("with (a) {\n b;\n}"); + } + + @Test + public void testVisitWith_1a() + { + IWithNode node = (IWithNode) getNode("with (a) b;", IWithNode.class); + asBlockWalker.visitWith(node); + assertOut("with (a)\n b;"); + } + + @Override + @Test + public void testVisit() + { + 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 (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) { " + + " switch(i){case 1: break; default: return;}" + + " } finally { " + + " d; var a:Object = function(foo:int, bar:String = 'goo'):int{return -1;};" + + " eee.dd; eee.dd; eee.dd; eee.dd;} }" + + "foo: for each(var i:int in obj) break foo;", + IFileNode.class); + asBlockWalker.visitFile(node); + assertOutWithMetadata("/**\n" + + " * FalconTest_A\n" + + " *\n" + + " * @fileoverview\n" + + " *\n" + + " * @suppress {checkTypes|accessControls}\n" + + " */\n" + + "\n" + + "goog.provide('FalconTest_A');\n" + + "\n\n\n" + + "/**\n" + + " * @constructor\n" + + " */\n" + + "FalconTest_A = function() {\n" + + "};\n\n\n" + + "FalconTest_A.prototype.falconTest_a = function() {\n" + + " var self = this;\n" + + " var /** @type {Function} */ __localFn0__ = function(foo, bar) {\n" + + " bar = typeof bar !== 'undefined' ? bar : 'goo';\n" + + " return -1;\n" + + " }\n" + + " try {\n" + + " a;\n" + + " } catch (e) {\n" + + " if (a) {\n" + + " if (b) {\n" + + " if (c)\n" + + " b;\n" + + " else if (f)\n" + + " a;\n" + + " else\n" + + " e;\n" + + " }\n" + + " }\n" + + " } finally {\n" + + " }\n" + + " if (d)\n" + + " for (var /** @type {number} */ i = 0; i < len; i++)\n" + + " break;\n" + + " if (a) {\n" + + " with (ab) {\n" + + " c();\n" + + " }\n" + + " do {\n" + + " a++;\n" + + " do\n" + + " a++;\n" + + " while (a > b);\n" + + " } while (c > d);\n" + + " }\n" + + " if (b) {\n" + + " try {\n" + + " a;\n" + + " throw new Error('foo');\n" + + " } catch (e) {\n" + + " switch (i) {\n" + + " case 1:\n" + + " break;\n" + + " default:\n" + + " return;\n" + + " }\n" + + " } finally {\n" + + " d;\n" + + " var /** @type {Object} */ a = __localFn0__;\n" + + " eee.dd;\n" + + " eee.dd;\n" + + " eee.dd;\n" + + " eee.dd;\n" + + " }\n" + + " }\n" + + " var foreachiter0_target = obj;\n" + + " foo : for (var foreachiter0 in foreachiter0_target) \n" + + " {\n" + + " var i = foreachiter0_target[foreachiter0];\n" + + " \n" + + " break foo;}\n" + + " ;\n};\n\n\n" + + "/**\n * Metadata\n" + + " *\n" + + " * @type {Object.<string, Array.<Object>>}\n" + + " */\n" + + "FalconTest_A.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'FalconTest_A', qName: 'FalconTest_A'}] };\n" + + "\n" + + "\n" + + "/**\n" + + " * Prevent renaming of class. Needed for reflection.\n" + + " */\n" + + "goog.exportSymbol('FalconTest_A', FalconTest_A);\n" + + "\n" + + "\n" + + "\n" + + "/**\n" + + " * Reflection\n" + + " *\n" + + " * @return {Object.<string, Function>}\n" + + " */\n" + + "FalconTest_A.prototype.FLEXJS_REFLECTION_INFO = function () {\n" + + "return {\n" + + " variables: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " accessors: function () {\n" + + " return {\n" + + " };\n" + + " },\n" + + " methods: function () {\n" + + " return {\n" + + " };\n" + + " }\n" + + "};\n" + + "};\n"); + } + + @Override + protected IBackend createBackend() + { + return new FlexJSBackend(); + } + +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/c3dce49f/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/goog/TestGoogAccessorMembers.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/goog/TestGoogAccessorMembers.java b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/goog/TestGoogAccessorMembers.java new file mode 100644 index 0000000..02965c0 --- /dev/null +++ b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/goog/TestGoogAccessorMembers.java @@ -0,0 +1,141 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.flex.compiler.internal.codegen.js.goog; + +import org.apache.flex.compiler.driver.IBackend; +import org.apache.flex.compiler.internal.codegen.as.TestAccessorMembers; +import org.apache.flex.compiler.internal.driver.js.goog.GoogBackend; +import org.apache.flex.compiler.tree.as.IGetterNode; +import org.apache.flex.compiler.tree.as.ISetterNode; +import org.junit.Test; + +/** + * This class tests the production of valid 'goog' JS code for Class Accessor + * members. + * + * @author Michael Schmalle + * @author Erik de Bruin + */ +public class TestGoogAccessorMembers extends TestAccessorMembers +{ + @Override + @Test + public void testGetAccessor() + { + IGetterNode node = (IGetterNode) getAccessor("function get foo():int{}"); + asBlockWalker.visitGetter(node); + assertOut("Object.defineProperty(\n\tFalconTest_A.prototype, \n\t'foo', " + + "\n\t{get:function() {\n\t}, configurable:true}\n)"); + } + + @Test + public void testGetAccessor_withBody() + { + IGetterNode node = (IGetterNode) getAccessor("function get foo():int{return -1;}"); + asBlockWalker.visitGetter(node); + assertOut("Object.defineProperty(\n\tFalconTest_A.prototype, \n\t'foo', " + + "\n\t{get:function() {\n\t\tvar self = this;\n\t\treturn -1;\n\t}, configurable:true}\n)"); + } + + @Override + @Test + public void testGetAccessor_withNamespace() + { + IGetterNode node = (IGetterNode) getAccessor("public function get foo():int{return -1;}"); + asBlockWalker.visitGetter(node); + assertOut("Object.defineProperty(\n\tFalconTest_A.prototype, \n\t'foo', " + + "\n\t{get:function() {\n\t\tvar self = this;\n\t\treturn -1;\n\t}, configurable:true}\n)"); + } + + @Override + @Test + public void testGetAccessor_withNamespaceOverride() + { + // TODO (erikdebruin) need to figure out how to handle calls to + // 'super' since the JS getter is actually an + // anonymous function... goog.bind or goog.partial? + IGetterNode node = (IGetterNode) getAccessor("public override function get foo():int{super.foo(); return -1;}"); + asBlockWalker.visitGetter(node); + assertOut("Object.defineProperty(\n\tFalconTest_A.prototype, \n\t'foo', \n\t{get:function() {\n\t\tvar self = this;\n\t\tFalconTest_A.base(this, 'foo');\n\t\treturn -1;\n\t}, configurable:true}\n)"); + } + + @Override + @Test + public void testGetAccessor_withStatic() + { + IGetterNode node = (IGetterNode) getAccessor("public static function get foo():int{return -1;}"); + asBlockWalker.visitGetter(node); + assertOut("Object.defineProperty(\n\tFalconTest_A, \n\t'foo', \n\t{get:function() {\n\t\treturn -1;\n\t}, configurable:true}\n)"); + } + + @Override + @Test + public void testSetAccessor() + { + ISetterNode node = (ISetterNode) getAccessor("function set foo(value:int):void{}"); + asBlockWalker.visitSetter(node); + assertOut("Object.defineProperty(\n\tFalconTest_A.prototype, \n\t'foo', \n\t{set:function(value)" + + " {\n\t}, configurable:true}\n)"); + } + + @Test + public void testSetAccessor_withBody() + { + ISetterNode node = (ISetterNode) getAccessor("function set foo(value:int):void{trace('haai');}"); + asBlockWalker.visitSetter(node); + assertOut("Object.defineProperty(\n\tFalconTest_A.prototype, \n\t'foo', " + + "\n\t{set:function(value) {\n\t\tvar self = this;\n\t\ttrace('haai');\n\t}, configurable:true}\n)"); + } + + @Override + @Test + public void testSetAccessor_withNamespace() + { + ISetterNode node = (ISetterNode) getAccessor("public function set foo(value:int):void{}"); + asBlockWalker.visitSetter(node); + assertOut("Object.defineProperty(\n\tFalconTest_A.prototype, \n\t'foo', \n\t{set:function(value)" + + " {\n\t}, configurable:true}\n)"); + } + + @Override + @Test + public void testSetAccessor_withNamespaceOverride() + { + // TODO (erikdebruin) see: testGetAccessor_withNamespaceOverride + ISetterNode node = (ISetterNode) getAccessor("public override function set foo(value:int):void{super.foo();}"); + asBlockWalker.visitSetter(node); + assertOut("Object.defineProperty(\n\tFalconTest_A.prototype, \n\t'foo', \n\t{set:function(value) {\n\t\tvar self = this;\n\t\tFalconTest_A.base(this, 'foo');\n\t}, configurable:true}\n)"); + } + + @Override + @Test + public void testSetAccessor_withStatic() + { + ISetterNode node = (ISetterNode) getAccessor("public static function set foo(value:int):void{}"); + asBlockWalker.visitSetter(node); + assertOut("Object.defineProperty(\n\tFalconTest_A, \n\t'foo', \n\t{set:function(value) {\n\t}, configurable:true}\n)"); + } + + @Override + protected IBackend createBackend() + { + return new GoogBackend(); + } +}