You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ah...@apache.org on 2016/08/30 07:30:31 UTC

[08/12] git commit: [flex-falcon] [refs/heads/develop] - [IMPROVEMENT] [NEEDS REVIEW] Removed the ASCompilationUnit 'extends' EventDispatcher implementation (which had some bugs) for binding support, and reimplemented this in falcon ClassDirectiveProcess

[IMPROVEMENT] [NEEDS REVIEW] Removed the ASCompilationUnit 'extends' EventDispatcher implementation (which had some bugs) for binding support, and reimplemented this in falcon ClassDirectiveProcessor, and also in various jx emitters for JS.
Falcon implementation is relatively straightforward, jx is a bit more fragmented because of the need to alter output in several different emitter classes.


Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/7842b1e0
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/7842b1e0
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/7842b1e0

Branch: refs/heads/develop
Commit: 7842b1e0bb0dae502fabbdd0307155d0dfce31ce
Parents: 503f721
Author: greg-dove <gr...@gmail.com>
Authored: Mon Aug 29 11:46:43 2016 +1200
Committer: greg-dove <gr...@gmail.com>
Committed: Mon Aug 29 11:46:43 2016 +1200

----------------------------------------------------------------------
 .../internal/codegen/js/JSSessionModel.java     | 31 +++++++
 .../codegen/js/flexjs/JSFlexJSEmitter.java      | 11 ++-
 .../internal/codegen/js/jx/BindableEmitter.java | 27 +++++-
 .../internal/codegen/js/jx/MethodEmitter.java   | 54 ++++++++----
 .../codegen/js/jx/PackageFooterEmitter.java     | 16 ++--
 .../codegen/js/jx/PackageHeaderEmitter.java     | 49 ++++++++---
 .../as/codegen/ClassDirectiveProcessor.java     | 58 ++++++++++++-
 .../internal/units/ASCompilationUnit.java       | 91 +-------------------
 8 files changed, 205 insertions(+), 132 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/7842b1e0/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSSessionModel.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSSessionModel.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSSessionModel.java
index c44d114..8c5fc9b 100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSSessionModel.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSSessionModel.java
@@ -55,6 +55,12 @@ public class JSSessionModel
         public String type;
     }
 
+    public enum ImplicitBindableImplementation {
+        NONE,
+        EXTENDS,
+        IMPLEMENTS
+    }
+
     private static class Context
     {
         public LinkedHashMap<String, PropertyNodes> propertyMap;
@@ -64,6 +70,7 @@ public class JSSessionModel
         public ArrayList<IVariableNode> vars;
         public ArrayList<IFunctionNode> methods;
         public IClassDefinition classDefinition;
+        public ImplicitBindableImplementation bindableImplementation;
     }
     private Stack<Context> stack = new Stack<Context>();
 
@@ -85,6 +92,10 @@ public class JSSessionModel
 
     private int foreachLoopCount = 0;
 
+    private HashMap<IClassDefinition,ImplicitBindableImplementation> implicitBindableImplementations = new HashMap<IClassDefinition, ImplicitBindableImplementation>(100);
+
+    private ImplicitBindableImplementation implicitBindableImplementation = ImplicitBindableImplementation.NONE;
+
     public IClassDefinition getCurrentClass()
     {
         return currentClass;
@@ -95,6 +106,20 @@ public class JSSessionModel
         this.currentClass = currentClass;
     }
 
