Repository: flex-falcon Updated Branches: refs/heads/develop cc7de9c3c -> 448df1764
FLEX-35227 and FLEX-35236 handle more [Bindable] 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/448df176 Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/448df176 Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/448df176 Branch: refs/heads/develop Commit: 448df176471251106639ea2c2af52d8c77bf54f0 Parents: cc7de9c Author: Alex Harui <aha...@apache.org> Authored: Thu Jan 12 15:12:38 2017 -0800 Committer: Alex Harui <aha...@apache.org> Committed: Thu Jan 12 15:12:38 2017 -0800 ---------------------------------------------------------------------- .../js/flexjs/JSFlexJSEmitterTokens.java | 1 + .../internal/codegen/js/jx/AccessorEmitter.java | 90 ++++++++++++ .../codegen/js/flexjs/TestFlexJSAccessors.java | 41 ++++++ .../codegen/js/flexjs/TestFlexJSClass.java | 144 +++++++++++++++++++ .../flex/compiler/internal/test/TestBase.java | 8 ++ 5 files changed, 284 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/448df176/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitterTokens.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitterTokens.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitterTokens.java index 50e612b..cff0a58 100644 --- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitterTokens.java +++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitterTokens.java @@ -52,6 +52,7 @@ public enum JSFlexJSEmitterTokens implements IEmitterTokens SUPERSETTER("superSetter"), GETTER_PREFIX("get__"), SETTER_PREFIX("set__"), + BINDABLE_PREFIX("bindable__"), CLOSURE_FUNCTION_NAME("org.apache.flex.utils.Language.closure"), SKIP_AS_COERCIONS("skipAsCoercions"), SKIP_FUNCTION_COERCIONS("skipFunctionCoercions"), http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/448df176/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/AccessorEmitter.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/AccessorEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/AccessorEmitter.java index abba383..c060381 100644 --- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/AccessorEmitter.java +++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/AccessorEmitter.java @@ -32,6 +32,7 @@ import org.apache.flex.compiler.definitions.IClassDefinition; import org.apache.flex.compiler.definitions.IFunctionDefinition; import org.apache.flex.compiler.definitions.INamespaceDefinition; import org.apache.flex.compiler.definitions.ITypeDefinition; +import org.apache.flex.compiler.definitions.metadata.IMetaTag; import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens; import org.apache.flex.compiler.internal.codegen.js.JSEmitterTokens; import org.apache.flex.compiler.internal.codegen.js.JSSessionModel.PropertyNodes; @@ -121,6 +122,36 @@ public class AccessorEmitter extends JSSubEmitter implements } if (setterNode != null) { + boolean isBindable = false; + IAccessorDefinition setterDef = (IAccessorDefinition)setterNode.getDefinition(); + IAccessorDefinition getterDef = null; + if (getterNode != null) + getterDef = (IAccessorDefinition)getterNode.getDefinition(); + if (setterDef.isBindable() || (getterDef != null && getterDef.isBindable())) + { + if (setterDef.isBindable()) + { + IMetaTag[] tags = setterDef.getMetaTagsByName("Bindable"); + if (tags.length > 1) + isBindable = true; + else if (tags.length == 1) + { + if (tags[0].getAllAttributes().length == 0) + isBindable = true; + } + } + else if (getterDef != null && getterDef.isBindable()) + { + IMetaTag[] tags = getterDef.getMetaTagsByName("Bindable"); + if (tags.length > 1) + isBindable = true; + else if (tags.length == 1) + { + if (tags[0].getAllAttributes().length == 0) + isBindable = true; + } + } + } writeNewline(); writeNewline(); writeNewline(); @@ -139,6 +170,8 @@ public class AccessorEmitter extends JSSubEmitter implements else { write(ASEmitterTokens.MEMBER_ACCESS); + if (isBindable) + write(JSFlexJSEmitterTokens.BINDABLE_PREFIX); write(JSFlexJSEmitterTokens.SETTER_PREFIX); write(propName); } @@ -151,6 +184,63 @@ public class AccessorEmitter extends JSSubEmitter implements fjs.emitDefinePropertyFunction(setterNode); write(ASEmitterTokens.SEMICOLON); + + if (isBindable) + { + writeNewline(); + writeNewline(); + writeNewline(); + write(getEmitter().formatQualifiedName(qname)); + write(ASEmitterTokens.MEMBER_ACCESS); + write(JSEmitterTokens.PROTOTYPE); + write(ASEmitterTokens.MEMBER_ACCESS); + write(JSFlexJSEmitterTokens.SETTER_PREFIX); + write(propName); + write(ASEmitterTokens.SPACE); + write(ASEmitterTokens.EQUAL); + write(ASEmitterTokens.SPACE); + write(ASEmitterTokens.FUNCTION); + write(ASEmitterTokens.PAREN_OPEN); + write("value"); + write(ASEmitterTokens.PAREN_CLOSE); + write(ASEmitterTokens.SPACE); + writeNewline(ASEmitterTokens.BLOCK_OPEN); + write(ASEmitterTokens.VAR); + write(ASEmitterTokens.SPACE); + write("oldValue"); + write(ASEmitterTokens.SPACE); + write(ASEmitterTokens.EQUAL); + write(ASEmitterTokens.SPACE); + write(ASEmitterTokens.THIS); + write(ASEmitterTokens.MEMBER_ACCESS); + write(JSFlexJSEmitterTokens.GETTER_PREFIX); + write(propName); + write(ASEmitterTokens.PAREN_OPEN); + write(ASEmitterTokens.PAREN_CLOSE); + writeNewline(ASEmitterTokens.SEMICOLON); + write(ASEmitterTokens.IF); + write(ASEmitterTokens.SPACE); + write(ASEmitterTokens.PAREN_OPEN); + write("oldValue != value"); + write(ASEmitterTokens.PAREN_CLOSE); + write(ASEmitterTokens.SPACE); + writeNewline(ASEmitterTokens.BLOCK_OPEN); + write(ASEmitterTokens.THIS); + write(ASEmitterTokens.MEMBER_ACCESS); + write(JSFlexJSEmitterTokens.BINDABLE_PREFIX); + write(JSFlexJSEmitterTokens.SETTER_PREFIX); + write(propName); + write(ASEmitterTokens.PAREN_OPEN); + write("value"); + write(ASEmitterTokens.PAREN_CLOSE); + writeNewline(ASEmitterTokens.SEMICOLON); + writeNewline(" this.dispatchEvent("+fjs.formatQualifiedName(BindableEmitter.VALUECHANGE_EVENT_QNAME)+".createUpdateEvent("); + writeNewline(" this, \"" + propName + "\", oldValue, value));"); + writeNewline(ASEmitterTokens.BLOCK_CLOSE); + write(ASEmitterTokens.BLOCK_CLOSE); + write(ASEmitterTokens.SEMICOLON); + + } } } } http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/448df176/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSAccessors.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSAccessors.java b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSAccessors.java index eb27626..1f88fe4 100644 --- a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSAccessors.java +++ b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSAccessors.java @@ -21,6 +21,8 @@ package org.apache.flex.compiler.internal.codegen.js.flexjs; import org.apache.flex.compiler.driver.IBackend; 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.internal.test.ASTestBase; import org.apache.flex.compiler.tree.as.IClassNode; import org.junit.Test; @@ -30,6 +32,12 @@ import org.junit.Test; */ public class TestFlexJSAccessors extends ASTestBase { + @Override + public void setUp() + { + super.setUp(); + ((FlexJSProject)project).config = new JSGoogConfiguration(); + } @Test public void testGetAndSetAccessor() @@ -105,6 +113,39 @@ public class TestFlexJSAccessors extends ASTestBase assertOut(expected); } + @Test + public void testBindableGetAndSetAccessor() + { + IClassNode node = (IClassNode) getNode( + "public function doStuff():void {label = 'hello, bye'; var theLabel:String = label;}; private var _label:String; [Bindable] public function get label():String {return _label}; public function set label(value:String):void {_label = value}; ", + IClassNode.class, WRAP_LEVEL_CLASS); + asBlockWalker.visitClass(node); + String expected = "/**\n * @constructor\n */\nFalconTest_A = function() {\n};\n\n\n/**\n * @export\n */\nFalconTest_A.prototype.doStuff = function() {\n this.label = 'hello, bye';\n var /** @type {string} */ theLabel = this.label;\n};\n\n\n/**\n * @private\n * @type {string}\n */\nFalconTest_A.prototype._label;\n\n\n" + + "FalconTest_A.prototype.get__label = function() {\n return this._label;\n};\n\n\n" + + "FalconTest_A.prototype.bindable__set__label = function(value) {\n this._label = value;\n};\n\n\n" + + "FalconTest_A.prototype.set__label = function(value) {\nvar oldValue = this.get__label();\nif (oldValue != value) {\nthis.bindable__set__label(value);\n" + + " this.dispatchEvent(org.apache.flex.events.ValueChangeEvent.createUpdateEvent(\n" + + " this, \"label\", oldValue, value));\n}\n};\n\n\n" + + "Object.defineProperties(FalconTest_A.prototype, /** @lends {FalconTest_A.prototype} */ {\n/** @export */\n" + + "label: {\nget: FalconTest_A.prototype.get__label,\nset: FalconTest_A.prototype.set__label}}\n);"; + assertOut(expected); + } + + @Test + public void testBindableWithEventGetAndSetAccessor() + { + IClassNode node = (IClassNode) getNode( + "public function doStuff():void {label = 'hello, bye'; var theLabel:String = label;}; private var _label:String; [Bindable(\"change\")] public function get label():String {return _label}; public function set label(value:String):void {_label = value}; ", + IClassNode.class, WRAP_LEVEL_CLASS); + asBlockWalker.visitClass(node); + String expected = "/**\n * @constructor\n */\nFalconTest_A = function() {\n};\n\n\n/**\n * @export\n */\nFalconTest_A.prototype.doStuff = function() {\n this.label = 'hello, bye';\n var /** @type {string} */ theLabel = this.label;\n};\n\n\n/**\n * @private\n * @type {string}\n */\nFalconTest_A.prototype._label;\n\n\n" + + "FalconTest_A.prototype.get__label = function() {\n return this._label;\n};\n\n\n" + + "FalconTest_A.prototype.set__label = function(value) {\n this._label = value;\n};\n\n\n" + + "Object.defineProperties(FalconTest_A.prototype, /** @lends {FalconTest_A.prototype} */ {\n/** @export */\n" + + "label: {\nget: FalconTest_A.prototype.get__label,\nset: FalconTest_A.prototype.set__label}}\n);"; + assertOut(expected); + } + @Override protected IBackend createBackend() { http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/448df176/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java index a8e88d9..a6f4787 100644 --- a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java +++ b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSClass.java @@ -22,6 +22,7 @@ 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.TestGoogClass; 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.internal.tree.as.FileNode; import org.apache.flex.compiler.tree.as.IClassNode; @@ -37,6 +38,7 @@ public class TestFlexJSClass extends TestGoogClass { backend = createBackend(); project = new FlexJSProject(workspace, backend); + ((FlexJSProject)project).config = new JSGoogConfiguration(); super.setUp(); } @@ -220,6 +222,148 @@ public class TestFlexJSClass extends TestGoogClass } @Test + public void testBindableFields() + { + IClassNode node = getClassNode("public class A {[Bindable] public var a:Object;[Bindable] protected var b:String; " + + "[Bindable] private var c:int; internal var d:uint; var e:Number}"); + asBlockWalker.visitClass(node); + assertOut("/**\n * @constructor\n" + + " */\norg.apache.flex.A = function() {\n" + + "};\n\n\n" + + "/**\n" + + " * @export\n" + + " * @type {Object}\n" + + " */\n" + + "org.apache.flex.A.prototype.a_;\n\n\n" + + "/**\n" + + " * @protected\n" + + " * @type {string}\n" + + " */\n" + + "org.apache.flex.A.prototype.b_;\n\n\n" + + "/**\n" + + " * @private\n" + + " * @type {number}\n" + + " */\n" + + "org.apache.flex.A.prototype.c_ = 0;\n\n\n" + + "/**\n" + + " * @export\n" + + " * @type {number}\n" + + " */\n" + + "org.apache.flex.A.prototype.d = 0;\n\n\n" + + "/**\n" + + " * @export\n" + + " * @type {number}\n" + + " */\n" + + "org.apache.flex.A.prototype.e;Object.defineProperties(org.apache.flex.A.prototype, /** @lends {org.apache.flex.A.prototype} */ {\n" + + "/** @export\n" + + " * @private\n" + + " * @type {string} */\n" + + "b: {\n" + + "/** @this {org.apache.flex.A} */\n" + + " get: function() {\n" + + " return this.b_;\n" + + " },\n" + + "\n" + + "/** @this {org.apache.flex.A} */\n" + + "set: function(value) {\n" + + "if (value != this.b_) {\n" + + " var oldValue = this.b_;\n" + + " this.b_ = value;\n" + + " this.dispatchEvent(org.apache.flex.events.ValueChangeEvent.createUpdateEvent(\n" + + " this, \"b\", oldValue, value));\n" + + "}\n" + + "}},/** @export\n" + + " * @private\n" + + " * @type {number} */\n" + + "c: {\n" + + "/** @this {org.apache.flex.A} */\n" + + " get: function() {\n" + + " return this.c_;\n" + + " },\n" + + "\n" + + "/** @this {org.apache.flex.A} */\n" + + "set: function(value) {\n" + + "if (value != this.c_) {\n" + + " var oldValue = this.c_;\n" + + " this.c_ = value;\n" + + " this.dispatchEvent(org.apache.flex.events.ValueChangeEvent.createUpdateEvent(\n" + + " this, \"c\", oldValue, value));\n" + + "}\n" + + "}},/** @export\n" + + " * @type {Object} */\n" + + "a: {\n" + + "/** @this {org.apache.flex.A} */\n" + + " get: function() {\n" + + " return this.a_;\n" + + " },\n" + + "\n" + + "/** @this {org.apache.flex.A} */\n" + + "set: function(value) {\n" + + "if (value != this.a_) {\n" + + " var oldValue = this.a_;\n" + + " this.a_ = value;\n" + + " this.dispatchEvent(org.apache.flex.events.ValueChangeEvent.createUpdateEvent(\n" + + " this, \"a\", oldValue, value));\n" + + "}\n" + + "}}}\n" + + ");"); + } + + @Test + public void testBindableClass() + { + IClassNode node = getClassNode("[Bindable] public class A {public var a:Object;protected var b:String; " + + "private var c:int; internal var d:uint; var e:Number}"); + asBlockWalker.visitClass(node); + assertOut("/**\n * @constructor\n" + + " */\norg.apache.flex.A = function() {\n" + + "};\n\n\n" + + "/**\n" + + " * @export\n" + + " * @type {Object}\n" + + " */\n" + + "org.apache.flex.A.prototype.a_;\n\n\n" + + "/**\n" + + " * @protected\n" + + " * @type {string}\n" + + " */\n" + + "org.apache.flex.A.prototype.b;\n\n\n" + + "/**\n" + + " * @private\n" + + " * @type {number}\n" + + " */\n" + + "org.apache.flex.A.prototype.c = 0;\n\n\n" + + "/**\n" + + " * @export\n" + + " * @type {number}\n" + + " */\n" + + "org.apache.flex.A.prototype.d = 0;\n\n\n" + + "/**\n" + + " * @export\n" + + " * @type {number}\n" + + " */\n" + + "org.apache.flex.A.prototype.e;Object.defineProperties(org.apache.flex.A.prototype, /** @lends {org.apache.flex.A.prototype} */ {\n" + + "/** @export\n" + + " * @type {Object} */\n" + + "a: {\n" + + "/** @this {org.apache.flex.A} */\n" + + " get: function() {\n" + + " return this.a_;\n" + + " },\n" + + "\n" + + "/** @this {org.apache.flex.A} */\n" + + "set: function(value) {\n" + + "if (value != this.a_) {\n" + + " var oldValue = this.a_;\n" + + " this.a_ = value;\n" + + " this.dispatchEvent(org.apache.flex.events.ValueChangeEvent.createUpdateEvent(\n" + + " this, \"a\", oldValue, value));\n" + + "}\n" + + "}}}\n" + + ");"); + } + + @Test public void testFieldsWithStaticInitializers() { IClassNode node = getClassNode("public class A {public static var a:int = 10;public static var b:String = initStatic(); " http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/448df176/compiler-jx/src/test/java/org/apache/flex/compiler/internal/test/TestBase.java ---------------------------------------------------------------------- diff --git a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/test/TestBase.java b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/test/TestBase.java index 346ee10..53cf426 100644 --- a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/test/TestBase.java +++ b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/test/TestBase.java @@ -183,6 +183,10 @@ public class TestBase implements ITestBase continue; if (problem.toString().equals("An externally-visible definition with the name 'TypeError' was unexpectedly found.")) continue; + if (problem.toString().equals("An externally-visible definition with the name 'int' was unexpectedly found.")) + continue; + if (problem.toString().equals("An externally-visible definition with the name 'uint' was unexpectedly found.")) + continue; if (problem.toString().equals("No externally-visible definition with the name 'externals.as.classes.Object' was found.")) continue; if (problem.toString().equals("No externally-visible definition with the name 'externals.as.classes.String' was found.")) @@ -199,6 +203,10 @@ public class TestBase implements ITestBase continue; if (problem.toString().equals("No externally-visible definition with the name 'externals.as.classes.TypeError' was found.")) continue; + if (problem.toString().equals("No externally-visible definition with the name 'externals.as.classes.int' was found.")) + continue; + if (problem.toString().equals("No externally-visible definition with the name 'externals.as.classes.uint' was found.")) + continue; if (problem.toString().equals("An externally-visible definition with the name 'FalconTest_A' was unexpectedly found.")) continue; if (problem.toString().startsWith("No externally-visible definition with the name 'TestFlexJSGlobalFunctions"))