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/22 15:13:19 UTC

[6/6] git commit: [flex-falcon] [refs/heads/feature/maven-migration-test] - - Merged upstream changes

- Merged upstream changes


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

Branch: refs/heads/feature/maven-migration-test
Commit: 5840930016ccc94355666ae59657ae860c400742
Parents: 28f5f13 b4e4fad
Author: Christofer Dutz <ch...@codecentric.de>
Authored: Fri Apr 22 15:13:05 2016 +0200
Committer: Christofer Dutz <ch...@codecentric.de>
Committed: Fri Apr 22 15:13:05 2016 +0200

----------------------------------------------------------------------
 .../compiler/clients/ExternCConfiguration.java  |  54 +++++++++
 .../externals/reference/ClassReference.java     |  30 ++++-
 .../codegen/js/jx/PackageHeaderEmitter.java     | 119 +++++++++++++------
 .../codegen/js/node/NodeEmitterTokens.java      |  21 ++++
 .../internal/projects/FlexJSProject.java        |  61 ++++++++++
 externs/node/node-compile-config.xml            |  64 +++++++++-
 6 files changed, 312 insertions(+), 37 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/58409300/compiler-jx/src/main/java/org/apache/flex/compiler/clients/ExternCConfiguration.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/clients/ExternCConfiguration.java
