Package org.apache.flex.compiler.internal.units

Source Code of org.apache.flex.compiler.internal.units.FXGCompilationUnit

/*
*
*  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.units;

import java.io.FileNotFoundException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.flex.compiler.internal.as.codegen.CodeGeneratorManager;
import org.apache.commons.io.FilenameUtils;

import org.apache.flex.compiler.common.DependencyType;
import org.apache.flex.compiler.common.Multiname;
import org.apache.flex.compiler.definitions.INamespaceDefinition;
import org.apache.flex.compiler.definitions.ITypeDefinition;
import org.apache.flex.compiler.definitions.references.INamespaceReference;
import org.apache.flex.compiler.definitions.references.IReference;
import org.apache.flex.compiler.definitions.references.ReferenceFactory;

import org.apache.flex.compiler.filespecs.IFileSpecification;
import org.apache.flex.compiler.fxg.dom.IFXGNode;
import org.apache.flex.compiler.fxg.flex.FXGSymbolClass;
import org.apache.flex.compiler.fxg.flex.FlexFXG2SWFTranscoder;
import org.apache.flex.compiler.internal.definitions.ClassDefinition;
import org.apache.flex.compiler.internal.definitions.PackageDefinition;
import org.apache.flex.compiler.internal.fxg.resources.FXGFileResolver;
import org.apache.flex.compiler.internal.fxg.sax.FXGSAXParser;
import org.apache.flex.compiler.internal.parsing.as.ASParser;
import org.apache.flex.compiler.internal.projects.CompilerProject;
import org.apache.flex.compiler.internal.projects.DefinitionPriority.BasePriority;
import org.apache.flex.compiler.internal.scopes.ASProjectScope;
import org.apache.flex.compiler.internal.scopes.FXGFileScope;
import org.apache.flex.compiler.internal.scopes.PackageScope;
import org.apache.flex.compiler.internal.scopes.TypeScope;
import org.apache.flex.compiler.internal.semantics.PostProcessStep;
import org.apache.flex.compiler.internal.targets.TagSorter;
import org.apache.flex.compiler.internal.tree.as.FileNode;
import org.apache.flex.compiler.internal.units.requests.ABCBytesRequestResult;
import org.apache.flex.compiler.internal.units.requests.ASFileScopeRequestResult;
import org.apache.flex.compiler.internal.units.requests.SyntaxTreeRequestResult;
import org.apache.flex.compiler.problems.ICompilerProblem;
import org.apache.flex.compiler.problems.InternalCompilerProblem2;
import org.apache.flex.compiler.units.requests.IABCBytesRequestResult;
import org.apache.flex.compiler.units.requests.IFileScopeRequestResult;
import org.apache.flex.compiler.units.requests.IOutgoingDependenciesRequestResult;
import org.apache.flex.compiler.units.requests.ISWFTagsRequestResult;
import org.apache.flex.compiler.units.requests.ISyntaxTreeRequestResult;
import org.apache.flex.swf.SWFFrame;
import org.apache.flex.swf.tags.DoABCTag;
import org.apache.flex.swf.tags.ICharacterTag;
import org.apache.flex.swf.tags.ITag;
import org.apache.flex.utils.FilenameNormalization;
import com.google.common.collect.Iterables;

/**
* This is a Compilation Unit which handles FXG compilation
*/
public class FXGCompilationUnit extends CompilationUnitBase
{
    private static final String fxgBaseClassName =  "spark.core.SpriteVisualElement";

    private String qname;
   
    private static final String SUB_SYSTEM = "FXGCompilationUnit";   // used for error reporting
   
    /**
     * A {@code IFileSpecification} implementation from {@code String}.
     */
    private class GeneratedSourceFileSpecfication implements IFileSpecification
    {
        public GeneratedSourceFileSpecfication(String name, String content)
        {
            this.reader = new StringReader(content);
            this.name = FilenameNormalization.normalize(name);
        }

        private final StringReader reader;
        private final String name;

        @Override
        public String getPath()
        {
            return name;
        }

        @Override
        public Reader createReader() throws FileNotFoundException
        {
            return reader;
        }

        @Override
        public long getLastModified()
        {
            return 0;
        }

        @Override
        public boolean isOpenDocument()
        {
            return false;
        }
    }

    public FXGCompilationUnit(CompilerProject project, String path, BasePriority basePriority, String qname)
    {
        super(project, path, basePriority, qname);
        this.qname = qname;
    }

    @Override
    public UnitType getCompilationUnitType()
    {
        return UnitType.FXG_UNIT;
    }

