You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by cd...@apache.org on 2016/04/14 09:46:47 UTC
[18/18] git commit: [flex-falcon]
[refs/heads/feature/maven-migration-test] - Merge branch 'develop' of
https://git-wip-us.apache.org/repos/asf/flex-falcon into
feature/maven-migration-test
Merge branch 'develop' of https://git-wip-us.apache.org/repos/asf/flex-falcon into feature/maven-migration-test
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/de070636
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/de070636
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/de070636
Branch: refs/heads/feature/maven-migration-test
Commit: de070636246d09e27b8aa25898cd22aa2dee1ae1
Parents: c3dce49 bc19c66
Author: Christofer Dutz <ch...@codecentric.de>
Authored: Thu Apr 14 09:39:02 2016 +0200
Committer: Christofer Dutz <ch...@codecentric.de>
Committed: Thu Apr 14 09:39:02 2016 +0200
----------------------------------------------------------------------
.../apache/flex/compiler/clients/MXMLJSC.java | 109 ++++++++-------
.../internal/codegen/js/JSSessionModel.java | 2 +
.../codegen/js/flexjs/JSFlexJSEmitter.java | 12 ++
.../codegen/js/jx/BinaryOperatorEmitter.java | 17 +++
.../codegen/js/jx/IdentifierEmitter.java | 14 ++
.../internal/codegen/js/jx/LiteralEmitter.java | 26 ++--
.../internal/codegen/js/utils/EmitterUtils.java | 12 ++
.../internal/codegen/mxml/MXMLWriter.java | 3 +-
.../codegen/mxml/flexjs/MXMLFlexJSEmitter.java | 73 +++++-----
.../mxml/flexjs/MXMLFlexJSPublisher.java | 140 ++++++++++---------
.../driver/js/goog/JSGoogConfiguration.java | 20 +++
.../js/flexjs/TestFlexJSGlobalClasses.java | 58 +++++++-
.../projects/xml_requires/XMLRequire_result.js | 2 +-
13 files changed, 320 insertions(+), 168 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/de070636/compiler-jx/src/main/java/org/apache/flex/compiler/clients/MXMLJSC.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/clients/MXMLJSC.java
index d324c9f,0000000..c6d9508
mode 100644,000000..100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/clients/MXMLJSC.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/clients/MXMLJSC.java
@@@ -1,847 -1,0 +1,852 @@@
+/*
+ *
+ * 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.clients;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.io.FilenameUtils;
+import org.apache.flex.compiler.clients.problems.ProblemPrinter;
+import org.apache.flex.compiler.clients.problems.ProblemQuery;
+import org.apache.flex.compiler.clients.problems.ProblemQueryProvider;
+import org.apache.flex.compiler.clients.problems.WorkspaceProblemFormatter;
+import org.apache.flex.compiler.codegen.js.IJSPublisher;
+import org.apache.flex.compiler.codegen.js.IJSWriter;
+import org.apache.flex.compiler.config.Configuration;
+import org.apache.flex.compiler.config.ConfigurationBuffer;
+import org.apache.flex.compiler.config.Configurator;
+import org.apache.flex.compiler.config.ICompilerSettingsConstants;
+import org.apache.flex.compiler.driver.IBackend;
+import org.apache.flex.compiler.driver.js.IJSApplication;
+import org.apache.flex.compiler.exceptions.ConfigurationException;
+import org.apache.flex.compiler.exceptions.ConfigurationException.IOError;
+import org.apache.flex.compiler.exceptions.ConfigurationException.MustSpecifyTarget;
+import org.apache.flex.compiler.exceptions.ConfigurationException.OnlyOneSource;
+import org.apache.flex.compiler.internal.codegen.js.JSSharedData;
+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.js.goog.JSGoogConfiguration;
+import org.apache.flex.compiler.internal.driver.js.jsc.JSCBackend;
+import org.apache.flex.compiler.internal.driver.js.node.NodeBackend;
+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.parsing.as.FlexJSASDocDelegate;
+import org.apache.flex.compiler.internal.projects.CompilerProject;
+import org.apache.flex.compiler.internal.projects.FlexJSProject;
+import org.apache.flex.compiler.internal.projects.ISourceFileHandler;
+import org.apache.flex.compiler.internal.targets.JSTarget;
+import org.apache.flex.compiler.internal.units.ResourceModuleCompilationUnit;
+import org.apache.flex.compiler.internal.units.SourceCompilationUnitFactory;
+import org.apache.flex.compiler.internal.workspaces.Workspace;
+import org.apache.flex.compiler.problems.ConfigurationProblem;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+import org.apache.flex.compiler.problems.InternalCompilerProblem;
+import org.apache.flex.compiler.problems.UnableToBuildSWFProblem;
+import org.apache.flex.compiler.problems.UnexpectedExceptionProblem;
+import org.apache.flex.compiler.projects.ICompilerProject;
+import org.apache.flex.compiler.targets.ITarget;
+import org.apache.flex.compiler.targets.ITarget.TargetType;
+import org.apache.flex.compiler.targets.ITargetSettings;
+import org.apache.flex.compiler.units.ICompilationUnit;
+import org.apache.flex.tools.FlexTool;
+import org.apache.flex.utils.ArgumentUtil;
+import org.apache.flex.utils.FilenameNormalization;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+/**
+ * @author Erik de Bruin
+ * @author Michael Schmalle
+ */
+public class MXMLJSC implements JSCompilerEntryPoint, ProblemQueryProvider,
+ FlexTool
+{
+ @Override
+ public ProblemQuery getProblemQuery()
+ {
+ return problems;
+ }
+
+ /*
+ * JS output type enumerations.
+ */
+ public enum JSOutputType
+ {
+ AMD("amd"),
+ FLEXJS("flexjs"),
+ GOOG("goog"),
+ VF2JS("vf2js"),
+ FLEXJS_DUAL("flexjs_dual"),
+ JSC("jsc"),
+ NODE("node");
+
+ private String text;
+
+ JSOutputType(String text)
+ {
+ this.text = text;
+ }
+
+ public String getText()
+ {
+ return this.text;
+ }
+
+ public static JSOutputType fromString(String text)
+ {
+ for (JSOutputType jsOutputType : JSOutputType.values())
+ {
+ if (text.equalsIgnoreCase(jsOutputType.text))
+ return jsOutputType;
+ }
+ return GOOG;
+ }
+ }
+
+ /*
+ * Exit code enumerations.
+ */
+ static enum ExitCode
+ {
+ SUCCESS(0),
+ PRINT_HELP(1),
+ FAILED_WITH_PROBLEMS(2),
+ FAILED_WITH_ERRORS(3),
+ FAILED_WITH_EXCEPTIONS(4),
+ FAILED_WITH_CONFIG_PROBLEMS(5);
+
+ ExitCode(int code)
+ {
+ this.code = code;
+ }
+
+ final int code;
+ }
+
+ public static JSOutputType jsOutputType;
+ public static boolean keepASDoc;
+
+ @Override
+ public String getName()
+ {
+ return FLEX_TOOL_MXMLC;
+ }
+
+ @Override
+ public int execute(String[] args)
+ {
+ final List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+ return mainNoExit(args, problems, true);
+ }
+
+ /**
+ * Java program entry point.
+ *
+ * @param args command line arguments
+ */
+ public static void main(final String[] args)
+ {
+ int exitCode = staticMainNoExit(args);
+ System.exit(exitCode);
+ }
+
+ /**
+ * Entry point for the {@code <compc>} Ant task.
+ *
+ * @param args Command line arguments.
+ * @return An exit code.
+ */
+ public static int staticMainNoExit(final String[] args)
+ {
+ long startTime = System.nanoTime();
+
+ IBackend backend = new ASBackend();
+ String jsOutputTypeString = "";
+ for (String s : args)
+ {
+ String[] kvp = s.split("=");
+
+ if (s.contains("-js-output-type"))
+ {
+ jsOutputTypeString = kvp[1];
+ }
+ }
+
+ if (jsOutputTypeString.equals(""))
+ {
+ jsOutputTypeString = JSOutputType.FLEXJS.getText();
+ }
+
+ jsOutputType = JSOutputType.fromString(jsOutputTypeString);
+ switch (jsOutputType)
+ {
+ case AMD:
+ backend = new AMDBackend();
+ break;
+ case JSC:
+ backend = new JSCBackend();
+ break;
+ case NODE:
+ backend = new NodeBackend();
+ break;
+ case FLEXJS:
+ case FLEXJS_DUAL:
+ backend = new MXMLFlexJSBackend();
+ break;
+ case GOOG:
+ backend = new GoogBackend();
+ break;
+ case VF2JS:
+ backend = new MXMLVF2JSBackend();
+ break;
+ // if you add a new js-output-type here, don't forget to also add it
+ // to flex2.tools.MxmlJSC in flex-compiler-oem for IDE support
+ }
+
+ final MXMLJSC mxmlc = new MXMLJSC(backend);
+ final List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
+ final int exitCode = mxmlc.mainNoExit(args, problems, true);
+
+ long endTime = System.nanoTime();
+ JSSharedData.instance.stdout((endTime - startTime) / 1e9 + " seconds");
+
+ return exitCode;
+ }
+
+ protected Workspace workspace;
+ protected FlexJSProject project;
+
+ protected ProblemQuery problems;
+ protected ISourceFileHandler asFileHandler;
+ protected Configuration config;
+ protected Configurator projectConfigurator;
+ private ConfigurationBuffer configBuffer;
+ private ICompilationUnit mainCU;
+ protected ITarget target;
+ protected ITargetSettings targetSettings;
+ protected IJSApplication jsTarget;
+ private IJSPublisher jsPublisher;
+
+ public MXMLJSC(IBackend backend)
+ {
+ JSSharedData.backend = backend;
+ workspace = new Workspace();
+ workspace.setASDocDelegate(new FlexJSASDocDelegate());
+ project = new FlexJSProject(workspace);
+ problems = new ProblemQuery(); // this gets replaced in configure(). Do we need it here?
+ JSSharedData.OUTPUT_EXTENSION = backend.getOutputExtension();
+ JSSharedData.workspace = workspace;
+ asFileHandler = backend.getSourceFileHandlerInstance();
+ }
+
+ @Override
+ public int mainNoExit(final String[] args, List<ICompilerProblem> problems,
+ Boolean printProblems)
+ {
+ int exitCode = -1;
+ try
+ {
+ exitCode = _mainNoExit(ArgumentUtil.fixArgs(args), problems);
+ }
+ catch (Exception e)
+ {
+ JSSharedData.instance.stderr(e.toString());
+ }
+ finally
+ {
+ if (problems != null && !problems.isEmpty())
+ {
+ if (printProblems)
+ {
+ final WorkspaceProblemFormatter formatter = new WorkspaceProblemFormatter(
+ workspace);
+ final ProblemPrinter printer = new ProblemPrinter(formatter);
+ printer.printProblems(problems);
+ }
+ }
+ }
+ return exitCode;
+ }
+
+ /**
+ * Entry point that doesn't call <code>System.exit()</code>. This is for
+ * unit testing.
+ *
+ * @param args command line arguments
+ * @return exit code
+ */
+ private int _mainNoExit(final String[] args,
+ List<ICompilerProblem> outProblems)
+ {
+ ExitCode exitCode = ExitCode.SUCCESS;
+ try
+ {
+ String[] adjustedArgs = args;
+
+ if (jsOutputType != null)
+ {
+ switch (jsOutputType)
+ {
+ case VF2JS:
+ boolean isFlashBuilderProject = useFlashBuilderProjectFiles(args);
+
+ if (isFlashBuilderProject)
+ {
+ adjustedArgs = FlashBuilderConfigurator.computeFlashBuilderArgs(
+ adjustedArgs, getTargetType().getExtension());
+ }
+
+ //String projectFilePath = adjustedArgs[adjustedArgs.length - 1];
+ //
+ //String newProjectFilePath = VF2JSProjectUtils
+ // .createTempProject(projectFilePath,
+ // isFlashBuilderProject);
+ //
+ //adjustedArgs[adjustedArgs.length - 1] = newProjectFilePath;
+
+ break;
+ default:
+ break;
+ }
+ }
+
+ final boolean continueCompilation = configure(adjustedArgs);
+
+ // ToDo (erikdebruin): use JSSharedData for globals ...
+ keepASDoc = ((JSGoogConfiguration) config).getKeepASDoc();
+
+ if (outProblems != null && !config.isVerbose())
+ JSSharedData.STDOUT = JSSharedData.STDERR = null;
+
+ if (continueCompilation)
+ {
+ project.setProblems(problems.getProblems());
- compile();
++ compile();
+ if (problems.hasFilteredProblems())
+ {
+ if (problems.hasErrors())
+ exitCode = ExitCode.FAILED_WITH_ERRORS;
+ else
+ exitCode = ExitCode.FAILED_WITH_PROBLEMS;
+ }
+ }
+ else if (problems.hasFilteredProblems())
+ {
+ exitCode = ExitCode.FAILED_WITH_CONFIG_PROBLEMS;
+ }
+ else
+ {
+ exitCode = ExitCode.PRINT_HELP;
+ }
+ }
+ catch (Exception e)
+ {
+ if (outProblems == null)
+ JSSharedData.instance.stderr(e.getMessage());
+ else
+ {
+ final ICompilerProblem unexpectedExceptionProblem = new UnexpectedExceptionProblem(
+ e);
+ problems.add(unexpectedExceptionProblem);
+ }
+ exitCode = ExitCode.FAILED_WITH_EXCEPTIONS;
+ }
+ finally
+ {
+ waitAndClose();
+
+ if (outProblems != null && problems.hasFilteredProblems())
+ {
+ for (ICompilerProblem problem : problems.getFilteredProblems())
+ {
+ outProblems.add(problem);
+ }
+ }
+ }
+ return exitCode.code;
+ }
+
+ /**
+ * Main body of this program. This method is called from the public static
+ * method's for this program.
+ *
+ * @return true if compiler succeeds
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ protected boolean compile()
+ {
+ boolean compilationSuccess = false;
+
+ try
+ {
+ project.getSourceCompilationUnitFactory().addHandler(asFileHandler);
+
- if (!setupTargetFile())
- return false;
-
- buildArtifact();
++ if (!((JSGoogConfiguration) config).getSkipTranspile())
++ {
++ if (!setupTargetFile())
++ return false;
+
- if (jsTarget != null)
++ buildArtifact();
++ }
++ if (jsTarget != null || ((JSGoogConfiguration) config).getSkipTranspile())
+ {
+ List<ICompilerProblem> errors = new ArrayList<ICompilerProblem>();
+ List<ICompilerProblem> warnings = new ArrayList<ICompilerProblem>();
+
+ if (!config.getCreateTargetWithErrors())
+ {
+ problems.getErrorsAndWarnings(errors, warnings);
+ if (errors.size() > 0)
+ return false;
+ }
+
+ jsPublisher = (IJSPublisher) JSSharedData.backend.createPublisher(
+ project, errors, config);
+
+ File outputFolder = jsPublisher.getOutputFolder();
+
- ArrayList<ICompilationUnit> roots = new ArrayList<ICompilationUnit>();
- roots.add(mainCU);
- Set<ICompilationUnit> incs = target.getIncludesCompilationUnits();
- roots.addAll(incs);
- List<ICompilationUnit> reachableCompilationUnits = project.getReachableCompilationUnitsInSWFOrder(roots);
- for (final ICompilationUnit cu : reachableCompilationUnits)
++ if (!((JSGoogConfiguration) config).getSkipTranspile())
+ {
- ICompilationUnit.UnitType cuType = cu.getCompilationUnitType();
-
- if (cuType == ICompilationUnit.UnitType.AS_UNIT
- || cuType == ICompilationUnit.UnitType.MXML_UNIT)
- {
- final File outputClassFile = getOutputClassFile(
- cu.getQualifiedNames().get(0), outputFolder);
-
- System.out.println("Compiling file: " + outputClassFile);
-
- ICompilationUnit unit = cu;
-
- IJSWriter writer;
- if (cuType == ICompilationUnit.UnitType.AS_UNIT)
- {
- writer = (IJSWriter) JSSharedData.backend.createWriter(project,
- errors, unit, false);
- }
- else
- {
- writer = (IJSWriter) JSSharedData.backend.createMXMLWriter(
- project, errors, unit, false);
- }
-
- BufferedOutputStream out = new BufferedOutputStream(
- new FileOutputStream(outputClassFile));
-
- File outputSourceMapFile = null;
- if (project.config.getSourceMap())
- {
- outputSourceMapFile = getOutputSourceMapFile(
- cu.getQualifiedNames().get(0), outputFolder);
- }
-
- writer.writeTo(out, outputSourceMapFile);
- out.flush();
- out.close();
- writer.close();
- }
++ ArrayList<ICompilationUnit> roots = new ArrayList<ICompilationUnit>();
++ roots.add(mainCU);
++ Set<ICompilationUnit> incs = target.getIncludesCompilationUnits();
++ roots.addAll(incs);
++ List<ICompilationUnit> reachableCompilationUnits = project.getReachableCompilationUnitsInSWFOrder(roots);
++ for (final ICompilationUnit cu : reachableCompilationUnits)
++ {
++ ICompilationUnit.UnitType cuType = cu.getCompilationUnitType();
++
++ if (cuType == ICompilationUnit.UnitType.AS_UNIT
++ || cuType == ICompilationUnit.UnitType.MXML_UNIT)
++ {
++ final File outputClassFile = getOutputClassFile(
++ cu.getQualifiedNames().get(0), outputFolder);
++
++ System.out.println("Compiling file: " + outputClassFile);
++
++ ICompilationUnit unit = cu;
++
++ IJSWriter writer;
++ if (cuType == ICompilationUnit.UnitType.AS_UNIT)
++ {
++ writer = (IJSWriter) JSSharedData.backend.createWriter(project,
++ errors, unit, false);
++ }
++ else
++ {
++ writer = (IJSWriter) JSSharedData.backend.createMXMLWriter(
++ project, errors, unit, false);
++ }
++
++ BufferedOutputStream out = new BufferedOutputStream(
++ new FileOutputStream(outputClassFile));
++
++ File outputSourceMapFile = null;
++ if (project.config.getSourceMap())
++ {
++ outputSourceMapFile = getOutputSourceMapFile(
++ cu.getQualifiedNames().get(0), outputFolder);
++ }
++
++ writer.writeTo(out, outputSourceMapFile);
++ out.flush();
++ out.close();
++ writer.close();
++ }
++ }
+ }
-
++
+ if (jsPublisher != null)
+ {
+ compilationSuccess = jsPublisher.publish(problems);
+ }
+ else
+ {
+ compilationSuccess = true;
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ final ICompilerProblem problem = new InternalCompilerProblem(e);
+ problems.add(problem);
+ }
+
+ return compilationSuccess;
+ }
+
+ /**
+ * Build target artifact.
+ *
+ * @throws InterruptedException threading error
+ * @throws IOException IO error
+ * @throws ConfigurationException
+ */
+ protected void buildArtifact() throws InterruptedException, IOException,
+ ConfigurationException
+ {
+ jsTarget = buildJSTarget();
+ }
+
+ private IJSApplication buildJSTarget() throws InterruptedException,
+ FileNotFoundException, ConfigurationException
+ {
+ final List<ICompilerProblem> problemsBuildingSWF = new ArrayList<ICompilerProblem>();
+
+ project.mainCU = mainCU;
+ final IJSApplication app = buildApplication(project,
+ config.getMainDefinition(), mainCU, problemsBuildingSWF);
+ problems.addAll(problemsBuildingSWF);
+ if (app == null)
+ {
+ ICompilerProblem problem = new UnableToBuildSWFProblem(
+ getOutputFilePath());
+ problems.add(problem);
+ }
+
+ return app;
+ }
+
+ /**
+ * Replaces FlexApplicationProject::buildSWF()
+ *
+ * @param applicationProject
+ * @param rootClassName
+ * @param problems
+ * @return
+ * @throws InterruptedException
+ */
+
+ private IJSApplication buildApplication(CompilerProject applicationProject,
+ String rootClassName, ICompilationUnit mainCU,
+ Collection<ICompilerProblem> problems) throws InterruptedException,
+ ConfigurationException, FileNotFoundException
+ {
+ Collection<ICompilerProblem> fatalProblems = applicationProject.getFatalProblems();
+ if (!fatalProblems.isEmpty())
+ {
+ problems.addAll(fatalProblems);
+ return null;
+ }
+
+ return ((JSTarget) target).build(mainCU, problems);
+ }
+
+ /**
+ * Get the output file path. If {@code -output} is specified, use its value;
+ * otherwise, use the same base name as the target file.
+ *
+ * @return output file path
+ */
+ private String getOutputFilePath()
+ {
+ if (config.getOutput() == null)
+ {
+ final String extension = "." + JSSharedData.OUTPUT_EXTENSION;
+ return FilenameUtils.removeExtension(config.getTargetFile()).concat(
+ extension);
+ }
+ else
+ return config.getOutput();
+ }
+
+ /**
+ * @author Erik de Bruin
+ *
+ * Get the output class file. This includes the (sub)directory in
+ * which the original class file lives. If the directory structure
+ * doesn't exist, it is created.
+ *
+ * @param qname
+ * @param outputFolder
+ * @return output class file path
+ */
+ private File getOutputClassFile(String qname, File outputFolder)
+ {
+ String[] cname = qname.split("\\.");
+ String sdirPath = outputFolder + File.separator;
+ if (cname.length > 0)
+ {
+ for (int i = 0, n = cname.length - 1; i < n; i++)
+ {
+ sdirPath += cname[i] + File.separator;
+ }
+
+ File sdir = new File(sdirPath);
+ if (!sdir.exists())
+ sdir.mkdirs();
+
+ qname = cname[cname.length - 1];
+ }
+
+ return new File(sdirPath + qname + "." + JSSharedData.OUTPUT_EXTENSION);
+ }
+
+ /**
+ * @param qname
+ * @param outputFolder
+ * @return output source map file path
+ */
+ private File getOutputSourceMapFile(String qname, File outputFolder)
+ {
+ String[] cname = qname.split("\\.");
+ String sdirPath = outputFolder + File.separator;
+ if (cname.length > 0)
+ {
+ for (int i = 0, n = cname.length - 1; i < n; i++)
+ {
+ sdirPath += cname[i] + File.separator;
+ }
+
+ File sdir = new File(sdirPath);
+ if (!sdir.exists())
+ sdir.mkdirs();
+
+ qname = cname[cname.length - 1];
+ }
+
+ return new File(sdirPath + qname + "." + JSSharedData.OUTPUT_EXTENSION + ".map");
+ }
+
+ /**
+ * Mxmlc uses target file as the main compilation unit and derive the output
+ * SWF file name from this file.
+ *
+ * @return true if successful, false otherwise.
+ * @throws OnlyOneSource
+ * @throws InterruptedException
+ */
+ protected boolean setupTargetFile() throws InterruptedException
+ {
+ final String mainFileName = config.getTargetFile();
+
+ final String normalizedMainFileName = FilenameNormalization.normalize(mainFileName);
+
+ final SourceCompilationUnitFactory compilationUnitFactory = project.getSourceCompilationUnitFactory();
+
+ File normalizedMainFile = new File(normalizedMainFileName);
+ if (compilationUnitFactory.canCreateCompilationUnit(normalizedMainFile))
+ {
+ project.addIncludeSourceFile(normalizedMainFile);
+
+ final List<String> sourcePath = config.getCompilerSourcePath();
+ String mainQName = null;
+ if (sourcePath != null && !sourcePath.isEmpty())
+ {
+ for (String path : sourcePath)
+ {
+ final String otherPath = new File(path).getAbsolutePath();
+ if (mainFileName.startsWith(otherPath))
+ {
+ mainQName = mainFileName.substring(otherPath.length() + 1);
+ mainQName = mainQName.replaceAll("\\\\", "/");
+ mainQName = mainQName.replaceAll("\\/", ".");
+ if (mainQName.endsWith(".as"))
+ mainQName = mainQName.substring(0,
+ mainQName.length() - 3);
+ break;
+ }
+ }
+ }
+
+ if (mainQName == null)
+ mainQName = FilenameUtils.getBaseName(mainFileName);
+
+ Collection<ICompilationUnit> mainFileCompilationUnits = workspace.getCompilationUnits(
+ normalizedMainFileName, project);
+
+ mainCU = Iterables.getOnlyElement(mainFileCompilationUnits);
+
+ config.setMainDefinition(mainQName);
+ }
+
+ Preconditions.checkNotNull(mainCU,
+ "Main compilation unit can't be null");
+
+ ITargetSettings settings = getTargetSettings();
+ if (settings != null)
+ project.setTargetSettings(settings);
+
+ target = JSSharedData.backend.createTarget(project,
+ getTargetSettings(), null);
+
+ return true;
+ }
+
+ private ITargetSettings getTargetSettings()
+ {
+ if (targetSettings == null)
+ targetSettings = projectConfigurator.getTargetSettings(null);
+
+ return targetSettings;
+ }
+
+ /**
+ * Create a new Configurator. This method may be overridden to allow
+ * Configurator subclasses to be created that have custom configurations.
+ *
+ * @return a new instance or subclass of {@link Configurator}.
+ */
+ protected Configurator createConfigurator()
+ {
+ return JSSharedData.backend.createConfigurator();
+ }
+
+ /**
+ * Load configurations from all the sources.
+ *
+ * @param args command line arguments
+ * @return True if mxmlc should continue with compilation.
+ */
+ protected boolean configure(final String[] args)
+ {
+ project.getSourceCompilationUnitFactory().addHandler(asFileHandler);
+ projectConfigurator = createConfigurator();
+
+ try
+ {
+ if (useFlashBuilderProjectFiles(args)
+ && !jsOutputType.equals(JSOutputType.VF2JS))
+ {
+ projectConfigurator.setConfiguration(
+ FlashBuilderConfigurator.computeFlashBuilderArgs(args,
+ getTargetType().getExtension()),
+ ICompilerSettingsConstants.FILE_SPECS_VAR);
+ }
+ else
+ {
+ projectConfigurator.setConfiguration(args,
+ ICompilerSettingsConstants.FILE_SPECS_VAR);
+ }
+
+ projectConfigurator.applyToProject(project);
+ problems = new ProblemQuery(
+ projectConfigurator.getCompilerProblemSettings());
+
+ project.config = (JSGoogConfiguration)projectConfigurator.getConfiguration();
+ config = projectConfigurator.getConfiguration();
+ configBuffer = projectConfigurator.getConfigurationBuffer();
+ problems.addAll(projectConfigurator.getConfigurationProblems());
+
+ if (configBuffer.getVar("version") != null) //$NON-NLS-1$
+ return false;
+
+ if (problems.hasErrors())
+ return false;
+
+ validateTargetFile();
+ return true;
+ }
+ catch (ConfigurationException e)
+ {
+ final ICompilerProblem problem = new ConfigurationProblem(e);
+ problems.add(problem);
+ return false;
+ }
+ catch (Exception e)
+ {
+ final ICompilerProblem problem = new ConfigurationProblem(null, -1,
+ -1, -1, -1, e.getMessage());
+ problems.add(problem);
+ return false;
+ }
+ finally
+ {
+ if (config == null)
+ {
+ config = new Configuration();
+ configBuffer = new ConfigurationBuffer(Configuration.class,
+ Configuration.getAliases());
+ }
+ }
+ }
+
+ private boolean useFlashBuilderProjectFiles(String[] args)
+ {
+ for (String arg : args)
+ {
+ if (arg.equals("-fb")
+ || arg.equals("-use-flashbuilder-project-files"))
+ return true;
+ }
+ return false;
+ }
+
+ protected TargetType getTargetType()
+ {
+ return TargetType.SWF;
+ }
+
+ /**
+ * Validate target file.
+ *
+ * @throws MustSpecifyTarget
+ * @throws IOError
+ */
+ protected void validateTargetFile() throws ConfigurationException
+ {
+ if (mainCU instanceof ResourceModuleCompilationUnit)
+ return; //when compiling a Resource Module, no target file is defined.
+
+ final String targetFile = config.getTargetFile();
+ if (targetFile == null)
+ throw new ConfigurationException.MustSpecifyTarget(null, null, -1);
+
+ final File file = new File(targetFile);
+ if (!file.exists())
+ throw new ConfigurationException.IOError(targetFile);
+ }
+
+ /**
+ * Wait till the workspace to finish compilation and close.
+ */
+ protected void waitAndClose()
+ {
+ workspace.startIdleState();
+ try
+ {
+ workspace.close();
+ }
+ finally
+ {
+ workspace.endIdleState(Collections.<ICompilerProject, Set<ICompilationUnit>> emptyMap());
+ }
+ }
+
+ /**
+ * Force terminate the compilation process.
+ */
+ protected void close()
+ {
+ workspace.close();
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/de070636/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSSessionModel.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSSessionModel.java
index 5c45227,0000000..acd8232
mode 100644,000000..100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSSessionModel.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSSessionModel.java
@@@ -1,180 -1,0 +1,182 @@@
+/*
+ *
+ * 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.js;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Stack;
+
+import org.apache.flex.compiler.definitions.IClassDefinition;
+import org.apache.flex.compiler.tree.as.IFunctionNode;
+import org.apache.flex.compiler.tree.as.IGetterNode;
+import org.apache.flex.compiler.tree.as.ISetterNode;
+import org.apache.flex.compiler.tree.as.IVariableNode;
+
+/**
+ * @author Michael Schmalle
+ */
+public class JSSessionModel
+{
+ public static final String CONSTRUCTOR_EMPTY = "emptyConstructor";
+ public static final String CONSTRUCTOR_FULL = "fullConstructor";
+ public static final String SUPER_FUNCTION_CALL = "replaceSuperFunction";
+
+ private IClassDefinition currentClass;
+
+ public static class PropertyNodes
+ {
+ public IGetterNode getter;
+ public ISetterNode setter;
+ }
+
+ private static class Context
+ {
+ public LinkedHashMap<String, PropertyNodes> propertyMap;
+ public List<String> interfacePropertyMap;
+ public LinkedHashMap<String, PropertyNodes> staticPropertyMap;
+ public ArrayList<String> bindableVars;
+ public ArrayList<IVariableNode> vars;
+ public ArrayList<IFunctionNode> methods;
+ public IClassDefinition classDefinition;
+ }
+ private Stack<Context> stack = new Stack<Context>();
+
++ public boolean inE4xFilter = false;
++
+ private LinkedHashMap<String, PropertyNodes> propertyMap = new LinkedHashMap<String, PropertyNodes>();
+
+ private List<String> interfacePropertyMap = new ArrayList<String>();
+
+ private LinkedHashMap<String, PropertyNodes> staticPropertyMap = new LinkedHashMap<String, PropertyNodes>();
+
+ private ArrayList<String> bindableVars = new ArrayList<String>();
+
+ private ArrayList<IVariableNode> vars = new ArrayList<IVariableNode>();
+
+ private ArrayList<IFunctionNode> methods = new ArrayList<IFunctionNode>();
+
+ private HashMap<String, String> internalClasses;
+
+ private int foreachLoopCount = 0;
+
+ public IClassDefinition getCurrentClass()
+ {
+ return currentClass;
+ }
+
+ public void setCurrentClass(IClassDefinition currentClass)
+ {
+ this.currentClass = currentClass;
+ }
+
+ public void pushClass(IClassDefinition currentClass)
+ {
+ Context context = new Context();
+ context.bindableVars = bindableVars;
+ context.interfacePropertyMap = interfacePropertyMap;
+ context.propertyMap = propertyMap;
+ context.staticPropertyMap = staticPropertyMap;
+ context.classDefinition = this.currentClass;
+ context.vars = vars;
+ context.methods = methods;
+ stack.push(context);
+ this.currentClass = currentClass;
+ bindableVars = new ArrayList<String>();
+ staticPropertyMap = new LinkedHashMap<String, PropertyNodes>();
+ interfacePropertyMap = new ArrayList<String>();
+ propertyMap = new LinkedHashMap<String, PropertyNodes>();
+ vars = new ArrayList<IVariableNode>();
+ methods = new ArrayList<IFunctionNode>();
+ }
+
+ public void popClass()
+ {
+ Context context = stack.pop();
+ this.currentClass = context.classDefinition;
+ bindableVars = context.bindableVars;
+ staticPropertyMap = context.staticPropertyMap;
+ propertyMap = context.propertyMap;
+ interfacePropertyMap = context.interfacePropertyMap;
+ vars = context.vars;
+ methods = context.methods;
+ }
+
+ public HashMap<String, PropertyNodes> getPropertyMap()
+ {
+ return propertyMap;
+ }
+
+ public List<String> getInterfacePropertyMap()
+ {
+ return interfacePropertyMap;
+ }
+
+ public HashMap<String, PropertyNodes> getStaticPropertyMap()
+ {
+ return staticPropertyMap;
+ }
+
+ public boolean hasBindableVars()
+ {
+ return bindableVars.size() > 0;
+ }
+
+ public List<String> getBindableVars()
+ {
+ return bindableVars;
+ }
+
+ public List<IVariableNode> getVars()
+ {
+ return vars;
+ }
+
+ public List<IFunctionNode> getMethods()
+ {
+ return methods;
+ }
+
+ public HashMap<String, String> getInternalClasses()
+ {
+ if (internalClasses == null)
+ internalClasses = new HashMap<String, String>();
+ return internalClasses;
+ }
+
+ public boolean isInternalClass(String className)
+ {
+ if (internalClasses == null) return false;
+
+ return internalClasses.containsKey(className);
+ }
+
+ public final void incForeachLoopCount()
+ {
+ foreachLoopCount++;
+ }
+
+ public String getCurrentForeachName()
+ {
+ return "foreachiter" + Integer.toString(foreachLoopCount);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/de070636/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java
index cde30e8,0000000..c954e2c
mode 100644,000000..100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java
@@@ -1,1009 -1,0 +1,1021 @@@
+/*
+ *
+ * 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.js.flexjs;
+
+import java.io.FilterWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.flex.compiler.codegen.js.flexjs.IJSFlexJSEmitter;
+import org.apache.flex.compiler.codegen.js.goog.IJSGoogDocEmitter;
+import org.apache.flex.compiler.constants.IASLanguageConstants;
+import org.apache.flex.compiler.definitions.IClassDefinition;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.definitions.IPackageDefinition;
+import org.apache.flex.compiler.definitions.ITypeDefinition;
+import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitter;
+import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.jx.AccessorEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.AsIsEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.BinaryOperatorEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.BindableEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.ClassEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.DefinePropertyFunctionEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.FieldEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.ForEachEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.FunctionCallEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.IdentifierEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.InterfaceEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.LiteralEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.MemberAccessEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.MethodEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.ObjectDefinePropertyEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.PackageFooterEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.PackageHeaderEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.SelfReferenceEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.SuperCallEmitter;
+import org.apache.flex.compiler.internal.codegen.js.jx.VarDeclarationEmitter;
+import org.apache.flex.compiler.internal.codegen.js.utils.EmitterUtils;
+import org.apache.flex.compiler.internal.codegen.mxml.flexjs.MXMLFlexJSEmitter;
+import org.apache.flex.compiler.internal.definitions.AccessorDefinition;
+import org.apache.flex.compiler.internal.projects.FlexJSProject;
+import org.apache.flex.compiler.internal.projects.FlexProject;
+import org.apache.flex.compiler.internal.tree.as.BinaryOperatorAsNode;
+import org.apache.flex.compiler.internal.tree.as.BlockNode;
+import org.apache.flex.compiler.internal.tree.as.DynamicAccessNode;
+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.LabeledStatementNode;
+import org.apache.flex.compiler.internal.tree.as.MemberAccessExpressionNode;
+import org.apache.flex.compiler.internal.tree.as.NumericLiteralNode;
+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.IAccessorNode;
+import org.apache.flex.compiler.tree.as.IBinaryOperatorNode;
+import org.apache.flex.compiler.tree.as.IClassNode;
+import org.apache.flex.compiler.tree.as.IContainerNode;
+import org.apache.flex.compiler.tree.as.IDefinitionNode;
+import org.apache.flex.compiler.tree.as.IExpressionNode;
+import org.apache.flex.compiler.tree.as.IFileNode;
+import org.apache.flex.compiler.tree.as.IForLoopNode;
+import org.apache.flex.compiler.tree.as.IFunctionCallNode;
+import org.apache.flex.compiler.tree.as.IFunctionNode;
+import org.apache.flex.compiler.tree.as.IFunctionObjectNode;
+import org.apache.flex.compiler.tree.as.IGetterNode;
+import org.apache.flex.compiler.tree.as.IIdentifierNode;
+import org.apache.flex.compiler.tree.as.IInterfaceNode;
+import org.apache.flex.compiler.tree.as.ILiteralNode;
+import org.apache.flex.compiler.tree.as.IMemberAccessExpressionNode;
+import org.apache.flex.compiler.tree.as.INamespaceNode;
+import org.apache.flex.compiler.tree.as.IPackageNode;
+import org.apache.flex.compiler.tree.as.IScopedNode;
+import org.apache.flex.compiler.tree.as.ISetterNode;
+import org.apache.flex.compiler.tree.as.IUnaryOperatorNode;
+import org.apache.flex.compiler.tree.as.IVariableNode;
+import org.apache.flex.compiler.utils.ASNodeUtils;
+
+import com.google.common.base.Joiner;
+
+/**
+ * Concrete implementation of the 'FlexJS' JavaScript production.
+ *
+ * @author Michael Schmalle
+ * @author Erik de Bruin
+ */
+public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
+{
+
+ private JSFlexJSDocEmitter docEmitter = null;
+
+ private PackageHeaderEmitter packageHeaderEmitter;
+ public PackageFooterEmitter packageFooterEmitter;
+
+ private BindableEmitter bindableEmitter;
+
+ private ClassEmitter classEmitter;
+ private InterfaceEmitter interfaceEmitter;
+
+ private FieldEmitter fieldEmitter;
+ public VarDeclarationEmitter varDeclarationEmitter;
+ public AccessorEmitter accessorEmitter;
+ public MethodEmitter methodEmitter;
+
+ private FunctionCallEmitter functionCallEmitter;
+ private SuperCallEmitter superCallEmitter;
+ private ForEachEmitter forEachEmitter;
+ private MemberAccessEmitter memberAccessEmitter;
+ private BinaryOperatorEmitter binaryOperatorEmitter;
+ private IdentifierEmitter identifierEmitter;
+ private LiteralEmitter literalEmitter;
+
+ private AsIsEmitter asIsEmitter;
+ private SelfReferenceEmitter selfReferenceEmitter;
+ private ObjectDefinePropertyEmitter objectDefinePropertyEmitter;
+ private DefinePropertyFunctionEmitter definePropertyFunctionEmitter;
+
+ public ArrayList<String> usedNames = new ArrayList<String>();
+
+ @Override
+ public String postProcess(String output)
+ {
+ output = super.postProcess(output);
+
+ String[] lines = output.split("\n");
+ ArrayList<String> finalLines = new ArrayList<String>();
+ boolean foundLanguage = false;
+ boolean foundXML = false;
+ boolean sawRequires = false;
+ boolean stillSearching = true;
+ int addIndex = -1;
+ int len = lines.length;
+ for (int i = 0; i < len; i++)
+ {
+ String line = lines[i];
+ if (stillSearching)
+ {
+ int c = line.indexOf(JSGoogEmitterTokens.GOOG_PROVIDE.getToken());
+ if (c != -1)
+ {
+ // if zero requires are found, require Language after the
+ // call to goog.provide
+ addIndex = i + 1;
+ }
+ c = line.indexOf(JSGoogEmitterTokens.GOOG_REQUIRE.getToken());
+ if (c != -1)
+ {
+ // we found other requires, so we'll just add Language at
+ // the end of the list
+ addIndex = -1;
+ int c2 = line.indexOf(")");
+ String s = line.substring(c + 14, c2 - 1);
+ if (s.equals(JSFlexJSEmitterTokens.LANGUAGE_QNAME.getToken()))
+ {
+ foundLanguage = true;
+ }
+ else if (s.equals(IASLanguageConstants.XML))
+ {
+ foundXML = true;
+ }
+ sawRequires = true;
+ if (!usedNames.contains(s))
+ {
+ removeLineFromMappings(i);
+ continue;
+ }
+ }
+ else if (sawRequires || i == len - 1)
+ {
+ stillSearching = false;
+
+ //when we emitted the requires based on the imports, we may
+ //not have known if Language was needed yet because the
+ //imports are at the beginning of the file. other code,
+ //later in the file, may require Language.
+ ICompilerProject project = getWalker().getProject();
+ if (project instanceof FlexJSProject)
+ {
+ FlexJSProject flexJSProject = (FlexJSProject) project;
+ boolean needLanguage = flexJSProject.needLanguage;
+ if (needLanguage && !foundLanguage)
+ {
+ StringBuilder appendString = new StringBuilder();
+ appendString.append(JSGoogEmitterTokens.GOOG_REQUIRE.getToken());
+ appendString.append(ASEmitterTokens.PAREN_OPEN.getToken());
+ appendString.append(ASEmitterTokens.SINGLE_QUOTE.getToken());
+ appendString.append(JSFlexJSEmitterTokens.LANGUAGE_QNAME.getToken());
+ appendString.append(ASEmitterTokens.SINGLE_QUOTE.getToken());
+ appendString.append(ASEmitterTokens.PAREN_CLOSE.getToken());
+ appendString.append(ASEmitterTokens.SEMICOLON.getToken());
+ if(addIndex != -1)
+ {
+ // if we didn't find other requires, this index
+ // points to the line after goog.provide
+ finalLines.add(addIndex, appendString.toString());
+ addLineToMappings(addIndex);
+ }
+ else
+ {
+ finalLines.add(appendString.toString());
+ addLineToMappings(i);
+ }
+ }
+ boolean needXML = flexJSProject.needXML;
+ if (needXML && !foundXML)
+ {
+ StringBuilder appendString = new StringBuilder();
+ appendString.append(JSGoogEmitterTokens.GOOG_REQUIRE.getToken());
+ appendString.append(ASEmitterTokens.PAREN_OPEN.getToken());
+ appendString.append(ASEmitterTokens.SINGLE_QUOTE.getToken());
+ appendString.append(IASLanguageConstants.XML);
+ appendString.append(ASEmitterTokens.SINGLE_QUOTE.getToken());
+ appendString.append(ASEmitterTokens.PAREN_CLOSE.getToken());
+ appendString.append(ASEmitterTokens.SEMICOLON.getToken());
+ if(addIndex != -1)
+ {
+ // if we didn't find other requires, this index
+ // points to the line after goog.provide
+ finalLines.add(addIndex, appendString.toString());
+ addLineToMappings(addIndex);
+ }
+ else
+ {
+ finalLines.add(appendString.toString());
+ addLineToMappings(i);
+ }
+ }
+ }
+ }
+ }
+ finalLines.add(line);
+ }
+
+ return Joiner.on("\n").join(finalLines);
+ }
+
+ public BindableEmitter getBindableEmitter()
+ {
+ return bindableEmitter;
+ }
+
+ public ClassEmitter getClassEmiter()
+ {
+ return classEmitter;
+ }
+
+ public AccessorEmitter getAccessorEmitter()
+ {
+ return accessorEmitter;
+ }
+
+ public PackageFooterEmitter getPackageFooterEmitter()
+ {
+ return packageFooterEmitter;
+ }
+
+ // TODO (mschmalle) Fix; this is not using the backend doc strategy for replacement
+ @Override
+ public IJSGoogDocEmitter getDocEmitter()
+ {
+ if (docEmitter == null)
+ docEmitter = new JSFlexJSDocEmitter(this);
+ return docEmitter;
+ }
+
+ public JSFlexJSEmitter(FilterWriter out)
+ {
+ super(out);
+
+ packageHeaderEmitter = new PackageHeaderEmitter(this);
+ packageFooterEmitter = new PackageFooterEmitter(this);
+
+ bindableEmitter = new BindableEmitter(this);
+
+ classEmitter = new ClassEmitter(this);
+ interfaceEmitter = new InterfaceEmitter(this);
+
+ fieldEmitter = new FieldEmitter(this);
+ varDeclarationEmitter = new VarDeclarationEmitter(this);
+ accessorEmitter = new AccessorEmitter(this);
+ methodEmitter = new MethodEmitter(this);
+
+ functionCallEmitter = new FunctionCallEmitter(this);
+ superCallEmitter = new SuperCallEmitter(this);
+ forEachEmitter = new ForEachEmitter(this);
+ memberAccessEmitter = new MemberAccessEmitter(this);
+ binaryOperatorEmitter = new BinaryOperatorEmitter(this);
+ identifierEmitter = new IdentifierEmitter(this);
+ literalEmitter = new LiteralEmitter(this);
+
+ asIsEmitter = new AsIsEmitter(this);
+ selfReferenceEmitter = new SelfReferenceEmitter(this);
+ objectDefinePropertyEmitter = new ObjectDefinePropertyEmitter(this);
+ definePropertyFunctionEmitter = new DefinePropertyFunctionEmitter(this);
+
+ }
+
+ @Override
+ protected void writeIndent()
+ {
+ write(JSFlexJSEmitterTokens.INDENT);
+ }
+
+ @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 emitLocalNamedFunction(IFunctionNode node)
+ {
+ IFunctionNode fnNode = (IFunctionNode)node.getAncestorOfType(IFunctionNode.class);
+ if (fnNode.getEmittingLocalFunctions())
+ {
+ super.emitLocalNamedFunction(node);
+ }
+ }
+
+ @Override
+ public void emitFunctionBlockHeader(IFunctionNode node)
+ {
+ node.setEmittingLocalFunctions(true);
+ super.emitFunctionBlockHeader(node);
+ if (node.isConstructor())
+ {
+ IClassNode cnode = (IClassNode) node
+ .getAncestorOfType(IClassNode.class);
+ emitComplexInitializers(cnode);
+ }
+ if (node.containsLocalFunctions())
+ {
+ List<IFunctionNode> anonFns = node.getLocalFunctions();
+ int n = anonFns.size();
+ for (int i = 0; i < n; i++)
+ {
+ IFunctionNode anonFn = anonFns.get(i);
+ if (anonFn.getParent().getNodeID() == ASTNodeID.AnonymousFunctionID)
+ {
+ write("var /** @type {Function} */ __localFn" + Integer.toString(i) + "__ = ");
+ getWalker().walk(anonFn.getParent());
+ }
+ else
+ {
+ getWalker().walk(anonFn);
+ write(ASEmitterTokens.SEMICOLON);
+ }
+ this.writeNewline();
+ }
+ }
+ node.setEmittingLocalFunctions(false);
+ }
+
+ @Override
+ public void emitFunctionObject(IFunctionObjectNode node)
+ {
+ IFunctionNode fnNode = (IFunctionNode)node.getAncestorOfType(IFunctionNode.class);
+ if (fnNode == null || fnNode.getEmittingLocalFunctions())
+ {
+ super.emitFunctionObject(node);
+ }
+ else
+ {
+ List<IFunctionNode> anonFns = fnNode.getLocalFunctions();
+ int i = anonFns.indexOf(node.getFunctionNode());
+ if (i < 0)
+ System.out.println("missing index for " + node.toString());
+ else
+ write("__localFn" + Integer.toString(i) + "__");
+ }
+ }
+
+ @Override
+ public void emitNamespace(INamespaceNode node)
+ {
+ write(formatQualifiedName(node.getName()));
+ write(ASEmitterTokens.SPACE);
+ writeToken(ASEmitterTokens.EQUAL);
+ writeToken(ASEmitterTokens.NEW);
+ write(IASLanguageConstants.Namespace);
+ write(ASEmitterTokens.PAREN_OPEN);
+ getWalker().walk(node.getNamespaceURINode());
+ write(ASEmitterTokens.PAREN_CLOSE);
+ write(ASEmitterTokens.SEMICOLON);
+ }
+
+ @Override
+ public void emitMemberName(IDefinitionNode node)
+ {
+ write(node.getName());
+ }
+
+ @Override
+ public String formatQualifiedName(String name)
+ {
+ return formatQualifiedName(name, false);
+ }
+
+ public MXMLFlexJSEmitter mxmlEmitter = null;
+
+ public String formatQualifiedName(String name, boolean isDoc)
+ {
+ if (mxmlEmitter != null)
+ name = mxmlEmitter.formatQualifiedName(name);
+ /*
+ if (name.contains("goog.") || name.startsWith("Vector."))
+ return name;
+ name = name.replaceAll("\\.", "_");
+ */
+ if (getModel().isInternalClass(name))
+ return getModel().getInternalClasses().get(name);
+ if (name.startsWith("window."))
+ name = name.substring(7);
+ else if (!isDoc)
+ {
+ if (!usedNames.contains(name))
+ usedNames.add(name);
+ }
+ return name;
+ }
+
+ //--------------------------------------------------------------------------
+ // Package Level
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitPackageHeader(IPackageDefinition definition)
+ {
+ IPackageNode packageNode = definition.getNode();
+ IFileNode fileNode = (IFileNode) packageNode.getAncestorOfType(IFileNode.class);
+ int nodeCount = fileNode.getChildCount();
+ String mainClassName = null;
+ for (int i = 0; i < nodeCount; i++)
+ {
+ IASNode pnode = fileNode.getChild(i);
+
+ if (pnode instanceof IPackageNode)
+ {
+ IScopedNode snode = ((IPackageNode)pnode).getScopedNode();
+ int snodeCount = snode.getChildCount();
+ for (int j = 0; j < snodeCount; j++)
+ {
+ IASNode cnode = snode.getChild(j);
+ if (cnode instanceof IClassNode)
+ {
+ mainClassName = ((IClassNode)cnode).getQualifiedName();
+ break;
+ }
+ }
+ }
+ else if (pnode instanceof IClassNode)
+ {
+ String className = ((IClassNode)pnode).getQualifiedName();
+ getModel().getInternalClasses().put(className, mainClassName + "." + className);
+ }
+ else if (pnode instanceof IInterfaceNode)
+ {
+ String className = ((IInterfaceNode)pnode).getQualifiedName();
+ getModel().getInternalClasses().put(className, mainClassName + "." + className);
+ }
+ else if (pnode instanceof IFunctionNode)
+ {
+ String className = ((IFunctionNode)pnode).getQualifiedName();
+ getModel().getInternalClasses().put(className, mainClassName + "." + className);
+ }
+ else if (pnode instanceof INamespaceNode)
+ {
+ String className = ((INamespaceNode)pnode).getQualifiedName();
+ getModel().getInternalClasses().put(className, mainClassName + "." + className);
+ }
+ else if (pnode instanceof IVariableNode)
+ {
+ String className = ((IVariableNode)pnode).getQualifiedName();
+ getModel().getInternalClasses().put(className, mainClassName + "." + className);
+ }
+ }
+
+ packageHeaderEmitter.emit(definition);
+ }
+
+ @Override
+ public void emitPackageHeaderContents(IPackageDefinition definition)
+ {
+ packageHeaderEmitter.emitContents(definition);
+ usedNames.clear();
+ }
+
+ @Override
+ public void emitPackageFooter(IPackageDefinition definition)
+ {
+ packageFooterEmitter.emit(definition);
+ }
+
+ //--------------------------------------------------------------------------
+ // Class
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitClass(IClassNode node)
+ {
+ classEmitter.emit(node);
+ }
+
+ @Override
+ public void emitInterface(IInterfaceNode node)
+ {
+ interfaceEmitter.emit(node);
+ }
+
+ @Override
+ public void emitField(IVariableNode node)
+ {
+ fieldEmitter.emit(node);
+ }
+
+ @Override
+ public void emitVarDeclaration(IVariableNode node)
+ {
+ varDeclarationEmitter.emit(node);
+ }
+
+ @Override
+ public void emitAccessors(IAccessorNode node)
+ {
+ accessorEmitter.emit(node);
+ }
+
+ @Override
+ public void emitGetAccessor(IGetterNode node)
+ {
+ accessorEmitter.emitGet(node);
+ }
+
+ @Override
+ public void emitSetAccessor(ISetterNode node)
+ {
+ accessorEmitter.emitSet(node);
+ }
+
+ @Override
+ public void emitMethod(IFunctionNode node)
+ {
+ methodEmitter.emit(node);
+ }
+
+ public void emitComplexInitializers(IClassNode node)
+ {
+ classEmitter.emitComplexInitializers(node);
+ }
+
+ //--------------------------------------------------------------------------
+ // Statements
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitFunctionCall(IFunctionCallNode node)
+ {
+ functionCallEmitter.emit(node);
+ }
+
+ @Override
+ public void emitForEachLoop(IForLoopNode node)
+ {
+ forEachEmitter.emit(node);
+ }
+
+ //--------------------------------------------------------------------------
+ // Expressions
+ //--------------------------------------------------------------------------
+
+ @Override
+ public void emitSuperCall(IASNode node, String type)
+ {
+ superCallEmitter.emit(node, type);
+ }
+
+ @Override
+ public void emitMemberAccessExpression(IMemberAccessExpressionNode node)
+ {
+ memberAccessEmitter.emit(node);
+ }
+
+ @Override
+ public void emitArguments(IContainerNode node)
+ {
+ IContainerNode newNode = node;
+ int len = node.getChildCount();
+ if (len == 2)
+ {
+ ICompilerProject project = getWalker().getProject();;
+ IFunctionCallNode fcNode = (IFunctionCallNode) node.getParent();
+ IExpressionNode nameNode = fcNode.getNameNode();
+ IDefinition def = nameNode.resolve(project);
+ if (def != null && def.getBaseName().equals("insertAt"))
+ {
+ if (def.getParent() != null &&
+ def.getParent().getQualifiedName().equals("Array"))
+ {
+ if (nameNode instanceof MemberAccessExpressionNode)
+ {
+ newNode = EmitterUtils.insertArgumentsAt(node, 1, new NumericLiteralNode("0"));
+ }
+ }
+ }
+ }
+ if (len == 1)
+ {
+ ICompilerProject project = getWalker().getProject();;
+ IFunctionCallNode fcNode = (IFunctionCallNode) node.getParent();
+ IExpressionNode nameNode = fcNode.getNameNode();
+ IDefinition def = nameNode.resolve(project);
+ if (def != null && def.getBaseName().equals("removeAt"))
+ {
+ if (def.getParent() != null &&
+ def.getParent().getQualifiedName().equals("Array"))
+ {
+ if (nameNode instanceof MemberAccessExpressionNode)
+ {
+ newNode = EmitterUtils.insertArgumentsAfter(node, new NumericLiteralNode("1"));
+ }
+ }
+ }
+ else if (def != null && def.getBaseName().equals("parseInt"))
+ {
+ IDefinition parentDef = def.getParent();
+ if (parentDef == null)
+ {
+ if (nameNode instanceof IdentifierNode)
+ {
+ newNode = EmitterUtils.insertArgumentsAfter(node, new NumericLiteralNode("10"));
+ }
+ }
+ }
+ }
+ super.emitArguments(newNode);
+ }
+
+ @Override
+ public void emitE4XFilter(IMemberAccessExpressionNode node)
+ {
++ getModel().inE4xFilter = true;
+ getWalker().walk(node.getLeftOperandNode());
+ write(".filter(function(node){return (node.");
+ String s = stringifyNode(node.getRightOperandNode());
+ if (s.startsWith("(") && s.endsWith(")"))
+ s = s.substring(1, s.length() - 1);
+ write(s);
+ write(")})");
++ getModel().inE4xFilter = false;
+ }
+
+ @Override
+ public void emitBinaryOperator(IBinaryOperatorNode node)
+ {
+ binaryOperatorEmitter.emit(node);
+ }
+
+ @Override
+ public void emitIdentifier(IIdentifierNode node)
+ {
+ identifierEmitter.emit(node);
+ }
+
+ @Override
+ public void emitLiteral(ILiteralNode node)
+ {
+ literalEmitter.emit(node);
+ }
+
+ //--------------------------------------------------------------------------
+ // Specific
+ //--------------------------------------------------------------------------
+
+ public void emitIsAs(IExpressionNode node, IExpressionNode left, IExpressionNode right, ASTNodeID id, boolean coercion)
+ {
+ asIsEmitter.emitIsAs(node, left, right, id, coercion);
+ }
+
+ @Override
+ protected void emitSelfReference(IFunctionNode node)
+ {
+ selfReferenceEmitter.emit(node);
+ }
+
+ @Override
+ protected void emitObjectDefineProperty(IAccessorNode node)
+ {
+ objectDefinePropertyEmitter.emit(node);
+ }
+
+ @Override
+ public void emitDefinePropertyFunction(IAccessorNode node)
+ {
+ definePropertyFunctionEmitter.emit(node);
+ }
+
+ public String stringifyDefineProperties(IClassDefinition cdef)
+ {
+ setBufferWrite(true);
+ accessorEmitter.emit(cdef);
+ String result = getBuilder().toString();
+ getBuilder().setLength(0);
+ setBufferWrite(false);
+ return result;
+ }
+
+ @Override
+ public void emitClosureStart()
+ {
+ ICompilerProject project = getWalker().getProject();;
+ if (project instanceof FlexJSProject)
+ ((FlexJSProject)project).needLanguage = true;
+ write(JSFlexJSEmitterTokens.CLOSURE_FUNCTION_NAME);
+ write(ASEmitterTokens.PAREN_OPEN);
+ }
+
+ @Override
+ public void emitClosureEnd(IASNode node)
+ {
+ write(ASEmitterTokens.COMMA);
+ write(ASEmitterTokens.SPACE);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ if (node.getNodeID() == ASTNodeID.IdentifierID)
+ write(((IIdentifierNode)node).getName());
+ else if (node.getNodeID() == ASTNodeID.MemberAccessExpressionID)
+ writeChainName(node);
+ else
+ System.out.println("unexpected node in emitClosureEnd");
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ write(ASEmitterTokens.PAREN_CLOSE);
+ }
+
+ @Override
+ public void emitStatement(IASNode node)
+ {
+ // don't emit named local functions as statements
+ // they are emitted as part of the function block header
+ if (node.getNodeID() == ASTNodeID.FunctionID)
+ {
+ return;
+ }
+ super.emitStatement(node);
+ }
+ private void writeChainName(IASNode node)
+ {
+ while (node.getNodeID() == ASTNodeID.MemberAccessExpressionID)
+ {
+ node = ((IMemberAccessExpressionNode)node).getRightOperandNode();
+ }
+ if (node.getNodeID() == ASTNodeID.IdentifierID)
+ write(((IdentifierNode)node).getName());
+ else
+ System.out.println("unexpected node in emitClosureEnd");
+ }
+
+ @Override
+ public void emitUnaryOperator(IUnaryOperatorNode node)
+ {
+ if (node.getNodeID() == ASTNodeID.Op_DeleteID)
+ {
+ if (node.getChild(0).getNodeID() == ASTNodeID.ArrayIndexExpressionID)
+ {
+ if (node.getChild(0).getChild(0).getNodeID() == ASTNodeID.MemberAccessExpressionID)
+ {
+ MemberAccessExpressionNode obj = (MemberAccessExpressionNode)(node.getChild(0).getChild(0));
+ if (isXMLList(obj))
+ {
+ if (ASNodeUtils.hasParenOpen(node))
+ write(ASEmitterTokens.PAREN_OPEN);
+
+ getWalker().walk(obj);
+ DynamicAccessNode dan = (DynamicAccessNode)(node.getChild(0));
+ IASNode indexNode = dan.getChild(1);
+ write(".removeChildAt(");
+ getWalker().walk(indexNode);
+ write(")");
+ if (ASNodeUtils.hasParenClose(node))
+ write(ASEmitterTokens.PAREN_CLOSE);
+ return;
+ }
+ }
+ else if (node.getChild(0).getChild(0).getNodeID() == ASTNodeID.IdentifierID)
+ {
+ if (isXML((IdentifierNode)(node.getChild(0).getChild(0))))
+ {
+ if (ASNodeUtils.hasParenOpen(node))
+ write(ASEmitterTokens.PAREN_OPEN);
+
+ getWalker().walk(node.getChild(0).getChild(0));
+ DynamicAccessNode dan = (DynamicAccessNode)(node.getChild(0));
+ IASNode indexNode = dan.getChild(1);
+ write(".removeChild(");
+ getWalker().walk(indexNode);
+ write(")");
+ if (ASNodeUtils.hasParenClose(node))
+ write(ASEmitterTokens.PAREN_CLOSE);
+ return;
+ }
+ else if (isProxy((IdentifierNode)(node.getChild(0).getChild(0))))
+ {
+ if (ASNodeUtils.hasParenOpen(node))
+ write(ASEmitterTokens.PAREN_OPEN);
+
+ getWalker().walk(node.getChild(0).getChild(0));
+ DynamicAccessNode dan = (DynamicAccessNode)(node.getChild(0));
+ IASNode indexNode = dan.getChild(1);
+ write(".deleteProperty(");
+ getWalker().walk(indexNode);
+ write(")");
+ if (ASNodeUtils.hasParenClose(node))
+ write(ASEmitterTokens.PAREN_CLOSE);
+ return;
+ }
+ }
+
+ }
+ else if (node.getChild(0).getNodeID() == ASTNodeID.MemberAccessExpressionID)
+ {
+ MemberAccessExpressionNode obj = (MemberAccessExpressionNode)(node.getChild(0));
+ if (isXMLList(obj))
+ {
+ if (ASNodeUtils.hasParenOpen(node))
+ write(ASEmitterTokens.PAREN_OPEN);
+
+ String s = stringifyNode(obj.getLeftOperandNode());
+ write(s);
+ write(".removeChild('");
+ s = stringifyNode(obj.getRightOperandNode());
+ write(s);
+ write("')");
+ if (ASNodeUtils.hasParenClose(node))
+ write(ASEmitterTokens.PAREN_CLOSE);
+ return;
+ }
+ }
+
+ }
+ else if (node.getNodeID() == ASTNodeID.Op_AtID)
+ {
+ write("attribute('");
+ getWalker().walk(node.getOperandNode());
+ write("')");
+ return;
+ }
+
+ super.emitUnaryOperator(node);
+
+ }
+
+ /**
+ * resolveType on an XML expression returns null
+ * (see IdentiferNode.resolveType).
+ * So, we have to walk the tree ourselves and resolve
+ * individual pieces.
+ * @param obj
+ * @return
+ */
+ public boolean isXMLList(MemberAccessExpressionNode obj)
+ {
+ IExpressionNode leftNode = obj.getLeftOperandNode();
+ IExpressionNode rightNode = obj.getRightOperandNode();
+ ASTNodeID rightID = rightNode.getNodeID();
+ if (rightID == ASTNodeID.IdentifierID)
+ {
+ IDefinition rightDef = rightNode.resolveType(getWalker().getProject());
+ if (rightDef != null)
+ return IdentifierNode.isXMLish(rightDef, getWalker().getProject());
+ }
+ ASTNodeID leftID = leftNode.getNodeID();
+ if (leftID == ASTNodeID.IdentifierID)
+ {
+ IDefinition leftDef = leftNode.resolveType(getWalker().getProject());
+ if (leftDef != null)
+ return IdentifierNode.isXMLish(leftDef, getWalker().getProject());
+ }
+ else if (leftID == ASTNodeID.MemberAccessExpressionID)
+ {
+ return isXMLList((MemberAccessExpressionNode)leftNode);
+ }
+ else if (leftID == ASTNodeID.FunctionCallID)
+ {
+ FunctionCallNode fcn = (FunctionCallNode)leftNode;
+ String fname = fcn.getFunctionName();
+ if (fname.equals("XML") || fname.equals("XMLList"))
+ return true;
+ }
+ else if (leftID == ASTNodeID.Op_AsID)
+ {
+ BinaryOperatorAsNode boan = (BinaryOperatorAsNode)leftNode;
+ String fname = ((IdentifierNode)boan.getChild(1)).getName();
+ if (fname.equals("XML") || fname.equals("XMLList"))
+ return true;
+ }
++ else if (leftID == ASTNodeID.ArrayIndexExpressionID)
++ {
++ leftNode = (IExpressionNode)(leftNode.getChild(0));
++ IDefinition leftDef = leftNode.resolveType(getWalker().getProject());
++ if (leftDef != null)
++ return IdentifierNode.isXMLish(leftDef, getWalker().getProject());
++
++ }
++ else if (leftID == ASTNodeID.E4XFilterID)
++ return true;
+ return false;
+ }
+
+ /**
+ * resolveType on an XML expression returns null
+ * (see IdentiferNode.resolveType).
+ * So, we have to walk the tree ourselves and resolve
+ * individual pieces.
+ * @param obj
+ * @return
+ */
+ public boolean isProxy(IExpressionNode obj)
+ {
+ FlexProject project = (FlexProject)getWalker().getProject();
+ // See if it is Proxy
+ ITypeDefinition leftDef = obj.resolveType(project);
+ if (leftDef == null)
+ {
+ if (obj.getNodeID() == ASTNodeID.MemberAccessExpressionID)
+ {
+ IExpressionNode leftNode = ((MemberAccessExpressionNode)obj).getLeftOperandNode();
+ leftDef = leftNode.resolveType(project);
+ if (leftDef != null && leftDef.isInstanceOf(project.getProxyBaseClass(), project))
+ return true;
+ while (leftNode.getNodeID() == ASTNodeID.MemberAccessExpressionID)
+ {
+ // walk up chain looking for a proxy
+ leftNode = ((MemberAccessExpressionNode)leftNode).getLeftOperandNode();
+ leftDef = leftNode.resolveType(project);
+ if (leftDef != null && leftDef.isInstanceOf(project.getProxyBaseClass(), project))
+ return true;
+ }
+ }
+ return false;
+ }
+ return leftDef.isInstanceOf(project.getProxyBaseClass(), project);
+ }
+
+ /**
+ * resolveType on an XML expression returns null
+ * (see IdentiferNode.resolveType).
+ * So, we have to walk the tree ourselves and resolve
+ * individual pieces.
+ * @param obj
+ * @return
+ */
+ public boolean isDateProperty(IExpressionNode obj)
+ {
+ FlexProject project = (FlexProject)getWalker().getProject();
+ if (obj.getNodeID() == ASTNodeID.MemberAccessExpressionID)
+ {
+ IDefinition leftDef;
+ IExpressionNode leftNode = ((MemberAccessExpressionNode)obj).getLeftOperandNode();
+ IExpressionNode rightNode = ((MemberAccessExpressionNode)obj).getRightOperandNode();
+ leftDef = leftNode.resolveType(project);
+ IDefinition rightDef = rightNode.resolve(project);
+ if (leftDef != null && leftDef.getQualifiedName().equals("Date") && rightDef instanceof AccessorDefinition)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * resolveType on an XML expression returns null
+ * (see IdentiferNode.resolveType).
+ * So, we have to walk the tree ourselves and resolve
+ * individual pieces.
+ * @param obj
+ * @return
+ */
+ public boolean isXML(IExpressionNode obj)
+ {
+ // See if the left side is XML or XMLList
+ IDefinition leftDef = obj.resolveType(getWalker().getProject());
+ return IdentifierNode.isXMLish(leftDef, getWalker().getProject());
+ }
+
+ public MemberAccessExpressionNode getLastMAEInChain(MemberAccessExpressionNode node)
+ {
+ while (node.getRightOperandNode() instanceof MemberAccessExpressionNode)
+ node = (MemberAccessExpressionNode)node.getRightOperandNode();
+ return node;
+ }
+
+ @Override
+ public void emitLabelStatement(LabeledStatementNode node)
+ {
+ BlockNode innerBlock = node.getLabeledStatement();
+ if (innerBlock.getChildCount() == 1 && innerBlock.getChild(0).getNodeID() == ASTNodeID.ForEachLoopID)
+ {
+ getWalker().walk(node.getLabeledStatement());
+ return; // for each emitter will emit label in the right spot
+ }
+ super.emitLabelStatement(node);
+ }
+}