flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aha...@apache.org
Subject [2/3] git commit: [flex-falcon] - COMPC equivalent: compiles the AS files specified by a SWC into a set of JS files in a directory structure. Does not minify
Date Mon, 29 Apr 2013 06:46:05 GMT
COMPC equivalent:  compiles the AS files specified by a SWC into a set of JS files in a directory
structure.  Does not minify


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

Branch: refs/heads/develop
Commit: da5904154a22c54c3d498da31778d089807ff8ae
Parents: d6fcec4
Author: Alex Harui <aharui@apache.org>
Authored: Fri Apr 26 15:45:41 2013 -0700
Committer: Alex Harui <aharui@apache.org>
Committed: Sun Apr 28 23:45:39 2013 -0700

----------------------------------------------------------------------
 .../org/apache/flex/compiler/clients/COMPJSC.java  |  404 +++++++++++++++
 .../org/apache/flex/compiler/clients/MXMLJSC.java  |   18 +-
 .../driver/mxml/flexjs/MXMLFlexJSSWCBackend.java   |  121 +++++
 .../compiler/internal/targets/FlexJSSWCTarget.java |  289 +++++++++++
 4 files changed, 823 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/da590415/compiler.jx/src/org/apache/flex/compiler/clients/COMPJSC.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/clients/COMPJSC.java b/compiler.jx/src/org/apache/flex/compiler/clients/COMPJSC.java