    @Override
    protected ISyntaxTreeRequestResult handleSyntaxTreeRequest() throws InterruptedException
    {
        startProfile(Operation.GET_SYNTAX_TREE);
       
        getProject().clearScopeCacheForCompilationUnit(this);
       
        final Collection<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
        IFXGNode fxgroot = null;
        try
        {
            fxgroot = new FXGSAXParser().parse(getRootFileSpecification().createReader(), qname, problems);              
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
            problems.add(new InternalCompilerProblem2(getAbsoluteFilename(), ex, SUB_SYSTEM));
        }
        finally
        {
            stopProfile(Operation.GET_SYNTAX_TREE);
        }
       
        return new FXGSyntaxTreeRequestResult(fxgroot, getRootFileSpecification().getLastModified(), problems);
    }
   
    /**
     * Syntax Tree request result for FXG files. FXG files are not represented
     * by a traditional AST, they use their own tree and this class allows
     * {@link FXGCompilationUnit} to cache an FXG tree result.
     */
    private static class FXGSyntaxTreeRequestResult extends SyntaxTreeRequestResult {

        private IFXGNode rootNode;
       
        public FXGSyntaxTreeRequestResult(IFXGNode rootNode, long lastModified, Collection<ICompilerProblem> problems)
        {
            super(lastModified, problems);
            this.rootNode = rootNode;
        }
       
        /**
         * Returns the root node for the FXG file handled
         * by this compilation unit
         *
         * @return root node
         */
        public IFXGNode getRootNode()
        {
            return rootNode;
        }
      
    }
   
    /**
     * This function will create a temporary filscope. Please note that this will not be the filescope that is used in the actual AST
     */
    @Override
    protected IFileScopeRequestResult handleFileScopeRequest() throws InterruptedException
    {
        startProfile(Operation.GET_FILESCOPE);
        try
        {
            List<ICompilerProblem> noProblems = Collections.emptyList();
            IFileSpecification rootFileSpec = getRootFileSpecification();
            FXGFileScope fileScope = createFileScope();

            return new ASFileScopeRequestResult(getDefinitionPromises(), getDefinitionPriority(), noProblems, fileScope, rootFileSpec);
        }
        finally
        {
            stopProfile(Operation.GET_FILESCOPE);
        }
    }
   
    @Override
    protected IOutgoingDependenciesRequestResult handleOutgoingDependenciesRequest () throws InterruptedException
    {
        startProfile(Operation.GET_SEMANTIC_PROBLEMS);
       
        final Collection<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
        Map<ITag, ITag> extraTags = new HashMap<ITag, ITag>();
        FXGSymbolClass symbolClass = null;
        FileNode fileNode = null;
        ASProjectScope projectScope = getProject().getScope();
       
        try
        {
            FXGSyntaxTreeRequestResult syntaxTreeResult = (FXGSyntaxTreeRequestResult)getSyntaxTreeRequest().get();
            IFXGNode tree = syntaxTreeResult.getRootNode();

            FlexFXG2SWFTranscoder transcoder = new FlexFXG2SWFTranscoder(getProject());          
            transcoder.setResourceResolver(new FXGFileResolver(FilenameUtils.getFullPath(getRootFileSpecification().getPath())));         

            symbolClass = transcoder.transcode(tree,
                    Multiname.getPackageNameForQName(qname), Multiname.getBaseNameForQName(qname), extraTags, problems);

           
            //Add dependencies to the classes required by the FXG processed by this compilation unit
            for (ITypeDefinition definition : transcoder.getDependencies())
            {
                getProject().addDependency(this, projectScope.getCompilationUnitForDefinition(definition),
                        DependencyType.EXPRESSION, definition.getQualifiedName());
            }

            StringBuilder sb = new StringBuilder(symbolClass.getGeneratedSource());
            if (symbolClass.getAdditionalSymbolClasses() != null)
            {
                for (FXGSymbolClass symbol : symbolClass.getAdditionalSymbolClasses())
                {
                    sb.append(symbol.getGeneratedSource());
                }
            }

            IFileSpecification virtualSymbolSource = new GeneratedSourceFileSpecfication(qname, sb.toString());
            fileNode = ASParser.parseFile(virtualSymbolSource, getProject().getWorkspace());
            fileNode.runPostProcess(EnumSet.of(PostProcessStep.POPULATE_SCOPE));

            projectScope.addScopeForCompilationUnit(this, fileNode.getFileScope());
           
            updateEmbedCompilationUnitDependencies(fileNode.getEmbedNodes(), problems);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            problems.add(new InternalCompilerProblem2(getAbsoluteFilename(), e, SUB_SYSTEM));
        }
        finally
        {
            stopProfile(Operation.GET_SEMANTIC_PROBLEMS);
        }
       
        return new FXGOutgoingDependenciesResult(fileNode, symbolClass, extraTags, problems);
    }
   
    /**
     * Semantic problems result for FXG files.
     */
    private static class FXGOutgoingDependenciesResult implements IOutgoingDependenciesRequestResult
    {

        private Collection<ICompilerProblem> problems;
        protected FileNode fileNode;
        protected FXGSymbolClass symbolClass;
        protected Map<ITag, ITag> extraTags;
       