+    public ImplicitBindableImplementation getImplicitBindableImplementation() {
+        return implicitBindableImplementation;
+    }
+
+    public void registerImplicitBindableImplementation(IClassDefinition classDefinition, ImplicitBindableImplementation type) {
+        implicitBindableImplementations.put(classDefinition, type);
+    }
+
+    public void unregisterImplicitBindableImplementation(IClassDefinition classDefinition) {
+        if (implicitBindableImplementations.keySet().contains(classDefinition)) {
+            implicitBindableImplementations.remove(classDefinition);
+        }
+    }
+
     public void pushClass(IClassDefinition currentClass)
     {
         Context context = new Context();
@@ -105,6 +130,7 @@ public class JSSessionModel
         context.classDefinition = this.currentClass;
         context.vars = vars;
         context.methods = methods;
+        context.bindableImplementation = implicitBindableImplementation;
         stack.push(context);
         this.currentClass = currentClass;
         bindableVars = new HashMap<String, BindableVarInfo>();
@@ -113,6 +139,9 @@ public class JSSessionModel
         propertyMap = new LinkedHashMap<String, PropertyNodes>();
         vars = new ArrayList<IVariableNode>();
         methods = new ArrayList<IFunctionNode>();
+        implicitBindableImplementation = implicitBindableImplementations.get(currentClass);
+        if (implicitBindableImplementation == null)
+            implicitBindableImplementation = ImplicitBindableImplementation.NONE;
     }
 
     public void popClass()
@@ -192,4 +221,6 @@ public class JSSessionModel
         return "foreachiter" + Integer.toString(foreachLoopCount);
     }
 
+
+
 }

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/7842b1e0/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java
index 4a1295f..e17e681 100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java
@@ -32,6 +32,8 @@ import org.apache.flex.compiler.definitions.IDefinition;
 import org.apache.flex.compiler.definitions.IPackageDefinition;
 import org.apache.flex.compiler.definitions.ITypeDefinition;
 import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.JSSessionModel;
+import org.apache.flex.compiler.internal.codegen.js.JSSessionModel.ImplicitBindableImplementation;
 import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitter;
 import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
 import org.apache.flex.compiler.internal.codegen.js.jx.AccessorEmitter;
@@ -345,10 +347,13 @@ public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
     	super.emitFunctionBlockHeader(node);
     	if (node.isConstructor())
     	{
-            IClassNode cnode = (IClassNode) node
-            .getAncestorOfType(IClassNode.class);
+            IClassNode cnode = (IClassNode) node.getAncestorOfType(IClassNode.class);
             if (cnode.getDefinition().needsEventDispatcher(getWalker().getProject())) {
-                bindableEmitter.emitBindableConstructorCode();
+                //add whatever variant of the implementation is necessary inside the constructor
+                if (getModel().getImplicitBindableImplementation() == ImplicitBindableImplementation.IMPLEMENTS)
+                    bindableEmitter.emitBindableImplementsConstructorCode();
+                else if (getModel().getImplicitBindableImplementation() == ImplicitBindableImplementation.EXTENDS)
+                    bindableEmitter.emitBindableExtendsConstructorCode(cnode.getDefinition().getQualifiedName(),false);
             }
             emitComplexInitializers(cnode);
 

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/7842b1e0/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/BindableEmitter.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/BindableEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/BindableEmitter.java
index e01ba88..8625733 100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/BindableEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/BindableEmitter.java
@@ -25,6 +25,7 @@ import org.apache.flex.compiler.constants.IASLanguageConstants;
 import org.apache.flex.compiler.definitions.IClassDefinition;
 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.ImplicitBindableImplementation;
 import org.apache.flex.compiler.internal.codegen.js.JSSessionModel.BindableVarInfo;
 import org.apache.flex.compiler.internal.codegen.js.JSSubEmitter;
 import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitter;
@@ -68,11 +69,11 @@ public class BindableEmitter extends JSSubEmitter implements
         }
     }
 