index c15786a,0000000..c6e7212
mode 100644,000000..100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/clients/ExternCConfiguration.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/clients/ExternCConfiguration.java
@@@ -1,364 -1,0 +1,418 @@@
 +/*
 + *
 + *  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.clients;
 +
 +import java.io.File;
 +import java.io.IOException;
 +import java.util.ArrayList;
 +import java.util.Collection;
 +import java.util.List;
 +
 +import org.apache.flex.compiler.config.Configuration;
 +import org.apache.flex.compiler.config.ConfigurationValue;
 +import org.apache.flex.compiler.exceptions.ConfigurationException.CannotOpen;
 +import org.apache.flex.compiler.exceptions.ConfigurationException.IncorrectArgumentCount;
 +import org.apache.flex.compiler.internal.codegen.externals.pass.ReferenceCompiler.ExternalFile;
 +import org.apache.flex.compiler.internal.codegen.externals.reference.BaseReference;
 +import org.apache.flex.compiler.internal.codegen.externals.reference.ClassReference;
 +import org.apache.flex.compiler.internal.codegen.externals.reference.FieldReference;
 +import org.apache.flex.compiler.internal.codegen.externals.reference.MemberReference;
 +import org.apache.flex.compiler.internal.config.annotations.Arguments;
 +import org.apache.flex.compiler.internal.config.annotations.Config;
 +import org.apache.flex.compiler.internal.config.annotations.InfiniteArguments;
 +import org.apache.flex.compiler.internal.config.annotations.Mapping;
 +import org.apache.flex.utils.FilenameNormalization;
 +
 +public class ExternCConfiguration extends Configuration
 +{
 +    private File jsRoot;
 +
 +    private File asRoot;
 +    
 +    private File asClassRoot;
 +    private File asInterfaceRoot;
 +    private File asFunctionRoot;
 +    private File asConstantRoot;
 +    private File asTypeDefRoot;
 +    private File asDuplicatesRoot;
 +
 +    private List<ExternalFile> externals = new ArrayList<ExternalFile>();
 +    private List<ExternalFile> externalExterns = new ArrayList<ExternalFile>();
 +
++    private List<String> namedModules = new ArrayList<String>();
++
 +    private List<String> classToFunctions = new ArrayList<String>();
 +    private List<ExcludedMember> excludesClass = new ArrayList<ExcludedMember>();
 +    private List<ExcludedMember> excludesField = new ArrayList<ExcludedMember>();
 +    private List<ExcludedMember> excludes = new ArrayList<ExcludedMember>();
 +
 +    public ExternCConfiguration()
 +    {
 +    }
 +
 +    public File getAsRoot()
 +    {
 +        return asRoot;
 +    }
 +
 +    @Config
 +    @Mapping("as-root")
 +    public void setASRoot(ConfigurationValue cfgval, String filename) throws CannotOpen
 +    {
 +    	setASRoot(new File(FilenameNormalization.normalize(getOutputPath(cfgval, filename))));
 +    }
 +    
 +    public void setASRoot(File file)
 +    {
 +        this.asRoot = file;
 +
 +        asClassRoot = new File(asRoot, "classes");
 +        asInterfaceRoot = new File(asRoot, "interfaces");
 +        asFunctionRoot = new File(asRoot, "functions");
 +        asConstantRoot = new File(asRoot, "constants");
 +        asTypeDefRoot = new File(asRoot, "typedefs");
 +        asDuplicatesRoot = new File(asRoot, "duplicates");
 +    }
 +
 +    public File getAsClassRoot()
 +    {
 +        return asClassRoot;
 +    }
 +
 +    public File getAsInterfaceRoot()
 +    {
 +        return asInterfaceRoot;
 +    }
 +
 +    public File getAsFunctionRoot()
 +    {
 +        return asFunctionRoot;
 +    }
 +
 +    public File getAsConstantRoot()
 +    {
 +        return asConstantRoot;
 +    }
 +
 +    public File getAsTypeDefRoot()
 +    {
 +        return asTypeDefRoot;
 +    }
 +
 +    public File getAsDuplicatesRoot()
 +    {
 +        return asDuplicatesRoot;
 +    }
 +
 +    public Collection<ExternalFile> getExternals()
 +    {
 +        return externals;
 +    }
 +
 +    public Collection<ExternalFile> getExternalExterns()
 +    {
 +        return externalExterns;
 +    }
 +
 +    public boolean isClassToFunctions(String className)
 +    {
 +        return classToFunctions.contains(className);
 +    }
 +
 +    public void addClassToFunction(String className)
 +    {
 +        classToFunctions.add(className);
 +    }
 +
 +    public void addExternal(File file) throws IOException
 +    {
 +        if (!file.exists())
 +            throw new IOException(file.getAbsolutePath() + " does not exist.");
 +        externals.add(new ExternalFile(file));
 +    }
 +
 +    public void addExternal(String externalFile) throws IOException
 +    {
 +        addExternal(new File(FilenameNormalization.normalize(externalFile)));
 +    }
 +
 +    public void addExternalExtern(File file) throws IOException
 +    {
 +        if (!file.exists())
 +            throw new IOException(file.getAbsolutePath() + " does not exist.");
 +        externalExterns.add(new ExternalFile(file));
 +    }
 +
 +    public void addExternalExtern(String externalFile) throws IOException
 +    {
 +        addExternalExtern(new File(FilenameNormalization.normalize(externalFile)));
 +    }
 +
 +    @Config(allowMultiple = true)
 +    @Mapping("class-to-function")
 +    @Arguments(Arguments.CLASS)
 +    public void setClassToFunctions(ConfigurationValue cfgval, List<String> values) throws IncorrectArgumentCount
 +    {
 +        addClassToFunction(values.get(0));
 +    }
 +
 +    @Config(allowMultiple = true, isPath = true)
 +    @Mapping("external")
 +    @Arguments(Arguments.PATH_ELEMENT)
 +    @InfiniteArguments
 +    public void setExternal(ConfigurationValue cfgval, String[] vals) throws IOException, CannotOpen
 +    {
 +    	for (String val : vals)
 +    		addExternal(resolvePathStrict(val, cfgval));
 +    }
 +
 +    @Config(allowMultiple = true, isPath = true)
 +    @Mapping("external-externs")
 +    @Arguments(Arguments.PATH_ELEMENT)
 +    @InfiniteArguments
 +    public void setExternalExterns(ConfigurationValue cfgval, String[] vals) throws IOException, CannotOpen
 +    {
 +        for (String val : vals)
 +            addExternalExtern(resolvePathStrict(val, cfgval));
 +    }
 +    
 +    public boolean isExternalExtern(BaseReference reference)
 +    {
 +        String sourceFileName = reference.getNode().getSourceFileName();
 +        for (ExternalFile file : externalExterns)
 +        {
 +            if (sourceFileName.equals("[" + file.getName() + "]"))
 +            {
 +                return true;
 +            }
 +        }
 +        return false;
 +    }
 +    
 +    public ExcludedMember isExcludedClass(ClassReference classReference)
 +    {
 +        for (ExcludedMember memeber : excludesClass)
 +        {
 +            if (memeber.isExcluded(classReference, null))
 +                return memeber;
 +        }
 +        return null;
 +    }
 +
 +    public ExcludedMember isExcludedMember(ClassReference classReference,
 +            MemberReference memberReference)
 +    {
 +        if (memberReference instanceof FieldReference)
 +        {
 +            for (ExcludedMember memeber : excludesField)
 +            {
 +                if (memeber.isExcluded(classReference, memberReference))
 +                    return memeber;
 +            }
 +        }
 +        for (ExcludedMember memeber : excludes)
 +        {
 +            if (memeber.isExcluded(classReference, memberReference))
 +                return memeber;
 +        }
 +        return null;
 +    }
 +
 +    @Config(allowMultiple = true)
 +    @Mapping("exclude")
 +    @Arguments({"class", "name"})
 +    public void setExcludes(ConfigurationValue cfgval, List<String> values) throws IncorrectArgumentCount
 +    {
 +        final int size = values.size();
 +        if (size % 2 != 0)
 +            throw new IncorrectArgumentCount(size + 1, size, cfgval.getVar(), cfgval.getSource(), cfgval.getLine());
 +
 +        for (int nameIndex = 0; nameIndex < size - 1; nameIndex += 2)
 +        {
 +            final String className = values.get(nameIndex);
 +            final String name = values.get(nameIndex + 1);
 +        	addExclude(className, name);
 +        }
 +    }
 +    
 +    public void addExclude(String className, String name)
 +    {
 +        excludes.add(new ExcludedMember(className, name));
 +    }
 +
 +    public void addExclude(String className, String name, String description)
 +    {
 +        excludes.add(new ExcludedMember(className, name, description));
 +    }
 +
 +    @Config(allowMultiple = true)
 +    @Mapping("field-exclude")
 +    @Arguments({"class", "field"})
 +    public void setFieldExcludes(ConfigurationValue cfgval, List<String> values) throws IncorrectArgumentCount
 +    {
 +        final int size = values.size();
 +        if (size % 2 != 0)
 +            throw new IncorrectArgumentCount(size + 1, size, cfgval.getVar(), cfgval.getSource(), cfgval.getLine());
 +
 +        for (int nameIndex = 0; nameIndex < size - 1; nameIndex += 2)
 +        {
 +            final String className = values.get(nameIndex);
 +            final String fieldName = values.get(nameIndex + 1);
 +        	addFieldExclude(className, fieldName);
 +        }
 +    }
 +    
 +    public void addFieldExclude(String className, String fieldName)
 +    {
 +        excludesField.add(new ExcludedMember(className, fieldName, ""));
 +    }
 +
 +    @Config(allowMultiple = true)
 +    @Mapping("class-exclude")
 +    @Arguments("class")
 +    public void setClassExcludes(ConfigurationValue cfgval, List<String> values)
 +    {
 +    	for (String className : values)
 +    		addClassExclude(className);
 +    }
 +    public void addClassExclude(String className)
 +    {
 +        excludesClass.add(new ExcludedMember(className, null, ""));
 +    }
 +
++    @Config(allowMultiple = true)
++    @Mapping("named-module")
++    @Arguments("module")
++    @InfiniteArguments
++    public void setNamedModules(ConfigurationValue cfgval, List<String> values)
++    {
++        for (String moduleName : values)
++        {
++            addNamedModule(moduleName);
++        }
++    }
++    public void addNamedModule(String moduleName)
++    {
++        namedModules.add(moduleName);
++    }
++
++    public String isNamedModule(ClassReference classReference)
++    {
++        String basePackageName = classReference.getPackageName();
++        int packageIndex = basePackageName.indexOf(".");
++        if (packageIndex != -1)
++        {
++            basePackageName = basePackageName.substring(0, packageIndex);
++        }
++        for (String module : namedModules)
++        {
++            //convert to camel case
++            String camelCaseModule = module;
++            int moduleIndex = camelCaseModule.indexOf("-");
++            while (moduleIndex != -1 && moduleIndex < camelCaseModule.length() - 1)
++            {
++                camelCaseModule = camelCaseModule.substring(0, moduleIndex)
++                        + camelCaseModule.substring(moduleIndex + 1, moduleIndex + 2).toUpperCase()
++                        + camelCaseModule.substring(moduleIndex + 2);
++                moduleIndex = camelCaseModule.indexOf("-");
++            }
++            if(basePackageName.length() == 0)
++            {
++                if (classReference.getBaseName().equals(camelCaseModule))
++                {
++                    return module;
++                }
++                continue;
++            }
++            if(basePackageName.equals(camelCaseModule))
++            {
++                return module;
++            }
++        }
++        return null;
++    }
++
 +    public File getJsRoot()
 +    {
 +        return jsRoot;
 +    }
 +
 +    @Config
 +    @Mapping("js-root")
 +    public void setJSRoot(ConfigurationValue cfgval, String filename) throws CannotOpen
 +    {
 +        this.jsRoot = new File(filename);
 +    }
 +
 +
 +    public static class ExcludedMember
 +    {
 +        private String className;
 +        private String name;
 +        private String description;
 +
 +        public String getClassName()
 +        {
 +            return className;
 +        }
 +
 +        public String getName()
 +        {
 +            return name;
 +        }
 +
 +        public String getDescription()
 +        {
 +            return description;
 +        }
 +
 +        public ExcludedMember(String className, String name)
 +        {
 +            this.className = className;
 +            this.name = name;
 +        }
 +
 +        public ExcludedMember(String className, String name, String description)
 +        {
 +            this.className = className;
 +            this.name = name;
 +            this.description = description;
 +        }
 +
 +        public boolean isExcluded(ClassReference classReference,
 +                MemberReference memberReference)
 +        {
 +            if (memberReference == null)
 +            {
 +                return classReference.getQualifiedName().equals(className);
 +            }
 +            return classReference.getQualifiedName().equals(className)
 +                    && memberReference.getQualifiedName().equals(name);
 +        }
 +
 +        public void print(StringBuilder sb)
 +        {
 +            if (description != null)
 +                sb.append("// " + description + "\n");
 +            sb.append("//");
 +        }
 +    }
 +
 +}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/58409300/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/reference/ClassReference.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/reference/ClassReference.java
index b04fb0e,0000000..fc1df39
mode 100644,000000..100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/reference/ClassReference.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/reference/ClassReference.java
@@@ -1,890 -1,0 +1,918 @@@
 +/*
 + *
 + *  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.externals.reference;
 +
 +import java.io.File;
 +import java.util.ArrayList;
 +import java.util.Collections;
 +import java.util.HashMap;
 +import java.util.HashSet;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Set;
 +
 +import org.apache.flex.compiler.internal.codegen.externals.utils.DebugLogUtils;
 +import org.apache.flex.compiler.internal.codegen.externals.utils.JSTypeUtils;
 +
 +import com.google.javascript.rhino.JSDocInfo;
 +import com.google.javascript.rhino.JSDocInfoBuilder;
 +import com.google.javascript.rhino.JSTypeExpression;
 +import com.google.javascript.rhino.Node;
 +import com.google.javascript.rhino.jstype.JSType;
 +
 +public class ClassReference extends BaseReference
 +{
 +    private boolean isFinal;
 +    private boolean isDynamic;
++    private String moduleName;
 +    private int enumConstantCounter = 0;
 +
 +    private Set<String> imports = new HashSet<String>();
 +    private MethodReference constructor;
 +    private Map<String, FieldReference> instanceFields = new HashMap<String, FieldReference>();
 +    private Map<String, FieldReference> staticFields = new HashMap<String, FieldReference>();
 +    private Map<String, MethodReference> instanceMethods = new HashMap<String, MethodReference>();
 +    private Map<String, MethodReference> staticMethods = new HashMap<String, MethodReference>();
 +
 +    private Node nameNode;
 +
 +    private Node functionNode;
 +
 +    @SuppressWarnings("unused")
 +    private Node paramListNode;
 +
 +    private boolean isNamespace;
 +
 +    public final int getEnumConstant()
 +    {
 +        return enumConstantCounter;
 +    }
 +
 +    public final void nextEnumConstant()
 +    {
 +        enumConstantCounter++;
 +    }
 +
 +    public void setIsNamespace(boolean isNamespace)
 +    {
 +        this.isNamespace = isNamespace;
 +    }
 +
 +    public boolean isNamespace()
 +    {
 +        return isNamespace;
 +    }
 +
 +    public MethodReference getConstructor()
 +    {
 +        return constructor;
 +    }
 +
 +    public ArrayList<FieldReference> getAllFields()
 +    {
 +        ArrayList<FieldReference> allMethods = new ArrayList<FieldReference>();
 +        if (!isInterface())
 +        	allMethods.addAll(staticFields.values());
 +        allMethods.addAll(instanceFields.values());
 +        return allMethods;
 +    }
 +
 +    public ArrayList<MethodReference> getAllMethods()
 +    {
 +    	ArrayList<MethodReference> allMethods = new ArrayList<MethodReference>();
 +    	if (!isInterface())
 +    		allMethods.addAll(staticMethods.values());
 +    	allMethods.addAll(instanceMethods.values());
 +        return allMethods;
 +    }
 +
 +    public FieldReference getStaticField(String name)
 +    {
 +    	return staticFields.get(name);
 +    }
 +    
 +    public FieldReference getInstanceField(String name)
 +    {
 +        return instanceFields.get(name);
 +    }
 +
 +    public MethodReference getStaticMethod(String name)
 +    {
 +        return staticMethods.get(name);
 +    }
 +
 +    public MethodReference getInstanceMethod(String name)
 +    {
 +        return instanceMethods.get(name);
 +    }
 +
 +    public boolean isDynamic()
 +    {
 +        return isDynamic;
 +    }
 +
 +    public void setDynamic(boolean isDynamic)
 +    {
 +        this.isDynamic = isDynamic;
 +    }
 +
 +    public boolean isFinal()
 +    {
 +        return isFinal;
 +    }
 +
 +    public void setFinal(boolean isFinal)
 +    {
 +        this.isFinal = isFinal;
 +    }
 +
++    public String getModuleName()
++    {
++        return moduleName;
++    }
++
++    public void setModuleName(String moduleName)
++    {
++        this.moduleName = moduleName;
++    }
++
 +    public final boolean isInterface()
 +    {
 +        return getComment().isInterface();
 +    }
 +
 +    /**
 +     * 
 +     * @param model
 +     * @param node (FUNCTION [NAME, PARAM_LIST, BLOCK]), or (ASSIGN [FUNCTION [NAME, PARAM_LIST, BLOCK]])
 +     * @param qualifiedName
 +     */
 +    public ClassReference(ReferenceModel model, Node node, String qualifiedName)
 +    {
 +        super(model, node, qualifiedName, node.getJSDocInfo());
 +
 +        indent = "";
 +
 +        nameNode = null;
 +        functionNode = null;
 +        paramListNode = null;
 +
 +        if (comment.hasEnumParameterType())
 +        {
 +            /*
 +            var Foo = { ...
 +            
 +            VAR 35 [jsdoc_info: JSDocInfo]
 +                NAME FontFaceSetLoadStatus
 +                    OBJECTLIT
 +                        STRING_KEY LOADED
 +                            STRING loaded
 +                        STRING_KEY LOADING
 +                            STRING loading
 +                            
 +             Or..
 +             
 +             foo.bar.baz.QualifiedEnum = { ...
 +             
 +             ASSIGN 50 [jsdoc_info: JSDocInfo]
 +                GETPROP 
 +                    GETPROP
 +                        ...
 +                    STRING QualifiedEnum 
 +                OBJECTLIT 50 
 +             */
 +
 +            String overrideStringType = JSTypeUtils.toEnumTypeString(this);
 +
 +            Node objLit = null;
 +            if (node.isVar())
 +            {
 +                objLit = node.getFirstChild().getFirstChild();
 +            }
 +            else if (node.isAssign())
 +            {
 +                objLit = node.getLastChild();
 +            }
 +
 +            if (objLit != null)
 +            {
 +                for (Node stringKey : objLit.children())
 +                {
 +                    if (stringKey.isStringKey())
 +                    {
 +                        Node valueNode = stringKey.getFirstChild();
 +
 +                        JSDocInfoBuilder b = new JSDocInfoBuilder(true);
 +                        JSDocInfo fieldComment = b.build();
 +                        String fieldName = stringKey.getString();
 +                        FieldReference field = addField(stringKey, fieldName, fieldComment, true);
 +                        field.setConst(true);
 +                        field.setOverrideStringType(overrideStringType);
 +                        field.setConstantValueNode(valueNode);
 +                    }
 +                }
 +            }
 +        }
 +        else if (comment.getTypedefType() != null)
 +        {
 +            //System.out.println(node.toStringTree());
 +            /*
 +             VAR 727 [jsdoc_info: JSDocInfo] [source_file: [w3c_rtc]] [length: 21]
 +                NAME MediaConstraints 727 [source_file: [w3c_rtc]] [length: 16]
 +             */
 +        }
 +        else if (comment.isConstant())
 +        {
 +            /*
 +             VAR 882 [jsdoc_info: JSDocInfo]
 +                NAME Math 
 +                    OBJECTLIT
 +             */
 +            constructor = new NullConstructorReference(model, this, node, getBaseName(), comment);
 +        }
 +        else if (node.isFunction())
 +        {
 +            /*
 +             FUNCTION FooVarArgs 43 [jsdoc_info: JSDocInfo]
 +                NAME FooVarArgs
 +                PARAM_LIST
 +                    NAME arg1
 +                    NAME var_args
 +                BLOCK 43
 +             */
 +            nameNode = node.getChildAtIndex(0);
 +            functionNode = node;
 +            paramListNode = functionNode.getChildAtIndex(1);
 +        }
 +        else if (node.isVar())
 +        {
 +            /*
 +            VAR 67 [jsdoc_info: JSDocInfo]
 +                NAME VarAssignFooNoArgs
 +                    FUNCTION 
 +                        NAME 
 +                        PARAM_LIST
 +                        BLOCK
 +             */
 +            nameNode = node.getChildAtIndex(0);
 +            functionNode = nameNode.getChildAtIndex(0);
 +            try
 +            {
 +                paramListNode = functionNode.getChildAtIndex(1);
 +            }
 +            catch (Exception e)
 +            {
 +                // TODO Auto-generated catch block
 +                e.printStackTrace();
 +            }
 +        }
 +        else if (node.isAssign() && node.getChildAtIndex(1).isFunction())
 +        {
 +            /*
 +             ASSIGN 60 [jsdoc_info: JSDocInfo]
 +                NAME AssignFooNoArgs
 +                FUNCTION
 +                    NAME
 +                    PARAM_LIST
 +                    BLOCK
 +             */
 +            nameNode = node.getFirstChild();
 +            functionNode = node.getLastChild();
 +            // this is an anonymous function assignment, no name
 +            //functionNameNode = functionNode.getChildAtIndex(0);
 +            paramListNode = functionNode.getChildAtIndex(1);
 +        }
 +
 +        if (functionNode != null)
 +        {
 +            constructor = new MethodReference(model, this, functionNode, getBaseName(), comment, false);
 +        }
 +
++        moduleName = model.getConfiguration().isNamedModule(this);
++
 +    }
 +
 +    private static List<String> definedPackages = new ArrayList<String>();
 +    
 +    @Override
 +    public void emit(StringBuilder sb)
 +    {
 +        enumConstantCounter = 0;
 +
 +        String packageName = getPackageName();
 +
 +        if (outputJS)
 +        {
 +        	sb.append("/** @fileoverview Auto-generated Externs files\n * @externs\n */\n");
 +        	if (!packageName.isEmpty())
 +        	{
 +            	if (!definedPackages.contains(packageName))
 +	        	{
 +            		definedPackages.add(packageName);
 +	        		String[] pieces = packageName.split("\\.");
 +	        		String chain = "";
 +	        		int n = pieces.length;
 +	        		for (int i = 0; i < n; i++)
 +	        		{
 +	        			String piece = pieces[i];
 +	                	sb.append("\n");
 +	                	sb.append("\n");
 +	        			sb.append("/**\n * @const\n * @suppress {duplicate|const} */\n");
 +	        			if (chain.isEmpty())
 +	        				sb.append("var " + piece + " = {};\n\n\n");
 +	        			else
 +	        				sb.append(chain + "." + piece + " = {}\n\n\n");
 +	        			chain = chain + "." + piece;
 +	        		}
 +	        	}
 +        	}
 +        }
 +        else
 +        {
 +	        sb.append("package ");
 +	        if (!packageName.equals(""))
 +	            sb.append(packageName).append(" ");
 +	        sb.append("{\n");
 +	        sb.append("\n");
 +	
 +	        emitImports(sb);
 +        }
++
++        if (moduleName != null)
++        {
++            sb.append("[JSModule");
++            if (packageName.length() > 0 || !getBaseName().equals(moduleName))
++            {
++                sb.append("(");
++                sb.append("name=\"");
++                sb.append(moduleName);
++                sb.append("\"");
++                sb.append(")");
++            }
++            sb.append("]");
++            sb.append("\n");
++        }
 +        
 +        emitComment(sb);
 +
 +        boolean isInterface = isInterface();
 +
 +        if (isInterface)
 +        {
 +            emitInterface(sb);
 +        }
 +        else
 +        {
 +            emitClass(sb);
 +        }
 +
 +        if (!outputJS)
 +        {
 +	        sb.append("{\n");
 +	        sb.append("\n");
 +        }
 +        
 +        if (!isInterface)
 +        {
 +            emitConstructor(sb);
 +            sb.append("\n");
 +        }
 +
 +        emitFields(sb);
 +        emitMethods(sb);
 +
 +        if (!outputJS)
 +        {
 +            sb.append("}\n");
 +            sb.append("}\n"); // package        	
 +        }
 +    }
 +
 +    public boolean hasSuperField(String fieldName)
 +    {
 +        List<ClassReference> list = getSuperClasses();
 +        for (ClassReference reference : list)
 +        {
 +            if (reference.hasInstanceField(fieldName))
 +                return true;
 +        }
 +        return false;
 +    }
 +
 +    public boolean hasSuperMethod(String methodName)
 +    {
 +        List<ClassReference> list = getSuperClasses();
 +        for (ClassReference reference : list)
 +        {
 +            if (reference.hasInstanceMethod(methodName))
 +                return true;
 +        }
 +        return false;
 +    }
 +
 +    public MethodReference getSuperMethod(String methodName)
 +    {
 +        List<ClassReference> list = getSuperClasses();
 +        for (ClassReference reference : list)
 +        {
 +            if (reference.hasInstanceMethod(methodName))
 +                return reference.getInstanceMethod(methodName);
 +        }
 +
 +        list = getAllImplInterfaces(); // return all our interfaces and all superclass
 +        for (ClassReference reference : list)
 +        {
 +            if (reference.hasInstanceMethod(methodName))
 +                return reference.getInstanceMethod(methodName);
 +        }
 +
 +        return null;
 +    }
 +
 +    public List<ClassReference> getSuperClasses()
 +    {
 +        ArrayList<ClassReference> result = new ArrayList<ClassReference>();
 +        ClassReference superClass = getSuperClass();
 +        while (superClass != null)
 +        {
 +            result.add(superClass);
 +            superClass = superClass.getSuperClass();
 +        }
 +
 +        return result;
 +    }
 +
 +    public List<ClassReference> getAllImplInterfaces()
 +    {
 +        ArrayList<ClassReference> result = new ArrayList<ClassReference>();
 +        for (JSTypeExpression jsTypeExpression : getComment().getImplementedInterfaces())
 +        {
 +            String interfaceName = getModel().evaluate(jsTypeExpression).getDisplayName();
 +            ClassReference classReference = getModel().getClassReference(interfaceName);
 +            if (classReference != null)
 +                result.add(classReference);
 +        }
 +
 +        return result;
 +    }
 +
 +    public List<ClassReference> getImplementedInterfaces()
 +    {
 +        ArrayList<ClassReference> result = new ArrayList<ClassReference>();
 +        for (JSTypeExpression jsTypeExpression : getComment().getImplementedInterfaces())
 +        {
 +            String interfaceName = getModel().evaluate(jsTypeExpression).toAnnotationString();
 +            ClassReference reference = getModel().getClassReference(interfaceName);
 +            if (reference != null)
 +                result.add(reference);
 +        }
 +        return result;
 +    }
 +
 +    public List<ClassReference> getExtendedInterfaces()
 +    {
 +        ArrayList<ClassReference> result = new ArrayList<ClassReference>();
 +        for (JSTypeExpression jsTypeExpression : getComment().getExtendedInterfaces())
 +        {
 +            String interfaceName = getModel().evaluate(jsTypeExpression).toAnnotationString();
 +            ClassReference reference = getModel().getClassReference(interfaceName);
 +            if (reference != null)
 +                result.add(reference);
 +        }
 +        return result;
 +    }
 +
 +    public List<ClassReference> getInterfaces()
 +    {
 +        ArrayList<ClassReference> result = new ArrayList<ClassReference>();
 +        List<JSTypeExpression> implementedInterfaces = getComment().getImplementedInterfaces();
 +        for (JSTypeExpression jsTypeExpression : implementedInterfaces)
 +        {
 +            JSType jsType = getModel().evaluate(jsTypeExpression);
 +            String interfaceName = jsType.toAnnotationString();
 +            result.add(getModel().getClassReference(interfaceName));
 +        }
 +        return result;
 +    }
 +
 +    public List<ClassReference> getSuperInterfaces()
 +    {
 +        ArrayList<ClassReference> result = new ArrayList<ClassReference>();
 +        result.addAll(getInterfaces());
 +
 +        ClassReference superClass = getSuperClass();
 +        while (superClass != null)
 +        {
 +            result.addAll(superClass.getInterfaces());
 +            superClass = superClass.getSuperClass();
 +        }
 +
 +        return result;
 +    }
 +
 +    public boolean hasInstanceField(String fieldName)
 +    {
 +        return instanceFields.containsKey(fieldName);
 +    }
 +
 +    public boolean hasStaticField(String fieldName)
 +    {
 +        return staticFields.containsKey(fieldName);
 +    }
 +
 +    public boolean hasInstanceMethod(String fieldName)
 +    {
 +        return instanceMethods.containsKey(fieldName);
 +    }
 +
 +    public boolean hasStaticMethod(String fieldName)
 +    {
 +        return staticMethods.containsKey(fieldName);
 +    }
 +
 +    public FieldReference addField(Node node, String fieldName, JSDocInfo comment, boolean isStatic)
 +    {
 +        if (isStatic ? hasStaticField(fieldName) : hasInstanceField(fieldName))
 +        {
 +            // XXX Warning
 +            return null;
 +        }
 +
 +        /* AJH This doesn't make sense to me
 +        if (isNamespace)
 +            isStatic = false;
 +        */
 +
 +        if (comment == null)
 +        {
 +            DebugLogUtils.err("Field comment null for; " + node.getQualifiedName());
 +            //DebugLogUtils.err(node);
 +            JSDocInfoBuilder b = new JSDocInfoBuilder(true);
 +            b.recordBlockDescription("Generated doc for missing field JSDoc.");
 +            comment = b.build();
 +        }
 +
 +        FieldReference field = new FieldReference(getModel(), this, node, fieldName, comment, isStatic);
 +
 +        if (isStatic)
 +        	staticFields.put(fieldName, field);
 +        else
 +        	instanceFields.put(fieldName, field);
 +        return field;
 +    }
 +
 +    public MethodReference addMethod(Node node, String functionName, JSDocInfo comment, boolean isStatic)
 +    {
 +        /* AJH This doesn't make sense to me
 +        if (isNamespace)
 +            isStatic = false;
 +		*/
 +    	
 +        if (comment == null)
 +        {
 +            DebugLogUtils.err("Method comment null for; " + node.getQualifiedName());
 +            //DebugLogUtils.err(node);
 +            JSDocInfoBuilder b = new JSDocInfoBuilder(true);
 +            b.recordBlockDescription("Generated doc for missing method JSDoc.");
 +            comment = b.build();
 +        }
 +
 +        MethodReference method = new MethodReference(getModel(), this, node, functionName, comment, isStatic);
 +
 +        if (isStatic)
 +        {
 +            staticMethods.put(functionName, method);
 +        }
 +        else if (getQualifiedName().equals("Object") && functionName.equals("toString"))
 +        {
 +            // skipping Object.prototype.toString() allows toString(opt_radix) for Number, int and uint
 +        }
 +        else
 +        {
 +       	    instanceMethods.put(functionName, method);
 +        }
 +        return method;
 +    }
 +
 +    public boolean isMethodOverrideFromInterface(MethodReference reference)
 +    {
 +        boolean isMethodOverrideFromInterface = false;
 +
 +        if (!hasImplementations())
 +        {
 +            List<JSTypeExpression> implementedInterfaces = getComment().getImplementedInterfaces();
 +            for (JSTypeExpression jsTypeExpression : implementedInterfaces)
 +            {
 +                String interfaceName = getModel().evaluate(jsTypeExpression).getDisplayName();
 +                ClassReference classReference = getModel().getClassReference(interfaceName);
 +                if (classReference.hasSuperMethod(reference.getQualifiedName()))
 +                {
 +                    isMethodOverrideFromInterface = true;
 +                    break;
 +                }
 +            }
 +        }
 +
 +        return isMethodOverrideFromInterface;
 +    }
 +
 +    public MethodReference getMethodOverrideFromInterface(MethodReference reference)
 +    {
 +        // get all super classes, reverse and search top down
 +        List<ClassReference> superClasses = getSuperClasses();
 +        superClasses.add(0, this);
 +        Collections.reverse(superClasses);
 +
 +        // for each superclass, get all implemented interfaces
 +        for (ClassReference classReference : superClasses)
 +        {
 +            List<ClassReference> interfaces = classReference.getImplementedInterfaces();
 +            for (ClassReference interfaceReference : interfaces)
 +            {
 +                // check for the method on the interface
 +                MethodReference method = interfaceReference.getInstanceMethod(reference.getBaseName());
 +                if (method != null)
 +                    return method;
 +            }
 +        }
 +
 +        return null;
 +    }
 +
 +    public ClassReference getSuperClass()
 +    {
 +        if (getBaseName().equals("Object"))
 +            return null;
 +
 +        JSTypeExpression baseType = getComment().getBaseType();
 +        if (baseType != null)
 +        {
 +            JSType jsType = getModel().evaluate(baseType);
 +            if (jsType != null)
 +                return getModel().getClassReference(jsType.getDisplayName());
 +        }
 +        else
 +        {
 +            return getModel().getObjectReference();
 +        }
 +
 +        return null;
 +    }
 +
 +    public boolean hasSuperFieldConflict(FieldReference reference)
 +    {
 +        //        ClassReference2 superClass = getSuperClass();
 +        //        if (superClass != null)
 +        //            return superClass.getInstanceFields().containsKey(
 +        //                    reference.getName());
 +        return false;
 +    }
 +
 +    public boolean isPropertyInterfaceImplementation(String fieldName)
 +    {
 +        List<ClassReference> superInterfaces = getSuperInterfaces();
 +        for (ClassReference interfaceRef : superInterfaces)
 +        {
 +            if (interfaceRef == null)
 +            {
 +                System.err.println("isPropertyInterfaceImplementation() null");
 +                continue;
 +            }
 +            if (interfaceRef.hasInstanceField(fieldName))
 +                return true;
 +        }
 +        return false;
 +    }
 +
 +    public boolean hasLocalMethodConflict(String functionName)
 +    {
 +        return instanceMethods.containsKey(functionName) || staticMethods.containsKey(functionName);
 +    }
 +
 +    public void addImport(ClassReference reference)
 +    {
 +        if (reference != null)
 +        {
 +            imports.add(reference.getQualifiedName());
 +        }
 +    }
 +
 +    public boolean hasImport(String qualifiedName)
 +    {
 +        return imports.contains(qualifiedName);
 +    }
 +
 +    private boolean hasImplementations()
 +    {
 +        return getComment().getImplementedInterfaceCount() > 0;
 +    }
 +
 +    private void emitImports(StringBuilder sb)
 +    {
 +        if (imports.size() > 0)
 +        {
 +            for (String anImport : imports)
 +            {
 +                sb.append("import ").append(anImport).append(";\n");
 +            }
 +            sb.append("\n");
 +        }
 +    }
 +
 +    @Override
 +    protected void emitCommentBody(StringBuilder sb)
 +    {
 +    	super.emitCommentBody(sb);
 +		if (isInterface())
 +			sb.append(" * @interface\n");
 +		else
 +			sb.append(" * @constructor ");
 +        if (getComment().hasBaseType())
 +        {
 +            emitSuperClass(sb);
 +        }
 +        if (!isInterface())
 +        {
 +            emitImplements(sb);
 +        }
 +    }
 +    
 +    private void emitClass(StringBuilder sb)
 +    {
 +    	if (outputJS)
 +    		return;
-     	
++
 +        sb.append("public ");
 +        if (isDynamic)
 +        {
 +            sb.append("dynamic ");
 +        }
 +
 +        if (isFinal)
 +        {
 +            sb.append("final ");
 +        }
 +
 +        sb.append("class ");
 +        sb.append(getBaseName()).append(" ");
 +
 +        if (getComment().hasBaseType())
 +        {
 +            emitSuperClass(sb);
 +            sb.append(" ");
 +        }
 +        else
 +        {
 +            // XXX JSObject extends
 +            //sb.append("extends JSObject ");
 +        }
 +
 +        if (!isInterface())
 +        {
 +            emitImplements(sb);
 +        }
 +    }
 +
 +    private void emitInterface(StringBuilder sb)
 +    {
 +        sb.append("public interface ");
 +
 +        sb.append(getBaseName()).append(" ");
 +
 +        List<JSTypeExpression> extendedInterfaces = getComment().getExtendedInterfaces();
 +        int len = extendedInterfaces.size();
 +        if (len > 0)
 +        {
 +            sb.append("extends ");
 +            for (JSTypeExpression jsTypeExpression : extendedInterfaces)
 +            {
 +                String value = getModel().evaluate(jsTypeExpression).toAnnotationString();
 +                sb.append(value);
 +                if (--len > 0)
 +                    sb.append(", ");
 +            }
 +            sb.append(" ");
 +        }
 +    }
 +
 +    private void emitSuperClass(StringBuilder sb)
 +    {
 +    	if (outputJS)
 +    	{
 +	        sb.append(" * @extends ");
 +	        String value = JSTypeUtils.toClassTypeString(this);
 +	        sb.append(value);
 +	        sb.append("\n");
 +    	}
 +    	else
 +    	{
 +	        sb.append("extends ");
 +	        String value = JSTypeUtils.toClassTypeString(this);
 +	        sb.append(value);
 +    	}
 +    }
 +
 +    private void emitImplements(StringBuilder sb)
 +    {
 +        List<JSTypeExpression> implementedInterfaces = getComment().getImplementedInterfaces();
 +        if (implementedInterfaces.size() == 0)
 +            return;
 +
 +        if (outputJS)
 +        	sb.append(" * @implements ");
 +        else
 +        	sb.append("implements ");
 +
 +        int len = implementedInterfaces.size();
 +        for (int i = 0; i < len; i++)
 +        {
 +            String value = getModel().evaluate(implementedInterfaces.get(i)).getDisplayName();
 +
 +            sb.append(value);
 +            if (outputJS)
 +            	sb.append("\n");
 +            else
 +            {
 +	            if (i < len - 1)
 +	                sb.append(", ");
 +            }
 +        }
 +
 +        sb.append(" ");
 +    }
 +
 +    private void emitConstructor(StringBuilder sb)
 +    {
 +        if (constructor != null)
 +        {
 +            constructor.emit(sb);
 +        }
 +    }
 +
 +    private void emitFields(StringBuilder sb)
 +    {
 +        for (FieldReference field : getAllFields())
 +        {
 +            field.emit(sb);
 +            sb.append("\n");
 +            nextEnumConstant();
 +        }
 +    }
 +
 +    private void emitMethods(StringBuilder sb)
 +    {
 +        for (MethodReference method : getAllMethods())
 +        {
 +            method.emit(sb);
 +            sb.append("\n");
 +        }
 +    }
 +
 +    public File getFile(File asSourceRoot)
 +    {
 +    	File jsRoot = getModel().getConfiguration().getJsRoot();
 +    	if (jsRoot == null)
 +    	{
 +            String packagePath = toPackagePath();
 +            return new File(asSourceRoot, packagePath + File.separator + getBaseName() + ".as");    		
 +    	}
 +    	
 +    	return new File(jsRoot, getBaseName() + ".js");
 +    }
 +
 +    private String toPackagePath()
 +    {
 +        String packageName = getPackageName();
 +
 +        String[] cname = packageName.split("\\.");
 +        String sdirPath = "";
 +        if (cname.length > 0)
 +        {
 +            for (final String aCname : cname)
 +            {
 +                sdirPath += aCname + File.separator;
 +            }
 +
 +            return sdirPath;
 +        }
 +
 +        return "";
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/58409300/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/PackageHeaderEmitter.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/PackageHeaderEmitter.java
index d47c6dc,0000000..6ce6328
mode 100644,000000..100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/PackageHeaderEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/PackageHeaderEmitter.java
@@@ -1,290 -1,0 +1,339 @@@
 +/*
 + *
 + *  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.js.jx;
 +
 +import java.io.File;
 +import java.util.ArrayList;
 +import java.util.Collection;
 +import java.util.Collections;
 +import java.util.List;
 +
 +import org.apache.flex.compiler.asdoc.flexjs.ASDocComment;
 +import org.apache.flex.compiler.codegen.ISubEmitter;
 +import org.apache.flex.compiler.codegen.js.IJSEmitter;
 +import org.apache.flex.compiler.definitions.IDefinition;
 +import org.apache.flex.compiler.definitions.IFunctionDefinition;
 +import org.apache.flex.compiler.definitions.IPackageDefinition;
 +import org.apache.flex.compiler.definitions.ITypeDefinition;
 +import org.apache.flex.compiler.definitions.IVariableDefinition;
 +import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
 +import org.apache.flex.compiler.internal.codegen.js.JSSubEmitter;
 +import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitter;
 +import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitterTokens;
 +import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
++import org.apache.flex.compiler.internal.codegen.js.node.NodeEmitterTokens;
 +import org.apache.flex.compiler.internal.codegen.js.utils.EmitterUtils;
 +import org.apache.flex.compiler.internal.projects.FlexJSProject;
 +import org.apache.flex.compiler.internal.scopes.ASProjectScope;
 +import org.apache.flex.compiler.internal.scopes.PackageScope;
 +import org.apache.flex.compiler.internal.tree.as.ClassNode;
 +import org.apache.flex.compiler.projects.ICompilerProject;
 +import org.apache.flex.compiler.scopes.IASScope;
 +import org.apache.flex.compiler.targets.ITarget.TargetType;
 +import org.apache.flex.compiler.tree.as.ITypeNode;
 +import org.apache.flex.compiler.units.ICompilationUnit;
 +import org.apache.flex.compiler.utils.NativeUtils;
 +
 +public class PackageHeaderEmitter extends JSSubEmitter implements
 +        ISubEmitter<IPackageDefinition>
 +{
 +
 +    public PackageHeaderEmitter(IJSEmitter emitter)
 +    {
 +        super(emitter);
 +    }
 +
 +    @Override
 +    public void emit(IPackageDefinition definition)
 +    {
 +        IASScope containedScope = definition.getContainedScope();
 +        ITypeDefinition type = EmitterUtils.findType(containedScope
 +                .getAllLocalDefinitions());
 +        String qname = null;
 +        if (type != null)
 +        {
 +            qname = type.getQualifiedName();
 +        }
 +        if (qname == null)
 +        {
 +            IFunctionDefinition fn = EmitterUtils.findFunction(containedScope
 +                    .getAllLocalDefinitions());
 +            if(fn != null)
 +            {
 +                qname = fn.getQualifiedName();
 +            }
 +        }
 +        if (qname == null)
 +        {
 +            IVariableDefinition variable = EmitterUtils.findVariable(containedScope
 +                    .getAllLocalDefinitions());
 +            if(variable != null)
 +            {
 +                qname = variable.getQualifiedName();
 +            }
 +        }
 +        if (qname == null)
 +        {
 +            return;
 +        }
 +        
 +        FlexJSProject project = (FlexJSProject) getProject();
 +        List<File> sourcePaths = project.getSourcePath();
 +        String sourceName = definition.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(" * " + qname);
 +        writeNewline(" *");
 +        writeNewline(" * @fileoverview");
 +        writeNewline(" *");
 +        // need to suppress access controls so access to protected/private from defineProperties
 +        // doesn't generate warnings. 
 +        writeNewline(" * @suppress {checkTypes|accessControls}");
 +        writeNewline(" */");
 +        writeNewline();
 +
 +        /* goog.provide('x');\n\n */
 +        write(JSGoogEmitterTokens.GOOG_PROVIDE);
 +        write(ASEmitterTokens.PAREN_OPEN);
 +        write(ASEmitterTokens.SINGLE_QUOTE);
 +        write(getEmitter().formatQualifiedName(qname));
 +        write(ASEmitterTokens.SINGLE_QUOTE);
 +        write(ASEmitterTokens.PAREN_CLOSE);
 +        writeNewline(ASEmitterTokens.SEMICOLON);
 +        writeNewline();
 +    }
 +
 +    public void emitContents(IPackageDefinition definition)
 +    {
 +        // TODO (mschmalle) will remove this cast as more things get abstracted
 +        JSFlexJSEmitter fjs = (JSFlexJSEmitter) getEmitter();
 +        
 +        getEmitter().pushSourceMapName(definition.getNode());
 +
 +        PackageScope containedScope = (PackageScope) definition
 +                .getContainedScope();
 +
 +        ArrayList<String> writtenRequires = new ArrayList<String>();
 +
 +        Collection<IDefinition> localDefinitions = containedScope.getAllLocalDefinitions();
 +        ITypeDefinition type = EmitterUtils.findType(localDefinitions);
 +        IDefinition otherMainDefinition = null;
 +        if (type == null)
 +        {
 +        	if (localDefinitions.isEmpty())
 +        		return;
 +        	// function or variable definition
 +        	otherMainDefinition = localDefinitions.iterator().next();
 +        }
 +        else
 +        {
 +	        ITypeNode typeNode = type.getNode();
 +	        if (typeNode instanceof ClassNode)
 +	        {
 +	            ClassNode classNode = (ClassNode) typeNode;
 +	            ASDocComment asDoc = (ASDocComment) classNode.getASDocComment();
 +	            if (asDoc != null)
 +	            {
 +	                String asDocString = asDoc.commentNoEnd();
 +	                String ignoreToken = JSFlexJSEmitterTokens.IGNORE_IMPORT
 +	                        .getToken();
 +	                int ignoreIndex = asDocString.indexOf(ignoreToken);
 +	                while (ignoreIndex != -1)
 +	                {
 +	                    String ignorable = asDocString.substring(ignoreIndex
 +	                            + ignoreToken.length());
 +	                    int endIndex = ignorable.indexOf("\n");
 +	                    ignorable = ignorable.substring(0, endIndex);
 +	                    ignorable = ignorable.trim();
 +	                    // pretend we've already written the goog.requires for this
 +	                    writtenRequires.add(ignorable);
 +	                    ignoreIndex = asDocString.indexOf(ignoreToken,
 +	                            ignoreIndex + ignoreToken.length());
 +	                }
 +	            }
 +	        }
 +        }
 +        
 +        //        if (project == null)
 +        //            project = getWalker().getProject();
 +
 +        FlexJSProject flexProject = (FlexJSProject) getProject();
 +        ASProjectScope projectScope = (ASProjectScope) flexProject.getScope();
 +        ICompilationUnit cu = projectScope
 +                .getCompilationUnitForDefinition(type != null ? type : otherMainDefinition);
 +        ArrayList<String> requiresList = flexProject.getRequires(cu);
 +        ArrayList<String> interfacesList = flexProject.getInterfaces(cu);
++        ArrayList<String> externalRequiresList = flexProject.getExternalRequires(cu);
 +        
 +        String cname = (type != null) ? type.getQualifiedName() : otherMainDefinition.getQualifiedName();
 +        writtenRequires.add(cname); // make sure we don't add ourselves
 +
++        boolean emitsRequires = emitRequires(requiresList, writtenRequires, cname);
++        boolean emitsInterfaces = emitInterfaces(interfacesList, writtenRequires);
++
++        // erikdebruin: Add missing language feature support, with e.g. 'is' and 
++        //              'as' operators. We don't need to worry about requiring
++        //              this in every project: ADVANCED_OPTIMISATIONS will NOT
++        //              include any of the code if it is not used in the project.
++        boolean makingSWC = flexProject.getSWFTarget() != null && 
++        					flexProject.getSWFTarget().getTargetType() == TargetType.SWC;
++        boolean isMainCU = flexProject.mainCU != null
++                && cu.getName().equals(flexProject.mainCU.getName());
++        if (isMainCU || makingSWC)
++        {
++            ICompilerProject project = this.getProject();
++            if (project instanceof FlexJSProject)
++            {
++            	if (((FlexJSProject)project).needLanguage)
++            	{
++		            write(JSGoogEmitterTokens.GOOG_REQUIRE);
++		            write(ASEmitterTokens.PAREN_OPEN);
++		            write(ASEmitterTokens.SINGLE_QUOTE);
++		            write(JSFlexJSEmitterTokens.LANGUAGE_QNAME);
++		            write(ASEmitterTokens.SINGLE_QUOTE);
++		            write(ASEmitterTokens.PAREN_CLOSE);
++		            writeNewline(ASEmitterTokens.SEMICOLON);
++            	}
++            }
++        }
++
++        boolean emitsExternalRequires = emitExternalRequires(externalRequiresList, writtenRequires);
++
++        if (emitsRequires || emitsInterfaces || emitsExternalRequires || isMainCU)
++        {
++            writeNewline();
++        }
++
++        writeNewline();
++        writeNewline();
++    }
++    
++    private boolean emitRequires(List<String> requiresList, List<String> writtenRequires, String cname)
++    {
 +        boolean emitsRequires = false;
 +        if (requiresList != null)
 +        {
 +            Collections.sort(requiresList);
 +            for (String imp : requiresList)
 +            {
 +                if (imp.contains(JSGoogEmitterTokens.AS3.getToken()))
 +                    continue;
 +
 +                if (imp.equals(JSGoogEmitterTokens.GOOG_BIND.getToken()))
 +                    continue;
 +
 +                if (imp.equals(cname))
 +                    continue;
 +
 +                if (NativeUtils.isNative(imp))
 +                {
-                 	if (!(imp.equals("QName") || imp.equals("Namespace") || imp.equals("XML") || imp.equals("XMLList")))
-                 		continue;                	
++                    if (!(imp.equals("QName") || imp.equals("Namespace") || imp.equals("XML") || imp.equals("XMLList")))
++                        continue;
 +                }
 +
 +                if (writtenRequires.indexOf(imp) == -1)
 +                {
 +
 +                    /* goog.require('x');\n */
 +                    write(JSGoogEmitterTokens.GOOG_REQUIRE);
 +                    write(ASEmitterTokens.PAREN_OPEN);
 +                    write(ASEmitterTokens.SINGLE_QUOTE);
-                     write(fjs.formatQualifiedName(imp));
++                    write(getEmitter().formatQualifiedName(imp));
 +                    write(ASEmitterTokens.SINGLE_QUOTE);
 +                    write(ASEmitterTokens.PAREN_CLOSE);
 +                    writeNewline(ASEmitterTokens.SEMICOLON);
 +
 +                    writtenRequires.add(imp);
 +
 +                    emitsRequires = true;
 +                }
 +            }
 +        }
- 
++        return emitsRequires;
++    }
++    
++    private boolean emitInterfaces(List<String> interfacesList, List<String> writtenRequires)
++    {
 +        boolean emitsInterfaces = false;
 +        if (interfacesList != null)
 +        {
 +            Collections.sort(interfacesList);
 +            for (String imp : interfacesList)
 +            {
 +                if (writtenRequires.indexOf(imp) == -1)
 +                {
 +                    write(JSGoogEmitterTokens.GOOG_REQUIRE);
 +                    write(ASEmitterTokens.PAREN_OPEN);
 +                    write(ASEmitterTokens.SINGLE_QUOTE);
-                     write(fjs.formatQualifiedName(imp));
++                    write(getEmitter().formatQualifiedName(imp));
 +                    write(ASEmitterTokens.SINGLE_QUOTE);
 +                    write(ASEmitterTokens.PAREN_CLOSE);
 +                    writeNewline(ASEmitterTokens.SEMICOLON);
 +
 +                    emitsInterfaces = true;
 +                }
 +            }
 +        }
- 
-         // erikdebruin: Add missing language feature support, with e.g. 'is' and 
-         //              'as' operators. We don't need to worry about requiring
-         //              this in every project: ADVANCED_OPTIMISATIONS will NOT
-         //              include any of the code if it is not used in the project.
-         boolean makingSWC = flexProject.getSWFTarget() != null && 
-         					flexProject.getSWFTarget().getTargetType() == TargetType.SWC;
-         boolean isMainCU = flexProject.mainCU != null
-                 && cu.getName().equals(flexProject.mainCU.getName());
-         if (isMainCU || makingSWC)
++        return emitsInterfaces;
++    }
++    
++    private boolean emitExternalRequires(List<String> externalRequiresList, List<String> writtenRequires)
++    {
++        boolean emitsExternalRequires = false;
++        if (externalRequiresList != null)
 +        {
-             ICompilerProject project = this.getProject();
-             if (project instanceof FlexJSProject)
++            Collections.sort(externalRequiresList);
++            for (String imp : externalRequiresList)
 +            {
-             	if (((FlexJSProject)project).needLanguage)
-             	{
- 		            write(JSGoogEmitterTokens.GOOG_REQUIRE);
- 		            write(ASEmitterTokens.PAREN_OPEN);
- 		            write(ASEmitterTokens.SINGLE_QUOTE);
- 		            write(JSFlexJSEmitterTokens.LANGUAGE_QNAME);
- 		            write(ASEmitterTokens.SINGLE_QUOTE);
- 		            write(ASEmitterTokens.PAREN_CLOSE);
- 		            writeNewline(ASEmitterTokens.SEMICOLON);
-             	}
-             }
-         }
++                if (writtenRequires.indexOf(imp) == -1)
++                {
++                    /* var x = require('x');\n */
++                    write(ASEmitterTokens.VAR);
++                    write(ASEmitterTokens.SPACE);
++                    write(imp);
++                    write(ASEmitterTokens.SPACE);
++                    write(ASEmitterTokens.EQUAL);
++                    write(ASEmitterTokens.SPACE);
++                    write(NodeEmitterTokens.REQUIRE);
++                    write(ASEmitterTokens.PAREN_OPEN);
++                    write(ASEmitterTokens.SINGLE_QUOTE);
++                    write(imp);
++                    write(ASEmitterTokens.SINGLE_QUOTE);
++                    write(ASEmitterTokens.PAREN_CLOSE);
++                    writeNewline(ASEmitterTokens.SEMICOLON);
 +
-         if (emitsRequires || emitsInterfaces || isMainCU)
-         {
-             writeNewline();
-         }
++                    writtenRequires.add(imp);
 +
-         writeNewline();
-         writeNewline();
++                    emitsExternalRequires = true;
++                }
++            }
++        }
++        return emitsExternalRequires;
 +    }
 +
 +}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/58409300/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/node/NodeEmitterTokens.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/node/NodeEmitterTokens.java
