| /* |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| |
| package org.apache.flex.compiler.internal.driver; |
| |
| import java.io.IOException; |
| import java.util.Collection; |
| |
| import org.apache.flex.compiler.common.DependencyType; |
| import org.apache.flex.compiler.definitions.IDefinition; |
| import org.apache.flex.compiler.internal.as.codegen.JSGeneratingReducer; |
| import org.apache.flex.compiler.internal.as.codegen.JSGenerator; |
| import org.apache.flex.compiler.internal.as.codegen.JSSharedData; |
| import org.apache.flex.compiler.internal.projects.CompilerProject; |
| import org.apache.flex.compiler.internal.projects.DefinitionPriority; |
| import org.apache.flex.compiler.internal.scopes.ASProjectScope; |
| import org.apache.flex.compiler.internal.units.ASCompilationUnit; |
| import org.apache.flex.compiler.problems.ICompilerProblem; |
| 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.requests.IABCBytesRequestResult; |
| import org.apache.flex.compiler.units.requests.IOutgoingDependenciesRequestResult; |
| import org.apache.flex.compiler.units.requests.ISyntaxTreeRequestResult; |
| |
| /** |
| * JSCompilationUnit is the CompilationUnit for compiling ActionScript source |
| * files to JavasScript. JSCompilationUnit is derived from ASCompilationUnit and |
| * overrides the parts that generate the code. JSCompilationUnit also supports |
| * requests for two-pass compilation (see m_needsSecondPass). |
| * JSSourceFileHandler provides JSCompilationUnit for *.as files. JSDriver |
| * registers JSSourceFileHandler at FlexApplicationProject. This implementation |
| * is part of FalconJS. For more details on FalconJS see |
| * org.apache.flex.compiler.JSDriver |
| */ |
| |
| public class JSCompilationUnit extends ASCompilationUnit |
| { |
| private IABCBytesRequestResult m_abcBytes = null; |
| private Boolean m_needsSecondPass = false; |
| private Boolean m_inCodeGen = false; |
| |
| /** |
| * Create a compilation unit from an ABC file. |
| * |
| * @param project compiler project |
| * @param path ABC file path |
| * @throws IOException error |
| */ |
| public JSCompilationUnit(CompilerProject project, String path) throws IOException |
| { |
| this(project, path, DefinitionPriority.BasePriority.LIBRARY_PATH); |
| } |
| |
| public JSCompilationUnit(CompilerProject project, String path, DefinitionPriority.BasePriority basePriority) |
| { |
| super(project, path, basePriority); |
| } |
| |
| public JSCompilationUnit(CompilerProject project, String path, DefinitionPriority.BasePriority basePriority, String qname) |
| { |
| super(project, path, basePriority, 0, qname); |
| } |
| |
| protected IABCBytesRequestResult _handleABCBytesRequest(Operation buildPhase) throws InterruptedException |
| { |
| // If JSEmitter.needsSecondPass() returns true, JSGenerator.generate() will return null during scanning, |
| // which will result in JSCompilationUnit::handleSemanticProblemsRequest not caching any abcBytes for |
| // handleABCBytesRequest. The net result is that JSGenerator.generate() will be called again in handleABCBytesRequest. |
| // This mechanic will ensure selective two-pass compilation. |
| if (m_abcBytes != null && |
| !JSSharedData.instance.hasSymbols() && // Symbol support |
| !JSSharedData.instance.hasAnyClassInit()) // support for class inits |
| return m_abcBytes; |
| |
| JSGenerator jsGenerator = new JSGenerator(); |
| jsGenerator.m_compilationUnit = this; |
| jsGenerator.setBuildPhase(buildPhase); |
| |
| // Need to force the file scope request to happen first to get the ASFileScope |
| // for this compilation unit registered with the project. |
| // ** TODO this is a hack! |
| getFileScopeRequest().get(); |
| |
| // This is also a hack! If there are embed directives, need to ensure |
| // semantic pass has finished, as that is what will generate the embed classes |
| // which are needed by codegen |
| if (buildPhase != Operation.GET_SEMANTIC_PROBLEMS) |
| { |
| // AJH this was deadlocking as getOutgoingDependencies calls handleABCBytes |
| if (buildPhase != Operation.GET_ABC_BYTES) |
| getOutgoingDependenciesRequest().get(); |
| } |
| |
| final ISyntaxTreeRequestResult fsr = getSyntaxTreeRequest().get(); |
| final IASNode rootNode = fsr.getAST(); |
| |
| startProfile(buildPhase); |
| IABCBytesRequestResult result = jsGenerator.generate(getFilenameNoPath(), rootNode, this.getProject()); |
| stopProfile(buildPhase); |
| |
| m_needsSecondPass = jsGenerator.needsSecondPass(); |
| |
| return result; |
| } |
| |
| @Override |
| protected IABCBytesRequestResult handleABCBytesRequest() throws InterruptedException |
| { |
| final IABCBytesRequestResult result = _handleABCBytesRequest(Operation.GET_ABC_BYTES); |
| |
| /* |
| * // explicitly reference all classes this class depends on if( |
| * result.getProblems() == null || result.getProblems().length == 0 ) { |
| * final String code = new String( result.getABCBytes() ); if( |
| * code.contains(JSSharedData.REQUIRED_TAG_MARKER) ) { final |
| * ICompilationUnit cu = this; final Set<ICompilationUnit> deps = new |
| * HashSet<ICompilationUnit>(); deps.addAll( |
| * getProject().getDependencies(cu) ); if( !deps.isEmpty() ) { String |
| * depNames = ""; Boolean separator = false; final List<IDefinition> |
| * defs = MXMLJSC.getClassDefinitions( cu ); for( IDefinition def: defs |
| * ) { if( def instanceof ClassDefinition ) { final String defName = |
| * JSGeneratingReducer.createFullNameFromDefinition(def); if( defName != |
| * null && !defName.isEmpty() ) { if( separator ) depNames += ":"; else |
| * separator = true; depNames += defName; } } } |
| * code.replaceFirst(JSSharedData.REQUIRED_TAG_MARKER, depNames); return |
| * new ABCBytesRequestResult(code.getBytes(), result.getProblems()); } } |
| * } |
| */ |
| return result; |
| } |
| |
| @Override |
| protected IOutgoingDependenciesRequestResult handleOutgoingDependenciesRequest() throws InterruptedException |
| { |
| // Every CU is dependent on the class glue, which is implemented in browser.adobe. |
| // Add dependency from this JSCompilationUnit to browser.adobe's JSCompilationUnit. |
| addDependency(JSSharedData.JS_FRAMEWORK_NAME, DependencyType.INHERITANCE); |
| addDependency(JSSharedData.FRAMEWORK_CLASS, DependencyType.INHERITANCE); |
| |
| IOutgoingDependenciesRequestResult result = super.handleOutgoingDependenciesRequest(); |
| |
| // SWFTarget::startBuildAndFindAllCompilationUnits() is called by SWFTarget::collectProblems(), which is called by SWFTarget::addToSWF() in JSDriver::main(). |
| // This is our first pass. jsGenerator.generate() will return null if JSGeneratingReducer.getMember |
| // If JSEmitter.needsSecondPass() returns true, JSGenerator.generate() will return null during scanning, |
| // which will result in JSCompilationUnit::handleSemanticProblemsRequest not caching any abcBytes for |
| // handleABCBytesRequest. The net result is that JSGenerator.generate() will be called again in handleABCBytesRequest. |
| // This mechanic will ensure selective two-pass compilation. |
| if (result.getProblems().length == 0) |
| { |
| m_needsSecondPass = false; |
| m_abcBytes = _handleABCBytesRequest(Operation.GET_SEMANTIC_PROBLEMS); |
| if (m_needsSecondPass) |
| m_abcBytes = null; |
| } |
| |
| return result; |
| } |
| |
| public Boolean addDependency(String className, DependencyType dt) |
| { |
| if (JSGeneratingReducer.isReservedDataType(className)) |
| return false; |
| |
| final ICompilationUnit fromCU = this; |
| final CompilerProject compilerProject = this.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); |
| |
| return true; |
| } |
| |
| @Override |
| public void startBuildAsync(TargetType targetType) |
| { |
| // super.startBuildAsync(targetType); |
| |
| getSyntaxTreeRequest(); |
| getFileScopeRequest(); |
| getOutgoingDependenciesRequest(); |
| |
| // scanning and code generating phases need to be separated |
| // in order to create two distinct passes for m_needSecondPass. |
| if (m_inCodeGen) |
| { |
| getABCBytesRequest(); |
| getSWFTagsRequest(); |
| } |
| } |
| |
| @Override |
| public void waitForBuildFinish(final Collection<ICompilerProblem> problems, TargetType targetType) throws InterruptedException |
| { |
| m_inCodeGen = true; |
| super.waitForBuildFinish(problems, targetType); |
| m_inCodeGen = false; |
| /* |
| * assert problems != null : |
| * "Expected 'problems'. Do not ignore problems."; //$NON-NLS-1$ |
| * Collections.addAll(problems, |
| * getSyntaxTreeRequest().get().getProblems()); |
| * Collections.addAll(problems, |
| * getFileScopeRequest().get().getProblems()); |
| * Collections.addAll(problems, |
| * getSemanticProblemsRequest().get().getProblems()); |
| * Collections.addAll(problems, |
| * getABCBytesRequest().get().getProblems()); |
| * Collections.addAll(problems, |
| * getSWFTagsRequest().get().getProblems()); |
| */ |
| } |
| |
| } |