-    public void emitBindableConstructorCode() {
-        emitBindableConstructorCode(false);
+    public void emitBindableImplementsConstructorCode() {
+        emitBindableImplementsConstructorCode(false);
     }
 
-    public void emitBindableConstructorCode(boolean popIndent) {
+    public void emitBindableImplementsConstructorCode(boolean popIndent) {
         writeNewline("// Compiler generated Binding support implementation:");
         String dispatcherClass = getEmitter().formatQualifiedName(DISPATCHER_CLASS_QNAME);
         write(ASEmitterTokens.THIS);
@@ -93,6 +94,23 @@ public class BindableEmitter extends JSSubEmitter implements
 
     }
 
+    public void emitBindableExtendsConstructorCode(String qname,boolean popIndent) {
+        writeNewline("// Compiler generated Binding support implementation:");
+        write(getEmitter().formatQualifiedName(qname));
+        write(ASEmitterTokens.MEMBER_ACCESS);
+        write(JSGoogEmitterTokens.GOOG_BASE);
+        write(ASEmitterTokens.PAREN_OPEN);
+        write(ASEmitterTokens.THIS);
+        writeToken(ASEmitterTokens.COMMA);
+        write(ASEmitterTokens.SINGLE_QUOTE);
+        write(JSGoogEmitterTokens.GOOG_CONSTRUCTOR);
+        write(ASEmitterTokens.SINGLE_QUOTE);
+        write(ASEmitterTokens.PAREN_CLOSE);
+        writeNewline(ASEmitterTokens.SEMICOLON);
+        if (popIndent) writeNewline("",false);
+        else writeNewline();
+    }
+
 
     private void emitBindableInterfaceMethods(IClassDefinition definition)  {
         writeNewline();
@@ -193,7 +211,8 @@ public class BindableEmitter extends JSSubEmitter implements
     private void emitInstanceBindableVars(IClassDefinition definition) {
 
         if (definition.needsEventDispatcher(getProject())) {
-            emitBindableInterfaceMethods(definition);
+            if (getModel().getImplicitBindableImplementation() == ImplicitBindableImplementation.IMPLEMENTS)
+                emitBindableInterfaceMethods(definition);
         }
 
         String qname = definition.getQualifiedName();

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/7842b1e0/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/MethodEmitter.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/MethodEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/MethodEmitter.java
index c57233c..00c8b16 100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/MethodEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/MethodEmitter.java
@@ -30,6 +30,7 @@ import org.apache.flex.compiler.definitions.ITypeDefinition;
 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;
+import org.apache.flex.compiler.internal.codegen.js.JSSessionModel.ImplicitBindableImplementation;
 import org.apache.flex.compiler.internal.codegen.js.JSSubEmitter;
 import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitter;
 import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
@@ -65,7 +66,12 @@ public class MethodEmitter extends JSSubEmitter implements
 
         boolean isConstructor = node.isConstructor();
 
-        boolean addingBindableSupport = isConstructor && ((IClassDefinition) node.getDefinition().getAncestorOfType(IClassDefinition.class)).needsEventDispatcher(getProject());
+        boolean addingBindableImplementsSupport = isConstructor &&
+                getModel().getImplicitBindableImplementation() == ImplicitBindableImplementation.IMPLEMENTS;
+
+        boolean addingBindableExtendsSupport = !addingBindableImplementsSupport
+                                        && isConstructor
+                                        && getModel().getImplicitBindableImplementation() == ImplicitBindableImplementation.EXTENDS;
 
         String qname = null;
         IFunctionDefinition.FunctionClassification classification = fn.getFunctionClassification();
@@ -118,12 +124,16 @@ public class MethodEmitter extends JSSubEmitter implements
             write(ASEmitterTokens.BLOCK_OPEN);
             if (hasSuperClass)
                 fjs.emitSuperCall(node, JSSessionModel.CONSTRUCTOR_EMPTY);
-            if (addingBindableSupport) {
+            //add whatever variant of the bindable implementation is necessary inside the constructor
+            if (addingBindableImplementsSupport) {
                 writeNewline("",true);
-                fjs.getBindableEmitter().emitBindableConstructorCode(true);
-            } else writeNewline();
-            IClassNode cnode = (IClassNode) node
-            .getAncestorOfType(IClassNode.class);
+                fjs.getBindableEmitter().emitBindableImplementsConstructorCode(true);
+            } else if (addingBindableExtendsSupport) {
+                IClassDefinition classDefinition = (IClassDefinition) node.getDefinition().getAncestorOfType(IClassDefinition.class);
+                fjs.getBindableEmitter().emitBindableExtendsConstructorCode(classDefinition.getQualifiedName(),true);
+            } else
+                writeNewline();
+            IClassNode cnode = (IClassNode) node.getAncestorOfType(IClassNode.class);
             fjs.emitComplexInitializers(cnode);
 
             write(ASEmitterTokens.BLOCK_CLOSE);
@@ -136,17 +146,29 @@ public class MethodEmitter extends JSSubEmitter implements
             getEmitter().popSourceMapName();
         }
 
-        if (isConstructor && hasSuperClass)
+        if (isConstructor)
         {
-            writeNewline(ASEmitterTokens.SEMICOLON);
-            write(JSGoogEmitterTokens.GOOG_INHERITS);
-            write(ASEmitterTokens.PAREN_OPEN);
-            write(fjs.formatQualifiedName(qname));
-            writeToken(ASEmitterTokens.COMMA);
-            String sname = EmitterUtils.getSuperClassDefinition(node, project)
-                    .getQualifiedName();
-            write(fjs.formatQualifiedName(sname));
-            write(ASEmitterTokens.PAREN_CLOSE);
+            if (hasSuperClass) {
+                writeNewline(ASEmitterTokens.SEMICOLON);
+                write(JSGoogEmitterTokens.GOOG_INHERITS);
+                write(ASEmitterTokens.PAREN_OPEN);
+                write(fjs.formatQualifiedName(qname));
+                writeToken(ASEmitterTokens.COMMA);
+                String sname = EmitterUtils.getSuperClassDefinition(node, project)
+                        .getQualifiedName();
+                write(fjs.formatQualifiedName(sname));
+                write(ASEmitterTokens.PAREN_CLOSE);
+            } else if (addingBindableExtendsSupport) {
+                //add goog.inherits for the 'extends' bindable implementation support
+                writeNewline(ASEmitterTokens.SEMICOLON);
+                writeNewline("// Compiler generated Binding support implementation:");
+                write(JSGoogEmitterTokens.GOOG_INHERITS);
+                write(ASEmitterTokens.PAREN_OPEN);
+                write(fjs.formatQualifiedName(qname));
+                writeToken(ASEmitterTokens.COMMA);
+                write(fjs.formatQualifiedName(BindableEmitter.DISPATCHER_CLASS_QNAME));
+                write(ASEmitterTokens.PAREN_CLOSE);
+            }
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/7842b1e0/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/PackageFooterEmitter.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/PackageFooterEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/PackageFooterEmitter.java
index 1cce913..1a21820 100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/PackageFooterEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/PackageFooterEmitter.java
@@ -33,11 +33,11 @@ import org.apache.flex.compiler.definitions.ITypeDefinition;
 import org.apache.flex.compiler.definitions.metadata.IMetaTagAttribute;
 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.ImplicitBindableImplementation;
 import org.apache.flex.compiler.internal.codegen.js.JSSubEmitter;
 import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSDocEmitter;
 import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitterTokens;
 import org.apache.flex.compiler.internal.codegen.js.utils.EmitterUtils;
-import org.apache.flex.compiler.internal.definitions.ClassDefinition;
 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.ClassNode;
@@ -129,10 +129,16 @@ public class PackageFooterEmitter extends JSSubEmitter implements
 	    else
 	        enodes = ((IInterfaceNode) tnode).getExtendedInterfaceNodes();
 
-		boolean needsEventDispatcher = tnode instanceof IClassNode
-				&& ((IClassDefinition) tnode.getDefinition()).needsEventDispatcher(getProject());
+		boolean needsIEventDispatcher = tnode instanceof IClassNode
+				&& ((IClassDefinition) tnode.getDefinition()).needsEventDispatcher(getProject())
+				&& getModel().getImplicitBindableImplementation() == ImplicitBindableImplementation.IMPLEMENTS;
 
-	    if (enodes.length > 0 || needsEventDispatcher)
+		//we can remove the mapping from the model for ImplicitBindableImplementation now
+		if (tnode.getDefinition() instanceof IClassDefinition)
+				getModel().unregisterImplicitBindableImplementation(
+						(IClassDefinition) tnode.getDefinition());
+
+	    if (enodes.length > 0 || needsIEventDispatcher)
 	    {
 	        writeToken(ASEmitterTokens.COMMA);
 	
@@ -140,7 +146,7 @@ public class PackageFooterEmitter extends JSSubEmitter implements
 	        write(JSFlexJSEmitterTokens.INTERFACES);
 	        writeToken(ASEmitterTokens.COLON);
 	        write(ASEmitterTokens.SQUARE_OPEN);
-			if (needsEventDispatcher) {
+			if (needsIEventDispatcher) {
 				//add IEventDispatcher interface to implemented interfaces list
 				write(getEmitter().formatQualifiedName(BindableEmitter.DISPATCHER_INTERFACE_QNAME));
 				if (enodes.length > 0)

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/7842b1e0/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/PackageHeaderEmitter.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/PackageHeaderEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/PackageHeaderEmitter.java
index 68b347e..6d3fb3b 100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/PackageHeaderEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/PackageHeaderEmitter.java
@@ -28,14 +28,17 @@ import java.util.List;
 import org.apache.flex.compiler.asdoc.flexjs.ASDocComment;
 import org.apache.flex.compiler.codegen.ISubEmitter;
 import org.apache.flex.compiler.codegen.js.IJSEmitter;
+import org.apache.flex.compiler.constants.IASLanguageConstants;
 import org.apache.flex.compiler.definitions.*;
 import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.JSSessionModel.ImplicitBindableImplementation;
 import org.apache.flex.compiler.internal.codegen.js.JSSubEmitter;
 import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitter;
 import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitterTokens;
 import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
 import org.apache.flex.compiler.internal.codegen.js.node.NodeEmitterTokens;
 import org.apache.flex.compiler.internal.codegen.js.utils.EmitterUtils;
+import org.apache.flex.compiler.internal.definitions.ClassDefinition;
 import org.apache.flex.compiler.internal.projects.FlexJSProject;
 import org.apache.flex.compiler.internal.scopes.ASProjectScope;
 import org.apache.flex.compiler.internal.scopes.PackageScope;
@@ -192,22 +195,44 @@ public class PackageHeaderEmitter extends JSSubEmitter implements
             boolean needsBindableSupport = ((IClassDefinition) type).needsEventDispatcher(flexProject);
 
             if (needsBindableSupport) {
-                //instance bindable (and possibly static bindable) requirements
-                if (requiresList.indexOf(fjs.formatQualifiedName(BindableEmitter.DISPATCHER_INTERFACE_QNAME))==-1) {
-                    requiresList.add(fjs.formatQualifiedName(BindableEmitter.DISPATCHER_INTERFACE_QNAME));
-                }
-                if (requiresList.indexOf(fjs.formatQualifiedName(BindableEmitter.DISPATCHER_CLASS_QNAME))==-1) {
-                    requiresList.add(fjs.formatQualifiedName(BindableEmitter.DISPATCHER_CLASS_QNAME));
-                }
-            } else {
-                needsBindableSupport = ((IClassDefinition) type).needsStaticEventDispatcher(flexProject);
-                if (needsBindableSupport) {
-                    //static-only bindable *only* requires Dispatcher class, not interface
-                    if (requiresList.indexOf(fjs.formatQualifiedName(BindableEmitter.DISPATCHER_CLASS_QNAME))==-1) {
+                IClassDefinition bindableClassDef = (IClassDefinition) type;
+                ClassDefinition objectClassDefinition = (ClassDefinition)flexProject.getBuiltinType(
+                        IASLanguageConstants.BuiltinType.OBJECT);
+
+                if (bindableClassDef.resolveBaseClass(flexProject).equals(objectClassDefinition)) {
+                    //keep the decision in the model for later
+                    getModel().registerImplicitBindableImplementation( bindableClassDef,
+                                                                       ImplicitBindableImplementation.EXTENDS);
+                    // add the requiresList support for extending the dispatcher class
+                    if (!requiresList.contains(fjs.formatQualifiedName(BindableEmitter.DISPATCHER_CLASS_QNAME))) {
+                        requiresList.add(fjs.formatQualifiedName(BindableEmitter.DISPATCHER_CLASS_QNAME));
+                    }
+                } else {
+                    //keep the decision in the model for later
+                    getModel().registerImplicitBindableImplementation( bindableClassDef,
+                                                                       ImplicitBindableImplementation.IMPLEMENTS);
+                    //add the requiresList support for implementing IEventDispatcher
+                    if (!requiresList.contains(fjs.formatQualifiedName(BindableEmitter.DISPATCHER_INTERFACE_QNAME))) {
+                        requiresList.add(fjs.formatQualifiedName(BindableEmitter.DISPATCHER_INTERFACE_QNAME));
+                    }
+                    if (!requiresList.contains(fjs.formatQualifiedName(BindableEmitter.DISPATCHER_CLASS_QNAME))) {
                         requiresList.add(fjs.formatQualifiedName(BindableEmitter.DISPATCHER_CLASS_QNAME));
                     }
                 }
             }
+
+            if (!needsBindableSupport) {
+                //we still need to check for static-only bindable requirements. If it was also instance-bindable,
+                //then the static-only requirements have already been met above
+                needsBindableSupport = ((IClassDefinition) type).needsStaticEventDispatcher(flexProject);
+                //static-only bindable *only* requires the Dispatcher class, not the interface
+                if (needsBindableSupport
+                        && !requiresList.contains(fjs.formatQualifiedName(BindableEmitter.DISPATCHER_CLASS_QNAME))) {
+                    requiresList.add(fjs.formatQualifiedName(BindableEmitter.DISPATCHER_CLASS_QNAME));
+                }
+
+            }
+
         }
 
         boolean emitsRequires = emitRequires(requiresList, writtenRequires, cname);

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/7842b1e0/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/ClassDirectiveProcessor.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/ClassDirectiveProcessor.java b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/ClassDirectiveProcessor.java
index d6ab0b1..0b1d882 100644
--- a/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/ClassDirectiveProcessor.java
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/ClassDirectiveProcessor.java
@@ -371,7 +371,57 @@ class ClassDirectiveProcessor extends DirectiveProcessor
                 IASLanguageConstants.BuiltinType.OBJECT);
             ancestorClassNames.add(objectDefinition.getMName(project));
         }
-        
+
+        //handle the case where this class needs an EventDispatcher implementation for binding support
+        //we check if we can replace EventDispatcher as the super class instead of Object, and if yes,
+        //reset the ancestorClassNames to those of the binding EventDispatcher class
+        if (class_definition.needsEventDispatcher(project)) {
+            if (ancestorClassNames.size()==1) {
+                ClassDefinition objectClassDefinition = (ClassDefinition)project.getBuiltinType(
+                        IASLanguageConstants.BuiltinType.OBJECT);
+
+                if (objectClassDefinition.equals(superclassDefinition)) {
+                    //the immediate and only ancestor is Object, we have a candidate for 'upgrading' the
+                    //ancestor chain to be the Binding EventDispatcher (which can be set via compiler configuration)
+                    IDefinition eventDispatcherCheck = project.resolveQNameToDefinition(BindableHelper.STRING_EVENT_DISPATCHER);
+                    if (eventDispatcherCheck !=null && eventDispatcherCheck instanceof ClassDefinition) {
+
+                        ClassDefinition eventDispatcherClass = (ClassDefinition) eventDispatcherCheck;
+
+                        // reset the superclass Name.
+                        // This can be used for testing to avoid adding IEventDispatcher implementation later
+                        this.superclassName = eventDispatcherClass.getMName(project);
+                        iinfo.superName = superclassName;
+                        //replace "Object" at the first position in ancestorClassNames
+                        // with the Binding EventDispatcher class
+                        // (which can sometimes be configured via compiler directives)
+                        ancestorClassNames.set(0, this.superclassName);
+
+                        //now get the ancestors of the binding EventDispatcher class
+                        c = null;
+                        IClassDefinition.IClassIterator eventDispatcherIterator =
+                                eventDispatcherClass.classIterator(project, true);
+
+                        needsProtected = eventDispatcherClass.getOwnNeedsProtected();
+                        while (eventDispatcherIterator.hasNext())
+                        {
+                            c = (ClassDefinition)eventDispatcherIterator.next();
+                            needsProtected |= c.getOwnNeedsProtected();
+                            if (c != classDefinition)
+                                ancestorClassNames.add(c.getMName(project));
+                        }
+
+                        //This may not ever be needed here, but duping the safety logic from above, just in case (GD)
+                        if (eventDispatcherIterator.foundLoop())
+                            classScope.addProblem(new CircularTypeReferenceProblem(c, c.getQualifiedName()));
+
+                    }
+                }
+            }
+        }
+
+
+
         // If this class or any of its ancestor classes needs the protected flag set, set it.
         if (needsProtected)
             iinfo.flags |= ABCConstants.CLASS_FLAG_protected;
@@ -653,7 +703,11 @@ class ClassDirectiveProcessor extends DirectiveProcessor
 
     protected void generateBindableImpl()
     {
-            if( classDefinition.needsEventDispatcher(classScope.getProject()) )
+            //  initially double-check that this class has not already been set to an
+            //  implicit subclass of EventDispatcher in this ClassDirectiveProcessor's constructor
+            //  before the needsEventDispatcher check (which doesn't know about the implementation)
+            if(!this.superclassName.equals(BindableHelper.NAME_EVENT_DISPATCHER)
+                    && classDefinition.needsEventDispatcher(classScope.getProject()) )
             {
                 // Generate a EventDispatcher member, equivalent to:
                 //   private var _bindingEventDispatcher : flash.events.EventDispatcher;

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/7842b1e0/compiler/src/main/java/org/apache/flex/compiler/internal/units/ASCompilationUnit.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/internal/units/ASCompilationUnit.java b/compiler/src/main/java/org/apache/flex/compiler/internal/units/ASCompilationUnit.java
index a857cda..b22e262 100644
--- a/compiler/src/main/java/org/apache/flex/compiler/internal/units/ASCompilationUnit.java
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/units/ASCompilationUnit.java
@@ -330,95 +330,8 @@ public class ASCompilationUnit extends CompilationUnitBase
         try
         {
             IRequest<ISyntaxTreeRequestResult, ICompilationUnit> syntaxTreeRequest = this.syntaxTreeRequest.get();
-            
-            //boolean isBindable = false;
-            //PackageNode pkg = null;
-            //ClassNode classNode = null;
-            //IMetaInfo[] metaInfos = null;
-            final FileNode ast = createFileNode(getRootFileSpecification());
-            /*if (this.getProject() instanceof FlexProject)
-            {
-                IASNode child = ast.getChild(0);
-                if (child instanceof PackageNode)
-                {
-                    pkg = (PackageNode)child;
-                    IDefinitionNode[] memberNodes = pkg.getAllMemberDefinitionNodes();
-                    if (memberNodes.length > 0 && memberNodes[0] instanceof ClassNode)
-                    {
-                        classNode = (ClassNode)memberNodes[0];
-                        memberNodes = classNode.getAllMemberNodes();
-                        metaInfos = classNode.getMetaInfos();
-                        for (IMetaInfo metaInfo : metaInfos)
-                        {
-                            String name = metaInfo.getTagName();
-                            if (name.equals("Bindable"))
-                            {
-                                isBindable = true;
-                                break;
-                            }
-                        }
-                    }
-                    if (!isBindable)
-                    {
-                        for (IDefinitionNode memberNode : memberNodes)
-                        {
-                            if (memberNode instanceof BaseDefinitionNode)
-                            {
-                                BaseDefinitionNode bdn = (BaseDefinitionNode)memberNode;
-                                metaInfos = bdn.getMetaInfos();
-                                for (IMetaInfo metaInfo : metaInfos)
-                                {
-                                    String name = metaInfo.getTagName();
-                                    if (name.equals("Bindable"))
-                                    {
-                                        isBindable = true;
-                                        break;
-                                    }
-                                }
-                                if (isBindable)
-                                    break;
-                            }
-                        }
-                    }
-                    if (isBindable && (classNode != null))
-                    {
-                        IExpressionNode baseNode = classNode.getBaseClassNode();
-                        Collection<IImportNode> importNodes = new ArrayList<IImportNode>();
-                        ast.getAllImportNodes(importNodes);
-                        if (baseNode == null)
-                        {
-                            // bindable class extends Object, must switch to
-                            // extend EventDispatcher
-                            String bindableBaseClassName = BindableHelper.STRING_EVENT_DISPATCHER;
-                            String[] pieces = bindableBaseClassName.split("\\.");
-                            int n = pieces.length;
-                            IdentifierNode baseClassNode = new IdentifierNode(pieces[n - 1]); // "EventDispatcher"
-                            baseClassNode.setParent(classNode);
-                            classNode.setBaseClass(baseClassNode);
-                            ExpressionNodeBase lastNode = null;
-                            for (int i = 0; i < n - 1; i++)
-                            {
-                                IdentifierNode part = new IdentifierNode(pieces[i]);
-                                if (i > 0)
-                                {
-                                    FullNameNode packageNode = new FullNameNode(lastNode,
-                                            new ASToken(ASToken.TOKEN_OPERATOR_MEMBER_ACCESS, 0, 0, 0, 0, "."), part);
-                                    lastNode = packageNode;
-                                }
-                                else
-                                    lastNode = part;
-                            }
-                            FullNameNode fullNameNode = new FullNameNode(lastNode,
-                                    new ASToken(ASToken.TOKEN_OPERATOR_MEMBER_ACCESS, 0, 0, 0, 0, "."), baseClassNode);
-                            ImportNode importNode = new ImportNode(fullNameNode);
-                            ScopedBlockNode sbn = (ScopedBlockNode)pkg.getChild(1);
-                            sbn.addChild(importNode, 0);
-                        }
-                    }
-                }
-            }*/
-            
 
+            final FileNode ast = createFileNode(getRootFileSpecification());
             IRequest<IFileScopeRequestResult, ICompilationUnit> fileScopeRequest = this.fileScopeRequest.get();
             if ((fileScopeRequest != null) && (fileScopeRequest.isDone()))
             {
@@ -428,8 +341,6 @@ public class ASCompilationUnit extends CompilationUnitBase
             {
                 getProject().clearScopeCacheForCompilationUnit(this);
                 ast.runPostProcess(EnumSet.of(PostProcessStep.POPULATE_SCOPE));
-                //if (isBindable)
-                //    pkg.getASScope().addImport(BindableHelper.STRING_EVENT_DISPATCHER);
             }
             final ImmutableSet<String> includedFiles = ast.getIncludeHandler().getIncludedFiles();
             addScopeToProjectScope(new ASFileScope[] { ast.getFileScope() });