index 0000000,0000000..dddcf90
new file mode 100644
--- /dev/null
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/node/NodeEmitterTokens.java
@@@ -1,0 -1,0 +1,21 @@@
++package org.apache.flex.compiler.internal.codegen.js.node;
++
++import org.apache.flex.compiler.codegen.IEmitterTokens;
++
++public enum NodeEmitterTokens implements IEmitterTokens
++{
++    REQUIRE("require"),
++    EXPORTS("exports");
++
++    private String token;
++
++    private NodeEmitterTokens(String value)
++    {
++        token = value;
++    }
++
++    public String getToken()
++    {
++        return token;
++    }
++}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/58409300/compiler-jx/src/main/java/org/apache/flex/compiler/internal/projects/FlexJSProject.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/internal/projects/FlexJSProject.java
index 67869ab,0000000..dab4843
mode 100644,000000..100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/projects/FlexJSProject.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/projects/FlexJSProject.java
@@@ -1,267 -1,0 +1,328 @@@
 +/*
 + *
 + *  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.projects;
 +
 +import java.util.ArrayList;
 +import java.util.Collection;
 +import java.util.HashMap;
++import java.util.Iterator;
 +import java.util.List;
 +import java.util.Set;
 +
 +import org.apache.flex.compiler.common.DependencyType;
 +import org.apache.flex.compiler.definitions.IDefinition;
++import org.apache.flex.compiler.definitions.metadata.IMetaTag;
++import org.apache.flex.compiler.definitions.metadata.IMetaTagAttribute;
 +import org.apache.flex.compiler.internal.codegen.mxml.flexjs.MXMLFlexJSEmitterTokens;
 +import org.apache.flex.compiler.internal.css.codegen.CSSCompilationSession;
 +import org.apache.flex.compiler.internal.definitions.InterfaceDefinition;
 +import org.apache.flex.compiler.internal.driver.js.flexjs.JSCSSCompilationSession;
 +import org.apache.flex.compiler.internal.driver.js.goog.JSGoogConfiguration;
 +import org.apache.flex.compiler.internal.scopes.ASProjectScope.DefinitionPromise;
 +import org.apache.flex.compiler.internal.targets.LinkageChecker;
 +import org.apache.flex.compiler.internal.tree.mxml.MXMLClassDefinitionNode;
 +import org.apache.flex.compiler.internal.units.SWCCompilationUnit;
 +import org.apache.flex.compiler.internal.workspaces.Workspace;
 +import org.apache.flex.compiler.targets.ITargetSettings;
 +import org.apache.flex.compiler.tree.as.IASNode;
 +import org.apache.flex.compiler.units.ICompilationUnit;
 +
 +/**
 + * @author aharui
 + * 
 + */
 +public class FlexJSProject extends FlexProject
 +{
 +
 +    /**
 +     * Constructor
 +     * 
 +     * @param workspace The {@code Workspace} containing this project.
 +     */
 +    public FlexJSProject(Workspace workspace)
 +    {
 +        super(workspace);
 +        MXMLClassDefinitionNode.GENERATED_ID_BASE = MXMLFlexJSEmitterTokens.ID_PREFIX.getToken();
 +    }
 +
 +    private HashMap<ICompilationUnit, HashMap<String, String>> interfaces = new HashMap<ICompilationUnit, HashMap<String, String>>();
 +    private HashMap<ICompilationUnit, HashMap<String, DependencyType>> requires = new HashMap<ICompilationUnit, HashMap<String, DependencyType>>();
++    private HashMap<ICompilationUnit, HashMap<String, DependencyType>> jsModules = new HashMap<ICompilationUnit, HashMap<String, DependencyType>>();
 +
 +    public JSGoogConfiguration config;
 +    
 +    public ICompilationUnit mainCU;
 +
 +    @Override
 +    public void addDependency(ICompilationUnit from, ICompilationUnit to,
 +            DependencyType dt, String qname)
 +    {
 +        // ToDo (erikdebruin): add VF2JS conditional -> only use check during full SDK compilation
 +        List<IDefinition> dp = to.getDefinitionPromises();
 +
 +        if (dp.size() == 0)
 +            return;
 +
 +        IDefinition def = dp.get(0);
 +        // IDefinition def = to.getDefinitionPromises().get(0);
 +        IDefinition actualDef = ((DefinitionPromise) def).getActualDefinition();
 +        boolean isInterface = actualDef instanceof InterfaceDefinition;
 +        if (!isInterface)
 +        {
 +            if (from != to)
 +            {
 +                HashMap<String, DependencyType> reqs;
 +                if (requires.containsKey(from))
 +                    reqs = requires.get(from);
 +                else
 +                {
 +                    reqs = new HashMap<String, DependencyType>();
 +                    requires.put(from, reqs);
 +                }
 +                if (reqs.containsKey(qname))
 +                {
 +                    // inheritance is important so remember it
 +                    if (reqs.get(qname) != DependencyType.INHERITANCE)
 +                    {
 +                        if (!isExternalLinkage(to))
 +                            reqs.put(qname, dt);
 +                    }
 +                }
 +                else if (!isExternalLinkage(to) || qname.equals("Namespace"))
 +                {
 +                	if (qname.equals("XML"))
 +                		needXML = true;
 +                    reqs.put(qname, dt);
 +                }
++                if (jsModules.containsKey(from))
++                {
++                    reqs = jsModules.get(from);
++                }
++                else
++                {
++                    reqs = new HashMap<String, DependencyType>();
++                    jsModules.put(from, reqs);
++                }
++                IMetaTag tag = getJSModuleMetadata(to);
++                if (tag != null)
++                {
++                    IMetaTagAttribute nameAttribute = tag.getAttribute("name");
++                    if (nameAttribute != null)
++                    {
++                        reqs.put(nameAttribute.getValue(), dt);
++                    }
++                    else
++                    {
++                        reqs.put(qname, dt);
++                    }
++                }
 +            }
 +        }
 +        else
 +        {
 +            if (from != to)
 +            {
 +                HashMap<String, String> interfacesArr;
 +
 +                if (interfaces.containsKey(from))
 +                {
 +                    interfacesArr = interfaces.get(from);
 +                }
 +                else
 +                {
 +                    interfacesArr = new HashMap<String, String>();
 +                    interfaces.put(from, interfacesArr);
 +                }
 +
 +                if (!interfacesArr.containsKey(qname))
 +                {
 +                	if (qname.equals("org.apache.flex.core.IValuesImpl"))
 +                		needCSS = true;
 +                    interfacesArr.put(qname, qname);
 +                }
 +            }
 +        }
 +
 +        super.addDependency(from, to, dt, qname);
 +    }
 +
 +    public boolean needLanguage;
 +    public boolean needCSS;
 +    public boolean needXML;
 +    
 +    private LinkageChecker linkageChecker;
 +    private ITargetSettings ts;
 +    
 +    // definitions that should be considered external linkage
 +    public Collection<String> unitTestExterns;
 +
++    private IMetaTag getJSModuleMetadata(ICompilationUnit cu)
++    {
++        try
++        {
++            Iterator<IDefinition> iterator = cu.getFileScopeRequest().get().getExternallyVisibleDefinitions().iterator();
++            while(iterator.hasNext())
++            {
++                IDefinition def = iterator.next();
++                if (def.hasMetaTagByName("JSModule"))
++                {
++                    return def.getMetaTagByName("JSModule");
++                }
++            }
++        }
++        catch (Exception ex)
++        {
++            //it's safe to ignore an exception here
++        }
++        return null;
++    }
++
 +    private boolean isExternalLinkage(ICompilationUnit cu)
 +    {
 +        if (linkageChecker == null)
 +        {
 +            ts = getTargetSettings();
 +            linkageChecker = new LinkageChecker(this, ts);
 +        }
 +        // in unit tests, ts may be null and LinkageChecker NPEs
 +        if (ts == null)
 +        {
 +        	if (unitTestExterns != null)
 +        	{
 +        		try {
 +        			if (!(cu instanceof SWCCompilationUnit))
 +        				if (unitTestExterns.contains(cu.getQualifiedNames().get(0)))
 +        					return true;
 +				} catch (InterruptedException e) {
 +					// TODO Auto-generated catch block
 +					e.printStackTrace();
 +				}
 +        	}
 +            return false;
 +        }
 +
 +        List<String> qnames;
 +		try {
 +			qnames = cu.getQualifiedNames();
 +	        String qname = qnames.get(0);
 +	        if (qname.equals("QName"))
 +	        	return false;
 +		} catch (InterruptedException e1) {
 +			// TODO Auto-generated catch block
 +			e1.printStackTrace();
 +		}
 +        try
 +        {
 +            return linkageChecker.isExternal(cu);
 +        }
 +        catch (InterruptedException e)
 +        {
 +            // TODO Auto-generated catch block
 +            e.printStackTrace();
 +        }
 +        return false;
 +    }
 +
 +    public ArrayList<String> getInterfaces(ICompilationUnit from)
 +    {
 +        if (interfaces.containsKey(from))
 +        {
 +            HashMap<String, String> map = interfaces.get(from);
 +            ArrayList<String> arr = new ArrayList<String>();
 +            Set<String> cus = map.keySet();
 +            for (String s : cus)
 +                arr.add(s);
 +            return arr;
 +        }
 +        return null;
 +    }
 +
 +    public ArrayList<String> getRequires(ICompilationUnit from)
 +    {
 +        if (requires.containsKey(from))
 +        {
 +            HashMap<String, DependencyType> map = requires.get(from);
 +            ArrayList<String> arr = new ArrayList<String>();
 +            Set<String> cus = map.keySet();
 +            for (String s : cus)
 +                arr.add(s);
 +            return arr;
 +        }
 +        return null;
 +    }
 +
++    public ArrayList<String> getExternalRequires(ICompilationUnit from)
++    {
++        if (jsModules.containsKey(from))
++        {
++            HashMap<String, DependencyType> map = jsModules.get(from);
++            ArrayList<String> arr = new ArrayList<String>();
++            Set<String> cus = map.keySet();
++            for (String s : cus)
++                arr.add(s);
++            return arr;
++        }
++        return null;
++    }
++
 +    JSCSSCompilationSession cssSession = new JSCSSCompilationSession();
 +
 +    @Override
 +    public CSSCompilationSession getCSSCompilationSession()
 +    {
 +        // When building SWFs, each MXML document may have its own styles
 +        // specified by fx:Style blocks.  The CSS is separately compiled and
 +        // stored in the class definition for the MXML document.  That helps
 +        // with deferred loading of classes.  The styles and thus the
 +        // classes for an MXML document are not initialized until the MXML
 +        // class is initialized.
 +        // For JS compilation, the CSS for non-standard CSS could be done the
 +        // same way, but AFAICT, standard CSS properties are best loaded by
 +        // specifying a .CSS file in the HTML.  The CSS is probably less text
 +        // than its codegen'd representation, and the browser can probably
 +        // load a .CSS file faster than us trying to run code to update the
 +        // styles.
 +        // So, for FlexJS, all style blocks from all MXML files are gathered into
 +        // one .css file and a corresponding codegen block that is output as
 +        // part of the main .JS file.
 +        return cssSession;
 +    }
 +
 +    private HashMap<IASNode, String> astCache = new HashMap<IASNode, String>();
 +
 +    @Override
 +    public void addToASTCache(IASNode ast)
 +    {
 +        astCache.put(ast, "");
 +    }
 +
 +    @Override
 +    public void setTargetSettings(ITargetSettings value)
 +    {
 +         super.setTargetSettings(value);
 +         ts = value;
 +         linkageChecker = new LinkageChecker(this, value);
 +         try {
 +			linkageChecker.initExterns();
 +		} catch (InterruptedException e) {
 +			// TODO Auto-generated catch block
 +			e.printStackTrace();
 +		}
 +    }
 +}