        public FXGOutgoingDependenciesResult (FileNode fileNode, FXGSymbolClass symbolClass,
                                              Map<ITag, ITag> extraTags, Collection<ICompilerProblem> problems)
        {
            this.problems = problems;
            this.fileNode = fileNode;
            this.symbolClass = symbolClass;
            this.extraTags = extraTags;
        }
       
        @Override
        public ICompilerProblem[] getProblems()
        {
            return problems.toArray(new ICompilerProblem[0]);
        }
      
    }
   
    @Override
    protected IABCBytesRequestResult handleABCBytesRequest() throws InterruptedException
    {
        FXGOutgoingDependenciesResult semanticResults = (FXGOutgoingDependenciesResult) getOutgoingDependenciesRequest().get();
       
        startProfile(Operation.GET_ABC_BYTES);
        try
        {
            byte abc[] = CodeGeneratorManager.getCodeGenerator().generate(getFilenameNoPath(), semanticResults.fileNode, getProject()).getABCBytes();

            return new ABCBytesRequestResult(abc);
        }
        finally
        {
            stopProfile(Operation.GET_ABC_BYTES);
        }
    }
   
    @Override
    protected ISWFTagsRequestResult handleSWFTagsRequest() throws InterruptedException
    {
        FXGOutgoingDependenciesResult semanticResults = (FXGOutgoingDependenciesResult) getOutgoingDependenciesRequest().get();
        IABCBytesRequestResult byteResult = getABCBytesRequest().get();
       
        startProfile(Operation.GET_SWF_TAGS);
       
        final FXGSymbolClass symbolClass = semanticResults.symbolClass;
        final Map<ITag, ITag> extraTags = semanticResults.extraTags;
        final Collection<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();      
        final DoABCTag abcTag = new DoABCTag();
       
        try
        {  
            abcTag.setName(qname);
            abcTag.setABCData(byteResult.getABCBytes());
        }
        catch (Exception e)
        {
            ICompilerProblem problem = new InternalCompilerProblem2(getRootFileSpecification().getPath(), e, SUB_SYSTEM);
            problems.add(problem);
        }
        finally
        {
            stopProfile(Operation.GET_SWF_TAGS);
        }
       
        return new ISWFTagsRequestResult()
        {
            @Override
            public boolean addToFrame(SWFFrame frame)
            {  
                ICharacterTag symbolTag = symbolClass.getSymbol();
               
                List<ITag> symbolTags = TagSorter.sortFullGraph(Collections.singletonList((ITag)symbolTag));
               
                for (ITag tag : symbolTags)
                {
                    frame.addTag(tag);
                    if (extraTags.containsKey(tag))
                    {
                        frame.addTag(extraTags.get(tag));
                    }
                }
               
                if (symbolClass.getAdditionalSymbolClasses() != null )
                {
                    for (FXGSymbolClass symbol : symbolClass.getAdditionalSymbolClasses())
                    {
                        frame.defineSymbol(symbol.getSymbol(), symbol.getQualifiedClassName());
                    }
                }

                frame.addTag(abcTag);
                frame.defineSymbol(symbolClass.getSymbol(), qname);
               
                return true;
            }
           
            @Override
            public ICompilerProblem[] getProblems()
            {
                return problems.toArray(new ICompilerProblem[0]);
            }

            @Override
            public String getDoABCTagName()
            {
                return abcTag.getName();
            }
           
        };
    }
   
    /**
     * Creates an empty FileScope for purposes of definition reporting
     *
     * @return a {@link FXGFileScope} with a class definition for the FXG source
     */
    private FXGFileScope createFileScope()
    {
        FXGFileScope fileScope = new FXGFileScope(this, getAbsoluteFilename());

        String packageName = Multiname.getPackageNameForQName(qname);
        PackageScope packageScope = new PackageScope(fileScope, packageName);
        packageScope.setContainingScope(fileScope);

        PackageDefinition packageDefinition = new PackageDefinition(packageName);
        packageDefinition.setContainedScope(packageScope);

        fileScope.addDefinition(packageDefinition);

        Multiname mname = Multiname.crackDottedQName(getProject(), qname);
        INamespaceDefinition packageNS = Iterables.getOnlyElement(mname.getNamespaceSet());

        ClassDefinition classDefinition = new ClassDefinition(mname.getBaseName(), (INamespaceReference)packageNS);
        IReference baseClass = ReferenceFactory.packageQualifiedReference(getProject().getWorkspace(), fxgBaseClassName);
        classDefinition.setBaseClassReference(baseClass);

        TypeScope classScope = new TypeScope(packageScope, classDefinition);
        classScope.setContainingDefinition(classDefinition);
        classDefinition.setContainedScope(classScope);
        classDefinition.setupThisAndSuper();

        packageScope.addDefinition(classDefinition);

        return fileScope;
    }
}
TOP

Related Classes of org.apache.flex.compiler.internal.units.FXGCompilationUnit

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.