This is an automated email from the ASF dual-hosted git repository.

joshtynjala pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git


The following commit(s) were added to refs/heads/develop by this push:
     new 5227fb433 JSDynamicAccessOverride, JSForInOverride, and 
JSForEachOverride metadata: followup to detect this metadata on subclasses and 
interfaces
5227fb433 is described below

commit 5227fb433493dd123fffc7fca065e7b088335c5f
Author: Josh Tynjala <[email protected]>
AuthorDate: Fri Aug 7 08:43:47 2026 -0700

    JSDynamicAccessOverride, JSForInOverride, and JSForEachOverride metadata: 
followup to detect this metadata on subclasses and interfaces
    
    Also added tests for the metadata to ensure that the emitted JS uses the 
methods specified
    
    Followup to commit 308d8867b923c0edff4bf814fa89a175123dcf37
---
 .../codegen/js/jx/BinaryOperatorEmitter.java       |  20 +-
 .../codegen/js/jx/DynamicAccessEmitter.java        |  24 ++-
 .../internal/codegen/js/jx/ForEachEmitter.java     |  46 +++--
 .../internal/codegen/js/jx/ForLoopEmitter.java     |  12 +-
 .../codegen/js/jx/UnaryOperatorEmitter.java        |  34 ++--
 .../js/royale/TestRoyaleJSDynamicOverrides.java    | 155 +++++++++++++++
 .../js/royale/TestRoyaleJSForEachOverrides.java    | 128 +++++++++++++
 .../js/royale/TestRoyaleJSForInOverrides.java      | 209 +++++++++++++++++++++
 8 files changed, 582 insertions(+), 46 deletions(-)

diff --git 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
index 904909e4f..0096ae5bf 100644
--- 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
+++ 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
@@ -869,7 +869,15 @@ public class BinaryOperatorEmitter extends JSSubEmitter 
implements
                {
                        return null;
                }
-               IMetaTag dynamicOverrideMeta = 
dynamicLeftType.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_DYNAMIC_OVERRIDE);
+               IMetaTag dynamicOverrideMeta = null;
+               for (ITypeDefinition currentType : 
dynamicLeftType.typeIteratable(getProject(), false))
+               {
+                       dynamicOverrideMeta = 
currentType.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_DYNAMIC_OVERRIDE);
+                       if (dynamicOverrideMeta != null)
+                       {
+                               break;
+                       }
+               }
                if (dynamicOverrideMeta == null)
                {
                        return null;
@@ -884,7 +892,15 @@ public class BinaryOperatorEmitter extends JSSubEmitter 
implements
                {
                        return null;
                }
-               IMetaTag dynamicOverrideMeta = 
typeDef.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_DYNAMIC_OVERRIDE);
+               IMetaTag dynamicOverrideMeta = null;
+               for (ITypeDefinition currentType : 
typeDef.typeIteratable(getProject(), false))
+               {
+                       dynamicOverrideMeta = 
currentType.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_DYNAMIC_OVERRIDE);
+                       if (dynamicOverrideMeta != null)
+                       {
+                               break;
+                       }
+               }
                if (dynamicOverrideMeta == null)
                {
                        return null;
diff --git 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java
 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java
index b0392de31..7fbac28f1 100644
--- 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java
+++ 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/DynamicAccessEmitter.java
@@ -95,18 +95,22 @@ public class DynamicAccessEmitter extends JSSubEmitter 
implements
                ITypeDefinition leftType = 
leftOperandNode.resolveType(getProject());
                if (leftType != null)
                {
-                       IMetaTag dynamicOverrideMeta = 
leftType.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_DYNAMIC_OVERRIDE);
-                       if (dynamicOverrideMeta != null)
+                       IMetaTag dynamicOverrideMeta = null;
+                       for (ITypeDefinition currentType : 
leftType.typeIteratable(getProject(), false))
                        {
-                               String getMethod = 
dynamicOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_DYNAMIC_OVERRIDE_GET_METHOD);
-                               if (getMethod != null)
+                               dynamicOverrideMeta = 
currentType.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_DYNAMIC_OVERRIDE);
+                               if (dynamicOverrideMeta != null)
                                {
-                                       write(ASEmitterTokens.MEMBER_ACCESS);
-                                       write(getMethod);
-                                       write(ASEmitterTokens.PAREN_OPEN);
-                               getWalker().walk(rightOperandNode);
-                                       write(ASEmitterTokens.PAREN_CLOSE);
-                                       return;
+                                       String getMethod = 
dynamicOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_DYNAMIC_OVERRIDE_GET_METHOD);
+                                       if (getMethod != null)
+                                       {
+                                               
write(ASEmitterTokens.MEMBER_ACCESS);
+                                               write(getMethod);
+                                               
write(ASEmitterTokens.PAREN_OPEN);
+                                               
getWalker().walk(rightOperandNode);
+                                               
write(ASEmitterTokens.PAREN_CLOSE);
+                                               return;
+                                       }
                                }
                        }
                }
diff --git 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ForEachEmitter.java
 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ForEachEmitter.java
