You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by er...@apache.org on 2014/07/31 14:20:24 UTC
[1/4] The first VF2JS specific compilation classes.
Repository: flex-falcon
Updated Branches:
refs/heads/VF2JS e5d07f570 -> 6ddfe4b2a
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/6ddfe4b2/compiler.jx/src/org/apache/flex/compiler/internal/codegen/mxml/vf2js/MXMLVF2JSPublisher.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/mxml/vf2js/MXMLVF2JSPublisher.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/mxml/vf2js/MXMLVF2JSPublisher.java
new file mode 100644
index 0000000..4a0f6cc
--- /dev/null
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/mxml/vf2js/MXMLVF2JSPublisher.java
@@ -0,0 +1,505 @@
+/*
+ *
+ * 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.codegen.mxml.vf2js;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Scanner;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.filefilter.DirectoryFileFilter;
+import org.apache.commons.io.filefilter.FileFileFilter;
+import org.apache.commons.io.filefilter.FileFilterUtils;
+import org.apache.commons.io.filefilter.IOFileFilter;
+import org.apache.commons.io.filefilter.RegexFileFilter;
+import org.apache.flex.compiler.clients.problems.ProblemQuery;
+import org.apache.flex.compiler.codegen.js.IJSPublisher;
+import org.apache.flex.compiler.config.Configuration;
+import org.apache.flex.compiler.internal.codegen.js.JSSharedData;
+import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogPublisher;
+import org.apache.flex.compiler.internal.driver.js.goog.JSGoogConfiguration;
+import org.apache.flex.compiler.internal.graph.GoogDepsWriter;
+import org.apache.flex.compiler.internal.projects.FlexJSProject;
+import org.apache.flex.compiler.utils.JSClosureCompilerWrapper;
+
+public class MXMLVF2JSPublisher extends JSGoogPublisher implements
+ IJSPublisher
+{
+
+ public static final String FLEXJS_OUTPUT_DIR_NAME = "bin";
+ public static final String FLEXJS_INTERMEDIATE_DIR_NAME = "js-debug";
+ public static final String FLEXJS_RELEASE_DIR_NAME = "js-release";
+
+ class DependencyRecord
+ {
+ String path;
+ String deps;
+ String line;
+ int lineNumber;
+ }
+
+ class DependencyLineComparator implements Comparator<DependencyRecord> {
+ @Override
+ public int compare(DependencyRecord o1, DependencyRecord o2) {
+ return new Integer(o1.lineNumber).compareTo(o2.lineNumber);
+ }
+ }
+
+ public MXMLVF2JSPublisher(Configuration config, FlexJSProject project)
+ {
+ super(config);
+
+ this.isMarmotinniRun = ((JSGoogConfiguration) configuration)
+ .getMarmotinni() != null;
+ this.outputPathParameter = ((JSGoogConfiguration) configuration)
+ .getOutput();
+ this.useStrictPublishing = ((JSGoogConfiguration) configuration)
+ .getStrictPublish();
+
+ this.project = project;
+ }
+
+ private FlexJSProject project;
+
+ private boolean isMarmotinniRun;
+ private String outputPathParameter;
+ private boolean useStrictPublishing;
+
+ @Override
+ public File getOutputFolder()
+ {
+ // (erikdebruin) - If there is a -marmotinni switch, we want
+ // the output redirected to the directory it specifies.
+ // - If there is an -output switch, use that path as the
+ // output parent folder.
+ if (isMarmotinniRun)
+ {
+ outputParentFolder = new File(
+ ((JSGoogConfiguration) configuration).getMarmotinni());
+ }
+ else if (outputPathParameter != null)
+ {
+ outputParentFolder = new File(outputPathParameter);
+ // FB usually specified -output <project-path>/bin-release/app.swf
+ if (outputPathParameter.contains(".swf"))
+ outputParentFolder = outputParentFolder.getParentFile().getParentFile();
+ }
+ else
+ {
+ outputParentFolder = new File(
+ configuration.getTargetFileDirectory()).getParentFile();
+ }
+
+ outputParentFolder = new File(outputParentFolder,
+ FLEXJS_OUTPUT_DIR_NAME);
+
+ outputFolder = new File(outputParentFolder, File.separator
+ + FLEXJS_INTERMEDIATE_DIR_NAME);
+
+ // (erikdebruin) Marmotinni handles file management, so we
+ // bypass the setup.
+ if (!isMarmotinniRun)
+ setupOutputFolder();
+
+ return outputFolder;
+ }
+
+ @Override
+ public boolean publish(ProblemQuery problems) throws IOException
+ {
+ boolean ok = true;
+ boolean subsetGoog = true;
+
+ final String intermediateDirPath = outputFolder.getPath();
+ final File intermediateDir = new File(intermediateDirPath);
+ File srcDir = new File(configuration.getTargetFile());
+ srcDir = srcDir.getParentFile();
+
+ final String projectName = FilenameUtils.getBaseName(configuration
+ .getTargetFile());
+ final String outputFileName = projectName
+ + "." + JSSharedData.OUTPUT_EXTENSION;
+
+ File releaseDir = new File(outputParentFolder, FLEXJS_RELEASE_DIR_NAME);
+ final String releaseDirPath = releaseDir.getPath();
+
+ if (!isMarmotinniRun)
+ {
+ if (releaseDir.exists())
+ org.apache.commons.io.FileUtils.deleteQuietly(releaseDir);
+
+ releaseDir.mkdirs();
+ }
+
+ final String closureLibDirPath = ((JSGoogConfiguration) configuration)
+ .getClosureLib();
+ final String closureGoogSrcLibDirPath = closureLibDirPath
+ + "/closure/goog/";
+ final String closureGoogTgtLibDirPath = intermediateDirPath
+ + "/library/closure/goog";
+ final String depsSrcFilePath = intermediateDirPath
+ + "/library/closure/goog/deps.js";
+ final String depsTgtFilePath = intermediateDirPath + "/deps.js";
+ final String projectIntermediateJSFilePath = intermediateDirPath
+ + File.separator + outputFileName;
+ final String projectReleaseJSFilePath = releaseDirPath
+ + File.separator + outputFileName;
+
+ appendExportSymbol(projectIntermediateJSFilePath, projectName);
+ appendEncodedCSS(projectIntermediateJSFilePath, projectName);
+
+ if (!subsetGoog)
+ {
+ // (erikdebruin) We need to leave the 'goog' files and dependencies well
+ // enough alone. We copy the entire library over so the
+ // 'goog' dependencies will resolve without our help.
+ FileUtils.copyDirectory(new File(closureGoogSrcLibDirPath), new File(closureGoogTgtLibDirPath));
+ }
+
+ JSClosureCompilerWrapper compilerWrapper = new JSClosureCompilerWrapper();
+
+ GoogDepsWriter gdw = new GoogDepsWriter(intermediateDir, projectName, (JSGoogConfiguration) configuration);
+ try
+ {
+ StringBuilder depsFileData = new StringBuilder();
+ ok = gdw.generateDeps(problems, depsFileData);
+ if (!subsetGoog)
+ {
+ writeFile(depsTgtFilePath, depsFileData.toString(), false);
+ }
+ else
+ {
+ String s = depsFileData.toString();
+ int c = s.indexOf("'goog.");
+ ArrayList<String> googreqs = new ArrayList<String>();
+ while (c != -1)
+ {
+ int c2 = s.indexOf("'", c + 1);
+ String googreq = s.substring(c, c2 + 1);
+ googreqs.add(googreq);
+ c = s.indexOf("'goog.", c2);
+ }
+ HashMap<String, DependencyRecord> defmap = new HashMap<String, DependencyRecord>();
+ // read in goog's deps.js
+ FileInputStream fis = new FileInputStream(closureGoogSrcLibDirPath + "/deps.js");
+ Scanner scanner = new Scanner(fis, "UTF-8");
+ String addDependency = "goog.addDependency('";
+ int currentLine = 0;
+ while (scanner.hasNextLine())
+ {
+ String googline = scanner.nextLine();
+ if (googline.indexOf(addDependency) == 0)
+ {
+ int c1 = googline.indexOf("'", addDependency.length() + 1);
+ String googpath = googline.substring(addDependency.length(), c1);
+ String googdefs = googline.substring(googline.indexOf("[") + 1, googline.indexOf("]"));
+ String googdeps = googline.substring(googline.lastIndexOf("[") + 1, googline.lastIndexOf("]"));
+ String[] thedefs = googdefs.split(",");
+ DependencyRecord deprec = new DependencyRecord();
+ deprec.path = googpath;
+ deprec.deps = googdeps;
+ deprec.line = googline;
+ deprec.lineNumber = currentLine;
+ for (String def : thedefs)
+ {
+ def = def.trim();
+ defmap.put(def, deprec);
+ }
+ }
+ currentLine++;
+ }
+ // (erikdebruin) Prevent 'Resource leak' warning on line 212:
+ scanner.close();
+ ArrayList<DependencyRecord> subsetdeps = new ArrayList<DependencyRecord>();
+ HashMap<String, String> gotgoog = new HashMap<String, String>();
+ for (String req : googreqs)
+ {
+ DependencyRecord deprec = defmap.get(req);
+ // if we've already processed this file, skip
+ if (!gotgoog.containsKey(deprec.path))
+ {
+ gotgoog.put(deprec.path, null);
+ subsetdeps.add(deprec);
+ addDeps(subsetdeps, gotgoog, defmap, deprec.deps);
+ }
+ }
+ // now we should have the subset of files we need in the order needed
+ StringBuilder sb = new StringBuilder();
+ sb.append("goog.addDependency('base.js', ['goog'], []);\n");
+ File file = new File(closureGoogSrcLibDirPath + "/base.js");
+ FileUtils.copyFileToDirectory(file, new File(closureGoogTgtLibDirPath));
+ compilerWrapper.addJSSourceFile(file.getCanonicalPath());
+ Collections.sort(subsetdeps, new DependencyLineComparator());
+ for (DependencyRecord subsetdeprec : subsetdeps)
+ {
+ sb.append(subsetdeprec.line + "\n");
+ }
+ writeFile(depsTgtFilePath, sb.toString() + depsFileData.toString(), false);
+ // copy the required files
+ for (String googfn : gotgoog.keySet())
+ {
+ file = new File(closureGoogSrcLibDirPath + File.separator + googfn);
+ String dir = closureGoogTgtLibDirPath;
+ if (googfn.contains("/"))
+ {
+ dir += File.separator + googfn.substring(0, googfn.lastIndexOf("/"));
+ }
+ FileUtils.copyFileToDirectory(file, new File(dir));
+ compilerWrapper.addJSSourceFile(file.getCanonicalPath());
+ }
+ }
+ }
+ catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ return false;
+ }
+
+ IOFileFilter pngSuffixFilter = FileFilterUtils.and(FileFileFilter.FILE,
+ FileFilterUtils.suffixFileFilter(".png"));
+ IOFileFilter gifSuffixFilter = FileFilterUtils.and(FileFileFilter.FILE,
+ FileFilterUtils.suffixFileFilter(".gif"));
+ IOFileFilter jpgSuffixFilter = FileFilterUtils.and(FileFileFilter.FILE,
+ FileFilterUtils.suffixFileFilter(".jpg"));
+ IOFileFilter assetFiles = FileFilterUtils.or(pngSuffixFilter,
+ jpgSuffixFilter, gifSuffixFilter);
+
+ FileUtils.copyDirectory(srcDir, intermediateDir, assetFiles);
+ FileUtils.copyDirectory(srcDir, releaseDir, assetFiles);
+
+ File srcDeps = new File(depsSrcFilePath);
+
+ writeHTML("intermediate", projectName, intermediateDirPath, gdw.additionalHTML);
+ writeHTML("release", projectName, releaseDirPath, gdw.additionalHTML);
+ writeCSS(projectName, intermediateDirPath);
+ writeCSS(projectName, releaseDirPath);
+
+ if (!subsetGoog)
+ {
+ // (erikdebruin) add 'goog' files
+ Collection<File> files = org.apache.commons.io.FileUtils.listFiles(new File(
+ closureGoogTgtLibDirPath), new RegexFileFilter("^.*(\\.js)"),
+ DirectoryFileFilter.DIRECTORY);
+ for (File file : files)
+ {
+ compilerWrapper.addJSSourceFile(file.getCanonicalPath());
+ }
+ }
+
+ // (erikdebruin) add project files
+ for (String filePath : gdw.filePathsInOrder)
+ {
+ compilerWrapper.addJSSourceFile(
+ new File(filePath).getCanonicalPath());
+ }
+
+ compilerWrapper.setOptions(
+ projectReleaseJSFilePath, useStrictPublishing);
+
+ // (erikdebruin) Include the 'goog' deps to allow the compiler to resolve
+ // dependencies.
+ compilerWrapper.addJSSourceFile(
+ closureGoogSrcLibDirPath + File.separator + "deps.js");
+
+ List<String> externs = ((JSGoogConfiguration)configuration).getExternalJSLib();
+ for (String extern : externs)
+ {
+ compilerWrapper.addJSExternsFile(extern);
+ }
+
+ compilerWrapper.targetFilePath = projectReleaseJSFilePath;
+ compilerWrapper.compile();
+
+ appendSourceMapLocation(projectReleaseJSFilePath, projectName);
+
+ if (!isMarmotinniRun)
+ {
+ String allDeps = "";
+ if (!subsetGoog)
+ allDeps += FileUtils.readFileToString(srcDeps);
+ allDeps += FileUtils.readFileToString(new File(depsTgtFilePath));
+
+ FileUtils.writeStringToFile(srcDeps, allDeps);
+
+ org.apache.commons.io.FileUtils.deleteQuietly(new File(depsTgtFilePath));
+ }
+
+ if (ok)
+ System.out.println("The project '"
+ + projectName
+ + "' has been successfully compiled and optimized.");
+
+ return true;
+ }
+
+ private void addDeps(ArrayList<DependencyRecord> subsetdeps, HashMap<String, String> gotgoog,
+ HashMap<String, DependencyRecord> defmap, String deps)
+ {
+ if (deps.length() == 0)
+ return;
+
+ String[] deplist = deps.split(",");
+ for (String dep : deplist)
+ {
+ dep = dep.trim();
+ DependencyRecord deprec = defmap.get(dep);
+ if (!gotgoog.containsKey(deprec.path))
+ {
+ gotgoog.put(deprec.path, null);
+ // put addDependencyLine in subset file
+ subsetdeps.add(deprec);
+ addDeps(subsetdeps, gotgoog, defmap, deprec.deps);
+ }
+ }
+ }
+
+ private void appendExportSymbol(String path, String projectName)
+ throws IOException
+ {
+ StringBuilder appendString = new StringBuilder();
+ appendString
+ .append("\n\n// Ensures the symbol will be visible after compiler renaming.\n");
+ appendString.append("goog.exportSymbol('");
+ appendString.append(projectName);
+ appendString.append("', ");
+ appendString.append(projectName);
+ appendString.append(");\n");
+ writeFile(path, appendString.toString(), true);
+ }
+
+ private void appendEncodedCSS(String path, String projectName)
+ throws IOException
+ {
+ StringBuilder appendString = new StringBuilder();
+ appendString.append("\n\n");
+ appendString.append(projectName);
+ appendString.append(".prototype.cssData = [");
+ String s = project.cssEncoding;
+ int reqidx = s.indexOf("goog.require");
+ if (reqidx != -1)
+ {
+ String reqs = s.substring(reqidx);
+ s = s.substring(0, reqidx - 1);
+ String fileData = readCode(new File(path));
+ reqidx = fileData.indexOf("goog.require");
+ String after = fileData.substring(reqidx);
+ String before = fileData.substring(0, reqidx - 1);
+ s = before + reqs + after + appendString.toString() + s;
+ writeFile(path, s, false);
+ }
+ else
+ {
+ appendString.append(s);
+ writeFile(path, appendString.toString(), true);
+ }
+ }
+
+ protected String readCode(File file)
+ {
+ String code = "";
+ try
+ {
+ BufferedReader in = new BufferedReader(new InputStreamReader(
+ new FileInputStream(file), "UTF8"));
+
+ String line = in.readLine();
+
+ while (line != null)
+ {
+ code += line + "\n";
+ line = in.readLine();
+ }
+ code = code.substring(0, code.length() - 1);
+
+ in.close();
+ }
+ catch (Exception e)
+ {
+ // nothing to see, move along...
+ }
+
+ return code;
+ }
+
+ private void writeHTML(String type, String projectName, String dirPath, List<String> additionalHTML)
+ throws IOException
+ {
+ StringBuilder htmlFile = new StringBuilder();
+ htmlFile.append("<!DOCTYPE html>\n");
+ htmlFile.append("<html>\n");
+ htmlFile.append("<head>\n");
+ htmlFile.append("\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n");
+ htmlFile.append("\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n");
+ htmlFile.append("\t<link rel=\"stylesheet\" type=\"text/css\" href=\""
+ + projectName + ".css\">\n");
+
+ for (String s : additionalHTML)
+ htmlFile.append(s + "\n");
+
+ if (type == "intermediate")
+ {
+ htmlFile.append("\t<script type=\"text/javascript\" src=\"./library/closure/goog/base.js\"></script>\n");
+ htmlFile.append("\t<script type=\"text/javascript\">\n");
+ htmlFile.append("\t\tgoog.require(\"");
+ htmlFile.append(projectName);
+ htmlFile.append("\");\n");
+ htmlFile.append("\t</script>\n");
+ }
+ else
+ {
+ htmlFile.append("\t<script type=\"text/javascript\" src=\"./");
+ htmlFile.append(projectName);
+ htmlFile.append(".js\"></script>\n");
+ }
+
+ htmlFile.append("</head>\n");
+ htmlFile.append("<body>\n");
+ htmlFile.append("\t<script type=\"text/javascript\">\n");
+ htmlFile.append("\t\tnew ");
+ htmlFile.append(projectName);
+ htmlFile.append("()");
+ htmlFile.append(".start();\n");
+ htmlFile.append("\t</script>\n");
+ htmlFile.append("</body>\n");
+ htmlFile.append("</html>");
+
+ writeFile(dirPath + File.separator + "index.html", htmlFile.toString(),
+ false);
+ }
+
+ private void writeCSS(String projectName, String dirPath)
+ throws IOException
+ {
+ StringBuilder cssFile = new StringBuilder();
+ cssFile.append(project.cssDocument);
+
+ writeFile(dirPath + File.separator + projectName + ".css",
+ cssFile.toString(), false);
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/6ddfe4b2/compiler.jx/src/org/apache/flex/compiler/internal/driver/mxml/vf2js/MXMLVF2JSBackend.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/driver/mxml/vf2js/MXMLVF2JSBackend.java b/compiler.jx/src/org/apache/flex/compiler/internal/driver/mxml/vf2js/MXMLVF2JSBackend.java
new file mode 100644
index 0000000..8d95230
--- /dev/null
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/driver/mxml/vf2js/MXMLVF2JSBackend.java
@@ -0,0 +1,121 @@
+/*
+ *
+ * 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.mxml.vf2js;
+
+import java.io.FilterWriter;
+import java.util.List;
+
+import org.apache.flex.compiler.codegen.IDocEmitter;
+import org.apache.flex.compiler.codegen.as.IASEmitter;
+import org.apache.flex.compiler.codegen.js.IJSEmitter;
+import org.apache.flex.compiler.codegen.js.IJSWriter;
+import org.apache.flex.compiler.codegen.mxml.IMXMLEmitter;
+import org.apache.flex.compiler.config.Configurator;
+import org.apache.flex.compiler.driver.IBackend;
+import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitter;
+import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogDocEmitter;
+import org.apache.flex.compiler.internal.codegen.mxml.MXMLBlockWalker;
+import org.apache.flex.compiler.internal.codegen.mxml.MXMLWriter;
+import org.apache.flex.compiler.internal.codegen.mxml.flexjs.MXMLFlexJSBlockWalker;
+import org.apache.flex.compiler.internal.codegen.mxml.vf2js.MXMLVF2JSEmitter;
+import org.apache.flex.compiler.internal.driver.js.goog.JSGoogConfiguration;
+import org.apache.flex.compiler.internal.driver.mxml.MXMLBackend;
+import org.apache.flex.compiler.internal.targets.FlexJSTarget;
+import org.apache.flex.compiler.internal.targets.JSTarget;
+import org.apache.flex.compiler.internal.visitor.as.ASNodeSwitch;
+import org.apache.flex.compiler.internal.visitor.mxml.MXMLNodeSwitch;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+import org.apache.flex.compiler.projects.IASProject;
+import org.apache.flex.compiler.targets.ITargetProgressMonitor;
+import org.apache.flex.compiler.targets.ITargetSettings;
+import org.apache.flex.compiler.tree.mxml.IMXMLFileNode;
+import org.apache.flex.compiler.units.ICompilationUnit;
+import org.apache.flex.compiler.visitor.IBlockVisitor;
+import org.apache.flex.compiler.visitor.IBlockWalker;
+import org.apache.flex.compiler.visitor.mxml.IMXMLBlockWalker;
+
+/**
+ * A concrete implementation of the {@link IBackend} API where the
+ * {@link MXMLBlockWalker} is used to traverse the {@link IMXMLFileNode} AST.
+ *
+ * @author Erik de Bruin
+ */
+public class MXMLVF2JSBackend extends MXMLBackend
+{
+
+ @Override
+ public Configurator createConfigurator()
+ {
+ return new Configurator(JSGoogConfiguration.class);
+ }
+
+ @Override
+ public IMXMLEmitter createMXMLEmitter(FilterWriter out)
+ {
+ return new MXMLVF2JSEmitter(out);
+ }
+
+ @Override
+ public IMXMLBlockWalker createMXMLWalker(IASProject project,
+ List<ICompilerProblem> errors, IMXMLEmitter mxmlEmitter,
+ IASEmitter asEmitter, IBlockWalker asBlockWalker)
+ {
+ MXMLBlockWalker walker = new MXMLFlexJSBlockWalker(errors, project,
+ mxmlEmitter, asEmitter, asBlockWalker);
+
+ ASNodeSwitch asStrategy = new ASNodeSwitch(
+ (IBlockVisitor) asBlockWalker);
+ walker.setASStrategy(asStrategy);
+
+ MXMLNodeSwitch mxmlStrategy = new MXMLNodeSwitch(walker);
+ walker.setMXMLStrategy(mxmlStrategy);
+
+ return walker;
+ }
+
+ @Override
+ public IDocEmitter createDocEmitter(IASEmitter emitter)
+ {
+ return new JSGoogDocEmitter((IJSEmitter) emitter);
+ }
+
+ @Override
+ public IJSEmitter createEmitter(FilterWriter out)
+ {
+ IJSEmitter emitter = new JSFlexJSEmitter(out);
+ emitter.setDocEmitter(createDocEmitter(emitter));
+ return emitter;
+ }
+
+ @Override
+ public IJSWriter createMXMLWriter(IASProject project,
+ List<ICompilerProblem> problems, ICompilationUnit compilationUnit,
+ boolean enableDebug)
+ {
+ return new MXMLWriter(project, problems, compilationUnit, enableDebug);
+ }
+
+ @Override
+ public JSTarget createTarget(IASProject project, ITargetSettings settings,
+ ITargetProgressMonitor monitor)
+ {
+ return new FlexJSTarget(project, settings, monitor);
+ }
+}
[2/4] git commit: [flex-falcon] [refs/heads/VF2JS] - The first VF2JS
specific compilation classes.
Posted by er...@apache.org.
The first VF2JS specific compilation classes.
Signed-off-by: Erik de Bruin <er...@ixsoftware.nl>
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/6ddfe4b2
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/6ddfe4b2
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/6ddfe4b2
Branch: refs/heads/VF2JS
Commit: 6ddfe4b2a4129321af42468a7790abb5cb42db6d
Parents: cf6b1d1
Author: Erik de Bruin <er...@ixsoftware.nl>
Authored: Thu Jul 31 14:19:36 2014 +0200
Committer: Erik de Bruin <er...@ixsoftware.nl>
Committed: Thu Jul 31 14:20:10 2014 +0200
----------------------------------------------------------------------
.../vf2js/MXMLVF2JSDescriptorSpecifier.java | 334 ++++
.../codegen/mxml/vf2js/MXMLVF2JSEmitter.java | 1668 ++++++++++++++++++
.../codegen/mxml/vf2js/MXMLVF2JSPublisher.java | 505 ++++++
.../driver/mxml/vf2js/MXMLVF2JSBackend.java | 121 ++
4 files changed, 2628 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/6ddfe4b2/compiler.jx/src/org/apache/flex/compiler/internal/codegen/mxml/vf2js/MXMLVF2JSDescriptorSpecifier.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/mxml/vf2js/MXMLVF2JSDescriptorSpecifier.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/mxml/vf2js/MXMLVF2JSDescriptorSpecifier.java
new file mode 100644
index 0000000..369e218
--- /dev/null
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/mxml/vf2js/MXMLVF2JSDescriptorSpecifier.java
@@ -0,0 +1,334 @@
+/*
+ *
+ * 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.codegen.mxml.vf2js;
+
+import java.util.ArrayList;
+
+import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.mxml.flexjs.MXMLEventSpecifier;
+import org.apache.flex.compiler.internal.codegen.mxml.flexjs.MXMLNodeSpecifier;
+
+/**
+ * @author Erik de Bruin
+ */
+public class MXMLVF2JSDescriptorSpecifier extends MXMLNodeSpecifier
+{
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ public MXMLVF2JSDescriptorSpecifier()
+ {
+ super();
+
+ eventSpecifiers = new ArrayList<MXMLEventSpecifier>();
+ propertySpecifiers = new ArrayList<MXMLVF2JSDescriptorSpecifier>();
+
+ valueNeedsQuotes = false;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ //---------------------------------
+ // children
+ //---------------------------------
+
+ public MXMLVF2JSDescriptorSpecifier childrenSpecifier;
+
+ //---------------------------------
+ // properties
+ //---------------------------------
+
+ public ArrayList<MXMLVF2JSDescriptorSpecifier> propertySpecifiers;
+
+ //---------------------------------
+ // events
+ //---------------------------------
+
+ public ArrayList<MXMLEventSpecifier> eventSpecifiers;
+
+ //---------------------------------
+ // hasArray
+ //---------------------------------
+
+ public boolean hasArray;
+
+ //---------------------------------
+ // id
+ //---------------------------------
+
+ public String id;
+
+ //---------------------------------
+ // isTopNode
+ //---------------------------------
+
+ public boolean isTopNode;
+
+ //---------------------------------
+ // isProperty
+ //---------------------------------
+
+ public boolean isProperty;
+
+ //---------------------------------
+ // parent
+ //---------------------------------
+
+ public MXMLVF2JSDescriptorSpecifier parent;
+
+ //--------------------------------------------------------------------------
+ //
+ // Methods
+ //
+ //--------------------------------------------------------------------------
+
+ //---------------------------------
+ // outputEventSpecifier
+ //---------------------------------
+
+ private void outputEventSpecifier(boolean writeNewline)
+ {
+ // number of events
+ int count = 0;
+ for (MXMLEventSpecifier me : eventSpecifiers)
+ {
+ if (me.name != null)
+ count++;
+ }
+ write(count + "");
+
+ for (MXMLEventSpecifier me : eventSpecifiers)
+ {
+ writeDelimiter(writeNewline);
+ write(me.output(writeNewline));
+ }
+ }
+
+ //---------------------------------
+ // outputPropertySpecifier
+ //---------------------------------
+
+ private String outputPropertySpecifier(boolean writeNewline)
+ {
+ /*
+ write((isProperty) ? ASEmitterTokens.SINGLE_QUOTE.getToken() : "");
+ write(name);
+ write((isProperty) ? ASEmitterTokens.SINGLE_QUOTE.getToken() : "");
+ */
+ //writeDelimiter(writeNewline);
+
+ if (isProperty)
+ {
+ if (value != null)
+ {
+ write(ASEmitterTokens.THIS);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(parent.id);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ writeToken(name);
+ writeToken(ASEmitterTokens.EQUAL);
+ write(value);
+ write(ASEmitterTokens.SEMICOLON);
+ }
+ else
+ {
+ //write((hasArray) ? ASEmitterTokens.NULL : ASEmitterTokens.FALSE);
+ //writeDelimiter(writeNewline && !hasArray);
+
+ //write(ASEmitterTokens.SQUARE_OPEN);
+ output(false);
+ //write(ASEmitterTokens.SQUARE_CLOSE);
+ }
+
+ if (parent != null)
+ {
+ //writeDelimiter(writeNewline);
+ }
+
+ writeNewline("");
+ }
+ else
+ {
+ write(ASEmitterTokens.THIS);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ writeToken(id);
+ writeToken(ASEmitterTokens.EQUAL);
+ writeToken(ASEmitterTokens.NEW);
+ write(name);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ write(ASEmitterTokens.SEMICOLON);
+
+ for (MXMLVF2JSDescriptorSpecifier md : propertySpecifiers)
+ {
+ if (md.name != null && md.name.equals("mxmlContent"))
+ {
+ childrenSpecifier = md;
+ propertySpecifiers.remove(md);
+ break;
+ }
+ }
+
+ /*
+ if (id != null)
+ {
+ write(propertySpecifiers.size() + 1 + "");
+ writeDelimiter(writeNewline);
+ String idPropName = (id
+ .startsWith(MXMLFlexJSEmitterTokens.ID_PREFIX.getToken())) ? "_id"
+ : "id";
+ writeSimpleDescriptor(idPropName, ASEmitterTokens.TRUE.getToken(),
+ ASEmitterTokens.SINGLE_QUOTE.getToken()
+ + id + ASEmitterTokens.SINGLE_QUOTE.getToken(),
+ writeNewline);
+
+ writeDelimiter(writeNewline);
+ }
+ else
+ {
+ write(propertySpecifiers.size() + "");
+ writeDelimiter(writeNewline);
+ }
+ */
+ writeNewline("");
+
+ output(writeNewline);
+
+ writeNewline("this." + id + ".render();");
+ }
+
+ return sb.toString();
+ }
+
+ //---------------------------------
+ // outputStyleSpecifier
+ //---------------------------------
+
+ private void outputStyleSpecifier(boolean writeNewline)
+ {
+ // TODO (erikdebruin) not yet implemented in FlexJS
+
+ write("0");
+ writeDelimiter(writeNewline);
+ }
+
+ //---------------------------------
+ // output
+ //---------------------------------
+
+ @Override
+ public String output(boolean writeNewline)
+ {
+ for (MXMLVF2JSDescriptorSpecifier md : propertySpecifiers)
+ {
+ write(md.outputPropertySpecifier(writeNewline));
+ }
+
+ /*
+ if (isTopNode)
+ {
+ int count = 0;
+ for (MXMLVF2JSDescriptorSpecifier md : propertySpecifiers)
+ {
+ if (md.name != null)
+ count++;
+ }
+
+ write(count + "");
+ writeNewline(ASEmitterTokens.COMMA);
+ }
+
+ MXMLVF2JSDescriptorSpecifier model = null; // model goes first
+ MXMLVF2JSDescriptorSpecifier beads = null; // beads go last
+
+ for (MXMLVF2JSDescriptorSpecifier md : propertySpecifiers)
+ {
+ if (md.name != null && md.name.equals("model"))
+ {
+ model = md;
+
+ break;
+ }
+ }
+
+ if (model != null)
+ write(model.outputPropertySpecifier(true));
+
+ for (MXMLVF2JSDescriptorSpecifier md : propertySpecifiers)
+ {
+ if (md.name != null)
+ {
+ if (!md.name.equals("model") && !md.name.equals("beads"))
+ write(md.outputPropertySpecifier(writeNewline));
+ else if (md.name.equals("beads"))
+ beads = md;
+ }
+ }
+
+ if (beads != null)
+ write(beads.outputPropertySpecifier(writeNewline));
+
+ if (!isProperty)
+ {
+ outputStyleSpecifier(writeNewline);
+
+ // TODO (erikdebruin) not yet implemented in FlexJS
+ //outputEffectSpecifier(writeNewline);
+
+ outputEventSpecifier(writeNewline);
+
+ if (!isTopNode)
+ {
+ writeDelimiter(writeNewline);
+
+ if (childrenSpecifier == null)
+ write(ASEmitterTokens.NULL);
+ else
+ outputChildren(childrenSpecifier, writeNewline);
+ }
+
+ boolean isLastChild = parent != null
+ && parent.propertySpecifiers.indexOf(this) == parent.propertySpecifiers
+ .size() - 1;
+
+ if (!isLastChild && !isTopNode)
+ writeDelimiter(writeNewline);
+ }
+ //*/
+
+ return sb.toString();
+ }
+
+ private void outputChildren(MXMLVF2JSDescriptorSpecifier children, boolean writeNewline)
+ {
+ write(ASEmitterTokens.SQUARE_OPEN.getToken());
+ write(children.output(false));
+ write(ASEmitterTokens.SQUARE_CLOSE.getToken());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/6ddfe4b2/compiler.jx/src/org/apache/flex/compiler/internal/codegen/mxml/vf2js/MXMLVF2JSEmitter.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/mxml/vf2js/MXMLVF2JSEmitter.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/mxml/vf2js/MXMLVF2JSEmitter.java
new file mode 100644
index 0000000..a8ad471
--- /dev/null
+++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/mxml/vf2js/MXMLVF2JSEmitter.java
@@ -0,0 +1,1668 @@
+/*
+ *
+ * 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.codegen.mxml.vf2js;
+
+
+import java.io.FilterWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.flex.abc.semantics.MethodInfo;
+import org.apache.flex.abc.semantics.Name;
+import org.apache.flex.abc.semantics.Namespace;
+import org.apache.flex.compiler.codegen.as.IASEmitter;
+import org.apache.flex.compiler.codegen.mxml.flexjs.IMXMLFlexJSEmitter;
+import org.apache.flex.compiler.definitions.IClassDefinition;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.databinding.BindingDatabase;
+import org.apache.flex.compiler.internal.codegen.databinding.BindingInfo;
+import org.apache.flex.compiler.internal.codegen.databinding.FunctionWatcherInfo;
+import org.apache.flex.compiler.internal.codegen.databinding.PropertyWatcherInfo;
+import org.apache.flex.compiler.internal.codegen.databinding.StaticPropertyWatcherInfo;
+import org.apache.flex.compiler.internal.codegen.databinding.WatcherInfoBase;
+import org.apache.flex.compiler.internal.codegen.databinding.WatcherInfoBase.WatcherType;
+import org.apache.flex.compiler.internal.codegen.databinding.XMLWatcherInfo;
+import org.apache.flex.compiler.internal.codegen.js.JSEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitter;
+import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.mxml.MXMLEmitter;
+import org.apache.flex.compiler.internal.codegen.mxml.flexjs.MXMLEventSpecifier;
+import org.apache.flex.compiler.internal.codegen.mxml.flexjs.MXMLFlexJSBlockWalker;
+import org.apache.flex.compiler.internal.codegen.mxml.flexjs.MXMLFlexJSEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.mxml.flexjs.MXMLScriptSpecifier;
+import org.apache.flex.compiler.internal.projects.FlexJSProject;
+import org.apache.flex.compiler.internal.projects.FlexProject;
+import org.apache.flex.compiler.internal.scopes.ASProjectScope;
+import org.apache.flex.compiler.internal.tree.as.FunctionCallNode;
+import org.apache.flex.compiler.internal.tree.as.IdentifierNode;
+import org.apache.flex.compiler.internal.tree.as.MemberAccessExpressionNode;
+import org.apache.flex.compiler.internal.tree.mxml.MXMLDocumentNode;
+import org.apache.flex.compiler.projects.ICompilerProject;
+import org.apache.flex.compiler.tree.ASTNodeID;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.as.IExpressionNode;
+import org.apache.flex.compiler.tree.as.IImportNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLArrayNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLClassDefinitionNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLClassNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLComponentNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLDataBindingNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLDocumentNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLEventSpecifierNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLFactoryNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLInstanceNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLLiteralNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLPropertySpecifierNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLScriptNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLSpecifierNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLStateNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLStringNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLStyleSpecifierNode;
+import org.apache.flex.compiler.units.ICompilationUnit;
+import org.apache.flex.compiler.utils.NativeUtils;
+import org.apache.flex.compiler.visitor.mxml.IMXMLBlockWalker;
+
+/**
+ * @author Erik de Bruin
+ */
+public class MXMLVF2JSEmitter extends MXMLEmitter implements
+ IMXMLFlexJSEmitter
+{
+
+ private ArrayList<MXMLVF2JSDescriptorSpecifier> currentInstances;
+ private ArrayList<MXMLVF2JSDescriptorSpecifier> currentPropertySpecifiers;
+ private ArrayList<MXMLVF2JSDescriptorSpecifier> descriptorTree;
+ private MXMLVF2JSDescriptorSpecifier propertiesTree;
+ private ArrayList<MXMLEventSpecifier> events;
+ private ArrayList<MXMLVF2JSDescriptorSpecifier> instances;
+ private ArrayList<MXMLScriptSpecifier> scripts;
+ //private ArrayList<MXMLStyleSpecifier> styles;
+
+ private int eventCounter;
+ private int idCounter;
+
+ private boolean inMXMLContent;
+ private boolean inStatesOverride;
+
+ private StringBuilder subDocuments = new StringBuilder();
+ private ArrayList<String> subDocumentNames = new ArrayList<String>();
+
+ public MXMLVF2JSEmitter(FilterWriter out)
+ {
+ super(out);
+ }
+
+ @Override
+ protected String getIndent(int numIndent)
+ {
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < numIndent; i++)
+ sb.append(JSFlexJSEmitterTokens.INDENT.getToken());
+ return sb.toString();
+ }
+
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitDocument(IMXMLDocumentNode node)
+ {
+ descriptorTree = new ArrayList<MXMLVF2JSDescriptorSpecifier>();
+ propertiesTree = new MXMLVF2JSDescriptorSpecifier();
+
+ events = new ArrayList<MXMLEventSpecifier>();
+ instances = new ArrayList<MXMLVF2JSDescriptorSpecifier>();
+ scripts = new ArrayList<MXMLScriptSpecifier>();
+ //styles = new ArrayList<MXMLStyleSpecifier>();
+
+ currentInstances = new ArrayList<MXMLVF2JSDescriptorSpecifier>();
+ currentPropertySpecifiers = new ArrayList<MXMLVF2JSDescriptorSpecifier>();
+
+ eventCounter = 0;
+ idCounter = 0;
+
+ // visit MXML
+ IClassDefinition cdef = node.getClassDefinition();
+ IASEmitter asEmitter = ((IMXMLBlockWalker) getMXMLWalker())
+ .getASEmitter();
+ ((JSFlexJSEmitter) asEmitter).thisClass = cdef;
+
+ // visit tags
+ final int len = node.getChildCount();
+ for (int i = 0; i < len; i++)
+ {
+ getMXMLWalker().walk(node.getChild(i));
+ }
+
+ String cname = node.getFileNode().getName();
+
+ emitHeader(node);
+
+ write(subDocuments.toString());
+ writeNewline();
+
+ emitClassDeclStart(cname, node.getBaseClassName(), false);
+
+ emitPropertyDecls();
+
+ emitClassDeclEnd(cname, node.getBaseClassName());
+
+ emitMetaData(cdef);
+
+ emitScripts();
+
+ emitEvents(cname);
+
+ emitPropertyGetterSetters(cname);
+
+ emitMXMLDescriptorFuncs(cname);
+
+ emitBindingData(cname, cdef);
+
+ emitEncodedCSS(cname);
+
+ }
+
+ public void emitSubDocument(IMXMLComponentNode node)
+ {
+ ArrayList<MXMLVF2JSDescriptorSpecifier> oldDescriptorTree;
+ MXMLVF2JSDescriptorSpecifier oldPropertiesTree;
+ ArrayList<MXMLEventSpecifier> oldEvents;
+ ArrayList<MXMLScriptSpecifier> oldScripts;
+ ArrayList<MXMLVF2JSDescriptorSpecifier> oldCurrentInstances;
+ ArrayList<MXMLVF2JSDescriptorSpecifier> oldCurrentPropertySpecifiers;
+ int oldEventCounter;
+ int oldIdCounter;
+
+ oldDescriptorTree = descriptorTree;
+ descriptorTree = new ArrayList<MXMLVF2JSDescriptorSpecifier>();
+ oldPropertiesTree = propertiesTree;
+ propertiesTree = new MXMLVF2JSDescriptorSpecifier();
+
+ oldEvents = events;
+ events = new ArrayList<MXMLEventSpecifier>();
+ // we don't save these. We want all requires to be generated at the top of the file
+ instances = new ArrayList<MXMLVF2JSDescriptorSpecifier>();
+ oldScripts = scripts;
+ scripts = new ArrayList<MXMLScriptSpecifier>();
+ //styles = new ArrayList<MXMLStyleSpecifier>();
+
+ oldCurrentInstances = currentInstances;
+ currentInstances = new ArrayList<MXMLVF2JSDescriptorSpecifier>();
+ oldCurrentPropertySpecifiers = currentPropertySpecifiers;
+ currentPropertySpecifiers = new ArrayList<MXMLVF2JSDescriptorSpecifier>();
+
+ oldEventCounter = eventCounter;
+ eventCounter = 0;
+ oldIdCounter = idCounter;
+ idCounter = 0;
+
+ // visit MXML
+ IClassDefinition cdef = node.getContainedClassDefinition();
+ IASEmitter asEmitter = ((IMXMLBlockWalker) getMXMLWalker())
+ .getASEmitter();
+ ((JSFlexJSEmitter) asEmitter).thisClass = cdef;
+
+ IASNode classNode = node.getContainedClassDefinitionNode();
+ // visit tags
+ final int len = classNode.getChildCount();
+ for (int i = 0; i < len; i++)
+ {
+ getMXMLWalker().walk(classNode.getChild(i));
+ }
+
+ String cname = cdef.getQualifiedName();
+ subDocumentNames.add(cname);
+ String baseClassName = cdef.getBaseClassAsDisplayString();
+
+ emitClassDeclStart(cname, baseClassName, false);
+
+ emitPropertyDecls();
+
+ emitClassDeclEnd(cname, baseClassName);
+
+ emitMetaData(cdef);
+
+ emitScripts();
+
+ emitEvents(cname);
+
+ emitPropertyGetterSetters(cname);
+
+ emitMXMLDescriptorFuncs(cname);
+
+ emitBindingData(cname, cdef);
+
+ emitEncodedCSS(cname);
+
+ descriptorTree = oldDescriptorTree;
+ propertiesTree = oldPropertiesTree;
+ events = oldEvents;
+ scripts = oldScripts;
+ currentInstances = oldCurrentInstances;
+ currentPropertySpecifiers = oldCurrentPropertySpecifiers;
+ eventCounter = oldEventCounter;
+ idCounter = oldIdCounter;
+
+ }
+
+ //--------------------------------------------------------------------------
+
+ protected void emitClassDeclStart(String cname, String baseClassName,
+ boolean indent)
+ {
+ writeNewline();
+ writeNewline("/**");
+ writeNewline(" * @constructor");
+ writeNewline(" * @extends {" + baseClassName + "}");
+ writeNewline(" */");
+ writeToken(cname);
+ writeToken(ASEmitterTokens.EQUAL);
+ write(ASEmitterTokens.FUNCTION);
+ write(ASEmitterTokens.PAREN_OPEN);
+ writeToken(ASEmitterTokens.PAREN_CLOSE);
+ if (indent)
+ indentPush();
+ writeNewline(ASEmitterTokens.BLOCK_OPEN, true);
+ write(cname);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(JSGoogEmitterTokens.GOOG_BASE);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.THIS);
+ writeToken(ASEmitterTokens.COMMA);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(JSGoogEmitterTokens.GOOG_CONSTRUCTOR);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ writeNewline(ASEmitterTokens.SEMICOLON);
+ }
+
+ //--------------------------------------------------------------------------
+
+ protected void emitClassDeclEnd(String cname, String baseClassName)
+ {
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ writeNewline(ASEmitterTokens.SEMICOLON);
+ write(JSGoogEmitterTokens.GOOG_INHERITS);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(cname);
+ writeToken(ASEmitterTokens.COMMA);
+ write(baseClassName);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ writeNewline(ASEmitterTokens.SEMICOLON);
+ writeNewline();
+ writeNewline();
+ }
+
+ //--------------------------------------------------------------------------
+
+ protected void emitMetaData(IClassDefinition cdef)
+ {
+ String cname = cdef.getQualifiedName();
+
+ writeNewline("/**");
+ writeNewline(" * Metadata");
+ writeNewline(" *");
+ writeNewline(" * @type {Object.<string, Array.<Object>>}");
+ writeNewline(" */");
+ write(cname + ".prototype.FLEXJS_CLASS_INFO = { names: [{ name: '");
+ write(cdef.getBaseName());
+ write("', qName: '");
+ write(cname);
+ writeNewline("' }] };");
+ writeNewline();
+ writeNewline();
+ }
+
+ //--------------------------------------------------------------------------
+
+ protected void emitPropertyDecls()
+ {
+ indentPop();
+
+ for (MXMLVF2JSDescriptorSpecifier instance : instances)
+ {
+ indentPush();
+ writeNewline();
+ writeNewline("/**");
+ writeNewline(" * @private");
+ writeNewline(" * @type {" + instance.name + "}");
+ writeNewline(" */");
+ write(ASEmitterTokens.THIS);
+ write(ASEmitterTokens.MEMBER_ACCESS);
+ write(instance.id);
+ indentPop();
+ writeNewline(ASEmitterTokens.SEMICOLON);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+
+ protected void emitBindingData(String cname, IClassDefinition cdef)
+ {
+ BindingDatabase bd = BindingDatabase.bindingMap.get(cdef);
+ if (bd == null)
+ return;
+ if (bd.getBindingInfo().isEmpty())
+ return;
+
+ outputBindingInfoAsData(cname, bd);
+ }
+
+ private void outputBindingInfoAsData(String cname, BindingDatabase bindingDataBase)
+ {
+ IASEmitter asEmitter = ((IMXMLBlockWalker) getMXMLWalker())
+ .getASEmitter();
+
+ writeNewline("/**");
+ writeNewline(" * @expose");
+ writeNewline(" */");
+ writeNewline(cname
+ + ".prototype._bindings = [");
+
+ Set<BindingInfo> bindingInfo = bindingDataBase.getBindingInfo();
+ writeNewline(bindingInfo.size() + ","); // number of bindings
+
+ for (BindingInfo bi : bindingInfo)
+ {
+ String s;
+ s = bi.getSourceString();
+ if (s == null)
+ s = getSourceStringFromGetter(bi.getExpressionNodesForGetter());
+ if (s.contains("."))
+ {
+ String[] parts = s.split("\\.");
+ write(ASEmitterTokens.SQUARE_OPEN.getToken() + ASEmitterTokens.DOUBLE_QUOTE.getToken() +
+ parts[0] + ASEmitterTokens.DOUBLE_QUOTE.getToken());
+ int n = parts.length;
+ for (int i = 1; i < n; i++)
+ {
+ String part = parts[i];
+ write(", " + ASEmitterTokens.DOUBLE_QUOTE.getToken() + part + ASEmitterTokens.DOUBLE_QUOTE.getToken());
+ }
+ writeNewline(ASEmitterTokens.SQUARE_CLOSE.getToken() + ASEmitterTokens.COMMA.getToken());
+ }
+ else if (s == null || s.length() == 0)
+ {
+ List<IExpressionNode> getterNodes = bi.getExpressionNodesForGetter();
+ StringBuilder sb = new StringBuilder();
+ sb.append("function() { return ");
+ for (IExpressionNode getterNode : getterNodes)
+ {
+ sb.append(asEmitter.stringifyNode(getterNode));
+ }
+ sb.append("; },");
+ writeNewline(sb.toString());
+ }
+ else
+ writeNewline(ASEmitterTokens.DOUBLE_QUOTE.getToken() + s +
+ ASEmitterTokens.DOUBLE_QUOTE.getToken() + ASEmitterTokens.COMMA.getToken());
+
+ IExpressionNode destNode = bi.getExpressionNodeForDestination();
+ if (destNode != null)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append(asEmitter.stringifyNode(destNode));
+ writeNewline(sb.toString());
+ }
+ else
+ writeNewline(ASEmitterTokens.NULL.getToken() + ASEmitterTokens.COMMA.getToken());
+
+ s = bi.getDestinationString();
+ if (s.contains("."))
+ {
+ String[] parts = s.split("\\.");
+ write(ASEmitterTokens.SQUARE_OPEN.getToken() + ASEmitterTokens.DOUBLE_QUOTE.getToken() +
+ parts[0] + ASEmitterTokens.DOUBLE_QUOTE.getToken());
+ int n = parts.length;
+ for (int i = 1; i < n; i++)
+ {
+ String part = parts[i];
+ write(", " + ASEmitterTokens.DOUBLE_QUOTE.getToken() + part + ASEmitterTokens.DOUBLE_QUOTE.getToken());
+ }
+ writeNewline(ASEmitterTokens.SQUARE_CLOSE.getToken() + ASEmitterTokens.COMMA.getToken());
+ }
+ else
+ writeNewline(ASEmitterTokens.DOUBLE_QUOTE.getToken() + s +
+ ASEmitterTokens.DOUBLE_QUOTE.getToken() + ASEmitterTokens.COMMA.getToken());
+ }
+ Set<Entry<Object, WatcherInfoBase>> watcherChains = bindingDataBase.getWatcherChains();
+ for (Entry<Object, WatcherInfoBase> entry : watcherChains)
+ {
+ WatcherInfoBase watcherInfoBase = entry.getValue();
+ encodeWatcher(watcherInfoBase);
+ }
+ // add a trailing null for now so I don't have to have logic where the watcher figures out not to add
+ // a comma
+ writeNewline("null" + ASEmitterTokens.SQUARE_CLOSE.getToken() + ASEmitterTokens.SEMICOLON.getToken());
+ }
+
+ private void encodeWatcher(WatcherInfoBase watcherInfoBase)
+ {
+ IASEmitter asEmitter = ((IMXMLBlockWalker) getMXMLWalker())
+ .getASEmitter();
+
+ writeNewline(watcherInfoBase.getIndex() + ASEmitterTokens.COMMA.getToken());
+ WatcherType type = watcherInfoBase.getType();
+ if (type == WatcherType.FUNCTION)
+ {
+ writeNewline("0" + ASEmitterTokens.COMMA.getToken());
+
+ FunctionWatcherInfo functionWatcherInfo = (FunctionWatcherInfo)watcherInfoBase;
+
+ writeNewline(ASEmitterTokens.DOUBLE_QUOTE.getToken() + functionWatcherInfo.getFunctionName() +
+ ASEmitterTokens.DOUBLE_QUOTE.getToken());
+ IExpressionNode params[] = functionWatcherInfo.params;
+ StringBuilder sb = new StringBuilder();
+ sb.append("function() { return [");
+ boolean firstone = true;
+ for (IExpressionNode param : params)
+ {
+ if (firstone)
+ firstone = false;
+ sb.append(ASEmitterTokens.COMMA.getToken());
+ sb.append(asEmitter.stringifyNode(param));
+ }
+ sb.append("]; },");
+ outputEventNames(functionWatcherInfo.getEventNames());
+ outputBindings(functionWatcherInfo.getBindings());
+ }
+ else if ((type == WatcherType.STATIC_PROPERTY) || (type == WatcherType.PROPERTY))
+ {
+ writeNewline((type == WatcherType.STATIC_PROPERTY ? "1" : "2") +
+ ASEmitterTokens.COMMA.getToken());
+
+ PropertyWatcherInfo propertyWatcherInfo = (PropertyWatcherInfo)watcherInfoBase;
+
+ boolean makeStaticWatcher = (watcherInfoBase.getType() == WatcherType.STATIC_PROPERTY);
+
+ // round up the getter function for the watcher, or null if we don't need one
+ MethodInfo propertyGetterFunction = null;
+ if (watcherInfoBase.isRoot && !makeStaticWatcher)
+ {
+ // TODO: figure out what this looks like
+ // propertyGetterFunction = this.propertyGetter;
+ // assert propertyGetterFunction != null;
+ }
+ else if (watcherInfoBase.isRoot && makeStaticWatcher)
+ {
+ // TODO: implement getter func for static watcher.
+ }
+ writeNewline(ASEmitterTokens.DOUBLE_QUOTE.getToken() + propertyWatcherInfo.getPropertyName() +
+ ASEmitterTokens.DOUBLE_QUOTE.getToken() + ASEmitterTokens.COMMA.getToken());
+ outputEventNames(propertyWatcherInfo.getEventNames());
+ outputBindings(propertyWatcherInfo.getBindings());
+ if (propertyGetterFunction == null)
+ writeNewline("null" + ASEmitterTokens.COMMA.getToken()); // null is valid
+ if (type == WatcherType.STATIC_PROPERTY)
+ {
+ StaticPropertyWatcherInfo pwinfo = (StaticPropertyWatcherInfo)watcherInfoBase;
+ Name classMName = pwinfo.getContainingClass(getMXMLWalker().getProject());
+ writeNewline(nameToString(classMName));
+ }
+ }
+ else if (type == WatcherType.XML)
+ {
+ writeNewline("3" + ASEmitterTokens.COMMA.getToken());
+
+ XMLWatcherInfo xmlWatcherInfo = (XMLWatcherInfo)watcherInfoBase;
+ writeNewline(ASEmitterTokens.DOUBLE_QUOTE.getToken() + xmlWatcherInfo.getPropertyName() +
+ ASEmitterTokens.DOUBLE_QUOTE.getToken() + ASEmitterTokens.COMMA.getToken());
+ outputBindings(xmlWatcherInfo.getBindings());
+ }
+ else assert false;
+
+ // then recurse into children
+ Set<Entry<Object, WatcherInfoBase>> children = watcherInfoBase.getChildren();
+ if (children != null)
+ {
+ writeNewline(ASEmitterTokens.SQUARE_OPEN.getToken());
+ for ( Entry<Object, WatcherInfoBase> ent : children)
+ {
+ encodeWatcher(ent.getValue());
+ }
+ writeNewline("null" + ASEmitterTokens.SQUARE_CLOSE.getToken() + ASEmitterTokens.COMMA.getToken());
+ }
+ else
+ {
+ writeNewline("null" + ASEmitterTokens.COMMA.getToken());
+ }
+ }
+
+ private String getSourceStringFromMemberAccessExpressionNode(MemberAccessExpressionNode node)
+ {
+ String s = "";
+
+ IExpressionNode left = node.getLeftOperandNode();
+ if (left instanceof FunctionCallNode) // probably a cast
+ {
+ IASNode child = ((FunctionCallNode)left).getArgumentsNode().getChild(0);
+ if (child instanceof IdentifierNode)
+ s = getSourceStringFromIdentifierNode((IdentifierNode)child);
+ else if (child instanceof MemberAccessExpressionNode)
+ s = getSourceStringFromMemberAccessExpressionNode((MemberAccessExpressionNode)child);
+ }
+ else if (left instanceof MemberAccessExpressionNode)
+ s = getSourceStringFromMemberAccessExpressionNode((MemberAccessExpressionNode)left);
+ else if (left instanceof IdentifierNode)
+ s = getSourceStringFromIdentifierNode((IdentifierNode)left);
+ else
+ System.out.println("expected binding member access left node" + node.toString());
+ s += ".";
+
+ IExpressionNode right = node.getRightOperandNode();
+ if (right instanceof FunctionCallNode) // probably a cast
+ {
+ IASNode child = ((FunctionCallNode)right).getArgumentsNode().getChild(0);
+ if (child instanceof IdentifierNode)
+ s += getSourceStringFromIdentifierNode((IdentifierNode)child);
+ else if (child instanceof MemberAccessExpressionNode)
+ s += getSourceStringFromMemberAccessExpressionNode((MemberAccessExpressionNode)child);
+ }
+ else if (right instanceof MemberAccessExpressionNode)
+ s += getSourceStringFromMemberAccessExpressionNode((MemberAccessExpressionNode)right);
+ else if (right instanceof IdentifierNode)
+ s += getSourceStringFromIdentifierNode((IdentifierNode)right);
+ else
+ System.out.println("expected binding member access right node" + node.toString());
+
+ return s;
+ }
+
+ private String getSourceStringFromIdentifierNode(IdentifierNode node)
+ {
+ return node.getName();
+ }
+
+ private String getSourceStringFromGetter(List<IExpressionNode> nodes)
+ {
+ String s = "";
+ IExpressionNode node = nodes.get(0);
+ if (node instanceof MemberAccessExpressionNode)
+ {
+ s = getSourceStringFromMemberAccessExpressionNode((MemberAccessExpressionNode)node);
+ }
+ return s;
+ }
+
+ private void outputEventNames(List<String> events)
+ {
+ if (events.size() > 1)
+ {
+ int n = events.size();
+ write(ASEmitterTokens.SQUARE_OPEN.getToken() + ASEmitterTokens.DOUBLE_QUOTE.getToken() +
+ events.get(0) + ASEmitterTokens.DOUBLE_QUOTE.getToken());
+ for (int i = 1; i < n; i++)
+ {
+ String event = events.get(i);
+ write(ASEmitterTokens.COMMA.getToken() + ASEmitterTokens.DOUBLE_QUOTE.getToken() +
+ event + ASEmitterTokens.DOUBLE_QUOTE.getToken());
+ }
+ writeNewline(ASEmitterTokens.SQUARE_CLOSE.getToken() + ASEmitterTokens.COMMA.getToken());
+ }
+ else if (events.size() == 1)
+ writeNewline(ASEmitterTokens.DOUBLE_QUOTE.getToken() + events.get(0) +
+ ASEmitterTokens.DOUBLE_QUOTE.getToken() + ASEmitterTokens.COMMA.getToken());
+ else
+ writeNewline("null" + ASEmitterTokens.COMMA.getToken());
+ }
+
+ private void outputBindings(List<BindingInfo> bindings)
+ {
+ if (bindings.size() > 1)
+ {
+ int n = bindings.size();
+ write(ASEmitterTokens.SQUARE_OPEN.getToken() + bindings.get(0).getIndex());
+ for (int i = 1; i < n; i++)
+ {
+ BindingInfo binding = bindings.get(i);
+ write(ASEmitterTokens.COMMA.getToken() + binding.getIndex());
+ }
+ writeNewline(ASEmitterTokens.SQUARE_CLOSE.getToken() + ASEmitterTokens.COMMA.getToken());
+ }
+ else if (bindings.size() == 1)
+ writeNewline(bindings.get(0).getIndex() + ASEmitterTokens.COMMA.getToken());
+ else
+ writeNewline("null" + ASEmitterTokens.COMMA.getToken());
+
+ }
+
+ //--------------------------------------------------------------------------
+
+ protected void emitScripts()
+ {
+ for (MXMLScriptSpecifier script : scripts)
+ {
+ String output = script.output();
+
+ if (!output.equals(""))
+ {
+ writeNewline(output);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+
+ protected void emitEvents(String cname)
+ {
+ for (MXMLEventSpecifier event : events)
+ {
+ writeNewline("/**");
+ writeNewline(" * @expose");
+ writeNewline(" * @param {" + event.type + "} event");
+ writeNewline(" */");
+ writeNewline(cname
+ + ".prototype." + event.eventHandler + " = function(event)");
+ writeNewline(ASEmitterTokens.BLOCK_OPEN, true);
+
+ writeNewline(event.value + ASEmitterTokens.SEMICOLON.getToken(),
+ false);
+
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ writeNewline(";");
+ writeNewline();
+ writeNewline();
+ }
+ }
+
+ //--------------------------------------------------------------------------
+
+ protected void emitPropertyGetterSetters(String cname)
+ {
+ for (MXMLVF2JSDescriptorSpecifier instance : instances)
+ {
+ if (!instance.id.startsWith(MXMLFlexJSEmitterTokens.ID_PREFIX
+ .getToken()))
+ {
+ writeNewline("/**");
+ writeNewline(" * @expose");
+ writeNewline(" * @return {" + instance.name + "}");
+ writeNewline(" */");
+ writeNewline(cname
+ + ".prototype.get_" + instance.id + " = function()");
+ indentPush();
+ writeNewline("{");
+ indentPop();
+ writeNewline("return this." + instance.id + ";");
+ writeNewline("};");
+ writeNewline();
+ writeNewline();
+ writeNewline("/**");
+ writeNewline(" * @expose");
+ writeNewline(" * @param {" + instance.name + "} value");
+ writeNewline(" */");
+ writeNewline(cname
+ + ".prototype.set_" + instance.id
+ + " = function(value)");
+ indentPush();
+ writeNewline("{");
+ indentPush();
+ writeNewline("if (value != this." + instance.id + ")");
+ indentPop();
+ indentPop();
+ writeNewline("this." + instance.id + " = value;");
+ writeNewline("};");
+ writeNewline();
+ writeNewline();
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+
+ protected void emitMXMLDescriptorFuncs(String cname)
+ {
+ // top level is 'mxmlContent', skip it...
+ if (descriptorTree.size() > 0)
+ {
+ MXMLVF2JSDescriptorSpecifier root = descriptorTree.get(0);
+ root.isTopNode = false;
+
+ writeNewline("/**");
+ writeNewline(" * @override");
+ writeNewline(" * @return {Array} the Array of UI element descriptors.");
+ writeNewline(" */");
+ writeNewline(cname + ".prototype.get_MXMLDescriptor = function()");
+ indentPush();
+ writeNewline("{");
+ writeNewline("if (this.mxmldd == undefined)");
+ indentPush();
+ writeNewline("{");
+ writeNewline("/** @type {Array} */");
+ writeNewline("var arr = " + cname + ".base(this, 'get_MXMLDescriptor');");
+ writeNewline("/** @type {Array} */");
+ indentPop();
+ indentPop();
+ writeNewline("var data = [");
+
+ writeNewline(root.output(true));
+
+ indentPush();
+ writeNewline("];");
+ indentPush();
+ writeNewline("");
+ indentPush();
+ writeNewline("if (arr)");
+ indentPop();
+ writeNewline("this.mxmldd = arr.concat(data);");
+ indentPush();
+ writeNewline("else");
+ indentPop();
+ indentPop();
+ writeNewline("this.mxmldd = data;");
+ writeNewline("}");
+ indentPop();
+ writeNewline("return this.mxmldd;");
+ writeNewline("};");
+ writeNewline();
+ }
+
+ if (propertiesTree.propertySpecifiers.size() > 0 ||
+ propertiesTree.eventSpecifiers.size() > 0)
+ {
+ MXMLVF2JSDescriptorSpecifier root = propertiesTree;
+ root.isTopNode = true;
+
+ writeNewline("/**");
+ writeNewline(" * start");
+ writeNewline(" *");
+ writeNewline(" * @expose");
+ writeNewline(" */");
+ writeNewline(cname + ".prototype.start = function () {");
+ writeNewline(root.output(true));
+ writeNewline("};");
+ }
+ }
+
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitEventSpecifier(IMXMLEventSpecifierNode node)
+ {
+ IDefinition cdef = node.getDefinition();
+
+ MXMLVF2JSDescriptorSpecifier currentDescriptor = getCurrentDescriptor("i");
+
+ MXMLEventSpecifier eventSpecifier = new MXMLEventSpecifier();
+ eventSpecifier.eventHandler = MXMLFlexJSEmitterTokens.EVENT_PREFIX
+ .getToken() + eventCounter++;
+ eventSpecifier.name = cdef.getBaseName();
+ eventSpecifier.type = node.getEventParameterDefinition()
+ .getTypeAsDisplayString();
+
+ IASEmitter asEmitter = ((IMXMLBlockWalker) getMXMLWalker())
+ .getASEmitter();
+
+ StringBuilder sb = null;
+ int len = node.getChildCount();
+ if (len > 0)
+ {
+ sb = new StringBuilder();
+ for (int i = 0; i < len; i++)
+ {
+ sb.append(getIndent((i > 0) ? 1 : 0)
+ + asEmitter.stringifyNode(node.getChild(i)));
+ if (i < len - 1)
+ {
+ sb.append(ASEmitterTokens.SEMICOLON.getToken());
+ sb.append(ASEmitterTokens.NEW_LINE.getToken());
+ }
+ }
+ }
+ eventSpecifier.value = sb.toString();
+
+ if (currentDescriptor != null)
+ currentDescriptor.eventSpecifiers.add(eventSpecifier);
+ else // in theory, if no currentdescriptor must be top tag event
+ propertiesTree.eventSpecifiers.add(eventSpecifier);
+
+ events.add(eventSpecifier);
+ }
+
+ @Override
+ public void emitInstance(IMXMLInstanceNode node)
+ {
+ if (isStateDependent(node) && !inStatesOverride)
+ return;
+
+ IClassDefinition cdef = node
+ .getClassReference((ICompilerProject) getMXMLWalker()
+ .getProject());
+
+ MXMLVF2JSDescriptorSpecifier currentPropertySpecifier = getCurrentDescriptor("ps");
+
+ String id = node.getID();
+ if (id == null)
+ id = node.getEffectiveID();
+ if (id == null)
+ id = MXMLFlexJSEmitterTokens.ID_PREFIX.getToken() + idCounter++;
+
+ MXMLVF2JSDescriptorSpecifier currentInstance = new MXMLVF2JSDescriptorSpecifier();
+ currentInstance.isProperty = false;
+ currentInstance.id = id;
+ currentInstance.name = cdef.getQualifiedName();
+ currentInstance.parent = currentPropertySpecifier;
+
+ if (currentPropertySpecifier != null)
+ currentPropertySpecifier.propertySpecifiers.add(currentInstance);
+ else if (inMXMLContent)
+ descriptorTree.add(currentInstance);
+ else
+ {
+ currentInstance.parent = propertiesTree;
+ propertiesTree.propertySpecifiers.add(currentInstance);
+ }
+
+ instances.add(currentInstance);
+
+ IMXMLPropertySpecifierNode[] pnodes = node.getPropertySpecifierNodes();
+ if (pnodes != null)
+ {
+ moveDown(false, currentInstance, null);
+
+ for (IMXMLPropertySpecifierNode pnode : pnodes)
+ {
+ getMXMLWalker().walk(pnode); // Property Specifier
+ }
+
+ moveUp(false, true);
+ }
+ else if (node instanceof IMXMLStateNode)
+ {
+ IMXMLStateNode stateNode = (IMXMLStateNode)node;
+ String name = stateNode.getStateName();
+ if (name != null)
+ {
+ MXMLVF2JSDescriptorSpecifier stateName = new MXMLVF2JSDescriptorSpecifier();
+ stateName.isProperty = true;
+ stateName.id = id;
+ stateName.name = "name";
+ stateName.value = ASEmitterTokens.SINGLE_QUOTE.getToken() + name + ASEmitterTokens.SINGLE_QUOTE.getToken();
+ stateName.parent = currentInstance;
+ currentInstance.propertySpecifiers.add(stateName);
+ }
+ MXMLVF2JSDescriptorSpecifier overrides = new MXMLVF2JSDescriptorSpecifier();
+ overrides.isProperty = true;
+ overrides.hasArray = true;
+ overrides.id = id;
+ overrides.name = "overrides";
+ overrides.parent = currentInstance;
+ currentInstance.propertySpecifiers.add(overrides);
+ moveDown(false, null, overrides);
+
+ IMXMLClassDefinitionNode classDefinitionNode = stateNode.getClassDefinitionNode();
+ List<IMXMLNode> snodes = classDefinitionNode.getNodesDependentOnState(stateNode.getStateName());
+ if (snodes != null)
+ {
+ for (int i=snodes.size()-1; i>=0; --i)
+ {
+ IMXMLNode inode = snodes.get(i);
+ if (inode.getNodeID() == ASTNodeID.MXMLInstanceID)
+ {
+ emitInstanceOverride((IMXMLInstanceNode)inode);
+ }
+ }
+ // Next process the non-instance overrides dependent on this state.
+ // Each one will generate code to push an IOverride instance.
+ for (IMXMLNode anode : snodes)
+ {
+ switch (anode.getNodeID())
+ {
+ case MXMLPropertySpecifierID:
+ {
+ emitPropertyOverride((IMXMLPropertySpecifierNode)anode);
+ break;
+ }
+ case MXMLStyleSpecifierID:
+ {
+ emitStyleOverride((IMXMLStyleSpecifierNode)node);
+ break;
+ }
+ case MXMLEventSpecifierID:
+ {
+ emitEventOverride((IMXMLEventSpecifierNode)node);
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ moveUp(false, false);
+ }
+
+ IMXMLEventSpecifierNode[] enodes = node.getEventSpecifierNodes();
+ if (enodes != null)
+ {
+ moveDown(false, currentInstance, null);
+
+ for (IMXMLEventSpecifierNode enode : enodes)
+ {
+ getMXMLWalker().walk(enode); // Event Specifier
+ }
+
+ moveUp(false, true);
+ }
+ }
+
+ public void emitPropertyOverride(IMXMLPropertySpecifierNode propertyNode)
+ {
+ FlexProject project = (FlexProject) getMXMLWalker().getProject();
+ Name propertyOverride = project.getPropertyOverrideClassName();
+ emitPropertyOrStyleOverride(propertyOverride, propertyNode);
+ }
+
+ /**
+ * Generates instructions in the current context
+ * to create an instance of mx.states.SetStyle
+ * with its <code>target</code>, <code>name</code>,
+ * and <code>value</code> properties set.
+ */
+ void emitStyleOverride(IMXMLStyleSpecifierNode styleNode)
+ {
+ FlexProject project = (FlexProject) getMXMLWalker().getProject();
+ Name styleOverride = project.getStyleOverrideClassName();
+ emitPropertyOrStyleOverride(styleOverride, styleNode);
+ }
+
+ void emitPropertyOrStyleOverride(Name overrideName, IMXMLPropertySpecifierNode propertyOrStyleNode)
+ {
+ MXMLVF2JSDescriptorSpecifier currentInstance = getCurrentDescriptor("ps");
+ IASNode parentNode = propertyOrStyleNode.getParent();
+ String id = parentNode instanceof IMXMLInstanceNode ?
+ ((IMXMLInstanceNode)parentNode).getEffectiveID() :
+ "";
+
+ String name = propertyOrStyleNode.getName();
+
+ IMXMLInstanceNode propertyOrStyleValueNode = propertyOrStyleNode.getInstanceNode();
+
+ MXMLVF2JSDescriptorSpecifier setProp = new MXMLVF2JSDescriptorSpecifier();
+ setProp.isProperty = false;
+ setProp.name = nameToString(overrideName);
+ setProp.parent = currentInstance;
+ currentInstance.propertySpecifiers.add(setProp);
+ // Set its 'target' property to the id of the object
+ // whose property or style this override will set.
+ MXMLVF2JSDescriptorSpecifier target = new MXMLVF2JSDescriptorSpecifier();
+ target.isProperty = true;
+ target.name = "target";
+ target.parent = setProp;
+ target.value = ASEmitterTokens.SINGLE_QUOTE.getToken() + id + ASEmitterTokens.SINGLE_QUOTE.getToken();
+ setProp.propertySpecifiers.add(target);
+
+ // Set its 'name' property to the name of the property or style.
+ MXMLVF2JSDescriptorSpecifier pname = new MXMLVF2JSDescriptorSpecifier();
+ pname.isProperty = true;
+ pname.name = "name";
+ pname.parent = setProp;
+ pname.value = ASEmitterTokens.SINGLE_QUOTE.getToken() + name + ASEmitterTokens.SINGLE_QUOTE.getToken();
+ setProp.propertySpecifiers.add(pname);
+
+ // Set its 'value' property to the value of the property or style.
+ MXMLVF2JSDescriptorSpecifier value = new MXMLVF2JSDescriptorSpecifier();
+ value.isProperty = true;
+ value.name = "value";
+ value.parent = setProp;
+ setProp.propertySpecifiers.add(value);
+ moveDown(false, null, value);
+ getMXMLWalker().walk(propertyOrStyleValueNode); // instance node
+ moveUp(false, false);
+ }
+
+ /**
+ * Generates instructions in the current context
+ * to create an instance of mx.states.SetEventHandler
+ * with its <code>target</code>, <code>name</code>,
+ * and <code>handlerFunction</code> properties set.
+ */
+ void emitEventOverride(IMXMLEventSpecifierNode eventNode)
+ {
+ MXMLVF2JSDescriptorSpecifier currentInstance = getCurrentDescriptor("ps");
+ FlexProject project = (FlexProject) getMXMLWalker().getProject();
+ Name eventOverride = project.getEventOverrideClassName();
+
+ IASNode parentNode = eventNode.getParent();
+ String id = parentNode instanceof IMXMLInstanceNode ?
+ ((IMXMLInstanceNode)parentNode).getEffectiveID() :
+ "";
+
+ String name = eventNode.getName();
+
+ MXMLDocumentNode doc = (MXMLDocumentNode)eventNode.getAncestorOfType(MXMLDocumentNode.class);
+
+ Name eventHandler = doc.cdp.getEventHandlerName(eventNode);
+
+ MXMLVF2JSDescriptorSpecifier setEvent = new MXMLVF2JSDescriptorSpecifier();
+ setEvent.isProperty = true;
+ setEvent.name = nameToString(eventOverride);
+ setEvent.parent = currentInstance;
+ currentInstance.propertySpecifiers.add(setEvent);
+ // Set its 'target' property to the id of the object
+ // whose event this override will set.
+ MXMLVF2JSDescriptorSpecifier target = new MXMLVF2JSDescriptorSpecifier();
+ target.isProperty = true;
+ target.name = "target";
+ target.parent = setEvent;
+ target.value = ASEmitterTokens.SINGLE_QUOTE.getToken() + id + ASEmitterTokens.SINGLE_QUOTE.getToken();
+ setEvent.propertySpecifiers.add(target);
+
+ // Set its 'name' property to the name of the property or style.
+ MXMLVF2JSDescriptorSpecifier pname = new MXMLVF2JSDescriptorSpecifier();
+ pname.isProperty = true;
+ pname.name = "name";
+ pname.parent = setEvent;
+ pname.value = ASEmitterTokens.SINGLE_QUOTE.getToken() + name + ASEmitterTokens.SINGLE_QUOTE.getToken();
+ setEvent.propertySpecifiers.add(pname);
+
+ // Set its 'handlerFunction' property to the autogenerated event handler.
+ MXMLVF2JSDescriptorSpecifier handler = new MXMLVF2JSDescriptorSpecifier();
+ handler.isProperty = false;
+ handler.name = "handlerFunction";
+ handler.parent = setEvent;
+ handler.value = eventHandler.toString();
+ setEvent.propertySpecifiers.add(handler);
+
+ }
+
+ public void emitInstanceOverride(IMXMLInstanceNode instanceNode)
+ {
+ inStatesOverride = true;
+
+ MXMLVF2JSDescriptorSpecifier currentInstance = getCurrentDescriptor("ps");
+ FlexProject project = (FlexProject) getMXMLWalker().getProject();
+ Name instanceOverrideName = project.getInstanceOverrideClassName();
+
+ MXMLVF2JSDescriptorSpecifier addItems = new MXMLVF2JSDescriptorSpecifier();
+ addItems.isProperty = false;
+ addItems.name = nameToString(instanceOverrideName);
+ addItems.parent = currentInstance;
+ currentInstance.propertySpecifiers.add(addItems);
+ MXMLVF2JSDescriptorSpecifier itemsDesc = new MXMLVF2JSDescriptorSpecifier();
+ itemsDesc.isProperty = true;
+ itemsDesc.hasArray = true;
+ itemsDesc.name = "itemsDescriptor";
+ itemsDesc.parent = addItems;
+ addItems.propertySpecifiers.add(itemsDesc);
+ boolean oldInMXMLContent = inMXMLContent;
+ moveDown(false, null, itemsDesc);
+ inMXMLContent = true;
+ getMXMLWalker().walk(instanceNode); // instance node
+ inMXMLContent = oldInMXMLContent;
+ moveUp(false, false);
+
+ //-----------------------------------------------------------------------------
+ // Second property set: maybe set destination and propertyName
+
+ // get the property specifier node for the property the instanceNode represents
+ IMXMLPropertySpecifierNode propertySpecifier = (IMXMLPropertySpecifierNode)
+ instanceNode.getAncestorOfType( IMXMLPropertySpecifierNode.class);
+
+ if (propertySpecifier == null)
+ {
+ assert false; // I think this indicates an invalid tree...
+ }
+ else
+ {
+ // Check the parent - if it's an instance then we want to use these
+ // nodes to get our property values from. If not, then it's the root
+ // and we don't need to specify destination
+
+ IASNode parent = propertySpecifier.getParent();
+ if (parent instanceof IMXMLInstanceNode)
+ {
+ IMXMLInstanceNode parentInstance = (IMXMLInstanceNode)parent;
+ String parentId = parentInstance.getEffectiveID();
+ assert parentId != null;
+ String propName = propertySpecifier.getName();
+
+ MXMLVF2JSDescriptorSpecifier dest = new MXMLVF2JSDescriptorSpecifier();
+ dest.isProperty = true;
+ dest.name = "destination";
+ dest.parent = addItems;
+ dest.value = ASEmitterTokens.SINGLE_QUOTE.getToken() + parentId + ASEmitterTokens.SINGLE_QUOTE.getToken();
+ addItems.propertySpecifiers.add(dest);
+
+ MXMLVF2JSDescriptorSpecifier prop = new MXMLVF2JSDescriptorSpecifier();
+ prop.isProperty = true;
+ prop.name = "propertyName";
+ prop.parent = addItems;
+ prop.value = ASEmitterTokens.SINGLE_QUOTE.getToken() + propName + ASEmitterTokens.SINGLE_QUOTE.getToken();
+ addItems.propertySpecifiers.add(prop);
+ }
+ }
+
+ //---------------------------------------------------------------
+ // Third property set: position and relativeTo
+ String positionPropertyValue = null;
+ String relativeToPropertyValue = null;
+
+ // look to see if we have any sibling nodes that are not state dependent
+ // that come BEFORE us
+ IASNode instanceParent = instanceNode.getParent();
+ IASNode prevStatelessSibling=null;
+ for (int i=0; i< instanceParent.getChildCount(); ++i)
+ {
+ IASNode sib = instanceParent.getChild(i);
+ assert sib instanceof IMXMLInstanceNode; // surely our siblings are also instances?
+
+ // stop looking for previous nodes when we find ourself
+ if (sib == instanceNode)
+ break;
+
+ if (!isStateDependent(sib))
+ {
+ prevStatelessSibling = sib;
+ }
+ }
+
+ if (prevStatelessSibling == null) {
+ positionPropertyValue = "first"; // TODO: these should be named constants
+ }
+ else {
+ positionPropertyValue = "after";
+ relativeToPropertyValue = ((IMXMLInstanceNode)prevStatelessSibling).getEffectiveID();
+ }
+
+ MXMLVF2JSDescriptorSpecifier pos = new MXMLVF2JSDescriptorSpecifier();
+ pos.isProperty = true;
+ pos.name = "position";
+ pos.parent = addItems;
+ pos.value = ASEmitterTokens.SINGLE_QUOTE.getToken() + positionPropertyValue + ASEmitterTokens.SINGLE_QUOTE.getToken();
+ addItems.propertySpecifiers.add(pos);
+
+ if (relativeToPropertyValue != null)
+ {
+ MXMLVF2JSDescriptorSpecifier rel = new MXMLVF2JSDescriptorSpecifier();
+ rel.isProperty = true;
+ rel.name = "relativeTo";
+ rel.parent = addItems;
+ rel.value = ASEmitterTokens.SINGLE_QUOTE.getToken() + relativeToPropertyValue + ASEmitterTokens.SINGLE_QUOTE.getToken();
+ addItems.propertySpecifiers.add(rel);
+ }
+
+ inStatesOverride = false;
+ }
+
+ private String nameToString(Name name)
+ {
+ String s = "";
+ Namespace ns = name.getSingleQualifier();
+ s = ns.getName() + ASEmitterTokens.MEMBER_ACCESS.getToken() + name.getBaseName();
+ return s;
+ }
+ /**
+ * Determines whether a node is state-dependent.
+ * TODO: we should move to IMXMLNode
+ */
+ protected boolean isStateDependent(IASNode node)
+ {
+ if (node instanceof IMXMLSpecifierNode)
+ {
+ String suffix = ((IMXMLSpecifierNode)node).getSuffix();
+ return suffix != null && suffix.length() > 0;
+ }
+ else if (isStateDependentInstance(node))
+ return true;
+ return false;
+ }
+
+ /**
+ * Determines whether the geven node is an instance node, as is state dependent
+ */
+ protected boolean isStateDependentInstance(IASNode node)
+ {
+ if (node instanceof IMXMLInstanceNode)
+ {
+ String[] includeIn = ((IMXMLInstanceNode)node).getIncludeIn();
+ String[] excludeFrom = ((IMXMLInstanceNode)node).getExcludeFrom();
+ return includeIn != null || excludeFrom != null;
+ }
+ return false;
+ }
+
+ /**
+ * Is a give node a "databinding node"?
+ */
+ public static boolean isDataBindingNode(IASNode node)
+ {
+ return node instanceof IMXMLDataBindingNode;
+ }
+
+ protected static boolean isDataboundProp(IMXMLPropertySpecifierNode propertyNode)
+ {
+ boolean ret = propertyNode.getChildCount() > 0 && isDataBindingNode(propertyNode.getInstanceNode());
+
+ // Sanity check that we based our conclusion about databinding on the correct node.
+ // (code assumes only one child if databinding)
+ int n = propertyNode.getChildCount();
+ for (int i = 0; i < n; i++)
+ {
+ boolean db = isDataBindingNode(propertyNode.getChild(i));
+ assert db == ret;
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void emitPropertySpecifier(IMXMLPropertySpecifierNode node)
+ {
+ if (isDataboundProp(node))
+ return;
+
+ IDefinition cdef = node.getDefinition();
+
+ IASNode cnode = node.getChild(0);
+
+ MXMLVF2JSDescriptorSpecifier currentInstance = getCurrentDescriptor("i");
+
+ MXMLVF2JSDescriptorSpecifier currentPropertySpecifier = new MXMLVF2JSDescriptorSpecifier();
+ currentPropertySpecifier.isProperty = true;
+ currentPropertySpecifier.name = cdef.getQualifiedName();
+ currentPropertySpecifier.parent = currentInstance;
+
+ boolean oldInMXMLContent = inMXMLContent;
+ if (currentPropertySpecifier.name.equals("mxmlContent"))
+ inMXMLContent = true;
+
+ if (currentInstance != null)
+ currentInstance.propertySpecifiers.add(currentPropertySpecifier);
+ else if (inMXMLContent)
+ descriptorTree.add(currentPropertySpecifier);
+ else
+ {
+ currentPropertySpecifier.parent = propertiesTree;
+ propertiesTree.propertySpecifiers.add(currentPropertySpecifier);
+ }
+
+ boolean bypass = cnode != null && cnode instanceof IMXMLArrayNode;
+
+ currentPropertySpecifier.hasArray = bypass;
+
+ moveDown(bypass, null, currentPropertySpecifier);
+
+ getMXMLWalker().walk(cnode); // Array or Instance
+
+ moveUp(bypass, false);
+
+ inMXMLContent = oldInMXMLContent;
+ }
+
+ @Override
+ public void emitScript(IMXMLScriptNode node)
+ {
+ IASEmitter asEmitter = ((IMXMLBlockWalker) getMXMLWalker())
+ .getASEmitter();
+
+ String nl = ASEmitterTokens.NEW_LINE.getToken();
+
+ StringBuilder sb = null;
+ MXMLScriptSpecifier scriptSpecifier = null;
+
+ int len = node.getChildCount();
+ if (len > 0)
+ {
+ for (int i = 0; i < len; i++)
+ {
+ IASNode cnode = node.getChild(i);
+
+ if (!(cnode instanceof IImportNode))
+ {
+ sb = new StringBuilder();
+ scriptSpecifier = new MXMLScriptSpecifier();
+
+ sb.append(asEmitter.stringifyNode(cnode));
+
+ sb.append(ASEmitterTokens.SEMICOLON.getToken());
+
+ if (i == len - 1)
+ indentPop();
+
+ sb.append(nl);
+ sb.append(nl);
+
+ scriptSpecifier.fragment = sb.toString();
+
+ scripts.add(scriptSpecifier);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void emitStyleSpecifier(IMXMLStyleSpecifierNode node)
+ {
+ }
+
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitArray(IMXMLArrayNode node)
+ {
+ moveDown(false, null, null);
+
+ final int len = node.getChildCount();
+ for (int i = 0; i < len; i++)
+ {
+ getMXMLWalker().walk(node.getChild(i)); // Instance
+ }
+
+ moveUp(false, false);
+ }
+
+ @Override
+ public void emitString(IMXMLStringNode node)
+ {
+ getCurrentDescriptor("ps").valueNeedsQuotes = true;
+
+ emitAttributeValue(node);
+ }
+
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitLiteral(IMXMLLiteralNode node)
+ {
+ MXMLVF2JSDescriptorSpecifier ps = getCurrentDescriptor("ps");
+ ps.value = "";
+
+ if (ps.valueNeedsQuotes)
+ ps.value += ASEmitterTokens.SINGLE_QUOTE.getToken();
+
+ String s = node.getValue().toString();
+ if (ps.valueNeedsQuotes)
+ {
+ // escape all single quotes found within the string
+ s = s.replace(ASEmitterTokens.SINGLE_QUOTE.getToken(),
+ "\\" + ASEmitterTokens.SINGLE_QUOTE.getToken());
+ }
+ ps.value += s;
+
+ if (ps.valueNeedsQuotes)
+ ps.value += ASEmitterTokens.SINGLE_QUOTE.getToken();
+ }
+
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitFactory(IMXMLFactoryNode node)
+ {
+ MXMLVF2JSDescriptorSpecifier ps = getCurrentDescriptor("ps");
+ ps.value = "new mx.core.ClassFactory(";
+
+ IASNode cnode = node.getChild(0);
+ if (cnode instanceof IMXMLClassNode)
+ {
+ ps.value += ((IMXMLClassNode)cnode).getValue(getMXMLWalker().getProject()).getQualifiedName();
+ }
+ ps.value += ")";
+ }
+
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitComponent(IMXMLComponentNode node)
+ {
+ MXMLVF2JSDescriptorSpecifier ps = getCurrentDescriptor("ps");
+ ps.value = "new mx.core.ClassFactory(";
+
+ ps.value += node.getName();
+ ps.value += ")";
+
+ setBufferWrite(true);
+ emitSubDocument(node);
+ subDocuments.append(getBuilder().toString());
+ getBuilder().setLength(0);
+ setBufferWrite(false);
+ }
+
+ //--------------------------------------------------------------------------
+ // JS output
+ //--------------------------------------------------------------------------
+
+ private void emitEncodedCSS(String cname)
+ {
+ String s = ((MXMLFlexJSBlockWalker)getMXMLWalker()).encodedCSS;
+ if (!s.isEmpty())
+ {
+ int reqidx = s.indexOf("goog.require");
+ if (reqidx != -1)
+ s = s.substring(0, reqidx - 1);
+
+ writeNewline();
+ writeNewline("/**");
+ writeNewline(" * @expose");
+ writeNewline(" */");
+ StringBuilder sb = new StringBuilder();
+ sb.append(cname);
+ sb.append(ASEmitterTokens.MEMBER_ACCESS.getToken());
+ sb.append(JSEmitterTokens.PROTOTYPE.getToken());
+ sb.append(ASEmitterTokens.MEMBER_ACCESS.getToken());
+ sb.append("cssData");
+ sb.append(ASEmitterTokens.SPACE.getToken() +
+ ASEmitterTokens.EQUAL.getToken() +
+ ASEmitterTokens.SPACE.getToken() +
+ ASEmitterTokens.SQUARE_OPEN.getToken());
+ sb.append(s);
+ write(sb.toString());
+ writeNewline();
+ }
+ }
+
+ private void emitHeader(IMXMLDocumentNode node)
+ {
+ String cname = node.getFileNode().getName();
+ String bcname = node.getBaseClassName();
+
+ writeNewline("/**");
+ writeNewline(" * " + cname);
+ writeNewline(" *");
+ writeNewline(" * @fileoverview");
+ writeNewline(" *");
+ writeNewline(" * @suppress {checkTypes}");
+ writeNewline(" */");
+ writeNewline();
+
+ emitHeaderLine(cname, true); // provide
+ for (String subDocumentName : subDocumentNames)
+ emitHeaderLine(subDocumentName, true);
+ writeNewline();
+ emitHeaderLine(bcname);
+ ArrayList<String> writtenInstances = new ArrayList<String>();
+ writtenInstances.add(cname); // make sure we don't add ourselves
+ writtenInstances.add(bcname); // make sure we don't add the baseclass twice
+ for (MXMLVF2JSDescriptorSpecifier instance : instances)
+ {
+ String name = instance.name;
+ if (writtenInstances.indexOf(name) == -1)
+ {
+ emitHeaderLine(name);
+ writtenInstances.add(name);
+ }
+ }
+ FlexJSProject project = (FlexJSProject) getMXMLWalker().getProject();
+ ASProjectScope projectScope = (ASProjectScope) project.getScope();
+ IDefinition cdef = node.getDefinition();
+ ICompilationUnit cu = projectScope
+ .getCompilationUnitForDefinition(cdef);
+ ArrayList<String> deps = project.getRequires(cu);
+
+ if (deps != null)
+ {
+ for (String imp : deps)
+ {
+ if (imp.indexOf(JSGoogEmitterTokens.AS3.getToken()) != -1)
+ continue;
+
+ if (imp.equals(cname))
+ continue;
+
+ if (imp.equals("mx.binding.Binding"))
+ continue;
+ if (imp.equals("mx.binding.BindingManager"))
+ continue;
+ if (imp.equals("mx.binding.FunctionReturnWatcher"))
+ continue;
+ if (imp.equals("mx.binding.PropertyWatcher"))
+ continue;
+ if (imp.equals("mx.binding.StaticPropertyWatcher"))
+ continue;
+ if (imp.equals("mx.binding.XMLWatcher"))
+ continue;
+ if (imp.equals("mx.events.PropertyChangeEvent"))
+ continue;
+ if (imp.equals("mx.events.PropertyChangeEventKind"))
+ continue;
+ if (imp.equals("mx.core.DeferredInstanceFromFunction"))
+ continue;
+
+ if (NativeUtils.isNative(imp))
+ continue;
+
+ if (writtenInstances.indexOf(imp) == -1)
+ {
+ emitHeaderLine(imp);
+ writtenInstances.add(imp);
+ }
+ }
+ }
+
+ String s = ((MXMLFlexJSBlockWalker)getMXMLWalker()).encodedCSS;
+ if (!s.isEmpty())
+ {
+ int reqidx = s.indexOf("goog.require");
+ if (reqidx != -1)
+ {
+ String reqs = s.substring(reqidx);
+ writeNewline(reqs);
+ }
+ }
+
+ // erikdebruin: Add missing language feature support, like the 'is' and
+ // 'as' operators. We don't need to worry about requiring
+ // this in every project: ADVANCED_OPTIMISATIONS will NOT
+ // include any of the code if it is not used in the project.
+ if (project.mainCU != null &&
+ cu.getName().equals(project.mainCU.getName()))
+ {
+ emitHeaderLine(JSFlexJSEmitterTokens.LANGUAGE_QNAME.getToken());
+ }
+
+ writeNewline();
+ writeNewline();
+ }
+
+ private void emitHeaderLine(String qname)
+ {
+ emitHeaderLine(qname, false);
+ }
+
+ private void emitHeaderLine(String qname, boolean isProvide)
+ {
+ write((isProvide) ? JSGoogEmitterTokens.GOOG_PROVIDE
+ : JSGoogEmitterTokens.GOOG_REQUIRE);
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(qname);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ writeNewline(ASEmitterTokens.SEMICOLON);
+ }
+
+ //--------------------------------------------------------------------------
+ // Utils
+ //--------------------------------------------------------------------------
+
+ @Override
+ protected void emitAttributeValue(IASNode node)
+ {
+ IMXMLLiteralNode cnode = (IMXMLLiteralNode) node.getChild(0);
+
+ if (cnode.getValue() != null)
+ getMXMLWalker().walk((IASNode) cnode); // Literal
+ }
+
+ private MXMLVF2JSDescriptorSpecifier getCurrentDescriptor(String type)
+ {
+ MXMLVF2JSDescriptorSpecifier currentDescriptor = null;
+
+ int index;
+
+ if (type.equals("i"))
+ {
+ index = currentInstances.size() - 1;
+ if (index > -1)
+ currentDescriptor = currentInstances.get(index);
+ }
+ else
+ {
+ index = currentPropertySpecifiers.size() - 1;
+ if (index > -1)
+ currentDescriptor = currentPropertySpecifiers.get(index);
+ }
+
+ return currentDescriptor;
+ }
+
+ protected void moveDown(boolean byPass,
+ MXMLVF2JSDescriptorSpecifier currentInstance,
+ MXMLVF2JSDescriptorSpecifier currentPropertySpecifier)
+ {
+ if (!byPass)
+ {
+ if (currentInstance != null)
+ currentInstances.add(currentInstance);
+ }
+
+ if (currentPropertySpecifier != null)
+ currentPropertySpecifiers.add(currentPropertySpecifier);
+ }
+
+ protected void moveUp(boolean byPass, boolean isInstance)
+ {
+ if (!byPass)
+ {
+ int index;
+
+ if (isInstance)
+ {
+ index = currentInstances.size() - 1;
+ if (index > -1)
+ currentInstances.remove(index);
+ }
+ else
+ {
+ index = currentPropertySpecifiers.size() - 1;
+ if (index > -1)
+ currentPropertySpecifiers.remove(index);
+ }
+ }
+ }
+
+}
[4/4] git commit: [flex-falcon] [refs/heads/VF2JS] - Started adding
VF2JS specific compilation classes.
Posted by er...@apache.org.
Started adding VF2JS specific compilation classes.
Signed-off-by: Erik de Bruin <er...@ixsoftware.nl>
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/47c7dbcf
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/47c7dbcf
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/47c7dbcf
Branch: refs/heads/VF2JS
Commit: 47c7dbcf1f22d3af158df484b43ca9f2a3813849
Parents: e5d07f5
Author: Erik de Bruin <er...@ixsoftware.nl>
Authored: Thu Jul 31 14:18:18 2014 +0200
Committer: Erik de Bruin <er...@ixsoftware.nl>
Committed: Thu Jul 31 14:20:10 2014 +0200
----------------------------------------------------------------------
compiler.jx/src/org/apache/flex/compiler/clients/MXMLJSC.java | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/47c7dbcf/compiler.jx/src/org/apache/flex/compiler/clients/MXMLJSC.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/clients/MXMLJSC.java b/compiler.jx/src/org/apache/flex/compiler/clients/MXMLJSC.java
index e97361e..84a1f18 100644
--- a/compiler.jx/src/org/apache/flex/compiler/clients/MXMLJSC.java
+++ b/compiler.jx/src/org/apache/flex/compiler/clients/MXMLJSC.java
@@ -51,11 +51,13 @@ import org.apache.flex.compiler.internal.codegen.js.JSPublisher;
import org.apache.flex.compiler.internal.codegen.js.JSSharedData;
import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogPublisher;
import org.apache.flex.compiler.internal.codegen.mxml.flexjs.MXMLFlexJSPublisher;
+import org.apache.flex.compiler.internal.codegen.mxml.vf2js.MXMLVF2JSPublisher;
import org.apache.flex.compiler.internal.config.FlashBuilderConfigurator;
import org.apache.flex.compiler.internal.driver.as.ASBackend;
import org.apache.flex.compiler.internal.driver.js.amd.AMDBackend;
import org.apache.flex.compiler.internal.driver.js.goog.GoogBackend;
import org.apache.flex.compiler.internal.driver.mxml.flexjs.MXMLFlexJSBackend;
+import org.apache.flex.compiler.internal.driver.mxml.vf2js.MXMLVF2JSBackend;
import org.apache.flex.compiler.internal.projects.CompilerProject;
import org.apache.flex.compiler.internal.projects.FlexJSProject;
import org.apache.flex.compiler.internal.projects.ISourceFileHandler;
@@ -197,7 +199,7 @@ public class MXMLJSC
}
}
- backend = new MXMLFlexJSBackend();
+ backend = new MXMLVF2JSBackend();
break;
}
@@ -376,7 +378,7 @@ public class MXMLJSC
}
case VF2JS: {
- jsPublisher = new MXMLFlexJSPublisher(config, project);
+ jsPublisher = new MXMLVF2JSPublisher(config, project);
break;
}
[3/4] git commit: [flex-falcon] [refs/heads/VF2JS] - Removed
redundant error message display.
Posted by er...@apache.org.
Removed redundant error message display.
Signed-off-by: Erik de Bruin <er...@ixsoftware.nl>
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/cf6b1d12
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/cf6b1d12
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/cf6b1d12
Branch: refs/heads/VF2JS
Commit: cf6b1d1246bcc4982a53b59382426ae60153d853
Parents: 47c7dbc
Author: Erik de Bruin <er...@ixsoftware.nl>
Authored: Thu Jul 31 14:18:57 2014 +0200
Committer: Erik de Bruin <er...@ixsoftware.nl>
Committed: Thu Jul 31 14:20:10 2014 +0200
----------------------------------------------------------------------
.../org/apache/flex/compiler/utils/JSClosureCompilerWrapper.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/cf6b1d12/compiler.jx/src/org/apache/flex/compiler/utils/JSClosureCompilerWrapper.java
----------------------------------------------------------------------
diff --git a/compiler.jx/src/org/apache/flex/compiler/utils/JSClosureCompilerWrapper.java b/compiler.jx/src/org/apache/flex/compiler/utils/JSClosureCompilerWrapper.java
index 9edfa66..05d46dc 100644
--- a/compiler.jx/src/org/apache/flex/compiler/utils/JSClosureCompilerWrapper.java
+++ b/compiler.jx/src/org/apache/flex/compiler/utils/JSClosureCompilerWrapper.java
@@ -31,7 +31,6 @@ import com.google.javascript.jscomp.CompilationLevel;
import com.google.javascript.jscomp.Compiler;
import com.google.javascript.jscomp.CompilerOptions;
import com.google.javascript.jscomp.DiagnosticGroups;
-import com.google.javascript.jscomp.JSError;
import com.google.javascript.jscomp.SourceFile;
import com.google.javascript.jscomp.SourceMap;
import com.google.javascript.jscomp.WarningLevel;
@@ -97,6 +96,7 @@ public class JSClosureCompilerWrapper
System.out.println(error);
}
+ /*
for (JSError message : compiler_.getWarnings())
{
System.err.println("Warning message: " + message.toString());
@@ -106,6 +106,7 @@ public class JSClosureCompilerWrapper
{
System.err.println("Error message: " + message.toString());
}
+ */
}
private void initExterns()