- Renamed the "generate" goal to "generate-extern"
- Replicated the changes to the node extern to match the develop branch
- Fixed the replace commands in js to generate an identical es3.js (Adjusted 
the build helper too)
- 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/dd503343
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/dd503343
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/dd503343

Branch: refs/heads/feature/maven-migration-test
Commit: dd5033438d69769a6e49e1f32cee6da66a9996a5
Parents: b42cb99 fb2dc7a
Author: Christofer Dutz <[email protected]>
Authored: Thu Apr 21 13:35:19 2016 +0200
Committer: Christofer Dutz <[email protected]>
Committed: Thu Apr 21 13:35:19 2016 +0200

----------------------------------------------------------------------
 .gitignore                                      |   1 +
 .../patchfiles/ReplaceRegexpOperation.java      |   3 +
 .../compiler/clients/ExternCConfiguration.java  |   7 ++
 .../externals/emit/ReferenceEmitter.java        |  20 +++
 .../codegen/externals/pass/AddMemberPass.java   |  43 ++++++-
 .../externals/pass/CollectTypesPass.java        |  10 ++
 .../externals/reference/FieldReference.java     |   9 +-
 .../externals/reference/MethodReference.java    |  33 ++++-
 .../externals/reference/ParameterReference.java |   6 +
 .../codegen/externals/utils/FunctionUtils.java  |  40 ++++--
 .../codegen/js/jx/BinaryOperatorEmitter.java    |   7 +-
 .../codegen/externals/ExternalsTestUtils.java   |  26 ----
 .../internal/caches/CSSDocumentCache.java       |  11 +-
 .../parsing/as/StreamingASTokenizer.java        |  13 ++
 compiler/src/test/java/as/ASKeywordTests.java   |  21 ++++
 externs/js/pom.xml                              |   3 +-
 externs/js/src/main/config/externc-config.xml   |  12 +-
 externs/node/pom.xml                            |  26 ++++
 .../node/src/main/config/compile-as-config.xml  | 123 ++++++++++++++++++-
 externs/node/src/main/config/externc-config.xml |  36 +++++-
 externs/node/src/main/javascript/missing.js     |  25 ++++
 externs/node/src/main/javascript/node.js        |  30 -----
 .../apache/flex/maven/flexjs/ExterncMojo.java   |   2 +-
 .../resources/META-INF/plexus/components.xml    |   2 +-
 24 files changed, 422 insertions(+), 87 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dd503343/.gitignore
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dd503343/compiler-build-tools/src/main/java/org/apache/flex/compiler/tools/patchfiles/ReplaceRegexpOperation.java
----------------------------------------------------------------------
diff --cc 
compiler-build-tools/src/main/java/org/apache/flex/compiler/tools/patchfiles/ReplaceRegexpOperation.java
index f295692,0000000..fbfcd2e
mode 100644,000000..100644
--- 
a/compiler-build-tools/src/main/java/org/apache/flex/compiler/tools/patchfiles/ReplaceRegexpOperation.java
+++ 
b/compiler-build-tools/src/main/java/org/apache/flex/compiler/tools/patchfiles/ReplaceRegexpOperation.java
@@@ -1,84 -1,0 +1,87 @@@
 +/*
 + * Copyright 2001-2005 The Apache Software Foundation.
 + *
 + * Licensed 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.tools.patchfiles;
 +
 +import org.apache.commons.io.FilenameUtils;
 +import org.apache.commons.io.IOUtils;
 +
 +import java.io.File;
 +import java.io.FileInputStream;
 +import java.io.FileOutputStream;
 +import java.io.IOException;
 +
 +/**
 + * Created by christoferdutz on 16.03.16.
 + */
 +public class ReplaceRegexpOperation extends Operation {
 +
 +    private String match;
 +    private String replace;
 +    private String flags;
 +
 +    public ReplaceRegexpOperation() {
 +    }
 +
 +    public String getMatch() {
 +        return match;
 +    }
 +
 +    public void setMatch(String match) {
 +        this.match = match;
 +    }
 +
 +    public String getReplace() {
 +        return replace;
 +    }
 +
 +    public void setReplace(String replace) {
 +        this.replace = replace;
 +    }
 +
 +    public String getFlags() {
 +        return flags;
 +    }
 +
 +    public void setFlags(String flags) {
 +        this.flags = flags;
 +    }
 +
 +    @Override
 +    public void perform(File file) throws IOException {
 +        String content = IOUtils.toString(new FileInputStream(file), "UTF-8");
 +        // TODO: Add the "flags" support
 +        String matchExpression = match;
 +        if(matchExpression.contains("§{file.base}")) {
 +            matchExpression = matchExpression.replaceAll("§\\{file.base\\}", 
FilenameUtils.getBaseName(file.getName()));
 +        }
 +        String replaceExpression = (replace == null) ? "" : replace;
 +        if(replaceExpression.contains("§{file.base}")) {
 +            replaceExpression = 
replaceExpression.replaceAll("§\\{file.base\\}", 
FilenameUtils.getBaseName(file.getName()));
 +        }
 +        if(replaceExpression.contains("_")) {
 +            replaceExpression = replaceExpression.replaceAll("_", " ");
 +        }
++        if(replaceExpression.contains("\\n")) {
++            replaceExpression = replaceExpression.replaceAll("\\\\n", "\n");
++        }
 +
 +        //content = Pattern.compile(matchExpression, 
Pattern.DOTALL).matcher(content).replaceAll(replaceExpression);
 +        content = content.replaceAll(matchExpression, replaceExpression);
 +        IOUtils.write(content, new FileOutputStream(file), "UTF-8");
 +    }
 +
 +}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dd503343/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 7eea457,0000000..c15786a
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,357 -1,0 +1,364 @@@
 +/*
 + *
 + *  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> 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, ""));
 +    }
 +
 +    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/dd503343/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/emit/ReferenceEmitter.java
----------------------------------------------------------------------
diff --cc 
compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/emit/ReferenceEmitter.java
index 957d352,0000000..c7d3c45
mode 100644,000000..100644
--- 
a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/emit/ReferenceEmitter.java
+++ 
b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/emit/ReferenceEmitter.java
@@@ -1,166 -1,0 +1,186 @@@
 +/*
 + *
 + *  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.emit;
 +
 +import java.io.File;
 +import java.io.IOException;
 +
 +import org.apache.commons.io.FileUtils;
 +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.ConstantReference;
 +import 
org.apache.flex.compiler.internal.codegen.externals.reference.FunctionReference;
 +import 
org.apache.flex.compiler.internal.codegen.externals.reference.ReferenceModel;
 +
 +public class ReferenceEmitter
 +{
 +    private ReferenceModel model;
 +
 +    public ReferenceEmitter(ReferenceModel model)
 +    {
 +        this.model = model;
 +    }
 +
 +    public void emit() throws IOException
 +    {
 +        final File asRoot = model.getConfiguration().getAsRoot();
 +        if (!asRoot.exists())
 +            asRoot.mkdirs();
 +
 +        emitClasses();
 +        emitInterfaces();
 +        emitTypedefs();
 +        emitFunctions();
 +        emitConstants();
 +    }
 +
 +    protected void emitInterfaces() throws IOException
 +    {
 +        final StringBuilder sb = new StringBuilder();
 +        for (ClassReference reference : model.getClasses())
 +        {
 +            if (model.isExcludedClass(reference) != null)
 +                continue;
 +
 +            if (!reference.isInterface())
 +                continue;
 +
 +            if (model.getConfiguration().isExternalExtern(reference))
 +                continue;
 +
 +            emit(reference, sb);
 +
 +            File sourceFile = 
reference.getFile(model.getConfiguration().getAsInterfaceRoot());
++            if(sourceFile.exists())
++            {
++                sourceFile = 
reference.getFile(model.getConfiguration().getAsDuplicatesRoot());
++            }
 +            FileUtils.write(sourceFile, sb.toString());
 +
 +            sb.setLength(0);
 +        }
 +    }
 +
 +    protected void emitClasses() throws IOException
 +    {
 +        final StringBuilder sb = new StringBuilder();
 +        for (ClassReference reference : model.getClasses())
 +        {
 +            if (model.isExcludedClass(reference) != null)
 +                continue;
 +
 +            if (reference.isInterface())
 +                continue;
 +
 +            if (model.getConfiguration().isExternalExtern(reference))
 +                continue;
 +            
 +            emit(reference, sb);
 +
 +            File sourceFile = 
reference.getFile(model.getConfiguration().getAsClassRoot());
++            if(sourceFile.exists())
++            {
++                sourceFile = 
reference.getFile(model.getConfiguration().getAsDuplicatesRoot());
++            }
 +            FileUtils.write(sourceFile, sb.toString());
 +
 +            sb.setLength(0);
 +        }
 +    }
 +
 +    protected void emitTypedefs() throws IOException
 +    {
 +        final StringBuilder sb = new StringBuilder();
 +        // TODO figure out how to resolve/emit @typedef
 +        for (ClassReference reference : model.getTypedefs())
 +        {
 +            if (model.isExcludedClass(reference) != null)
 +                continue;
 +
 +            if (model.getConfiguration().isExternalExtern(reference))
 +                continue;
 +
 +            emit(reference, sb);
 +
 +            File sourceFile = 
reference.getFile(model.getConfiguration().getAsTypeDefRoot());
++            if(sourceFile.exists())
++            {
++                sourceFile = 
reference.getFile(model.getConfiguration().getAsDuplicatesRoot());
++            }
 +            FileUtils.write(sourceFile, sb.toString());
 +
 +            sb.setLength(0);
 +        }
 +    }
 +
 +    protected void emitFunctions() throws IOException
 +    {
 +        final StringBuilder sb = new StringBuilder();
 +        for (FunctionReference reference : model.getFunctions())
 +        {
 +            if (model.getConfiguration().isExternalExtern(reference))
 +                continue;
 +            
 +            emit(reference, sb);
 +
 +            File sourceFile = 
reference.getFile(model.getConfiguration().getAsFunctionRoot());
++            if(sourceFile.exists())
++            {
++                sourceFile = 
reference.getFile(model.getConfiguration().getAsDuplicatesRoot());
++            }
 +            FileUtils.write(sourceFile, sb.toString());
 +
 +            sb.setLength(0);
 +        }
 +    }
 +
 +    protected void emitConstants() throws IOException
 +    {
 +        final StringBuilder sb = new StringBuilder();
 +        for (ConstantReference reference : model.getConstants())
 +        {
 +            if (model.getConfiguration().isExternalExtern(reference))
 +                continue;
 +            
 +            emit(reference, sb);
 +
 +            File sourceFile = 
reference.getFile(model.getConfiguration().getAsConstantRoot());
++            if(sourceFile.exists())
++            {
++                sourceFile = 
reference.getFile(model.getConfiguration().getAsDuplicatesRoot());
++            }
 +            FileUtils.write(sourceFile, sb.toString());
 +
 +            sb.setLength(0);
 +        }
 +    }
 +
 +    public void emit(BaseReference reference, StringBuilder sb)
 +    {
 +        reference.emit(sb);
 +    }
 +
 +    public String emit(BaseReference reference)
 +    {
 +        final StringBuilder sb = new StringBuilder();
 +        reference.emit(sb);
 +        return sb.toString();
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dd503343/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/pass/AddMemberPass.java
----------------------------------------------------------------------
diff --cc 
compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/pass/AddMemberPass.java
index 8379af9,0000000..9308ff0
mode 100644,000000..100644
--- 
a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/pass/AddMemberPass.java
+++ 
b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/pass/AddMemberPass.java
@@@ -1,150 -1,0 +1,191 @@@
 +/*
 + *
 + *  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.pass;
 +
 +import 
org.apache.flex.compiler.internal.codegen.externals.reference.ReferenceModel;
 +
 +import com.google.javascript.jscomp.AbstractCompiler;
 +import com.google.javascript.jscomp.NodeTraversal;
++import com.google.javascript.rhino.JSDocInfo;
 +import com.google.javascript.rhino.Node;
 +
 +public class AddMemberPass extends AbstractCompilerPass
 +{
 +
 +    public AddMemberPass(ReferenceModel model, AbstractCompiler compiler)
 +    {
 +        super(model, compiler);
 +    }
 +
 +    @Override
 +    public boolean shouldTraverse(NodeTraversal nodeTraversal, Node n,
 +            Node parent)
 +    {
 +        return n.isBlock() || n.isScript();
 +    }
 +
 +    @Override
 +    public void visit(NodeTraversal t, Node n, Node parent)
 +    {
 +        for (Node child : n.children())
 +        {
 +            //log(child);
 +
 +            if (child.isExprResult())
 +            {
 +                Node first = child.getFirstChild();
 +
 +                if (first.isVar())
 +                {
 +                    // visitVar(t, n);
 +                }
 +                else if (first.isFunction())
 +                {
 +                    // visitFunction(t, n);
 +                }
 +                else if (first.isAssign())
 +                {
 +                    if (first.getFirstChild().isGetProp()
 +                            && first.getLastChild().isFunction())
 +                    {
 +                        // instance or static method
 +                        visitMethod(t, first);
 +                    }
 +                    else
 +                    {
 +                        // DOMException.INDEX_SIZE_ERR = 1;
 +                        // The first child of the assign is the GetProp node,
 +                        // if later you need the value, either change this or 
check
 +                        // for a parent assign node when creating the 
FieldReference
 +                        // which the value would be n.getLastChild()
 +                        // XXX visitStaticField(t, n);
 +                        //System.err.println(n.toStringTree());
 +                    }
 +                }
 +                else if (first.isGetProp())
 +                {
-                     visitGetProp(t, first);
++                    JSDocInfo jsDocInfo = first.getJSDocInfo();
++                    if (jsDocInfo != null
++                        && (jsDocInfo.getParameterCount() > 0
++                            || jsDocInfo.getReturnType() != null))
++                    {
++                        // instance or static method that isn't declared as a
++                        // function, but has @param or @returns
++                        visitMethodFromJSDoc(t, first);
++                    }
++                    else
++                    {
++                        visitGetProp(t, first);
++                    }
 +                }
 +            }
 +        }
 +    }
 +
 +    // n == ASSIGN
 +    private void visitMethod(NodeTraversal t, Node n)
 +    {
 +        String qName = n.getFirstChild().getQualifiedName();
 +
 +        if (n.getFirstChild().isGetProp())
 +        {
 +            int protoType = qName.indexOf(".prototype.");
 +            if (protoType != -1)
 +            {
 +                String className = qName.substring(0, protoType);
 +                String memberName = qName.substring(protoType + 11,
 +                        qName.length());
 +                //log("Prototype:: className [" + className
 +                //        + "] memberName [" + memberName + "]");
 +                model.addMethod(n, className, memberName);
 +            }
 +            else
 +            {
 +                String className = qName.substring(0, qName.lastIndexOf("."));
 +                String memberName = qName.substring(qName.lastIndexOf(".") + 
1,
 +                        qName.length());
 +                //log("className [" + className + "] memberName ["
 +                //        + memberName + "]");
 +                model.addStaticMethod(n, className, memberName);
 +            }
 +        }
 +        else if (n.getFirstChild().isName())
 +        {
 +            err("visitMethod() non impl");
 +            log(n);
 +        }
 +    }
++    private void visitMethodFromJSDoc(NodeTraversal t, Node n)
++    {
++        String qName = n.getQualifiedName();
++
++        if (n.isGetProp())
++        {
++            int protoType = qName.indexOf(".prototype.");
++            if (protoType != -1)
++            {
++                String className = qName.substring(0, protoType);
++                String memberName = qName.substring(protoType + 11,
++                        qName.length());
++                model.addMethod(n, className, memberName);
++            }
++            else
++            {
++                String className = qName.substring(0, qName.lastIndexOf("."));
++                String memberName = qName.substring(qName.lastIndexOf(".") + 
1,
++                        qName.length());
++                model.addStaticMethod(n, className, memberName);
++            }
++        }
++        else if (n.isName())
++        {
++            err("visitMethod() non impl");
++            log(n);
++        }
++    }
 +
 +    private void visitGetProp(NodeTraversal t, Node n)
 +    {
 +        String qualifiedName = n.getQualifiedName();
 +
 +        log("visitGetProp [" + qualifiedName + "]");
 +
 +        int protoType = qualifiedName.indexOf(".prototype.");
 +        if (protoType != -1)
 +        {
 +            String className = qualifiedName.substring(0, protoType);
 +            String memberName = qualifiedName.substring(protoType + 11,
 +                    qualifiedName.length());
 +            //log("Prototype:: className [" + className
 +            //        + "] memberName [" + memberName + "]");
 +            model.addField(n, className, memberName);
 +        }
 +        else
 +        {
 +            String className = qualifiedName.substring(0,
 +                    qualifiedName.lastIndexOf("."));
 +            String memberName = qualifiedName.substring(
 +                    qualifiedName.lastIndexOf(".") + 1, 
qualifiedName.length());
 +            //log("className [" + className + "] memberName ["
 +            //        + memberName + "]");
 +            model.addStaticField(n, className, memberName);
 +        }
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dd503343/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/pass/CollectTypesPass.java
----------------------------------------------------------------------
diff --cc 
compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/pass/CollectTypesPass.java
index 8ddde76,0000000..44a9cc4
mode 100644,000000..100644
--- 
a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/pass/CollectTypesPass.java
+++ 
b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/pass/CollectTypesPass.java
@@@ -1,165 -1,0 +1,175 @@@
 +/*
 + *
 + *  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.pass;
 +
 +import 
org.apache.flex.compiler.internal.codegen.externals.reference.ReferenceModel;
 +
 +import com.google.javascript.jscomp.AbstractCompiler;
 +import com.google.javascript.jscomp.NodeTraversal;
 +import com.google.javascript.rhino.JSDocInfo;
 +import com.google.javascript.rhino.Node;
 +
 +public class CollectTypesPass extends AbstractCompilerPass
 +{
 +    public CollectTypesPass(ReferenceModel model, AbstractCompiler compiler)
 +    {
 +        super(model, compiler);
 +    }
 +
 +    @Override
 +    public boolean shouldTraverse(NodeTraversal nodeTraversal, Node n,
 +            Node parent)
 +    {
 +        return n.isBlock() || n.isScript();
 +    }
 +
 +    @Override
 +    public void visit(NodeTraversal t, Node n, Node parent)
 +    {
 +        for (Node child : n.children())
 +        {
 +            if (child.isVar())
 +            {
 +                visitVar(child);
 +            }
 +            else if (child.isFunction())
 +            {
 +                visitFunction(child);
 +            }
 +            else if (child.isExprResult())
 +            {
 +                visitExprResult(child);
 +            }
 +        }
 +    }
 +
 +    private void visitExprResult(Node child)
 +    {
 +        JSDocInfo comment = null;
 +
 +        Node container = child.getFirstChild();
 +        if (container.isAssign())
 +        {
 +            comment = container.getJSDocInfo();
 +
 +            Node left = container.getFirstChild();
 +            Node right = container.getLastChild();
 +
 +            if (left.isName() && right.isFunction())
 +            {
 +                if (comment.isConstructor() || comment.isInterface())
 +                {
 +                    // Foo = function () {};
 +                    model.addClass(container, left.getString());
 +                }
 +
 +            }
 +            else if (left.isGetProp() && right.isFunction())
 +            {
 +                boolean isConstructor = comment != null
 +                        && (comment.isConstructor() || comment.isInterface());
 +                // foo.bar.Baz = function () {};
 +                if (isConstructor)
 +                {
 +                    model.addClass(container, left.getQualifiedName());
 +                }
 +            }
 +        }
++        else
++        {
++            comment = container.getJSDocInfo();
++            boolean isConstructor = comment != null
++                    && (comment.getTypedefType() != null);
++            if (isConstructor)
++            {
++                model.addTypeDef(container, container.getQualifiedName());
++            }
++        }
 +    }
 +
 +    private void visitFunction(Node child)
 +    {
 +        JSDocInfo comment = child.getJSDocInfo();
 +
 +        boolean isConstructor = comment != null
 +                && (comment.isConstructor() || comment.isInterface());
 +
 +        if (isConstructor)
 +        {
 +            // function Goo () {};
 +            model.addClass(child, child.getFirstChild().getString());
 +        }
 +        else
 +        {
 +            model.addFunction(child, child.getFirstChild().getString());
 +        }
 +    }
 +
 +    private void visitVar(Node child)
 +    {
 +        JSDocInfo comment = child.getJSDocInfo();
 +
 +        Node first = child.getFirstChild();
 +        if (first.isName())
 +        {
 +            Node subFirst = first.getFirstChild();
 +            if (subFirst != null && subFirst.isObjectLit())
 +            {
 +                if (comment.hasEnumParameterType())
 +                {
 +
 +                }
 +                else
 +                {
 +                    
//System.out.println(first.getFirstChild().toStringTree());
 +                    //log("Encountered namespace [" + 
first.getQualifiedName() + "]");
 +                    model.addNamespace(child, first.getQualifiedName());
 +                }
 +            }
 +            else if (subFirst != null && subFirst.isFunction())
 +            {
 +                boolean isConstructor = comment != null
 +                        && (comment.isConstructor() || comment.isInterface());
 +                // foo.bar.Baz = function () {};
 +                if (isConstructor)
 +                {
 +                    model.addClass(child, first.getString());
 +                }
 +            }
 +            else
 +            {
 +                boolean isConstructor = comment != null
 +                        && (comment.getTypedefType() != null);
 +                // * @typedef
 +                // var foo;
 +                if (isConstructor)
 +                {
 +                    // model.addClass(child, first.getString());
 +                    model.addTypeDef(child, first.getString());
 +                }
 +                else if (comment != null && comment.isConstant())
 +                {
 +                    //System.out.println(child.toStringTree());
 +                    model.addConstant(child, first.getString());
 +                }
 +            }
 +        }
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dd503343/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/reference/FieldReference.java
----------------------------------------------------------------------
diff --cc 
compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/reference/FieldReference.java
index d99a66d,0000000..e01a72a
mode 100644,000000..100644
--- 
a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/reference/FieldReference.java
+++ 
b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/reference/FieldReference.java
@@@ -1,264 -1,0 +1,271 @@@
 +/*
 + *
 + *  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 org.apache.flex.compiler.clients.ExternCConfiguration.ExcludedMember;
++import 
org.apache.flex.compiler.internal.codegen.externals.utils.FunctionUtils;
 +import org.apache.flex.compiler.internal.codegen.externals.utils.JSTypeUtils;
 +
 +import com.google.javascript.rhino.JSDocInfo;
 +import com.google.javascript.rhino.JSTypeExpression;
 +import com.google.javascript.rhino.Node;
 +import com.google.javascript.rhino.jstype.JSType;
 +
 +public class FieldReference extends MemberReference
 +{
 +
 +    private boolean isStatic;
 +    private boolean isConst;
 +    private String overrideStringType;
 +    private Node constantValueNode;
 +
 +    public boolean isStatic()
 +    {
 +        return isStatic;
 +    }
 +
 +    public void setStatic(boolean isStatic)
 +    {
 +        this.isStatic = isStatic;
 +    }
 +
 +    public boolean isConst()
 +    {
 +        return isConst;
 +    }
 +
 +    public void setConst(boolean isConst)
 +    {
 +        this.isConst = isConst;
 +    }
 +
 +    public void setOverrideStringType(String overrideStringType)
 +    {
 +        this.overrideStringType = overrideStringType;
 +    }
 +
 +    public void setConstantValueNode(Node constantValueNode)
 +    {
 +        this.constantValueNode = constantValueNode;
 +    }
 +
 +    public String toTypeAnnotationString()
 +    {
 +        JSType jsType = null;
 +        if (getComment() != null && getComment().getType() != null)
 +        {
 +            jsType = getModel().evaluate(getComment().getType());
 +        }
 +        return jsType != null ? jsType.toAnnotationString() : "Object";
 +    }
 +
 +    public FieldReference(ReferenceModel model, ClassReference 
classReference, Node node, String name,
 +            JSDocInfo comment, boolean isStatic)
 +    {
 +        super(model, classReference, node, name, comment);
 +        this.isStatic = isStatic;
 +    }
 +
 +    @Override
 +    public void emit(StringBuilder sb)
 +    {
 +        // XXX HACK TEMP!
 +        if (getComment().isConstructor())
 +            return;
 +
 +        // Window has a global var Window that conflicts with the constructor.
 +        if (getQualifiedName().equals(getClassReference().getQualifiedName()))
 +            return;
 +
 +        if (getClassReference().hasSuperField(getQualifiedName()))
 +            return;
 +
 +        emitComment(sb);
 +
 +        ExcludedMember excluded = isExcluded();
 +        if (excluded != null)
 +        {
 +            excluded.print(sb);
 +            return; // XXX (mschmalle) accessors are not treated right, need 
to exclude get/set
 +        }
 +
 +        if (!getClassReference().isInterface() && !getComment().isOverride()
 +                && 
!getClassReference().isPropertyInterfaceImplementation(getBaseName()))
 +        {
 +            emitVar(sb);
 +        }
 +        else
 +        {
 +            emitAccessor(sb);
 +        }
 +    }
 +
 +    private void emitAccessor(StringBuilder sb)
 +    {
 +        boolean isInterface = getClassReference().isInterface();
 +
 +        String staticValue = (isStatic) ? "static " : "";
 +        String isPublic = isInterface ? "" : "public ";
 +        String getBody = isInterface ? "" : "{ return null; }";
 +        String setBody = isInterface ? "" : "{}";
 +
 +        String type = toTypeString();
 +        if (type.contains("|") || type.contains("?"))
 +            type = "*";
 +
 +        if (outputJS)
 +        {
 +              sb.append(getClassReference().getPackageName());
 +              sb.append(".");
 +              sb.append(getClassReference().getBaseName());
 +              sb.append(".");
 +              if (!isStatic)
 +                      sb.append("prototype.");
 +              sb.append(getBaseName());
 +              sb.append(";\n");
 +              return;
 +        }
 +        // getter
 +        sb.append(indent);
 +        sb.append(isPublic);
 +        sb.append(staticValue);
 +        sb.append("function get ");
 +        sb.append(getBaseName());
 +        sb.append("():");
 +        sb.append(type);
 +        sb.append(getBody);
 +        sb.append(";\n");
 +
 +        // setter
 +        sb.append(indent);
 +        sb.append(isPublic);
 +        sb.append(staticValue);
 +        sb.append("function set ");
 +        sb.append(getBaseName());
 +        sb.append("(value:");
 +        sb.append(type);
 +        sb.append("):void");
 +        sb.append(setBody);
 +        sb.append(";\n");
 +    }
 +
 +    private void emitVar(StringBuilder sb)
 +    {
 +        String staticValue = (isStatic) ? "static " : "";
 +        String constVarValue = (isConst) ? "const " : "var ";
 +
 +        String type = toTypeString();
 +        if (type.contains("|") || type.contains("?"))
 +            type = "*";
 +
 +        if (outputJS)
 +        {
 +              sb.append(getClassReference().getPackageName());
 +              sb.append(".");
 +              sb.append(getClassReference().getBaseName());
 +              sb.append(".");
 +              if (!isStatic)
 +                      sb.append("prototype.");
 +              sb.append(getBaseName());
 +              sb.append(";\n");
 +              return;
 +        }
 +        
 +        sb.append(indent);
 +        sb.append("public ");
 +        sb.append(staticValue);
 +        sb.append(constVarValue);
 +        sb.append(getQualifiedName());
 +        sb.append(":");
 +        sb.append(type);
 +        if (isConst)
 +        {
 +            emitConstValue(sb);
 +        }
 +        sb.append(";\n");
 +    }
 +
 +    private void emitConstValue(StringBuilder sb)
 +    {
 +        sb.append(" = ");
 +        sb.append(toConstValue(constantValueNode));
 +    }
 +
 +    private String toConstValue(Node node)
 +    {
 +        if (toTypeString().equals("Number"))
 +            return Integer.toString(getClassReference().getEnumConstant());
 +        if (node.isString())
 +            return "'" + node.getString() + "'";
 +        return "undefined /* TODO type not set */";
 +    }
 +
 +    public String toTypeString()
 +    {
 +        if (overrideStringType != null)
 +            return overrideStringType;
-         return JSTypeUtils.toFieldTypeString(this);
++        String typeString = JSTypeUtils.toFieldTypeString(this);
++        if (FunctionUtils.hasTemplate(this)
++                && FunctionUtils.containsTemplate(this, typeString))
++        {
++            return "Object";
++        }
++        return typeString;
 +    }
 +
 +    @Override
 +    protected void emitCommentBody(StringBuilder sb)
 +    {
 +        emitBlockDescription(sb);
 +        emitType(sb);
 +        emitSee(sb);
 +        emitSeeSourceFileName(sb);
 +    }
 +
 +    private void emitType(StringBuilder sb)
 +    {
 +        JSTypeExpression type = getComment().getType();
 +        if (type != null)
 +        {
 +              if (outputJS)
 +              {
 +                sb.append(indent);
 +                sb.append(" * @type ");
 +                sb.append("{");
 +                
sb.append(mapBackToJS(getModel().evaluate(type).toAnnotationString()));
 +                sb.append("} ");
 +                sb.append("\n");
 +              }
 +              else
 +              {
 +                sb.append(indent);
 +                sb.append(" * @see JSType - ");
 +                sb.append("[");
 +                sb.append(getModel().evaluate(type).toAnnotationString());
 +                sb.append("] ");
 +                String description = getComment().getReturnDescription();
 +                if (description != null)
 +                    sb.append(description);
 +                sb.append("\n");                      
 +              }
 +        }
 +    }
 +
 +}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dd503343/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/reference/MethodReference.java