index 4b603b287..05b707118 100644
--- 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ForEachEmitter.java
+++ 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ForEachEmitter.java
@@ -61,18 +61,26 @@ public class ForEachEmitter extends JSSubEmitter implements
         ITypeDefinition rtype = rnode.resolveType(getProject());
         if (rtype != null)
         {
-            IMetaTag forEachOverrideMeta = 
rtype.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_FOR_EACH_OVERRIDE);
-            if (forEachOverrideMeta != null)
+            IMetaTag forEachOverrideMeta = null;
+            for (ITypeDefinition currentType : 
rtype.typeIteratable(getProject(), false))
             {
-                emitForEachOverride(node, rtype, forEachOverrideMeta);
-                return;
+                forEachOverrideMeta = 
currentType.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_FOR_EACH_OVERRIDE);
+                if (forEachOverrideMeta != null)
+                {
+                    emitForEachOverride(node, rtype, forEachOverrideMeta);
+                    return;
+                }
             }
             // it's possible to use ForInOverride for for-each loops too
-            IMetaTag forInOverrideMeta = 
rtype.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_FOR_IN_OVERRIDE);
-            if (forInOverrideMeta != null)
+            IMetaTag forInOverrideMeta = null;
+            for (ITypeDefinition currentType : 
rtype.typeIteratable(getProject(), false))
             {
-                emitForInOverride(node, rtype, forInOverrideMeta);
-                return;
+                forInOverrideMeta = 
currentType.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_FOR_IN_OVERRIDE);
+                if (forInOverrideMeta != null)
+                {
+                    emitForInOverride(node, rtype, forInOverrideMeta);
+                    return;
+                }
             }
         }
 
@@ -349,7 +357,7 @@ public class ForEachEmitter extends JSSubEmitter implements
         getModel().incForeachLoopCount();
         final String iterTargetName = iterBaseName + "_target";
         final String iterResultName = iterBaseName + "_iterator";
-        final String iterKeyName = iterBaseName + "_key";
+        final String iterValueName = iterBaseName + "_value";
 
         final String iteratorMethodName = 
forEachOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_FOR_EACH_OVERRIDE_ITERATOR_METHOD);
         final String iteratorNextMethodName = 
forEachOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_FOR_EACH_OVERRIDE_ITERATOR_NEXT_METHOD);
@@ -422,7 +430,7 @@ public class ForEachEmitter extends JSSubEmitter implements
         if (iteratorHasNextMethodName == null && iteratorDoneMethodName == 
null)
         {
             writeToken(ASEmitterTokens.VAR);
-            writeToken(iterKeyName);
+            writeToken(iterValueName);
             writeToken(ASEmitterTokens.EQUAL);
             write(iterResultName);
             write(ASEmitterTokens.MEMBER_ACCESS);
@@ -434,7 +442,7 @@ public class ForEachEmitter extends JSSubEmitter implements
 
             writeToken(ASEmitterTokens.IF);
             write(ASEmitterTokens.PAREN_OPEN);
-            writeToken(iterKeyName);
+            writeToken(iterValueName);
             writeToken("==");
             write(ASEmitterTokens.UNDEFINED);
             writeToken(ASEmitterTokens.PAREN_CLOSE);
@@ -466,7 +474,7 @@ public class ForEachEmitter extends JSSubEmitter implements
 
         if (iteratorHasNextMethodName == null && iteratorDoneMethodName == 
null)
         {
-            write(iterKeyName);
+            write(iterValueName);
             write(ASEmitterTokens.SEMICOLON);
             writeNewline();
         }
@@ -499,11 +507,19 @@ public class ForEachEmitter extends JSSubEmitter 
implements
         IExpressionNode childNode = bnode.getLeftOperandNode();
         IExpressionNode rnode = bnode.getRightOperandNode();
 
-        IMetaTag dynamicOverrideMeta = 
rtype.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_DYNAMIC_OVERRIDE);
         String getMethod = null;
-        if (dynamicOverrideMeta != null)
+        IMetaTag dynamicOverrideMeta = null;
+        for (ITypeDefinition currentType : rtype.typeIteratable(getProject(), 
false))
         {
-            getMethod = 
dynamicOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_DYNAMIC_OVERRIDE_GET_METHOD);
+            dynamicOverrideMeta = 
currentType.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_DYNAMIC_OVERRIDE);
+            if (dynamicOverrideMeta != null)
+            {
+                getMethod = 
dynamicOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_DYNAMIC_OVERRIDE_GET_METHOD);
+                if (getMethod != null)
+                {
+                    break;
+                }
+            }
         }
 
         final String iterBaseName = getModel().getCurrentForeachName();
diff --git 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ForLoopEmitter.java
 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ForLoopEmitter.java
index 0a4ad168d..7a1bc899a 100644
--- 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ForLoopEmitter.java
+++ 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ForLoopEmitter.java
@@ -59,11 +59,15 @@ public class ForLoopEmitter extends JSSubEmitter implements
             ITypeDefinition rtype = rnode.resolveType(getProject());
             if (rtype != null)
             {
-                IMetaTag forInOverrideMeta = 
rtype.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_FOR_IN_OVERRIDE);
-                if (forInOverrideMeta != null)
+                IMetaTag forInOverrideMeta = null;
+                for (ITypeDefinition currentType : 
rtype.typeIteratable(getProject(), false))
                 {
-                    emitForInOverride(node, rtype, forInOverrideMeta);
-                    return;
+                    forInOverrideMeta = 
currentType.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_FOR_IN_OVERRIDE);
+                    if (forInOverrideMeta != null)
+                    {
+                        emitForInOverride(node, rtype, forInOverrideMeta);
+                        return;
+                    }
                 }
             }
         }
diff --git 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
index 72475713c..5b0171ded 100644
--- 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
+++ 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/UnaryOperatorEmitter.java
@@ -147,23 +147,27 @@ public class UnaryOperatorEmitter extends JSSubEmitter 
implements
             ITypeDefinition leftType = 