new file mode 100644
index 0000000..4702195
--- /dev/null
+++ b/compiler.jx/src/org/apache/flex/compiler/clients/COMPJSC.java
@@ -0,0 +1,404 @@
+/*
+ *
+ *  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.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.io.FilenameUtils;
+import org.apache.flex.compiler.codegen.as.IASWriter;
+import org.apache.flex.compiler.driver.IBackend;
+import org.apache.flex.compiler.driver.js.IJSApplication;
+import org.apache.flex.compiler.exceptions.ConfigurationException;
+import org.apache.flex.compiler.exceptions.ConfigurationException.IOError;
+import org.apache.flex.compiler.exceptions.ConfigurationException.MustSpecifyTarget;
+import org.apache.flex.compiler.internal.codegen.js.JSSharedData;
+import org.apache.flex.compiler.internal.driver.as.ASBackend;
+import org.apache.flex.compiler.internal.driver.js.amd.AMDBackend;
+import org.apache.flex.compiler.internal.driver.js.goog.GoogBackend;
+import org.apache.flex.compiler.internal.driver.mxml.flexjs.MXMLFlexJSSWCBackend;
+import org.apache.flex.compiler.internal.projects.CompilerProject;
+import org.apache.flex.compiler.internal.targets.JSTarget;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+import org.apache.flex.compiler.problems.InternalCompilerProblem;
+import org.apache.flex.compiler.targets.ITargetSettings;
+import org.apache.flex.compiler.targets.ITarget.TargetType;
+import org.apache.flex.compiler.units.ICompilationUnit;
+import org.apache.flex.utils.FileUtils;
+import org.apache.flex.compiler.problems.UnableToBuildSWFProblem;
+
+
+/**
+ * @author Erik de Bruin
+ * @author Michael Schmalle
+ */
+public class COMPJSC extends MXMLJSC
+{
+    /*
+     * Exit code enumerations.
+     */
+    static enum ExitCode
+    {
+        SUCCESS(0),
+        PRINT_HELP(1),
+        FAILED_WITH_PROBLEMS(2),
+        FAILED_WITH_EXCEPTIONS(3),
+        FAILED_WITH_CONFIG_PROBLEMS(4);
+
+        ExitCode(int code)
+        {
+            this.code = code;
+        }
+
+        final int code;
+    }
+
+    private static JSOutputType jsOutputType;
+
+    /**
+     * Java program entry point.
+     * 
+     * @param args command line arguments
+     */
+    public static void main(final String[] args)
+    {
+        long startTime = System.nanoTime();
+
+        IBackend backend = new ASBackend();
+        for (String s : args)
+        {
+            if (s.contains("-js-output-type"))
+            {
+                jsOutputType = JSOutputType.fromString(s.split("=")[1]);
+
+                switch (jsOutputType)
+                {
+                case AMD:
+                    backend = new AMDBackend();
+                    break;
+                case FLEXJS:
+                    backend = new MXMLFlexJSSWCBackend();
+                    break;
+                case GOOG:
+                    backend = new GoogBackend();
+                    break;
+                }
+
+                break;
+            }
+        }
+
+        final COMPJSC mxmlc = new COMPJSC(backend);
+        final Set<ICompilerProblem> problems = new HashSet<ICompilerProblem>();
+        final int exitCode = mxmlc.mainNoExit(args, problems, true);
+
+        long endTime = System.nanoTime();
+        JSSharedData.instance.stdout((endTime - startTime) / 1e9 + " seconds");
+
+        System.exit(exitCode);
+    }
+
+    protected COMPJSC(IBackend backend)
+    {
+        super(backend);
+    }
+
+    /**
+     * Main body of this program. This method is called from the public static
+     * method's for this program.
+     * 
+     * @return true if compiler succeeds
+     * @throws IOException
+     * @throws InterruptedException
+     */
+    protected boolean compile()
+    {
+        boolean compilationSuccess = false;
+
+        try
+        {
+            project.getSourceCompilationUnitFactory().addHandler(asFileHandler);
+
+            if (!setupTargetFile())
+                return false;
+
+            buildArtifact();
+
+            if (jsTarget != null)
+            {
+                Collection<ICompilerProblem> errors = new ArrayList<ICompilerProblem>();
+                Collection<ICompilerProblem> warnings = new ArrayList<ICompilerProblem>();
+
+                if (!config.getCreateTargetWithErrors())
+                {
+                    problems.getErrorsAndWarnings(errors, warnings);
+                    if (errors.size() > 0)
+                        return false;
+                }
+                
+                File outputFolder = new File(getOutputFilePath());
+                
+                Collection<ICompilationUnit> reachableCompilationUnits = project
+                        .getCompilationUnits();
+                for (final ICompilationUnit cu : reachableCompilationUnits)
+                {
+                    ICompilationUnit.UnitType cuType = cu
+                            .getCompilationUnitType();
+
+                    if (cuType == ICompilationUnit.UnitType.AS_UNIT
+                            || cuType == ICompilationUnit.UnitType.MXML_UNIT)
+                    {
+                        final File outputClassFile = getOutputClassFile(cu
+                                .getQualifiedNames().get(0), outputFolder);
+
+                        System.out
+                                .println("Compiling file: " + outputClassFile);
+
+                        ICompilationUnit unit = cu;
+
+                        IASWriter writer;
+                        if (cuType == ICompilationUnit.UnitType.AS_UNIT)
+                        {
+                            writer = JSSharedData.backend.createWriter(project,
+                                    (List<ICompilerProblem>) errors, unit,
+                                    false);
+                        }
+                        else
+                        {
+                            writer = JSSharedData.backend.createMXMLWriter(
+                                    project, (List<ICompilerProblem>) errors,
+                                    unit, false);
+                        }
+
+                        BufferedOutputStream out = new BufferedOutputStream(
+                                new FileOutputStream(outputClassFile));
+                        writer.writeTo(out);
+                        out.flush();
+                        out.close();
+                        writer.close();
+                    }
+                }
+
+                compilationSuccess = true;
+            }
+        }
+        catch (Exception e)
+        {
+            final ICompilerProblem problem = new InternalCompilerProblem(e);
+            problems.add(problem);
+        }
+
+        return compilationSuccess;
+    }
+
+    /**
+     * Build target artifact.
+     * 
+     * @throws InterruptedException threading error
+     * @throws IOException IO error
+     * @throws ConfigurationException
+     */
+    protected void buildArtifact() throws InterruptedException, IOException,
+            ConfigurationException
+    {
+        jsTarget = buildJSTarget();
+    }
+
+    private IJSApplication buildJSTarget() throws InterruptedException,
+            FileNotFoundException, ConfigurationException
+    {
+        final List<ICompilerProblem> problemsBuildingSWF = new ArrayList<ICompilerProblem>();
+
+        final IJSApplication app = buildApplication(project,
+                config.getMainDefinition(), null, problemsBuildingSWF);
+        problems.addAll(problemsBuildingSWF);
+        if (app == null)
+        {
+            ICompilerProblem problem = new UnableToBuildSWFProblem(
+                    getOutputFilePath());
+            problems.add(problem);
+        }
+
+        return app;
+    }
+
+    /**
+     * Replaces FlexApplicationProject::buildSWF()
+     * 
+     * @param applicationProject
+     * @param rootClassName
+     * @param problems
+     * @return
+     * @throws InterruptedException
+     */
+
+    private IJSApplication buildApplication(CompilerProject applicationProject,
+            String rootClassName, ICompilationUnit mainCU,
+            Collection<ICompilerProblem> problems) throws InterruptedException,
+            ConfigurationException, FileNotFoundException
+    {
+        Collection<ICompilerProblem> fatalProblems = applicationProject
+                .getFatalProblems();
+        if (!fatalProblems.isEmpty())
+        {
+            problems.addAll(fatalProblems);
+            return null;
+        }
+
+        return ((JSTarget) target).build(mainCU, problems);
+    }
+
+    /**
+     * Get the output file path. If {@code -output} is specified, use its value;
+     * otherwise, use the same base name as the target file.
+     * 
+     * @return output file path
+     */
+    private String getOutputFilePath()
+    {
+        if (config.getOutput() == null)
+        {
+            final String extension = "." + JSSharedData.OUTPUT_EXTENSION;
+            return FilenameUtils.removeExtension(config.getTargetFile())
+                    .concat(extension);
+        }
+        else
+            return config.getOutput();
+    }
+
+    /**
+     * @author Erik de Bruin
+     * 
+     * Get the output class file. This includes the (sub)directory in which the
+     * original class file lives. If the directory structure doesn't exist, it
+     * is created.
+     * 
+     * @param qname
+     * @param outputFolder
+     * @return output class file path
+     */
+    private File getOutputClassFile(String qname, File outputFolder)
+    {
+        String[] cname = qname.split("\\.");
+        String sdirPath = outputFolder + File.separator;
+        if (cname.length > 0)
+        {
+            for (int i = 0, n = cname.length - 1; i < n; i++)
+            {
+                sdirPath += cname[i] + File.separator;
+            }
+
+            File sdir = new File(sdirPath);
+            if (!sdir.exists())
+                sdir.mkdirs();
+
+            qname = cname[cname.length - 1];
+        }
+
+        return new File(sdirPath + qname + "." + JSSharedData.OUTPUT_EXTENSION);
+    }
+
+    /**
+     * Mxmlc uses target file as the main compilation unit and derive the output
+     * SWF file name from this file.
+     * 
+     * @return true if successful, false otherwise.
+     * @throws InterruptedException
+     */
+    @Override
+    protected boolean setupTargetFile() throws InterruptedException
+    {
+        config.getTargetFile();
+
+        ITargetSettings settings = getTargetSettings();
+        if (settings != null)
+            project.setTargetSettings(settings);
+
+        target = JSSharedData.backend.createTarget(project,
+                getTargetSettings(), null);
+
+        return true;
+    }
+
+    private ITargetSettings getTargetSettings()
+    {
+        if (targetSettings == null)
+            targetSettings = projectConfigurator.getTargetSettings(getTargetType());
+
+        return targetSettings;
+    }
+
+    /**
+     * Validate target file.
+     * 
+     * @throws MustSpecifyTarget
+     * @throws IOError
+     */
+    @Override
+    protected void validateTargetFile() throws ConfigurationException
+    {
+    
+    }
+
+    protected String getProgramName()
+    {
+        return "compc";
+    }
+
+    protected boolean isCompc()
+    {
+        return true;
+    }
+    
+    protected TargetType getTargetType()
+    {
+        return TargetType.SWC;
+    }
+
+    // Workaround for Falcon bug: input files with relative paths confuse the 
+    // algorithm that extracts the root class name.
+    protected static String[] fixArgs(final String[] args)
+    {
+        String[] newArgs = args;
+        if (args.length > 1)
+        {
+            String targetPath = args[args.length - 1];
+            if (targetPath.startsWith("."))
+            {
+                targetPath = FileUtils
+                        .getTheRealPathBecauseCanonicalizeDoesNotFixCase(new File(
+                                targetPath));
+                newArgs = new String[args.length];
+                for (int i = 0; i < args.length - 1; ++i)
+                    newArgs[i] = args[i];
+                newArgs[args.length - 1] = targetPath;
+            }
+        }
+        return newArgs;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/da590415/compiler.jx/src/org/apache/flex/compiler/clients/MXMLJSC.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/clients/MXMLJSC.java b/compiler.jx/src/org/apache/flex/compiler/clients/MXMLJSC.java
index 41caa43..1b3f7d1 100644
--- a/compiler.jx/src/org/apache/flex/compiler/clients/MXMLJSC.java
+++ b/compiler.jx/src/org/apache/flex/compiler/clients/MXMLJSC.java
@@ -178,17 +178,17 @@ public class MXMLJSC
         System.exit(exitCode);
     }
 
-    private Workspace workspace;
-    private FlexJSProject project;
-    private ProblemQuery problems;
-    private ISourceFileHandler asFileHandler;
-    private Configuration config;
-    private Configurator projectConfigurator;
+    protected Workspace workspace;
+    protected FlexJSProject project;
+    protected ProblemQuery problems;
+    protected ISourceFileHandler asFileHandler;
+    protected Configuration config;
+    protected Configurator projectConfigurator;
     private ConfigurationBuffer configBuffer;
     private ICompilationUnit mainCU;
-    private ITarget target;
-    private ITargetSettings targetSettings;
-    private IJSApplication jsTarget;
+    protected ITarget target;
+    protected ITargetSettings targetSettings;
+    protected IJSApplication jsTarget;
     private IJSPublisher jsPublisher;
 
     protected MXMLJSC(IBackend backend)

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/da590415/compiler.jx/src/org/apache/flex/compiler/internal/driver/mxml/flexjs/MXMLFlexJSSWCBackend.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/driver/mxml/flexjs/MXMLFlexJSSWCBackend.java
b/compiler.jx/src/org/apache/flex/compiler/internal/driver/mxml/flexjs/MXMLFlexJSSWCBackend.java
new file mode 100644
index 0000000..45bc336
--- /dev/null
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/driver/mxml/flexjs/MXMLFlexJSSWCBackend.java
@@ -0,0 +1,121 @@
+/*
+ *
+ *  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.driver.mxml.flexjs;
+
+import java.io.FilterWriter;
+import java.util.List;
+
+import org.apache.flex.compiler.codegen.IDocEmitter;
+import org.apache.flex.compiler.codegen.as.IASEmitter;
+import org.apache.flex.compiler.codegen.js.IJSEmitter;
+import org.apache.flex.compiler.codegen.js.IJSWriter;
+import org.apache.flex.compiler.codegen.mxml.IMXMLEmitter;
+import org.apache.flex.compiler.config.Configurator;
+import org.apache.flex.compiler.driver.IBackend;
+import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitter;
+import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogDocEmitter;
+import org.apache.flex.compiler.internal.codegen.mxml.MXMLBlockWalker;
+import org.apache.flex.compiler.internal.codegen.mxml.MXMLWriter;
+import org.apache.flex.compiler.internal.codegen.mxml.flexjs.MXMLFlexJSBlockWalker;
+import org.apache.flex.compiler.internal.codegen.mxml.flexjs.MXMLFlexJSEmitter;
+import org.apache.flex.compiler.internal.driver.js.goog.JSGoogConfiguration;
+import org.apache.flex.compiler.internal.driver.mxml.MXMLBackend;
+import org.apache.flex.compiler.internal.targets.FlexJSSWCTarget;
+import org.apache.flex.compiler.internal.targets.JSTarget;
+import org.apache.flex.compiler.internal.visitor.as.ASNodeSwitch;
+import org.apache.flex.compiler.internal.visitor.mxml.MXMLNodeSwitch;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+import org.apache.flex.compiler.projects.IASProject;
+import org.apache.flex.compiler.targets.ITargetProgressMonitor;
+import org.apache.flex.compiler.targets.ITargetSettings;
+import org.apache.flex.compiler.tree.mxml.IMXMLFileNode;
+import org.apache.flex.compiler.units.ICompilationUnit;
+import org.apache.flex.compiler.visitor.IBlockVisitor;
+import org.apache.flex.compiler.visitor.IBlockWalker;
+import org.apache.flex.compiler.visitor.mxml.IMXMLBlockWalker;
+
+/**
+ * A concrete implementation of the {@link IBackend} API where the
+ * {@link MXMLBlockWalker} is used to traverse the {@link IMXMLFileNode} AST.
+ * 
+ * @author Erik de Bruin
+ */
+public class MXMLFlexJSSWCBackend extends MXMLBackend
+{
+
+    @Override
+    public Configurator createConfigurator()
+    {
+        return new Configurator(JSGoogConfiguration.class);
+    }
+
+    @Override
+    public IMXMLEmitter createMXMLEmitter(FilterWriter out)
+    {
+        return new MXMLFlexJSEmitter(out);
+    }
+
+    @Override
+    public IMXMLBlockWalker createMXMLWalker(IASProject project,
+            List<ICompilerProblem> errors, IMXMLEmitter mxmlEmitter,
+            IASEmitter asEmitter, IBlockWalker asBlockWalker)
+    {
+        MXMLBlockWalker walker = new MXMLFlexJSBlockWalker(errors, project,
+                mxmlEmitter, asEmitter, asBlockWalker);
+
+        ASNodeSwitch asStrategy = new ASNodeSwitch(
+                (IBlockVisitor) asBlockWalker);
+        walker.setASStrategy(asStrategy);
+
+        MXMLNodeSwitch mxmlStrategy = new MXMLNodeSwitch(walker);
+        walker.setMXMLStrategy(mxmlStrategy);
+
+        return walker;
+    }
+
+    @Override
+    public IDocEmitter createDocEmitter(IASEmitter emitter)
+    {
+        return new JSGoogDocEmitter((IJSEmitter) emitter);
+    }
+
+    @Override
+    public IJSEmitter createEmitter(FilterWriter out)
+    {
+        IJSEmitter emitter = new JSFlexJSEmitter(out);
+        emitter.setDocEmitter(createDocEmitter(emitter));
+        return emitter;
+    }
+    
+    @Override
+    public IJSWriter createMXMLWriter(IASProject project,
+            List<ICompilerProblem> problems, ICompilationUnit compilationUnit,
+            boolean enableDebug)
+    {
+        return new MXMLWriter(project, problems, compilationUnit, enableDebug);
+    }
+
+    @Override
+    public JSTarget createTarget(IASProject project, ITargetSettings settings,
+            ITargetProgressMonitor monitor)
+    {
+        return new FlexJSSWCTarget(project, settings, monitor);
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/da590415/compiler.jx/src/org/apache/flex/compiler/internal/targets/FlexJSSWCTarget.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/targets/FlexJSSWCTarget.java
b/compiler.jx/src/org/apache/flex/compiler/internal/targets/FlexJSSWCTarget.java
new file mode 100644
index 0000000..0feebcd
--- /dev/null
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/targets/FlexJSSWCTarget.java
@@ -0,0 +1,289 @@
+/*
+ *
+ *  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.targets;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.flex.compiler.common.XMLName;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.definitions.references.IResolvedQualifiersReference;
+import org.apache.flex.compiler.definitions.references.ReferenceFactory;
+import org.apache.flex.compiler.internal.projects.FlexJSProject;
+import org.apache.flex.compiler.internal.projects.SourcePathManager;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+import org.apache.flex.compiler.problems.NoCompilationUnitForDefinitionProblem;
+import org.apache.flex.compiler.problems.NoSourceForClassInNamespaceProblem;
+import org.apache.flex.compiler.problems.NoSourceForClassProblem;
+import org.apache.flex.compiler.projects.IASProject;
+import org.apache.flex.compiler.targets.IJSTarget;
+import org.apache.flex.compiler.targets.ITargetProgressMonitor;
+import org.apache.flex.compiler.targets.ITargetSettings;
+import org.apache.flex.compiler.units.ICompilationUnit;
+import org.apache.flex.compiler.units.ICompilationUnit.UnitType;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+public class FlexJSSWCTarget extends JSTarget implements IJSTarget
+{
+    protected ICompilationUnit mainCU;
+    protected RootedCompilationUnits rootedCompilationUnits;
+
+    /**
+     * Initialize a JS target with the owner project and root compilation units.
+     * 
+     * @param project the owner project
+     */
+    public FlexJSSWCTarget(IASProject project, ITargetSettings targetSettings,
+            ITargetProgressMonitor progressMonitor)
+    {
+        super(project, targetSettings, progressMonitor);
+        flexProject = (FlexJSProject)project;
+    }
+
+    private FlexJSProject flexProject;
+    
+    @Override
+    protected Target.RootedCompilationUnits computeRootedCompilationUnits() throws InterruptedException
+    {
+        final Set<ICompilationUnit> rootCompilationUnits = new HashSet<ICompilationUnit>();
+
+        final Collection<File> includedSourceFiles = targetSettings.getIncludeSources();
+        final Set<String> includeClassNameSet = ImmutableSet.copyOf(targetSettings.getIncludeClasses());
+        final Set<String> includedNamespaces = ImmutableSet.copyOf(targetSettings.getIncludeNamespaces());
+
+        final ArrayList<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+        
+        // Select definitions according to configurations.
+
+        // include-namespace
+        final Collection<ICompilationUnit> includeNamespaceUnits = 
+            getCompilationUnitsForIncludedNamespaces(includedNamespaces, problems); 
+        rootCompilationUnits.addAll(includeNamespaceUnits);
+        
+        // include-class + include-namespace
+        rootCompilationUnits.addAll(getCompilationUnitsFromClassNames(null, includeClassNameSet,
problems));
+
+        // include-source
+        for (final File includedSourceFileName : includedSourceFiles)
+        {
+            // Get all the compilation units in the project that reference the specified
file.
+            Collection<ICompilationUnit> compilationUnitsForFile = project.getWorkspace().getCompilationUnits(includedSourceFileName.getAbsolutePath(),
project);
+            
+            // For compilation units with that differ by qname, choose the compilation that
+            // appears first on the source-path.
+            if (compilationUnitsForFile.size() > 1)
+            {
+                compilationUnitsForFile = filterUnitsBasedOnSourcePath(compilationUnitsForFile);
+            }
+            
+            for (ICompilationUnit cu : compilationUnitsForFile)
+            {
+                // IFilter out any compilation unit in the list where the specified file
is not the root
+                // source file compiled by the compilation unit.
+                if (cu.getAbsoluteFilename().equals(includedSourceFileName.getAbsolutePath()))
+                    rootCompilationUnits.add(cu);
+            }
+        }
+
+        //Add compilation units for included resource bundles
+        for (ICompilationUnit rbCompUnit : getIncludedResourceBundlesCompilationUnits(problems))
+            rootCompilationUnits.add(rbCompUnit);
+
+        // -include and -include-libraries
+        rootCompilationUnits.addAll(getIncludesCompilationUnits());
+        rootCompilationUnits.addAll(getIncludeLibrariesCompilationUnits());
+        
+        return new Target.RootedCompilationUnits(rootCompilationUnits, problems);
+    }
+
+    /**
+     * For compilation units with the same absolute source path, filter based on
+     * the source path. The compilation unit found on the highest priority
+     * source path wins. The rest of the compilation units with qnames are
+     * discared. If a unit is not on the source path or does not have a qname or
+     * more than one qname, then let it thru the filter.
+     * 
+     * @param compilationUnitsForFile list of compilation units to filter.
+     * @return filtered compilation units.
+     * @throws InterruptedException
+     */
+    private Collection<ICompilationUnit> filterUnitsBasedOnSourcePath(Collection<ICompilationUnit>
compilationUnitsForFile) throws InterruptedException
+    {
+        List<ICompilationUnit> sourcePathUnits = new ArrayList<ICompilationUnit>(compilationUnitsForFile);
+        boolean foundHighestPriorityUnit = false;
+        for (File sourcePath : flexProject.getSourcePath())
+        {
+            for (ICompilationUnit unit : sourcePathUnits)
+            {
+                // We only care about filtering units on the source path
+                // that follow the single definition rule.
+                UnitType unitType = unit.getCompilationUnitType();
+                if (unitType == UnitType.AS_UNIT || unitType == UnitType.FXG_UNIT ||
+                    unitType == UnitType.MXML_UNIT || unitType == UnitType.CSS_UNIT)
+                {
+                    Collection<String> qnames = unit.getQualifiedNames();
+                    if (qnames.size() > 1)
+                        continue;
+                    
+                    String unitQname = qnames.isEmpty() ? "" : qnames.iterator().next();
+                    String computedQname = SourcePathManager.computeQName(sourcePath, new
File(unit.getAbsoluteFilename()));
+                    
+                    if (unitQname.equals(computedQname))
+                    {
+                        // We found a unit on the source path. Only keep the 
+                        // first unit found on the source path and remove the 
+                        // others.
+                        if (foundHighestPriorityUnit)
+                            compilationUnitsForFile.remove(unit);
+                        
+                        foundHighestPriorityUnit = true;
+                        break; // should only be one compilation unit on a source path
+                    }
+                }
+            }
+        }
+        
+        return compilationUnitsForFile;
+    }
+
+    /**
+     * Get the compilation units for the given included namespaces. Also perform error
+     * checking.
+     * 
+     * @param namespaces the namespaces included in this swc target.
+     * @param problems A collection where detected problems are added.
+     * @return A collection of compilation units.
+     * @throws InterruptedException 
+     */
+    private Collection<ICompilationUnit> getCompilationUnitsForIncludedNamespaces(
+            Collection<String> namespaces,
+            Collection<ICompilerProblem> problems) throws InterruptedException
+    {
+        final Collection<ICompilationUnit> allUnits = new HashSet<ICompilationUnit>();
+        
+        for (String namespace : namespaces)
+        {
+            // For each namespace get the set of classes. 
+            // From the classes get the the compilation units.
+            // Validate the compilation units are resolved to source
+            // files unless there are lookupOnly entries.
+            final Collection<String> includeNamespaceQualifiedNames =
+                flexProject.getQualifiedClassNamesForManifestNamespaces(
+                        Collections.singleton(namespace));
+            final Collection<ICompilationUnit> units = 
+                getCompilationUnitsFromClassNames(namespace, includeNamespaceQualifiedNames,
problems);
+            validateIncludeNamespaceEntries(namespace, units, problems);
+            allUnits.addAll(units);
+        }
+        return allUnits;
+    }
+    
+    /**
+     * Validate that the manifest entries in the included namespaces resolve to
+     * source files, not classes from other SWCs. The exception is for entries
+     * that are "lookupOnly".
+     * 
+     * @param namespace The target namespace.
+     * @param units The compilation units found in that namespace.
+     * @param problems detected problems are added to this list.
+     * @throws InterruptedException 
+     */
+    private void validateIncludeNamespaceEntries(String namespace, 
+            Collection<ICompilationUnit> units, 
+            Collection<ICompilerProblem> problems) throws InterruptedException
+    {
+        for (ICompilationUnit unit : units)
+        {
+            List<String> classNames = unit.getQualifiedNames();
+            String className = classNames.get(classNames.size() - 1);
+            Collection<XMLName> xmlNames = flexProject.getTagNamesForClass(className);
+            for (XMLName xmlName : xmlNames)
+            {
+                if (namespace.equals(xmlName.getXMLNamespace()))
+                {
+                    if (!flexProject.isManifestComponentLookupOnly(xmlName) && 
+                        unit.getCompilationUnitType() == UnitType.SWC_UNIT)
+                    {
+                        problems.add(new NoSourceForClassInNamespaceProblem(namespace, className));
+                    }
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
+     * Return a collection of compilation units for a collection of class names. 
+     *
+     * @param namespace the namespace of the classes. Null if there is no namespace.
+     * @param classNames
+     * @param problems detected problems are added to this list.
+     * @return a collection of compilation units.
+     */
+    private Collection<ICompilationUnit> getCompilationUnitsFromClassNames(String namespace,
+            Collection<String> classNames,
+            final Collection<ICompilerProblem> problems)
+    {
+        // Class names are turned into references and then info compilation units.
+        final Iterable<IResolvedQualifiersReference> references = 
+            Iterables.transform(classNames, new Function<String, IResolvedQualifiersReference>()
+                {
+                    @Override
+                    public IResolvedQualifiersReference apply(String qualifiedName)
+                    {
+                        return ReferenceFactory.packageQualifiedReference(project.getWorkspace(),
qualifiedName, true);
+                    }
+                });
+
+        Collection<ICompilationUnit> units = new LinkedList<ICompilationUnit>();
+        for (IResolvedQualifiersReference reference : references)
+        {
+            IDefinition def = reference.resolve(flexProject);
+            if (def == null)
+            {
+                if (namespace == null)
+                    problems.add(new NoSourceForClassProblem(reference.getDisplayString()));
+                else
+                    problems.add(new NoSourceForClassInNamespaceProblem(namespace, reference.getDisplayString()));
+            }
+            else
+            {
+                ICompilationUnit defCU = project.getScope().getCompilationUnitForDefinition(def);
+                if (defCU == null)
+                    problems.add(new NoCompilationUnitForDefinitionProblem(def.getBaseName()));
+                else
+                    units.add(defCU);
+            }
+        }
+
+        return units;
+    }
+
+
+}


Mime
View raw message