incubator-flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aha...@apache.org
Subject svn commit: r1413061 [6/14] - in /incubator/flex/falcon/trunk/compiler.js: ./ bin/ build/ in/ intermediates/ localization/ localization/src/ localization/src/org/ localization/src/org/apache/ localization/src/org/apache/flex/ localization/src/org/apach...
Date Fri, 23 Nov 2012 20:58:56 GMT
Added: incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/clients/MXMLJSC.java
URL: http://svn.apache.org/viewvc/incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/clients/MXMLJSC.java?rev=1413061&view=auto
==============================================================================
--- incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/clients/MXMLJSC.java (added)
+++ incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/clients/MXMLJSC.java Fri Nov 23 20:58:50 2012
@@ -0,0 +1,1336 @@
+/*
+ *
+ *  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.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.output.CountingOutputStream;
+
+import org.apache.flex.compiler.clients.problems.ProblemPrinter;
+import org.apache.flex.compiler.clients.problems.ProblemQuery;
+import org.apache.flex.compiler.clients.problems.WorkspaceProblemFormatter;
+import org.apache.flex.compiler.common.DependencyType;
+import org.apache.flex.compiler.common.VersionInfo;
+import org.apache.flex.compiler.config.CommandLineConfigurator;
+import org.apache.flex.compiler.config.Configuration;
+import org.apache.flex.compiler.config.ConfigurationBuffer;
+import org.apache.flex.compiler.config.ConfigurationValue;
+import org.apache.flex.compiler.config.Configurator;
+import org.apache.flex.compiler.config.ICompilerSettingsConstants;
+import org.apache.flex.compiler.config.RSLSettings;
+import org.apache.flex.compiler.config.RSLSettings.RSLAndPolicyFileURLPair;
+import org.apache.flex.compiler.definitions.IDefinition;
+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.exceptions.ConfigurationException.OnlyOneSource;
+import org.apache.flex.compiler.filespecs.IFileSpecification;
+import org.apache.flex.compiler.internal.as.codegen.JSGeneratingReducer;
+import org.apache.flex.compiler.internal.as.codegen.JSSharedData;
+import org.apache.flex.compiler.internal.as.codegen.JSWriter;
+import org.apache.flex.compiler.internal.config.localization.LocalizationManager;
+import org.apache.flex.compiler.internal.definitions.ClassDefinition;
+import org.apache.flex.compiler.internal.driver.IBackend;
+import org.apache.flex.compiler.internal.driver.JSBackend;
+import org.apache.flex.compiler.internal.driver.JSTarget;
+import org.apache.flex.compiler.internal.graph.GraphMLWriter;
+import org.apache.flex.compiler.internal.projects.CompilerProject;
+import org.apache.flex.compiler.internal.projects.DefinitionPriority;
+import org.apache.flex.compiler.internal.projects.FlexProject;
+import org.apache.flex.compiler.internal.projects.ISourceFileHandler;
+import org.apache.flex.compiler.internal.projects.DefinitionPriority.BasePriority;
+import org.apache.flex.compiler.internal.resourcebundles.ResourceBundleUtils;
+import org.apache.flex.compiler.internal.scopes.ASProjectScope;
+import org.apache.flex.compiler.internal.scopes.ASProjectScope.DefinitionPromise;
+import org.apache.flex.compiler.internal.targets.LinkageChecker;
+import org.apache.flex.compiler.internal.targets.Target;
+import org.apache.flex.compiler.internal.units.ABCCompilationUnit;
+import org.apache.flex.compiler.internal.units.ResourceModuleCompilationUnit;
+import org.apache.flex.compiler.internal.units.SWCCompilationUnit;
+import org.apache.flex.compiler.internal.units.SourceCompilationUnitFactory;
+import org.apache.flex.compiler.internal.units.StyleModuleCompilationUnit;
+import org.apache.flex.compiler.internal.workspaces.Workspace;
+import org.apache.flex.compiler.problems.ConfigurationProblem;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+import org.apache.flex.compiler.problems.InternalCompilerProblem;
+import org.apache.flex.compiler.problems.UnableToBuildSWFProblem;
+import org.apache.flex.compiler.problems.UnexpectedExceptionProblem;
+import org.apache.flex.compiler.projects.ICompilerProject;
+import org.apache.flex.compiler.targets.ISWFTarget;
+import org.apache.flex.compiler.targets.ITargetReport;
+import org.apache.flex.compiler.targets.ITargetSettings;
+import org.apache.flex.compiler.targets.ITarget.TargetType;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.units.ICompilationUnit;
+import org.apache.flex.compiler.units.ICompilationUnit.UnitType;
+import org.apache.flex.compiler.units.requests.IFileScopeRequestResult;
+import org.apache.flex.swc.ISWC;
+import org.apache.flex.swf.ISWF;
+import org.apache.flex.swf.io.ISWFWriter;
+import org.apache.flex.swf.types.Rect;
+import org.apache.flex.utils.FileUtils;
+import org.apache.flex.utils.FilenameNormalization;
+
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+/**
+ * The entry-point class for the FalconJS version of mxmlc.
+ */
+public class MXMLJSC
+{
+    private static final String DEFAULT_VAR = "file-specs";
+    private static final String L10N_CONFIG_PREFIX = "flex2.configuration";
+    private static final int TWIPS_PER_PIXEL = 20;
+
+    /*
+     * 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;
+    }
+
+    /**
+     * Java program entry point.
+     * 
+     * @param args command line arguments
+     */
+    public static void main(final String[] args)
+    {
+        long startTime = System.nanoTime();
+
+        final IBackend backend = new JSBackend();
+        final MXMLJSC mxmlc = new MXMLJSC(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);
+    }
+
+    public static int mainNoExit(final String[] args, List<ICompilerProblem> problemList)
+    {
+        final IBackend backend = new JSBackend();
+        final MXMLJSC mxmlc = new MXMLJSC(backend);
+        final Set<ICompilerProblem> problems = new HashSet<ICompilerProblem>();
+        final int exitCode = mxmlc.mainNoExit(args, problems, problemList == null);
+        if (problemList != null)
+            problemList.addAll(problems);
+        return exitCode;
+    }
+
+    public int mainNoExit(final String[] args, Set<ICompilerProblem> problems, Boolean printProblems)
+    {
+        int exitCode = -1;
+        try
+        {
+            exitCode = _mainNoExit(fixArgs(args), problems);
+        }
+        catch (Exception e)
+        {
+            JSSharedData.instance.stderr(e.toString());
+        }
+        finally
+        {
+            if (problems != null && !problems.isEmpty())
+            {
+                if (printProblems)
+                {
+                    final WorkspaceProblemFormatter formatter = new WorkspaceProblemFormatter(workspace);
+                    final ProblemPrinter printer = new ProblemPrinter(formatter);
+                    printer.printProblems(problems);
+                }
+            }
+        }
+        return exitCode;
+    }
+
+    /**
+     * Entry point that doesn't call <code>System.exit()</code>. This is for
+     * unit testing.
+     * 
+     * @param args command line arguments
+     * @return exit code
+     */
+    private int _mainNoExit(final String[] args, Set<ICompilerProblem> outProblems)
+    {
+        ExitCode exitCode = ExitCode.SUCCESS;
+        try
+        {
+            final boolean continueCompilation = configure(args);
+
+            if (outProblems != null && !config.isVerbose())
+                JSSharedData.STDOUT = JSSharedData.STDERR = null;
+
+            if (continueCompilation)
+            {
+                compile();
+                if (problems.hasFilteredProblems())
+                    exitCode = ExitCode.FAILED_WITH_PROBLEMS;
+            }
+            else if (problems.hasFilteredProblems())
+            {
+                exitCode = ExitCode.FAILED_WITH_CONFIG_PROBLEMS;
+            }
+            else
+            {
+                exitCode = ExitCode.PRINT_HELP;
+            }
+        }
+        catch (Exception e)
+        {
+            if (outProblems == null)
+                JSSharedData.instance.stderr(e.getMessage());
+            else
+            {
+                final ICompilerProblem unexpectedExceptionProblem = new UnexpectedExceptionProblem(e);
+                problems.add(unexpectedExceptionProblem);
+            }
+            exitCode = ExitCode.FAILED_WITH_EXCEPTIONS;
+        }
+        finally
+        {
+            waitAndClose();
+
+            if (outProblems != null && problems.hasFilteredProblems())
+            {
+                for (ICompilerProblem problem : problems.getFilteredProblems())
+                {
+                    outProblems.add(problem);
+                }
+            }
+        }
+        return exitCode.code;
+    }
+
+    protected MXMLJSC(IBackend backend)
+    {
+        JSSharedData.backend = backend;
+        workspace = new Workspace();
+        project = new FlexProject(workspace);
+        problems = new ProblemQuery();
+        JSSharedData.OUTPUT_EXTENSION = backend.getOutputExtension();
+        JSSharedData.workspace = workspace;
+        asFileHandler = backend.getSourceFileHandlerInstance();
+    }
+
+    protected Workspace workspace;
+    protected FlexProject project;
+    protected Configuration config;
+    protected ProblemQuery problems;
+    private ConfigurationBuffer configBuffer;
+
+    protected Configurator projectConfigurator;
+
+    protected ICompilationUnit mainCU;
+    protected JSTarget target;
+    private ITargetSettings targetSettings;
+    private ISWF swfTarget;
+
+    private Collection<ICompilationUnit> includedResourceBundleCompUnits;
+    protected ISourceFileHandler asFileHandler;
+
+    /**
+     * Print a message.
+     * 
+     * @param msg Message text.
+     */
+    public void println(final String msg)
+    {
+        JSSharedData.instance.stdout(msg);
+    }
+
+    /**
+     * Wait till the workspace to finish compilation and close.
+     */
+    protected void waitAndClose()
+    {
+        workspace.startIdleState();
+        try
+        {
+            workspace.close();
+        }
+        finally
+        {
+            workspace.endIdleState(Collections.<ICompilerProject, Set<ICompilationUnit>> emptyMap());
+        }
+    }
+
+    /**
+     * Force terminate the compilation process.
+     */
+    protected void close()
+    {
+        workspace.close();
+    }
+
+    /**
+     * Create a new Configurator. This method may be overridden to allow
+     * Configurator subclasses to be created that have custom configurations.
+     * 
+     * @return a new instance or subclass of {@link Configurator}.
+     */
+    protected Configurator createConfigurator()
+    {
+        return JSSharedData.backend.createConfigurator();
+    }
+
+    /**
+     * Load configurations from all the sources.
+     * 
+     * @param args command line arguments
+     * @return True if mxmlc should continue with compilation.
+     */
+    protected boolean configure(final String[] args)
+    {
+        project.getSourceCompilationUnitFactory().addHandler(asFileHandler);
+        projectConfigurator = createConfigurator();
+
+        try
+        {
+            // Print brief usage if no arguments provided.
+            if (args.length == 0)
+            {
+                final String usage = CommandLineConfigurator.brief(
+                        getProgramName(), DEFAULT_VAR, LocalizationManager.get(), L10N_CONFIG_PREFIX);
+                if (usage != null)
+                    println(usage);
+                return false;
+            }
+
+            projectConfigurator.setConfiguration(args, ICompilerSettingsConstants.FILE_SPECS_VAR);
+            projectConfigurator.applyToProject(project);
+            problems = new ProblemQuery(projectConfigurator.getCompilerProblemSettings());
+
+            // Get the configuration and configBuffer which are now initialized.
+            config = projectConfigurator.getConfiguration();
+            configBuffer = projectConfigurator.getConfigurationBuffer();
+            problems.addAll(projectConfigurator.getConfigurationProblems());
+
+            // Print version if "-version" is present.
+            if (configBuffer.getVar("version") != null) //$NON-NLS-1$
+            {
+                println(VersionInfo.buildMessage() + " (" + JSSharedData.COMPILER_VERSION + ")");
+                return false;
+            }
+
+            // Print help if "-help" is present.
+            final List<ConfigurationValue> helpVar = configBuffer.getVar("help"); //$NON-NLS-1$
+            if (helpVar != null)
+            {
+                processHelp(helpVar);
+                return false;
+            }
+
+            for (String fileName : projectConfigurator.getLoadedConfigurationFiles())
+            {
+                JSSharedData.instance.stdout("Loading configuration: " + fileName);
+            }
+
+            if (config.isVerbose())
+            {
+                for (final IFileSpecification themeFile : project.getThemeFiles())
+                {
+                    JSSharedData.instance.stdout(String.format("Found theme file %s", themeFile.getPath()));
+                }
+            }
+
+            // If we have configuration errors then exit before trying to 
+            // validate the target.
+            if (problems.hasErrors())
+                return false;
+
+            validateTargetFile();
+            return true;
+        }
+        catch (ConfigurationException e)
+        {
+            final ICompilerProblem problem = new ConfigurationProblem(e);
+            problems.add(problem);
+            return false;
+        }
+        catch (Exception e)
+        {
+            final ICompilerProblem problem = new ConfigurationProblem(null, -1, -1, -1, -1, e.getMessage());
+            problems.add(problem);
+            return false;
+        }
+        finally
+        {
+            // If we couldn't create a configuration, then create a default one
+            // so we can exit without throwing an exception.
+            if (config == null)
+            {
+                config = new Configuration();
+                configBuffer = new ConfigurationBuffer(Configuration.class, Configuration.getAliases());
+            }
+        }
+    }
+
+    /**
+     * Validate target file.
+     * 
+     * @throws MustSpecifyTarget
+     * @throws IOError
+     */
+    protected void validateTargetFile() throws ConfigurationException
+    {
+        if (mainCU instanceof ResourceModuleCompilationUnit)
+            return; //when compiling a Resource Module, no target file is defined.
+
+        final String targetFile = config.getTargetFile();
+        if (targetFile == null)
+            throw new ConfigurationException.MustSpecifyTarget(null, null, -1);
+
+        final File file = new File(targetFile);
+        if (!file.exists())
+            throw new ConfigurationException.IOError(targetFile);
+    }
+
+    /**
+     * 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
+        {
+            setupJS();
+            if (!setupTargetFile())
+                return false;
+
+            if (config.isDumpAst())
+                dumpAST();
+
+            buildArtifact();
+
+            if (swfTarget != null)
+            {
+                Collection<ICompilerProblem> errors = new ArrayList<ICompilerProblem>();
+                Collection<ICompilerProblem> warnings = new ArrayList<ICompilerProblem>();
+                
+                // Don't create a swf if there are errors unless a 
+                // developer requested otherwise.
+                if (!config.getCreateTargetWithErrors())
+                {
+                    problems.getErrorsAndWarnings(errors, warnings);
+                    if (errors.size() > 0)
+                        return false;
+                }
+
+                final File outputFile = new File(getOutputFilePath());
+                final int swfSize = writeSWF(swfTarget, outputFile);
+
+                println(String.format("%d bytes written to %s", swfSize, outputFile.getCanonicalPath()));
+                
+                if (JSSharedData.OUTPUT_ISOLATED)
+                {
+                	final File outputFolder = new File(outputFile.getParent());
+                    List<ICompilationUnit> reachableCompilationUnits = project.getReachableCompilationUnitsInSWFOrder(ImmutableSet.of(mainCU));
+                    for (final ICompilationUnit cu : reachableCompilationUnits)
+                    {
+                    	if (cu.getCompilationUnitType() == UnitType.AS_UNIT && cu != mainCU)
+                    	{
+		                	final File outputClassFile = new File(outputFolder.getAbsolutePath() + File.separator + cu.getShortNames().get(0) + ".js");
+		                	System.out.println(outputClassFile.getAbsolutePath());
+		                    final ISWFWriter swfWriter = JSSharedData.backend.createJSWriter(project, (List<ICompilerProblem>) errors, ImmutableSet.of(cu), false);
+		
+		                    if (swfWriter instanceof JSWriter)
+		                    {
+		                        final JSWriter writer = (JSWriter)swfWriter;
+		
+		                        final CountingOutputStream output =
+		                                new CountingOutputStream(new BufferedOutputStream(new FileOutputStream(outputClassFile)));
+		                        writer.writeTo(output);
+		                        output.flush();
+		                        output.close();
+		                        writer.close();
+		                    }
+	                    }
+                    }
+                }
+            }
+
+            dumpDependencyGraphIfNeeded();
+
+            compilationSuccess = true;
+
+        }
+        catch (Exception e)
+        {
+            final ICompilerProblem problem = new InternalCompilerProblem(e);
+            problems.add(problem);
+        }
+        return compilationSuccess;
+    }
+
+    /**
+     * Setup theme files.
+     */
+    protected void setupThemeFiles()
+    {
+        project.setThemeFiles(toFileSpecifications(config.getCompilerThemeFiles(), workspace));
+
+        if (config.isVerbose())
+        {
+            for (final IFileSpecification themeFile : project.getThemeFiles())
+            {
+                verboseMessage(String.format("Found theme file %s", themeFile.getPath()));
+            }
+        }
+    }
+
+    /**
+     * Setup {@code -compatibility-version} level. Falcon only support Flex 3+.
+     */
+    protected void setupCompatibilityVersion()
+    {
+        final int compatibilityVersion = config.getCompilerMxmlCompatibilityVersion();
+        if (compatibilityVersion < Configuration.MXML_VERSION_3_0)
+            throw new UnsupportedOperationException("Unsupported compatibility version: " + config.getCompilerCompatibilityVersionString());
+        this.project.setCompatibilityVersion(
+                config.getCompilerMxmlMajorCompatibilityVersion(),
+                config.getCompilerMxmlMinorCompatibilityVersion(),
+                config.getCompilerMxmlRevisionCompatibilityVersion());
+    }
+
+    /**
+     * Parse all source files and dumpAST
+     * 
+     * @throws InterruptedException
+     */
+    private void dumpAST() throws InterruptedException
+    {
+        final List<String> astDump = new ArrayList<String>();
+        final ImmutableList<ICompilationUnit> compilationUnits = getReachableCompilationUnits();
+        for (final ICompilationUnit compilationUnit : compilationUnits)
+        {
+            final IASNode ast = compilationUnit.getSyntaxTreeRequest().get().getAST();
+            astDump.add(ast.toString());
+        }
+
+        println(Joiner.on("\n\n").join(astDump)); //$NON-NLS-1$
+    }
+
+    /**
+     * Build target artifact.
+     * 
+     * @throws InterruptedException threading error
+     * @throws IOException IO error
+     * @throws ConfigurationException
+     */
+    protected void buildArtifact() throws InterruptedException, IOException, ConfigurationException
+    {
+        swfTarget = buildSWFModel();
+    }
+
+    /**
+     * Build SWF model object and collect problems building SWF in
+     * {@link #problems}.
+     * 
+     * @return SWF model or null if SWF can't be built.
+     * @throws InterruptedException concurrency problem
+     * @throws ConfigurationException
+     * @throws FileNotFoundException
+     */
+    private ISWF buildSWFModel() throws InterruptedException, FileNotFoundException, ConfigurationException
+    {
+        final List<ICompilerProblem> problemsBuildingSWF =
+                new ArrayList<ICompilerProblem>();
+
+        final ISWF swf = buildSWF(project, config.getMainDefinition(), mainCU, problemsBuildingSWF);
+        problems.addAll(problemsBuildingSWF);
+        if (swf == null)
+        {
+            ICompilerProblem problem = new UnableToBuildSWFProblem(getOutputFilePath());
+            problems.add(problem);
+        }
+        else
+        {
+            swf.setFrameRate(config.getDefaultFrameRate());
+            final int swfWidth = config.getDefaultWidth() * TWIPS_PER_PIXEL;
+            final int swfHeight = config.getDefaultHeight() * TWIPS_PER_PIXEL;
+            swf.setFrameSize(new Rect(swfWidth, swfHeight));
+            swf.setVersion(config.getSwfVersion());
+            swf.setTopLevelClass(config.getMainDefinition());
+            swf.setUseAS3(true);
+        }
+
+        reportRequiredRSLs(target);
+
+        return swf;
+    }
+
+    private void reportRequiredRSLs(ISWFTarget target) throws FileNotFoundException, InterruptedException, ConfigurationException
+    {
+        // Report the required RSLs:
+        if (hasRSLs())
+        {
+            ITargetReport report = target.getTargetReport();
+
+            if (report == null)
+                return; // target must not have been built.
+
+            // TODO (dloverin): localize messages
+            JSSharedData.instance.stdout("Required RSLs:");
+
+            // loop thru the RSLs and print out the required RSLs.
+            for (RSLSettings rslSettings : report.getRequiredRSLs())
+            {
+                List<RSLAndPolicyFileURLPair> rslUrls = rslSettings.getRSLURLs();
+
+                switch (rslUrls.size())
+                {
+                    case 0:
+                        assert false; // One RSL URL is required.
+                        break;
+                    case 1:
+                        JSSharedData.instance.stdout("    " + rslUrls.get(0).getRSLURL());
+                        //ThreadLocalToolkit.log(new RequiredRSLUrl(rslUrls.get(0)));                    
+                        break;
+                    case 2:
+                        JSSharedData.instance.stdout("    " + rslUrls.get(0).getRSLURL() + " with 1 failover.");
+                        //ThreadLocalToolkit.log(new RequiredRSLUrlWithFailover(rslUrls.get(0)));
+                        break;
+                    default:
+                        JSSharedData.instance.stdout("    " + rslUrls.get(0).getRSLURL() + " with " + (rslUrls.size() - 1) + " failovers.");
+                        //                            ThreadLocalToolkit.log(new RequiredRSLUrlWithMultipleFailovers(
+                        //                                    rslUrls.get(0),
+                        //                                    rslUrls.size() - 1));
+                        break;
+                }
+
+            }
+
+            // All -runtime-shared-libraries are required
+            for (String rslUrl : targetSettings.getRuntimeSharedLibraries())
+            {
+                JSSharedData.instance.stdout("    " + rslUrl);
+                //ThreadLocalToolkit.log(new RequiredRSLUrl(rslUrls.get(0)));                    
+            }
+        }
+    }
+
+    private ITargetSettings getTargetSettings()
+    {
+        if (targetSettings == null)
+            targetSettings = projectConfigurator.getTargetSettings(TargetType.SWF);
+
+        return targetSettings;
+    }
+
+    private boolean hasRSLs() throws FileNotFoundException, InterruptedException, ConfigurationException
+    {
+        return (getTargetSettings().getRuntimeSharedLibraryPath().size() > 0) ||
+               (getTargetSettings().getRuntimeSharedLibraryPath().size() > 0);
+    }
+
+    /**
+     * Write out SWF file and return file size in bytes.
+     * 
+     * @param swf SWF model
+     * @param outputFile output SWF file handle
+     * @return SWF file size in bytes
+     * @throws FileNotFoundException error
+     * @throws IOException error
+     */
+    private int writeSWF(final ISWF swf, final File outputFile) throws FileNotFoundException, IOException
+    {
+        int swfSize = 0;
+        final List<ICompilerProblem> problemList = new ArrayList<ICompilerProblem>();
+        final ISWFWriter swfWriter = JSSharedData.backend.createSWFWriter(project, problemList, swf, false, config.debug());
+
+        if (swfWriter instanceof JSWriter)
+        {
+            final JSWriter writer = (JSWriter)swfWriter;
+
+            final CountingOutputStream output =
+                    new CountingOutputStream(new BufferedOutputStream(new FileOutputStream(outputFile)));
+            writer.writeTo(output);
+            output.flush();
+            output.close();
+            writer.close();
+            swfSize = output.getCount();
+        }
+
+        /*
+         * W#3047880 falconjs_cs6: internal compiler error generated with
+         * optimize enabled compiling as3_enumerate.fla and fails to release the
+         * JS file http://watsonexp.corp.adobe.com/#bug=3047880 This is part #3
+         * of the fix: The closure compiler throws RTEs on internal compiler
+         * errors, that don't get caught until they bubble up to MXMLJSC's
+         * scope. On their way out files remain unclosed and cause problems,
+         * because Flame cannot delete open files. We now get
+         * InternalCompilerProblems, which we need to transfer to our problem
+         * list.
+         */
+        problems.addAll(problemList);
+
+        return swfSize;
+    }
+
+    /**
+     * Computes the set of compilation units that root the dependency walk. The
+     * returned set of compilation units and their dependencies will be
+     * compiled.
+     * <p>
+     * This method can be overriden by sub-classes.
+     * 
+     * @return The set of rooted {@link ICompilationUnit}'s.
+     */
+    protected ImmutableSet<ICompilationUnit> getRootedCompilationUnits()
+    {
+        return ImmutableSet.of(mainCU);
+    }
+
+    /**
+     * @return All the reachable compilation units in this job.
+     */
+    protected ImmutableList<ICompilationUnit> getReachableCompilationUnits()
+    {
+        final Set<ICompilationUnit> root = getRootedCompilationUnits();
+        final List<ICompilationUnit> reachableCompilationUnitsInSWFOrder =
+                project.getReachableCompilationUnitsInSWFOrder(root);
+        final ImmutableList<ICompilationUnit> compilationUnits = ImmutableList.<ICompilationUnit> copyOf(reachableCompilationUnitsInSWFOrder);
+        return compilationUnits;
+    }
+
+    /**
+     * 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 OnlyOneSource
+     * @throws InterruptedException
+     */
+    protected boolean setupTargetFile() throws InterruptedException
+    {
+        final String mainFileName = config.getTargetFile();
+
+        if (mainFileName != null)
+        {
+            final String normalizedMainFileName = FilenameNormalization.normalize(mainFileName);
+
+            // Can not add a SourceHandler for *.css file because we don't want
+            // to create compilation units for CSS files on the source path.
+            if (mainFileName.toLowerCase().endsWith(".css")) //$NON-NLS-1$
+            {
+                mainCU = new StyleModuleCompilationUnit(
+                        project,
+                        workspace.getFileSpecification(normalizedMainFileName),
+                        BasePriority.SOURCE_LIST);
+                // TODO: Use CSS file name once CSS module runtime code is finalized. (scai)
+                config.setMainDefinition("CSSModule2Main"); //$NON-NLS-1$
+                project.addCompilationUnitsAndUpdateDefinitions(
+                        Collections.singleton(mainCU));
+            }
+            else
+            {
+                final SourceCompilationUnitFactory compilationUnitFactory =
+                        project.getSourceCompilationUnitFactory();
+
+                File normalizedMainFile = new File(normalizedMainFileName);
+                if (compilationUnitFactory.canCreateCompilationUnit(normalizedMainFile))
+                {
+                    project.addIncludeSourceFile(normalizedMainFile);
+
+                    // just using the basename is obviously wrong:
+                    // final String mainQName = FilenameUtils.getBaseName(normalizedMainFile);
+
+                    final List<String> sourcePath = config.getCompilerSourcePath();
+                    String mainQName = null;
+                    if (sourcePath != null && !sourcePath.isEmpty())
+                    {
+                        for (String path : sourcePath)
+                        {
+                            final String otherPath = new File(path).getAbsolutePath();
+                            if (mainFileName.startsWith(otherPath))
+                            {
+                                mainQName = mainFileName.substring(otherPath.length() + 1);
+                                mainQName = mainQName.replaceAll("\\\\", "/");
+                                mainQName = mainQName.replaceAll("\\/", ".");
+                                if (mainQName.endsWith(".as"))
+                                    mainQName = mainQName.substring(0, mainQName.length() - 3);
+                                break;
+                            }
+                        }
+                    }
+
+                    if (mainQName == null)
+                        mainQName = FilenameUtils.getBaseName(mainFileName);
+
+                    Collection<ICompilationUnit> mainFileCompilationUnits =
+                            workspace.getCompilationUnits(normalizedMainFileName, project);
+
+                    assert mainFileCompilationUnits.size() == 1;
+                    mainCU = Iterables.getOnlyElement(mainFileCompilationUnits);
+
+                    assert ((DefinitionPriority)mainCU.getDefinitionPriority()).getBasePriority() == DefinitionPriority.BasePriority.SOURCE_LIST;
+
+                    // Use main source file name as the root class name.
+                    config.setMainDefinition(mainQName);
+                }
+            }
+        }
+        else
+        {
+            final List<ICompilerProblem> resourceBundleProblems = new ArrayList<ICompilerProblem>();
+            Collection<ICompilationUnit> includedResourceBundles = target.getIncludedResourceBundlesCompilationUnits(resourceBundleProblems);
+            problems.addAll(resourceBundleProblems);
+
+            if (includedResourceBundles.size() > 0)
+            {
+                //This means that a Resource Module is requested to be built.
+                mainCU = new ResourceModuleCompilationUnit(project, "GeneratedResourceModule", //$NON-NLS-1$
+                        includedResourceBundles,
+                        BasePriority.SOURCE_LIST);
+                config.setMainDefinition("GeneratedResourceModule"); //$NON-NLS-1$
+                project.addCompilationUnitsAndUpdateDefinitions(
+                        Collections.singleton(mainCU));
+            }
+        }
+
+        Preconditions.checkNotNull(mainCU, "Main compilation unit can't be null"); //$NON-NLS-1$
+
+        /*
+         * final String mainFileName = new
+         * File(config.getTargetFile()).getAbsolutePath(); final
+         * SourceCompilationUnitFactory compilationUnitFactory =
+         * project.getSourceCompilationUnitFactory(); final File mainFile = new
+         * File(mainFileName); // just using the basename is obviously wrong: //
+         * final String mainQName = FilenameUtils.getBaseName(mainFileName);
+         * final List<String> sourcePath = config.getCompilerSourcePath();
+         * String mainQName = null; if( sourcePath != null &&
+         * !sourcePath.isEmpty() ) { for( String path : sourcePath ) { final
+         * String otherPath = new File(path).getAbsolutePath(); if(
+         * mainFileName.startsWith(otherPath) ) { mainQName =
+         * mainFileName.substring(otherPath.length() + 1); mainQName =
+         * mainQName.replaceAll("\\\\", "/"); mainQName =
+         * mainQName.replaceAll("\\/", "."); if( mainQName.endsWith(".as") )
+         * mainQName = mainQName.substring(0, mainQName.length() - 3); break; }
+         * } } if( mainQName == null ) mainQName =
+         * FilenameUtils.getBaseName(mainFileName); mainCU =
+         * compilationUnitFactory.createCompilationUnit( mainFile,
+         * DefinitionPriority.BasePriority.SOURCE_LIST, mainQName, null);
+         * Preconditions.checkNotNull(mainCU,
+         * "Main compilation unit can't be null");
+         * project.addCompilationUnitsAndUpdateDefinitions(
+         * Collections.singleton(mainCU)); // Use main source file name as the
+         * root class name. config.setMainDefinition(mainQName);
+         */
+
+        // target = (FlexSWFTarget)project.createSWFTarget(getTargetSettings(), null);
+        if (getTargetSettings() == null)
+            return false;
+
+        target = (JSTarget)JSSharedData.backend.createSWFTarget(project, getTargetSettings(), null);
+
+        return true;
+    }
+
+    /**
+     * @return a list of resource bundle compilation units that are included
+     * into the build process by -include-resource-bundles compiler argument.
+     */
+    protected Collection<ICompilationUnit> getIncludedResourceBundlesCompUnits() throws InterruptedException
+    {
+        Collection<ICompilerProblem> bundleProblems = new ArrayList<ICompilerProblem>();
+        if (includedResourceBundleCompUnits == null)
+        {
+            includedResourceBundleCompUnits = new HashSet<ICompilationUnit>();
+
+            for (String bundleName : config.getIncludeResourceBundles())
+            {
+                includedResourceBundleCompUnits.addAll(ResourceBundleUtils.findCompilationUnits(bundleName, project, bundleProblems));
+                problems.addAll(bundleProblems);
+            }
+        }
+
+        return includedResourceBundleCompUnits;
+    }
+
+    /**
+     * Setup the source paths.
+     * 
+     * @throws InterruptedException
+     */
+    /**
+     * Setup the source paths.
+     * 
+     * @throws InterruptedException
+     */
+    protected void setupSourcePath() throws InterruptedException
+    {
+        project.setSourcePath(toFiles(config.getCompilerSourcePath()));
+    }
+
+    /**
+     * Setups the locale related settings.
+     */
+    protected void setupLocaleSettings()
+    {
+        project.setLocales(config.getCompilerLocales());
+        project.setLocaleDependentResources(config.getLocaleDependentSources());
+    }
+
+    /**
+     * 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();
+    }
+
+    private void verboseMessage(String s)
+    {
+        if (config.isVerbose())
+            println(s);
+    }
+
+    /**
+     * Convert file path strings to {@code File} objects. Null values are
+     * discarded.
+     * 
+     * @param fileSpecs file specifications
+     * @return List of File objects. No null values will be returned.
+     */
+    public static List<File> toFiles(final List<String> paths)
+    {
+        final List<File> result = new ArrayList<File>();
+        for (final String path : paths)
+        {
+            if (path != null)
+                result.add(new File(path));
+        }
+        return result;
+    }
+
+    /**
+     * Resolve a list of normalized paths to {@link IFileSpecification} objects
+     * from the given {@code workspace}.
+     * 
+     * @param paths A list of normalized paths.
+     * @param workspace Workspace.
+     * @return A list of file specifications.
+     */
+    public static List<IFileSpecification> toFileSpecifications(
+            final List<String> paths,
+            final Workspace workspace)
+    {
+        return Lists.transform(paths, new Function<String, IFileSpecification>()
+        {
+            @Override
+            public IFileSpecification apply(final String path)
+            {
+                return workspace.getFileSpecification(path);
+            }
+        });
+    }
+
+    /**
+     * Get my program name.
+     * 
+     * @return always "mxmlc".
+     */
+    protected String getProgramName()
+    {
+        return "mxmljsc"; //$NON-NLS-1$
+    }
+
+    /**
+     * Print detailed help information if -help is provided.
+     */
+    private void processHelp(final List<ConfigurationValue> helpVar)
+    {
+        final Set<String> keywords = new LinkedHashSet<String>();
+        for (final ConfigurationValue val : helpVar)
+        {
+            for (final Object element : val.getArgs())
+            {
+                String keyword = (String)element;
+                while (keyword.startsWith("-")) //$NON-NLS-1$
+                    keyword = keyword.substring(1);
+                keywords.add(keyword);
+            }
+        }
+
+        if (keywords.size() == 0)
+            keywords.add("help"); //$NON-NLS-1$
+
+        final String usages = CommandLineConfigurator.usage(
+                getProgramName(),
+                DEFAULT_VAR,
+                configBuffer,
+                keywords,
+                LocalizationManager.get(),
+                L10N_CONFIG_PREFIX);
+        println(usages);
+    }
+
+    /**
+     * "compc" subclass will override this method.
+     * 
+     * @return False if the client is not "compc".
+     */
+    protected boolean isCompc()
+    {
+        return false;
+    }
+
+    private void dumpDependencyGraphIfNeeded() throws IOException, InterruptedException, ConfigurationException
+    {
+        File dependencyGraphOutput = config.getDependencyGraphOutput();
+        if (dependencyGraphOutput != null)
+        {
+            LinkedList<ICompilerProblem> problemList = new LinkedList<ICompilerProblem>();
+            LinkageChecker linkageChecker = new LinkageChecker(project, getTargetSettings());
+            final Target.RootedCompilationUnits rootedCompilationUnits = target.getRootedCompilationUnits();
+            problems.addAll(rootedCompilationUnits.getProblems());
+            GraphMLWriter dependencyGraphWriter =
+                    new GraphMLWriter(project.getDependencyGraph(),
+                            rootedCompilationUnits.getUnits(), true,
+                            linkageChecker);
+            BufferedOutputStream graphStream = new BufferedOutputStream(new FileOutputStream(dependencyGraphOutput));
+            dependencyGraphWriter.writeToStream(graphStream, problemList);
+            problems.addAll(problemList);
+        }
+    }
+
+    /**
+     * Get the current project.
+     * 
+     * @return project
+     */
+    protected FlexProject getProject()
+    {
+        return this.project;
+    }
+
+    /**
+     * sets up JavaScript specific options
+     * 
+     * @throws IOException
+     * @throws InterruptedException
+     */
+    protected void setupJS() throws IOException, InterruptedException
+    {
+        JSGeneratingReducer.validate();
+
+        JSSharedData.instance.reset();
+        project.getSourceCompilationUnitFactory().addHandler(asFileHandler);
+
+        if (isCompc())
+            JSSharedData.COMPILER_NAME = "COMPJSC";
+        else
+            JSSharedData.COMPILER_NAME = "MXMLJSC";
+
+        JSSharedData.instance.setVerbose(config.isVerbose());
+
+        JSSharedData.DEBUG = config.debug();
+        JSSharedData.OPTIMIZE = !config.debug() && config.optimize();
+
+        // workaround for Falcon bug: getCompilerLibraryPath() is not supported yet.
+        /*
+         * if( config.getCompilerLibraryPath() != null ) { final List<String>
+         * libs = config.getCompilerLibraryPath(); final File libPaths[] = new
+         * File[libs.size()]; int nthPath = 0; for( String lib: libs ) { if( lib
+         * == null ) throw JSSharedData.backend.createException(
+         * "Invalid swc path in -compiler.library-path"); final String pathname
+         * = lib; final File libPath = new File(pathname); libPaths[nthPath++] =
+         * libPath; if( JSSharedData.SDK_PATH == null &&
+         * libPath.getName().equals("browserglobal.swc")) { //
+         * ../sdk/frameworks/libs/browser/browserglobal.swc File sdkFolder =
+         * libPath.getParentFile(); if( sdkFolder != null ) { sdkFolder =
+         * sdkFolder.getParentFile(); if( sdkFolder != null ) { sdkFolder =
+         * sdkFolder.getParentFile(); if( sdkFolder != null ) { sdkFolder =
+         * sdkFolder.getParentFile(); if( sdkFolder != null )
+         * JSSharedData.SDK_PATH = sdkFolder.getAbsolutePath(); } } } } } //
+         * Setting the library path into the project // causes an ISWC to be
+         * built for each SWC on the library path. // It also causes an
+         * MXMLManifestManager to be built for the project // from the manifest
+         * info in the project's SWCs. project.setInternalLibraryPath(libPaths);
+         * }
+         */
+
+        final Set<ICompilationUnit> compilationUnits = new HashSet<ICompilationUnit>();
+
+        // workaround for Falcon bug: getCompilerIncludeLibraries() is not supported yet.
+        /*
+         * if( config.getCompilerIncludeLibraries() != null ) { // see
+         * LibraryPathManager.computeUnitsToAdd() for( String swcSpec:
+         * config.getCompilerIncludeLibraries() ) { final ISWCManager swcManager
+         * = project.getWorkspace().getSWCManager(); final String swcFilePath =
+         * swcSpec; final ISWC swc = swcManager.get(new File(swcFilePath));
+         * final boolean isExternal = true; for (final ISWCLibrary library :
+         * swc.getLibraries()) { for (final ISWCScript script :
+         * library.getScripts()) { // Multiple definition in a script share the
+         * same compilation unit // with the same ABC byte code block. final
+         * List<String> qnames = new
+         * ArrayList<String>(script.getDefinitions().size()); for (final String
+         * definitionQName : script.getDefinitions()) { final String defName =
+         * definitionQName.replace(":", "."); qnames.add(defName); //$NON-NLS-1$
+         * //$NON-NLS-2$ } final ICompilationUnit cu = new SWCCompilationUnit(
+         * project, swc, library, script, qnames, isExternal);
+         * compilationUnits.add(cu); } } } }
+         */
+
+        // add builtins
+        final File builtin = new File(JSSharedData.BUILT_IN);
+        if (builtin.canRead())
+        {
+            if (config.isVerbose())
+                JSSharedData.instance.stdout("[abc] found: " + builtin);
+            ABCCompilationUnit cu = new ABCCompilationUnit(project, builtin.getPath());
+            compilationUnits.add(cu);
+        }
+
+        if (!compilationUnits.isEmpty())
+        {
+            final List<ICompilationUnit> units = new LinkedList<ICompilationUnit>();
+            units.addAll(compilationUnits);
+            project.addCompilationUnitsAndUpdateDefinitions(units);
+
+            if (config.isVerbose())
+            {
+                for (final ISWC swc : project.getLibraries())
+                {
+                    JSSharedData.instance.stdout(String.format("[lib] found library %s", swc.getSWCFile().getPath()));
+                }
+            }
+        }
+
+        registerSWCs(project);
+    }
+
+    /**
+     * Replaces FlexApplicationProject::buildSWF()
+     * 
+     * @param applicationProject
+     * @param rootClassName
+     * @param problems
+     * @return
+     * @throws InterruptedException
+     */
+
+    private ISWF buildSWF(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 target.build(mainCU, problems);
+    }
+
+    protected void verboseMessage(PrintStream strm, String s)
+    {
+        if (strm != null && config.isVerbose())
+            strm.println(s);
+    }
+
+    /**
+     * Scans JavaScript code for @requires tags and registers class
+     * dependencies.
+     * 
+     * @param cu current CompilationUnit
+     * @param classDef ClassDefinition of the JavaScript code
+     * @param jsCode JavaScript code of the ClassDefinition. private static void
+     * registerDependencies( ICompilationUnit cu, ClassDefinition classDef,
+     * String jsCode ) { final JSSharedData sharedData = JSSharedData.instance;
+     * final String requiresTag = "@requires"; // extract @requires class names
+     * and register dependencies. if( jsCode.contains(requiresTag) ) { final
+     * String line = jsCode.substring( jsCode.indexOf(requiresTag) +
+     * requiresTag.length() ); for( String part : line.split(requiresTag) ) {
+     * final String[] names = part.split("\\s+"); if( names.length > 1 ) { final
+     * String depClassName = names[1]; ASProjectScope projectScope =
+     * (ASProjectScope)cu.getProject().getScope(); IDefinition depClassDef =
+     * projectScope.findDefinitionByName(depClassName); if(depClassDef != null)
+     * { sharedData.addDependency(classDef, depClassDef); } } } } }
+     */
+
+    public static Boolean addDependency(ICompilationUnit cu, String className, DependencyType dt)
+    {
+        if (JSGeneratingReducer.isReservedDataType(className))
+            return false;
+
+        final ICompilationUnit fromCU = cu;
+        final CompilerProject compilerProject = (CompilerProject)cu.getProject();
+        final ASProjectScope projectScope = compilerProject.getScope();
+
+        final IDefinition classDef = projectScope.findDefinitionByName(className);
+        if (classDef == null)
+            return false;
+
+        final ICompilationUnit toCU = projectScope.getCompilationUnitForDefinition(classDef);
+        if (fromCU == toCU)
+            return false;
+
+        // sharedData.verboseMessage( "Adding dependency: " + className );
+        compilerProject.addDependency(fromCU, toCU, dt);
+        JSSharedData.instance.registerDefinition(classDef);
+        return true;
+    }
+
+    public static List<IDefinition> getDefinitions(ICompilationUnit cu, Boolean onlyClasses) throws InterruptedException
+    {
+        final List<IDefinition> classDefs = new ArrayList<IDefinition>();
+        // populate the IDefinition to ClassDefinition map
+        final List<IDefinition> defs = cu.getDefinitionPromises();
+        for (IDefinition def : defs)
+        {
+            if (def instanceof DefinitionPromise)
+            {
+                // see DefinitionPromise::getActualDefinition 
+                final String qname = def.getQualifiedName();
+                final IFileScopeRequestResult fileScopeRequestResult = cu.getFileScopeRequest().get();
+                def = fileScopeRequestResult.getMainDefinition(qname);
+            }
+
+            if (def != null && !onlyClasses || (def instanceof ClassDefinition))
+            {
+                classDefs.add(def);
+            }
+        }
+        return classDefs;
+    }
+
+    public static void registerSWCs(CompilerProject project) throws InterruptedException
+    {
+        final JSSharedData sharedData = JSSharedData.instance;
+
+        // collect all SWCCompilationUnit in swcUnits
+        final List<ICompilationUnit> swcUnits = new ArrayList<ICompilationUnit>();
+        for (ICompilationUnit cu : project.getCompilationUnits())
+        {
+            if (cu instanceof SWCCompilationUnit)
+                swcUnits.add(cu);
+
+            final List<IDefinition> defs = getDefinitions(cu, false);
+            for (IDefinition def : defs)
+            {
+                sharedData.registerDefinition(def);
+            }
+        }
+
+    }
+
+    protected String getFlexHomePath()
+    {
+        final String loadConfig = config.getLoadConfig();
+        if (loadConfig == null || loadConfig.isEmpty())
+            return null;
+        // throw new Error("Cannot find load configuration file: " + loadConfig.getPath() );
+
+        final File loadConfigFile = new File(loadConfig);
+        if (!loadConfigFile.isFile())
+            return null;
+        // throw new Error("Cannot find load configuration file: " + loadConfigFile.getAbsolutePath() );
+
+        final File frameworksFolder = new File(loadConfigFile.getParent());
+        if (!frameworksFolder.isDirectory())
+            return null;
+        // throw new Error("Cannot find framework folder: " + frameworksFolder.getAbsolutePath() );
+
+        final String flexHome = frameworksFolder.getParent();
+        if (flexHome == null || flexHome.isEmpty())
+            return null;
+        // throw new Error("Cannot find FLEX_HOME environment variable.");
+
+        return flexHome;
+    }
+
+    // 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;
+    }
+
+    protected JSCommandLineConfiguration getConfiguration()
+    {
+        if (config instanceof JSCommandLineConfiguration)
+            return (JSCommandLineConfiguration)config;
+        return null;
+    }
+}

