All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.royale.compiler.internal.targets.RoyaleJSTarget Maven / Gradle / Ivy

The newest version!
/*
 *
 *  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.royale.compiler.internal.targets;

import java.io.File;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.apache.royale.compiler.common.DependencyType;
import org.apache.royale.compiler.css.ICSSDocument;
import org.apache.royale.compiler.css.ICSSManager;
import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.internal.css.semantics.ActivatedStyleSheets;
import org.apache.royale.compiler.internal.driver.js.royale.JSCSSCompilationSession;
import org.apache.royale.compiler.internal.projects.DependencyGraph;
import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
import org.apache.royale.compiler.internal.units.SWCCompilationUnit;
import org.apache.royale.compiler.problems.FileNotFoundProblem;
import org.apache.royale.compiler.problems.ICompilerProblem;
import org.apache.royale.compiler.targets.IJSTarget;
import org.apache.royale.compiler.targets.ITargetProgressMonitor;
import org.apache.royale.compiler.targets.ITargetSettings;
import org.apache.royale.compiler.units.ICompilationUnit;
import org.apache.royale.compiler.units.ICompilationUnit.UnitType;

import com.google.common.collect.ImmutableList;

public class RoyaleJSTarget extends JSTarget implements IJSTarget
{
    /**
     * Initialize a JS target with the owner project and root compilation units.
     * 
     * @param project the owner project
     */
    public RoyaleJSTarget(RoyaleJSProject project, ITargetSettings targetSettings,
            ITargetProgressMonitor progressMonitor)
    {
        super(project, targetSettings, progressMonitor);
        royaleProject = project;
    }
    
    private final RoyaleJSProject royaleProject;

    ///////////
    //
    //  Copied from RoyaleAppSWFTarget.java then modified
    //
    ///////////
    /**
     * Discovers dependent compilation units from a set of root compilation
     * units.
     * 

* For each public visible definition in all the compilation units, if * there's an applicable CSS rule, check if the CSS rule pulls in any * dependencies. (i.e. embedded assets, skin classes) Add the dependencies * to the list of compilation units, and check if they have any applicable * CSS rules which could pull in more dependencies. Loop until we reach a * stable set of compilation units. *

* CSS rules in these CSS documents can introduce class dependencies. If any * candidate rule matches a class known to be linked into the target, the * candidate rule's dependencies are selected for linking. Those selected * dependencies will be included in the next iteration of the dependency * discovery loop. *

* Once a CSS document is "activated", it stays in this collection and its * rules are tested against all classes introduced in the * "dependency discovery loop". *

* For example: Suppose in project P, there are "A.as" and "styles.css", and * class "A" is selected for linking.
* In "styles.css", there're two rules: * *

     * A { xSkin : ClassReference("B"); }
     * K { xSkin : ClassReference("L"); }
     * 
* * In the 1st iteration, rule "A" is matched, which introduces dependency on * "B".
* "B" is defined in a SWC library "myskins.swc", and there's a * "defaults.css" in "myskins.swc". * *
     * B { ySkin : ClassReference("C"); }
     * A { ySkin : ClassReference("D"); }
     * K { ySkin : ClassReference("M"); }
     * 
* * In the 2nd iteration, rule "A" and rule "B" in "defaults.css" are * matched, which introduces dependencies on "C" and "D". However, "K" has * not been selected so far, so "L" and "M" are not selected. *

* Now imagine, "C" is defined in "anotherSkin.swc", and there's a * "defaults.css" in "anotherSkin.swc" as well. * *

     * C { zSkin : ClassReference("K"); }
     * 
* * In the 3rd iteration, rule "C" is matched because "C" was selected in the * previous iteration, which makes "K" the selected dependency. *

* At the beginning of the 4th iteration, the classes selected for linking * are "A", "B", "C", "D" and "K". In this iteration, these classes will be * tested against all the "activated style sheets" - "styles.css" and two * "defaults.css" in "myskins.swc" and "anotherSkin.swc". "K" rules in * "styles.css" and "myskins.swc" are now matched, which introduces new * dependencies on "L" and "M". *

* In the 5th iteration, the classes to link are "A", "B", "C", "D", "K", * "L" and "M". They are tested against all the activate CSS. No more * dependencies are introduced by CSS rules, making it the last iteration of * the loop. * * @param compilationUnits Collection of compilation units known to be * linked in. * @param problems Collection of {@link ICompilerProblem}'s that the each * found {@link ICompilationUnit} is added to. * @return All compilation units which were compiled * @throws InterruptedException */ @Override protected Set findAllCompilationUnitsToLink(final Collection compilationUnits, final Collection problems) throws InterruptedException { JSCSSCompilationSession cssCompilationSession = (JSCSSCompilationSession) royaleProject.getCSSCompilationSession(); cssCompilationSession.setKeepAllTypeSelectors(targetSettings.keepAllTypeSelectors()); // Performance heuristic: let's start compilation on all of the compilation // units we know about up front. This is particularly useful on SWC projects where // we are using "include-sources" to force a bunch of possibly unrelated classes to be // compiled. // Note that by putting the code here, we will start aggressive early compilation for // all projects. Limited data so far shows this this is a good thing. But down the // road it's possible that we might find tests cases that force us to reconsider / refine // this "shotgun" approach. for (ICompilationUnit cu : compilationUnits) cu.startBuildAsync(getTargetType()); assert compilationUnits != null : "compilation units can't be null"; assert problems != null : "problems can't be null"; // Collection of all the compilation units that will be linked in the target. final Set allCompilationUnitsInTarget = new HashSet(compilationUnits); // Collection of all the referenced CSS. Once a CSS is activated, it's always // included in the dependency checking, even none of its rules are matched. final ActivatedStyleSheets activatedStyleSheets = new ActivatedStyleSheets(); final ICSSManager cssManager = royaleProject.getCSSManager(); collectThemes(cssManager, activatedStyleSheets, problems); collectDefaultCSS(cssManager, activatedStyleSheets, problems); // The dependency discovery loop. // It terminates when no more dependencies are introduced by CSS. boolean done = false; while (!done) { //LoggingProfiler.onStartIteration(); // Get all non-CSS dependencies. final Set dependencies = getDependentCompilationUnits(allCompilationUnitsInTarget, problems); //LoggingProfiler.onCompilationUnitDependenciesChanged(allCompilationUnitsInTarget, dependencies); allCompilationUnitsInTarget.addAll(dependencies); // Get all activated defaults.css from SWCs. final Map activatedDefaultCSSList = getAllDefaultCSS(cssManager, allCompilationUnitsInTarget); for (final Map.Entry entry : activatedDefaultCSSList.entrySet()) { activatedStyleSheets.addLibraryCSS(entry.getKey(), entry.getValue().getAbsolutePath()); } //LoggingProfiler.onDefaultsCSSCollectionChanged(activatedStyleSheets); // Get all dependencies introduced by defaults.css from SWCs. final ImmutableList definitions = Target.getAllExternallyVisibleDefinitions(allCompilationUnitsInTarget); final Collection cssDependencies = new HashSet(); // activate rules in user specified CSS for (ICSSDocument cssDocument : cssCompilationSession.cssDocuments) { // Side-effects of this method: // 1. Resolve all type selectors in the CSS model to IClassDefinition definitions. // 2. Activate CSS rules whose subject is in the definition set. final Collection dependentCUListFromCSS = cssManager.getDependentCompilationUnitsFromCSS( cssCompilationSession, cssDocument, definitions, problems); cssDependencies.addAll(dependentCUListFromCSS); } for (final ICSSDocument cssDocument : activatedStyleSheets.all()) { // Side-effects of this method: // 1. Resolve all type selectors in the CSS model to IClassDefinition definitions. // 2. Activate CSS rules whose subject is in the definition set. final Collection dependentCUListFromCSS = cssManager.getDependentCompilationUnitsFromCSS( cssCompilationSession, cssDocument, definitions, problems); cssDependencies.addAll(dependentCUListFromCSS); //LoggingProfiler.onCSSDependenciesChanged(dependentCUListFromCSS); } // If there's more dependencies introduced by CSS, the loop continues. done = !allCompilationUnitsInTarget.addAll(cssDependencies); if (done) { DependencyGraph graph = royaleProject.getDependencyGraph(); for (ICompilationUnit cu : cssDependencies) { graph.addDependency(mainCU, cu, DependencyType.EXPRESSION); } } } // add to front so user specified css overrides defaults cssCompilationSession.cssDocuments.addAll(0, activatedStyleSheets.sort()); return super.findAllCompilationUnitsToLink(compilationUnits, problems); } /** * Collect CSS from themes. */ private void collectThemes( final ICSSManager cssManager, final ActivatedStyleSheets activatedStyleSheets, final Collection problems) { final Collection cssFromThemes = cssManager.getCSSFromThemes(problems); for (final ICSSDocument themeCSS : cssFromThemes) { // Theme files are sorted by declaration order instead of filenames, so we needn't // their filenames here. activatedStyleSheets.addThemeCSS(themeCSS); } } /** * Collect CSS from 'defaults-css-files' configuration option. */ private void collectDefaultCSS( final ICSSManager cssManager, final ActivatedStyleSheets activatedStyleSheets, final Collection problems) { for (final String defaultsCSSPath : getTargetSettings().getDefaultsCSSFiles()) { final ICSSDocument defaultsCSSModel = cssManager.getCSS(defaultsCSSPath); if (defaultsCSSModel == null) problems.add(new FileNotFoundProblem(defaultsCSSPath)); else activatedStyleSheets.addDefaultCSS(defaultsCSSModel); } } /** * Find all the {@link SWCCompilationUnit}'s, and return the default CSS * model in the SWCs. * * @param cssManager Project-level CSS manager. * @param compilationUnits All the compilation units. Non-SWC compilation * units are ignored. * @return Model of the default CSS in the SWCs. The map keys are CSS * models; the values are the enclosing SWC file. */ private static Map getAllDefaultCSS( final ICSSManager cssManager, final Collection compilationUnits) { assert cssManager != null : "Expected CSS manager."; assert compilationUnits != null : "Expected collection of compilation units."; final Map result = new HashMap(); for (final ICompilationUnit compilationUnit : compilationUnits) { if (compilationUnit.getCompilationUnitType() == UnitType.SWC_UNIT) { final File swcFile = new File(compilationUnit.getAbsoluteFilename()); final ICSSDocument defaultCSS = cssManager.getDefaultCSS(swcFile); if (defaultCSS != null) { result.put(defaultCSS, swcFile); } } } return result; } public void collectMixinMetaData(TreeSet mixinClassNames, List units) { for (ICompilationUnit unit : units) { try { RoyaleApplicationFrame1Info.collectMixinMetaData(mixinClassNames, unit); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void collectRemoteClassMetaData(Map remoteClassAliasMap, List units) { for (ICompilationUnit unit : units) { try { RoyaleApplicationFrame1Info.collectRemoteClassMetaData(remoteClassAliasMap, unit); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy