Preliminary addition of VF2JS publishing classes Right now, they're plain copies. I need to rewrite the dependency handling in order to get the GCC to accept the VF2JS application JS.
Signed-off-by: Erik de Bruin <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/667f93e7 Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/667f93e7 Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/667f93e7 Branch: refs/heads/develop Commit: 667f93e7db9ba508dddf432ab3f0b64d6184d2db Parents: 5eee1b1 Author: Erik de Bruin <[email protected]> Authored: Fri Oct 31 17:42:41 2014 +0100 Committer: Erik de Bruin <[email protected]> Committed: Fri Oct 31 17:44:04 2014 +0100 ---------------------------------------------------------------------- .../internal/graph/VF2JSDepsWriter.java | 403 +++++++++++++++++++ .../utils/VF2JSClosureCompilerWrapper.java | 226 +++++++++++ 2 files changed, 629 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/667f93e7/compiler.jx/src/org/apache/flex/compiler/internal/graph/VF2JSDepsWriter.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/graph/VF2JSDepsWriter.java b/compiler.jx/src/org/apache/flex/compiler/internal/graph/VF2JSDepsWriter.java new file mode 100644 index 0000000..82251e7 --- /dev/null +++ b/compiler.jx/src/org/apache/flex/compiler/internal/graph/VF2JSDepsWriter.java @@ -0,0 +1,403 @@ +/* + * + * 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.graph; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Scanner; + +import org.apache.commons.io.FileUtils; +import org.apache.flex.compiler.clients.problems.ProblemQuery; +import org.apache.flex.compiler.internal.driver.js.goog.JSGoogConfiguration; +import org.apache.flex.compiler.problems.FileNotFoundProblem; + +import com.google.common.io.Files; + +public class VF2JSDepsWriter { + + public VF2JSDepsWriter(File outputFolder, String mainClassName, JSGoogConfiguration config) + { + this.outputFolderPath = outputFolder.getAbsolutePath(); + this.mainName = mainClassName; + otherPaths = config.getSDKJSLib(); + } + + private ProblemQuery problems; + private String outputFolderPath; + private String mainName; + private List<String> otherPaths; + private boolean problemsFound = false; + + private HashMap<String,GoogDep> depMap = new HashMap<String,GoogDep>(); + + public ArrayList<String> getListOfFiles() throws InterruptedException + { + buildDB(); + ArrayList<GoogDep> dps = sort(mainName); + ArrayList<String> files = new ArrayList<String>(); + for (GoogDep gd : dps) + { + files.add(gd.filePath); + } + return files; + } + + public boolean generateDeps(ProblemQuery problems, StringBuilder depsFileData) throws InterruptedException, FileNotFoundException + { + problemsFound = false; + this.problems = problems; + buildDB(); + ArrayList<GoogDep> dps = sort(mainName); + String outString = "// generated by FalconJS" + "\n"; + int n = dps.size(); + for (int i = n - 1; i >= 0; i--) + { + GoogDep gd = dps.get(i); + if (!isGoogClass(gd.className)) + { + String s = "goog.addDependency('"; + s += relativePath(gd.filePath); + s += "', ['"; + s += gd.className; + s += "'], ["; + s += getDependencies(gd.deps); + s += "]);\n"; + outString += s; + } + } + depsFileData.append(outString); + return !problemsFound; + } + + private boolean isGoogClass(String className) + { + return className.startsWith("goog."); + } + + private void buildDB() + { + addDeps(mainName); + } + + public ArrayList<String> filePathsInOrder = new ArrayList<String>(); + + public ArrayList<String> additionalHTML = new ArrayList<String>(); + + private HashMap<String, GoogDep> visited = new HashMap<String, GoogDep>(); + + private ArrayList<GoogDep> sort(String rootClassName) + { + ArrayList<GoogDep> arr = new ArrayList<GoogDep>(); + GoogDep current = depMap.get(rootClassName); + sortFunction(current, arr); + return arr; + } + + private void sortFunction(GoogDep current, ArrayList<GoogDep> arr) + { + visited.put(current.className, current); + + filePathsInOrder.add(current.filePath); + System.out.println("Dependencies calculated for '" + current.filePath + "'"); + + ArrayList<String> deps = current.deps; + for (String className : deps) + { + if (!visited.containsKey(className) && !isGoogClass(className)) + { + GoogDep gd = depMap.get(className); + sortFunction(gd, arr); + } + } + arr.add(current); + } + + private void addDeps(String className) + { + if (depMap.containsKey(className) || isGoogClass(className)) + return; + + // build goog dependency list + GoogDep gd = new GoogDep(); + gd.className = className; + gd.filePath = getFilePath(className); + depMap.put(gd.className, gd); + ArrayList<String> deps = getDirectDependencies(gd.filePath); + + gd.deps = new ArrayList<String>(); + ArrayList<String> circulars = new ArrayList<String>(); + for (String dep : deps) + { + if (depMap.containsKey(dep) && !isGoogClass(dep)) + { + circulars.add(dep); + continue; + } + gd.deps.add(dep); + } + for (String dep : deps) + { + addDeps(dep); + } + if (circulars.size() > 0) + { + // remove requires that would cause circularity + try + { + List<String> fileLines = Files.readLines(new File(gd.filePath), Charset.defaultCharset()); + ArrayList<String> finalLines = new ArrayList<String>(); + + String inherits = getBaseClass(fileLines, className); + + for (String line : fileLines) + { + int c = line.indexOf("goog.require"); + if (c > -1) + { + int c2 = line.indexOf(")"); + String s = line.substring(c + 14, c2 - 1); + if (circulars.contains(s) && !s.equals(inherits)) + continue; + } + finalLines.add(line); + } + File file = new File(gd.filePath); + PrintWriter out = new PrintWriter(new FileWriter(file)); + for (String s : finalLines) + { + out.println(s); + } + out.close(); + + } + catch (IOException e) + { + e.printStackTrace(); + } + + } + } + + String getBaseClass(List<String> lines, String className) + { + int n = lines.size(); + for (int i = 0; i < n; i++) + { + String line = lines.get(i); + int c2; + int c = line.indexOf("goog.inherits"); + if (c > -1) + { + String inheritLine = ""; + while (true) + { + inheritLine += line; + c2 = line.indexOf(")"); + if (c2 > -1) + break; + else + { + i++; + line = lines.get(i); + } + } + c = inheritLine.indexOf(","); + c2 = inheritLine.indexOf(")"); + return inheritLine.substring(c + 1, c2).trim(); + } + } + return null; + } + + String getFilePath(String className) + { + String fn; + File destFile; + File f; + + String classPath = className.replace(".", File.separator); + + fn = outputFolderPath + File.separator + classPath + ".js"; + f = new File(fn); + if (f.exists()) + { + return fn; + } + + for (String otherPath : otherPaths) + { + fn = otherPath + File.separator + classPath + ".js"; + f = new File(fn); + if (f.exists()) + { + fn = outputFolderPath + File.separator + classPath + ".js"; + destFile = new File(fn); + // copy source to output + try { + FileUtils.copyFile(f, destFile); + + // (erikdebruin) copy class assets files + if (className.indexOf("org.apache.flex") > -1) + { + File assetsDir = new File(f.getParentFile(), "assets"); + if (assetsDir.exists()) + { + String nameOfClass = className.substring(className.lastIndexOf('.') + 1); + + File[] assetsList = assetsDir.listFiles(); + for (int i = 0; i < assetsList.length; i++) + { + File assetFile = assetsList[i]; + String assetFileName = assetFile.getName(); + + if (assetFile.isFile() && assetFileName.indexOf(nameOfClass) == 0) + { + String pathOfClass = ""; + pathOfClass = className.substring(0, className.lastIndexOf('.')); + pathOfClass = pathOfClass.replace(".", File.separator); + + destFile = new File(outputFolderPath + + File.separator + pathOfClass + + File.separator + "assets" + + File.separator + assetFileName); + FileUtils.copyFile(assetFile, destFile); + + destFile = new File(outputFolderPath.replace("js-debug", "js-release") + + File.separator + pathOfClass + + File.separator + "assets" + + File.separator + assetFileName); + FileUtils.copyFile(assetFile, destFile); + + System.out.println("Copied assets of the '" + nameOfClass + "' class"); + } + } + } + } + } catch (IOException e) { + System.out.println("Error copying file for class: " + className); + } + return fn; + } + } + + System.out.println("Could not find file for class: " + className); + problems.add(new FileNotFoundProblem(className)); + problemsFound = true; + return ""; + } + + private ArrayList<String> getDirectDependencies(String fn) + { + ArrayList<String> deps = new ArrayList<String>(); + + FileInputStream fis; + try { + fis = new FileInputStream(fn); + Scanner scanner = new Scanner(fis, "UTF-8"); + boolean inInjectHTML = false; + while (scanner.hasNextLine()) + { + String s = scanner.nextLine(); + if (s.indexOf("goog.inherits") > -1) + break; + if (inInjectHTML) + { + int c = s.indexOf("</inject_html>"); + if (c > -1) + { + inInjectHTML = false; + continue; + } + } + if (inInjectHTML) + { + additionalHTML.add(s); + continue; + } + int c = s.indexOf("goog.require"); + if (c > -1) + { + int c2 = s.indexOf(")"); + s = s.substring(c + 14, c2 - 1); + deps.add(s); + } + c = s.indexOf("<inject_html>"); + if (c > -1) + { + inInjectHTML = true; + } + } + scanner.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + return deps; + } + + private String getDependencies(ArrayList<String> deps) + { + String s = ""; + for (String dep : deps) + { + if (s.length() > 0) + { + s += ", "; + } + s += "'" + dep + "'"; + } + return s; + } + + String relativePath(String path) + { + if (path.indexOf(outputFolderPath) == 0) + { + path = path.replace(outputFolderPath, "../../.."); + } + else + { + for (String otherPath : otherPaths) + { + if (path.indexOf(otherPath) == 0) + { + path = path.replace(otherPath, "../../.."); + + } + } + } + // paths are actually URIs and always have forward slashes + path = path.replace('\\', '/'); + return path; + } + private class GoogDep + { + public String filePath; + public String className; + public ArrayList<String> deps; + + } +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/667f93e7/compiler.jx/src/org/apache/flex/compiler/utils/VF2JSClosureCompilerWrapper.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/utils/VF2JSClosureCompilerWrapper.java b/compiler.jx/src/org/apache/flex/compiler/utils/VF2JSClosureCompilerWrapper.java new file mode 100644 index 0000000..9fdf8d3 --- /dev/null +++ b/compiler.jx/src/org/apache/flex/compiler/utils/VF2JSClosureCompilerWrapper.java @@ -0,0 +1,226 @@ +/* + * + * 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.utils; + +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; + +import com.google.javascript.jscomp.CheckLevel; +import com.google.javascript.jscomp.CommandLineRunner; +import com.google.javascript.jscomp.CompilationLevel; +import com.google.javascript.jscomp.Compiler; +import com.google.javascript.jscomp.CompilerOptions; +import com.google.javascript.jscomp.CompilerOptions.LanguageMode; +import com.google.javascript.jscomp.DiagnosticGroups; +import com.google.javascript.jscomp.SourceFile; +import com.google.javascript.jscomp.SourceMap; +import com.google.javascript.jscomp.WarningLevel; +import com.google.javascript.rhino.Node; +import com.google.javascript.rhino.Token; + +public class VF2JSClosureCompilerWrapper +{ + + public VF2JSClosureCompilerWrapper() + { + Compiler.setLoggingLevel(Level.ALL); + + compiler_ = new Compiler(); + + options_ = new CompilerOptions(); + initOptions(); + + jsExternsFiles_ = new ArrayList<SourceFile>(); + initExterns(); + + jsSourceFiles_ = new ArrayList<SourceFile>(); + } + + private Compiler compiler_; + private CompilerOptions options_; + private List<SourceFile> jsExternsFiles_; + private List<SourceFile> jsSourceFiles_; + + public String targetFilePath; + + public void addJSExternsFile(String fileName) + { + addJSExternsFile(SourceFile.fromFile(fileName)); + } + + public void addJSExternsFile(SourceFile file) + { + jsExternsFiles_.add(file); + } + + public void addJSSourceFile(String fileName) + { + jsSourceFiles_.add(SourceFile.fromFile(fileName)); + } + + public void compile() + { + compiler_.compile(jsExternsFiles_, jsSourceFiles_, options_); + + try + { + FileWriter targetFile = new FileWriter(targetFilePath); + targetFile.write(compiler_.toSource()); + targetFile.close(); + + FileWriter sourceMapFile = new FileWriter(options_.sourceMapOutputPath); + compiler_.getSourceMap().appendTo(sourceMapFile, ""); + sourceMapFile.close(); + } + catch (IOException error) + { + System.out.println(error); + } + } + + private void initExterns() + { + try + { + List<SourceFile> defaultExterns = CommandLineRunner.getDefaultExterns(); + for (SourceFile defaultExtern : defaultExterns) + { + this.addJSExternsFile(defaultExtern); + } + } + catch (IOException error) + { + System.out.println(error); + } + } + + private void initOptions() + { + CompilationLevel.ADVANCED_OPTIMIZATIONS.setOptionsForCompilationLevel( + options_); + + WarningLevel.VERBOSE.setOptionsForWarningLevel(options_); + + String[] asdocTags = new String[] {"productversion", + "playerversion", "langversion", "copy"}; + options_.setExtraAnnotationNames(Arrays.asList(asdocTags)); + } + + public void setOptions(String sourceMapPath, boolean useStrictPublishing) + { + if (useStrictPublishing) + { + // (erikdebruin) set compiler flags to 'strictest' to allow maximum + // code optimization + + options_.getDefineReplacements().put( + "goog.DEBUG", new Node(Token.TRUE)); + + // ToDo (erikdebruin): re-evaluate this option on future GC release + options_.setLanguageIn(LanguageMode.ECMASCRIPT6_STRICT); + + options_.setPreferSingleQuotes(true); + + options_.setFoldConstants(true); + options_.setDeadAssignmentElimination(true); + options_.setInlineConstantVars(true); + options_.setInlineFunctions(true); + options_.setInlineLocalFunctions(true); + options_.setCrossModuleCodeMotion(true); + options_.setCoalesceVariableNames(true); + options_.setCrossModuleMethodMotion(true); + options_.setInlineGetters(true); + options_.setInlineVariables(true); + options_.setSmartNameRemoval(true); + options_.setRemoveDeadCode(true); + options_.setCheckMissingReturn(CheckLevel.WARNING); + options_.setExtractPrototypeMemberDeclarations(true); + options_.setRemoveUnusedPrototypeProperties(true); + options_.setRemoveUnusedPrototypePropertiesInExterns(true); + options_.setRemoveUnusedClassProperties(true); + options_.setRemoveUnusedVars(true); + options_.setRemoveUnusedLocalVars(true); + options_.setAliasExternals(true); + options_.setCollapseVariableDeclarations(true); + options_.setCollapseAnonymousFunctions(true); + options_.setAliasAllStrings(true); + options_.setConvertToDottedProperties(true); + options_.setRewriteFunctionExpressions(true); + options_.setOptimizeParameters(true); + options_.setOptimizeReturns(true); + options_.setOptimizeCalls(true); + options_.setOptimizeArgumentsArray(true); + + // warnings already activated in previous incarnation + options_.setWarningLevel(DiagnosticGroups.ACCESS_CONTROLS, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.CONST, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.CONSTANT_PROPERTY, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.STRICT_MODULE_DEP_CHECK, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.VISIBILITY, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.DEPRECATED, CheckLevel.OFF); // OFF + + // the 'full' set of warnings + options_.setWarningLevel(DiagnosticGroups.AMBIGUOUS_FUNCTION_DECL, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.CHECK_EVENTFUL_OBJECT_DISPOSAL, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.CHECK_PROVIDES, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.CHECK_REGEXP, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.CHECK_STRUCT_DICT_INHERITANCE, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.CHECK_TYPES, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.CHECK_USELESS_CODE, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.CHECK_VARIABLES, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.DEBUGGER_STATEMENT_PRESENT, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.DUPLICATE_MESSAGE, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.DUPLICATE_VARS, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.ES3, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.ES5_STRICT, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.EXTERNS_VALIDATION, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.GLOBAL_THIS, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.FILEOVERVIEW_JSDOC, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.INTERNET_EXPLORER_CHECKS, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.INVALID_CASTS, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.LINT_CHECKS, CheckLevel.OFF); // OFF + options_.setWarningLevel(DiagnosticGroups.MISPLACED_TYPE_ANNOTATION, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.MISSING_PROPERTIES, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.MISSING_PROVIDE, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.MISSING_REQUIRE, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.MISSING_RETURN, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.NEW_CHECK_TYPES, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.NON_STANDARD_JSDOC, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.REPORT_UNKNOWN_TYPES, CheckLevel.OFF); // OFF + options_.setWarningLevel(DiagnosticGroups.SUSPICIOUS_CODE, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.TWEAKS, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.TYPE_INVALIDATION, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.UNDEFINED_NAMES, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.UNDEFINED_VARIABLES, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.UNKNOWN_DEFINES, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.UNNECESSARY_CASTS, CheckLevel.OFF); // OFF + options_.setWarningLevel(DiagnosticGroups.USE_OF_GOOG_BASE, CheckLevel.WARNING); + options_.setWarningLevel(DiagnosticGroups.VIOLATED_MODULE_DEP, CheckLevel.WARNING); + } + + options_.sourceMapFormat = SourceMap.Format.V3; + options_.sourceMapOutputPath = sourceMapPath + ".map"; + } + +}
