Updated Branches:
  refs/heads/develop 8611dcb87 -> 4af7ad216

changes to get model databinding to work in JS


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

Branch: refs/heads/develop
Commit: bd64874191821dccd18f54dba47a57c29a72608a
Parents: 734f9be
Author: Alex Harui <aha...@apache.org>
Authored: Mon Jun 24 22:50:16 2013 -0700
Committer: Alex Harui <aha...@apache.org>
Committed: Mon Jun 24 22:53:18 2013 -0700

----------------------------------------------------------------------
 .../codegen/mxml/flexjs/MXMLFlexJSEmitter.java  | 305 ++++++++++++++++++-
 .../codegen/databinding/BindingDatabase.java    |   4 +
 .../databinding/MXMLBindingDirectiveHelper.java |   1 +
 .../codegen/databinding/WatcherInfoBase.java    |   2 +-
 4 files changed, 310 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bd648741/compiler.jx/src/org/apache/flex/compiler/internal/codegen/mxml/flexjs/MXMLFlexJSEmitter.java
----------------------------------------------------------------------
diff --git 
a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/mxml/flexjs/MXMLFlexJSEmitter.java
 
b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/mxml/flexjs/MXMLFlexJSEmitter.java
index 127df84..09fe26a 100644
--- 
a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/mxml/flexjs/MXMLFlexJSEmitter.java
+++ 
b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/mxml/flexjs/MXMLFlexJSEmitter.java
@@ -19,10 +19,14 @@
 
 package org.apache.flex.compiler.internal.codegen.mxml.flexjs;
 
+
 import java.io.FilterWriter;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
+import java.util.Map.Entry;
 
+import org.apache.flex.abc.semantics.MethodInfo;
 import org.apache.flex.abc.semantics.Name;
 import org.apache.flex.abc.semantics.Namespace;
 import org.apache.flex.compiler.codegen.as.IASEmitter;
@@ -30,19 +34,31 @@ import 
org.apache.flex.compiler.codegen.mxml.flexjs.IMXMLFlexJSEmitter;
 import org.apache.flex.compiler.definitions.IClassDefinition;
 import org.apache.flex.compiler.definitions.IDefinition;
 import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.databinding.BindingDatabase;
+import org.apache.flex.compiler.internal.codegen.databinding.BindingInfo;
+import 
org.apache.flex.compiler.internal.codegen.databinding.FunctionWatcherInfo;
+import 
org.apache.flex.compiler.internal.codegen.databinding.PropertyWatcherInfo;
+import org.apache.flex.compiler.internal.codegen.databinding.WatcherInfoBase;
+import org.apache.flex.compiler.internal.codegen.databinding.XMLWatcherInfo;
+import 
org.apache.flex.compiler.internal.codegen.databinding.WatcherInfoBase.WatcherType;
 import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitter;
 import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
 import org.apache.flex.compiler.internal.codegen.mxml.MXMLEmitter;
 import org.apache.flex.compiler.internal.projects.FlexJSProject;
 import org.apache.flex.compiler.internal.projects.FlexProject;
 import org.apache.flex.compiler.internal.scopes.ASProjectScope;
+import org.apache.flex.compiler.internal.tree.as.FunctionCallNode;
+import org.apache.flex.compiler.internal.tree.as.IdentifierNode;
+import org.apache.flex.compiler.internal.tree.as.MemberAccessExpressionNode;
 import org.apache.flex.compiler.internal.tree.mxml.MXMLDocumentNode;
 import org.apache.flex.compiler.projects.ICompilerProject;
 import org.apache.flex.compiler.tree.ASTNodeID;
 import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.as.IExpressionNode;
 import org.apache.flex.compiler.tree.as.IImportNode;
 import org.apache.flex.compiler.tree.mxml.IMXMLArrayNode;
 import org.apache.flex.compiler.tree.mxml.IMXMLClassDefinitionNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLDataBindingNode;
 import org.apache.flex.compiler.tree.mxml.IMXMLDocumentNode;
 import org.apache.flex.compiler.tree.mxml.IMXMLEventSpecifierNode;
 import org.apache.flex.compiler.tree.mxml.IMXMLInstanceNode;
@@ -124,7 +140,7 @@ public class MXMLFlexJSEmitter extends MXMLEmitter 
implements
         emitClassDeclStart(cname, node, false);
 
         emitPropertyDecls();
