You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by cd...@apache.org on 2016/04/14 09:46:45 UTC

[16/18] git commit: [flex-falcon] [refs/heads/feature/maven-migration-test] - Merge branch 'develop' of https://git-wip-us.apache.org/repos/asf/flex-falcon into feature/maven-migration-test

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/de070636/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/mxml/flexjs/MXMLFlexJSEmitter.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/mxml/flexjs/MXMLFlexJSEmitter.java
index 094f5c7,0000000..8beba40
mode 100644,000000..100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/mxml/flexjs/MXMLFlexJSEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/mxml/flexjs/MXMLFlexJSEmitter.java
@@@ -1,2320 -1,0 +1,2323 @@@
 +/*
 + *
 + *  Licensed to the Apache Software Foundation (ASF) under one or more
 + *  contributor license agreements.  See the NOTICE file distributed with
 + *  this work for additional information regarding copyright ownership.
 + *  The ASF licenses this file to You under the Apache License, Version 2.0
 + *  (the "License"); you may not use this file except in compliance with
 + *  the License.  You may obtain a copy of the License at
 + *
 + *      http://www.apache.org/licenses/LICENSE-2.0
 + *
 + *  Unless required by applicable law or agreed to in writing, software
 + *  distributed under the License is distributed on an "AS IS" BASIS,
 + *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + *  See the License for the specific language governing permissions and
 + *  limitations under the License.
 + *
 + */
 +
 +package org.apache.flex.compiler.internal.codegen.mxml.flexjs;
 +
 +
 +import java.io.File;
 +import java.io.FilterWriter;
 +import java.util.ArrayList;
 +import java.util.Collections;
 +import java.util.HashMap;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Map.Entry;
 +import java.util.Set;
 +
 +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;
 +import org.apache.flex.compiler.codegen.mxml.flexjs.IMXMLFlexJSEmitter;
 +import org.apache.flex.compiler.constants.IASKeywordConstants;
 +import org.apache.flex.compiler.constants.IASLanguageConstants;
 +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.StaticPropertyWatcherInfo;
 +import org.apache.flex.compiler.internal.codegen.databinding.WatcherInfoBase;
 +import org.apache.flex.compiler.internal.codegen.databinding.WatcherInfoBase.WatcherType;
 +import org.apache.flex.compiler.internal.codegen.databinding.XMLWatcherInfo;
 +import org.apache.flex.compiler.internal.codegen.js.JSSessionModel.PropertyNodes;
 +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.jx.PackageFooterEmitter;
 +import org.apache.flex.compiler.internal.codegen.js.utils.EmitterUtils;
 +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.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.IFunctionNode;
 +import org.apache.flex.compiler.tree.as.IIdentifierNode;
 +import org.apache.flex.compiler.tree.as.IImportNode;
 +import org.apache.flex.compiler.tree.as.IVariableNode;
 +import org.apache.flex.compiler.tree.metadata.IMetaTagNode;
 +import org.apache.flex.compiler.tree.metadata.IMetaTagsNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLArrayNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLClassDefinitionNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLClassNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLComponentNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLDataBindingNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLDeclarationsNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLDocumentNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLEventSpecifierNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLFactoryNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLImplementsNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLInstanceNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLLiteralNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLMetadataNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLObjectNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLPropertySpecifierNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLScriptNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLSpecifierNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLStateNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLStringNode;
 +import org.apache.flex.compiler.tree.mxml.IMXMLStyleSpecifierNode;
 +import org.apache.flex.compiler.units.ICompilationUnit;
 +import org.apache.flex.compiler.utils.NativeUtils;
 +import org.apache.flex.compiler.visitor.mxml.IMXMLBlockWalker;
 +
 +import com.google.common.base.Joiner;
 +
 +/**
 + * @author Erik de Bruin
 + */
 +public class MXMLFlexJSEmitter extends MXMLEmitter implements
 +        IMXMLFlexJSEmitter
 +{
 +
 +	// the instances in a container
 +    private ArrayList<MXMLDescriptorSpecifier> currentInstances;
 +    private ArrayList<MXMLDescriptorSpecifier> currentPropertySpecifiers;
 +    private ArrayList<MXMLDescriptorSpecifier> descriptorTree;
 +    private MXMLDescriptorSpecifier propertiesTree;
 +    private MXMLDescriptorSpecifier currentStateOverrides;
 +    private ArrayList<MXMLEventSpecifier> events;
 +    // all instances in the current document or subdocument
 +    private ArrayList<MXMLDescriptorSpecifier> instances;
 +    // all instances in the document AND its subdocuments
 +    private ArrayList<MXMLDescriptorSpecifier> allInstances = new ArrayList<MXMLDescriptorSpecifier>();
 +    private ArrayList<MXMLScriptSpecifier> scripts;
 +    //private ArrayList<MXMLStyleSpecifier> styles;
 +    private IClassDefinition classDefinition;
 +    private IClassDefinition documentDefinition;
 +    private ArrayList<String> usedNames = new ArrayList<String>();
 +    private ArrayList<IMXMLMetadataNode> metadataNodes = new ArrayList<IMXMLMetadataNode>();
 +    
 +    private int eventCounter;
 +    private int idCounter;
 +    private int bindingCounter;
 +
 +    private boolean inMXMLContent;
 +    private boolean inStatesOverride;
 +    private boolean makingSimpleArray;
 +    
 +    private StringBuilder subDocuments = new StringBuilder();
 +    private ArrayList<String> subDocumentNames = new ArrayList<String>();
 +    private String interfaceList;
 +    
 +    /**
 +     * This keeps track of the entries in our temporary array of 
 +     * DeferredInstanceFromFunction objects that we CG to help with
 +     * State override CG.
 +     * 
 +     * Keys are Instance nodes,
 +     * values are the array index where the deferred instance is:
 +     * 
 +     *  deferred instance = local3[ nodeToIndexMap.get(an instance) ]
 +     */
 +    protected Map<IMXMLNode, Integer> nodeToIndexMap;
 +    
 +    public MXMLFlexJSEmitter(FilterWriter out)
 +    {
 +        super(out);
 +    }
 +
 +    @Override
 +    public String postProcess(String output)
 +    {
 +        IASEmitter asEmitter = ((IMXMLBlockWalker) getMXMLWalker()).getASEmitter();
 +        usedNames.addAll(((JSFlexJSEmitter)asEmitter).usedNames);
 +        
 +        boolean foundXML = false;
 +    	String[] lines = output.split("\n");
 +    	ArrayList<String> finalLines = new ArrayList<String>();
 +    	int endRequires = -1;
 +    	boolean sawRequires = false;
 +    	boolean stillSearching = true;
 +    	for (String line : lines)
 +    	{
 +    		if (stillSearching)
 +    		{
 +	            int c = line.indexOf(JSGoogEmitterTokens.GOOG_REQUIRE.getToken());
 +	            if (c > -1)
 +	            {
 +	                int c2 = line.indexOf(")");
 +	                String s = line.substring(c + 14, c2 - 1);
 +                    if (s.equals(IASLanguageConstants.XML))
 +                    {
 +                        foundXML = true;
 +                    }
 +	    			sawRequires = true;
 +	    			if (!usedNames.contains(s))
 +	    				continue;
 +	    		}
 +	    		else if (sawRequires)
 +	    		{
 +	    			stillSearching = false;
 +	    			endRequires = finalLines.size();
 +	    		}
 +    		}
 +    		finalLines.add(line);
 +    	}
 +        boolean needXML = ((FlexJSProject)(((IMXMLBlockWalker) getMXMLWalker()).getProject())).needXML;
 +        if (needXML && !foundXML)
 +        {
 +            StringBuilder appendString = new StringBuilder();
 +            appendString.append(JSGoogEmitterTokens.GOOG_REQUIRE.getToken());
 +            appendString.append(ASEmitterTokens.PAREN_OPEN.getToken());
 +            appendString.append(ASEmitterTokens.SINGLE_QUOTE.getToken());
 +            appendString.append(IASLanguageConstants.XML);
 +            appendString.append(ASEmitterTokens.SINGLE_QUOTE.getToken());
 +            appendString.append(ASEmitterTokens.PAREN_CLOSE.getToken());
 +            appendString.append(ASEmitterTokens.SEMICOLON.getToken());
 +            finalLines.add(endRequires, appendString.toString());
 +            // TODO (aharui) addLineToMappings(finalLines.size());
 +        }
 +    	// append info() structure if main CU
 +        ICompilerProject project = getMXMLWalker().getProject();
 +        if (project instanceof FlexJSProject)
 +        {
 +            FlexJSProject flexJSProject = (FlexJSProject) project;
-             String mainDef = null;
- 			try {
- 				mainDef = flexJSProject.mainCU.getQualifiedNames().get(0);
- 			} catch (InterruptedException e) {
- 				// TODO Auto-generated catch block
- 				e.printStackTrace();
- 			}
-             String thisDef = documentDefinition.getQualifiedName();
-             if (mainDef != null && mainDef.equals(thisDef))
-             {
-             	Set<String> mixins = flexJSProject.config.getIncludes();
-             	if (mixins.size() > 0)
-             	{
- 	            	String infoInject = "\n\n" + thisDef + ".prototype.info = function() {\n" +
- 	            						"  return { mixins: [";
- 	            	boolean firstOne = true;
- 	            	for (String mixin : mixins)
++        	if (flexJSProject.mainCU != null)
++        	{
++	            String mainDef = null;
++				try {
++					mainDef = flexJSProject.mainCU.getQualifiedNames().get(0);
++				} catch (InterruptedException e) {
++					// TODO Auto-generated catch block
++					e.printStackTrace();
++				}
++	            String thisDef = documentDefinition.getQualifiedName();
++	            if (mainDef != null && mainDef.equals(thisDef))
++	            {
++	            	Set<String> mixins = flexJSProject.config.getIncludes();
++	            	if (mixins.size() > 0)
 +	            	{
- 	            		if (!firstOne)
- 	            			infoInject += ", "; 
- 	            		infoInject += mixin;
- 	            		firstOne = false;
- 	                    StringBuilder appendString = new StringBuilder();
- 	                    appendString.append(JSGoogEmitterTokens.GOOG_REQUIRE.getToken());
- 	                    appendString.append(ASEmitterTokens.PAREN_OPEN.getToken());
- 	                    appendString.append(ASEmitterTokens.SINGLE_QUOTE.getToken());
- 	                    appendString.append(mixin);
- 	                    appendString.append(ASEmitterTokens.SINGLE_QUOTE.getToken());
- 	                    appendString.append(ASEmitterTokens.PAREN_CLOSE.getToken());
- 	                    appendString.append(ASEmitterTokens.SEMICOLON.getToken());
-                         finalLines.add(endRequires, appendString.toString());
-                         //addLineToMappings(finalLines.size());
++		            	String infoInject = "\n\n" + thisDef + ".prototype.info = function() {\n" +
++		            						"  return { mixins: [";
++		            	boolean firstOne = true;
++		            	for (String mixin : mixins)
++		            	{
++		            		if (!firstOne)
++		            			infoInject += ", "; 
++		            		infoInject += mixin;
++		            		firstOne = false;
++		                    StringBuilder appendString = new StringBuilder();
++		                    appendString.append(JSGoogEmitterTokens.GOOG_REQUIRE.getToken());
++		                    appendString.append(ASEmitterTokens.PAREN_OPEN.getToken());
++		                    appendString.append(ASEmitterTokens.SINGLE_QUOTE.getToken());
++		                    appendString.append(mixin);
++		                    appendString.append(ASEmitterTokens.SINGLE_QUOTE.getToken());
++		                    appendString.append(ASEmitterTokens.PAREN_CLOSE.getToken());
++		                    appendString.append(ASEmitterTokens.SEMICOLON.getToken());
++	                        finalLines.add(endRequires, appendString.toString());
++	                        //addLineToMappings(finalLines.size());
++		            	}
++		            	infoInject += "]}};";
++	                    finalLines.add(infoInject);
++	                    //addLineToMappings(finalLines.size());	            	
 +	            	}
- 	            	infoInject += "]}};";
-                     finalLines.add(infoInject);
-                     //addLineToMappings(finalLines.size());	            	
-             	}
++	            }
 +            }
 +        }
 +    	return Joiner.on("\n").join(finalLines);
 +    }
 +    
 +    @Override
 +    protected String getIndent(int numIndent)
 +    {
 +        final StringBuilder sb = new StringBuilder();
 +        for (int i = 0; i < numIndent; i++)
 +            sb.append(JSFlexJSEmitterTokens.INDENT.getToken());
 +        return sb.toString();
 +    }
 +
 +    //--------------------------------------------------------------------------
 +
 +    @Override
 +    public void emitDeclarations(IMXMLDeclarationsNode node)
 +    {
 +    	inMXMLContent = true;
 +        MXMLDescriptorSpecifier currentInstance = getCurrentDescriptor("i");
 +
 +        MXMLDescriptorSpecifier currentPropertySpecifier = new MXMLDescriptorSpecifier();
 +        currentPropertySpecifier.isProperty = true;
 +        currentPropertySpecifier.name = "mxmlContent";
 +        currentPropertySpecifier.parent = currentInstance;
 +        descriptorTree.add(currentPropertySpecifier);
 +        moveDown(false, currentInstance, currentPropertySpecifier);
 +    	super.emitDeclarations(node);
 +        moveUp(false, false);
 +    	inMXMLContent = false;
 +    }
 +    
 +    @Override
 +    public void emitDocument(IMXMLDocumentNode node)
 +    {
 +        descriptorTree = new ArrayList<MXMLDescriptorSpecifier>();
 +        propertiesTree = new MXMLDescriptorSpecifier();
 +
 +        events = new ArrayList<MXMLEventSpecifier>();
 +        instances = new ArrayList<MXMLDescriptorSpecifier>();
 +        scripts = new ArrayList<MXMLScriptSpecifier>();
 +        //styles = new ArrayList<MXMLStyleSpecifier>();
 +
 +        currentInstances = new ArrayList<MXMLDescriptorSpecifier>();
 +        currentStateOverrides = new MXMLDescriptorSpecifier();
 +        currentPropertySpecifiers = new ArrayList<MXMLDescriptorSpecifier>();
 +
 +        eventCounter = 0;
 +        idCounter = 0;
 +        bindingCounter = 0;
 +        
 +        // visit MXML
 +        IClassDefinition cdef = node.getClassDefinition();
 +        classDefinition = cdef;
 +        documentDefinition = cdef;
 +        
 +        // TODO (mschmalle) will remove this cast as more things get abstracted
 +        JSFlexJSEmitter fjs = (JSFlexJSEmitter) ((IMXMLBlockWalker) getMXMLWalker())
 +                .getASEmitter();
 +
 +        fjs.getModel().setCurrentClass(cdef);
 +
 +        // visit tags
 +        final int len = node.getChildCount();
 +        for (int i = 0; i < len; i++)
 +        {
 +            getMXMLWalker().walk(node.getChild(i));
 +        }
 +
 +        String cname = node.getFileNode().getName();
 +
 +        emitHeader(node);
 +
 +        emitClassDeclStart(cname, node.getBaseClassName(), false);
 +
 +        emitComplexInitializers(node);
 +
 +        emitPropertyDecls();
 +        
 +        emitClassDeclEnd(cname, node.getBaseClassName());
 +
 +        emitMetaData(cdef);
 +
 +        write(subDocuments.toString());
 +        writeNewline();
 +
 +        emitScripts();
 +
 +        fjs.getBindableEmitter().emit(cdef);
 +        fjs.getAccessorEmitter().emit(cdef);
 +        
 +        emitEvents(cname);
 +
 +        emitPropertyGetterSetters(cname);
 +
 +        emitMXMLDescriptorFuncs(cname);
 +
 +        emitBindingData(cname, cdef);
 +    }
 +
 +    public void emitSubDocument(IMXMLComponentNode node)
 +    {
 +        ArrayList<MXMLDescriptorSpecifier> oldDescriptorTree;
 +        MXMLDescriptorSpecifier oldPropertiesTree;
 +        ArrayList<MXMLEventSpecifier> oldEvents;
 +        ArrayList<MXMLScriptSpecifier> oldScripts;
 +        ArrayList<MXMLDescriptorSpecifier> oldCurrentInstances;
 +        ArrayList<MXMLDescriptorSpecifier> oldInstances;
 +        ArrayList<MXMLDescriptorSpecifier> oldCurrentPropertySpecifiers;
 +        int oldEventCounter;
 +        int oldIdCounter;
 +        boolean oldInMXMLContent;
 +        
 +        oldDescriptorTree = descriptorTree;
 +        descriptorTree = new ArrayList<MXMLDescriptorSpecifier>();
 +        oldPropertiesTree = propertiesTree;
 +        propertiesTree = new MXMLDescriptorSpecifier();
 +
 +        oldInMXMLContent = inMXMLContent;
 +        inMXMLContent = false;
 +        oldEvents = events;
 +        events = new ArrayList<MXMLEventSpecifier>();
 +        oldInstances = instances;
 +        instances = new ArrayList<MXMLDescriptorSpecifier>();
 +        oldScripts = scripts;
 +        scripts = new ArrayList<MXMLScriptSpecifier>();
 +        //styles = new ArrayList<MXMLStyleSpecifier>();
 +
 +        oldCurrentInstances = currentInstances;
 +        currentInstances = new ArrayList<MXMLDescriptorSpecifier>();
 +        oldCurrentPropertySpecifiers = currentPropertySpecifiers;
 +        currentPropertySpecifiers = new ArrayList<MXMLDescriptorSpecifier>();
 +
 +        oldEventCounter = eventCounter;
 +        eventCounter = 0;
 +        oldIdCounter = idCounter;
 +        idCounter = 0;
 +
 +        // visit MXML
 +        IClassDefinition oldClassDef = classDefinition;
 +        IClassDefinition cdef = node.getContainedClassDefinition();
 +        classDefinition = cdef;
 +        IASEmitter asEmitter = ((IMXMLBlockWalker) getMXMLWalker())
 +                .getASEmitter();
 +        ((JSFlexJSEmitter) asEmitter).getModel().pushClass(cdef);
 +        
 +        IASNode classNode = node.getContainedClassDefinitionNode();
 +        // visit tags
 +        final int len = classNode.getChildCount();
 +        for (int i = 0; i < len; i++)
 +        {
 +            getMXMLWalker().walk(classNode.getChild(i));
 +        }
 +
 +        String cname = cdef.getQualifiedName();
 +        subDocumentNames.add(cname);
 +        ((JSFlexJSEmitter) asEmitter).mxmlEmitter = this;
 +        String baseClassName = cdef.getBaseClassAsDisplayString();
 +
 +        emitClassDeclStart(cname, baseClassName, false);
 +
 +        emitComplexInitializers(classNode);
 +        
 +        emitPropertyDecls();
 +        
 +        emitClassDeclEnd(cname, baseClassName);
 +
 +        emitMetaData(cdef);
 +
 +        emitScripts();
 +
 +        emitEvents(cname);
 +
 +        emitPropertyGetterSetters(cname);
 +
 +        emitMXMLDescriptorFuncs(cname);
 +
 +        emitBindingData(cname, cdef);
 +
 +        write(((JSFlexJSEmitter) asEmitter).stringifyDefineProperties(cdef));
 +        
 +        descriptorTree = oldDescriptorTree;
 +        propertiesTree = oldPropertiesTree;
 +        events = oldEvents;
 +        scripts = oldScripts;
 +        currentInstances = oldCurrentInstances;
 +        allInstances.addAll(instances);
 +        instances = oldInstances;
 +        currentPropertySpecifiers = oldCurrentPropertySpecifiers;
 +        eventCounter = oldEventCounter;
 +        idCounter = oldIdCounter;
 +        inMXMLContent = oldInMXMLContent;
 +        classDefinition = oldClassDef;
 +        ((JSFlexJSEmitter) asEmitter).getModel().popClass();
 +        ((JSFlexJSEmitter) asEmitter).mxmlEmitter = null;
 +
 +    }
 +
 +    @Override
 +    public void emitMetadata(IMXMLMetadataNode node)
 +    {
 +        metadataNodes.add(node);
 +    }
 +
 +    //--------------------------------------------------------------------------
 +
 +    protected void emitClassDeclStart(String cname, String baseClassName,
 +            boolean indent)
 +    {
 +        writeNewline();
 +        writeNewline("/**");
 +        writeNewline(" * @constructor");
 +        writeNewline(" * @extends {" + formatQualifiedName(baseClassName) + "}");
 +        writeNewline(" */");
 +        writeToken(formatQualifiedName(cname));
 +        writeToken(ASEmitterTokens.EQUAL);
 +        write(ASEmitterTokens.FUNCTION);
 +        write(ASEmitterTokens.PAREN_OPEN);
 +        writeToken(ASEmitterTokens.PAREN_CLOSE);
 +        if (indent)
 +            indentPush();
 +        writeNewline(ASEmitterTokens.BLOCK_OPEN, true);
 +        write(formatQualifiedName(cname));
 +        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);        
 +    }
 +
 +    //--------------------------------------------------------------------------
 +
 +    protected void emitClassDeclEnd(String cname, String baseClassName)
 +    {
 +        writeNewline();
 +        writeNewline("/**");
 +        writeNewline(" * @private");
 +        writeNewline(" * @type {Array}");
 +        writeNewline(" */");
 +        writeNewline("this.mxmldd;");
 +
 +        // top level is 'mxmlContent', skip it...
 +        if (currentStateOverrides.propertySpecifiers.size() > 0)
 +        {
 +            MXMLDescriptorSpecifier root = currentStateOverrides;
 +            root.isTopNode = true;
 +    
 +	        writeNewline("/**");
 +	        writeNewline(" * @export");
 +	        writeNewline(" * @type {Array}");
 +	        writeNewline(" */");
 +	        writeNewline("this.mxmlsd = " + ASEmitterTokens.SQUARE_OPEN.getToken());
 +	        indentPush();
 +	        write(root.outputStateDescriptors());
 +	        write("null");
 +	        write(ASEmitterTokens.SQUARE_CLOSE);
 +	        indentPop();
 +	        writeNewline(ASEmitterTokens.SEMICOLON);
 +        }
 +        
 +        writeNewline();
 +        writeNewline("/**");
 +        writeNewline(" * @private");
 +        writeNewline(" * @type {Array}");
 +        writeNewline(" */");
 +
 +        indentPop();
 +        writeNewline("this.mxmldp;");
 +
 +        if (propertiesTree.propertySpecifiers.size() > 0 ||
 +                propertiesTree.eventSpecifiers.size() > 0)
 +        {
 +            indentPush();
 +            writeNewline();
 +            writeNewline("this.generateMXMLAttributes");
 +            write(ASEmitterTokens.PAREN_OPEN);
 +            write(ASEmitterTokens.SQUARE_OPEN);
 +    
 +            MXMLDescriptorSpecifier root = propertiesTree;
 +            root.isTopNode = true;
 +            writeNewline(root.output(true));
 +    
 +            write(ASEmitterTokens.SQUARE_CLOSE);
 +            write(ASEmitterTokens.PAREN_CLOSE);
 +            writeNewline(ASEmitterTokens.SEMICOLON);
 +            indentPop();
 +            writeNewline();
 +        }
 +
 +        write(ASEmitterTokens.BLOCK_CLOSE);
 +        writeNewline(ASEmitterTokens.SEMICOLON);
 +        write(JSGoogEmitterTokens.GOOG_INHERITS);
 +        write(ASEmitterTokens.PAREN_OPEN);
 +        write(formatQualifiedName(cname));
 +        writeToken(ASEmitterTokens.COMMA);
 +        write(formatQualifiedName(baseClassName));
 +        write(ASEmitterTokens.PAREN_CLOSE);
 +        writeNewline(ASEmitterTokens.SEMICOLON);
 +        writeNewline();
 +        writeNewline();
 +    }
 +
 +    //--------------------------------------------------------------------------
 +
 +    protected void emitMetaData(IClassDefinition cdef)
 +    {
 +        String cname = cdef.getQualifiedName();
 +        
 +        writeNewline("/**");
 +        writeNewline(" * Metadata");
 +        writeNewline(" *");
 +        writeNewline(" * @type {Object.<string, Array.<Object>>}");
 +        writeNewline(" */");
 +        write(formatQualifiedName(cname) + ".prototype.FLEXJS_CLASS_INFO = { names: [{ name: '");
 +        write(cdef.getBaseName());
 +        write("', qName: '");
 +        write(formatQualifiedName(cname));
 +        write("' }]");
 +        if (interfaceList != null)
 +        {
 +        	write(", interfaces: [");
 +        	write(interfaceList);
 +        	write("]");
 +        }
 +        write(" };");
 +        
 +	    writeNewline();
 +	    writeNewline();
 +	    writeNewline();
 +        writeNewline("/**");
 +	    writeNewline(" * Prevent renaming of class. Needed for reflection.");
 +        writeNewline(" */");
 +	    write(JSFlexJSEmitterTokens.GOOG_EXPORT_SYMBOL);
 +	    write(ASEmitterTokens.PAREN_OPEN);
 +	    write(ASEmitterTokens.SINGLE_QUOTE);
 +	    write(formatQualifiedName(cname));
 +	    write(ASEmitterTokens.SINGLE_QUOTE);
 +	    write(ASEmitterTokens.COMMA);
 +	    write(ASEmitterTokens.SPACE);
 +	    write(formatQualifiedName(cname));
 +	    write(ASEmitterTokens.PAREN_CLOSE);
 +	    write(ASEmitterTokens.SEMICOLON);
 +
 +        emitReflectionData(cdef);
 +        writeNewline();
 +        writeNewline();
 +        
 +    }
 +    
 +    private void emitReflectionData(IClassDefinition cdef)
 +    {
 +        JSFlexJSEmitter asEmitter = (JSFlexJSEmitter)((IMXMLBlockWalker) getMXMLWalker()).getASEmitter();
 +
 +        ArrayList<PackageFooterEmitter.VariableData> varData = new ArrayList<PackageFooterEmitter.VariableData>();
 +        // vars can only come from script blocks?
 +        List<IVariableNode> vars = asEmitter.getModel().getVars();
 +        for (IVariableNode varNode : vars)
 +        {
 +            String ns = varNode.getNamespace();
 +            if (ns == IASKeywordConstants.PUBLIC)
 +            {
 +            	PackageFooterEmitter.VariableData data = asEmitter.packageFooterEmitter.new VariableData();
 +            	varData.add(data);
 +            	data.name = varNode.getName();
 +        	    data.type = formatQualifiedName(varNode.getVariableType());
 +        	    IMetaTagsNode metaData = varNode.getMetaTags();
 +        	    if (metaData != null)
 +        	    {
 +        	    	IMetaTagNode[] tags = metaData.getAllTags();
 +        	    	if (tags.length > 0)
 +        	    		data.metaData = tags;
 +        	    }
 +            }
 +        }
 +        
 +        ArrayList<PackageFooterEmitter.MethodData> accessorData = new ArrayList<PackageFooterEmitter.MethodData>();
 +        HashMap<String, PropertyNodes> accessors = asEmitter.getModel().getPropertyMap();
 +        for (String propName : accessors.keySet())
 +        {
 +        	PropertyNodes p = accessors.get(propName);
 +        	IFunctionNode accessorNode = p.getter;
 +        	if (accessorNode == null)
 +        		accessorNode = p.setter;
 +            String ns = accessorNode.getNamespace();
 +            if (ns == IASKeywordConstants.PUBLIC)
 +            {
 +            	PackageFooterEmitter.MethodData data = asEmitter.packageFooterEmitter.new MethodData();
 +            	accessorData.add(data);
 +            	data.name = accessorNode.getName();
 +            	if (p.getter != null)
 +            		data.type = formatQualifiedName(p.getter.getReturnType());
 +            	else
 +            		data.type = formatQualifiedName(p.setter.getVariableType());
 +	    	    data.declaredBy = formatQualifiedName(cdef.getQualifiedName());
 +        	    IMetaTagsNode metaData = accessorNode.getMetaTags();
 +        	    if (metaData != null)
 +        	    {
 +        	    	IMetaTagNode[] tags = metaData.getAllTags();
 +        	    	if (tags.length > 0)
 +        	    		data.metaData = tags;
 +        	    }
 +            }
 +        }
 +        
 +        for (MXMLDescriptorSpecifier instance : instances)
 +        {
 +            if (!instance.id.startsWith(MXMLFlexJSEmitterTokens.ID_PREFIX
 +                    .getToken()))
 +            {
 +	        	PackageFooterEmitter.MethodData data = asEmitter.packageFooterEmitter.new MethodData();
 +	        	accessorData.add(data);
 +	        	data.name = instance.id;
 +	        	data.type = formatQualifiedName(instance.name);
 +	    	    data.declaredBy = formatQualifiedName(cdef.getQualifiedName());
 +            }	        	
 +        }
 +        
 +        ArrayList<PackageFooterEmitter.MethodData> methodData = new ArrayList<PackageFooterEmitter.MethodData>();
 +        List<IFunctionNode> methods = asEmitter.getModel().getMethods();
 +        for (IFunctionNode methodNode : methods)
 +        {
 +            String ns = methodNode.getNamespace();
 +            if (ns == IASKeywordConstants.PUBLIC)
 +            {
 +            	PackageFooterEmitter.MethodData data = asEmitter.packageFooterEmitter.new MethodData();
 +            	methodData.add(data);
 +            	data.name = methodNode.getName();
 +            	data.type = formatQualifiedName(methodNode.getReturnType());
 +        	    data.declaredBy = formatQualifiedName(cdef.getQualifiedName());
 +        	    IMetaTagsNode metaData = methodNode.getMetaTags();
 +        	    if (metaData != null)
 +        	    {
 +        	    	IMetaTagNode[] tags = metaData.getAllTags();
 +        	    	if (tags.length > 0)
 +        	    		data.metaData = tags;
 +        	    }
 +            }
 +        }
 +        
 +        for (MXMLEventSpecifier event : events)
 +        {
 +        	PackageFooterEmitter.MethodData data = asEmitter.packageFooterEmitter.new MethodData();
 +        	methodData.add(data);
 +        	data.name = event.eventHandler;
 +        	data.type = ASEmitterTokens.VOID.getToken();
 +    	    data.declaredBy = formatQualifiedName(cdef.getQualifiedName());
 +        }
 +        
 +        ArrayList<IMetaTagNode> metadataTagNodes = new ArrayList<IMetaTagNode>();
 +        for (IMXMLMetadataNode metadataTag : metadataNodes)
 +        {
 +        	IMetaTagNode[] tags = metadataTag.getMetaTagNodes();
 +        	for (IMetaTagNode tag : tags)
 +        	{
 +        		metadataTagNodes.add(tag);
 +        	}
 +        }
 +        IMetaTagNode[] metaDataTags = new IMetaTagNode[metadataTagNodes.size()];
 +        asEmitter.packageFooterEmitter.emitReflectionData(formatQualifiedName(cdef.getQualifiedName()), varData, 
 +        		accessorData, methodData, metadataTagNodes.toArray(metaDataTags));
 +    }
 +
 +    //--------------------------------------------------------------------------
 +
 +    protected void emitPropertyDecls()
 +    {
 +        for (MXMLDescriptorSpecifier instance : instances)
 +        {
 +            writeNewline();
 +            writeNewline("/**");
 +            writeNewline(" * @private");
 +            writeNewline(" * @type {" + instance.name + "}");
 +            writeNewline(" */");
 +            write(ASEmitterTokens.THIS);
 +            write(ASEmitterTokens.MEMBER_ACCESS);
 +            write(instance.id + "_");
 +            writeNewline(ASEmitterTokens.SEMICOLON);
 +        }
 +    }
 +
 +    //--------------------------------------------------------------------------
 +
 +    protected void emitBindingData(String cname, IClassDefinition cdef)
 +    {
 +        BindingDatabase bd = BindingDatabase.bindingMap.get(cdef);
 +        if (bd == null)
 +            return;
 +        if (bd.getBindingInfo().isEmpty())
 +            return;
 +
 +        outputBindingInfoAsData(cname, bd);
 +    }
 +
 +    private void outputBindingInfoAsData(String cname, BindingDatabase bindingDataBase)
 +    {
 +        IASEmitter asEmitter = ((IMXMLBlockWalker) getMXMLWalker())
 +        .getASEmitter();
 +
 +        writeNewline("/**");
 +        writeNewline(" * @export");
 +        writeNewline(" */");
 +        writeNewline(formatQualifiedName(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 if (s == null || s.length() == 0)
 +            {
 +                List<IExpressionNode> getterNodes = bi.getExpressionNodesForGetter();
 +                StringBuilder sb = new StringBuilder();
 +                sb.append("function() { return ");
 +                int n = getterNodes.size();
 +                for (int i = 0; i < n; i++)
 +                {
 +                	IExpressionNode getterNode = getterNodes.get(i);
 +                	if (getterNode.getNodeID() == ASTNodeID.LiteralStringID)
 +                	{
 +                		sb.append(ASEmitterTokens.DOUBLE_QUOTE.getToken());
 +                		sb.append(asEmitter.stringifyNode(getterNode));
 +                		sb.append(ASEmitterTokens.DOUBLE_QUOTE.getToken());
 +                	}
 +                	else
 +                		sb.append(asEmitter.stringifyNode(getterNode));
 +                    if (i < n - 1)
 +                    	sb.append(ASEmitterTokens.SPACE.getToken() + ASEmitterTokens.PLUS.getToken() + ASEmitterTokens.SPACE.getToken());
 +                }
 +                sb.append("; },");
 +                writeNewline(sb.toString());
 +            }
 +            else
 +                writeNewline(ASEmitterTokens.DOUBLE_QUOTE.getToken() + s + 
 +                        ASEmitterTokens.DOUBLE_QUOTE.getToken() + ASEmitterTokens.COMMA.getToken());
 +            
 +            IExpressionNode destNode = bi.getExpressionNodeForDestination();
 +            if (destNode != null)
 +            {
 +                StringBuilder sb = new StringBuilder();
 +                sb.append(generateSetterFunction(destNode));
 +                writeNewline(sb.toString() + ASEmitterTokens.COMMA.getToken());
 +            }
 +            else
 +                writeNewline(ASEmitterTokens.NULL.getToken() + ASEmitterTokens.COMMA.getToken());
 +            
 +            s = bi.getDestinationString();
 +            if (s == null)
 +            {
 +                writeNewline(ASEmitterTokens.NULL.getToken() + ASEmitterTokens.COMMA.getToken());            	
 +            }
 +            else 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();
 +        if (watcherChains != null)
 +        {
 +            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 String generateSetterFunction(IExpressionNode destNode) {
 +        IASEmitter asEmitter = ((IMXMLBlockWalker) getMXMLWalker())
 +        	.getASEmitter();
 +		String body = asEmitter.stringifyNode(destNode);
 +        
 +		StringBuilder sb = new StringBuilder();
 +		sb.append("function (value) { ");
 +		int lastGet = body.lastIndexOf("get_");
 +		int lastDot = body.lastIndexOf(".");
 +		if (lastDot == lastGet - 1)
 +		{
 +			String object = body.substring(0, lastDot);
 +			String getter = body.substring(lastDot);
 +			String setter = getter.replace("get_", "set_");
 +			setter = setter.replace("()", "(value)");
 +			body = object + setter;
 +			sb.append(body);
 +		}
 +		else
 +		{
 +			sb.append(body);
 +			sb.append(" = value;");
 +		}
 +		sb.append(";}");
 +		return sb.toString();
 +	}
 +
 +	private void encodeWatcher(WatcherInfoBase watcherInfoBase)
 +    {
 +        IASEmitter asEmitter = ((IMXMLBlockWalker) getMXMLWalker())
 +        .getASEmitter();
 +
 +        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());
 +            IExpressionNode params[] = functionWatcherInfo.params;
 +            StringBuilder sb = new StringBuilder();
 +            sb.append("function() { return [");
 +            boolean firstone = true;
 +            for (IExpressionNode param : params)
 +            {
 +                if (firstone)
 +                    firstone = false;
 +                sb.append(ASEmitterTokens.COMMA.getToken());
 +                sb.append(asEmitter.stringifyNode(param));   
 +            }
 +            sb.append("]; },");
 +            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
 +            if (type == WatcherType.STATIC_PROPERTY)
 +            {
 +                StaticPropertyWatcherInfo pwinfo = (StaticPropertyWatcherInfo)watcherInfoBase;
 +                Name classMName = pwinfo.getContainingClass(getMXMLWalker().getProject());
 +                writeNewline(nameToString(classMName));
 +            }
 +        }
 +        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);
 +        }
 +        else if (node instanceof IdentifierNode)
 +        {
 +            s = ((IdentifierNode)node).getName();
 +        }
 +        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()
 +    {
 +        for (MXMLScriptSpecifier script : scripts)
 +        {
 +            String output = script.output();
 +
 +            if (!output.equals(""))
 +            {
 +                writeNewline(output);
 +            }
 +        }
 +    }
 +
 +    //--------------------------------------------------------------------------    
 +
 +    protected void emitEvents(String cname)
 +    {
 +        for (MXMLEventSpecifier event : events)
 +        {
 +            writeNewline("/**");
 +            writeNewline(" * @export");
 +            writeNewline(" * @param {" + formatQualifiedName(event.type) + "} event");
 +            writeNewline(" */");
 +            writeNewline(formatQualifiedName(cname)
 +                    + ".prototype." + event.eventHandler + " = function(event)");
 +            writeNewline(ASEmitterTokens.BLOCK_OPEN, true);
 +
 +            writeNewline(event.value + ASEmitterTokens.SEMICOLON.getToken(),
 +                    false);
 +
 +            write(ASEmitterTokens.BLOCK_CLOSE);
 +            writeNewline(";");
 +            writeNewline();
 +            writeNewline();
 +        }
 +    }
 +
 +    //--------------------------------------------------------------------------    
 +
 +    protected void emitPropertyGetterSetters(String cname)
 +    {
 +    	int n = 0;
 +        for (MXMLDescriptorSpecifier instance : instances)
 +        {
 +            if (!instance.id.startsWith(MXMLFlexJSEmitterTokens.ID_PREFIX
 +                    .getToken()))
 +            {
 +            	n++;
 +            }
 +        }
 +    	if (n == 0 && descriptorTree.size() == 0)
 +    		return;
 +    	
 +    	String formattedCName = formatQualifiedName(cname);
 +    	
 +    	write("Object.defineProperties(");
 +    	write(formattedCName);
 +    	writeNewline(".prototype, /** @lends {" + formattedCName + ".prototype} */ {");
 +        indentPush();
 +        int i = 0;
 +        for (MXMLDescriptorSpecifier instance : instances)
 +        {
 +            if (!instance.id.startsWith(MXMLFlexJSEmitterTokens.ID_PREFIX
 +                    .getToken()))
 +            {
 +                indentPush();
 +                writeNewline("/** @export */");
 +                writeNewline(instance.id + ": {");
 +                writeNewline("/** @this {" + formattedCName + "} */");
 +                indentPush();
 +                writeNewline("get: function() {");
 +                indentPop();
 +                writeNewline("return this." + instance.id + "_;");
 +                writeNewline("},");
 +                writeNewline("/** @this {" + formattedCName + "} */");
 +                indentPush();
 +                writeNewline("set: function(value) {");
 +                indentPush();
 +                writeNewline("if (value != this." + instance.id + "_) {");
 +                writeNewline("this." + instance.id + "_ = value;");
 +                write("this.dispatchEvent(org.apache.flex.events.ValueChangeEvent.createUpdateEvent(this, '");
 +                indentPop();
 +                writeNewline(instance.id + "', null, value));");
 +                indentPop();
 +                writeNewline("}");
 +                indentPop();
 +                writeNewline("}");
 +                if (i < n - 1 || descriptorTree.size() > 0)
 +                	writeNewline("},");
 +                else
 +                {
 +                    indentPop();
 +                    writeNewline("}");
 +                }
 +                i++;
 +            }
 +        }
 +        if (descriptorTree.size() == 0)
 +        	writeNewline("});");
 +    }
 +
 +    //--------------------------------------------------------------------------    
 +
 +    protected void emitMXMLDescriptorFuncs(String cname)
 +    {
 +        // top level is 'mxmlContent', skip it...
 +        if (descriptorTree.size() > 0)
 +        {
 +            FlexJSProject project = (FlexJSProject) getMXMLWalker().getProject();
 +            project.needLanguage = true;
 +            MXMLDescriptorSpecifier root = descriptorTree.get(0);
 +            root.isTopNode = false;
 +    
 +            indentPush();
 +            writeNewline("'MXMLDescriptor': {");
 +            writeNewline("/** @this {" + formatQualifiedName(cname) + "} */");
 +            indentPush();
 +            writeNewline("get: function() {");
 +            indentPush();
 +            writeNewline("{");
 +            writeNewline("if (this.mxmldd == undefined)");
 +            indentPush();
 +            writeNewline("{");
 +            writeNewline("/** @type {Array} */");
 +            writeNewline("var arr = org.apache.flex.utils.Language.superGetter(" + formatQualifiedName(cname) + ",this, 'MXMLDescriptor');");
 +            writeNewline("/** @type {Array} */");
 +            indentPop();
 +            indentPop();
 +            writeNewline("var data = [");
 +    
 +            writeNewline(root.output(true));
 +    
 +            indentPush();
 +            writeNewline("];");
 +            indentPush();
 +            writeNewline("");
 +            indentPush();
 +            writeNewline("if (arr)");
 +            indentPop();
 +            writeNewline("this.mxmldd = arr.concat(data);");
 +            indentPush();
 +            writeNewline("else");
 +            indentPop();
 +            indentPop();
 +            writeNewline("this.mxmldd = data;");
 +            writeNewline("}");
 +            indentPop();
 +            writeNewline("return this.mxmldd;");
 +            writeNewline("}");
 +            indentPop();
 +            writeNewline("}");
 +            indentPop();
 +            writeNewline("}");
 +        	writeNewline("});");
 +        }
 +   
 +    }
 +
 +    //--------------------------------------------------------------------------    
 +
 +    private HashMap<IMXMLEventSpecifierNode, String> eventHandlerNameMap = new HashMap<IMXMLEventSpecifierNode, String>();
 +    
 +    @Override
 +    public void emitEventSpecifier(IMXMLEventSpecifierNode node)
 +    {
 +    	if (isStateDependent(node) && !inStatesOverride)
 +    		return;
 +    	
 +        IDefinition cdef = node.getDefinition();
 +
 +        MXMLDescriptorSpecifier currentDescriptor = getCurrentDescriptor("i");
 +
 +        MXMLEventSpecifier eventSpecifier = new MXMLEventSpecifier();
 +        eventSpecifier.eventHandler = MXMLFlexJSEmitterTokens.EVENT_PREFIX
 +                .getToken() + eventCounter++;
 +        eventSpecifier.name = cdef.getBaseName();
 +        eventSpecifier.type = node.getEventParameterDefinition()
 +                .getTypeAsDisplayString();
 +
 +        eventHandlerNameMap.put(node, eventSpecifier.eventHandler);
 +        
 +        IASEmitter asEmitter = ((IMXMLBlockWalker) getMXMLWalker())
 +                .getASEmitter();
 +
 +        StringBuilder sb = null;
 +        int len = node.getChildCount();
 +        if (len > 0)
 +        {
 +            sb = new StringBuilder();
 +            for (int i = 0; i < len; i++)
 +            {
 +                sb.append(getIndent((i > 0) ? 1 : 0)
 +                        + asEmitter.stringifyNode(node.getChild(i)));
 +                if (i < len - 1)
 +                {
 +                    sb.append(ASEmitterTokens.SEMICOLON.getToken());
 +                    sb.append(ASEmitterTokens.NEW_LINE.getToken());
 +                }
 +            }
 +        }
 +        eventSpecifier.value = sb.toString();
 +
 +	    if (currentDescriptor != null)
 +	        currentDescriptor.eventSpecifiers.add(eventSpecifier);
 +	    else if (!inStatesOverride) // in theory, if no currentdescriptor must be top tag event
 +	        propertiesTree.eventSpecifiers.add(eventSpecifier);
 +        events.add(eventSpecifier);
 +    }
 +
 +    @Override
 +    public void emitInstance(IMXMLInstanceNode node)
 +    {
 +        if (isStateDependent(node) && !inStatesOverride)
 +            return;
 +        
 +        IClassDefinition cdef = node
 +                .getClassReference((ICompilerProject) getMXMLWalker()
 +                        .getProject());
 +
 +        MXMLDescriptorSpecifier currentPropertySpecifier = getCurrentDescriptor("ps");
 +
 +        String id = node.getID();
 +        if (id == null)
 +            id = node.getEffectiveID();
 +        if (id == null)
 +            id = MXMLFlexJSEmitterTokens.ID_PREFIX.getToken() + idCounter++;
 +
 +        MXMLDescriptorSpecifier currentInstance = new MXMLDescriptorSpecifier();
 +        currentInstance.isProperty = false;
 +        currentInstance.id = id;
 +        currentInstance.name = formatQualifiedName(cdef.getQualifiedName());
 +        currentInstance.parent = currentPropertySpecifier;
 +
 +        if (currentPropertySpecifier != null)
 +            currentPropertySpecifier.propertySpecifiers.add(currentInstance);
 +        else if (inMXMLContent)
 +            descriptorTree.add(currentInstance);
 +        else
 +        {
 +            currentInstance.parent = propertiesTree;
 +            propertiesTree.propertySpecifiers.add(currentInstance);
 +        }
 +
 +        instances.add(currentInstance);
 +
 +        IMXMLPropertySpecifierNode[] pnodes = node.getPropertySpecifierNodes();
 +        if (pnodes != null)
 +        {
 +            moveDown(false, currentInstance, null);
 +
 +            for (IMXMLPropertySpecifierNode pnode : pnodes)
 +            {
 +                getMXMLWalker().walk(pnode); // Property Specifier
 +            }
 +
 +            moveUp(false, true);
 +        }
 +        else if (node instanceof IMXMLStateNode)
 +        {
 +            IMXMLStateNode stateNode = (IMXMLStateNode)node;
 +            String name = stateNode.getStateName();
 +            if (name != null)
 +            {
 +                MXMLDescriptorSpecifier stateName = new MXMLDescriptorSpecifier();
 +                stateName.isProperty = true;
 +                stateName.id = id;
 +                stateName.name = "name";
 +                stateName.value = ASEmitterTokens.SINGLE_QUOTE.getToken() + name + ASEmitterTokens.SINGLE_QUOTE.getToken();
 +                stateName.parent = currentInstance;
 +                currentInstance.propertySpecifiers.add(stateName);
 +            }
 +            MXMLDescriptorSpecifier overrides = new MXMLDescriptorSpecifier();
 +            overrides.isProperty = true;
 +            overrides.hasArray = true;
 +            overrides.id = id;
 +            overrides.name = "overrides";
 +            overrides.parent = currentInstance;
 +            currentInstance.propertySpecifiers.add(overrides);
 +            moveDown(false, null, overrides);
 +
 +            IMXMLClassDefinitionNode classDefinitionNode = stateNode.getClassDefinitionNode();
 +            List<IMXMLNode> snodes = classDefinitionNode.getNodesDependentOnState(stateNode.getStateName());
 +            if (snodes != null)
 +            {
 +                for (int i=snodes.size()-1; i>=0; --i)
 +                {
 +                    IMXMLNode inode = snodes.get(i);
 +                    if (inode.getNodeID() == ASTNodeID.MXMLInstanceID)
 +                    {
 +                        emitInstanceOverride((IMXMLInstanceNode)inode);
 +                    }
 +                }
 +                // Next process the non-instance overrides dependent on this state.
 +                // Each one will generate code to push an IOverride instance.
 +                for (IMXMLNode anode : snodes)
 +                {
 +                    switch (anode.getNodeID())
 +                    {
 +                        case MXMLPropertySpecifierID:
 +                        {
 +                            emitPropertyOverride((IMXMLPropertySpecifierNode)anode);
 +                            break;
 +                        }
 +                        case MXMLStyleSpecifierID:
 +                        {
 +                            emitStyleOverride((IMXMLStyleSpecifierNode)anode);
 +                            break;
 +                        }
 +                        case MXMLEventSpecifierID:
 +                        {
 +                            emitEventOverride((IMXMLEventSpecifierNode)anode);
 +                            break;
 +                        }
 +                        default:
 +                        {
 +                            break;
 +                        }
 +                    }
 +                }
 +            }
 +            
 +            moveUp(false, false);
 +        }
 +
 +        IMXMLEventSpecifierNode[] enodes = node.getEventSpecifierNodes();
 +        if (enodes != null)
 +        {
 +            moveDown(false, currentInstance, null);
 +
 +            for (IMXMLEventSpecifierNode enode : enodes)
 +            {
 +                getMXMLWalker().walk(enode); // Event Specifier
 +            }
 +
 +            moveUp(false, true);
 +        }
 +    }
 +
 +    public void emitPropertyOverride(IMXMLPropertySpecifierNode propertyNode)
 +    {
 +        FlexProject project = (FlexProject) getMXMLWalker().getProject();
 +        Name propertyOverride = project.getPropertyOverrideClassName();
 +        emitPropertyOrStyleOverride(propertyOverride, propertyNode);
 +    }
 +    
 +    /**
 +     * Generates instructions in the current context
 +     * to create an instance of mx.states.SetStyle
 +     * with its <code>target</code>, <code>name</code>,
 +     * and <code>value</code> properties set.
 +     */
 +    void emitStyleOverride(IMXMLStyleSpecifierNode styleNode)
 +    {
 +        FlexProject project = (FlexProject) getMXMLWalker().getProject();
 +        Name styleOverride = project.getStyleOverrideClassName();
 +        emitPropertyOrStyleOverride(styleOverride, styleNode);
 +    }
 +    
 +    void emitPropertyOrStyleOverride(Name overrideName, IMXMLPropertySpecifierNode propertyOrStyleNode)
 +    {
 +        MXMLDescriptorSpecifier currentInstance = getCurrentDescriptor("ps");
 +        IASNode parentNode = propertyOrStyleNode.getParent();
 +        String id = parentNode instanceof IMXMLInstanceNode ?
 +                    ((IMXMLInstanceNode)parentNode).getEffectiveID() :
 +                    null;
 +        
 +        String name = propertyOrStyleNode.getName();        
 +        
 +        boolean valueIsDataBound = isDataBindingNode(propertyOrStyleNode.getChild(0));
 +        IMXMLInstanceNode propertyOrStyleValueNode = propertyOrStyleNode.getInstanceNode();
 +        
 +        MXMLDescriptorSpecifier setProp = new MXMLDescriptorSpecifier();
 +        setProp.isProperty = false;
 +        setProp.name = formatQualifiedName(nameToString(overrideName));
 +        setProp.parent = currentInstance;
 +        currentInstance.propertySpecifiers.add(setProp);
 +        
 +        if (id != null)
 +        {
 +	            // Set its 'target' property to the id of the object
 +	            // whose property or style this override will set.
 +	        MXMLDescriptorSpecifier target = new MXMLDescriptorSpecifier();
 +	        target.isProperty = true;
 +	        target.name = "target";
 +	        target.parent = setProp;
 +	        target.value = ASEmitterTokens.SINGLE_QUOTE.getToken() + id + ASEmitterTokens.SINGLE_QUOTE.getToken();
 +	        setProp.propertySpecifiers.add(target);
 +        }
 +        
 +            // Set its 'name' property to the name of the property or style.
 +        MXMLDescriptorSpecifier pname = new MXMLDescriptorSpecifier();
 +        pname.isProperty = true;
 +        pname.name = "name";
 +        pname.parent = setProp;
 +        pname.value = ASEmitterTokens.SINGLE_QUOTE.getToken() + name + ASEmitterTokens.SINGLE_QUOTE.getToken();
 +        setProp.propertySpecifiers.add(pname);
 +
 +        if (!valueIsDataBound)
 +        {
 +	            // Set its 'value' property to the value of the property or style.
 +	        MXMLDescriptorSpecifier value = new MXMLDescriptorSpecifier();
 +	        value.isProperty = true;
 +	        value.name = "value";
 +	        value.parent = setProp;
 +	        setProp.propertySpecifiers.add(value);
 +	        moveDown(false, null, value);
 +	        getMXMLWalker().walk(propertyOrStyleValueNode); // instance node
 +	        moveUp(false, false);
 +        }
 +        else
 +        {
 +            String overrideID = MXMLFlexJSEmitterTokens.BINDING_PREFIX.getToken() + bindingCounter++;
 +	        setProp.id = overrideID;
 +	        instances.add(setProp);
 +	        BindingDatabase bd = BindingDatabase.bindingMap.get(classDefinition);
 +	        Set<BindingInfo> bindingInfo = bd.getBindingInfo();
 +	        IMXMLDataBindingNode bindingNode = (IMXMLDataBindingNode)propertyOrStyleNode.getChild(0);
 +	        for (BindingInfo bi : bindingInfo)
 +	        {
 +	        	if (bi.node == bindingNode)
 +	        	{
 +	                bi.setDestinationString(overrideID + ".value");
 +	                break;
 +	        	}
 +	        }
 +        }
 +    }
 +        
 +    /**
 +     * Generates instructions in the current context
 +     * to create an instance of mx.states.SetEventHandler
 +     * with its <code>target</code>, <code>name</code>,
 +     * and <code>handlerFunction</code> properties set.
 +     */
 +    void emitEventOverride(IMXMLEventSpecifierNode eventNode)
 +    {
 +        inStatesOverride = true;
 +        
 +        MXMLDescriptorSpecifier currentInstance = getCurrentDescriptor("ps");
 +        FlexProject project = (FlexProject) getMXMLWalker().getProject();
 +        Name eventOverride = project.getEventOverrideClassName();
 +        
 +        IASNode parentNode = eventNode.getParent();
 +        String id = parentNode instanceof IMXMLInstanceNode ?
 +                    ((IMXMLInstanceNode)parentNode).getEffectiveID() :
 +                    "";
 +        
 +        String name = MXMLEventSpecifier.getJSEventName(eventNode.getName());
 +        
 +        String eventHandler = eventHandlerNameMap.get(eventNode);
 +        if (eventHandler == null)
 +        {
 +        	emitEventSpecifier(eventNode);
 +        	eventHandler = eventHandlerNameMap.get(eventNode);
 +        }
 +
 +        MXMLDescriptorSpecifier setEvent = new MXMLDescriptorSpecifier();
 +        setEvent.isProperty = false;
 +        setEvent.name = formatQualifiedName(nameToString(eventOverride));
 +        setEvent.parent = currentInstance;
 +        currentInstance.propertySpecifiers.add(setEvent);
 +        // Set its 'target' property to the id of the object
 +        // whose event this override will set.
 +        MXMLDescriptorSpecifier target = new MXMLDescriptorSpecifier();
 +        target.isProperty = true;
 +        target.name = "target";
 +        target.parent = setEvent;
 +        target.value = ASEmitterTokens.SINGLE_QUOTE.getToken() + id + ASEmitterTokens.SINGLE_QUOTE.getToken();
 +        setEvent.propertySpecifiers.add(target);
 +
 +        // Set its 'name' property to the name of the event.
 +        MXMLDescriptorSpecifier pname = new MXMLDescriptorSpecifier();
 +        pname.isProperty = true;
 +        pname.name = "name";
 +        pname.parent = setEvent;
 +        pname.value = ASEmitterTokens.SINGLE_QUOTE.getToken() + name + ASEmitterTokens.SINGLE_QUOTE.getToken();
 +        setEvent.propertySpecifiers.add(pname);
 +        
 +        // Set its 'handlerFunction' property to the autogenerated event handler.
 +        MXMLDescriptorSpecifier handler = new MXMLDescriptorSpecifier();
 +        handler.isProperty = true;
 +        handler.name = "handlerFunction";
 +        handler.parent = setEvent;
 +        handler.value = JSFlexJSEmitterTokens.CLOSURE_FUNCTION_NAME.getToken() + ASEmitterTokens.PAREN_OPEN.getToken() + 
 +        		ASEmitterTokens.THIS.getToken() + ASEmitterTokens.MEMBER_ACCESS.getToken() + eventHandler +
 +        		ASEmitterTokens.COMMA.getToken() + ASEmitterTokens.SPACE.getToken() + ASEmitterTokens.THIS.getToken() +
 +        		ASEmitterTokens.COMMA.getToken() + ASEmitterTokens.SPACE.getToken() + ASEmitterTokens.SINGLE_QUOTE.getToken() +
 +        			eventHandler + ASEmitterTokens.SINGLE_QUOTE.getToken() +
 +        		ASEmitterTokens.PAREN_CLOSE.getToken();
 +        setEvent.propertySpecifiers.add(handler);
 +        
 +        inStatesOverride = false;
 +    }
 +
 +    public void emitInstanceOverride(IMXMLInstanceNode instanceNode)
 +    {
 +        inStatesOverride = true;
 +        
 +        MXMLDescriptorSpecifier currentInstance = getCurrentDescriptor("ps");
 +        FlexProject project = (FlexProject) getMXMLWalker().getProject();
 +        Name instanceOverrideName = project.getInstanceOverrideClassName();
 +
 +        MXMLDescriptorSpecifier overrideInstances = getCurrentDescriptor("so");
 +        int index = overrideInstances.propertySpecifiers.size();
 +        if (nodeToIndexMap == null)
 +        	nodeToIndexMap = new HashMap<IMXMLNode, Integer>();
 +        if (nodeToIndexMap.containsKey(instanceNode))
 +        {
 +        	index = nodeToIndexMap.get(instanceNode);
 +        }
 +        else
 +        {
 +        	nodeToIndexMap.put(instanceNode, index);
 +            MXMLDescriptorSpecifier itemsDesc = new MXMLDescriptorSpecifier();
 +            itemsDesc.isProperty = true;
 +            itemsDesc.hasArray = true;
 +            itemsDesc.name = "itemsDescriptor";
 +            itemsDesc.parent = overrideInstances;
 +            overrideInstances.propertySpecifiers.add(itemsDesc);
 +            boolean oldInMXMLContent = inMXMLContent;
 +            moveDown(false, null, itemsDesc);
 +            inMXMLContent = true;
 +            getMXMLWalker().walk(instanceNode); // instance node
 +            inMXMLContent = oldInMXMLContent;
 +            moveUp(false, false);
 +        }
 +
 +        MXMLDescriptorSpecifier addItems = new MXMLDescriptorSpecifier();
 +        addItems.isProperty = false;
 +        addItems.name = formatQualifiedName(nameToString(instanceOverrideName));
 +        addItems.parent = currentInstance;
 +        currentInstance.propertySpecifiers.add(addItems);
 +        MXMLDescriptorSpecifier itemsDescIndex = new MXMLDescriptorSpecifier();
 +        itemsDescIndex.isProperty = true;
 +        itemsDescIndex.hasArray = true;
 +        itemsDescIndex.name = "itemsDescriptorIndex";
 +        itemsDescIndex.parent = addItems;
 +        itemsDescIndex.value = Integer.toString(index);
 +        addItems.propertySpecifiers.add(itemsDescIndex);
 +        
 +        //-----------------------------------------------------------------------------
 +        // Second property set: maybe set destination and propertyName
 +        
 +        // get the property specifier node for the property the instanceNode represents
 +        IMXMLPropertySpecifierNode propertySpecifier = (IMXMLPropertySpecifierNode) 
 +            instanceNode.getAncestorOfType( IMXMLPropertySpecifierNode.class);
 +    
 +        if (propertySpecifier == null)
 +        {
 +           assert false;        // I think this indicates an invalid tree...
 +        }
 +        else
 +        {
 +            // Check the parent - if it's an instance then we want to use these
 +            // nodes to get our property values from. If not, then it's the root
 +            // and we don't need to specify destination
 +            
 +            IASNode parent = propertySpecifier.getParent();
 +            if (parent instanceof IMXMLInstanceNode)
 +            {
 +               IMXMLInstanceNode parentInstance = (IMXMLInstanceNode)parent;
 +               String parentId = parentInstance.getEffectiveID();
 +               assert parentId != null;
 +               String propName = propertySpecifier.getName();
 +               
 +               MXMLDescriptorSpecifier dest = new MXMLDescriptorSpecifier();
 +               dest.isProperty = true;
 +               dest.name = "destination";
 +               dest.parent = addItems;
 +               dest.value = ASEmitterTokens.SINGLE_QUOTE.getToken() + parentId + ASEmitterTokens.SINGLE_QUOTE.getToken();
 +               addItems.propertySpecifiers.add(dest);
 +
 +               MXMLDescriptorSpecifier prop = new MXMLDescriptorSpecifier();
 +               prop.isProperty = true;
 +               prop.name = "propertyName";
 +               prop.parent = addItems;
 +               prop.value = ASEmitterTokens.SINGLE_QUOTE.getToken() + propName + ASEmitterTokens.SINGLE_QUOTE.getToken();
 +               addItems.propertySpecifiers.add(prop);
 +            }
 +        }  
 +        
 +        //---------------------------------------------------------------
 +        // Third property set: position and relativeTo
 +        String positionPropertyValue = null;
 +        String relativeToPropertyValue = null;
 +       
 +        // look to see if we have any sibling nodes that are not state dependent
 +        // that come BEFORE us
 +        IASNode instanceParent = instanceNode.getParent();
 +        IASNode prevStatelessSibling=null;
 +        for (int i=0; i< instanceParent.getChildCount(); ++i)
 +        {
 +            IASNode sib = instanceParent.getChild(i);
 +            assert sib instanceof IMXMLInstanceNode;    // surely our siblings are also instances?
 +           
 +            // stop looking for previous nodes when we find ourself
 +            if (sib == instanceNode)
 +                break;
 +
 +            if (sib instanceof IMXMLInstanceNode && !isStateDependent(sib))
 +            {
 +                prevStatelessSibling = sib;
 +            }
 +        }
 +        
 +        if (prevStatelessSibling == null) {
 +            positionPropertyValue = "first";        // TODO: these should be named constants
 +        }
 +        else {
 +            positionPropertyValue = "after";
 +            relativeToPropertyValue = ((IMXMLInstanceNode)prevStatelessSibling).getEffectiveID();
 +        }
 +       
 +        MXMLDescriptorSpecifier pos = new MXMLDescriptorSpecifier();
 +        pos.isProperty = true;
 +        pos.name = "position";
 +        pos.parent = addItems;
 +        pos.value = ASEmitterTokens.SINGLE_QUOTE.getToken() + positionPropertyValue + ASEmitterTokens.SINGLE_QUOTE.getToken();
 +        addItems.propertySpecifiers.add(pos);
 +        
 +        if (relativeToPropertyValue != null)
 +        {
 +            MXMLDescriptorSpecifier rel = new MXMLDescriptorSpecifier();
 +            rel.isProperty = true;
 +            rel.name = "relativeTo";
 +            rel.parent = addItems;
 +            rel.value = ASEmitterTokens.SINGLE_QUOTE.getToken() + relativeToPropertyValue + ASEmitterTokens.SINGLE_QUOTE.getToken();
 +            addItems.propertySpecifiers.add(rel);
 +        }
 +        
 +        inStatesOverride = false;
 +    }
 +
 +    private String nameToString(Name name)
 +    {
 +        String s = "";
 +        Namespace ns = name.getSingleQualifier();
 +        s = ns.getName() + ASEmitterTokens.MEMBER_ACCESS.getToken() + name.getBaseName();
 +        return s;
 +    }
 +    /**
 +     * Determines whether a node is state-dependent.
 +     * TODO: we should move to IMXMLNode
 +     */
 +    protected boolean isStateDependent(IASNode node)
 +    {
 +        if (node instanceof IMXMLSpecifierNode)
 +        {
 +            String suffix = ((IMXMLSpecifierNode)node).getSuffix();
 +            return suffix != null && suffix.length() > 0;
 +        }
 +        else if (isStateDependentInstance(node))
 +            return true;
 +        return false;
 +    }
 +    
 +    /**
 +     * Determines whether the geven node is an instance node, as is state dependent
 +     */
 +    protected boolean isStateDependentInstance(IASNode node)
 +    {
 +        if (node instanceof IMXMLInstanceNode)
 +        {
 +            String[] includeIn = ((IMXMLInstanceNode)node).getIncludeIn();
 +            String[] excludeFrom = ((IMXMLInstanceNode)node).getExcludeFrom();
 +            return includeIn != null || excludeFrom != null;
 +        }
 +        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;
 +        
 +        if (isStateDependent(node))
 +            return;
 +        
 +        IDefinition cdef = node.getDefinition();
 +
 +        IASNode cnode = node.getChild(0);
 +
 +        MXMLDescriptorSpecifier currentInstance = getCurrentDescriptor("i");
 +
 +        MXMLDescriptorSpecifier currentPropertySpecifier = new MXMLDescriptorSpecifier();
 +        currentPropertySpecifier.isProperty = true;
 +        currentPropertySpecifier.name = cdef.getQualifiedName();
 +        currentPropertySpecifier.parent = currentInstance;
 +
 +        boolean oldInMXMLContent = inMXMLContent;
 +        boolean reusingDescriptor = false;
 +        if (currentPropertySpecifier.name.equals("mxmlContent"))
 +        {
 +            inMXMLContent = true;
 +            ArrayList<MXMLDescriptorSpecifier> specList = 
 +            	(currentInstance == null) ? descriptorTree : currentInstance.propertySpecifiers;
 +            for (MXMLDescriptorSpecifier ds : specList)
 +            {
 +            	if (ds.name.equals("mxmlContent"))
 +            	{
 +            		currentPropertySpecifier = ds;
 +            		reusingDescriptor = true;
 +            		break;
 +            	}
 +            }
 +        }
 +        
 +        if (currentInstance != null)
 +        {
 +        	// we end up here for children of tags
 +        	if (!reusingDescriptor)
 +        		currentInstance.propertySpecifiers.add(currentPropertySpecifier);
 +        }
 +        else if (inMXMLContent)
 +        {
 +        	// we end up here for top tags?
 +        	if (!reusingDescriptor)
 +        		descriptorTree.add(currentPropertySpecifier);
 +        }
 +        else
 +        {
 +            currentPropertySpecifier.parent = propertiesTree;
 +            propertiesTree.propertySpecifiers.add(currentPropertySpecifier);
 +        }
 +
 +        boolean valueIsArray = cnode != null && cnode instanceof IMXMLArrayNode;
 +        boolean valueIsObject = cnode != null && cnode instanceof IMXMLObjectNode;
 +
 +        currentPropertySpecifier.hasArray = valueIsArray;
 +        currentPropertySpecifier.hasObject = valueIsObject;
 +
 +        moveDown(valueIsArray || valueIsObject, null, currentPropertySpecifier);
 +
 +        getMXMLWalker().walk(cnode); // Array or Instance
 +
 +        moveUp(valueIsArray || valueIsObject, false);
 +        
 +        inMXMLContent = oldInMXMLContent;
 +    }
 +
 +    @Override
 +    public void emitScript(IMXMLScriptNode node)
 +    {
 +        IASEmitter asEmitter = ((IMXMLBlockWalker) getMXMLWalker())
 +                .getASEmitter();
 +
 +        String nl = ASEmitterTokens.NEW_LINE.getToken();
 +
 +        StringBuilder sb = null;
 +        MXMLScriptSpecifier scriptSpecifier = null;
 +
 +        int len = node.getChildCount();
 +        if (len > 0)
 +        {
 +            for (int i = 0; i < len; i++)
 +            {
 +                IASNode cnode = node.getChild(i);
 +
 +                if (!(cnode instanceof IImportNode))
 +                {
 +                    sb = new StringBuilder();
 +                    scriptSpecifier = new MXMLScriptSpecifier();
 +
 +                    sb.append(asEmitter.stringifyNode(cnode));
 +
 +                    sb.append(ASEmitterTokens.SEMICOLON.getToken());
 +
 +                    if (i == len - 1)
 +                        indentPop();
 +
 +                    sb.append(nl);
 +                    sb.append(nl);
 +
 +                    scriptSpecifier.fragment = sb.toString();
 +
 +                    scripts.add(scriptSpecifier);
 +                }
 +            }
 +        }
 +    }
 +
 +    @Override
 +    public void emitStyleSpecifier(IMXMLStyleSpecifierNode node)
 +    {
 +    }
 +
 +    //--------------------------------------------------------------------------
 +
 +    @Override
 +    public void emitObject(IMXMLObjectNode node)
 +    {
 +        final int len = node.getChildCount();
 +    	if (!makingSimpleArray)
 +    	{
 +            for (int i = 0; i < len; i++)
 +            {
 +                getMXMLWalker().walk(node.getChild(i)); // props in object
 +            }    		
 +    	}
 +    	else
 +    	{
 +            MXMLDescriptorSpecifier ps = getCurrentDescriptor("ps");
 +            if (ps.value == null)
 +            	ps.value = "";
 +            ps.value += "{";	
 +            for (int i = 0; i < len; i++)
 +            {
 +                IMXMLPropertySpecifierNode propName = (IMXMLPropertySpecifierNode)node.getChild(i);
 +                ps.value += propName.getName() + ": ";	                
 +                getMXMLWalker().walk(propName.getChild(0));
 +                if (i < len - 1)
 +                    ps.value += ", ";	                                	
 +            }    		
 +            ps.value += "}";	
 +    	}
 +    }
 +    
 +    @Override
 +    public void emitArray(IMXMLArrayNode node)
 +    {
 +        moveDown(false, null, null);
 +
 +        boolean isSimple = true;
 +        final int len = node.getChildCount();
 +        for (int i = 0; i < len; i++)
 +        {
 +            final IASNode child = node.getChild(i);
 +            ASTNodeID nodeID = child.getNodeID();
 +            if (nodeID == ASTNodeID.MXMLArrayID || nodeID == ASTNodeID.MXMLInstanceID || nodeID == ASTNodeID.MXMLStateID)
 +            {
 +                isSimple = false;
 +                break;
 +            }
 +        }
 +        boolean oldMakingSimpleArray = makingSimpleArray;
 +        MXMLDescriptorSpecifier ps = getCurrentDescriptor("ps");
 +        if (isSimple)
 +        {
 +        	makingSimpleArray = true;
 +        	ps.value = ASEmitterTokens.SQUARE_OPEN.getToken();
 +        }
 +        for (int i = 0; i < len; i++)
 +        {
 +            getMXMLWalker().walk(node.getChild(i)); // Instance
 +            if (isSimple && i < len - 1)
 +            	ps.value += ASEmitterTokens.COMMA.getToken();
 +        }
 +        if (isSimple)
 +        {
 +        	ps.value += ASEmitterTokens.SQUARE_CLOSE.getToken();        	
 +        }
 +        makingSimpleArray = oldMakingSimpleArray;
 +
 +        moveUp(false, false);
 +    }
 +
 +    @Override
 +    public void emitString(IMXMLStringNode node)
 +    {
 +        getCurrentDescriptor("ps").valueNeedsQuotes = true;
 +
 +        emitAttributeValue(node);
 +    }
 +
 +    //--------------------------------------------------------------------------
 +
 +    @Override
 +    public void emitLiteral(IMXMLLiteralNode node)
 +    {
 +        MXMLDescriptorSpecifier ps = getCurrentDescriptor("ps");
 +        if (ps.value == null) // might be non-null if makingSimpleArray
 +        	ps.value = "";
 +
 +        if (ps.valueNeedsQuotes)
 +            ps.value += ASEmitterTokens.SINGLE_QUOTE.getToken();
 +
 +        String s = node.getValue().toString();
 +        if (ps.valueNeedsQuotes)
 +        {
 +            // escape all single quotes found within the string
 +            s = s.replace(ASEmitterTokens.SINGLE_QUOTE.getToken(), 
 +                    "\\" + ASEmitterTokens.SINGLE_QUOTE.getToken());
 +        }
 +        ps.value += s;
 +        
 +        if (ps.valueNeedsQuotes)
 +            ps.value += ASEmitterTokens.SINGLE_QUOTE.getToken();
 +    }
 +
 +    //--------------------------------------------------------------------------
 +
 +    @Override
 +    public void emitFactory(IMXMLFactoryNode node)
 +    {
 +        MXMLDescriptorSpecifier ps = getCurrentDescriptor("ps");
 +        ps.value = "new " + formatQualifiedName("org.apache.flex.core.ClassFactory") + "(";
 +
 +        IASNode cnode = node.getChild(0);
 +        if (cnode instanceof IMXMLClassNode)
 +        {
 +            ps.value += formatQualifiedName(((IMXMLClassNode)cnode).getValue(getMXMLWalker().getProject()).getQualifiedName());
 +        }
 +        ps.value += ")";
 +    }
 +
 +    //--------------------------------------------------------------------------
 +
 +    @Override
 +    public void emitComponent(IMXMLComponentNode node)
 +    {
 +        MXMLDescriptorSpecifier ps = getCurrentDescriptor("ps");
 +        ps.value = "new " + formatQualifiedName("org.apache.flex.core.ClassFactory") + "(";
 +
 +        ps.value += formatQualifiedName(documentDefinition.getQualifiedName()) + ".";
 +        ps.value += formatQualifiedName(node.getName());
 +        ps.value += ")";
 +        
 +        setBufferWrite(true);
 +        emitSubDocument(node);
 +        subDocuments.append(getBuilder().toString());
 +        getBuilder().setLength(0);
 +        setBufferWrite(false);
 +    }
 +
 +    @Override
 +    protected void setBufferWrite(boolean value)
 +    {
 +    	super.setBufferWrite(value);
 +        IASEmitter asEmitter = ((IMXMLBlockWalker) getMXMLWalker()).getASEmitter();
 +        ((JSFlexJSEmitter)asEmitter).setBufferWrite(value);
 +    }
 +    
 +    //--------------------------------------------------------------------------
 +    //    JS output
 +    //--------------------------------------------------------------------------
 +    
 +    private void emitHeader(IMXMLDocumentNode node)
 +    {
 +        String cname = node.getFileNode().getName();
 +        String bcname = node.getBaseClassName();
 +
 +        FlexJSProject project = (FlexJSProject) getMXMLWalker().getProject();
 +        List<File> sourcePaths = project.getSourcePath();
 +        String sourceName = node.getSourcePath();
 +        for (File sourcePath : sourcePaths)
 +        {
 +            if (sourceName.startsWith(sourcePath.getAbsolutePath())) 
 +            {
 +            	sourceName = sourceName.substring(sourcePath.getAbsolutePath().length() + 1);        	
 +            }
 +        }
 +        writeNewline("/**");
 +        writeNewline(" * Generated by Apache Flex Cross-Compiler from " + sourceName);
 +        writeNewline(" * " + cname);
 +        writeNewline(" *");
 +        writeNewline(" * @fileoverview");
 +        writeNewline(" *");
 +        writeNewline(" * @suppress {checkTypes|accessControls}");
 +        writeNewline(" */");
 +        writeNewline();
 +        
 +        ArrayList<String> writtenInstances = new ArrayList<String>();
 +        emitHeaderLine(cname, true); // provide
 +        for (String subDocumentName : subDocumentNames)
 +        {
 +            emitHeaderLine(subDocumentName, true);
 +            writtenInstances.add(formatQualifiedName(subDocumentName));
 +        }
 +        writeNewline();
 +        emitHeaderLine(bcname);
 +        writtenInstances.add(formatQualifiedName(cname)); // make sure we don't add ourselves
 +        writtenInstances.add(formatQualifiedName(bcname)); // make sure we don't add the baseclass twice
 +        allInstances.addAll(0, instances);
 +        for (MXMLDescriptorSpecifier instance : allInstances)
 +        {
 +            String name = instance.name;
 +            if (writtenInstances.indexOf(name) == -1)
 +            {
 +                emitHeaderLine(name);
 +                writtenInstances.add(name);
 +            }
 +        }
 +        ASProjectScope projectScope = (ASProjectScope) project.getScope();
 +        IDefinition cdef = node.getDefinition();
 +        ICompilationUnit cu = projectScope
 +                .getCompilationUnitForDefinition(cdef);
 +        ArrayList<String> deps = project.getRequires(cu);
 +
 +        if (interfaceList != null)
 +        {
 +        	String[] interfaces = interfaceList.split(", ");
 +        	for (String iface : interfaces)
 +        	{
 +        		deps.add(iface);
 +        		usedNames.add(iface);
 +        	}
 +        }
 +        if (deps != null)
 +        {
 +        	Collections.sort(deps);
 +            for (String imp : deps)
 +            {
 +                if (imp.indexOf(JSGoogEmitterTokens.AS3.getToken()) != -1)
 +                    continue;
 +    
 +                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

<TRUNCATED>