leftOperandNode.resolveType(getProject());
             if (leftType != null)
             {
-                IMetaTag dynamicOverrideMeta = 
leftType.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_DYNAMIC_OVERRIDE);
-                if (dynamicOverrideMeta != null)
+                IMetaTag dynamicOverrideMeta = null;
+                for (ITypeDefinition currentType : 
leftType.typeIteratable(getProject(), false))
                 {
-                    String deleteMethod = 
dynamicOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_DYNAMIC_OVERRIDE_DELETE_METHOD);
-                    if (deleteMethod != null)
+                    dynamicOverrideMeta = 
currentType.getMetaTagByName(IJSMetaAttributeConstants.ATTRIBUTE_DYNAMIC_OVERRIDE);
+                    if (dynamicOverrideMeta != null)
                     {
-                        
getWalker().walk(dynamicAccessNode.getLeftOperandNode());
-                        startMapping(node);
-                        write(ASEmitterTokens.MEMBER_ACCESS);
-                        write(deleteMethod);
-                        write(ASEmitterTokens.PAREN_OPEN);
-                        endMapping(node);
-                        
getWalker().walk(dynamicAccessNode.getRightOperandNode());
-                        startMapping(node);
-                        write(ASEmitterTokens.PAREN_CLOSE);
-                        endMapping(node);
-                        return;
+                        String deleteMethod = 
dynamicOverrideMeta.getAttributeValue(IJSMetaAttributeConstants.NAME_DYNAMIC_OVERRIDE_DELETE_METHOD);
+                        if (deleteMethod != null)
+                        {
+                            
getWalker().walk(dynamicAccessNode.getLeftOperandNode());
+                            startMapping(node);
+                            write(ASEmitterTokens.MEMBER_ACCESS);
+                            write(deleteMethod);
+                            write(ASEmitterTokens.PAREN_OPEN);
+                            endMapping(node);
+                            
getWalker().walk(dynamicAccessNode.getRightOperandNode());
+                            startMapping(node);
+                            write(ASEmitterTokens.PAREN_CLOSE);
+                            endMapping(node);
+                            return;
+                        }
                     }
                 }
             }