-
+        
         emitClassDeclEnd(cname, node);
 
         emitScripts();
@@ -134,6 +150,9 @@ public class MXMLFlexJSEmitter extends MXMLEmitter 
implements
         emitPropertyGetterSetters(cname);
 
         emitMXMLDescriptorFuncs(cname);
+
+        emitBindingData(cname, cdef);
+
     }
 
     
//--------------------------------------------------------------------------
@@ -212,6 +231,252 @@ public class MXMLFlexJSEmitter extends MXMLEmitter 
implements
         }
     }
 
+    
//--------------------------------------------------------------------------
+
+    protected void emitBindingData(String cname, IClassDefinition cdef)
+    {
+        BindingDatabase bd = BindingDatabase.bindingMap.get(cdef);
+        if (bd.getBindingInfo().isEmpty())
+            return;
+
+        outputBindingInfoAsData(cname, bd);
+    }
+
+    private void outputBindingInfoAsData(String cname, BindingDatabase 
bindingDataBase)
+    {
+        writeNewline("/**");
+        writeNewline(" * @expose");
+        writeNewline(" * @this {" + cname + "}");
+        writeNewline(" */");
+        writeNewline(cname
+                + ".prototype._bindings = [");
+        
+        Set<BindingInfo> bindingInfo = bindingDataBase.getBindingInfo();
+        writeNewline(bindingInfo.size() + ","); // number of bindings
+        
+        for (BindingInfo bi : bindingInfo)
+        {
+            String s;
+            s = bi.getSourceString();
+            if (s == null)
+                s = 
getSourceStringFromGetter(bi.getExpressionNodesForGetter());
+            if (s.contains("."))
+            {
+                String[] parts = s.split("\\.");
+                write(ASEmitterTokens.SQUARE_OPEN.getToken() + 
ASEmitterTokens.DOUBLE_QUOTE.getToken() + 
+                        parts[0] + ASEmitterTokens.DOUBLE_QUOTE.getToken());
+                int n = parts.length;
+                for (int i = 1; i < n; i++)
+                {
+                    String part = parts[i];
+                    write(", " +  ASEmitterTokens.DOUBLE_QUOTE.getToken() + 
part + ASEmitterTokens.DOUBLE_QUOTE.getToken());
+                }
+                writeNewline(ASEmitterTokens.SQUARE_CLOSE.getToken() + 
ASEmitterTokens.COMMA.getToken());
+            }
+            else
+                writeNewline(ASEmitterTokens.DOUBLE_QUOTE.getToken() + s + 
+                        ASEmitterTokens.DOUBLE_QUOTE.getToken() + 
ASEmitterTokens.COMMA.getToken());
+            
+            s = bi.getDestinationString();
+            if (s.contains("."))
+            {
+                String[] parts = s.split("\\.");
+                write(ASEmitterTokens.SQUARE_OPEN.getToken() + 
ASEmitterTokens.DOUBLE_QUOTE.getToken() + 
+                        parts[0] + ASEmitterTokens.DOUBLE_QUOTE.getToken());
+                int n = parts.length;
+                for (int i = 1; i < n; i++)
+                {
+                    String part = parts[i];
+                    write(", " + ASEmitterTokens.DOUBLE_QUOTE.getToken() + 
part + ASEmitterTokens.DOUBLE_QUOTE.getToken());
+                }
+                writeNewline(ASEmitterTokens.SQUARE_CLOSE.getToken() + 
ASEmitterTokens.COMMA.getToken());
+            }
+            else
+                writeNewline(ASEmitterTokens.DOUBLE_QUOTE.getToken() + s +
+                        ASEmitterTokens.DOUBLE_QUOTE.getToken() + 
ASEmitterTokens.COMMA.getToken());
+        }
+        Set<Entry<Object, WatcherInfoBase>> watcherChains = 
bindingDataBase.getWatcherChains();
+        for (Entry<Object, WatcherInfoBase> entry : watcherChains)
+        {
+            WatcherInfoBase watcherInfoBase = entry.getValue();
+            encodeWatcher(watcherInfoBase);
+        }
+        // add a trailing null for now so I don't have to have logic where the 
watcher figures out not to add
+        // a comma
+        writeNewline("null" + ASEmitterTokens.SQUARE_CLOSE.getToken() + 
ASEmitterTokens.SEMICOLON.getToken());
+    }
+
+    private void encodeWatcher(WatcherInfoBase watcherInfoBase)
+    {
+        writeNewline(watcherInfoBase.getIndex() + 
ASEmitterTokens.COMMA.getToken());
+        WatcherType type = watcherInfoBase.getType();
+        if (type == WatcherType.FUNCTION)
+        {
+            writeNewline("0" + ASEmitterTokens.COMMA.getToken());
+
+            FunctionWatcherInfo functionWatcherInfo = 
(FunctionWatcherInfo)watcherInfoBase;
+           
+            writeNewline(ASEmitterTokens.DOUBLE_QUOTE.getToken() + 
functionWatcherInfo.getFunctionName() + 
+                    ASEmitterTokens.DOUBLE_QUOTE.getToken());
+            outputEventNames(functionWatcherInfo.getEventNames());
+            outputBindings(functionWatcherInfo.getBindings());
+        }
+        else if ((type == WatcherType.STATIC_PROPERTY) || (type == 
WatcherType.PROPERTY))
+        {
+            writeNewline((type == WatcherType.STATIC_PROPERTY ? "1" : "2") + 
+                    ASEmitterTokens.COMMA.getToken());
+
+            PropertyWatcherInfo propertyWatcherInfo = 
(PropertyWatcherInfo)watcherInfoBase;
+           
+            boolean makeStaticWatcher = (watcherInfoBase.getType() == 
WatcherType.STATIC_PROPERTY);
+            
+            // round up the getter function for the watcher, or null if we 
don't need one
+            MethodInfo propertyGetterFunction = null;
+            if (watcherInfoBase.isRoot && !makeStaticWatcher)
+            {
+                // TODO: figure out what this looks like
+                // propertyGetterFunction = this.propertyGetter;
+                assert propertyGetterFunction != null;
+            }
+            else if (watcherInfoBase.isRoot && makeStaticWatcher)
+            {
+                 // TODO: implement getter func for static watcher.
+            }
+            writeNewline(ASEmitterTokens.DOUBLE_QUOTE.getToken() + 
propertyWatcherInfo.getPropertyName() +
+                    ASEmitterTokens.DOUBLE_QUOTE.getToken() + 
ASEmitterTokens.COMMA.getToken());
+            outputEventNames(propertyWatcherInfo.getEventNames());
+            outputBindings(propertyWatcherInfo.getBindings());
+            if (propertyGetterFunction == null)
+                writeNewline("null" + ASEmitterTokens.COMMA.getToken()); // 
null is valid
+            // else 
+                // writeNewline(propertyGetterFunction);
+        }
+        else if (type == WatcherType.XML)
+        {
+            writeNewline("3" + ASEmitterTokens.COMMA.getToken());
+
+            XMLWatcherInfo xmlWatcherInfo = (XMLWatcherInfo)watcherInfoBase;
+            writeNewline(ASEmitterTokens.DOUBLE_QUOTE.getToken() + 
xmlWatcherInfo.getPropertyName() +
+                    ASEmitterTokens.DOUBLE_QUOTE.getToken() + 
ASEmitterTokens.COMMA.getToken());
+            outputBindings(xmlWatcherInfo.getBindings());
+        }
+        else assert false;     
+
+        // then recurse into children
+        Set<Entry<Object, WatcherInfoBase>> children = 
watcherInfoBase.getChildren();
+        if (children != null)
+        {
+            writeNewline(ASEmitterTokens.SQUARE_OPEN.getToken());
+            for ( Entry<Object, WatcherInfoBase> ent : children)
+            {
+                encodeWatcher(ent.getValue());
+            }
+            writeNewline("null" + ASEmitterTokens.SQUARE_CLOSE.getToken() + 
ASEmitterTokens.COMMA.getToken());
+        }
+        else
+        {
+            writeNewline("null" + ASEmitterTokens.COMMA.getToken());
+        }
+    }
+    
+    private String 
getSourceStringFromMemberAccessExpressionNode(MemberAccessExpressionNode node)
+    {
+        String s = "";
+        
+        IExpressionNode left = node.getLeftOperandNode();
+        if (left instanceof FunctionCallNode) //  probably a cast
+        {
+            IASNode child = 
((FunctionCallNode)left).getArgumentsNode().getChild(0);
+            if (child instanceof IdentifierNode)
+                s = getSourceStringFromIdentifierNode((IdentifierNode)child);
+            else if (child instanceof MemberAccessExpressionNode)
+                s = 
getSourceStringFromMemberAccessExpressionNode((MemberAccessExpressionNode)child);
+        }
+        else if (left instanceof MemberAccessExpressionNode)
+            s = 
getSourceStringFromMemberAccessExpressionNode((MemberAccessExpressionNode)left);
+        else if (left instanceof IdentifierNode)
+            s = getSourceStringFromIdentifierNode((IdentifierNode)left);
+        else
+            System.out.println("expected binding member access left node" + 
node.toString());
+        s += ".";
+        
+        IExpressionNode right = node.getRightOperandNode();
+        if (right instanceof FunctionCallNode) //  probably a cast
+        {
+            IASNode child = 
((FunctionCallNode)right).getArgumentsNode().getChild(0);
+            if (child instanceof IdentifierNode)
+                s += getSourceStringFromIdentifierNode((IdentifierNode)child);
+            else if (child instanceof MemberAccessExpressionNode)
+                s += 
getSourceStringFromMemberAccessExpressionNode((MemberAccessExpressionNode)child);
+        }
+        else if (right instanceof MemberAccessExpressionNode)
+            s += 
getSourceStringFromMemberAccessExpressionNode((MemberAccessExpressionNode)right);
+        else if (right instanceof IdentifierNode)
+            s += getSourceStringFromIdentifierNode((IdentifierNode)right);
+        else
+            System.out.println("expected binding member access right node" + 
node.toString());
+        
+        return s;
+    }
+    
+    private String getSourceStringFromIdentifierNode(IdentifierNode node)
+    {
+        return node.getName();
+    }
+    
+    private String getSourceStringFromGetter(List<IExpressionNode> nodes)
+    {
+        String s = "";
+        IExpressionNode node = nodes.get(0);
+        if (node instanceof MemberAccessExpressionNode)
+        {
+            s = 
getSourceStringFromMemberAccessExpressionNode((MemberAccessExpressionNode)node);
+        }
+        return s;
+    }
+    
+    private void outputEventNames(List<String> events)
+    {
+        if (events.size() > 1)
+        {
+            int n = events.size();
+            write(ASEmitterTokens.SQUARE_OPEN.getToken() + 
ASEmitterTokens.DOUBLE_QUOTE.getToken() +
+                    events.get(0) + ASEmitterTokens.DOUBLE_QUOTE.getToken());
+            for (int i = 1; i < n; i++)
+            {
+                String event = events.get(i);
+                write(ASEmitterTokens.COMMA.getToken() + 
ASEmitterTokens.DOUBLE_QUOTE.getToken() + 
+                        event + ASEmitterTokens.DOUBLE_QUOTE.getToken());
+            }
+            writeNewline(ASEmitterTokens.SQUARE_CLOSE.getToken() + 
ASEmitterTokens.COMMA.getToken());
+        }
+        else if (events.size() == 1)
+            writeNewline(ASEmitterTokens.DOUBLE_QUOTE.getToken() + 
events.get(0) +
+                    ASEmitterTokens.DOUBLE_QUOTE.getToken() + 
ASEmitterTokens.COMMA.getToken());
+        else
+            writeNewline("null" + ASEmitterTokens.COMMA.getToken());
+    }
+    
+    private void outputBindings(List<BindingInfo> bindings)
+    {
+        if (bindings.size() > 1)
+        {
+            int n = bindings.size();
+            write(ASEmitterTokens.SQUARE_OPEN.getToken() + 
bindings.get(0).getIndex());
+            for (int i = 1; i < n; i++)
+            {
+                BindingInfo binding = bindings.get(i);
+                write(ASEmitterTokens.COMMA.getToken() + binding.getIndex());
+            }
+            writeNewline(ASEmitterTokens.SQUARE_CLOSE.getToken() + 
ASEmitterTokens.COMMA.getToken());
+        }
+        else if (bindings.size() == 1)
+            writeNewline(bindings.get(0).getIndex() + 
ASEmitterTokens.COMMA.getToken());
+        else
+            writeNewline("null" + ASEmitterTokens.COMMA.getToken());
+        
+    }
+
     