Propchange: incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/clients/MXMLJSC.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/AbcGeneratingReducer.java
URL: http://svn.apache.org/viewvc/incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/AbcGeneratingReducer.java?rev=1413061&view=auto
==============================================================================
--- incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/AbcGeneratingReducer.java (added)
+++ incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/AbcGeneratingReducer.java Fri Nov 23 20:58:50 2012
@@ -0,0 +1,28 @@
+/*
+ *
+ *  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.as.codegen;
+
+public class AbcGeneratingReducer extends JSGeneratingReducer
+{
+    public AbcGeneratingReducer()
+    {
+        super(JSSharedData.instance);
+    }
+}

Propchange: incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/AbcGeneratingReducer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSClassDirectiveProcessor.java
URL: http://svn.apache.org/viewvc/incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSClassDirectiveProcessor.java?rev=1413061&view=auto
==============================================================================
--- incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSClassDirectiveProcessor.java (added)
+++ incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSClassDirectiveProcessor.java Fri Nov 23 20:58:50 2012
@@ -0,0 +1,357 @@
+/*
+ *
+ *  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.as.codegen;
+
+import static org.apache.flex.abc.ABCConstants.*;
+
+import org.apache.flex.abc.ABCConstants;
+import org.apache.flex.abc.visitors.IABCVisitor;
+import org.apache.flex.abc.visitors.ITraitVisitor;
+import org.apache.flex.abc.visitors.ITraitsVisitor;
+import org.apache.flex.abc.semantics.MethodInfo;
+import org.apache.flex.abc.semantics.Name;
+import org.apache.flex.abc.semantics.Trait;
+import org.apache.flex.abc.instructionlist.InstructionList;
+import org.apache.flex.compiler.common.ASModifier;
+import org.apache.flex.compiler.internal.definitions.ClassDefinition;
+import org.apache.flex.compiler.internal.definitions.DefinitionBase;
+import org.apache.flex.compiler.internal.definitions.FunctionDefinition;
+import org.apache.flex.compiler.internal.definitions.NamespaceDefinition;
+import org.apache.flex.compiler.internal.semantics.SemanticUtils;
+import org.apache.flex.compiler.internal.tree.as.ClassNode;
+import org.apache.flex.compiler.internal.tree.as.FunctionNode;
+import org.apache.flex.compiler.internal.tree.as.NamespaceNode;
+import org.apache.flex.compiler.internal.tree.as.VariableNode;
+import org.apache.flex.compiler.problems.StaticNamespaceDefinitionProblem;
+import org.apache.flex.compiler.projects.ICompilerProject;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.as.ICommonClassNode;
+
+/**
+ * A ClassDirectiveProcessor generates an ABC class from a ClassNode and its
+ * contents. JSClassDirectiveProcessor is derived from ClassDirectiveProcessor
+ * and adds workarounds necessary for FalconJS. Ideally FalconJS should use
+ * ClassDirectiveProcessor and retire JSClassDirectiveProcessor. This
+ * implementation is part of FalconJS. For more details on FalconJS see
+ * org.apache.flex.compiler.JSDriver.
+ */
+@SuppressWarnings("nls")
+public class JSClassDirectiveProcessor extends ClassDirectiveProcessor
+{
+    JSGenerator m_generator;
+
+    /**
+     * Instructions to place in the class' initializer. Note that these are part
+     * of the class itself, as opposed to the above instructions which create
+     * the class at the global scope.
+     */
+    InstructionList looseInsns = new InstructionList();
+
+    /**
+     * Constructor. Initializes the ClassDirectiveProcessor and its associated
+     * AET data structures.
+     * 
+     * @param c - the class' AST.
+     * @param enclosing_scope - the immediately enclosing lexical scope.
+     * @param emitter - the active ABC emitter.
+     */
+    public JSClassDirectiveProcessor(JSGenerator generator, ClassNode c, LexicalScope enclosing_scope, IABCVisitor emitter)
+    {
+        this(generator, c, addDefinition(enclosing_scope.getProject(), c.getDefinition()), enclosing_scope, emitter);
+    }
+
+    private static ClassDefinition addDefinition(ICompilerProject project, ClassDefinition cdef)
+    {
+        JSSharedData.instance.registerDefinition(cdef);
+        return cdef;
+    }
+
+    /**
+     * Constructor. Initializes the ClassDirectiveProcessor and its associated
+     * AET data structures.
+     * 
+     * @param class_definition - the class' definition
+     * @param enclosing_scope - the immediately enclosing lexical scope.
+     * @param emitter - the active ABC emitter.
+     */
+    public JSClassDirectiveProcessor(JSGenerator generator, IASNode node, ClassDefinition class_definition, LexicalScope enclosing_scope, IABCVisitor emitter)
+    {
+        super((ICommonClassNode)node, class_definition, enclosing_scope, emitter);
+        m_generator = generator;
+
+        /*
+         * // add explicit dependencies. final ICompilerProject project =
+         * classScope.getProject(); final ClassDefinition superclassDefinition =
+         * class_definition.resolveBaseClass( new ASDefinitionCache(project),
+         * new RecursionGuard(), classScope.getProblems()); if(
+         * superclassDefinition != null )
+         * JSSharedData.instance.addDependency(class_definition,
+         * superclassDefinition);
+         */
+
+        generator.getReducer().setClassDefinition(enclosing_scope.getProject(), class_definition);
+    }
+
+    /**
+     * Finish the class' definition.
+     */
+    @Override
+    void finishClassDefinition()
+    {
+        //  Create the class' constructor function.
+        if (this.ctorFunction != null /* || !iinitInsns.isEmpty() */)
+        {
+            MethodInfo mi = m_generator.generateFunction(this.ctorFunction, classScope, this.iinitInsns);
+            if (mi != null)
+                this.iinfo.iInit = mi;
+
+            this.ctorFunction = null;
+            this.iinitInsns = new InstructionList();
+        }
+
+        // clear cinitInsns if there are no side effects
+        // by initializing the static members directly.
+        final String fullName = JSGeneratingReducer.createFullNameFromDefinition(classScope.getProject(), classDefinition);
+        if (!JSSharedData.instance.hasClassInit(fullName))
+            cinitInsns = new InstructionList();
+
+        // support for class inits 
+        // loose statement are now collected in looseInsns
+        if (!this.looseInsns.isEmpty())
+            cinitInsns.addAll(looseInsns);
+
+        super.finishClassDefinition();
+
+        m_generator.getReducer().setClassDefinition(null, null);
+    }
+
+    /**
+     * Declare a function. TODO: static vs. instance.
+     */
+    @Override
+    void declareFunction(FunctionNode func)
+    {
+        func.parseFunctionBody(classScope.getProblems());
+
+        boolean is_constructor = func.isConstructor();
+
+        functionSemanticChecks(func);
+
+        //  Save the constructor function until
+        //  we've seen all the instance variables
+        //  that might need initialization.
+        if (is_constructor)
+        {
+            this.ctorFunction = func;
+        }
+        else
+        {
+            MethodInfo mi = m_generator.generateFunction(func, classScope, null);
+            ITraitVisitor tv;
+
+            if (mi != null)
+            {
+                FunctionDefinition funcDef = func.getDefinition();
+                Name funcName = funcDef.getMName(classScope.getProject());
+
+                if (func.hasModifier(ASModifier.STATIC))
+                    tv = ctraits.visitMethodTrait(functionTraitKind(func, TRAIT_Method), funcName, 0, mi);
+                else
+                {
+                    tv = itraits.visitMethodTrait(functionTraitKind(func, TRAIT_Method), funcName, 0, mi);
+                    if (funcDef.getNamespaceReference() instanceof NamespaceDefinition.IProtectedNamespaceDefinition)
+                        this.iinfo.flags |= ABCConstants.CLASS_FLAG_protected;
+                }
+
+                this.classScope.processMetadata(tv, funcDef.getAllMetaTags());
+
+                if (func.hasModifier(ASModifier.FINAL))
+                    tv.visitAttribute(Trait.TRAIT_FINAL, Boolean.TRUE);
+                if (func.hasModifier(ASModifier.OVERRIDE))
+                    tv.visitAttribute(Trait.TRAIT_OVERRIDE, Boolean.TRUE);
+            }
+        }
+    }
+
+    /**
+     * Declare a variable. TODO: static vs. instance.
+     */
+    @Override
+    void declareVariable(VariableNode var)
+    {
+        verifyVariableModifiers(var);
+
+        DefinitionBase varDef = var.getDefinition();
+        m_generator.getReducer().startDeclareVariable(varDef);
+
+        boolean is_static = var.hasModifier(ASModifier.STATIC);
+        boolean is_const = SemanticUtils.isConst(var, classScope.getProject());
+
+        //  generateConstantValue() returns null if no constant value
+        //  can be generated, and null is the correct value for "no value."
+        Object initializer = m_generator.generateConstantValue(var.getAssignedValueNode(), this.classScope.getProject());
+
+        ITraitVisitor tv = declareVariable(var, varDef, is_static, is_const, initializer);
+
+        this.classScope.processMetadata(tv, varDef.getAllMetaTags());
+
+        //  Generate variable initializers and append them to the 
+        //  proper initialization list.
+        if (var.getChildCount() > 1)
+        {
+            //  We need to put the correct traits visitor on the class'
+            //  LexicalScope; the BURM may encounter variable declarations
+            //  chained onto this one, and it will need the traits visitor to declare them.
+
+            //  Save the scope's current traits visitor (which should be null)
+            //  and restore it 
+            ITraitsVisitor saved_traits_visitor = this.classScope.traitsVisitor;
+            assert (saved_traits_visitor == null);
+            try
+            {
+                // the following line causes duplicate Traits.
+                // JSEmitter::emitTraits works around duplicate Traits by checking against
+                // a visitedTraits set.
+                this.classScope.traitsVisitor = (is_static) ? ctraits : itraits;
+                this.classScope.resetDebugInfo();
+                InstructionList init_expression = m_generator.generateInstructions(var, CmcJSEmitter.__statement_NT, this.classScope);
+                if (init_expression != null && !init_expression.isEmpty())
+                {
+                    // final JSEmitter emitter = (JSEmitter)this.classScope.getEmitter();
+                    final String str = JSGeneratingReducer.instructionListToString(init_expression, true);
+
+                    if (str.contains(" = "))
+                    {
+                        final String varInit = m_generator.getReducer().getVariableInitializer(varDef);
+                        if (varInit != null && !varInit.isEmpty())
+                        {
+                            // set the value of the slot trait.
+                            final String varName = varDef.getBaseName();
+                            for (Trait t : this.classScope.traitsVisitor.getTraits())
+                            {
+                                final byte kind = t.getKind();
+                                if (kind == TRAIT_Const || kind == TRAIT_Var)
+                                {
+                                    final Name name = t.getNameAttr(Trait.TRAIT_NAME);
+                                    if (name.getBaseName().equals(varName))
+                                    {
+                                        t.setAttr(Trait.SLOT_VALUE, varInit);
+                                        break;
+                                    }
+                                }
+                            }
+
+                        }
+
+                        if (is_static)
+                        {
+                            // see finishClassDefinition.
+                            // We clear cinitInsns only if there are no side effects
+                            // by initializing the static members directly.
+                            // If varInit is null, or varInit is isEmpty() 
+                            // then we have side effects. 
+                            if (!init_expression.isEmpty())
+                                registerClassInit(var);
+
+                            cinitInsns.addAll(init_expression);
+                        }
+                        else
+                            iinitInsns.addAll(init_expression);
+                    }
+                }
+            }
+            finally
+            {
+                this.classScope.traitsVisitor = saved_traits_visitor;
+            }
+        }
+
+        m_generator.getReducer().endDeclareVariable(varDef);
+    }
+
+    /**
+     * Ignore modifier nodes that are in the AST, but processed as attributes of
+     * the definition nodes. Other loose directives are processed as statements
+     * and added to the class' static init method.
+     */
+    @Override
+    void processDirective(IASNode n)
+    {
+        switch (n.getNodeID())
+        {
+
+            case StaticID:
+            case FinalID:
+            case OverrideID:
+            case UseID:
+                break;
+
+            case NamespaceID:
+            {
+                NamespaceNode ns = (NamespaceNode)n;
+
+                if (ns.hasModifier(ASModifier.STATIC))
+                {
+                    this.classScope.addProblem(new StaticNamespaceDefinitionProblem(ns));
+                }
+                else
+                {
+                    try
+                    {
+                        this.classScope.traitsVisitor = itraits;
+                        m_generator.generateInstructions(n, CmcEmitter.__statement_NT, this.classScope);
+                        // assert(stmt_insns == null);
+                    }
+                    finally
+                    {
+                        this.classScope.traitsVisitor = null;
+                    }
+                }
+                break;
+            }
+            default:
+            {
+                // support for class inits.
+                // loose statement are now collected in looseInsns
+                //  Handle a loose statement.
+                InstructionList stmt_insns = m_generator.generateInstructions(n, CmcJSEmitter.__statement_NT, this.classScope);
+                if (stmt_insns != null)
+                {
+                    if (looseInsns.size() == 0)
+                        registerClassInit(n);
+
+                    looseInsns.addAll(stmt_insns);
+                }
+                break;
+            }
+        }
+    }
+
+    private void registerClassInit(IASNode node)
+    {
+        final String fullName = JSGeneratingReducer.createFullNameFromDefinition(classScope.getProject(), classDefinition);
+        if (!fullName.equals(JSSharedData.JS_FRAMEWORK_NAME))
+        {
+            JSSharedData.instance.registerClassInit(fullName);
+            m_generator.getReducer().warnClassInitPerformance(node);
+            m_generator.getReducer().setNeedsSecondPass();
+        }
+    }
+}

Propchange: incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSClassDirectiveProcessor.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message