diff --git 
a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleJSDynamicOverrides.java
 
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleJSDynamicOverrides.java
new file mode 100644
index 000000000..217296030
--- /dev/null
+++ 
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleJSDynamicOverrides.java
@@ -0,0 +1,155 @@
+/*
+ *
+ *  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.royale.compiler.internal.codegen.js.royale;
+
+import org.apache.royale.compiler.driver.IBackend;
+import org.apache.royale.compiler.internal.driver.js.goog.JSGoogConfiguration;
+import org.apache.royale.compiler.internal.driver.js.royale.RoyaleBackend;
+import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
+import org.apache.royale.compiler.internal.test.ASTestBase;
+import org.apache.royale.compiler.tree.as.IClassNode;
+import org.junit.Test;
+
+public class TestRoyaleJSDynamicOverrides extends ASTestBase
+{
+    @Override
+    public void setUp()
+    {
+        backend = createBackend();
+        project = new RoyaleJSProject(workspace, backend);
+        project.config = new JSGoogConfiguration();
+        super.setUp();
+    }
+    
+    @Test
+    public void testDynamicOverride_getMethod()
+    {
+        IClassNode node = (IClassNode) 
getNode("[JSDynamicOverride(getMethod=\"get\")] class A { public function A() { 
var a = this[0]; } }",
+                       IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  var /** 
@type {*} */ a = this.get(0);\n};");
+    }
+    
+    @Test
+    public void testDynamicOverride_getMethod_subclass()
+    {
+        IClassNode node = (IClassNode) getNode("public class B extends A { 
public function B() { var a = this[0]; } }; 
[JSDynamicOverride(getMethod=\"get\")] public class A { public function A() {} 
}",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() 
{\n  B.base(this, 'constructor');\n  var /** @type {*} */ a = 
this.get(0);\n};\ngoog.inherits(B, A);");
+    }
+    
+    @Test
+    public void testDynamicOverride_getMethod_implementsInterface()
+    {
+        IClassNode node = (IClassNode) getNode("public class B implements A { 
public function B() { var a = this[0]; } }; 
[JSDynamicOverride(getMethod=\"get\")] public interface A { }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @implements {A}\n */\nB = 
function() {\n  var /** @type {*} */ a = this.get(0);\n};");
+    }
+    
+    @Test
+    public void testDynamicOverride_setMethod()
+    {
+        IClassNode node = (IClassNode) 
getNode("[JSDynamicOverride(setMethod=\"set\")] class A { public function A() { 
this[0] = 123.4; } }",
+                       IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  
this.set(0,123.4);\n};");
+    }
+    
+    @Test
+    public void testDynamicOverride_setMethod_subclass()
+    {
+        IClassNode node = (IClassNode) getNode("public class B extends A { 
public function B() { this[0] = 123.4; } }; 
[JSDynamicOverride(setMethod=\"set\")] public class A { public function A() {} 
}",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() 
{\n  B.base(this, 'constructor');\n  this.set(0,123.4);\n};\ngoog.inherits(B, 
A);");
+    }
+    
+    @Test
+    public void testDynamicOverride_setMethod_implementsInterface()
+    {
+        IClassNode node = (IClassNode) getNode("public class B implements A { 
public function B() { this[0] = 123.4; } }; 
[JSDynamicOverride(setMethod=\"set\")] public interface A { }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @implements {A}\n */\nB = 
function() {\n  this.set(0,123.4);\n};");
+    }
+    
+    @Test
+    public void testDynamicOverride_deleteMethod()
+    {
+        IClassNode node = (IClassNode) 
getNode("[JSDynamicOverride(deleteMethod=\"del\")] class A { public function 
A() { delete this[0]; } }",
+                       IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  
this.del(0);\n};");
+    }
+    
+    @Test
+    public void testDynamicOverride_deleteMethod_subclass()
+    {
+        IClassNode node = (IClassNode) getNode("public class B extends A { 
public function B() { delete this[0]; } }; 
[JSDynamicOverride(deleteMethod=\"del\")] public class A { public function A() 
{} }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() 
{\n  B.base(this, 'constructor');\n  this.del(0);\n};\ngoog.inherits(B, A);");
+    }
+    
+    @Test
+    public void testDynamicOverride_deleteMethod_implementsInterface()
+    {
+        IClassNode node = (IClassNode) getNode("public class B implements A { 
public function B() { delete this[0]; } }; 
[JSDynamicOverride(deleteMethod=\"del\")] public interface A { }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @implements {A}\n */\nB = 
function() {\n  this.del(0);\n};");
+    }
+    
+    @Test
+    public void testDynamicOverride_inMethod()
+    {
+        IClassNode node = (IClassNode) 
getNode("[JSDynamicOverride(inMethod=\"exists\")] class A { public function A() 
{ 0 in this; } }",
+                       IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  
this.exists(0);\n};");
+    }
+    
+    @Test
+    public void testDynamicOverride_inMethod_subclass()
+    {
+        IClassNode node = (IClassNode) getNode("public class B extends A { 
public function B() { 0 in this; } }; [JSDynamicOverride(inMethod=\"exists\")] 
public class A { public function A() {} }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() 
{\n  B.base(this, 'constructor');\n  this.exists(0);\n};\ngoog.inherits(B, 
A);");
+    }
+    
+    @Test
+    public void testDynamicOverride_inMethod_implementsInterface()
+    {
+        IClassNode node = (IClassNode) getNode("public class B implements A { 
public function B() { 0 in this; } }; [JSDynamicOverride(inMethod=\"exists\")] 
public interface A { }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @implements {A}\n */\nB = 
function() {\n  this.exists(0);\n};");
+    }
+
+    @Override
+    protected IBackend createBackend()
+    {
+        return new RoyaleBackend();
+    }
+
+}
diff --git 
a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleJSForEachOverrides.java
 
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleJSForEachOverrides.java
new file mode 100644
index 000000000..7fe56a5fd
--- /dev/null
+++ 
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleJSForEachOverrides.java
@@ -0,0 +1,128 @@
+/*
+ *
+ *  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.royale.compiler.internal.codegen.js.royale;
+
+import org.apache.royale.compiler.driver.IBackend;
+import org.apache.royale.compiler.internal.driver.js.goog.JSGoogConfiguration;
+import org.apache.royale.compiler.internal.driver.js.royale.RoyaleBackend;
+import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
+import org.apache.royale.compiler.internal.test.ASTestBase;
+import org.apache.royale.compiler.tree.as.IClassNode;
+import org.junit.Test;
+
+public class TestRoyaleJSForEachOverrides extends ASTestBase
+{
+    @Override
+    public void setUp()
+    {
+        backend = createBackend();
+        project = new RoyaleJSProject(workspace, backend);
+        project.config = new JSGoogConfiguration();
+        super.setUp();
+    }
+    
+    @Test
+    public void testForEachOverride_iteratorMethod_iteratorNextMethod()
+    {
+        IClassNode node = (IClassNode) 
getNode("[JSForEachOverride(iteratorMethod=\"iterator\",iteratorNextMethod=\"next\")]
 class A { public function A() { for each (var value in this) {} } }",
+                       IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  var 
foreachiter0_target = this;\n  if (foreachiter0_target)\n  {\n    var 
foreachiter0_iterator = foreachiter0_target.iterator();\n    while (true)\n    
{\n      var foreachiter0_value = foreachiter0_iterator.next();\n      if 
(foreachiter0_value == undefined) break;\n      var value = 
foreachiter0_value;\n      {\n      }}\n    }\n  \n};");
+    }
+    
+    @Test
+    public void 
testForEachOverride_iteratorMethod_iteratorNextMethod_subclass()
+    {
+        IClassNode node = (IClassNode) getNode("public class B extends A { 
public function B() { for each (var value in this) {} } }; 
[JSForEachOverride(iteratorMethod=\"iterator\",iteratorNextMethod=\"next\")] 
public class A { public function A() {} }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() 
{\n  B.base(this, 'constructor');\n  var foreachiter0_target = this;\n  if 
(foreachiter0_target)\n  {\n    var foreachiter0_iterator = 
foreachiter0_target.iterator();\n    while (true)\n    {\n      var 
foreachiter0_value = foreachiter0_iterator.next();\n      if 
(foreachiter0_value == undefined) break;\n      var value = 
foreachiter0_value;\n      {\n      }}\n    }\n  \n};\ngoog.inherits(B, A);");
+    }
+    
+    @Test
+    public void 
testForEachOverride_iteratorMethod_iteratorNextMethod_implementsInterface()
+    {
+        IClassNode node = (IClassNode) getNode("public class B implements A { 
public function B() { for each (var value in this) {} } }; 
[JSForEachOverride(iteratorMethod=\"iterator\",iteratorNextMethod=\"next\")] 
public interface A { }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @implements {A}\n */\nB = 
function() {\n  var foreachiter0_target = this;\n  if (foreachiter0_target)\n  
{\n    var foreachiter0_iterator = foreachiter0_target.iterator();\n    while 
(true)\n    {\n      var foreachiter0_value = foreachiter0_iterator.next();\n   
   if (foreachiter0_value == undefined) break;\n      var value = 
foreachiter0_value;\n      {\n      }}\n    }\n  \n};");
+    }
+    
+    @Test
+    public void 
testForEachOverride_iteratorMethod_iteratorHasNextMethod_iteratorNextMethod()
+    {
+        IClassNode node = (IClassNode) 
getNode("[JSForEachOverride(iteratorMethod=\"iterator\",iteratorHasNextMethod=\"hasNext\",iteratorNextMethod=\"next\")]
 class A { public function A() { for each (var value in this) {} } }",
+                       IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  var 
foreachiter0_target = this;\n  if (foreachiter0_target)\n  {\n    var 
foreachiter0_iterator = foreachiter0_target.iterator();\n    while 
(foreachiter0_iterator.hasNext())\n    {\n      var value = 
foreachiter0_iterator.next();\n      {\n      }}\n    }\n  \n};");
+    }
+    
+    @Test
+    public void 
testForEachOverride_iteratorMethod_iteratorHasNextMethod_iteratorNextMethod_subclass()
+    {
+        IClassNode node = (IClassNode) getNode("public class B extends A { 
public function B() { for each (var value in this) {} } }; 
[JSForEachOverride(iteratorMethod=\"iterator\",iteratorHasNextMethod=\"hasNext\",iteratorNextMethod=\"next\")]
 public class A { public function A() {} }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() 
{\n  B.base(this, 'constructor');\n  var foreachiter0_target = this;\n  if 
(foreachiter0_target)\n  {\n    var foreachiter0_iterator = 
foreachiter0_target.iterator();\n    while (foreachiter0_iterator.hasNext())\n  
  {\n      var value = foreachiter0_iterator.next();\n      {\n      }}\n    
}\n  \n};\ngoog.inherits(B, A);");
+    }
+    
+    @Test
+    public void 
testForEachOverride_iteratorMethod_iteratorHasNextMethod_iteratorNextMethod_implementsInterface()
+    {
+        IClassNode node = (IClassNode) getNode("public class B implements A { 
public function B() { for each (var value in this) {} } }; 
[JSForEachOverride(iteratorMethod=\"iterator\",iteratorHasNextMethod=\"hasNext\",iteratorNextMethod=\"next\")]
 public interface A { }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @implements {A}\n */\nB = 
function() {\n  var foreachiter0_target = this;\n  if (foreachiter0_target)\n  
{\n    var foreachiter0_iterator = foreachiter0_target.iterator();\n    while 
(foreachiter0_iterator.hasNext())\n    {\n      var value = 
foreachiter0_iterator.next();\n      {\n      }}\n    }\n  \n};");
+    }
+    
+    @Test
+    public void 
testForEachOverride_iteratorMethod_iteratorDoneMethod_iteratorNextMethod()
+    {
+        IClassNode node = (IClassNode) 
getNode("[JSForEachOverride(iteratorMethod=\"iterator\",iteratorDoneMethod=\"done\",iteratorNextMethod=\"next\")]
 class A { public function A() { for each (var value in this) {} } }",
+                       IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  var 
foreachiter0_target = this;\n  if (foreachiter0_target)\n  {\n    var 
foreachiter0_iterator = foreachiter0_target.iterator();\n    while 
(!foreachiter0_iterator.done())\n    {\n      var value = 
foreachiter0_iterator.next();\n      {\n      }}\n    }\n  \n};");
+    }
+    
+    @Test
+    public void 
testForEachOverride_iteratorMethod_iteratorDoneMethod_iteratorNextMethod_subclass()
+    {
+        IClassNode node = (IClassNode) getNode("public class B extends A { 
public function B() { for each (var value in this) {} } }; 
[JSForEachOverride(iteratorMethod=\"iterator\",iteratorDoneMethod=\"done\",iteratorNextMethod=\"next\")]
 public class A { public function A() {} }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() 
{\n  B.base(this, 'constructor');\n  var foreachiter0_target = this;\n  if 
(foreachiter0_target)\n  {\n    var foreachiter0_iterator = 
foreachiter0_target.iterator();\n    while (!foreachiter0_iterator.done())\n    
{\n      var value = foreachiter0_iterator.next();\n      {\n      }}\n    }\n  
\n};\ngoog.inherits(B, A);");
+    }
+    
+    @Test
+    public void 
testForEachOverride_iteratorMethod_iteratorDoneMethod_iteratorNextMethod_implementsInterface()
+    {
+        IClassNode node = (IClassNode) getNode("public class B implements A { 
public function B() { for each (var value in this) {} } }; 
[JSForEachOverride(iteratorMethod=\"iterator\",iteratorDoneMethod=\"done\",iteratorNextMethod=\"next\")]
 public interface A { }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @implements {A}\n */\nB = 
function() {\n  var foreachiter0_target = this;\n  if (foreachiter0_target)\n  
{\n    var foreachiter0_iterator = foreachiter0_target.iterator();\n    while 
(!foreachiter0_iterator.done())\n    {\n      var value = 
foreachiter0_iterator.next();\n      {\n      }}\n    }\n  \n};");
+    }
+
+    @Override
+    protected IBackend createBackend()
+    {
+        return new RoyaleBackend();
+    }
+
+}
diff --git 
a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleJSForInOverrides.java
 
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleJSForInOverrides.java
new file mode 100644
index 000000000..5c4e87747
--- /dev/null
+++ 
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleJSForInOverrides.java
@@ -0,0 +1,209 @@
+/*
+ *
+ *  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.royale.compiler.internal.codegen.js.royale;
+
+import org.apache.royale.compiler.driver.IBackend;
+import org.apache.royale.compiler.internal.driver.js.goog.JSGoogConfiguration;
+import org.apache.royale.compiler.internal.driver.js.royale.RoyaleBackend;
+import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
+import org.apache.royale.compiler.internal.test.ASTestBase;
+import org.apache.royale.compiler.tree.as.IClassNode;
+import org.junit.Test;
+
+public class TestRoyaleJSForInOverrides extends ASTestBase
+{
+    @Override
+    public void setUp()
+    {
+        backend = createBackend();
+        project = new RoyaleJSProject(workspace, backend);
+        project.config = new JSGoogConfiguration();
+        super.setUp();
+    }
+    
+    @Test
+    public void testForInOverride_iteratorMethod_iteratorNextMethod()
+    {
+        IClassNode node = (IClassNode) 
getNode("[JSForInOverride(iteratorMethod=\"iterator\",iteratorNextMethod=\"next\")]
 class A { public function A() { for (var key in this) {} } }",
+                       IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  var 
foreachiter0_target = this;\n  if (foreachiter0_target)\n  {\n    var 
foreachiter0_iterator = foreachiter0_target.iterator();\n    while (true)\n    
{\n      var foreachiter0_key = foreachiter0_iterator.next();\n      if 
(foreachiter0_key == undefined) break;\n      var key = foreachiter0_key;\n     
 {\n      }}\n    }\n  \n};");
+    }
+    
+    @Test
+    public void testForInOverride_iteratorMethod_iteratorNextMethod_subclass()
+    {
+        IClassNode node = (IClassNode) getNode("public class B extends A { 
public function B() { for (var key in this) {} } }; 
[JSForInOverride(iteratorMethod=\"iterator\",iteratorNextMethod=\"next\")] 
public class A { public function A() {} }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() 
{\n  B.base(this, 'constructor');\n  var foreachiter0_target = this;\n  if 
(foreachiter0_target)\n  {\n    var foreachiter0_iterator = 
foreachiter0_target.iterator();\n    while (true)\n    {\n      var 
foreachiter0_key = foreachiter0_iterator.next();\n      if (foreachiter0_key == 
undefined) break;\n      var key = foreachiter0_key;\n      {\n      }}\n    
}\n  \n};\ngoog.inherits(B, A);");
+    }
+    
+    @Test
+    public void 
testForInOverride_iteratorMethod_iteratorNextMethod_implementsInterface()
+    {
+        IClassNode node = (IClassNode) getNode("public class B implements A { 
public function B() { for (var key in this) {} } }; 
[JSForInOverride(iteratorMethod=\"iterator\",iteratorNextMethod=\"next\")] 
public interface A { }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @implements {A}\n */\nB = 
function() {\n  var foreachiter0_target = this;\n  if (foreachiter0_target)\n  
{\n    var foreachiter0_iterator = foreachiter0_target.iterator();\n    while 
(true)\n    {\n      var foreachiter0_key = foreachiter0_iterator.next();\n     
 if (foreachiter0_key == undefined) break;\n      var key = foreachiter0_key;\n 
     {\n      }}\n    }\n  \n};");
+    }
+    
+    @Test
+    public void 
testForInOverride_iteratorMethod_iteratorHasNextMethod_iteratorNextMethod()
+    {
+        IClassNode node = (IClassNode) 
getNode("[JSForInOverride(iteratorMethod=\"iterator\",iteratorHasNextMethod=\"hasNext\",iteratorNextMethod=\"next\")]
 class A { public function A() { for (var key in this) {} } }",
+                       IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  var 
foreachiter0_target = this;\n  if (foreachiter0_target)\n  {\n    var 
foreachiter0_iterator = foreachiter0_target.iterator();\n    while 
(foreachiter0_iterator.hasNext())\n    {\n      var key = 
foreachiter0_iterator.next();\n      {\n      }}\n    }\n  \n};");
+    }
+    
+    @Test
+    public void 
testForInOverride_iteratorMethod_iteratorHasNextMethod_iteratorNextMethod_subclass()
+    {
+        IClassNode node = (IClassNode) getNode("public class B extends A { 
public function B() { for (var key in this) {} } }; 
[JSForInOverride(iteratorMethod=\"iterator\",iteratorHasNextMethod=\"hasNext\",iteratorNextMethod=\"next\")]
 public class A { public function A() {} }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() 
{\n  B.base(this, 'constructor');\n  var foreachiter0_target = this;\n  if 
(foreachiter0_target)\n  {\n    var foreachiter0_iterator = 
foreachiter0_target.iterator();\n    while (foreachiter0_iterator.hasNext())\n  
  {\n      var key = foreachiter0_iterator.next();\n      {\n      }}\n    }\n  
\n};\ngoog.inherits(B, A);");
+    }
+    
+    @Test
+    public void 
testForInOverride_iteratorMethod_iteratorHasNextMethod_iteratorNextMethod_implementsInterface()
+    {
+        IClassNode node = (IClassNode) getNode("public class B implements A { 
public function B() { for (var key in this) {} } }; 
[JSForInOverride(iteratorMethod=\"iterator\",iteratorHasNextMethod=\"hasNext\",iteratorNextMethod=\"next\")]
 public interface A { }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @implements {A}\n */\nB = 
function() {\n  var foreachiter0_target = this;\n  if (foreachiter0_target)\n  
{\n    var foreachiter0_iterator = foreachiter0_target.iterator();\n    while 
(foreachiter0_iterator.hasNext())\n    {\n      var key = 
foreachiter0_iterator.next();\n      {\n      }}\n    }\n  \n};");
+    }
+    
+    @Test
+    public void 
testForInOverride_iteratorMethod_iteratorDoneMethod_iteratorNextMethod()
+    {
+        IClassNode node = (IClassNode) 
getNode("[JSForInOverride(iteratorMethod=\"iterator\",iteratorDoneMethod=\"done\",iteratorNextMethod=\"next\")]
 class A { public function A() { for (var key in this) {} } }",
+                       IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  var 
foreachiter0_target = this;\n  if (foreachiter0_target)\n  {\n    var 
foreachiter0_iterator = foreachiter0_target.iterator();\n    while 
(!foreachiter0_iterator.done())\n    {\n      var key = 
foreachiter0_iterator.next();\n      {\n      }}\n    }\n  \n};");
+    }
+    
+    @Test
+    public void 
testForInOverride_iteratorMethod_iteratorDoneMethod_iteratorNextMethod_subclass()
+    {
+        IClassNode node = (IClassNode) getNode("public class B extends A { 
public function B() { for (var key in this) {} } }; 
[JSForInOverride(iteratorMethod=\"iterator\",iteratorDoneMethod=\"done\",iteratorNextMethod=\"next\")]
 public class A { public function A() {} }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() 
{\n  B.base(this, 'constructor');\n  var foreachiter0_target = this;\n  if 
(foreachiter0_target)\n  {\n    var foreachiter0_iterator = 
foreachiter0_target.iterator();\n    while (!foreachiter0_iterator.done())\n    
{\n      var key = foreachiter0_iterator.next();\n      {\n      }}\n    }\n  
\n};\ngoog.inherits(B, A);");
+    }
+    
+    @Test
+    public void 
testForInOverride_iteratorMethod_iteratorDoneMethod_iteratorNextMethod_implementsInterface()
+    {
+        IClassNode node = (IClassNode) getNode("public class B implements A { 
public function B() { for (var key in this) {} } }; 
[JSForInOverride(iteratorMethod=\"iterator\",iteratorDoneMethod=\"done\",iteratorNextMethod=\"next\")]
 public interface A { }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @implements {A}\n */\nB = 
function() {\n  var foreachiter0_target = this;\n  if (foreachiter0_target)\n  
{\n    var foreachiter0_iterator = foreachiter0_target.iterator();\n    while 
(!foreachiter0_iterator.done())\n    {\n      var key = 
foreachiter0_iterator.next();\n      {\n      }}\n    }\n  \n};");
+    }
+    
+    @Test
+    public void testForInOverride_forEach_iteratorMethod_iteratorNextMethod()
+    {
+        IClassNode node = (IClassNode) 
getNode("[JSForInOverride(iteratorMethod=\"iterator\",iteratorNextMethod=\"next\")]
 class A { public function A() { for each (var value in this) {} } }",
+                       IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  var 
foreachiter0_target = this;\n  if (foreachiter0_target)\n  {\n    var 
foreachiter0_iterator = foreachiter0_target.iterator();\n    while (true)\n    
{\n      var foreachiter0_key = foreachiter0_iterator.next();\n      if 
(foreachiter0_key == undefined) break;\n      var value = 
foreachiter0_target[foreachiter0_key];\n      {\n      }}\n    }\n  \n};");
+    }
+    
+    @Test
+    public void 
testForInOverride_forEach_iteratorMethod_iteratorNextMethod_subclass()
+    {
+        IClassNode node = (IClassNode) getNode("public class B extends A { 
public function B() { for each (var value in this) {} } }; 
[JSForInOverride(iteratorMethod=\"iterator\",iteratorNextMethod=\"next\")] 
public class A { public function A() {} }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() 
{\n  B.base(this, 'constructor');\n  var foreachiter0_target = this;\n  if 
(foreachiter0_target)\n  {\n    var foreachiter0_iterator = 
foreachiter0_target.iterator();\n    while (true)\n    {\n      var 
foreachiter0_key = foreachiter0_iterator.next();\n      if (foreachiter0_key == 
undefined) break;\n      var value = foreachiter0_target[foreachiter0_key];\n   
   {\n      }}\n    }\n  \n};\ngoog.inherits(B, A);");
+    }
+    
+    @Test
+    public void 
testForInOverride_forEach_iteratorMethod_iteratorNextMethod_implementsInterface()
+    {
+        IClassNode node = (IClassNode) getNode("public class B implements A { 
public function B() { for each (var value in this) {} } }; 
[JSForInOverride(iteratorMethod=\"iterator\",iteratorNextMethod=\"next\")] 
public interface A { }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @implements {A}\n */\nB = 
function() {\n  var foreachiter0_target = this;\n  if (foreachiter0_target)\n  
{\n    var foreachiter0_iterator = foreachiter0_target.iterator();\n    while 
(true)\n    {\n      var foreachiter0_key = foreachiter0_iterator.next();\n     
 if (foreachiter0_key == undefined) break;\n      var value = 
foreachiter0_target[foreachiter0_key];\n      {\n      }}\n    }\n  \n};");
+    }
+    
+    @Test
+    public void 
testForInOverride_forEach_iteratorMethod_iteratorHasNextMethod_iteratorNextMethod()
+    {
+        IClassNode node = (IClassNode) 
getNode("[JSForInOverride(iteratorMethod=\"iterator\",iteratorHasNextMethod=\"hasNext\",iteratorNextMethod=\"next\")]
 class A { public function A() { for each (var value in this) {} } }",
+                       IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  var 
foreachiter0_target = this;\n  if (foreachiter0_target)\n  {\n    var 
foreachiter0_iterator = foreachiter0_target.iterator();\n    while 
(foreachiter0_iterator.hasNext())\n    {\n      var foreachiter0_key = 
foreachiter0_iterator.next();\n      var value = 
foreachiter0_target[foreachiter0_key];\n      {\n      }}\n    }\n  \n};");
+    }
+    
+    @Test
+    public void 
testForInOverride_forEach_iteratorMethod_iteratorHasNextMethod_iteratorNextMethod_subclass()
+    {
+        IClassNode node = (IClassNode) getNode("public class B extends A { 
public function B() { for each (var value in this) {} } }; 
[JSForInOverride(iteratorMethod=\"iterator\",iteratorHasNextMethod=\"hasNext\",iteratorNextMethod=\"next\")]
 public class A { public function A() {} }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() 
{\n  B.base(this, 'constructor');\n  var foreachiter0_target = this;\n  if 
(foreachiter0_target)\n  {\n    var foreachiter0_iterator = 
foreachiter0_target.iterator();\n    while (foreachiter0_iterator.hasNext())\n  
  {\n      var foreachiter0_key = foreachiter0_iterator.next();\n      var 
value = foreachiter0_target[foreachiter0_key];\n      {\n      }}\n    }\n  
\n};\ngoog.inherits(B, A);");
+    }
+    
+    @Test
+    public void 
testForInOverride_forEach_iteratorMethod_iteratorHasNextMethod_iteratorNextMethod_implementsInterface()
+    {
+        IClassNode node = (IClassNode) getNode("public class B implements A { 
public function B() { for each (var value in this) {} } }; 
[JSForInOverride(iteratorMethod=\"iterator\",iteratorHasNextMethod=\"hasNext\",iteratorNextMethod=\"next\")]
 public interface A { }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @implements {A}\n */\nB = 
function() {\n  var foreachiter0_target = this;\n  if (foreachiter0_target)\n  
{\n    var foreachiter0_iterator = foreachiter0_target.iterator();\n    while 
(foreachiter0_iterator.hasNext())\n    {\n      var foreachiter0_key = 
foreachiter0_iterator.next();\n      var value = 
foreachiter0_target[foreachiter0_key];\n      {\n      }}\n    }\n  \n};");
+    }
+    
+    @Test
+    public void 
testForInOverride_forEach_iteratorMethod_iteratorDoneMethod_iteratorNextMethod()
+    {
+        IClassNode node = (IClassNode) 
getNode("[JSForInOverride(iteratorMethod=\"iterator\",iteratorDoneMethod=\"done\",iteratorNextMethod=\"next\")]
 class A { public function A() { for each (var value in this) {} } }",
+                       IClassNode.class, WRAP_LEVEL_NONE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n */\nA = function() {\n  var 
foreachiter0_target = this;\n  if (foreachiter0_target)\n  {\n    var 
foreachiter0_iterator = foreachiter0_target.iterator();\n    while 
(!foreachiter0_iterator.done())\n    {\n      var foreachiter0_key = 
foreachiter0_iterator.next();\n      var value = 
foreachiter0_target[foreachiter0_key];\n      {\n      }}\n    }\n  \n};");
+    }
+    
+    @Test
+    public void 
testForInOverride_forEach_iteratorMethod_iteratorDoneMethod_iteratorNextMethod_subclass()
+    {
+        IClassNode node = (IClassNode) getNode("public class B extends A { 
public function B() { for each (var value in this) {} } }; 
[JSForInOverride(iteratorMethod=\"iterator\",iteratorDoneMethod=\"done\",iteratorNextMethod=\"next\")]
 public class A { public function A() {} }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @extends {A}\n */\nB = function() 
{\n  B.base(this, 'constructor');\n  var foreachiter0_target = this;\n  if 
(foreachiter0_target)\n  {\n    var foreachiter0_iterator = 
foreachiter0_target.iterator();\n    while (!foreachiter0_iterator.done())\n    
{\n      var foreachiter0_key = foreachiter0_iterator.next();\n      var value 
= foreachiter0_target[foreachiter0_key];\n      {\n      }}\n    }\n  
\n};\ngoog.inherits(B, A);");
+    }
+    
+    @Test
+    public void 
testForInOverride_forEach_iteratorMethod_iteratorDoneMethod_iteratorNextMethod_implementsInterface()
+    {
+        IClassNode node = (IClassNode) getNode("public class B implements A { 
public function B() { for each (var value in this) {} } }; 
[JSForInOverride(iteratorMethod=\"iterator\",iteratorDoneMethod=\"done\",iteratorNextMethod=\"next\")]
 public interface A { }",
+                       IClassNode.class, WRAP_LEVEL_PACKAGE);
+        asBlockWalker.visitClass(node);
+        assertOut("/**\n * @constructor\n * @implements {A}\n */\nB = 
function() {\n  var foreachiter0_target = this;\n  if (foreachiter0_target)\n  
{\n    var foreachiter0_iterator = foreachiter0_target.iterator();\n    while 
(!foreachiter0_iterator.done())\n    {\n      var foreachiter0_key = 
foreachiter0_iterator.next();\n      var value = 
foreachiter0_target[foreachiter0_key];\n      {\n      }}\n    }\n  \n};");
+    }
+
+    @Override
+    protected IBackend createBackend()
+    {
+        return new RoyaleBackend();
+    }
+
+}

Reply via email to