//--------------------------------------------------------------------------    
 
     protected void emitScripts()
@@ -834,10 +1099,36 @@ public class MXMLFlexJSEmitter extends MXMLEmitter 
implements
         return false;
     }
     
+    /**
+     * Is a give node a "databinding node"?
+     */
+    public static boolean isDataBindingNode(IASNode node)
+    {
+        return node instanceof IMXMLDataBindingNode;
+    }
+    
+    protected static boolean isDataboundProp(IMXMLPropertySpecifierNode 
propertyNode)
+    {
+        boolean ret = propertyNode.getChildCount() > 0 && 
isDataBindingNode(propertyNode.getInstanceNode());
+        
+        // Sanity check that we based our conclusion about databinding on the 
correct node.
+        // (code assumes only one child if databinding)
+        int n = propertyNode.getChildCount();
+        for (int i = 0; i < n; i++)
+        {
+            boolean db = isDataBindingNode(propertyNode.getChild(i));
+            assert db == ret;
+        }
+        
+        return ret;
+    }
 
     @Override
     public void emitPropertySpecifier(IMXMLPropertySpecifierNode node)
     {
+        if (isDataboundProp(node))
+            return;
+        
         IDefinition cdef = node.getDefinition();
 
         IASNode cnode = node.getChild(0);
@@ -1010,6 +1301,18 @@ public class MXMLFlexJSEmitter extends MXMLEmitter 
implements
                 if (imp.equals(cname))
                     continue;
     
+                if (imp.equals("mx.binding.Binding"))
+                    continue;
+                if (imp.equals("mx.binding.BindingManager"))
+                    continue;
+                if (imp.equals("mx.binding.FunctionReturnWatcher"))
+                    continue;
+                if (imp.equals("mx.binding.PropertyWatcher"))
+                    continue;
+                if (imp.equals("mx.binding.StaticPropertyWatcher"))
+                    continue;
+                if (imp.equals("mx.binding.XMLWatcher"))
+                    continue;
                 if (imp.equals("mx.events.PropertyChangeEvent"))
                     continue;
                 if (imp.equals("mx.events.PropertyChangeEventKind"))

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bd648741/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/BindingDatabase.java
----------------------------------------------------------------------
diff --git 
a/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/BindingDatabase.java
 
b/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/BindingDatabase.java
index e799950..f55aba1 100644
--- 
a/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/BindingDatabase.java
+++ 
b/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/BindingDatabase.java
@@ -21,6 +21,7 @@ package org.apache.flex.compiler.internal.codegen.databinding;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -28,6 +29,7 @@ import java.util.Map.Entry;
 import java.util.Set;
 import java.util.TreeSet;
 
+import org.apache.flex.compiler.definitions.IClassDefinition;
 import 
org.apache.flex.compiler.internal.as.codegen.MXMLClassDirectiveProcessor;
 import 
org.apache.flex.compiler.internal.codegen.databinding.WatcherInfoBase.WatcherType;
 import org.apache.flex.compiler.internal.scopes.ASScope;
@@ -89,6 +91,8 @@ public class BindingDatabase
    
    private static List<BindingDatabase> _diagnosticLogger;
    
+   public static Map<IClassDefinition, BindingDatabase> bindingMap = new 
HashMap<IClassDefinition, BindingDatabase>();
+   
    /**
     * test only field. Total number of watcher info's of all types
     */

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bd648741/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/MXMLBindingDirectiveHelper.java
----------------------------------------------------------------------
diff --git 
a/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/MXMLBindingDirectiveHelper.java
 
b/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/MXMLBindingDirectiveHelper.java
index daee6d5..825324f 100644
--- 
a/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/MXMLBindingDirectiveHelper.java
+++ 
b/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/MXMLBindingDirectiveHelper.java
@@ -83,6 +83,7 @@ public class MXMLBindingDirectiveHelper
     public MXMLBindingDirectiveHelper(MXMLClassDirectiveProcessor ddp, 
IABCVisitor emitter)
     {
         host = ddp;
+        BindingDatabase.bindingMap.put(ddp.getClassDefinition(), 
bindingDataBase);
         this.emitter = emitter;
     }
     

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/bd648741/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/WatcherInfoBase.java
----------------------------------------------------------------------
diff --git 
a/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/WatcherInfoBase.java
 
b/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/WatcherInfoBase.java
index b9dd180..ba52f7f 100644
--- 
a/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/WatcherInfoBase.java
+++ 
b/compiler/src/org/apache/flex/compiler/internal/codegen/databinding/WatcherInfoBase.java
@@ -98,7 +98,7 @@ public class WatcherInfoBase
      */
     public boolean isRoot = false;
 
-    WatcherType getType()
+    public WatcherType getType()
     {
         return type;
     }

Reply via email to