----------------------------------------------------------------------
diff --cc 
compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/reference/MethodReference.java
index 96aa9f2,0000000..6cfbadf
mode 100644,000000..100644
--- 
a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/reference/MethodReference.java
+++ 
b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/reference/MethodReference.java
@@@ -1,316 -1,0 +1,347 @@@
 +/*
 + *
 + *  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.util.ArrayList;
 +import java.util.List;
 +import java.util.Set;
 +
 +import org.apache.flex.compiler.clients.ExternCConfiguration.ExcludedMember;
 +import 
org.apache.flex.compiler.internal.codegen.externals.utils.FunctionUtils;
 +
 +import com.google.common.collect.Lists;
 +import com.google.javascript.rhino.JSDocInfo;
++import com.google.javascript.rhino.JSTypeExpression;
 +import com.google.javascript.rhino.Node;
 +import com.google.javascript.rhino.jstype.JSType;
 +
 +public class MethodReference extends MemberReference
 +{
 +
 +    private boolean isStatic;
 +    private MethodReference override;
 +    private Node paramNode;
 +
 +    private List<ParameterReference> parameters;
 +
 +    private MethodReference getContext()
 +    {
 +        return override == null ? this : override;
 +    }
 +
 +    public boolean isStatic()
 +    {
 +        return isStatic;
 +    }
 +
 +    public void setStatic(boolean isStatic)
 +    {
 +        this.isStatic = isStatic;
 +    }
 +
 +    public List<ParameterReference> getParameters()
 +    {
 +        return parameters;
 +    }
 +
 +    public Set<String> getParameterNames()
 +    {
 +        return getComment().getParameterNames();
 +    }
 +
 +    public String toReturnTypeAnnotationString()
 +    {
 +        JSType jsType = getModel().evaluate(getComment().getReturnType());
 +        return jsType.toAnnotationString();
 +    }
 +
 +    public MethodReference(ReferenceModel model, ClassReference 
classReference, Node node, String name,
 +            JSDocInfo comment, boolean isStatic)
 +    {
 +        super(model, classReference, node, name, comment);
 +        this.isStatic = isStatic;
 +
 +        if (node.isFunction())
 +        {
 +            this.paramNode = node.getChildAtIndex(1);
 +        }
 +        else if (node.getLastChild().isFunction())
 +        {
 +            this.paramNode = node.getLastChild().getChildAtIndex(1);
 +        }
 +
 +        addParameterReferences();
 +    }
 +
 +    private void addParameterReferences()
 +    {
 +
 +        parameters = new ArrayList<ParameterReference>();
 +
 +        if (paramNode != null)
 +        {
 +
 +            final boolean isDocumented = comment.getParameterCount() > 0;
 +            List<String> parameterNames = null;
 +
 +            if (isDocumented)
 +            {
 +                parameterNames = 
Lists.newArrayList(comment.getParameterNames());
 +            }
 +
 +            for (Node param : paramNode.children())
 +            {
 +                ParameterReference parameterReference;
 +
 +                if (isDocumented && 
parameterNames.contains(param.getString()))
 +                {
 +                    final String qualifiedName = 
FunctionUtils.toParameterType(this, param.getString());
 +                    parameterReference = new ParameterReference(getModel(), 
param, qualifiedName);
 +                }
 +                else
 +                {
 +                    parameterReference = new ParameterReference(getModel(), 
param);
 +                }
 +
 +                parameters.add(parameterReference);
 +            }
 +        }
++        else if(comment.getParameterCount() > 0 || comment.getReturnType() != 
null)
++        {
++            for (int i = 0; i < comment.getParameterCount(); i++)
++            {
++                String parameterName = comment.getParameterNameAt(i);
++                String qualifiedName = FunctionUtils.toParameterType(this, 
parameterName);
++                ParameterReference parameterReference = new 
ParameterReference(getModel(), parameterName, qualifiedName);
++                parameters.add(parameterReference);
++            }
++        }
++        else
++        {
++            System.out.println(getQualifiedName() + " parameters not found! " 
+ " " + comment.getParameterCount());
++        }
 +    }
 +
 +    @Override
 +    public void emit(StringBuilder sb)
 +    {
 +      String className = getClassReference().getBaseName();
 +      
 +        // XXX HACK TEMP!
 +        if (getComment().isConstructor() && !getBaseName().equals(className))
 +            return;
 +
 +        if (isConstructor())
 +        {
 +            emitConstructor(sb);
 +            return;
 +        }
 +
 +        String qName = getQualifiedName();
 +        // skip overrides since they have to have the same signature as the 
super method
 +        if (getClassReference().hasSuperMethod(qName))
 +              return;
 +
 +        emitComment(sb);
 +
 +        ExcludedMember excluded = isExcluded();
 +        if (excluded != null)
 +        {
 +            excluded.print(sb);
 +        }
 +
 +        emitCode(sb);
 +
 +        override = null;
 +    }
 +
 +    public void emitCode(StringBuilder sb)
 +    {
 +        String staticValue = (isStatic) ? "static " : "";
 +        if (getClassReference().isInterface())
 +            staticValue = "";
 +
 +        String isOverride = "";
 +
 +        if (!getClassReference().isInterface())
 +        {
 +            MethodReference overrideFromInterface = 
getClassReference().getMethodOverrideFromInterface(this);
 +            if (/*isOverride() && */overrideFromInterface != null)
 +            {
 +                override = overrideFromInterface;
 +            }
 +        }
 +
 +        String qName = getQualifiedName();
 +        
 +        String publicModifier = "";
 +        String braces = "";
 +        String returns = "";
 +
 +        String returnString = transformReturnString();
 +        if (!returnString.equals("void"))
 +        {
 +              if (returnString.equals("Number"))
 +                      returns = "return 0;";
 +              else
 +                      returns = " return null;";
 +        }
 +
 +        if (!getClassReference().isInterface())
 +        {
 +            publicModifier = "public ";
 +            braces = " { " + returns + " }";
 +        }
 +        
 +        if (getClassReference().hasSuperMethod(qName))
 +        {
 +              isOverride = "override ";
 +        }
 +
 +      if (outputJS)
 +      {
 +              sb.append(getClassReference().getPackageName());
 +              sb.append(".");
 +              sb.append(getClassReference().getBaseName());
 +              sb.append(".");
 +              if (isStatic)
 +                      sb.append("prototype.");
 +              sb.append(qName);               
 +              sb.append(" = function ");              
 +            sb.append(toParameterString());
 +            sb.append(braces);
 +            sb.append("\n");
 +            return;
 +      }
 +      
 +        sb.append(indent);
 +        sb.append(publicModifier);
 +        sb.append(isOverride);
 +        sb.append(staticValue);
 +        sb.append("function ");
 +        sb.append(getQualifiedName());
 +        sb.append(toParameterString());
 +        sb.append(":");
 +        sb.append(transformReturnString());
 +        sb.append(braces);
 +        sb.append("\n");
 +    }
 +
 +    private void emitConstructor(StringBuilder sb)
 +    {
 +      if (!outputJS)
 +              emitComment(sb);
 +
 +      if (outputJS)
 +      {
 +              sb.append(getClassReference().getPackageName());
 +              sb.append(".");
 +              sb.append(getBaseName());               
 +              sb.append(" = function ");              
 +            sb.append(toParameterString());
 +            sb.append(" {}\n");
 +            return;
 +      }
 +      
 +        sb.append(indent);
 +        sb.append("public function ");
 +        sb.append(getBaseName());
 +        if (!getBaseName().equals("Object"))
 +        {
 +            sb.append(toParameterString());
 +            sb.append(" {\n");
 +            sb.append(indent);
 +            emitSuperCall(sb);
 +            sb.append(indent);
 +            sb.append("}");
 +        }
 +        else
 +        {
 +            sb.append("() {}");
 +        }
 +
 +        sb.append("\n");
 +    }
 +
 +    private void emitSuperCall(StringBuilder sb)
 +    {
 +
 +        sb.append(indent);
 +        sb.append("super(");
 +
 +        ClassReference superClass = getClassReference().getSuperClass();
 +        if (superClass != null && !superClass.getBaseName().equals("Object"))
 +        {
 +            MethodReference constructor = superClass.getConstructor();
 +            Set<String> parameterNames = constructor.getParameterNames();
 +            int len = parameterNames.size();
 +            for (int i = 0; i < len; i++)
 +            {
 +                sb.append("null");
 +                if (i < len - 1)
 +                    sb.append(", ");
 +            }
 +        }
 +
 +        sb.append(");\n");
 +    }
 +
 +    public boolean isConstructor()
 +    {
 +        return getComment().isConstructor();
 +    }
 +
 +    public String transformReturnString()
 +    {
 +        return FunctionUtils.toReturnString(getContext());
 +    }
 +
 +    private String toParameterString()
 +    {
-         return FunctionUtils.toParameterString(getContext(), 
getContext().getComment(), paramNode, outputJS);
++        if (paramNode != null)
++        {
++            return FunctionUtils.toParameterString(getContext(), 
getContext().getComment(), paramNode, outputJS);
++        }
++        StringBuilder sb = new StringBuilder();
++        sb.append("(");
++        int len = comment.getParameterCount();
++        for (int i = 0; i < len; i++)
++        {
++            String parameterName = comment.getParameterNameAt(i);
++            JSTypeExpression parameterType = comment.getParameterType(i);
++            sb.append(FunctionUtils.toParameter(getContext(), comment, 
parameterName, parameterType, outputJS));
++            if (i < len - 1)
++                sb.append(", ");
++        }
++        sb.append(")");
++        return sb.toString();
 +    }
 +
 +    public boolean isOverride()
 +    {
 +        return getComment().isOverride();
 +    }
 +
 +    @Override
 +    protected void emitCommentBody(StringBuilder sb)
 +    {
 +        emitFunctionCommentBody(sb);
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dd503343/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/reference/ParameterReference.java
----------------------------------------------------------------------
diff --cc 
compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/reference/ParameterReference.java
index 4823873,0000000..30d7c15
mode 100644,000000..100644
--- 
a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/reference/ParameterReference.java
+++ 
b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/reference/ParameterReference.java
@@@ -1,53 -1,0 +1,59 @@@
 +/*
 + *
 + *  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 com.google.javascript.rhino.Node;
 +
 +/**
 + * @author: Frederic Thomas Date: 05/07/2015 Time: 19:34
 + */
 +public class ParameterReference extends BaseReference
 +{
 +
 +    private String name;
 +
 +    public ParameterReference(final ReferenceModel model, final Node node, 
final String qualifiedName)
 +    {
 +        super(model, node, qualifiedName, null);
 +        name = node.getString();
 +    }
 +
++    public ParameterReference(final ReferenceModel model, final String name, 
final String qualifiedName)
++    {
++        super(model, null, qualifiedName, null);
++        this.name = name;
++    }
++
 +    public ParameterReference(final ReferenceModel model, final Node 
parameterNode)
 +    {
 +        this(model, parameterNode, "Object");
 +    }
 +
 +    @Override
 +    public void emit(final StringBuilder sb)
 +    {
 +        // Emitted by the Method / Function reference.
 +    }
 +
 +    public String getName()
 +    {
 +        return name;
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/dd503343/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/utils/FunctionUtils.java
----------------------------------------------------------------------
diff --cc 
compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/utils/FunctionUtils.java
index 473e42c,0000000..5a9b658
mode 100644,000000..100644
--- 
a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/utils/FunctionUtils.java
+++ 
b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/externals/utils/FunctionUtils.java
@@@ -1,232 -1,0 +1,254 @@@
 +/*
 + *
 + *  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.utils;
 +
 +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.MemberReference;
 +import 
org.apache.flex.compiler.internal.codegen.externals.reference.ReferenceModel;
 +
 +import com.google.common.base.Strings;
 +import com.google.javascript.rhino.JSDocInfo;
 +import com.google.javascript.rhino.JSTypeExpression;
 +import com.google.javascript.rhino.Node;
 +
 +public class FunctionUtils
 +{
 +    /**
 +     * Compute the type of a function or method parameter.
 +     * 
 +     * @param reference The FunctionReference or MethodReference the 
parameter belongs to
 +     * @param name The name of the parameter
 +     * @return the type of a function or method parameter
 +     */
 +    public static String toParameterType(final BaseReference reference, final 
String name)
 +    {
 +
 +        String parameterType;
 +        if (FunctionUtils.hasTemplate(reference) && 
FunctionUtils.containsTemplate(reference, name))
 +        {
 +            parameterType = "Object";
 +        }
 +        else
 +        {
 +            parameterType = JSTypeUtils.toParamTypeString(reference, name);
 +        }
 +
 +        return parameterType;
 +    }
 +
 +    public static String toReturnString(BaseReference reference)
 +    {
 +        final StringBuilder sb = new StringBuilder();
 +
 +        String returnType;
 +
 +        if (hasTemplate(reference))
 +        {
 +            returnType = JSTypeUtils.toReturnTypeString(reference);
 +            if (containsTemplate(reference, returnType))
 +              returnType = "*";
 +            else if (returnType.equals("RESULT"))
 +              returnType = "Object";
 +        }
 +        else
 +        {
 +            returnType = JSTypeUtils.toReturnTypeString(reference);
 +        }
 +
 +        sb.append(returnType);
 +
 +        return sb.toString();
 +    }
 +
 +    public static String toParameterString(BaseReference reference, JSDocInfo 
comment, Node paramNode, boolean outputJS)
 +    {
 +        final StringBuilder sb = new StringBuilder();
 +
 +        sb.append("(");
 +
 +        if (paramNode != null)
 +        {
 +            int index = 0;
 +            int len = comment.getParameterCount();
 +            if (len == 0)
 +            {
 +                // Missing JSDocInf @param tags, so instead of using the 
@param tags
 +                // we use the actual Node list from the AST
 +                len = paramNode.getChildCount();
 +                if (len > 0)
 +                {
 +                    for (Node param : paramNode.children())
 +                    {
 +                        sb.append(param.getString());
 +                        if (!outputJS)
 +                              sb.append(":Object");
 +                        if (index < len - 1)
 +                            sb.append(", ");
 +                        index++;
 +                    }
 +                }
 +            }
 +            else
 +            {
 +                for (String paramName : comment.getParameterNames())
 +                {
 +                    sb.append(toParameter(reference, comment, paramName, 
comment.getParameterType(paramName), outputJS));
 +
 +                    if (index < len - 1)
 +                        sb.append(", ");
 +
 +                    index++;
 +                }
 +            }
 +        }
 +
 +        sb.append(")");
 +
 +        return sb.toString();
 +    }
 +
 +    /**
 +     * Check we can import the given type into the given package.
 +     *
 +     * @param model The containing reference model
 +     * @param node The containing node
 +     * @param typeName The type we want check
 +     * @param packageName The current package
 +     * @return true if we can import the given type into the given package
 +     */
 +    public static boolean canBeImported(final ReferenceModel model, final 
Node node, final String typeName,
 +            final String packageName)
 +    {
 +        boolean canImport = false;
 +
 +        if (model != null && node != null && !Strings.isNullOrEmpty(typeName))
 +        {
 +            final ClassReference reference = new ClassReference(null, node, 
typeName);
 +
 +            final int lastDotPosition = typeName.lastIndexOf(".");
 +
 +            // Can import when the type to import does not belong to the 
current package.
 +            canImport = lastDotPosition > -1 && !typeName.substring(0, 
lastDotPosition).equals(packageName);
 +
 +            // And is not excluded.
 +            canImport &= model.isExcludedClass(reference) == null;
 +        }
 +
 +        return canImport;
 +    }
 +
-     private static String toParameter(BaseReference reference, JSDocInfo 
comment, String paramName,
++    public static String toParameter(BaseReference reference, JSDocInfo 
comment, String paramName,
 +            JSTypeExpression parameterType, boolean outputJS)
 +    {
 +        final StringBuilder sb = new StringBuilder();
 +
 +        String paramType;
 +
 +        if (parameterType == null)
 +        {
 +              System.out.println("no parameter type for " + paramName + " " + 
reference.getQualifiedName());
 +            paramType = "Object";
 +            if (outputJS)
 +              sb.append(paramName);
 +        }
 +        else if (parameterType.isVarArgs())
 +        {
 +              if (outputJS)
 +                      sb.append("var_").append(paramName);
 +              else
 +                      sb.append("...").append(paramName);
 +        }
 +        else
 +        {
 +            paramType = JSTypeUtils.toParamTypeString(reference, paramName);
 +            if (hasTemplate(reference) && containsTemplate(reference, 
paramType))
 +            {
 +                paramType = "Object";
 +            }
 +
 +            sb.append(paramName);
 +            if (!outputJS)
 +            {
 +                sb.append(":");
 +                sb.append(paramType);                 
 +                  if (parameterType.isOptionalArg())
 +                  {
 +                      sb.append(" = ");
 +                      sb.append(toDefaultParameterValue(paramType));
 +                  }
 +            }
 +        }
 +
 +        return sb.toString();
 +    }
 +
 +    private static String toDefaultParameterValue(String paramType)
 +    {
 +        if (paramType.equals("Function"))
 +            return "null";
 +        else if (paramType.equals("Number"))
 +            return "0";
 +        else if (paramType.equals("String"))
 +            return "''";
 +        else if (paramType.equals("Boolean"))
 +            return "false";
 +        return "null";
 +    }
 +
 +    public static boolean hasTemplate(BaseReference reference)
 +    {
++        if(reference instanceof MemberReference)
++        {
++            MemberReference memberRef = (MemberReference) reference;
++            
if(memberRef.getClassReference().getComment().getTemplateTypeNames().size() > 0)
++            {
++                return true;
++            }
++        }
 +        return reference.getComment().getTemplateTypeNames().size() > 0;
 +    }
 +    
 +    public static boolean containsTemplate(BaseReference reference, String 
name)
 +    {
-       for (String template : reference.getComment().getTemplateTypeNames())
-       {
-               if (name.contains("<" + template + ">"))
-                       return true;
-               if (name.equals(template))
-                       return true;
-       }
-       return false;
++        if(reference instanceof MemberReference)
++        {
++            MemberReference memberRef = (MemberReference) reference;
++            
if(commentContainsTemplate(memberRef.getClassReference().getComment(), name))
++            {
++                return true;
++            }
++        }
++        return commentContainsTemplate(reference.getComment(), name);
++    }
++    
++    private static boolean commentContainsTemplate(JSDocInfo comment, String 
name)
++    {
++        for (String template : comment.getTemplateTypeNames())
++        {
++            if (name.contains("<" + template + ">"))
++                return true;
++            if (name.equals(template))
++                return true;
++        }
++        return false;
 +    }
 +
 +}

Reply via email to