Remove the pre-GwtAstBuilder compile chain.
- WebModeCompilerFrontEnd
- BuildTypeMap
- GenerateJavaAST
http://gwt-code-reviews.appspot.com/1465805/
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10490 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/GwtAstBuilderUtil.java b/dev/core/src/com/google/gwt/dev/GwtAstBuilderUtil.java
deleted file mode 100644
index 18c66cf..0000000
--- a/dev/core/src/com/google/gwt/dev/GwtAstBuilderUtil.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed 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 com.google.gwt.dev;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.linker.ArtifactSet;
-import com.google.gwt.dev.cfg.ModuleDef;
-import com.google.gwt.dev.javac.CompilationState;
-import com.google.gwt.dev.javac.CompilationUnit;
-import com.google.gwt.dev.javac.StandardGeneratorContext;
-import com.google.gwt.dev.jdt.RebindPermutationOracle;
-import com.google.gwt.dev.jdt.WebModeCompilerFrontEnd;
-import com.google.gwt.dev.jjs.CorrelationFactory;
-import com.google.gwt.dev.jjs.CorrelationFactory.DummyCorrelationFactory;
-import com.google.gwt.dev.jjs.JJSOptionsImpl;
-import com.google.gwt.dev.jjs.ast.JProgram;
-import com.google.gwt.dev.jjs.impl.BuildTypeMap;
-import com.google.gwt.dev.jjs.impl.GenerateJavaAST;
-import com.google.gwt.dev.jjs.impl.GwtAstBuilder;
-import com.google.gwt.dev.jjs.impl.TypeLinker;
-import com.google.gwt.dev.jjs.impl.TypeMap;
-import com.google.gwt.dev.js.ast.JsProgram;
-
-import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Used by GwtAstBuilderTest.
- *
- * TODO(zundel): remove after GwtAstBuilderTest is obsolete.
- */
-public class GwtAstBuilderUtil {
-
- public static JProgram buildGenerateJavaAst(final TreeLogger logger, ModuleDef module,
- final CompilationState compilationState) throws UnableToCompleteException {
- final StandardGeneratorContext genCtx =
- new StandardGeneratorContext(compilationState, module, null, new ArtifactSet(), true);
- RebindPermutationOracle rpo = new RebindPermutationOracle() {
- public void clear() {
- }
-
- public String[] getAllPossibleRebindAnswers(TreeLogger logger, String sourceTypeName)
- throws UnableToCompleteException {
- return new String[0];
- }
-
- public CompilationState getCompilationState() {
- return compilationState;
- }
-
- public StandardGeneratorContext getGeneratorContext() {
- return genCtx;
- }
- };
-
- List<String> allRootTypes = new ArrayList<String>();
- for (CompilationUnit unit : compilationState.getCompilationUnits()) {
- allRootTypes.add(unit.getTypeName());
- }
- CompilationUnitDeclaration[] goldenCuds =
- WebModeCompilerFrontEnd.getCompilationUnitDeclarations(logger, allRootTypes
- .toArray(new String[allRootTypes.size()]), rpo, TypeLinker.NULL_TYPE_LINKER).compiledUnits;
-
- CorrelationFactory correlator = DummyCorrelationFactory.INSTANCE;
- JsProgram jsProgram = new JsProgram(correlator);
- JProgram jprogram = new JProgram(correlator);
- TypeMap typeMap = new TypeMap(jprogram);
- TypeDeclaration[] allTypeDeclarations = BuildTypeMap.exec(typeMap, goldenCuds, jsProgram);
- // BuildTypeMap can uncover syntactic JSNI errors; report & abort
- checkForErrors(logger, goldenCuds);
-
- // Compute all super type/sub type info
- jprogram.typeOracle.computeBeforeAST();
-
- // (2) Create our own Java AST from the JDT AST.
- GenerateJavaAST.exec(allTypeDeclarations, typeMap, jprogram, new JJSOptionsImpl());
-
- // GenerateJavaAST can uncover semantic JSNI errors; report & abort
- checkForErrors(logger, goldenCuds);
- return jprogram;
- }
-
- public static CompilationState buildGwtAst(TreeLogger logger, ModuleDef module)
- throws UnableToCompleteException {
- boolean gwtAstWasEnabled = GwtAstBuilder.ENABLED;
- try {
- GwtAstBuilder.ENABLED = true;
- // Avoid call to System.currentTimeMillis() if not logging INFO level
- long start = logger.isLoggable(TreeLogger.INFO) ? System.currentTimeMillis() : 0L;
- final CompilationState compilationState = module.getCompilationState(logger);
- if (logger.isLoggable(TreeLogger.INFO)) {
- logger.log(TreeLogger.INFO, (System.currentTimeMillis() - start)
- + " time to get compilation state");
- }
- return compilationState;
- } finally {
- GwtAstBuilder.ENABLED = gwtAstWasEnabled;
- }
- }
-
- private static void checkForErrors(TreeLogger logger, CompilationUnitDeclaration[] goldenCuds)
- throws UnableToCompleteException {
- for (CompilationUnitDeclaration cud : goldenCuds) {
- CompilationResult result = cud.compilationResult();
- if (result.hasErrors()) {
- logger.log(TreeLogger.ERROR, "Aborting on '" + String.valueOf(cud.getFileName()) + "'");
- throw new UnableToCompleteException();
- }
- }
- }
-}
diff --git a/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java b/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java
index 2aa4957..91bbe05 100644
--- a/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java
+++ b/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java
@@ -117,11 +117,9 @@
new Dependencies(packageName, unresolvedQualified, unresolvedSimple, apiRefs);
List<JDeclaredType> types = Collections.emptyList();
- if (GwtAstBuilder.ENABLED) {
- if (!cud.compilationResult().hasErrors()) {
- // Make a GWT AST.
- types = astBuilder.process(cud, artificialRescues, jsniMethods, jsniRefs);
- }
+ if (!cud.compilationResult().hasErrors()) {
+ // Make a GWT AST.
+ types = astBuilder.process(cud, artificialRescues, jsniMethods, jsniRefs);
}
for (CompiledClass cc : compiledClasses) {
diff --git a/dev/core/src/com/google/gwt/dev/javac/PersistentUnitCache.java b/dev/core/src/com/google/gwt/dev/javac/PersistentUnitCache.java
index f07afbb..183b500 100644
--- a/dev/core/src/com/google/gwt/dev/javac/PersistentUnitCache.java
+++ b/dev/core/src/com/google/gwt/dev/javac/PersistentUnitCache.java
@@ -494,10 +494,8 @@
if (unit == null) {
break;
}
- if (GwtAstBuilder.ENABLED) {
- if (unit.getTypesSerializedVersion() != GwtAstBuilder.getSerializationVersion()) {
- continue;
- }
+ if (unit.getTypesSerializedVersion() != GwtAstBuilder.getSerializationVersion()) {
+ continue;
}
UnitCacheEntry entry = new UnitCacheEntry(unit, UnitOrigin.PERSISTENT);
UnitCacheEntry existingEntry = unitMap.get(unit.getResourcePath());
diff --git a/dev/core/src/com/google/gwt/dev/jdt/AbstractCompiler.java b/dev/core/src/com/google/gwt/dev/jdt/AbstractCompiler.java
deleted file mode 100644
index d555625..0000000
--- a/dev/core/src/com/google/gwt/dev/jdt/AbstractCompiler.java
+++ /dev/null
@@ -1,627 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed 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 com.google.gwt.dev.jdt;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.TreeLogger.HelpInfo;
-import com.google.gwt.dev.javac.CompilationState;
-import com.google.gwt.dev.javac.CompilationUnit;
-import com.google.gwt.dev.javac.GWTProblem;
-import com.google.gwt.dev.javac.JdtCompiler;
-import com.google.gwt.dev.javac.Shared;
-import com.google.gwt.dev.util.CharArrayComparator;
-import com.google.gwt.dev.util.Empty;
-import com.google.gwt.dev.util.Util;
-import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
-import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
-
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.compiler.IProblem;
-import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.Compiler;
-import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
-import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
-import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
-import org.eclipse.jdt.internal.compiler.IProblemFactory;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
-import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
-import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
-import org.eclipse.jdt.internal.compiler.env.IBinaryType;
-import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
-import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
-import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
-import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
-import org.eclipse.jdt.internal.compiler.util.Messages;
-
-import java.net.URL;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-
-/**
- * A facade around the JDT compiler to manage on-demand compilation, caching
- * smartly where possible.
- */
-public abstract class AbstractCompiler {
-
- /**
- * Contains the results of a compilation run. Includes both the compiled
- * source units and the type bindings for binary types that were looked up
- * during the compilation.
- */
- public static class CompilationResults {
- /**
- * Bindings for binary types looked up during compilation.
- */
- public final Map<String, BinaryTypeBinding> binaryBindings;
-
- /**
- * Compiled source units.
- */
- public final CompilationUnitDeclaration[] compiledUnits;
-
- public CompilationResults(CompilationUnitDeclaration[] compiledUnits,
- Map<String, BinaryTypeBinding> binaryBindings) {
- this.compiledUnits = compiledUnits;
- this.binaryBindings = binaryBindings;
- }
- }
-
- /**
- * Adapts a {@link CompilationUnit} for a JDT compile.
- */
- public static class CompilationUnitAdapter implements ICompilationUnit {
-
- private final CompilationUnit unit;
-
- public CompilationUnitAdapter(CompilationUnit unit) {
- this.unit = unit;
- }
-
- @SuppressWarnings("deprecation")
- public char[] getContents() {
- return unit.getSource().toCharArray();
- }
-
- public char[] getFileName() {
- return unit.getResourceLocation().toCharArray();
- }
-
- public char[] getMainTypeName() {
- return Shared.getShortName(unit.getTypeName()).toCharArray();
- }
-
- public char[][] getPackageName() {
- String packageName = Shared.getPackageName(unit.getTypeName());
- return CharOperation.splitOn('.', packageName.toCharArray());
- }
-
- @Override
- public String toString() {
- return unit.toString();
- }
- }
-
- /**
- * Shields {@link AbstractCompiler} so it can be garbage collected at the end
- * of a compile.
- */
- private static class Sandbox {
-
- /**
- * Adapted to hook the processing of compilation unit declarations so as to
- * be able to add additional compilation units based on the results of
- * previously-compiled ones. Examples of cases where this is useful include
- * classes referenced only from JSNI and <code>GWT.create</code>.
- */
- private class CompilerImpl extends Compiler {
-
- private Map<String, BinaryTypeBinding> bindings;
- private Set<CompilationUnitDeclaration> cuds;
- private long jdtProcessNanos;
-
- public CompilerImpl(INameEnvironment environment, IErrorHandlingPolicy policy,
- CompilerOptions compilerOptions, ICompilerRequestor requestor,
- IProblemFactory problemFactory) {
- super(environment, policy, compilerOptions, requestor, problemFactory);
- }
-
- @Override
- public void accept(IBinaryType binaryType, PackageBinding packageBinding,
- AccessRestriction accessRestriction) {
- // Do the same thing as super.accept(), but record the BinaryTypeBinding
- // that is generated from lookupEnvironment.
- if (this.options.verbose) {
- out.println(Messages.bind(Messages.compilation_loadBinary, new String(binaryType
- .getName())));
- }
- BinaryTypeBinding binding =
- lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding, accessRestriction);
- String name = CharOperation.toString(binding.compoundName);
- if (bindings != null) {
- bindings.put(name, binding);
- }
- }
-
- @Override
- public void compile(ICompilationUnit[] sourceUnits) {
- SpeedTracerLogger.Event compileEvent =
- SpeedTracerLogger.start(CompilerEventType.JDT_COMPILER_SANDBOX);
- try {
- super.compile(sourceUnits);
- } finally {
- compileEvent.end();
- }
- cuds = null;
- }
-
- @Override
- public void process(CompilationUnitDeclaration unit, int index) {
-
- long processBeginNanos = System.nanoTime();
-
- // The following block of code is a copy of super.process(cud, index),
- // with the modification that cud.generateCode is conditionally called
- // based on doGenerateBytes
- {
- this.lookupEnvironment.unitBeingCompleted = unit;
- long parseStart = System.currentTimeMillis();
-
- this.parser.getMethodBodies(unit);
-
- long resolveStart = System.currentTimeMillis();
- this.stats.parseTime += resolveStart - parseStart;
-
- // fault in fields & methods
- if (unit.scope != null) {
- unit.scope.faultInTypes();
- }
-
- // verify inherited methods
- if (unit.scope != null) {
- unit.scope.verifyMethods(lookupEnvironment.methodVerifier());
- }
-
- // type checking
- unit.resolve();
-
- long analyzeStart = System.currentTimeMillis();
- this.stats.resolveTime += analyzeStart - resolveStart;
-
- // flow analysis
- unit.analyseCode();
-
- long generateStart = System.currentTimeMillis();
- this.stats.analyzeTime += generateStart - analyzeStart;
-
- // code generation
- if (doGenerateBytes) {
- unit.generateCode();
- }
-
- // reference info
- if (options.produceReferenceInfo && unit.scope != null) {
- unit.scope.storeDependencyInfo();
- }
-
- // finalize problems (suppressWarnings)
- unit.finalizeProblems();
-
- this.stats.generateTime += System.currentTimeMillis() - generateStart;
-
- // refresh the total number of units known at this stage
- unit.compilationResult.totalUnitsKnown = totalUnits;
-
- this.lookupEnvironment.unitBeingCompleted = null;
- }
-
- ICompilationUnit cu = unit.compilationResult.compilationUnit;
- String loc = String.valueOf(cu.getFileName());
- TreeLogger branch =
- logger.branch(TreeLogger.SPAM, "Scanning for additional dependencies: " + loc, null);
-
- // Examine the cud for types outside of the flow of the original Java
- // source.
- //
- String[] typeNames = outer.doFindAdditionalTypesUsingJsni(branch, unit);
- addAdditionalTypes(branch, typeNames);
-
- typeNames = outer.doFindAdditionalTypesUsingArtificialRescues(branch, unit);
- addAdditionalTypes(branch, typeNames);
-
- typeNames = outer.doFindAdditionalTypesUsingRebinds(branch, unit);
- addAdditionalTypes(branch, typeNames);
- if (typeNames.length > 0) {
- refreshPackagesFromCompState();
- }
-
- // Optionally remember this cud.
- //
- if (cuds != null) {
- cuds.add(unit);
- }
-
- jdtProcessNanos += System.nanoTime() - processBeginNanos;
- }
-
- /**
- * Helper method for process() that receives the types found outside the
- * flow of the original Java source. This causes the compiler to find the
- * additional type, possibly causing the type to be compiled from source.
- */
- private void addAdditionalTypes(TreeLogger logger, String[] typeNames) {
- for (String typeName : typeNames) {
- if (logger.isLoggable(TreeLogger.SPAM)) {
- logger.log(TreeLogger.SPAM, "Need additional type '" + typeName + "'", null);
- }
-
- resolvePossiblyNestedType(typeName);
- }
- }
-
- private void compile(ICompilationUnit[] units, Set<CompilationUnitDeclaration> cuds,
- Map<String, BinaryTypeBinding> bindings) {
- this.bindings = bindings;
- this.cuds = cuds;
- compile(units);
- }
-
- private ReferenceBinding resolvePossiblyNestedType(String typeName) {
- return JdtCompiler.resolveType(lookupEnvironment, typeName);
- }
- }
-
- private class ICompilerRequestorImpl implements ICompilerRequestor {
-
- public ICompilerRequestorImpl() {
- }
-
- public void acceptResult(CompilationResult result) {
- // Handle compilation errors.
- //
- IProblem[] errors = result.getErrors();
-
- if (errors != null && errors.length > 0) {
- // Dump it to disk.
- //
- String fn = String.valueOf(result.compilationUnit.getFileName());
- String msg = "Errors in '" + fn + "'";
- TreeLogger branch = logger.branch(TreeLogger.ERROR, msg, null);
-
- for (IProblem error : errors) {
- // Strip the initial code from each error.
- //
- msg = error.toString();
- msg = msg.substring(msg.indexOf(' '));
-
- // Append 'Line #: msg' to the error message.
- //
- StringBuffer msgBuf = new StringBuffer();
- int line = error.getSourceLineNumber();
- if (line > 0) {
- msgBuf.append("Line ");
- msgBuf.append(line);
- msgBuf.append(": ");
- }
- msgBuf.append(msg);
-
- HelpInfo helpInfo = null;
- if (error instanceof GWTProblem) {
- GWTProblem gwtProblem = (GWTProblem) error;
- helpInfo = gwtProblem.getHelpInfo();
- }
- branch.log(TreeLogger.ERROR, msgBuf.toString(), null, helpInfo);
- }
- }
- }
- }
-
- private class INameEnvironmentImpl implements INameEnvironment {
-
- public INameEnvironmentImpl() {
- }
-
- public void cleanup() {
- // intentionally blank
- }
-
- public NameEnvironmentAnswer findType(char[] type, char[][] pkg) {
- return findType(CharOperation.arrayConcat(pkg, type));
- }
-
- public NameEnvironmentAnswer findType(char[][] compoundTypeName) {
- String qname = CharOperation.toString(compoundTypeName);
- TreeLogger branch =
- logger.branch(TreeLogger.SPAM, "Compiler is asking about '" + qname + "'", null);
-
- if (isPackage(qname)) {
- branch.log(TreeLogger.SPAM, "Found to be a package", null);
- return null;
- }
-
- // Didn't find it in the cache, so let's compile from source.
- // Strip off the inner types, if any
- //
- String className = qname;
- int pos = qname.indexOf('$');
- if (pos >= 0) {
- qname = qname.substring(0, pos);
- }
- CompilationUnit unit = findCompilationUnit(qname);
- if (unit != null) {
- if (branch.isLoggable(TreeLogger.SPAM)) {
- branch.log(TreeLogger.SPAM, "Found type in compilation unit: "
- + unit.getResourceLocation());
- }
- ICompilationUnit icu = new CompilationUnitAdapter(unit);
- return new NameEnvironmentAnswer(icu, null);
- } else {
- ClassLoader classLoader = getClassLoader();
- URL resourceURL = classLoader.getResource(className.replace('.', '/') + ".class");
- if (resourceURL != null) {
- /*
- * We know that there is a .class file that matches the name that we
- * are looking for. However, at least on OSX, this lookup is case
- * insensitive so we need to use Class.forName to effectively verify
- * the case.
- */
- if (isBinaryType(classLoader, className)) {
- byte[] classBytes = Util.readURLAsBytes(resourceURL);
- try {
- ClassFileReader cfr = new ClassFileReader(classBytes, null);
- return new NameEnvironmentAnswer(cfr, null);
- } catch (ClassFormatException e) {
- // Ignored.
- }
- }
- }
-
- branch.log(TreeLogger.SPAM, "Not a known type", null);
- return null;
- }
- }
-
- public boolean isPackage(char[][] parentPkg, char[] pkg) {
- // In special cases where class bytes are asserted from the outside,
- // a package can exist that the host doesn't know about. We have to
- // do a special check for these cases.
- //
- final char[] pathChars = CharOperation.concatWith(parentPkg, pkg, '.');
- String packageName = String.valueOf(pathChars);
- if (isPackage(packageName)) {
- return true;
- } else if (isPackage(getClassLoader(), packageName)) {
- // Grow our own list to spare calls into the host.
- //
- rememberPackage(packageName);
- return true;
- } else {
- return false;
- }
- }
-
- private ClassLoader getClassLoader() {
- return Thread.currentThread().getContextClassLoader();
- }
-
- private boolean isBinaryType(ClassLoader classLoader, String typeName) {
- try {
- Class.forName(typeName, false, classLoader);
- return true;
- } catch (ClassNotFoundException e) {
- // Ignored.
- } catch (LinkageError e) {
- // Ignored.
- }
-
- // Assume that it is not a binary type.
- return false;
- }
-
- private boolean isPackage(ClassLoader classLoader, String packageName) {
- String packageAsPath = packageName.replace('.', '/');
-
- // Test the JRE explicitly, because the classloader trick doesn't work.
- if (JdtCompiler.JreIndex.contains(packageAsPath)) {
- return true;
- }
-
- return classLoader.getResource(packageAsPath) != null;
- }
-
- private boolean isPackage(String packageName) {
- return knownPackages.contains(packageName);
- }
- }
-
- final CompilerImpl compiler;
- final boolean doGenerateBytes;
- final Set<String> knownPackages = new HashSet<String>();
- TreeLogger logger = null;
- AbstractCompiler outer;
-
- Sandbox(AbstractCompiler outer, boolean doGenerateBytes) {
- this.outer = outer;
- this.doGenerateBytes = doGenerateBytes;
- rememberPackage("");
-
- INameEnvironment env = new INameEnvironmentImpl();
- IErrorHandlingPolicy pol = DefaultErrorHandlingPolicies.proceedWithAllProblems();
- IProblemFactory probFact = new DefaultProblemFactory(Locale.getDefault());
- ICompilerRequestor req = new ICompilerRequestorImpl();
- CompilerOptions options = getCompilerOptions();
-
- // This is only needed by TypeOracleBuilder to parse metadata.
- options.docCommentSupport = false;
-
- compiler = new CompilerImpl(env, pol, options, req, probFact);
-
- // Initialize the packages list.
- refreshPackagesFromCompState();
- }
-
- public void clear() {
- outer = null;
- logger = TreeLogger.NULL;
- compiler.bindings = null;
- }
-
- private CompilationUnit findCompilationUnit(String qname) {
- if (outer == null) {
- return null;
- }
-
- // Build the initial set of compilation units.
- Map<String, CompilationUnit> unitMap = outer.compilationState.getCompilationUnitMap();
- CompilationUnit unit = unitMap.get(qname);
- while (unit == null) {
- int pos = qname.lastIndexOf('.');
- if (pos < 0) {
- return null;
- }
- qname = qname.substring(0, pos);
- unit = unitMap.get(qname);
- }
- return unit;
- }
-
- private void refreshPackagesFromCompState() {
- for (CompilationUnit unit : outer.compilationState.getCompilationUnits()) {
- String packageName = Shared.getPackageName(unit.getTypeName());
- rememberPackage(packageName);
- }
- }
-
- /**
- * Causes the compilation service itself to recognize the specified package
- * name (and all its parent packages), avoiding a call back into the host.
- * This is useful as an optimization, but more importantly, it is useful to
- * compile against bytecode that was pre-compiled to which we don't have the
- * source. This ability is crucial bridging the gap between user-level and
- * "dev" code in Development Mode for classes such as JavaScriptHost and
- * ShellJavaScriptHost.
- */
- private void rememberPackage(String packageName) {
- if (knownPackages.add(packageName)) {
- int i = packageName.lastIndexOf('.');
- if (i != -1) {
- // Ensure the parent package is also created.
- //
- rememberPackage(packageName.substring(0, i));
- }
- }
- }
- }
-
- private static final Comparator<CompilationUnitDeclaration> CUD_COMPARATOR =
- new Comparator<CompilationUnitDeclaration>() {
-
- public int compare(CompilationUnitDeclaration cud1, CompilationUnitDeclaration cud2) {
- ICompilationUnit cu1 = cud1.compilationResult().getCompilationUnit();
- ICompilationUnit cu2 = cud2.compilationResult().getCompilationUnit();
- char[][] package1 = cu1.getPackageName();
- char[][] package2 = cu2.getPackageName();
- for (int i = 0, c = Math.min(package1.length, package2.length); i < c; ++i) {
- int result = CharArrayComparator.INSTANCE.compare(package1[i], package2[i]);
- if (result != 0) {
- return result;
- }
- }
- int result = package2.length - package1.length;
- if (result != 0) {
- return result;
- }
- return CharArrayComparator.INSTANCE.compare(cu1.getMainTypeName(), cu2.getMainTypeName());
- }
- };
-
- public static CompilerOptions getCompilerOptions() {
- CompilerOptions options = JdtCompiler.getCompilerOptions();
-
- // Turn off all debugging for Production Mode.
- options.produceDebugAttributes = 0;
- options.preserveAllLocalVariables = false;
- return options;
- }
-
- protected CompilationState compilationState;
- private Sandbox sandbox;
-
- protected AbstractCompiler(CompilationState compilationState, boolean doGenerateBytes) {
- this.compilationState = compilationState;
- this.sandbox = new Sandbox(this, doGenerateBytes);
- }
-
- protected final CompilationResults compile(TreeLogger logger, ICompilationUnit[] units) {
-
- // Any additional compilation units that are found to be needed will be
- // pulled in while processing compilation units. See CompilerImpl.process().
- //
- sandbox.logger = logger;
- try {
- Set<CompilationUnitDeclaration> cuds =
- new TreeSet<CompilationUnitDeclaration>(CUD_COMPARATOR);
- LinkedHashMap<String, BinaryTypeBinding> bindings =
- new LinkedHashMap<String, BinaryTypeBinding>();
- sandbox.compiler.compile(units, cuds, bindings);
- return new CompilationResults(cuds.toArray(new CompilationUnitDeclaration[cuds.size()]),
- bindings);
- } finally {
- sandbox.clear();
- sandbox = null;
- }
- }
-
- /**
- * @param logger a {@link TreeLogger}
- * @param cud a {@link CompilationUnitDeclaration}
- */
- protected String[] doFindAdditionalTypesUsingArtificialRescues(TreeLogger logger,
- CompilationUnitDeclaration cud) {
- return Empty.STRINGS;
- }
-
- /**
- * @param logger a {@link TreeLogger}
- * @param cud a {@link CompilationUnitDeclaration}
- */
- protected String[] doFindAdditionalTypesUsingJsni(TreeLogger logger,
- CompilationUnitDeclaration cud) {
- return Empty.STRINGS;
- }
-
- /**
- * @param logger a {@link TreeLogger}
- * @param cud a {@link CompilationUnitDeclaration}
- */
- protected String[] doFindAdditionalTypesUsingRebinds(TreeLogger logger,
- CompilationUnitDeclaration cud) {
- return Empty.STRINGS;
- }
-
- protected final ReferenceBinding resolvePossiblyNestedType(String typeName) {
- return sandbox.compiler.resolvePossiblyNestedType(typeName);
- }
-}
diff --git a/dev/core/src/com/google/gwt/dev/jdt/BasicWebModeCompiler.java b/dev/core/src/com/google/gwt/dev/jdt/BasicWebModeCompiler.java
deleted file mode 100644
index eaf1dee..0000000
--- a/dev/core/src/com/google/gwt/dev/jdt/BasicWebModeCompiler.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed 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 com.google.gwt.dev.jdt;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.dev.javac.CompilationState;
-import com.google.gwt.dev.javac.CompilationUnit;
-import com.google.gwt.dev.javac.CompiledClass;
-import com.google.gwt.dev.jjs.impl.TypeLinker;
-import com.google.gwt.dev.util.JsniRef;
-import com.google.gwt.dev.util.Memory;
-
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Provides a basic front-end based on the JDT compiler that incorporates
- * GWT-specific concepts such as JSNI.
- */
-public class BasicWebModeCompiler extends AbstractCompiler {
-
- public static CompilationResults getCompilationUnitDeclarations(TreeLogger logger,
- CompilationState state, TypeLinker linker, String... seedTypeNames)
- throws UnableToCompleteException {
- return new BasicWebModeCompiler(state, linker).getCompilationUnitDeclarations(logger,
- seedTypeNames);
- }
-
- private final TypeLinker linker;
-
- /**
- * Construct a BasicWebModeCompiler.
- */
- public BasicWebModeCompiler(CompilationState compilationState, TypeLinker linker) {
- super(compilationState, false);
- this.linker = linker;
- }
-
- /**
- * Build the initial set of compilation units.
- */
- public CompilationResults getCompilationUnitDeclarations(TreeLogger logger,
- String[] seedTypeNames, ICompilationUnit... additionalUnits) throws UnableToCompleteException {
-
- Map<String, CompiledClass> classMapBySource = compilationState.getClassFileMapBySource();
-
- /*
- * The alreadyAdded set prevents duplicate CompilationUnits from being added
- * to the icu list in the case of multiple JSO implementations as inner
- * classes in the same top-level class or seed classes as SingleJsoImpls
- * (e.g. JSO itself as the SingleImpl for all tag interfaces).
- */
- Set<CompilationUnit> alreadyAdded = new HashSet<CompilationUnit>();
-
- List<ICompilationUnit> icus =
- new ArrayList<ICompilationUnit>(seedTypeNames.length + additionalUnits.length);
-
- Collections.addAll(icus, additionalUnits);
-
- for (String seedTypeName : seedTypeNames) {
- CompilationUnit unit = getUnitForType(logger, classMapBySource, seedTypeName);
-
- if (unit == null) {
- continue;
- }
-
- if (alreadyAdded.add(unit)) {
- icus.add(new CompilationUnitAdapter(unit));
- }
- }
-
- /*
- * Compile, which will pull in everything else via the
- * doFindAdditionalTypesUsingFoo() methods.
- */
- CompilationResults units = compile(logger, icus.toArray(new ICompilationUnit[icus.size()]));
- Memory.maybeDumpMemory("WebModeCompiler");
- return units;
- }
-
- /**
- * Pull in types referenced only via JSNI.
- */
- @Override
- protected String[] doFindAdditionalTypesUsingJsni(TreeLogger logger,
- CompilationUnitDeclaration cud) {
- FindJsniRefVisitor v = new FindJsniRefVisitor();
- cud.traverse(v, cud.scope);
- Set<String> jsniRefs = v.getJsniRefs();
- Set<String> dependentTypeNames = new HashSet<String>();
- for (String jsniRef : jsniRefs) {
- JsniRef parsed = JsniRef.parse(jsniRef);
- if (parsed != null) {
- // If we fail to parse, don't add a class reference.
- dependentTypeNames.add(parsed.className());
- }
- }
- return dependentTypeNames.toArray(new String[dependentTypeNames.size()]);
- }
-
- /**
- * Get the CompilationUnit for a named type or throw an
- * UnableToCompleteException.
- */
- private CompilationUnit getUnitForType(TreeLogger logger,
- Map<String, CompiledClass> classMapBySource, String typeName)
- throws UnableToCompleteException {
-
- CompiledClass compiledClass = classMapBySource.get(typeName);
- if (compiledClass == null) {
- if (linker.isExternalType(typeName)) {
- return null;
- }
- logger.log(TreeLogger.ERROR, "Unable to find compilation unit for type '" + typeName + "'");
- throw new UnableToCompleteException();
- }
-
- assert compiledClass.getUnit() != null;
- return compiledClass.getUnit();
- }
-}
diff --git a/dev/core/src/com/google/gwt/dev/jdt/FindDeferredBindingSitesVisitor.java b/dev/core/src/com/google/gwt/dev/jdt/FindDeferredBindingSitesVisitor.java
deleted file mode 100644
index fe180a1..0000000
--- a/dev/core/src/com/google/gwt/dev/jdt/FindDeferredBindingSitesVisitor.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed 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 com.google.gwt.dev.jdt;
-
-import com.google.gwt.dev.javac.GWTProblem;
-
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.Expression;
-import org.eclipse.jdt.internal.compiler.ast.MessageSend;
-import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
-import org.eclipse.jdt.internal.compiler.lookup.Scope;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Walks a
- * {@link org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration} to
- * find <code>GWT.create()</code> class so that we can eagerly complain about
- * deferred binding problems.
- */
-public class FindDeferredBindingSitesVisitor extends SafeASTVisitor {
-
- /**
- * Information about the site at which a rebind request was found, used to
- * report problems.
- */
- public static class MessageSendSite {
- public final MessageSend messageSend;
-
- public final Scope scope;
-
- public MessageSendSite(MessageSend messageSend, Scope scope) {
- this.messageSend = messageSend;
- this.scope = scope;
- }
- }
-
- public static final String MAGIC_CLASS = "com.google.gwt.core.client.GWT";
- public static final String REBIND_MAGIC_METHOD = "create";
-
- public static void reportRebindProblem(MessageSendSite site, String message) {
- MessageSend messageSend = site.messageSend;
- Scope scope = site.scope;
- // Safe since CUS.referenceContext is set in its constructor.
- CompilationUnitDeclaration cud = scope.compilationUnitScope().referenceContext;
- GWTProblem.recordError(messageSend, cud, message, null);
- }
-
- private final Map<String, MessageSendSite> results = new HashMap<String, MessageSendSite>();
-
- @Override
- public void endVisit(MessageSend messageSend, BlockScope scope) {
- if (messageSend.binding == null) {
- // Some sort of problem.
- return;
- }
-
- String methodName = String.valueOf(messageSend.selector);
- if (!methodName.equals(REBIND_MAGIC_METHOD)) {
- // Not the create() method.
- return;
- }
-
- char[][] targetClass = messageSend.binding.declaringClass.compoundName;
- String targetClassName = CharOperation.toString(targetClass);
- if (!targetClassName.equals(MAGIC_CLASS)) {
- // Not being called on the Rebind class.
- return;
- }
-
- MessageSendSite site = new MessageSendSite(messageSend, scope);
-
- Expression[] args = messageSend.arguments;
- if (args.length != 1) {
- reportRebindProblem(site, "GWT.create() should take exactly one argument");
- return;
- }
-
- if (!(args[0] instanceof ClassLiteralAccess)) {
- reportRebindProblem(site, "Only class literals may be used as arguments to GWT.create()");
- return;
- }
-
- ClassLiteralAccess cla = (ClassLiteralAccess) args[0];
- String typeName = String.valueOf(cla.targetType.readableName());
-
- if (!results.containsKey(typeName)) {
- results.put(typeName, site);
- }
- }
-
- public Map<String, MessageSendSite> getSites() {
- return Collections.unmodifiableMap(results);
- }
-}
diff --git a/dev/core/src/com/google/gwt/dev/jdt/FindJsniRefVisitor.java b/dev/core/src/com/google/gwt/dev/jdt/FindJsniRefVisitor.java
deleted file mode 100644
index 2fe19cf..0000000
--- a/dev/core/src/com/google/gwt/dev/jdt/FindJsniRefVisitor.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed 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 com.google.gwt.dev.jdt;
-
-import com.google.gwt.dev.javac.JsniCollector;
-import com.google.gwt.dev.jjs.InternalCompilerException;
-import com.google.gwt.dev.jjs.SourceOrigin;
-import com.google.gwt.dev.js.JsParser;
-import com.google.gwt.dev.js.JsParserException;
-import com.google.gwt.dev.js.ast.JsContext;
-import com.google.gwt.dev.js.ast.JsNameRef;
-import com.google.gwt.dev.js.ast.JsProgram;
-import com.google.gwt.dev.js.ast.JsStatement;
-import com.google.gwt.dev.js.ast.JsVisitor;
-
-import org.eclipse.jdt.internal.compiler.ast.Argument;
-import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
-import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Walks the AST to find references to Java identifiers from within JSNI blocks.
- * By default, it does a full JavaScript parse to accurately find JSNI
- * references. If {@link #beSloppy()} is called, then it will run much more
- * quickly but it will return a superset of the actual JSNI references.
- */
-public class FindJsniRefVisitor extends SafeASTVisitor {
- private final Set<String> jsniRefs = new LinkedHashSet<String>();
-
- public Set<String> getJsniRefs() {
- return Collections.unmodifiableSet(jsniRefs);
- }
-
- @Override
- public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
- if (!methodDeclaration.isNative()) {
- return false;
- }
-
- // Handle JSNI block
- String jsniCode = getJSNICode(methodDeclaration);
- if (jsniCode == null) {
- return false;
- }
- if (jsniCode.indexOf('@') < 0) {
- // short cut: if there are no at signs, there are no JSNI refs
- return false;
- }
-
- findJsniRefsAccurately(methodDeclaration, jsniCode);
- return false;
- }
-
- private void findJsniRefsAccurately(MethodDeclaration methodDeclaration, String jsniCode)
- throws InternalCompilerException {
- JsProgram jsProgram = new JsProgram();
-
- String syntheticFnHeader = "function(";
- boolean first = true;
- if (methodDeclaration.arguments != null) {
- for (int i = 0, c = methodDeclaration.arguments.length; i < c; ++i) {
- Argument arg = methodDeclaration.arguments[i];
- if (first) {
- first = false;
- } else {
- syntheticFnHeader += ',';
- }
- syntheticFnHeader += String.valueOf(arg.name);
- }
- }
- syntheticFnHeader += ')';
- StringReader sr = new StringReader(syntheticFnHeader + '\n' + jsniCode);
- try {
- // start at -1 to avoid counting our synthetic header
- List<JsStatement> result = JsParser.parse(SourceOrigin.UNKNOWN, jsProgram.getScope(), sr);
- new JsVisitor() {
- @Override
- public void endVisit(JsNameRef x, JsContext ctx) {
- String ident = x.getIdent();
- if (ident.charAt(0) == '@') {
- jsniRefs.add(ident.substring(1));
- }
- }
- }.acceptList(result);
- } catch (IOException e) {
- throw new InternalCompilerException(e.getMessage(), e);
- } catch (JsParserException e) {
- // ignore, we only care about finding valid references
- }
- }
-
- private String getJSNICode(MethodDeclaration methodDeclaration) {
- char[] source = methodDeclaration.compilationResult().getCompilationUnit().getContents();
- String jsniCode =
- String.valueOf(source, methodDeclaration.bodyStart, methodDeclaration.bodyEnd
- - methodDeclaration.bodyStart + 1);
- int startPos = jsniCode.indexOf(JsniCollector.JSNI_BLOCK_START);
- int endPos = jsniCode.lastIndexOf(JsniCollector.JSNI_BLOCK_END);
- if (startPos < 0 || endPos < 0) {
- return null; // ignore the error
- }
-
- // move up to open brace
- startPos += JsniCollector.JSNI_BLOCK_START.length() - 1;
- // move past close brace
- endPos += 1;
-
- jsniCode = jsniCode.substring(startPos, endPos);
- return jsniCode;
- }
-
-}
diff --git a/dev/core/src/com/google/gwt/dev/jdt/WebModeCompilerFrontEnd.java b/dev/core/src/com/google/gwt/dev/jdt/WebModeCompilerFrontEnd.java
deleted file mode 100644
index 3492108..0000000
--- a/dev/core/src/com/google/gwt/dev/jdt/WebModeCompilerFrontEnd.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed 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 com.google.gwt.dev.jdt;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.dev.javac.ArtificialRescueChecker;
-import com.google.gwt.dev.jdt.FindDeferredBindingSitesVisitor.MessageSendSite;
-import com.google.gwt.dev.jjs.impl.TypeLinker;
-import com.google.gwt.dev.util.Empty;
-import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
-import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
-import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
-
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Provides a reusable front-end based on the JDT compiler that incorporates
- * GWT-specific concepts such as JSNI and deferred binding.
- */
-public class WebModeCompilerFrontEnd extends BasicWebModeCompiler {
-
- public static CompilationResults getCompilationUnitDeclarations(TreeLogger logger,
- String[] seedTypeNames, RebindPermutationOracle rebindPermOracle, TypeLinker linker,
- ICompilationUnit... additionalUnits) throws UnableToCompleteException {
- Event getCompilationUnitsEvent =
- SpeedTracerLogger.start(CompilerEventType.GET_COMPILATION_UNITS);
- CompilationResults results =
- new WebModeCompilerFrontEnd(rebindPermOracle, linker).getCompilationUnitDeclarations(
- logger, seedTypeNames, additionalUnits);
- getCompilationUnitsEvent.end();
- return results;
- }
-
- private final RebindPermutationOracle rebindPermOracle;
-
- /**
- * Construct a WebModeCompilerFrontEnd.
- */
- private WebModeCompilerFrontEnd(RebindPermutationOracle rebindPermOracle, TypeLinker linker) {
- super(rebindPermOracle.getCompilationState(), linker);
- this.rebindPermOracle = rebindPermOracle;
- }
-
- @Override
- protected String[] doFindAdditionalTypesUsingArtificialRescues(TreeLogger logger,
- CompilationUnitDeclaration cud) {
- List<String> types = ArtificialRescueChecker.collectReferencedTypes(cud);
- return types.isEmpty() ? Empty.STRINGS : types.toArray(new String[types.size()]);
- }
-
- /**
- * Pull in types implicitly referenced through rebind answers.
- */
- @Override
- protected String[] doFindAdditionalTypesUsingRebinds(TreeLogger logger,
- CompilationUnitDeclaration cud) {
- Set<String> dependentTypeNames = new LinkedHashSet<String>();
-
- // Find all the deferred binding request types.
- FindDeferredBindingSitesVisitor v = new FindDeferredBindingSitesVisitor();
- cud.traverse(v, cud.scope);
- Map<String, MessageSendSite> requestedTypes = v.getSites();
- Map<String, String[]> rebindAnswers = new HashMap<String, String[]>();
- boolean doFinish = false;
-
- // For each, ask the host for every possible deferred binding answer.
- for (Map.Entry<String, MessageSendSite> entry : requestedTypes.entrySet()) {
- String reqType = entry.getKey();
- MessageSendSite site = entry.getValue();
- try {
- String[] resultTypes = rebindPermOracle.getAllPossibleRebindAnswers(logger, reqType);
- rebindAnswers.put(reqType, resultTypes);
- Collections.addAll(dependentTypeNames, resultTypes);
- doFinish = true;
- } catch (UnableToCompleteException e) {
- FindDeferredBindingSitesVisitor.reportRebindProblem(site, "Failed to resolve '" + reqType
- + "' via deferred binding");
- rebindAnswers.put(reqType, new String[0]);
- }
- }
-
- if (doFinish) {
- rebindPermOracle.getGeneratorContext().finish(logger);
- }
-
- // Sanity check all rebind answers.
- for (Map.Entry<String, MessageSendSite> entry : requestedTypes.entrySet()) {
- String reqType = entry.getKey();
- MessageSendSite site = entry.getValue();
- String[] resultTypes = rebindAnswers.get(reqType);
- // Check that each result is instantiable.
- for (String typeName : resultTypes) {
- checkRebindResultInstantiable(site, typeName);
- }
- }
-
- return dependentTypeNames.toArray(new String[dependentTypeNames.size()]);
- }
-
- private void checkRebindResultInstantiable(MessageSendSite site, String typeName) {
- /*
- * This causes the compiler to find the additional type, possibly winding
- * its back to ask for the compilation unit from the source oracle.
- */
- ReferenceBinding type = resolvePossiblyNestedType(typeName);
-
- // Sanity check rebind results.
- if (type == null) {
- FindDeferredBindingSitesVisitor.reportRebindProblem(site, "Rebind result '" + typeName
- + "' could not be found");
- return;
- }
- if (!type.isClass()) {
- FindDeferredBindingSitesVisitor.reportRebindProblem(site, "Rebind result '" + typeName
- + "' must be a class");
- return;
- }
- if (type.isAbstract()) {
- FindDeferredBindingSitesVisitor.reportRebindProblem(site, "Rebind result '" + typeName
- + "' cannot be abstract");
- return;
- }
- if (type.isNestedType() && !type.isStatic()) {
- FindDeferredBindingSitesVisitor.reportRebindProblem(site, "Rebind result '" + typeName
- + "' cannot be a non-static nested class");
- return;
- }
- if (type.isLocalType()) {
- FindDeferredBindingSitesVisitor.reportRebindProblem(site, "Rebind result '" + typeName
- + "' cannot be a local class");
- return;
- }
- // Look for a noArg ctor.
- MethodBinding noArgCtor = type.getExactConstructor(Binding.NO_PARAMETERS);
- if (noArgCtor == null) {
- FindDeferredBindingSitesVisitor.reportRebindProblem(site, "Rebind result '" + typeName
- + "' has no default (zero argument) constructors");
- return;
- }
- }
-}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/AstConstructor.java b/dev/core/src/com/google/gwt/dev/jjs/AstConstructor.java
index 4b4c7f7..8826981 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/AstConstructor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/AstConstructor.java
@@ -20,12 +20,10 @@
import com.google.gwt.dev.javac.CompilationState;
import com.google.gwt.dev.javac.StandardGeneratorContext;
import com.google.gwt.dev.jdt.RebindPermutationOracle;
-import com.google.gwt.dev.jjs.CorrelationFactory.DummyCorrelationFactory;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.impl.AssertionNormalizer;
import com.google.gwt.dev.jjs.impl.AssertionRemover;
import com.google.gwt.dev.jjs.impl.FixAssignmentToUnbox;
-import com.google.gwt.dev.jjs.impl.GwtAstBuilder;
import com.google.gwt.dev.jjs.impl.ImplementClassLiteralsAsFields;
import com.google.gwt.dev.jjs.impl.ReplaceRunAsyncs;
import com.google.gwt.dev.jjs.impl.UnifyAst;
@@ -66,9 +64,8 @@
}
};
- JProgram jprogram = new JProgram(DummyCorrelationFactory.INSTANCE);
- JsProgram jsProgram = new JsProgram(DummyCorrelationFactory.INSTANCE);
- assert GwtAstBuilder.ENABLED;
+ JProgram jprogram = new JProgram();
+ JsProgram jsProgram = new JsProgram();
UnifyAst unifyAst = new UnifyAst(jprogram, jsProgram, options, rpo);
unifyAst.buildEverything(logger);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
index 67d86c7..db7f4f7 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -41,12 +41,8 @@
import com.google.gwt.dev.cfg.ConfigurationProperty;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.javac.CompilationProblemReporter;
-import com.google.gwt.dev.javac.CompilationProblemReporter.SourceFetcher;
import com.google.gwt.dev.javac.typemodel.TypeOracle;
import com.google.gwt.dev.jdt.RebindPermutationOracle;
-import com.google.gwt.dev.jdt.WebModeCompilerFrontEnd;
-import com.google.gwt.dev.jjs.CorrelationFactory.DummyCorrelationFactory;
-import com.google.gwt.dev.jjs.CorrelationFactory.RealCorrelationFactory;
import com.google.gwt.dev.jjs.UnifiedAst.AST;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
@@ -68,7 +64,6 @@
import com.google.gwt.dev.jjs.impl.AssertionNormalizer;
import com.google.gwt.dev.jjs.impl.AssertionRemover;
import com.google.gwt.dev.jjs.impl.AstDumper;
-import com.google.gwt.dev.jjs.impl.BuildTypeMap;
import com.google.gwt.dev.jjs.impl.CastNormalizer;
import com.google.gwt.dev.jjs.impl.CatchBlockNormalizer;
import com.google.gwt.dev.jjs.impl.CodeSplitter;
@@ -79,9 +74,7 @@
import com.google.gwt.dev.jjs.impl.EqualityNormalizer;
import com.google.gwt.dev.jjs.impl.Finalizer;
import com.google.gwt.dev.jjs.impl.FixAssignmentToUnbox;
-import com.google.gwt.dev.jjs.impl.GenerateJavaAST;
import com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST;
-import com.google.gwt.dev.jjs.impl.GwtAstBuilder;
import com.google.gwt.dev.jjs.impl.HandleCrossFragmentReferences;
import com.google.gwt.dev.jjs.impl.ImplementClassLiteralsAsFields;
import com.google.gwt.dev.jjs.impl.JavaToJavaScriptMap;
@@ -100,13 +93,10 @@
import com.google.gwt.dev.jjs.impl.RecordRebinds;
import com.google.gwt.dev.jjs.impl.RemoveEmptySuperCalls;
import com.google.gwt.dev.jjs.impl.ReplaceGetClassOverrides;
-import com.google.gwt.dev.jjs.impl.ReplaceRebinds;
import com.google.gwt.dev.jjs.impl.ReplaceRunAsyncs;
import com.google.gwt.dev.jjs.impl.ResolveRebinds;
import com.google.gwt.dev.jjs.impl.SameParameterValueOptimizer;
import com.google.gwt.dev.jjs.impl.SourceInfoCorrelator;
-import com.google.gwt.dev.jjs.impl.TypeLinker;
-import com.google.gwt.dev.jjs.impl.TypeMap;
import com.google.gwt.dev.jjs.impl.TypeTightener;
import com.google.gwt.dev.jjs.impl.UnifyAst;
import com.google.gwt.dev.jjs.impl.gflow.DataflowOptimizer;
@@ -145,9 +135,6 @@
import com.google.gwt.soyc.SoycDashboard;
import com.google.gwt.soyc.io.ArtifactsOutputDirectory;
-import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.xml.sax.SAXException;
import java.io.ByteArrayOutputStream;
@@ -533,94 +520,36 @@
Memory.maybeDumpMemory("CompStateBuilt");
- CorrelationFactory correlator =
- options.isSoycExtra() ? RealCorrelationFactory.INSTANCE : DummyCorrelationFactory.INSTANCE;
- JProgram jprogram = new JProgram(correlator);
- JsProgram jsProgram = new JsProgram(correlator);
+ JProgram jprogram = new JProgram();
+ JsProgram jsProgram = new JsProgram();
try {
- if (GwtAstBuilder.ENABLED) {
- UnifyAst unifyAst = new UnifyAst(jprogram, jsProgram, options, rpo);
- unifyAst.addRootTypes(allRootTypes);
- // TODO: errors.
- // TODO: move this into UnifyAst.
- findEntryPoints(logger, rpo, declEntryPts, jprogram);
- unifyAst.exec(logger);
- // TODO: errors.
+ // (2) Assemble the Java AST.
+ UnifyAst unifyAst = new UnifyAst(jprogram, jsProgram, options, rpo);
+ unifyAst.addRootTypes(allRootTypes);
+ // TODO: move this into UnifyAst?
+ findEntryPoints(logger, rpo, declEntryPts, jprogram);
+ unifyAst.exec(logger);
- List<String> finalTypeOracleTypes = Lists.create();
- if (precompilationMetrics != null) {
- for (com.google.gwt.core.ext.typeinfo.JClassType type : typeOracle.getTypes()) {
- finalTypeOracleTypes =
- Lists.add(finalTypeOracleTypes, type.getPackage().getName() + "." + type.getName());
- }
- precompilationMetrics.setFinalTypeOracleTypes(finalTypeOracleTypes);
+ List<String> finalTypeOracleTypes = Lists.create();
+ if (precompilationMetrics != null) {
+ for (com.google.gwt.core.ext.typeinfo.JClassType type : typeOracle.getTypes()) {
+ finalTypeOracleTypes =
+ Lists.add(finalTypeOracleTypes, type.getPackage().getName() + "." + type.getName());
}
-
- // Free up memory.
- rpo.clear();
-
- if (options.isSoycEnabled()) {
- SourceInfoCorrelator.exec(jprogram);
- }
-
- // Compute all super type/sub type info
- jprogram.typeOracle.computeBeforeAST();
- } else {
-
- // Compile the source and get the compiler so we can get the parse tree
- CompilationUnitDeclaration[] goldenCuds =
- WebModeCompilerFrontEnd.getCompilationUnitDeclarations(logger, allRootTypes
- .toArray(new String[allRootTypes.size()]), rpo, TypeLinker.NULL_TYPE_LINKER).compiledUnits;
-
- List<String> finalTypeOracleTypes = Lists.create();
- if (precompilationMetrics != null) {
- for (com.google.gwt.core.ext.typeinfo.JClassType type : typeOracle.getTypes()) {
- finalTypeOracleTypes =
- Lists.add(finalTypeOracleTypes, type.getPackage().getName() + "." + type.getName());
- }
- precompilationMetrics.setFinalTypeOracleTypes(finalTypeOracleTypes);
- }
-
- // Free up memory.
- rpo.clear();
- Memory.maybeDumpMemory("GoldenCudsBuilt");
-
- /*
- * Check for compilation problems. We don't log here because any
- * problems found here will have already been logged by
- * AbstractCompiler.
- */
- checkForErrors(logger, goldenCuds, false);
-
- /*
- * (1) Build a flattened map of TypeDeclarations => JType. The resulting
- * map contains entries for all reference types. BuildTypeMap also
- * parses all JSNI.
- */
- TypeMap typeMap = new TypeMap(jprogram);
- TypeDeclaration[] allTypeDeclarations = BuildTypeMap.exec(typeMap, goldenCuds, jsProgram);
-
- // BuildTypeMap can uncover syntactic JSNI errors; report & abort
- checkForErrors(logger, goldenCuds, true);
-
- // Compute all super type/sub type info
- jprogram.typeOracle.computeBeforeAST();
-
- // (2) Create our own Java AST from the JDT AST.
- GenerateJavaAST.exec(allTypeDeclarations, typeMap, jprogram, options);
-
- // GenerateJavaAST can uncover semantic JSNI errors; report & abort
- checkForErrors(logger, goldenCuds, true);
-
- Memory.maybeDumpMemory("AstBuilt");
-
- // Allow GC
- goldenCuds = null;
- typeMap = null;
- allTypeDeclarations = null;
+ precompilationMetrics.setFinalTypeOracleTypes(finalTypeOracleTypes);
}
+ // Free up memory.
+ rpo.clear();
+
+ if (options.isSoycEnabled()) {
+ SourceInfoCorrelator.exec(jprogram);
+ }
+
+ // Compute all super type/sub type info
+ jprogram.typeOracle.computeBeforeAST();
+
Memory.maybeDumpMemory("AstOnly");
AstDumper.maybeDumpAST(jprogram);
@@ -649,22 +578,12 @@
AssertionRemover.exec(jprogram);
}
- if (!GwtAstBuilder.ENABLED) {
- // Replace GWT.create calls with JGwtCreate nodes.
- ReplaceRebinds.exec(logger, jprogram, rpo);
- }
-
// Fix up GWT.runAsync()
if (module != null && options.isRunAsyncEnabled()) {
ReplaceRunAsyncs.exec(logger, jprogram);
CodeSplitter.pickInitialLoadSequence(logger, jprogram, module.getProperties());
}
- if (!GwtAstBuilder.ENABLED) {
- // Resolve entry points, rebinding non-static entry points.
- findEntryPoints(logger, rpo, declEntryPts, jprogram);
- }
-
ImplementClassLiteralsAsFields.exec(jprogram);
/*
@@ -875,48 +794,6 @@
return stats;
}
- /**
- * Look through the list of compiled units for errors and log them to the
- * console.
- *
- * @param logger logger to use for compilation errors
- * @param cuds compiled units to analyze for errors.
- * @param itemizeErrors log each error or simply log one message if the build
- * failed.
- * @throws UnableToCompleteException if a compilation error is found in the
- * cuds argument.
- */
- static void checkForErrors(TreeLogger logger, CompilationUnitDeclaration[] cuds,
- boolean itemizeErrors) throws UnableToCompleteException {
- Event checkForErrorsEvent = SpeedTracerLogger.start(CompilerEventType.CHECK_FOR_ERRORS);
- boolean compilationFailed = false;
- if (cuds.length == 0) {
- compilationFailed = true;
- }
- for (CompilationUnitDeclaration cud : cuds) {
- final CompilationResult result = cud.compilationResult();
- if (result.hasErrors()) {
- compilationFailed = true;
- // Early out if we don't need to itemize.
- if (!itemizeErrors) {
- break;
- }
- String typeName = new String(cud.getMainTypeName());
- CompilationProblemReporter.reportErrors(logger, result.getErrors(), new String(cud
- .getFileName()), true, new SourceFetcher() {
- public String getSource() {
- return new String(result.getCompilationUnit().getContents());
- }
- }, typeName, false);
- }
- }
- checkForErrorsEvent.end();
- if (compilationFailed) {
- logger.log(TreeLogger.ERROR, "Cannot proceed due to previous errors", null);
- throw new UnableToCompleteException();
- }
- }
-
private static MultipleDependencyGraphRecorder chooseDependencyRecorder(boolean soycEnabled,
OutputStream out) {
MultipleDependencyGraphRecorder dependencyRecorder = CodeSplitter.NULL_RECORDER;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JDeclaredType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JDeclaredType.java
index 0ed7343..7b127d2 100755
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JDeclaredType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JDeclaredType.java
@@ -83,15 +83,6 @@
}
/**
- * TODO: remove me, just for source compatibility.
- */
- @Deprecated
- public void addField(int index, JField field) {
- assert field.getEnclosingType() == this;
- fields = Lists.add(fields, index, field);
- }
-
- /**
* Adds a field to this type.
*/
public void addField(JField field) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
index 63351a5..95aba96 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
@@ -16,14 +16,10 @@
package com.google.gwt.dev.jjs.ast;
import com.google.gwt.dev.jjs.Correlation.Literal;
-import com.google.gwt.dev.jjs.CorrelationFactory;
-import com.google.gwt.dev.jjs.CorrelationFactory.DummyCorrelationFactory;
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.SourceOrigin;
-import com.google.gwt.dev.jjs.ast.JField.Disposition;
import com.google.gwt.dev.jjs.ast.js.JsCastMap;
-import com.google.gwt.dev.jjs.ast.js.JsniMethodBody;
import com.google.gwt.dev.jjs.impl.CodeSplitter;
import com.google.gwt.dev.util.collect.Lists;
@@ -333,11 +329,6 @@
private Map<JType, JField> classLiteralFields;
- /**
- * A factory to create correlations.
- */
- private final CorrelationFactory correlator;
-
private final List<JMethod> entryMethods = new ArrayList<JMethod>();
private final Map<String, JField> indexedFields = new HashMap<String, JField>();
@@ -379,10 +370,6 @@
private JClassType typeString;
- public JProgram() {
- this(DummyCorrelationFactory.INSTANCE);
- }
-
/**
* Constructor.
*
@@ -391,10 +378,8 @@
* will collect extra data during the compilation cycle, but at a
* cost of memory and object allocations.
*/
- public JProgram(CorrelationFactory correlator) {
- super(correlator.makeSourceInfo(SourceOrigin.create(0, JProgram.class.getName())));
-
- this.correlator = correlator;
+ public JProgram() {
+ super(SourceOrigin.UNKNOWN);
}
public void addEntryMethod(JMethod entryPoint) {
@@ -445,115 +430,6 @@
}
}
- public JClassType createClass(SourceInfo info, String name, boolean isAbstract, boolean isFinal) {
- JClassType x = new JClassType(info, name, isAbstract, isFinal);
- addType(x);
- return x;
- }
-
- public JConstructor createConstructor(SourceInfo info, JClassType enclosingType) {
- JConstructor x = new JConstructor(info, enclosingType);
- x.setBody(new JMethodBody(info));
- if (indexedTypes.containsValue(enclosingType)) {
- indexedMethods.put(enclosingType.getShortName() + '.' + enclosingType.getShortName(), x);
- }
-
- enclosingType.addMethod(x);
- return x;
- }
-
- public JEnumType createEnum(SourceInfo info, String name, boolean isAbstract) {
- JEnumType x = new JEnumType(info, name, isAbstract);
- x.setSuperClass(getTypeJavaLangEnum());
-
- allTypes.add(x);
- putIntoTypeMap(name, x);
-
- return x;
- }
-
- public JField createEnumField(SourceInfo info, String name, JEnumType enclosingType,
- JClassType type, int ordinal) {
- assert (name != null);
- assert (type != null);
- assert (ordinal >= 0);
-
- JEnumField x = new JEnumField(info, name, ordinal, enclosingType, type);
- enclosingType.addField(x);
- return x;
- }
-
- public JField createField(SourceInfo info, String name, JDeclaredType enclosingType, JType type,
- boolean isStatic, Disposition disposition) {
- assert (name != null);
- assert (enclosingType != null);
- assert (type != null);
-
- JField x = new JField(info, name, enclosingType, type, isStatic, disposition);
-
- if (indexedTypes.containsValue(enclosingType)) {
- indexedFields.put(enclosingType.getShortName() + '.' + name, x);
- }
-
- enclosingType.addField(x);
- return x;
- }
-
- public JInterfaceType createInterface(SourceInfo info, String name) {
- JInterfaceType x = new JInterfaceType(info, name);
- addType(x);
- return x;
- }
-
- public JMethod createMethod(SourceInfo info, String name, JDeclaredType enclosingType,
- JType returnType, boolean isAbstract, boolean isStatic, boolean isFinal,
- AccessModifier access, boolean isNative) {
- assert (name != null);
- assert (enclosingType != null);
- assert (returnType != null);
- assert (!isAbstract || !isNative);
- JMethod x =
- new JMethod(info, name, enclosingType, returnType, isAbstract, isStatic, isFinal, access);
- if (isNative) {
- x.setBody(new JsniMethodBody(info));
- } else if (!isAbstract) {
- x.setBody(new JMethodBody(info));
- }
-
- if (access != AccessModifier.PRIVATE && indexedTypes.containsValue(enclosingType)) {
- indexedMethods.put(enclosingType.getShortName() + '.' + name, x);
- }
-
- enclosingType.addMethod(x);
- return x;
- }
-
- /**
- * Create a SourceInfo object when the source is derived from a physical
- * location.
- */
- public SourceInfo createSourceInfo(int startPos, int endPos, int startLine, String fileName) {
- return correlator.makeSourceInfo(SourceOrigin.create(startPos, endPos, startLine, fileName));
- }
-
- /**
- * Create a SourceInfo object when the source is derived from a physical
- * location.
- */
- public SourceInfo createSourceInfo(int startLine, String fileName) {
- return correlator.makeSourceInfo(SourceOrigin.create(startLine, fileName));
- }
-
- /**
- * Create a SourceInfo object when the source is created by the compiler
- * itself.
- */
- public SourceInfo createSourceInfoSynthetic(Class<?> caller) {
- // TODO: consider using Java stack frames to discover the caller's file
- // and line number.
- return createSourceInfo(0, caller.getName());
- }
-
/**
* Return the least upper bound of a set of types. That is, the smallest type
* that is a supertype of all the input types.
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java b/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
deleted file mode 100644
index 83bd75d..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
+++ /dev/null
@@ -1,1010 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed 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 com.google.gwt.dev.jjs.impl;
-
-import com.google.gwt.dev.javac.JsniCollector;
-import com.google.gwt.dev.jdt.AbstractCompiler.CompilationResults;
-import com.google.gwt.dev.jdt.SafeASTVisitor;
-import com.google.gwt.dev.jjs.HasSourceInfo;
-import com.google.gwt.dev.jjs.InternalCompilerException;
-import com.google.gwt.dev.jjs.SourceInfo;
-import com.google.gwt.dev.jjs.SourceOrigin;
-import com.google.gwt.dev.jjs.ast.AccessModifier;
-import com.google.gwt.dev.jjs.ast.JClassType;
-import com.google.gwt.dev.jjs.ast.JConstructor;
-import com.google.gwt.dev.jjs.ast.JDeclaredType;
-import com.google.gwt.dev.jjs.ast.JEnumType;
-import com.google.gwt.dev.jjs.ast.JField;
-import com.google.gwt.dev.jjs.ast.JField.Disposition;
-import com.google.gwt.dev.jjs.ast.JInterfaceType;
-import com.google.gwt.dev.jjs.ast.JLocal;
-import com.google.gwt.dev.jjs.ast.JMethod;
-import com.google.gwt.dev.jjs.ast.JMethodBody;
-import com.google.gwt.dev.jjs.ast.JNullType;
-import com.google.gwt.dev.jjs.ast.JParameter;
-import com.google.gwt.dev.jjs.ast.JProgram;
-import com.google.gwt.dev.jjs.ast.JReferenceType;
-import com.google.gwt.dev.jjs.ast.JType;
-import com.google.gwt.dev.jjs.ast.js.JsniMethodBody;
-import com.google.gwt.dev.js.JsAbstractSymbolResolver;
-import com.google.gwt.dev.js.ast.JsFunction;
-import com.google.gwt.dev.js.ast.JsName;
-import com.google.gwt.dev.js.ast.JsNameRef;
-import com.google.gwt.dev.js.ast.JsNode;
-import com.google.gwt.dev.js.ast.JsParameter;
-import com.google.gwt.dev.js.ast.JsProgram;
-import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
-import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
-import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
-
-import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
-import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.Argument;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.Expression;
-import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.Statement;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
-import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
-import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
-import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
-import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
-import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
-import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
-import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
-import org.eclipse.jdt.internal.compiler.lookup.NestedTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding;
-import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
-import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
-import org.eclipse.jdt.internal.compiler.util.Util;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * This is a Builder for {@link TypeMap}. The whole point of this pass is to
- * create raw unfinished, unlinked AST nodes for types, methods, fields, and
- * parameters, and to map the original JDT nodes to these AST nodes. That way
- * when GenerateJavaDom runs, it just uses the TypeMap output from this Builder
- * to retrieve whatever referenceable nodes it needs without worrying about
- * whether they need to be created. Building our AST from JDT starts here.
- */
-public class BuildTypeMap {
-
- /**
- * Creates JNodes for every method, field, initializer, parameter, and local
- * and memorizes the mapping from the JDT Binding to the corresponding JNode
- * for each thing created. Note that this pass also 1) sets up the super
- * type(s) for any member or local types created in BuildTypeMapVisitor (see
- * the comments there about why it had to be deferred). 2) adds each
- * user-defined type to a flat list. 3) Creates JNodes for all methods and
- * variables and memorizes the mapping from the JDT Binding to the
- * corresponding JNode for each created method and variable. 4) Maps all
- * synthetic arguments and fields for nested and local classes. 5) Slurps in
- * JSNI code for native methods as an opaque string.
- *
- * Note that methods and fields are not added to their classes here, that
- * isn't done until {@link GenerateJavaAST}.
- */
- private class BuildDeclMapVisitor extends SafeASTVisitor {
-
- private String currentFileName;
- private int[] currentSeparatorPositions;
- private final List<TypeDeclaration> typeDecls = new ArrayList<TypeDeclaration>();
-
- public TypeDeclaration[] getTypeDeclarataions() {
- return typeDecls.toArray(new TypeDeclaration[typeDecls.size()]);
- }
-
- @Override
- public boolean visit(AnnotationMethodDeclaration methodDeclaration, ClassScope scope) {
- return visit((MethodDeclaration) methodDeclaration, scope);
- }
-
- @Override
- public boolean visit(Argument argument, BlockScope scope) {
- try {
- if (scope == scope.methodScope()) {
- return true;
- }
-
- JMethodBody enclosingBody = findEnclosingMethod(scope);
- if (enclosingBody == null) {
- // Happens in the case of external types
- return true;
- }
- SourceInfo info = makeSourceInfo(argument, enclosingBody.getMethod());
- LocalVariableBinding b = argument.binding;
- JType localType = getType(b.type);
- JLocal newLocal =
- JProgram.createLocal(info, String.valueOf(argument.name), localType, b.isFinal(),
- enclosingBody);
- typeMap.put(b, newLocal);
- return true;
- } catch (Throwable e) {
- throw translateException(argument, e);
- }
- }
-
- @Override
- public boolean visit(ConstructorDeclaration ctorDecl, ClassScope scope) {
- try {
- MethodBinding b = ctorDecl.binding;
- JClassType enclosingType = (JClassType) getType(scope.enclosingSourceType());
- SourceInfo info = makeSourceInfo(ctorDecl, enclosingType);
- processConstructor(b, ctorDecl, info);
- return true;
- } catch (Throwable e) {
- throw translateException(ctorDecl, e);
- }
- }
-
- @Override
- public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
- try {
- FieldBinding b = fieldDeclaration.binding;
- JDeclaredType enclosingType = (JDeclaredType) getType(scope.enclosingSourceType());
- SourceInfo info = makeSourceInfo(fieldDeclaration, enclosingType);
- Expression initialization = fieldDeclaration.initialization;
- if (initialization != null && initialization instanceof AllocationExpression
- && ((AllocationExpression) initialization).enumConstant != null) {
- createEnumField(info, b, enclosingType);
- } else {
- createField(info, b, enclosingType);
- }
- return true;
- } catch (Throwable e) {
- throw translateException(fieldDeclaration, e);
- }
- }
-
- @Override
- public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) {
- try {
- LocalVariableBinding b = localDeclaration.binding;
- TypeBinding resolvedType = localDeclaration.type.resolvedType;
- JType localType;
- if (resolvedType.constantPoolName() != null) {
- localType = getType(resolvedType);
- } else {
- // Special case, a statically unreachable local type.
- localType = JNullType.INSTANCE;
- }
- JMethodBody enclosingBody = findEnclosingMethod(scope);
- if (enclosingBody == null) {
- // Happens in the case of external types
- return true;
- }
- SourceInfo info = makeSourceInfo(localDeclaration, enclosingBody.getMethod());
- JLocal newLocal =
- JProgram.createLocal(info, String.valueOf(localDeclaration.name), localType, b
- .isFinal(), enclosingBody);
- typeMap.put(b, newLocal);
- return true;
- } catch (Throwable e) {
- throw translateException(localDeclaration, e);
- }
- }
-
- @Override
- public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
- try {
- MethodBinding b = methodDeclaration.binding;
- JDeclaredType enclosingType = (JDeclaredType) getType(scope.enclosingSourceType());
- SourceInfo info = makeSourceInfo(methodDeclaration, enclosingType);
- JMethod newMethod = processMethodBinding(b, enclosingType, info);
- SourceInfo methodInfo = makeSourceInfo(methodDeclaration, newMethod);
- mapParameters(newMethod, methodDeclaration, methodInfo);
- info.addCorrelation(info.getCorrelator().by(newMethod));
-
- if (newMethod.isNative()) {
- processNativeMethod(methodDeclaration, info, enclosingType, newMethod);
- }
-
- return true;
- } catch (Throwable e) {
- throw translateException(methodDeclaration, e);
- }
- }
-
- @Override
- public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
- return process(memberTypeDeclaration);
- }
-
- @Override
- public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
- return process(typeDeclaration);
- }
-
- @Override
- public boolean visitValid(TypeDeclaration localTypeDeclaration, BlockScope scope) {
- return process(localTypeDeclaration);
- }
-
- private JField createEnumField(SourceInfo info, FieldBinding binding,
- JReferenceType enclosingType) {
- JType type = getType(binding.type);
- JField field =
- program.createEnumField(info, String.valueOf(binding.name), (JEnumType) enclosingType,
- (JClassType) type, binding.original().id);
- info.addCorrelation(info.getCorrelator().by(field));
- typeMap.put(binding, field);
- return field;
- }
-
- private JMethodBody findEnclosingMethod(BlockScope scope) {
- JMethod method;
- MethodScope methodScope = scope.methodScope();
- if (methodScope.isInsideInitializer()) {
- JDeclaredType enclosingType =
- (JDeclaredType) getType(scope.classScope().referenceContext.binding);
- if (methodScope.isStatic) {
- // clinit
- method = enclosingType.getMethods().get(0);
- } else {
- // init
- assert (enclosingType instanceof JClassType);
- method = enclosingType.getMethods().get(1);
- }
- } else {
- AbstractMethodDeclaration referenceMethod = methodScope.referenceMethod();
- method = (JMethod) typeMap.get(referenceMethod.binding);
- }
- assert !method.isNative() && !method.isAbstract();
- return (JMethodBody) (method.isExternal() ? null : method.getBody());
- }
-
- private SourceInfo makeSourceInfo(AbstractMethodDeclaration methodDecl, HasSourceInfo enclosing) {
- int startLine =
- Util.getLineNumber(methodDecl.sourceStart, currentSeparatorPositions, 0,
- currentSeparatorPositions.length - 1);
- SourceOrigin toReturn =
- SourceOrigin.create(methodDecl.sourceStart, methodDecl.bodyEnd, startLine,
- currentFileName);
- if (enclosing != null) {
- return enclosing.getSourceInfo().makeChild(toReturn);
- }
- return toReturn;
- }
-
- private SourceInfo makeSourceInfo(Statement stmt, HasSourceInfo enclosing) {
- int startLine =
- Util.getLineNumber(stmt.sourceStart, currentSeparatorPositions, 0,
- currentSeparatorPositions.length - 1);
- SourceOrigin toReturn =
- SourceOrigin.create(stmt.sourceStart, stmt.sourceEnd, startLine, currentFileName);
- if (enclosing != null) {
- return enclosing.getSourceInfo().makeChild(toReturn);
- }
- return toReturn;
- }
-
- /**
- * Add synthetic fields, setup super types. You'll notice that we DON'T have
- * any concept of "inner" or "outer" types in our AST. Truth is, we found it
- * easier to simply model everything as flat classes and emulate the nesting
- * behavior (and final local access on local classes). It's much closer to
- * how we'll eventually be generating JavaScript code (code generation is
- * more straightforward), it makes for fewer kinds of things to worry about
- * when optimizing (more aggressive optimizations), and it's how Java
- * actually implements the stuff under the hood anyway.
- */
- private boolean process(TypeDeclaration typeDeclaration) {
- CompilationResult compResult = typeDeclaration.compilationResult;
- currentSeparatorPositions = compResult.lineSeparatorPositions;
- currentFileName = String.valueOf(compResult.fileName);
-
- if (BuildTypeMap.this.process(typeDeclaration.binding)) {
- if (!linker.isExternalType(dotify(typeDeclaration.binding.compoundName))) {
- typeDecls.add(typeDeclaration);
- }
- return true;
- }
-
- return false;
- }
-
- private void processNativeMethod(MethodDeclaration methodDeclaration, SourceInfo info,
- JDeclaredType enclosingType, JMethod newMethod) {
- // TODO: use existing parsed JSNI functions from CompilationState.
- // Handle JSNI block
- char[] source = methodDeclaration.compilationResult().getCompilationUnit().getContents();
- String unitSource = String.valueOf(source);
- JsFunction jsFunction =
- JsniCollector.parseJsniFunction(methodDeclaration, unitSource, enclosingType.getName(),
- info, jsProgram.getScope());
- if (jsFunction != null) {
- jsFunction.setFromJava(true);
- ((JsniMethodBody) newMethod.getBody()).setFunc(jsFunction);
- // Ensure that we've resolved the parameter and local references within
- // the JSNI method for later pruning.
- JsParameterResolver localResolver = new JsParameterResolver(jsFunction);
- localResolver.accept(jsFunction);
- }
- }
-
- private InternalCompilerException translateException(AbstractMethodDeclaration amd, Throwable e) {
- if (e instanceof VirtualMachineError) {
- // Always rethrow VM errors (an attempt to wrap may fail).
- throw (VirtualMachineError) e;
- }
- InternalCompilerException ice;
- if (e instanceof InternalCompilerException) {
- ice = (InternalCompilerException) e;
- } else {
- ice = new InternalCompilerException("Error building type map", e);
- }
- ice.addNode(amd.getClass().getName(), amd.toString(), makeSourceInfo(amd, null));
- return ice;
- }
-
- private InternalCompilerException translateException(Statement stmt, Throwable e) {
- if (e instanceof VirtualMachineError) {
- // Always rethrow VM errors (an attempt to wrap may fail).
- throw (VirtualMachineError) e;
- }
- InternalCompilerException ice;
- if (e instanceof InternalCompilerException) {
- ice = (InternalCompilerException) e;
- } else {
- ice = new InternalCompilerException("Error building type map", e);
- }
- ice.addNode(stmt.getClass().getName(), stmt.toString(), makeSourceInfo(stmt, null));
- return ice;
- }
- }
-
- /**
- * Creates JNodes for every type and memorizes the mapping from the JDT
- * Binding to the corresponding JNode for each created type. Note that since
- * there could be forward references, it is not possible to set up super
- * types; it must be done is a subsequent pass.
- */
- private class BuildTypeMapVisitor extends SafeASTVisitor {
-
- @Override
- public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
- return process(memberTypeDeclaration);
- }
-
- @Override
- public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
- return process(typeDeclaration);
- }
-
- @Override
- public boolean visitValid(TypeDeclaration localTypeDeclaration, BlockScope scope) {
- assert (TypeDeclaration.kind(localTypeDeclaration.modifiers) != TypeDeclaration.INTERFACE_DECL);
- return process(localTypeDeclaration);
- }
-
- private SourceInfo makeSourceInfo(TypeDeclaration typeDecl) {
- CompilationResult compResult = typeDecl.compilationResult;
- int[] indexes = compResult.lineSeparatorPositions;
- String fileName = String.valueOf(compResult.fileName);
- int startLine = Util.getLineNumber(typeDecl.sourceStart, indexes, 0, indexes.length - 1);
- return program.createSourceInfo(typeDecl.sourceStart, typeDecl.bodyEnd, startLine, fileName);
- }
-
- private boolean process(TypeDeclaration typeDeclaration) {
- try {
- SourceTypeBinding binding = typeDeclaration.binding;
- String name = dotify(binding.compoundName);
- if (binding instanceof LocalTypeBinding) {
- char[] localName = binding.constantPoolName();
- name = new String(localName).replace('/', '.');
- }
-
- SourceInfo info = makeSourceInfo(typeDeclaration);
- typeMap.put(binding, createType(name, info, binding));
- return true;
- } catch (Throwable e) {
- throw translateException(typeDeclaration, e);
- }
- }
-
- private InternalCompilerException translateException(TypeDeclaration typeDecl, Throwable e) {
- if (e instanceof VirtualMachineError) {
- // Always rethrow VM errors (an attempt to wrap may fail).
- throw (VirtualMachineError) e;
- }
- InternalCompilerException ice;
- if (e instanceof InternalCompilerException) {
- ice = (InternalCompilerException) e;
- } else {
- ice = new InternalCompilerException("Error building type map", e);
- }
- ice.addNode(typeDecl.getClass().getName(), typeDecl.toString(), makeSourceInfo(typeDecl));
- return ice;
- }
- }
-
- private class ExternalTypeCreator implements ExternalTypeTask {
-
- public void process(String klass, BinaryTypeBinding binding) {
- if (program.getFromTypeMap(klass) == null) {
- // NB(tobyr) There are a few cases where certain compiler intrinsic
- // types are only needed if the program references them
- // (e.g. boxed numeric types). If we don't have the binding for those
- // types, we can safely ignore it.
- createExternalType(klass, binding);
- }
- }
- }
-
- private class ExternalTypeResolver implements ExternalTypeTask {
-
- public void process(String klass, BinaryTypeBinding binding) {
- if (binding != null) {
- JDeclaredType type = program.getFromTypeMap(klass);
- resolve(type, binding);
- }
- }
- }
-
- private interface ExternalTypeTask {
-
- void process(String klass, BinaryTypeBinding binding);
- }
-
- /**
- * Resolves the scope of JS identifiers solely within the scope of a method.
- */
- private static class JsParameterResolver extends JsAbstractSymbolResolver {
- private final JsFunction jsFunction;
-
- public JsParameterResolver(JsFunction jsFunction) {
- this.jsFunction = jsFunction;
- }
-
- @Override
- public void resolve(JsNameRef x) {
- // Only resolve unqualified names
- if (x.getQualifier() == null) {
- JsName name = getScope().findExistingName(x.getIdent());
-
- // Ensure that we're resolving a name from the function's parameters
- JsNode node = name == null ? null : name.getStaticRef();
- if (node instanceof JsParameter) {
- JsParameter param = (JsParameter) node;
- if (jsFunction.getParameters().contains(param)) {
- x.resolve(name);
- }
- }
- }
- }
- }
-
- // TODO: Remove this overload altogether at some point.
-
- public static TypeDeclaration[] exec(TypeMap typeMap, CompilationResults results,
- JsProgram jsProgram, TypeLinker linker) {
- BuildTypeMap btm = new BuildTypeMap(typeMap, jsProgram, linker, results.compiledUnits);
- Event buildTypeMapEvent = SpeedTracerLogger.start(CompilerEventType.BUILD_TYPE_MAP_FOR_AST);
- btm.createPeersForUnits();
- btm.resolveExternalTypes(results.binaryBindings);
- TypeDeclaration[] result = btm.createPeersForNonTypeDecls();
- buildTypeMapEvent.end();
- return result;
- }
-
- public static TypeDeclaration[] exec(TypeMap typeMap, CompilationUnitDeclaration[] unitDecls,
- JsProgram jsProgram) {
- CompilationResults results =
- new CompilationResults(unitDecls, new HashMap<String, BinaryTypeBinding>(0));
- return exec(typeMap, results, jsProgram, TypeLinker.NULL_TYPE_LINKER);
- }
-
- static String dotify(char[][] name) {
- StringBuffer result = new StringBuffer();
- for (int i = 0; i < name.length; ++i) {
- if (i > 0) {
- result.append('.');
- }
-
- result.append(name[i]);
- }
- return result.toString();
- }
-
- private final JsProgram jsProgram;
- private final TypeLinker linker;
- private final JProgram program;
- private final TypeMap typeMap;
- private final CompilationUnitDeclaration[] unitDecls;
-
- private BuildTypeMap(TypeMap typeMap, JsProgram jsProgram, TypeLinker linker,
- CompilationUnitDeclaration[] unitDecls) {
- this.typeMap = typeMap;
- this.program = typeMap.getProgram();
- this.jsProgram = jsProgram;
- this.linker = linker;
- this.unitDecls = unitDecls;
- }
-
- private void addThrownExceptions(MethodBinding methodBinding, JMethod method) {
- for (ReferenceBinding thrownBinding : methodBinding.thrownExceptions) {
- JClassType type = (JClassType) getType(thrownBinding.erasure());
- method.addThrownException(type);
- }
- }
-
- private JDeclaredType createExternalType(String name, ReferenceBinding binding) {
- char[] chars = binding.getFileName();
- String fileName = chars == null ? "" : String.valueOf(chars);
- SourceInfo sourceInfo = SourceOrigin.create(0, fileName);
- JDeclaredType type = createType(name, sourceInfo, binding);
- typeMap.put(binding, type);
- return type;
- }
-
- private JField createField(SourceInfo info, FieldBinding binding, JDeclaredType enclosingType) {
- JType type = getType(binding.type);
- JField field =
- program.createField(info, String.valueOf(binding.name), enclosingType, type, binding
- .isStatic(), GwtAstBuilder.getFieldDisposition(binding));
- typeMap.put(binding, field);
- info.addCorrelation(info.getCorrelator().by(field));
- return field;
- }
-
- private JField createField(SyntheticArgumentBinding binding, JDeclaredType enclosingType,
- Disposition disposition) {
- JType type = getType(binding.type);
- SourceInfo info = enclosingType.getSourceInfo().makeChild();
- JField field =
- program.createField(info, String.valueOf(binding.name), enclosingType, type, false,
- disposition);
- info.addCorrelation(info.getCorrelator().by(field));
- if (binding.matchingField != null) {
- typeMap.put(binding.matchingField, field);
- }
- typeMap.put(binding, field);
- return field;
- }
-
- private void createMethod(MethodBinding binding, SourceInfo info) {
- JDeclaredType enclosingType = (JDeclaredType) getType(binding.declaringClass);
- JMethod newMethod = processMethodBinding(binding, enclosingType, info);
- mapParameters(newMethod, binding, info);
- }
-
- private JParameter createParameter(LocalVariableBinding binding, JMethod enclosingMethod,
- SourceInfo info) {
- JType type = getType(binding.type);
- JParameter param =
- JProgram.createParameter(info, String.valueOf(binding.name), type, binding.isFinal(),
- false, enclosingMethod);
- typeMap.put(binding, param);
- return param;
- }
-
- private JParameter createParameter(SyntheticArgumentBinding arg, String argName,
- JMethod enclosingMethod) {
- JType type = getType(arg.type);
- JParameter param =
- JProgram.createParameter(enclosingMethod.getSourceInfo(), argName, type, true, false,
- enclosingMethod);
- return param;
- }
-
- private JParameter createParameter(TypeBinding paramType, JMethod enclosingMethod,
- SourceInfo info, int argPosition) {
- JType type = getType(paramType);
- // TODO(tobyr) Get the actual param name if it's present in debug info
- // or otherwise.
- String syntheticParamName = "arg" + argPosition;
- JParameter param =
- JProgram.createParameter(info, syntheticParamName, type, true, false, enclosingMethod);
- // Don't need to put the parameter in the TypeMap as it won't be looked
- // up for binary types.
- return param;
- }
-
- private TypeDeclaration[] createPeersForNonTypeDecls() {
- // Traverse to create our JNode peers for each method, field,
- // parameter, and local
- BuildDeclMapVisitor v = new BuildDeclMapVisitor();
- for (CompilationUnitDeclaration unitDecl : unitDecls) {
- unitDecl.traverse(v, unitDecl.scope);
- }
- return v.getTypeDeclarataions();
- }
-
- private void createPeersForUnits() {
- // Traverse to create our JNode peers for each type
- BuildTypeMapVisitor v = new BuildTypeMapVisitor();
- for (CompilationUnitDeclaration unitDecl : unitDecls) {
- unitDecl.traverse(v, unitDecl.scope);
- }
- }
-
- private JDeclaredType createType(String name, SourceInfo info, ReferenceBinding binding) {
-
- JDeclaredType newType;
- if (binding.isClass()) {
- newType = program.createClass(info, name, binding.isAbstract(), binding.isFinal());
- } else if (binding.isInterface() || binding.isAnnotationType()) {
- newType = program.createInterface(info, name);
- } else if (binding.isEnum()) {
- if (binding.isAnonymousType()) {
- // Don't model an enum subclass as a JEnumType.
- newType = program.createClass(info, name, false, true);
- } else {
- newType = program.createEnum(info, name, binding.isAbstract());
- }
- } else {
- throw new InternalCompilerException("ReferenceBinding is not a class, interface, or enum.");
- }
-
- info.addCorrelation(info.getCorrelator().by(newType));
-
- /**
- * We emulate static initializers and instance initializers as methods. As
- * in other cases, this gives us: simpler AST, easier to optimize, more like
- * output JavaScript. Clinit is always in slot 0, init (if it exists) is
- * always in slot 1.
- */
- SourceInfo child = info.makeChild();
- JMethod clinit =
- program.createMethod(child, "$clinit", newType, program.getTypeVoid(), false, true, true,
- AccessModifier.PRIVATE, false);
- clinit.freezeParamTypes();
- clinit.setSynthetic();
- child.addCorrelation(info.getCorrelator().by(clinit));
-
- if (newType instanceof JClassType) {
- child = info.makeChild();
- JMethod init =
- program.createMethod(child, "$init", newType, program.getTypeVoid(), false, false, true,
- AccessModifier.PRIVATE, false);
- init.freezeParamTypes();
- init.setSynthetic();
- child.addCorrelation(info.getCorrelator().by(init));
- }
-
- newType.setExternal(linker.isExternalType(newType.getName()));
- return newType;
- }
-
- private void forEachExternalType(Map<String, BinaryTypeBinding> bindings, ExternalTypeTask task) {
- for (Map.Entry<String, BinaryTypeBinding> entry : bindings.entrySet()) {
- String klass = entry.getKey();
- if (linker.isExternalType(klass)) {
- BinaryTypeBinding binding = bindings.get(klass);
- if (binding != null) {
- task.process(klass, binding);
- }
- }
- }
- }
-
- private JType getType(TypeBinding binding) {
- JType type = (JType) typeMap.tryGet(binding);
-
- if (type != null) {
- return type;
- }
-
- if (binding instanceof ArrayBinding) {
- binding = ((ArrayBinding) binding).leafComponentType;
- }
-
- if (!(binding instanceof ReferenceBinding)) {
- throw new InternalCompilerException("Expected a ReferenceBinding but received a "
- + binding.getClass());
- }
-
- ReferenceBinding refBinding = (ReferenceBinding) binding;
- String name = dotify(refBinding.compoundName);
- if (!linker.isExternalType(name)) {
- // typeMap.get() will fail with an appropriate exception
- return (JType) typeMap.get(binding);
- }
-
- type = createExternalType(name, refBinding);
- resolve((JDeclaredType) type, refBinding);
- return type;
- }
-
- private void mapParameters(JMethod method, AbstractMethodDeclaration x, SourceInfo info) {
- MethodBinding b = x.binding;
- int paramCount = (b.parameters != null ? b.parameters.length : 0);
- if (paramCount > 0) {
- for (int i = 0, n = x.arguments.length; i < n; ++i) {
- createParameter(x.arguments[i].binding, method, info);
- }
- }
- method.freezeParamTypes();
- }
-
- private void mapParameters(JMethod method, MethodBinding binding, SourceInfo info) {
- int paramCount = binding.parameters != null ? binding.parameters.length : 0;
- if (paramCount > 0) {
- int counter = 0;
- for (TypeBinding argType : binding.parameters) {
- createParameter(argType, method, info, counter++);
- }
- }
- method.freezeParamTypes();
- }
-
- private boolean process(ReferenceBinding binding) {
- JDeclaredType type = (JDeclaredType) getType(binding);
-
- try {
- // Create an override for getClass().
- if (type instanceof JClassType && type != program.getTypeJavaLangObject()) {
-
- SourceInfo info = type.getSourceInfo().makeChild();
- JMethod getClassMethod =
- program.createMethod(info, "getClass", type, program.getTypeJavaLangClass(), false,
- false, false, AccessModifier.PUBLIC, false);
- assert (type.getMethods().get(2) == getClassMethod);
- getClassMethod.freezeParamTypes();
- getClassMethod.setSynthetic();
- info.addCorrelation(info.getCorrelator().by(getClassMethod));
- }
-
- if (binding.isNestedType() && !binding.isStatic() && !(binding instanceof BinaryTypeBinding)) {
- // TODO(tobyr) Do something here for binary types?
-
- // add synthetic fields for outer this and locals
- assert (type instanceof JClassType);
- NestedTypeBinding nestedBinding = (NestedTypeBinding) binding;
- if (nestedBinding.enclosingInstances != null) {
- for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) {
- SyntheticArgumentBinding arg = nestedBinding.enclosingInstances[i];
- createField(arg, type, Disposition.THIS_REF);
- }
- }
-
- if (nestedBinding.outerLocalVariables != null) {
- for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) {
- SyntheticArgumentBinding arg = nestedBinding.outerLocalVariables[i];
- // See InnerClassTest.testOuterThisFromSuperCall().
- boolean isReallyThisRef = false;
- if (arg.actualOuterLocalVariable instanceof SyntheticArgumentBinding) {
- SyntheticArgumentBinding outer =
- (SyntheticArgumentBinding) arg.actualOuterLocalVariable;
- if (outer.matchingField != null) {
- JField field = (JField) typeMap.get(outer.matchingField);
- if (field.isThisRef()) {
- isReallyThisRef = true;
- }
- }
- }
- createField(arg, type, isReallyThisRef ? Disposition.THIS_REF : Disposition.FINAL);
- }
- }
- }
-
- ReferenceBinding superClassBinding = binding.superclass();
- if (type instanceof JClassType && superClassBinding != null) {
- // TODO: handle separately?
- assert (binding.superclass().isClass() || binding.superclass().isEnum());
- JClassType superClass = (JClassType) getType(superClassBinding);
- ((JClassType) type).setSuperClass(superClass);
- }
-
- ReferenceBinding[] superInterfaces = binding.superInterfaces();
- for (ReferenceBinding superInterfaceBinding : superInterfaces) {
- assert (superInterfaceBinding.isInterface());
- JInterfaceType superInterface = (JInterfaceType) getType(superInterfaceBinding);
- type.addImplements(superInterface);
- }
-
- ReferenceBinding enclosingBinding = binding.enclosingType();
- if (enclosingBinding != null) {
- type.setEnclosingType((JDeclaredType) getType(enclosingBinding));
- }
-
- if (type instanceof JEnumType) {
- processEnumType(binding, (JEnumType) type);
- }
-
- return true;
- } catch (VirtualMachineError e) {
- // Always rethrow VM errors (an attempt to wrap may fail).
- throw e;
- } catch (InternalCompilerException ice) {
- ice.addNode(type);
- throw ice;
- } catch (Throwable e) {
- throw new InternalCompilerException(type, "Error building type map", e);
- }
- }
-
- private JConstructor processConstructor(MethodBinding b, ConstructorDeclaration decl,
- SourceInfo info) {
- JClassType enclosingType = (JClassType) getType(b.declaringClass);
- JConstructor newCtor = program.createConstructor(info, enclosingType);
-
- // Enums have hidden arguments for name and value
- if (enclosingType.isEnumOrSubclass() != null) {
- JProgram.createParameter(info, "enum$name", program.getTypeJavaLangString(), true, false,
- newCtor);
- JProgram.createParameter(info, "enum$ordinal", program.getTypePrimitiveInt(), true, false,
- newCtor);
- }
-
- ReferenceBinding declaringClass = b.declaringClass;
- Set<String> alreadyNamedVariables = new HashSet<String>();
- if (declaringClass.isNestedType() && !declaringClass.isStatic()) {
- // TODO(tobyr) Do we have to do the equivalent for binary types here
- // or will this just fall out correctly?
-
- // add synthetic args for outer this
- NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClass;
- if (nestedBinding.enclosingInstances != null) {
- for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) {
- SyntheticArgumentBinding arg = nestedBinding.enclosingInstances[i];
- String argName = String.valueOf(arg.name);
- if (alreadyNamedVariables.contains(argName)) {
- argName += "_" + i;
- }
- createParameter(arg, argName, newCtor);
- alreadyNamedVariables.add(argName);
- }
- }
- }
-
- // user args
- if (decl == null) {
- mapParameters(newCtor, b, info);
- } else {
- mapParameters(newCtor, decl, info);
- }
- // original params are now frozen
-
- addThrownExceptions(b, newCtor);
-
- info.addCorrelation(info.getCorrelator().by(newCtor));
-
- if (declaringClass.isNestedType() && !declaringClass.isStatic()) {
- // add synthetic args for locals
- NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClass;
- // add synthetic args for outer this and locals
- if (nestedBinding.outerLocalVariables != null) {
- for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) {
- SyntheticArgumentBinding arg = nestedBinding.outerLocalVariables[i];
- String argName = String.valueOf(arg.name);
- if (alreadyNamedVariables.contains(argName)) {
- argName += "_" + i;
- }
- createParameter(arg, argName, newCtor);
- alreadyNamedVariables.add(argName);
- }
- }
- }
-
- if (enclosingType.isExternal()) {
- newCtor.setBody(null);
- }
-
- typeMap.put(b, newCtor);
- return newCtor;
- }
-
- private void processEnumType(ReferenceBinding binding, JEnumType type) {
- // Visit the synthetic values() and valueOf() methods.
- for (MethodBinding methodBinding : binding.methods()) {
- if (methodBinding instanceof SyntheticMethodBinding) {
- JMethod newMethod = processMethodBinding(methodBinding, type, type.getSourceInfo());
- TypeBinding[] parameters = methodBinding.parameters;
- if (parameters.length == 0) {
- assert newMethod.getName().equals("values");
- } else if (parameters.length == 1) {
- assert newMethod.getName().equals("valueOf");
- assert typeMap.get(parameters[0]) == program.getTypeJavaLangString();
- JProgram.createParameter(newMethod.getSourceInfo(), "name", program
- .getTypeJavaLangString(), true, false, newMethod);
- } else {
- assert false;
- }
- newMethod.freezeParamTypes();
- }
- }
- }
-
- private void processExternalMethod(MethodBinding binding, JDeclaredType type) {
- if (binding.isPrivate()
- || (type.getName().startsWith("java.") && !binding.isPublic() && !binding.isProtected())) {
- return;
- }
- if (binding.isConstructor()) {
- processConstructor(binding, null, type.getSourceInfo());
- } else {
- createMethod(binding, type.getSourceInfo());
- }
- }
-
- private JMethod processMethodBinding(MethodBinding b, JDeclaredType enclosingType, SourceInfo info) {
- JType returnType = getType(b.returnType);
- JMethod newMethod =
- program.createMethod(info, String.valueOf(b.selector), enclosingType, returnType, b
- .isAbstract(), b.isStatic(), b.isFinal(), AccessModifier.fromMethodBinding(b), b
- .isNative());
- addThrownExceptions(b, newMethod);
- if (b.isSynthetic()) {
- newMethod.setSynthetic();
- }
-
- if (enclosingType.isExternal()) {
- newMethod.setBody(null);
- }
- typeMap.put(b, newMethod);
- return newMethod;
- }
-
- private void resolve(JDeclaredType type, ReferenceBinding binding) {
- process(binding);
-
- for (FieldBinding fieldBinding : binding.fields()) {
- if (fieldBinding.isPrivate()
- || (type.getName().startsWith("java.") && !fieldBinding.isPublic() && !fieldBinding
- .isProtected())) {
- continue;
- }
-
- createField(type.getSourceInfo(), fieldBinding, type);
- }
-
- for (MethodBinding methodBinding : binding.methods()) {
- processExternalMethod(methodBinding, type);
- }
-
- if (binding instanceof BinaryTypeBinding) {
- // Unlike SourceTypeBindings, we have to explicitly ask for bridge methods
- // for BinaryTypeBindings.
- try {
- // TODO(tobyr) Fix so we don't have to use reflection.
- Method m = BinaryTypeBinding.class.getDeclaredMethod("bridgeMethods");
- MethodBinding[] bridgeMethods = (MethodBinding[]) m.invoke(binding);
-
- for (MethodBinding methodBinding : bridgeMethods) {
- processExternalMethod(methodBinding, type);
- }
- } catch (Exception e) {
- throw new InternalCompilerException("Unexpected failure", e);
- }
- }
- }
-
- /**
- * Creates and resolves all external types.
- */
- private void resolveExternalTypes(Map<String, BinaryTypeBinding> bindings) {
- forEachExternalType(bindings, new ExternalTypeCreator());
- forEachExternalType(bindings, new ExternalTypeResolver());
- }
-}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
deleted file mode 100644
index 3c4883f..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
+++ /dev/null
@@ -1,3010 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed 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 com.google.gwt.dev.jjs.impl;
-
-import com.google.gwt.dev.javac.ArtificialRescueChecker.RescueData;
-import com.google.gwt.dev.javac.JsniCollector;
-import com.google.gwt.dev.jjs.InternalCompilerException;
-import com.google.gwt.dev.jjs.JJSOptions;
-import com.google.gwt.dev.jjs.SourceInfo;
-import com.google.gwt.dev.jjs.SourceOrigin;
-import com.google.gwt.dev.jjs.ast.AccessModifier;
-import com.google.gwt.dev.jjs.ast.Context;
-import com.google.gwt.dev.jjs.ast.JArrayLength;
-import com.google.gwt.dev.jjs.ast.JArrayRef;
-import com.google.gwt.dev.jjs.ast.JArrayType;
-import com.google.gwt.dev.jjs.ast.JAssertStatement;
-import com.google.gwt.dev.jjs.ast.JBinaryOperation;
-import com.google.gwt.dev.jjs.ast.JBinaryOperator;
-import com.google.gwt.dev.jjs.ast.JBlock;
-import com.google.gwt.dev.jjs.ast.JBooleanLiteral;
-import com.google.gwt.dev.jjs.ast.JBreakStatement;
-import com.google.gwt.dev.jjs.ast.JCaseStatement;
-import com.google.gwt.dev.jjs.ast.JCastOperation;
-import com.google.gwt.dev.jjs.ast.JCharLiteral;
-import com.google.gwt.dev.jjs.ast.JClassLiteral;
-import com.google.gwt.dev.jjs.ast.JClassType;
-import com.google.gwt.dev.jjs.ast.JConditional;
-import com.google.gwt.dev.jjs.ast.JConstructor;
-import com.google.gwt.dev.jjs.ast.JContinueStatement;
-import com.google.gwt.dev.jjs.ast.JDeclarationStatement;
-import com.google.gwt.dev.jjs.ast.JDeclaredType;
-import com.google.gwt.dev.jjs.ast.JDoStatement;
-import com.google.gwt.dev.jjs.ast.JDoubleLiteral;
-import com.google.gwt.dev.jjs.ast.JEnumField;
-import com.google.gwt.dev.jjs.ast.JEnumType;
-import com.google.gwt.dev.jjs.ast.JExpression;
-import com.google.gwt.dev.jjs.ast.JExpressionStatement;
-import com.google.gwt.dev.jjs.ast.JField;
-import com.google.gwt.dev.jjs.ast.JField.Disposition;
-import com.google.gwt.dev.jjs.ast.JFieldRef;
-import com.google.gwt.dev.jjs.ast.JFloatLiteral;
-import com.google.gwt.dev.jjs.ast.JForStatement;
-import com.google.gwt.dev.jjs.ast.JIfStatement;
-import com.google.gwt.dev.jjs.ast.JInstanceOf;
-import com.google.gwt.dev.jjs.ast.JIntLiteral;
-import com.google.gwt.dev.jjs.ast.JInterfaceType;
-import com.google.gwt.dev.jjs.ast.JLabel;
-import com.google.gwt.dev.jjs.ast.JLabeledStatement;
-import com.google.gwt.dev.jjs.ast.JLiteral;
-import com.google.gwt.dev.jjs.ast.JLocal;
-import com.google.gwt.dev.jjs.ast.JLocalRef;
-import com.google.gwt.dev.jjs.ast.JLongLiteral;
-import com.google.gwt.dev.jjs.ast.JMethod;
-import com.google.gwt.dev.jjs.ast.JMethodBody;
-import com.google.gwt.dev.jjs.ast.JMethodCall;
-import com.google.gwt.dev.jjs.ast.JModVisitor;
-import com.google.gwt.dev.jjs.ast.JNewArray;
-import com.google.gwt.dev.jjs.ast.JNewInstance;
-import com.google.gwt.dev.jjs.ast.JNode;
-import com.google.gwt.dev.jjs.ast.JNonNullType;
-import com.google.gwt.dev.jjs.ast.JParameter;
-import com.google.gwt.dev.jjs.ast.JParameterRef;
-import com.google.gwt.dev.jjs.ast.JPostfixOperation;
-import com.google.gwt.dev.jjs.ast.JPrefixOperation;
-import com.google.gwt.dev.jjs.ast.JPrimitiveType;
-import com.google.gwt.dev.jjs.ast.JProgram;
-import com.google.gwt.dev.jjs.ast.JReferenceType;
-import com.google.gwt.dev.jjs.ast.JReturnStatement;
-import com.google.gwt.dev.jjs.ast.JStatement;
-import com.google.gwt.dev.jjs.ast.JStringLiteral;
-import com.google.gwt.dev.jjs.ast.JSwitchStatement;
-import com.google.gwt.dev.jjs.ast.JThisRef;
-import com.google.gwt.dev.jjs.ast.JThrowStatement;
-import com.google.gwt.dev.jjs.ast.JTryStatement;
-import com.google.gwt.dev.jjs.ast.JType;
-import com.google.gwt.dev.jjs.ast.JTypeOracle;
-import com.google.gwt.dev.jjs.ast.JUnaryOperator;
-import com.google.gwt.dev.jjs.ast.JVariable;
-import com.google.gwt.dev.jjs.ast.JVariableRef;
-import com.google.gwt.dev.jjs.ast.JWhileStatement;
-import com.google.gwt.dev.jjs.ast.js.JsniClassLiteral;
-import com.google.gwt.dev.jjs.ast.js.JsniFieldRef;
-import com.google.gwt.dev.jjs.ast.js.JsniMethodBody;
-import com.google.gwt.dev.jjs.ast.js.JsniMethodRef;
-import com.google.gwt.dev.js.ast.JsContext;
-import com.google.gwt.dev.js.ast.JsExpression;
-import com.google.gwt.dev.js.ast.JsModVisitor;
-import com.google.gwt.dev.js.ast.JsNameRef;
-import com.google.gwt.dev.util.JsniRef;
-import com.google.gwt.dev.util.collect.Maps;
-import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
-import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
-import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
-
-import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression;
-import org.eclipse.jdt.internal.compiler.ast.ASTNode;
-import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
-import org.eclipse.jdt.internal.compiler.ast.Annotation;
-import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
-import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
-import org.eclipse.jdt.internal.compiler.ast.ArrayReference;
-import org.eclipse.jdt.internal.compiler.ast.AssertStatement;
-import org.eclipse.jdt.internal.compiler.ast.Assignment;
-import org.eclipse.jdt.internal.compiler.ast.BinaryExpression;
-import org.eclipse.jdt.internal.compiler.ast.Block;
-import org.eclipse.jdt.internal.compiler.ast.BreakStatement;
-import org.eclipse.jdt.internal.compiler.ast.CaseStatement;
-import org.eclipse.jdt.internal.compiler.ast.CastExpression;
-import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
-import org.eclipse.jdt.internal.compiler.ast.CombinedBinaryExpression;
-import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment;
-import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ContinueStatement;
-import org.eclipse.jdt.internal.compiler.ast.DoStatement;
-import org.eclipse.jdt.internal.compiler.ast.EmptyStatement;
-import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
-import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
-import org.eclipse.jdt.internal.compiler.ast.Expression;
-import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.FieldReference;
-import org.eclipse.jdt.internal.compiler.ast.ForStatement;
-import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
-import org.eclipse.jdt.internal.compiler.ast.IfStatement;
-import org.eclipse.jdt.internal.compiler.ast.Initializer;
-import org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression;
-import org.eclipse.jdt.internal.compiler.ast.LabeledStatement;
-import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.MessageSend;
-import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
-import org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression;
-import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
-import org.eclipse.jdt.internal.compiler.ast.PostfixExpression;
-import org.eclipse.jdt.internal.compiler.ast.PrefixExpression;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference;
-import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
-import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
-import org.eclipse.jdt.internal.compiler.ast.Statement;
-import org.eclipse.jdt.internal.compiler.ast.SuperReference;
-import org.eclipse.jdt.internal.compiler.ast.SwitchStatement;
-import org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement;
-import org.eclipse.jdt.internal.compiler.ast.ThisReference;
-import org.eclipse.jdt.internal.compiler.ast.ThrowStatement;
-import org.eclipse.jdt.internal.compiler.ast.TryStatement;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
-import org.eclipse.jdt.internal.compiler.ast.WhileStatement;
-import org.eclipse.jdt.internal.compiler.impl.BooleanConstant;
-import org.eclipse.jdt.internal.compiler.impl.ByteConstant;
-import org.eclipse.jdt.internal.compiler.impl.CharConstant;
-import org.eclipse.jdt.internal.compiler.impl.Constant;
-import org.eclipse.jdt.internal.compiler.impl.DoubleConstant;
-import org.eclipse.jdt.internal.compiler.impl.FloatConstant;
-import org.eclipse.jdt.internal.compiler.impl.IntConstant;
-import org.eclipse.jdt.internal.compiler.impl.LongConstant;
-import org.eclipse.jdt.internal.compiler.impl.ShortConstant;
-import org.eclipse.jdt.internal.compiler.impl.StringConstant;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
-import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
-import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
-import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
-import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
-import org.eclipse.jdt.internal.compiler.lookup.NestedTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding;
-import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
-import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
-import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
-import org.eclipse.jdt.internal.compiler.util.Util;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * This is the big kahuna where most of the nitty gritty of creating our AST
- * happens. BuildTypeMap must have already run so we have valid mappings between
- * JDT nodes and our already-created AST nodes.
- */
-public class GenerateJavaAST {
-
- /**
- * Visit the JDT AST and produce our own AST into the passed-in TypeMap's
- * JProgram. By the end of this pass, the produced AST should contain every
- * piece of information we'll ever need about the code. The JDT nodes should
- * never again be referenced after this.
- *
- * This is implemented as a reflective visitor for JDT's AST. The advantage of
- * doing it reflectively is that if we run into any JDT nodes we can't handle,
- * we'll automatically throw an exception. If we had subclassed
- * {@link org.eclipse.jdt.internal.compiler.ast.ASTNode} we'd have to override
- * every single method and explicitly throw an exception to get the same
- * behavior.
- *
- * NOTE ON JDT FORCED OPTIMIZATIONS - If JDT statically determines that a
- * section of code in unreachable, it won't fully resolve that section of
- * code. This invalid-state code causes us major problems. As a result, we
- * have to optimize out those dead blocks early and never try to translate
- * them to our AST.
- */
- // Reflective invocation causes unused warnings.
- @SuppressWarnings("unused")
- private static class JavaASTGenerationVisitor {
-
- /**
- * Used to cache {@link Method} lookups.
- */
- private static class MethodKey {
- private final Class<? extends Object> childClass;
- private final String name;
-
- public MethodKey(String name, Class<? extends Object> childClass) {
- this.name = name;
- this.childClass = childClass;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof MethodKey) {
- MethodKey otherKey = (MethodKey) obj;
- return name.equals(otherKey.name) && childClass.equals(otherKey.childClass);
- }
- return super.equals(obj);
- }
-
- @Override
- public int hashCode() {
- return name.hashCode() + (101 * childClass.hashCode());
- }
- }
-
- /**
- * Used to cache {@link Method} lookups.
- */
- private static class MethodValue {
- private final NoSuchMethodException ex;
- private final Method method;
-
- public MethodValue(Method method) {
- this.method = method;
- this.ex = null;
- }
-
- public MethodValue(NoSuchMethodException ex) {
- this.ex = ex;
- this.method = null;
- }
-
- public Method getMethod() throws NoSuchMethodException {
- if (this.ex != null) {
- throw (ex);
- }
- return method;
- }
- }
-
- /**
- * The literal for the JLS identifier that represents the length field on an
- * array.
- */
- private static final String ARRAY_LENGTH_FIELD = "length";
-
- private static InternalCompilerException translateException(JNode node, Throwable e) {
- if (e instanceof VirtualMachineError) {
- // Always rethrow VM errors (an attempt to wrap may fail).
- throw (VirtualMachineError) e;
- }
- InternalCompilerException ice;
- if (e instanceof InternalCompilerException) {
- ice = (InternalCompilerException) e;
- ice.addNode(node);
- } else {
- ice = new InternalCompilerException(node, "Error constructing Java AST", e);
- }
- return ice;
- }
-
- private final AutoboxUtils autoboxUtils;
-
- private JDeclaredType currentClass;
-
- private ClassScope currentClassScope;
-
- private String currentFileName;
-
- private JMethod currentMethod;
-
- private JMethodBody currentMethodBody;
-
- private MethodScope currentMethodScope;
-
- private Map<JField, JParameter> currentOuterThisRefParams;
-
- private int[] currentSeparatorPositions;
-
- private final boolean disableClassMetadata;
-
- private final boolean enableAsserts;
-
- private final Map<JsniMethodBody, AbstractMethodDeclaration> jsniMethodMap =
- new HashMap<JsniMethodBody, AbstractMethodDeclaration>();
-
- private final Map<JMethod, Map<String, JLabel>> labelMap =
- new IdentityHashMap<JMethod, Map<String, JLabel>>();
-
- private final Map<MethodKey, MethodValue> methodCache = new HashMap<MethodKey, MethodValue>();
-
- private final JProgram program;
-
- private final TypeMap typeMap;
-
- public JavaASTGenerationVisitor(TypeMap typeMap, JProgram program, JJSOptions options) {
- this.typeMap = typeMap;
- this.program = program;
- this.enableAsserts = options.isEnableAssertions();
-
- /*
- * TODO: Determine if this should be controlled by a compiler flag or a
- * module property.
- */
- this.disableClassMetadata = options.isClassMetadataDisabled();
- autoboxUtils = new AutoboxUtils(program);
- }
-
- /**
- * <p>
- * Add a bridge method to <code>clazzBinding</code> for any method it
- * inherits that implements an interface method but that has a different
- * erased signature from the interface method.
- * </p>
- *
- * <p>
- * The need for these bridges was pointed out in issue 3064. The goal is
- * that virtual method calls through an interface type are translated to
- * JavaScript that will function correctly. If the interface signature
- * matches the signature of the implementing method, then nothing special
- * needs to be done. If they are different, due to the use of generics, then
- * GenerateJavaScriptAST is careful to do the right thing. There is a
- * remaining case, though, that GenerateJavaScriptAST is not in a good
- * position to fix: a method could be inherited from a superclass, used to
- * implement an interface method that has a different type signature, and
- * does not have the interface method in its list of overrides. In that
- * case, a bridge method should be added that overrides the interface method
- * and then calls the implementation method.
- * </p>
- *
- * <p>
- * This method should only be called once all regular, non-bridge methods
- * have been installed on the GWT types.
- * </p>
- */
- public void addBridgeMethods(SourceTypeBinding clazzBinding) {
- if (clazzBinding.isInterface()) {
- // Only add bridges in classes, to simplify matters.
- return;
- }
-
- JClassType clazz = (JClassType) typeMap.get(clazzBinding);
-
- /*
- * The JDT adds bridge methods in all the places GWT needs them. Look
- * through the bridge methods the JDT added.
- */
- if (clazzBinding.syntheticMethods() != null) {
- for (SyntheticMethodBinding synthmeth : clazzBinding.syntheticMethods()) {
- if (synthmeth.purpose == SyntheticMethodBinding.BridgeMethod && !synthmeth.isStatic()) {
- JMethod implmeth = (JMethod) typeMap.get(synthmeth.targetMethod);
-
- createBridgeMethod(clazz, synthmeth, implmeth);
- }
- }
- }
- }
-
- public void processEnumType(JEnumType type) {
- // Generate the synthetic values() method.
- JField valuesField = null;
- for (JMethod method : type.getMethods()) {
- currentMethod = method;
- if ("values".equals(method.getName())) {
- if (method.getParams().size() != 0) {
- continue;
- }
- currentMethodBody = (JMethodBody) method.getBody();
- valuesField = writeEnumValuesMethod(type);
- }
- currentMethodBody = null;
- currentMethod = null;
- }
- // Generate the synthetic valueOf() method.
- if (isScript(program)) {
- for (JMethod method : type.getMethods()) {
- currentMethod = method;
- if ("valueOf".equals(method.getName())) {
- if (method.getParams().size() != 1) {
- continue;
- }
- if (method.getParams().get(0).getType() != program.getTypeJavaLangString()) {
- continue;
- }
- currentMethodBody = (JMethodBody) method.getBody();
- writeEnumValueOfMethod(type, valuesField);
- }
- currentMethodBody = null;
- currentMethod = null;
- }
- }
- }
-
- /**
- * We emulate static initializers and instance initializers as methods. As
- * in other cases, this gives us: simpler AST, easier to optimize, more like
- * output JavaScript.
- */
- public void processType(TypeDeclaration x) {
- currentClass = (JDeclaredType) typeMap.get(x.binding);
- processArtificialRescues(x.annotations);
- try {
- currentClassScope = x.scope;
- currentSeparatorPositions = x.compilationResult.lineSeparatorPositions;
- currentFileName = String.valueOf(x.compilationResult.fileName);
-
- /*
- * Make clinits chain to super class (JDT doesn't write code to do
- * this). Call super class $clinit; $clinit is always in position 0.
- */
- if (currentClass.getSuperClass() != null) {
- JMethod myClinit = currentClass.getMethods().get(0);
- JMethod superClinit = currentClass.getSuperClass().getMethods().get(0);
- JMethodCall superClinitCall =
- new JMethodCall(myClinit.getSourceInfo(), null, superClinit);
- JMethodBody body = (JMethodBody) myClinit.getBody();
- body.getBlock().addStmt(0, superClinitCall.makeStatement());
- }
-
- if (x.fields != null) {
- // Process fields
- for (int i = 0, n = x.fields.length; i < n; ++i) {
- FieldDeclaration fieldDeclaration = x.fields[i];
- if (fieldDeclaration.isStatic()) {
- // clinit
- currentMethod = currentClass.getMethods().get(0);
- currentMethodBody = (JMethodBody) currentMethod.getBody();
- currentMethodScope = x.staticInitializerScope;
- } else {
- // init
- currentMethod = currentClass.getMethods().get(1);
- currentMethodBody = (JMethodBody) currentMethod.getBody();
- currentMethodScope = x.initializerScope;
- }
-
- if (fieldDeclaration instanceof Initializer) {
- assert (currentClass instanceof JClassType);
- processInitializer((Initializer) fieldDeclaration);
- } else {
- processField(fieldDeclaration);
- }
- }
- }
-
- currentMethodScope = null;
- currentMethod = null;
-
- if (x.methods != null) {
- // Process methods
- for (int i = 0, n = x.methods.length; i < n; ++i) {
- if (x.methods[i].isConstructor()) {
- assert (currentClass instanceof JClassType);
- processConstructor((ConstructorDeclaration) x.methods[i]);
- } else if (x.methods[i].isClinit()) {
- // nothing to do
- } else {
- processMethod(x.methods[i]);
- }
- }
- }
-
- // Write the body of the getClass() override.
- if (currentClass instanceof JClassType && currentClass != program.getTypeJavaLangObject()) {
- JMethod method = currentClass.getMethods().get(2);
- assert ("getClass".equals(method.getName()));
-
- if (program.isJavaScriptObject(currentClass)
- && currentClass != program.getJavaScriptObject()) {
- // Just use JavaScriptObject's implementation for all subclasses.
- currentClass.getMethods().remove(2);
- } else {
- if (currentClass == program.getIndexedType("Array")) {
- /*
- * Don't implement, fall through to Object.getClass(). Array emulation code
- * in com.google.gwt.lang.Array invokes Array.getClass() and expects to get the
- * class literal for the actual runtime type of the array (e.g. Foo[].class) and
- * not Array.class.
- */
- currentClass.getMethods().remove(2);
- } else {
- tryFindUpRefs(method);
- SourceInfo info = method.getSourceInfo();
- implementMethod(method, new JClassLiteral(info.makeChild(), currentClass));
- }
- }
- }
-
- // Reimplement GWT.isClient(), GWT.isProdMode(), GWT.isScript().
- if (currentClass == program.getIndexedType("GWT")) {
- JMethod method = program.getIndexedMethod("GWT.isClient");
- implementMethod(method, program.getLiteralBoolean(true));
-
- method = program.getIndexedMethod("GWT.isProdMode");
- implementMethod(method, program.getLiteralBoolean(true));
-
- method = program.getIndexedMethod("GWT.isScript");
- implementMethod(method, program.getLiteralBoolean(isScript(program)));
- }
-
- // Implement various methods on Class
- if (currentClass == program.getTypeJavaLangClass()) {
- JMethod method = program.getIndexedMethod("Class.desiredAssertionStatus");
- implementMethod(method, program.getLiteralBoolean(enableAsserts));
-
- if (disableClassMetadata) {
- JMethod isMetadataEnabledMethod =
- program.getIndexedMethod("Class.isClassMetadataEnabled");
- implementMethod(isMetadataEnabledMethod, program.getLiteralBoolean(false));
- }
- }
-
- if (currentClass instanceof JEnumType) {
- processEnumType((JEnumType) currentClass);
- }
-
- currentClassScope = null;
- currentClass = null;
- currentSeparatorPositions = null;
- currentFileName = null;
- } catch (Throwable e) {
- throw translateException(currentClass, e);
- }
- }
-
- /**
- * This is the guts of the "reflective" part of this visitor. Try to find a
- * "process" method that exactly matches the run-time type of the argument.
- */
- protected JNode dispatch(String name, Object child) {
- if (child == null) {
- return null;
- }
-
- try {
- Method method = getCachedMethod(name, child.getClass());
- return (JNode) method.invoke(this, child);
- } catch (Throwable e) {
- if (e instanceof InvocationTargetException) {
- e = ((InvocationTargetException) e).getTargetException();
- }
- throw translateException(child, e);
- }
- }
-
- /**
- * Process an Expression type node reflectively; must return a JExpression.
- */
- protected JExpression dispProcessExpression(Expression x) {
- /*
- * Note that we always prefer a JDT-computed constant value to the actual
- * written expression. (Let's hope JDT is always right.) This means we
- * don't have to write processExpression methods for the numerous JDT
- * literal nodes because they ALWAYS have a constant value.
- */
- JExpression result = null;
- if (x != null && x.constant != null && x.constant != Constant.NotAConstant) {
- result = (JExpression) dispatch("processConstant", x.constant);
- }
-
- if (result == null) {
- // The expression was not a constant, so use the general logic.
- result = (JExpression) dispatch("processExpression", x);
- }
-
- // Check if we need to box the resulting expression.
- if (x != null) {
- if ((x.implicitConversion & TypeIds.BOXING) != 0) {
- result = autoboxUtils.box(result, implicitConversionTargetType(x));
- } else if ((x.implicitConversion & TypeIds.UNBOXING) != 0) {
- // This code can actually leave an unbox operation in
- // an lvalue position, for example ++(x.intValue()).
- // Such trees are cleaned up in FixAssignmentToUnbox.
- JType typeToUnbox = (JType) typeMap.get(x.resolvedType);
- if (!(typeToUnbox instanceof JClassType)) {
- throw new InternalCompilerException(result, "Attempt to unbox a non-class type: "
- + typeToUnbox.getName(), null);
- }
-
- result = unbox(result, (JClassType) typeToUnbox);
- }
- }
- return result;
- }
-
- /**
- * Process an Statement type node reflectively; must return a JStatement.
- */
- protected JStatement dispProcessStatement(Statement x) {
- JStatement stmt;
- if (x instanceof Expression) {
- JExpression expr = dispProcessExpression((Expression) x);
- if (expr == null) {
- return null;
- }
- stmt = expr.makeStatement();
- } else {
- stmt = (JStatement) dispatch("processStatement", x);
- }
- return stmt;
- }
-
- Map<JsniMethodBody, AbstractMethodDeclaration> getJsniMethodMap() {
- return jsniMethodMap;
- }
-
- JBooleanLiteral processConstant(BooleanConstant x) {
- return program.getLiteralBoolean(x.booleanValue());
- }
-
- JIntLiteral processConstant(ByteConstant x) {
- return program.getLiteralInt(x.byteValue());
- }
-
- JCharLiteral processConstant(CharConstant x) {
- return program.getLiteralChar(x.charValue());
- }
-
- JDoubleLiteral processConstant(DoubleConstant x) {
- return program.getLiteralDouble(x.doubleValue());
- }
-
- JFloatLiteral processConstant(FloatConstant x) {
- return program.getLiteralFloat(x.floatValue());
- }
-
- JIntLiteral processConstant(IntConstant x) {
- return program.getLiteralInt(x.intValue());
- }
-
- JLongLiteral processConstant(LongConstant x) {
- return program.getLiteralLong(x.longValue());
- }
-
- JIntLiteral processConstant(ShortConstant x) {
- return program.getLiteralInt(x.shortValue());
- }
-
- JStringLiteral processConstant(StringConstant x) {
- // May be processing an annotation
- SourceInfo info =
- currentMethod == null ? currentClass.getSourceInfo() : currentMethod.getSourceInfo();
- return program.getLiteralString(info.makeChild(), x.stringValue().toCharArray());
- }
-
- /**
- * This is slightly different from the normal Java language. Specifically,
- * we explicitly handle synthetic fields that are part of nested/local
- * classes. It boils down to the fact that we really HAVE to assign
- * synthetic arguments to synthetic fields BEFORE calling the superclass
- * constructor (because it might call you back polymorphically). In straight
- * Java that glue code is a semantic error, because a this/super call must
- * be the first statement of your constructor. On the upside, optimizations
- * work the same on our synthetic fields as with any user fields.
- *
- * The order of emulation is: - assign all synthetic fields from synthetic
- * args - call our super constructor emulation method - call our instance
- * initializer emulation method - run user code
- */
- void processConstructor(ConstructorDeclaration x) {
- JConstructor ctor = (JConstructor) typeMap.get(x.binding);
- try {
- SourceInfo info = ctor.getSourceInfo();
-
- currentMethod = ctor;
- currentMethodBody = ctor.getBody();
- currentMethodScope = x.scope;
-
- /*
- * Determine if we have an explicit this call. The presence of an
- * explicit this call indicates we can skip certain initialization steps
- * (as the callee will perform those steps for us). These skippable
- * steps are 1) assigning synthetic args to fields and 2) running
- * initializers.
- */
- boolean hasExplicitThis = (x.constructorCall != null) && !x.constructorCall.isSuperAccess();
-
- JClassType enclosingType = ctor.getEnclosingType();
- JBlock block = currentMethodBody.getBlock();
- currentOuterThisRefParams = Maps.create();
-
- /*
- * All synthetic fields must be assigned, unless we have an explicit
- * this constructor call, in which case the callee will assign them for
- * us.
- */
- ReferenceBinding declaringClass = x.binding.declaringClass;
- if (declaringClass instanceof NestedTypeBinding) {
- Iterator<JParameter> paramIt = currentMethod.getParams().iterator();
- NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClass;
- if (nestedBinding.enclosingInstances != null) {
- for (SyntheticArgumentBinding arg : nestedBinding.enclosingInstances) {
- JParameter param = paramIt.next();
- JField field = (JField) typeMap.get(arg);
- if (!hasExplicitThis) {
- block.addStmt(JProgram.createAssignmentStmt(info, createVariableRef(info, field),
- createVariableRef(info, param)));
- }
- currentOuterThisRefParams = Maps.put(currentOuterThisRefParams, field, param);
- }
- }
-
- if (!hasExplicitThis) {
- paramIt = getSyntheticLocalsIterator();
- if (nestedBinding.outerLocalVariables != null) {
- for (SyntheticArgumentBinding arg : nestedBinding.outerLocalVariables) {
- JParameter param = paramIt.next();
- JField field = (JField) typeMap.get(arg);
- block.addStmt(JProgram.createAssignmentStmt(info, createVariableRef(info, field),
- createVariableRef(info, param)));
- }
- }
- }
- }
-
- // optional this or super constructor call
- if (x.constructorCall != null) {
- JMethodCall superOrThisCall =
- (JMethodCall) dispatch("processExpression", x.constructorCall);
- // Enums: wire up synthetic name/ordinal params to the super method.
- if (enclosingType.isEnumOrSubclass() != null) {
- JVariableRef enumNameRef =
- createVariableRef(superOrThisCall.getSourceInfo(), ctor.getParams().get(0));
- superOrThisCall.addArg(0, enumNameRef);
- JVariableRef enumOrdinalRef =
- createVariableRef(superOrThisCall.getSourceInfo(), ctor.getParams().get(1));
- superOrThisCall.addArg(1, enumOrdinalRef);
- }
-
- superOrThisCall.setStaticDispatchOnly();
- block.addStmt(superOrThisCall.makeStatement());
- }
-
- JExpression thisRef = createThisRef(info, enclosingType);
-
- /*
- * Call the synthetic instance initializer method, unless we have an
- * explicit this constructor call, in which case the callee will.
- */
- if (!hasExplicitThis) {
- // $init is always in position 1 (clinit is in 0)
- JMethod initMethod = enclosingType.getMethods().get(1);
- JMethodCall initCall = new JMethodCall(info, thisRef, initMethod);
- block.addStmt(initCall.makeStatement());
- }
-
- // user code (finally!)
- block.addStmts(processStatements(x.statements));
-
- currentOuterThisRefParams = null;
- currentMethodScope = null;
- currentMethod = null;
- } catch (Throwable e) {
- throw translateException(ctor, e);
- }
- }
-
- JExpression processExpression(AllocationExpression x) {
- SourceInfo info = makeSourceInfo(x);
- TypeBinding typeBinding = erasure(x.resolvedType);
- if (typeBinding.constantPoolName() == null) {
- /*
- * Weird case: if JDT determines that this local class is totally
- * uninstantiable, it won't bother allocating a local name.
- */
- return program.getLiteralNull();
- }
- JClassType newType = (JClassType) typeMap.get(typeBinding);
- MethodBinding b = x.binding;
- JConstructor ctor = (JConstructor) typeMap.get(b);
- JMethodCall call;
- JClassType javaLangString = program.getTypeJavaLangString();
- if (newType == javaLangString && !newType.isExternal()) {
- /*
- * MAGIC: java.lang.String is implemented as a JavaScript String
- * primitive with a modified prototype. This requires funky handling of
- * constructor calls. We find a method named _String() whose signature
- * matches the requested constructor
- */
- int ctorArgc = ctor.getParams().size();
- JMethod targetMethod = null;
- outer : for (JMethod method : javaLangString.getMethods()) {
- if (method.getName().equals("_String") && method.getParams().size() == ctorArgc) {
- for (int i = 0; i < ctorArgc; ++i) {
- JParameter mparam = method.getParams().get(i);
- JParameter cparam = ctor.getParams().get(i);
- if (mparam.getType() != cparam.getType()) {
- continue outer;
- }
- }
- targetMethod = method;
- break;
- }
- }
- if (targetMethod == null) {
- throw new InternalCompilerException(
- "String constructor error; no matching implementation.");
- }
- call = new JMethodCall(makeSourceInfo(x), null, targetMethod);
- } else {
- call = new JNewInstance(info, ctor, currentClass);
- }
-
- // Enums: hidden arguments for the name and id.
- if (x.enumConstant != null) {
- call.addArgs(program.getLiteralString(info, x.enumConstant.name), program
- .getLiteralInt(x.enumConstant.binding.original().id));
- }
-
- // Synthetic args for inner classes
- ReferenceBinding targetBinding = b.declaringClass;
- if (targetBinding.isNestedType() && !targetBinding.isStatic()) {
- NestedTypeBinding nestedBinding = (NestedTypeBinding) erasure(targetBinding);
- // Synthetic this args for inner classes
- if (nestedBinding.enclosingInstances != null) {
- for (SyntheticArgumentBinding arg : nestedBinding.enclosingInstances) {
- JClassType syntheticThisType = (JClassType) typeMap.get(arg.type);
- call.addArg(createThisRef(info, syntheticThisType));
- }
- }
- }
-
- // Plain old regular user arguments
- addCallArgs(x.arguments, call, b);
-
- // Synthetic args for inner classes
- if (targetBinding.isNestedType() && !targetBinding.isStatic()) {
- NestedTypeBinding nestedBinding = (NestedTypeBinding) erasure(targetBinding);
- // Synthetic locals for local classes
- if (nestedBinding.outerLocalVariables != null) {
- for (SyntheticArgumentBinding arg : nestedBinding.outerLocalVariables) {
- JVariable variable = (JVariable) typeMap.get(arg.actualOuterLocalVariable);
- call.addArg(createVariableRef(info, variable, arg.actualOuterLocalVariable));
- }
- }
- }
-
- return call;
- }
-
- JExpression processExpression(AND_AND_Expression x) {
- JType type = (JType) typeMap.get(x.resolvedType);
- SourceInfo info = makeSourceInfo(x);
- return processBinaryOperation(info, JBinaryOperator.AND, type, x.left, x.right);
- }
-
- JExpression processExpression(ArrayAllocationExpression x) {
- SourceInfo info = makeSourceInfo(x);
- JArrayType type = (JArrayType) typeMap.get(x.resolvedType);
-
- if (x.initializer != null) {
- List<JExpression> initializers = new ArrayList<JExpression>();
- if (x.initializer.expressions != null) {
- for (Expression expression : x.initializer.expressions) {
- initializers.add(dispProcessExpression(expression));
- }
- }
- return JNewArray.createInitializers(info, type, initializers);
- } else {
- List<JExpression> dims = new ArrayList<JExpression>();
- for (Expression dimension : x.dimensions) {
- // can be null if index expression was empty
- if (dimension == null) {
- dims.add(program.getLiteralAbsentArrayDimension());
- } else {
- dims.add(dispProcessExpression(dimension));
- }
- }
- return JNewArray.createDims(info, type, dims);
- }
- }
-
- JExpression processExpression(ArrayInitializer x) {
- SourceInfo info = makeSourceInfo(x);
- JArrayType type = (JArrayType) typeMap.get(x.resolvedType);
-
- List<JExpression> initializers = new ArrayList<JExpression>();
- if (x.expressions != null) {
- for (Expression expression : x.expressions) {
- initializers.add(dispProcessExpression(expression));
- }
- }
- return JNewArray.createInitializers(info, type, initializers);
- }
-
- JExpression processExpression(ArrayReference x) {
- SourceInfo info = makeSourceInfo(x);
- JArrayRef arrayRef =
- new JArrayRef(info, dispProcessExpression(x.receiver), dispProcessExpression(x.position));
- return arrayRef;
- }
-
- JExpression processExpression(Assignment x) {
- JType type = (JType) typeMap.get(x.resolvedType);
- SourceInfo info = makeSourceInfo(x);
- return processBinaryOperation(info, JBinaryOperator.ASG, type, x.lhs, x.expression);
- }
-
- JExpression processExpression(BinaryExpression x) {
- JBinaryOperator op;
-
- int binOp = (x.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT;
- switch (binOp) {
- case OperatorIds.LEFT_SHIFT:
- op = JBinaryOperator.SHL;
- break;
- case OperatorIds.RIGHT_SHIFT:
- op = JBinaryOperator.SHR;
- break;
- case OperatorIds.UNSIGNED_RIGHT_SHIFT:
- op = JBinaryOperator.SHRU;
- break;
- case OperatorIds.PLUS:
- if (program.isJavaLangString((JType) typeMap.get(x.resolvedType))) {
- op = JBinaryOperator.CONCAT;
- } else {
- op = JBinaryOperator.ADD;
- }
- break;
- case OperatorIds.MINUS:
- op = JBinaryOperator.SUB;
- break;
- case OperatorIds.REMAINDER:
- op = JBinaryOperator.MOD;
- break;
- case OperatorIds.XOR:
- op = JBinaryOperator.BIT_XOR;
- break;
- case OperatorIds.AND:
- op = JBinaryOperator.BIT_AND;
- break;
- case OperatorIds.MULTIPLY:
- op = JBinaryOperator.MUL;
- break;
- case OperatorIds.OR:
- op = JBinaryOperator.BIT_OR;
- break;
- case OperatorIds.DIVIDE:
- op = JBinaryOperator.DIV;
- break;
- case OperatorIds.LESS_EQUAL:
- op = JBinaryOperator.LTE;
- break;
- case OperatorIds.GREATER_EQUAL:
- op = JBinaryOperator.GTE;
- break;
- case OperatorIds.GREATER:
- op = JBinaryOperator.GT;
- break;
- case OperatorIds.LESS:
- op = JBinaryOperator.LT;
- break;
- default:
- throw new InternalCompilerException("Unexpected operator for BinaryExpression");
- }
-
- JType type = (JType) typeMap.get(x.resolvedType);
- SourceInfo info = makeSourceInfo(x);
- return processBinaryOperation(info, op, type, x.left, x.right);
- }
-
- JExpression processExpression(CastExpression x) {
- SourceInfo info = makeSourceInfo(x);
- JType type = (JType) typeMap.get(x.resolvedType);
- JCastOperation cast = new JCastOperation(info, type, dispProcessExpression(x.expression));
- return cast;
- }
-
- JExpression processExpression(ClassLiteralAccess x) {
- SourceInfo info = makeSourceInfo(x);
- JType type = (JType) typeMap.get(x.targetType);
- return new JClassLiteral(info, type);
- }
-
- JExpression processExpression(CombinedBinaryExpression x) {
- return processExpression((BinaryExpression) x);
- }
-
- JExpression processExpression(CompoundAssignment x) {
- JBinaryOperator op;
-
- switch (x.operator) {
- case OperatorIds.PLUS:
- if (program.isJavaLangString((JType) typeMap.get(x.resolvedType))) {
- op = JBinaryOperator.ASG_CONCAT;
- } else {
- op = JBinaryOperator.ASG_ADD;
- }
- break;
- case OperatorIds.MINUS:
- op = JBinaryOperator.ASG_SUB;
- break;
- case OperatorIds.MULTIPLY:
- op = JBinaryOperator.ASG_MUL;
- break;
- case OperatorIds.DIVIDE:
- op = JBinaryOperator.ASG_DIV;
- break;
- case OperatorIds.AND:
- op = JBinaryOperator.ASG_BIT_AND;
- break;
- case OperatorIds.OR:
- op = JBinaryOperator.ASG_BIT_OR;
- break;
- case OperatorIds.XOR:
- op = JBinaryOperator.ASG_BIT_XOR;
- break;
- case OperatorIds.REMAINDER:
- op = JBinaryOperator.ASG_MOD;
- break;
- case OperatorIds.LEFT_SHIFT:
- op = JBinaryOperator.ASG_SHL;
- break;
- case OperatorIds.RIGHT_SHIFT:
- op = JBinaryOperator.ASG_SHR;
- break;
- case CompoundAssignment.UNSIGNED_RIGHT_SHIFT:
- op = JBinaryOperator.ASG_SHRU;
- break;
- default:
- throw new InternalCompilerException("Unexpected operator for CompoundAssignment");
- }
-
- JType type = (JType) typeMap.get(x.resolvedType);
- SourceInfo info = makeSourceInfo(x);
- return processBinaryOperation(info, op, type, x.lhs, x.expression);
- }
-
- JExpression processExpression(ConditionalExpression x) {
- SourceInfo info = makeSourceInfo(x);
- JType type = (JType) typeMap.get(x.resolvedType);
- JExpression ifTest = dispProcessExpression(x.condition);
- JExpression thenExpr = dispProcessExpression(x.valueIfTrue);
- JExpression elseExpr = dispProcessExpression(x.valueIfFalse);
- JConditional conditional = new JConditional(info, type, ifTest, thenExpr, elseExpr);
- return conditional;
- }
-
- JExpression processExpression(EqualExpression x) {
- JBinaryOperator op;
- switch ((x.bits & BinaryExpression.OperatorMASK) >> BinaryExpression.OperatorSHIFT) {
- case BinaryExpression.EQUAL_EQUAL:
- op = JBinaryOperator.EQ;
- break;
- case BinaryExpression.NOT_EQUAL:
- op = JBinaryOperator.NEQ;
- break;
- default:
- throw new InternalCompilerException("Unexpected operator for EqualExpression");
- }
-
- JType type = (JType) typeMap.get(x.resolvedType);
- SourceInfo info = makeSourceInfo(x);
- return processBinaryOperation(info, op, type, x.left, x.right);
- }
-
- /**
- * How we have to treat super calls vs. this calls is so different, they may
- * as well have been two different JDT nodes.
- */
- JMethodCall processExpression(ExplicitConstructorCall x) {
- if (x.isSuperAccess()) {
- return processSuperConstructorCall(x);
- } else {
- return processThisConstructorCall(x);
- }
- }
-
- JExpression processExpression(FieldReference x) {
- FieldBinding fieldBinding = x.binding;
- SourceInfo info = makeSourceInfo(x);
- JExpression instance = dispProcessExpression(x.receiver);
- JExpression expr;
- if (fieldBinding.declaringClass == null) {
- if (!ARRAY_LENGTH_FIELD.equals(String.valueOf(fieldBinding.name))) {
- throw new InternalCompilerException("Expected [array].length.");
- }
- expr = new JArrayLength(info, instance);
- } else {
- JField field = (JField) typeMap.get(fieldBinding);
- expr = new JFieldRef(info, instance, field, currentClass);
- }
-
- if (x.genericCast != null) {
- JType castType = (JType) typeMap.get(x.genericCast);
- /*
- * Note, this may result in an invalid AST due to an LHS cast operation.
- * We fix this up in FixAssignmentToUnbox.
- */
- return maybeCast(castType, expr);
- }
- return expr;
- }
-
- JExpression processExpression(InstanceOfExpression x) {
- SourceInfo info = makeSourceInfo(x);
- JExpression expr = dispProcessExpression(x.expression);
- JReferenceType testType = (JReferenceType) typeMap.get(x.type.resolvedType);
- return new JInstanceOf(info, testType, expr);
- }
-
- JExpression processExpression(MessageSend x) {
- SourceInfo info = makeSourceInfo(x);
- JMethod method = (JMethod) typeMap.get(x.binding);
-
- JExpression qualifier;
- if (x.receiver instanceof ThisReference) {
- if (method.isStatic()) {
- // don't bother qualifying it, it's a no-op
- qualifier = null;
- } else if (x.receiver instanceof QualifiedThisReference) {
- // use the supplied qualifier
- qualifier = dispProcessExpression(x.receiver);
- } else {
- /*
- * In cases where JDT had to synthesize a this ref for us, it could
- * actually be the wrong type, if the target method is in an enclosing
- * class. We have to synthesize our own ref of the correct type.
- */
- qualifier = createThisRef(info, method.getEnclosingType());
- }
- } else {
- qualifier = dispProcessExpression(x.receiver);
- }
-
- JMethodCall call = new JMethodCall(info, qualifier, method);
-
- // On a super ref, don't allow polymorphic dispatch. Oddly enough,
- // QualifiedSuperReference not derived from SuperReference!
- boolean isSuperRef =
- x.receiver instanceof SuperReference || x.receiver instanceof QualifiedSuperReference;
- if (isSuperRef) {
- call.setStaticDispatchOnly();
- }
-
- // The arguments come first...
- addCallArgs(x.arguments, call, x.binding);
-
- if (x.valueCast != null) {
- JType castType = (JType) typeMap.get(x.valueCast);
- return maybeCast(castType, call);
- }
- return call;
- }
-
- JExpression processExpression(NullLiteral x) {
- return program.getLiteralNull();
- }
-
- JExpression processExpression(OR_OR_Expression x) {
- JType type = (JType) typeMap.get(x.resolvedType);
- SourceInfo info = makeSourceInfo(x);
- return processBinaryOperation(info, JBinaryOperator.OR, type, x.left, x.right);
- }
-
- JExpression processExpression(PostfixExpression x) {
- SourceInfo info = makeSourceInfo(x);
- JUnaryOperator op;
-
- switch (x.operator) {
- case PostfixExpression.MINUS:
- op = JUnaryOperator.DEC;
- break;
-
- case PostfixExpression.PLUS:
- op = JUnaryOperator.INC;
- break;
-
- default:
- throw new InternalCompilerException("Unexpected postfix operator");
- }
-
- JPostfixOperation postOp = new JPostfixOperation(info, op, dispProcessExpression(x.lhs));
- return postOp;
- }
-
- JExpression processExpression(PrefixExpression x) {
- SourceInfo info = makeSourceInfo(x);
- JUnaryOperator op;
-
- switch (x.operator) {
- case PrefixExpression.MINUS:
- op = JUnaryOperator.DEC;
- break;
-
- case PrefixExpression.PLUS:
- op = JUnaryOperator.INC;
- break;
-
- default:
- throw new InternalCompilerException("Unexpected prefix operator");
- }
-
- JPrefixOperation preOp = new JPrefixOperation(info, op, dispProcessExpression(x.lhs));
- return preOp;
- }
-
- JExpression processExpression(QualifiedAllocationExpression x) {
- /*
- * Weird: sometimes JDT will create a QualifiedAllocationExpression with
- * no qualifier. I guess this is supposed to let us know that we need to
- * synthesize a synthetic this arg based on our own current "this"? But
- * plain old regular AllocationExpression also must be treated as if it
- * might be be implicitly qualified, so I'm not sure what the point is.
- * Let's just defer to the AllocationExpression logic if there's no
- * qualifier.
- */
- if (x.enclosingInstance() == null) {
- return processExpression((AllocationExpression) x);
- }
-
- SourceInfo info = makeSourceInfo(x);
- MethodBinding b = x.binding;
- JConstructor ctor = (JConstructor) typeMap.get(b);
- JNewInstance newInstance = new JNewInstance(info, ctor, currentClass);
- JExpression qualifier = dispProcessExpression(x.enclosingInstance);
- List<JExpression> qualList = new ArrayList<JExpression>();
- qualList.add(qualifier);
-
- /*
- * Really weird: Sometimes an allocation expression needs both its
- * explicit qualifier AND its implicit enclosing class! We add this second
- * because the explicit qualifier takes precedence.
- */
- if (!currentMethod.isStatic()) {
- JExpression implicitOuter = new JThisRef(info, (JClassType) currentClass);
- qualList.add(implicitOuter);
- }
-
- // Synthetic this args for inner classes
- ReferenceBinding targetBinding = b.declaringClass;
- if (targetBinding.isNestedType() && !targetBinding.isStatic()) {
- NestedTypeBinding nestedBinding = (NestedTypeBinding) erasure(targetBinding);
- if (nestedBinding.enclosingInstances != null) {
- for (SyntheticArgumentBinding arg : nestedBinding.enclosingInstances) {
- JClassType syntheticThisType = (JClassType) typeMap.get(arg.type);
- newInstance.addArg(createThisRef(syntheticThisType, qualList));
- }
- }
- }
-
- // Plain old regular arguments
- addCallArgs(x.arguments, newInstance, b);
-
- // Synthetic locals for local classes
- if (targetBinding.isNestedType() && !targetBinding.isStatic()) {
- NestedTypeBinding nestedBinding = (NestedTypeBinding) erasure(targetBinding);
- if (nestedBinding.outerLocalVariables != null) {
- for (SyntheticArgumentBinding arg : nestedBinding.outerLocalVariables) {
- JVariable variable = (JVariable) typeMap.get(arg.actualOuterLocalVariable);
- newInstance.addArg(createVariableRef(info, variable, arg.actualOuterLocalVariable));
- }
- }
- }
-
- return newInstance;
- }
-
- JExpression processExpression(QualifiedNameReference x) {
- SourceInfo info = makeSourceInfo(x);
- Binding binding = x.binding;
- JNode node = typeMap.get(binding);
- if (!(node instanceof JVariable)) {
- return null;
- }
- JVariable variable = (JVariable) node;
-
- JExpression curRef = createVariableRef(info, variable, binding);
- if (x.genericCast != null) {
- JType castType = (JType) typeMap.get(x.genericCast);
- curRef = maybeCast(castType, curRef);
- }
-
- /*
- * Wackiness: JDT represents multiple field access as an array of fields,
- * each qualified by everything to the left. So each subsequent item in
- * otherBindings takes the current expression as a qualifier.
- */
- if (x.otherBindings != null) {
- for (int i = 0; i < x.otherBindings.length; ++i) {
- FieldBinding fieldBinding = x.otherBindings[i];
- if (fieldBinding.declaringClass == null) {
- // probably array.length
- if (!ARRAY_LENGTH_FIELD.equals(String.valueOf(fieldBinding.name))) {
- throw new InternalCompilerException("Expected [array].length.");
- }
- curRef = new JArrayLength(info, curRef);
- } else {
- JField field = (JField) typeMap.get(fieldBinding);
- curRef = new JFieldRef(info, curRef, field, currentClass);
- }
- if (x.otherGenericCasts != null && x.otherGenericCasts[i] != null) {
- JType castType = (JType) typeMap.get(x.otherGenericCasts[i]);
- curRef = maybeCast(castType, curRef);
- }
- }
- }
-
- return curRef;
- }
-
- JExpression processExpression(QualifiedSuperReference x) {
- JClassType refType = (JClassType) typeMap.get(x.resolvedType);
- JClassType qualType = (JClassType) typeMap.get(x.qualification.resolvedType);
- assert (refType == qualType.getSuperClass());
- // Oddly enough, super refs can be modeled as this refs, because whatever
- // expression they qualify has already been resolved.
- return processQualifiedThisOrSuperRef(x, qualType);
- }
-
- JExpression processExpression(QualifiedThisReference x) {
- JClassType refType = (JClassType) typeMap.get(x.resolvedType);
- JClassType qualType = (JClassType) typeMap.get(x.qualification.resolvedType);
- assert (refType == qualType);
- return processQualifiedThisOrSuperRef(x, qualType);
- }
-
- JExpression processExpression(SingleNameReference x) {
- SourceInfo info = makeSourceInfo(x);
- Binding binding = x.binding;
- Object target = typeMap.get(binding);
- if (!(target instanceof JVariable)) {
- return null;
- }
- JVariable variable = (JVariable) target;
-
- /*
- * Wackiness: if a field happens to have synthetic accessors (only fields
- * can have them, apparently), this is a ref to a field in an enclosing
- * instance. CreateThisRef should compute a "this" access of the
- * appropriate type, unless the field is static.
- */
- JExpression result = null;
- if (x.syntheticAccessors != null) {
- JField field = (JField) variable;
- if (!field.isStatic()) {
- JExpression instance = createThisRef(info, field.getEnclosingType());
- result = new JFieldRef(info, instance, field, currentClass);
- }
- }
- if (result == null) {
- result = createVariableRef(info, variable, binding);
- }
- if (x.genericCast != null) {
- JType castType = (JType) typeMap.get(x.genericCast);
- result = maybeCast(castType, result);
- }
- return result;
- }
-
- JExpression processExpression(SuperReference x) {
- JClassType type = (JClassType) typeMap.get(x.resolvedType);
- assert (type == currentClass.getSuperClass());
- SourceInfo info = makeSourceInfo(x);
- // Oddly enough, super refs can be modeled as a this refs.
- JExpression superRef = createThisRef(info, currentClass);
- return superRef;
- }
-
- JExpression processExpression(ThisReference x) {
- JClassType type = (JClassType) typeMap.get(x.resolvedType);
- assert (type == currentClass);
- SourceInfo info = makeSourceInfo(x);
- JExpression thisRef = createThisRef(info, currentClass);
- return thisRef;
- }
-
- JExpression processExpression(UnaryExpression x) {
- SourceInfo info = makeSourceInfo(x);
- JUnaryOperator op;
- int operator = ((x.bits & UnaryExpression.OperatorMASK) >> UnaryExpression.OperatorSHIFT);
-
- switch (operator) {
- case UnaryExpression.MINUS:
- op = JUnaryOperator.NEG;
- break;
-
- case UnaryExpression.NOT:
- op = JUnaryOperator.NOT;
- break;
-
- case UnaryExpression.PLUS:
- // Odd case.. a useless + operator; just return the operand
- return dispProcessExpression(x.expression);
-
- case UnaryExpression.TWIDDLE:
- op = JUnaryOperator.BIT_NOT;
- break;
-
- default:
- throw new InternalCompilerException("Unexpected operator for unary expression");
- }
-
- JPrefixOperation preOp = new JPrefixOperation(info, op, dispProcessExpression(x.expression));
- return preOp;
- }
-
- List<JExpressionStatement> processExpressionStatements(Statement[] statements) {
- List<JExpressionStatement> jstatements = new ArrayList<JExpressionStatement>();
- if (statements != null) {
- for (int i = 0, n = statements.length; i < n; ++i) {
- JStatement jstmt = dispProcessStatement(statements[i]);
- if (jstmt != null) {
- jstatements.add((JExpressionStatement) jstmt);
- }
- }
- }
- return jstatements;
- }
-
- void processField(FieldDeclaration declaration) {
- JField field = (JField) typeMap.tryGet(declaration.binding);
- if (field == null) {
- /*
- * When anonymous classes declare constant fields, the field declaration
- * is not visited by JDT. Just bail since any references to that field
- * are guaranteed to be replaced with literals.
- */
- return;
- }
- try {
- JExpression initializer = null;
- if (declaration.initialization != null) {
- initializer = dispProcessExpression(declaration.initialization);
- }
-
- if (field instanceof JEnumField) {
- // An enum field must be initialized!
- assert (initializer instanceof JMethodCall);
- }
-
- if (initializer != null) {
- SourceInfo info = makeSourceInfo(declaration);
- // JDeclarationStatement's ctor sets up the field's initializer.
- JStatement decl =
- new JDeclarationStatement(info, createVariableRef(info, field), initializer);
- // will either be init or clinit
- currentMethodBody.getBlock().addStmt(decl);
- }
- } catch (Throwable e) {
- throw translateException(field, e);
- }
- }
-
- void processInitializer(Initializer initializer) {
- JBlock block = (JBlock) dispProcessStatement(initializer.block);
- try {
- // will either be init or clinit
- currentMethodBody.getBlock().addStmt(block);
- } catch (Throwable e) {
- throw translateException(initializer, e);
- }
- }
-
- void processMethod(AbstractMethodDeclaration x) {
- MethodBinding b = x.binding;
- JMethod method = (JMethod) typeMap.get(b);
- try {
- if (!b.isStatic() && (b.isImplementing() || b.isOverriding())) {
- tryFindUpRefs(method, b);
- }
-
- if (x.isNative()) {
- processNativeMethod(x, (JsniMethodBody) method.getBody());
- return;
- }
-
- currentMethod = method;
- currentMethodBody = (JMethodBody) method.getBody();
- currentMethodScope = x.scope;
-
- if (currentMethodBody != null) {
- currentMethodBody.getBlock().addStmts(processStatements(x.statements));
- }
- currentMethodScope = null;
- currentMethodBody = null;
- currentMethod = null;
- } catch (Throwable e) {
- throw translateException(method, e);
- }
- }
-
- void processNativeMethod(AbstractMethodDeclaration x, JsniMethodBody nativeMethodBody) {
- // Squirrel away a reference to the JDT node to enable error reporting.
- jsniMethodMap.put(nativeMethodBody, x);
- }
-
- JStatement processStatement(AssertStatement x) {
- SourceInfo info = makeSourceInfo(x);
- JExpression expr = dispProcessExpression(x.assertExpression);
- JExpression arg = dispProcessExpression(x.exceptionArgument);
- return new JAssertStatement(info, expr, arg);
- }
-
- JBlock processStatement(Block x) {
- if (x == null) {
- return null;
- }
-
- SourceInfo info = makeSourceInfo(x);
- JBlock block = new JBlock(info);
- block.addStmts(processStatements(x.statements));
- return block;
- }
-
- JStatement processStatement(BreakStatement x) {
- SourceInfo info = makeSourceInfo(x);
- return new JBreakStatement(info, getOrCreateLabel(info, currentMethod, x.label));
- }
-
- JStatement processStatement(CaseStatement x) {
- SourceInfo info = makeSourceInfo(x);
- JExpression expression = dispProcessExpression(x.constantExpression);
- if (expression != null && x.constantExpression.resolvedType.isEnum()) {
- // TODO: propagate enum information?
- assert (expression instanceof JFieldRef);
- JFieldRef fieldRef = (JFieldRef) expression;
- JEnumField field = (JEnumField) fieldRef.getField();
- return new JCaseStatement(info, program.getLiteralInt(field.ordinal()));
- } else {
- return new JCaseStatement(info, (JLiteral) expression);
- }
- }
-
- JStatement processStatement(ContinueStatement x) {
- SourceInfo info = makeSourceInfo(x);
- return new JContinueStatement(info, getOrCreateLabel(info, currentMethod, x.label));
- }
-
- JStatement processStatement(DoStatement x) {
- SourceInfo info = makeSourceInfo(x);
- JExpression loopTest = dispProcessExpression(x.condition);
- JStatement loopBody = dispProcessStatement(x.action);
- JDoStatement stmt = new JDoStatement(info, loopTest, loopBody);
- return stmt;
- }
-
- JStatement processStatement(EmptyStatement x) {
- return null;
- }
-
- JStatement processStatement(ForeachStatement x) {
- SourceInfo info = makeSourceInfo(x);
-
- JBlock body;
- JStatement action = dispProcessStatement(x.action);
- if (action instanceof JBlock) {
- body = (JBlock) action;
- } else {
- body = new JBlock(info);
- if (action != null) {
- body.addStmt(action);
- }
- }
-
- JLocal elementVar = (JLocal) typeMap.get(x.elementVariable.binding);
- String elementVarName = elementVar.getName();
-
- JDeclarationStatement elementDecl =
- (JDeclarationStatement) processStatement(x.elementVariable);
- assert (elementDecl.initializer == null);
-
- JForStatement result;
- if (x.collectionVariable != null) {
- /**
- * <pre>
- * for (final T[] i$array = collection,
- * int i$index = 0,
- * final int i$max = i$array.length;
- * i$index < i$max; ++i$index) {
- * T elementVar = i$array[i$index];
- * // user action
- * }
- * </pre>
- */
- JLocal arrayVar =
- JProgram.createLocal(info, elementVarName + "$array", ((JType) typeMap
- .get(x.collection.resolvedType)), true, currentMethodBody);
- JLocal indexVar =
- JProgram.createLocal(info, elementVarName + "$index", program.getTypePrimitiveInt(),
- false, currentMethodBody);
- JLocal maxVar =
- JProgram.createLocal(info, elementVarName + "$max", program.getTypePrimitiveInt(),
- true, currentMethodBody);
-
- List<JStatement> initializers = new ArrayList<JStatement>(3);
- // T[] i$array = arr
- initializers.add(createDeclaration(info, arrayVar, dispProcessExpression(x.collection)));
- // int i$index = 0
- initializers.add(createDeclaration(info, indexVar, program.getLiteralInt(0)));
- // int i$max = i$array.length
- initializers.add(createDeclaration(info, maxVar, new JArrayLength(info, new JLocalRef(info,
- arrayVar))));
-
- // i$index < i$max
- JExpression condition =
- new JBinaryOperation(info, program.getTypePrimitiveBoolean(), JBinaryOperator.LT,
- createVariableRef(info, indexVar), createVariableRef(info, maxVar));
-
- // ++i$index
- List<JExpressionStatement> increments = new ArrayList<JExpressionStatement>(1);
- increments.add(new JPrefixOperation(info, JUnaryOperator.INC, createVariableRef(info,
- indexVar)).makeStatement());
-
- // T elementVar = i$array[i$index];
- elementDecl.initializer =
- new JArrayRef(info, createVariableRef(info, arrayVar),
- createVariableRef(info, indexVar));
- body.addStmt(0, elementDecl);
-
- result = new JForStatement(info, initializers, condition, increments, body);
- } else {
- /**
- * <pre>
- * for (Iterator<T> i$iterator = collection.iterator(); i$iterator.hasNext();) {
- * T elementVar = i$iterator.next();
- * // user action
- * }
- * </pre>
- */
- JLocal iteratorVar =
- JProgram.createLocal(info, (elementVarName + "$iterator"), program
- .getIndexedType("Iterator"), false, currentMethodBody);
-
- List<JStatement> initializers = new ArrayList<JStatement>(1);
- // Iterator<T> i$iterator = collection.iterator()
- initializers.add(createDeclaration(info, iteratorVar, new JMethodCall(info,
- dispProcessExpression(x.collection), program.getIndexedMethod("Iterable.iterator"))));
-
- // i$iterator.hasNext()
- JExpression condition =
- new JMethodCall(info, createVariableRef(info, iteratorVar), program
- .getIndexedMethod("Iterator.hasNext"));
-
- // T elementVar = (T) i$iterator.next();
- elementDecl.initializer =
- new JMethodCall(info, createVariableRef(info, iteratorVar), program
- .getIndexedMethod("Iterator.next"));
-
- // Perform any implicit reference type casts (due to generics).
- // Note this occurs before potential unboxing.
- if (elementVar.getType() != program.getTypeJavaLangObject()) {
- TypeBinding collectionType;
- try {
- // TODO: This is slow! Cache lookup.
- Field privateField = ForeachStatement.class.getDeclaredField("collectionElementType");
- privateField.setAccessible(true);
- collectionType = (TypeBinding) privateField.get(x);
- } catch (Exception e) {
- throw new InternalCompilerException(elementDecl,
- "Failed to retreive collectionElementType through reflection", e);
- }
- JType toType = (JType) typeMap.get(collectionType);
- assert (toType instanceof JReferenceType);
- elementDecl.initializer = maybeCast(toType, elementDecl.initializer);
- }
-
- body.addStmt(0, elementDecl);
-
- result =
- new JForStatement(info, initializers, condition, Collections
- .<JExpressionStatement> emptyList(), body);
- }
-
- // May need to box or unbox the element assignment.
- if (x.elementVariableImplicitWidening != -1) {
- if ((x.elementVariableImplicitWidening & TypeIds.BOXING) != 0) {
- /*
- * Boxing is necessary. In this special case of autoboxing, the boxed
- * expression cannot be a constant, so the box type must be exactly
- * that associated with the expression.
- */
- elementDecl.initializer =
- autoboxUtils.box(elementDecl.initializer, ((JPrimitiveType) elementDecl.initializer
- .getType()));
- } else if ((x.elementVariableImplicitWidening & TypeIds.UNBOXING) != 0) {
- elementDecl.initializer =
- unbox(elementDecl.initializer, (JClassType) elementDecl.initializer.getType());
- }
- }
- return result;
- }
-
- JStatement processStatement(ForStatement x) {
- SourceInfo info = makeSourceInfo(x);
- // SEE NOTE ON JDT FORCED OPTIMIZATIONS
- // If the condition is false, don't process the body
- boolean removeBody = isOptimizedFalse(x.condition);
-
- List<JStatement> init = processStatements(x.initializations);
- JExpression expr = dispProcessExpression(x.condition);
- List<JExpressionStatement> incr = processExpressionStatements(x.increments);
- JStatement body = removeBody ? null : dispProcessStatement(x.action);
- return new JForStatement(info, init, expr, incr, body);
- }
-
- JStatement processStatement(IfStatement x) {
- // SEE NOTE ON JDT FORCED OPTIMIZATIONS
- // If the condition is false, don't process the then statement
- // If the condition is false, don't process the else statement
- boolean removeThen = isOptimizedFalse(x.condition);
- boolean removeElse = isOptimizedTrue(x.condition);
-
- SourceInfo info = makeSourceInfo(x);
- JExpression expr = dispProcessExpression(x.condition);
- JStatement thenStmt = removeThen ? null : dispProcessStatement(x.thenStatement);
- JStatement elseStmt = removeElse ? null : dispProcessStatement(x.elseStatement);
- JIfStatement ifStmt = new JIfStatement(info, expr, thenStmt, elseStmt);
- return ifStmt;
- }
-
- JStatement processStatement(LabeledStatement x) {
- JStatement body = dispProcessStatement(x.statement);
- if (body == null) {
- return null;
- }
- SourceInfo info = makeSourceInfo(x);
- return new JLabeledStatement(info, getOrCreateLabel(info, currentMethod, x.label), body);
- }
-
- JStatement processStatement(LocalDeclaration x) {
- SourceInfo info = makeSourceInfo(x);
- JLocal local = (JLocal) typeMap.get(x.binding);
- JLocalRef localRef = new JLocalRef(info, local);
- JExpression initializer = dispProcessExpression(x.initialization);
- return new JDeclarationStatement(info, localRef, initializer);
- }
-
- JStatement processStatement(ReturnStatement x) {
- SourceInfo info = makeSourceInfo(x);
- return new JReturnStatement(info, dispProcessExpression(x.expression));
- }
-
- JStatement processStatement(SwitchStatement x) {
- SourceInfo info = makeSourceInfo(x);
- JExpression expression = dispProcessExpression(x.expression);
- if (isEnumType(expression.getType())) {
- // Must be an enum; synthesize a call to ordinal().
- expression = new JMethodCall(info, expression, program.getIndexedMethod("Enum.ordinal"));
- }
- JBlock block = new JBlock(info);
- // Don't use processStatements here, because it stops at control breaks
- if (x.statements != null) {
- for (Statement stmt : x.statements) {
- JStatement jstmt = dispProcessStatement(stmt);
- if (jstmt != null) {
- block.addStmt(jstmt);
- }
- }
- }
- return new JSwitchStatement(info, expression, block);
- }
-
- JStatement processStatement(SynchronizedStatement x) {
- JBlock block = (JBlock) dispProcessStatement(x.block);
- JExpression expr = dispProcessExpression(x.expression);
- block.addStmt(0, expr.makeStatement());
- return block;
- }
-
- JStatement processStatement(ThrowStatement x) {
- SourceInfo info = makeSourceInfo(x);
- JExpression toThrow = dispProcessExpression(x.exception);
- return new JThrowStatement(info, toThrow);
- }
-
- JStatement processStatement(TryStatement x) {
- SourceInfo info = makeSourceInfo(x);
- JBlock tryBlock = (JBlock) dispProcessStatement(x.tryBlock);
- List<JLocalRef> catchArgs = new ArrayList<JLocalRef>();
- List<JBlock> catchBlocks = new ArrayList<JBlock>();
- if (x.catchBlocks != null) {
- for (int i = 0, c = x.catchArguments.length; i < c; ++i) {
- JLocal local = (JLocal) typeMap.get(x.catchArguments[i].binding);
- catchArgs.add((JLocalRef) createVariableRef(info, local));
- }
- for (int i = 0, c = x.catchBlocks.length; i < c; ++i) {
- catchBlocks.add((JBlock) dispProcessStatement(x.catchBlocks[i]));
- }
- }
- JBlock finallyBlock = (JBlock) dispProcessStatement(x.finallyBlock);
- return new JTryStatement(info, tryBlock, catchArgs, catchBlocks, finallyBlock);
- }
-
- JStatement processStatement(TypeDeclaration x) {
- // do nothing -- the local class is treated at the program level
- return null;
- }
-
- JStatement processStatement(WhileStatement x) {
- // SEE NOTE ON JDT FORCED OPTIMIZATIONS
- // If the condition is false, don't process the body
- boolean removeBody = isOptimizedFalse(x.condition);
-
- SourceInfo info = makeSourceInfo(x);
- JExpression loopTest = dispProcessExpression(x.condition);
- JStatement loopBody = removeBody ? null : dispProcessStatement(x.action);
- JWhileStatement stmt = new JWhileStatement(info, loopTest, loopBody);
- return stmt;
- }
-
- List<JStatement> processStatements(Statement[] statements) {
- List<JStatement> jstatements = new ArrayList<JStatement>();
- if (statements != null) {
- for (Statement stmt : statements) {
- JStatement jstmt = dispProcessStatement(stmt);
- if (jstmt != null) {
- jstatements.add(jstmt);
- if (jstmt.unconditionalControlBreak()) {
- /*
- * Stop processing statements, because the remaining ones are
- * unreachable. The JDT compiler might not have fully fleshed out
- * the unreachable statements.
- */
- break;
- }
- }
- }
- }
-
- return jstatements;
- }
-
- JMethodCall processSuperConstructorCall(ExplicitConstructorCall x) {
- SourceInfo info = makeSourceInfo(x);
- JMethod ctor = (JMethod) typeMap.get(x.binding);
- JExpression trueQualifier = createThisRef(info, currentClass);
- JMethodCall call = new JMethodCall(info, trueQualifier, ctor);
-
- // We have to find and pass through any synthetics our supertype needs
- ReferenceBinding superClass = x.binding.declaringClass;
- if (superClass.isNestedType() && !superClass.isStatic()) {
- ReferenceBinding myBinding = currentClassScope.referenceType().binding;
- ReferenceBinding superBinding = superClass;
-
- // enclosing types
- if (superBinding.syntheticEnclosingInstanceTypes() != null) {
- JExpression qualifier = dispProcessExpression(x.qualification);
- for (ReferenceBinding arg : superBinding.syntheticEnclosingInstanceTypes()) {
- JClassType classType = (JClassType) typeMap.get(arg);
- if (qualifier == null) {
- /*
- * Got to be one of my params; it would be illegal to use a this
- * ref at this moment-- we would most likely be passing in a
- * supertype field that HASN'T BEEN INITIALIZED YET.
- *
- * Unfortunately, my params might not work as-is, so we have to
- * check each one to see if any will make a suitable this ref.
- */
- List<JExpression> workList = new ArrayList<JExpression>();
- Iterator<JParameter> paramIt = currentMethod.getParams().iterator();
- for (ReferenceBinding b : myBinding.syntheticEnclosingInstanceTypes()) {
- workList.add(createVariableRef(info, paramIt.next()));
- }
- call.addArg(createThisRef(classType, workList));
- } else {
- call.addArg(createThisRef(classType, qualifier));
- }
- }
- }
- }
-
- addCallArgs(x.arguments, call, x.binding);
-
- // We have to find and pass through any synthetics our supertype needs
- if (superClass.isNestedType() && !superClass.isStatic()) {
- ReferenceBinding superBinding = superClass;
-
- // outer locals
- if (superBinding.syntheticOuterLocalVariables() != null) {
- for (SyntheticArgumentBinding arg : superBinding.syntheticOuterLocalVariables()) {
- // Got to be one of my params
- JType varType = (JType) typeMap.get(arg.type);
- String varName = String.valueOf(arg.name);
- JParameter param = null;
- for (JParameter paramIt : currentMethod.getParams()) {
- if (varType == paramIt.getType() && varName.equals(paramIt.getName())) {
- param = paramIt;
- }
- }
- if (param == null) {
- throw new InternalCompilerException(
- "Could not find matching local arg for explicit super ctor call.");
- }
- call.addArg(createVariableRef(info, param));
- }
- }
- }
-
- return call;
- }
-
- JMethodCall processThisConstructorCall(ExplicitConstructorCall x) {
- SourceInfo info = makeSourceInfo(x);
- JMethod ctor = (JMethod) typeMap.get(x.binding);
- JExpression trueQualifier = createThisRef(info, currentClass);
- JMethodCall call = new JMethodCall(info, trueQualifier, ctor);
-
- assert (x.qualification == null);
-
- // All synthetic this args must be passed through to the target ctor
- ReferenceBinding declaringClass = x.binding.declaringClass;
- if (declaringClass.isNestedType() && !declaringClass.isStatic()) {
- Iterator<JParameter> paramIt = currentMethod.getParams().iterator();
- NestedTypeBinding nestedBinding = (NestedTypeBinding) erasure(declaringClass);
- if (nestedBinding.enclosingInstances != null) {
- for (SyntheticArgumentBinding unused : nestedBinding.enclosingInstances) {
- call.addArg(createVariableRef(info, paramIt.next()));
- }
- }
- }
-
- addCallArgs(x.arguments, call, x.binding);
-
- // All synthetic locals must be passed through to the target ctor
- if (declaringClass.isNestedType() && !declaringClass.isStatic()) {
- Iterator<JParameter> paramIt = getSyntheticLocalsIterator();
- NestedTypeBinding nestedBinding = (NestedTypeBinding) erasure(declaringClass);
- if (nestedBinding.outerLocalVariables != null) {
- for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) {
- call.addArg(createVariableRef(info, paramIt.next()));
- }
- }
- }
-
- return call;
- }
-
- private void addAllOuterThisRefs(List<? super JVariableRef> list, JExpression expr,
- JClassType classType) {
- for (JField field : classType.getFields()) {
- // This fields are always first.
- if (!field.isThisRef()) {
- break;
- }
- // In a constructor, use the local param instead of the field.
- JParameter param = null;
- if (currentOuterThisRefParams != null && expr instanceof JThisRef) {
- param = currentOuterThisRefParams.get(field);
- }
- if (param != null) {
- list.add(new JParameterRef(expr.getSourceInfo(), param));
- } else {
- list.add(new JFieldRef(expr.getSourceInfo(), expr, field, currentClass));
- }
- }
- }
-
- private void addAllOuterThisRefsPlusSuperChain(List<? super JVariableRef> workList,
- JExpression expr, JClassType classType) {
- for (; classType != null; classType = classType.getSuperClass()) {
- addAllOuterThisRefs(workList, expr, classType);
- }
- }
-
- private void addCallArgs(Expression[] jdtArgs, JMethodCall call, MethodBinding binding) {
- JExpression[] args = new JExpression[jdtArgs == null ? 0 : jdtArgs.length];
- for (int i = 0; i < args.length; ++i) {
- args[i] = dispProcessExpression(jdtArgs[i]);
- }
- if (!binding.isVarargs()) {
- call.addArgs(args);
- return;
- }
-
- // Handle the odd var-arg case.
- TypeBinding[] params = binding.parameters;
- int varArg = params.length - 1;
-
- // Everything but the last arg.
- for (int i = 0; i < varArg; ++i) {
- call.addArg(args[i]);
- }
-
- // Handle the last arg.
-
- // See if there's a single varArg which is already an array.
- if (args.length == params.length) {
- if (jdtArgs[varArg].resolvedType.isCompatibleWith(params[varArg])) {
- // Already the correct array type.
- call.addArg(args[varArg]);
- return;
- }
- }
-
- // Need to synthesize an appropriately-typed array.
- List<JExpression> initializers = new ArrayList<JExpression>();
- for (int i = varArg; i < args.length; ++i) {
- initializers.add(args[i]);
- }
- JArrayType lastParamType = (JArrayType) typeMap.get(params[varArg]);
- JNewArray newArray =
- JNewArray.createInitializers(call.getSourceInfo(), lastParamType, initializers);
- call.addArg(newArray);
- }
-
- private void addThrownExceptions(MethodBinding methodBinding, JMethod method) {
- for (ReferenceBinding exceptionReference : methodBinding.thrownExceptions) {
- method.addThrownException((JClassType) typeMap.get(exceptionReference.erasure()));
- }
- }
-
- /**
- * Create a bridge method. It calls a same-named method with the same
- * arguments, but with a different type signature.
- *
- * @param clazz The class to put the bridge method in
- * @param jdtBridgeMethod The corresponding bridge method added in the JDT
- * @param implmeth The implementation method to bridge to
- */
- private void createBridgeMethod(JClassType clazz, SyntheticMethodBinding jdtBridgeMethod,
- JMethod implmeth) {
- SourceInfo info = implmeth.getSourceInfo().makeChild();
- // create the method itself
- JMethod bridgeMethod =
- program.createMethod(info, String.valueOf(jdtBridgeMethod.selector), clazz,
- (JType) typeMap.get(jdtBridgeMethod.returnType.erasure()), false, false, implmeth
- .isFinal(), implmeth.getAccess(), false);
- bridgeMethod.setSynthetic();
- int paramIdx = 0;
- List<JParameter> implParams = implmeth.getParams();
- for (TypeBinding jdtParamType : jdtBridgeMethod.parameters) {
- JParameter param = implParams.get(paramIdx++);
- JType paramType = (JType) typeMap.get(jdtParamType.erasure());
- JParameter newParam =
- new JParameter(info.makeChild(param.getSourceInfo().getOrigin()), param.getName(),
- paramType, true, false, bridgeMethod);
- bridgeMethod.addParam(newParam);
- }
- addThrownExceptions(jdtBridgeMethod, bridgeMethod);
- bridgeMethod.freezeParamTypes();
- info.addCorrelation(info.getCorrelator().by(bridgeMethod));
-
- // create a call
- JMethodCall call = new JMethodCall(info, new JThisRef(info, clazz), implmeth);
-
- for (int i = 0; i < bridgeMethod.getParams().size(); i++) {
- JParameter param = bridgeMethod.getParams().get(i);
- JParameterRef paramRef = new JParameterRef(info, param);
- call.addArg(maybeCast(implParams.get(i).getType(), paramRef));
- }
-
- // wrap it in a return if necessary
- JStatement callOrReturn;
- if (bridgeMethod.getType() == program.getTypeVoid()) {
- callOrReturn = call.makeStatement();
- } else {
- callOrReturn = new JReturnStatement(info, call);
- }
-
- // create a body that is just that call
- JMethodBody body = (JMethodBody) bridgeMethod.getBody();
- body.getBlock().addStmt(callOrReturn);
-
- // Add overrides.
- List<JMethod> overrides = new ArrayList<JMethod>();
- tryFindUpRefs(bridgeMethod, overrides);
- assert !overrides.isEmpty();
- for (JMethod over : overrides) {
- bridgeMethod.addOverride(over);
- /*
- * TODO(scottb): with a diamond-shape inheritance hierarchy, it may be
- * possible to get dups in this way. Really, method.overrides should
- * probably just be an IdentitySet to avoid having to check contains in
- * various places. Left as a todo because I don't think dups is super
- * harmful.
- */
- bridgeMethod.addOverrides(over.getOverrides());
- }
- }
-
- private JDeclarationStatement createDeclaration(SourceInfo info, JLocal local, JExpression value) {
- return new JDeclarationStatement(info, new JLocalRef(info, local), value);
- }
-
- /**
- * Helper to create a qualified "this" ref (really a synthetic this field
- * access) of the appropriate type. Always use this method instead of
- * creating a naked JThisRef or you won't get the synthetic accesses right.
- */
- private JExpression createQualifiedThisRef(SourceInfo info, JClassType targetType) {
- assert (currentClass instanceof JClassType);
- JExpression expr = new JThisRef(info, ((JClassType) currentClass));
- List<JExpression> list = new ArrayList<JExpression>();
- addAllOuterThisRefsPlusSuperChain(list, expr, (JClassType) currentClass);
- return createThisRef(targetType, list);
- }
-
- /**
- * Helper to create an expression of the target type, possibly by accessing
- * synthetic this fields on the passed-in expression. This is needed by a
- * QualifiedAllocationExpression, because the qualifier may not be the
- * correct type, and we may need use one of its fields.
- */
- private JExpression createThisRef(JReferenceType qualType, JExpression expr) {
- List<JExpression> list = new ArrayList<JExpression>();
- list.add(expr);
- return createThisRef(qualType, list);
- }
-
- /**
- * Helper to create an expression of the target type, possibly by accessing
- * synthetic this fields on ANY of several passed-in expressions. Why in the
- * world would we need to do this? It turns out that when making an
- * unqualified explicit super constructor call to something that needs a
- * synthetic outer this arg, the correct value to pass in can be one of
- * several of the calling constructor's own synthetic args. The catch is,
- * it's possible none of the args are exactly the right type-- we have to
- * make one of them the right type by following each of their synthetic this
- * refs up an arbitrarily big tree of enclosing classes and
- * supertypes-with-enclosing-classes until we find something that's the
- * right type.
- *
- * We have this implemented as a Breadth-First Search to minimize the number
- * of derefs required, and this seems to be correct. Note that we explicitly
- * prefer the current expression as one of its supertypes over a synthetic
- * this ref rooted off the current expression that happens to be the correct
- * type. We have observed this to be consistent with how Java handles it.
- *
- * TODO(scottb): could we get this info directly from JDT?
- */
- private JExpression createThisRef(JReferenceType qualType, List<JExpression> list) {
- LinkedList<JExpression> workList = new LinkedList<JExpression>();
- workList.addAll(list);
- while (!workList.isEmpty()) {
- JExpression expr = workList.removeFirst();
- JClassType classType = (JClassType) ((JReferenceType) expr.getType()).getUnderlyingType();
- for (; classType != null; classType = classType.getSuperClass()) {
- // prefer myself or myself-as-supertype over any of my this$ fields
- // that may have already been added to the work list
- if (program.typeOracle.canTriviallyCast(classType, qualType)) {
- return expr;
- }
- addAllOuterThisRefs(workList, expr, classType);
- }
- }
-
- throw new InternalCompilerException("Cannot create a ThisRef of the appropriate type.");
- }
-
- /**
- * Helper to creates this ref (or maybe a synthetic this field access) of
- * the appropriate type. Always use this method instead of creating a naked
- * JThisRef or you won't get the synthetic accesses right.
- */
- private JExpression createThisRef(SourceInfo info, JReferenceType targetType) {
- assert (currentClass instanceof JClassType);
- return createThisRef(targetType, new JThisRef(info, ((JClassType) currentClass)));
- }
-
- /**
- * Creates an appropriate JVariableRef for the polymorphic type of the
- * requested JVariable.
- */
- private JVariableRef createVariableRef(SourceInfo info, JVariable variable) {
- if (variable instanceof JLocal) {
- JLocal local = (JLocal) variable;
- if (local.getEnclosingMethod() != currentMethod) {
- throw new InternalCompilerException("LocalRef referencing local in a different method.");
- }
- return new JLocalRef(info, local);
- } else if (variable instanceof JParameter) {
- JParameter parameter = (JParameter) variable;
- if (parameter.getEnclosingMethod() != currentMethod) {
- throw new InternalCompilerException(
- "ParameterRef referencing param in a different method.");
- }
- return new JParameterRef(info, parameter);
- } else if (variable instanceof JField) {
- JField field = (JField) variable;
- JExpression instance = null;
- if (!field.isStatic()) {
- JClassType fieldEnclosingType = (JClassType) field.getEnclosingType();
- instance = createThisRef(info, fieldEnclosingType);
- if (!program.typeOracle.canTriviallyCast((JReferenceType) instance.getType(),
- fieldEnclosingType)) {
- throw new InternalCompilerException("FieldRef referencing field in a different type.");
- }
- }
- return new JFieldRef(info, instance, field, currentClass);
- }
- throw new InternalCompilerException("Unknown JVariable subclass.");
- }
-
- /**
- * Creates an appropriate JVariableRef for the polymorphic type of the
- * requested JVariable.
- */
- private JVariableRef createVariableRef(SourceInfo info, JVariable variable, Binding binding) {
- // Fix up the reference if it's to an outer local/param
- variable = possiblyReferenceOuterLocal(variable, binding);
- if (variable == null) {
- /*
- * Strange case: in certain circumstances, JDT will fail to provide an
- * emulation path to an outer local variable. In the case I know of, the
- * reference is a spurious qualifier to a static method call. Let's just
- * return null and ditch the expression.
- */
- return null;
- }
- return createVariableRef(info, variable);
- }
-
- private TypeBinding erasure(TypeBinding typeBinding) {
- if (typeBinding instanceof ParameterizedTypeBinding) {
- typeBinding = typeBinding.erasure();
- }
- return typeBinding;
- }
-
- private Method getCachedMethod(String name, Class<? extends Object> childClass)
- throws NoSuchMethodException {
- MethodKey key = new MethodKey(name, childClass);
- MethodValue value = methodCache.get(key);
- if (value == null) {
- try {
- Method method = getClass().getDeclaredMethod(name, childClass);
- value = new MethodValue(method);
- } catch (NoSuchMethodException ex) {
- value = new MethodValue(ex);
- }
- methodCache.put(key, value);
- }
- // Might throw an exception here.
- return value.getMethod();
- }
-
- private JInterfaceType getOrCreateExternalType(SourceInfo info, char[][] compoundName) {
- String name = BuildTypeMap.dotify(compoundName);
- JInterfaceType external = (JInterfaceType) program.getFromTypeMap(name);
- if (external == null) {
- external = program.createInterface(info, name);
- external.setExternal(true);
- }
- return external;
- }
-
- /**
- * Get a new label of a particular name, or create a new one if it doesn't
- * exist already.
- */
- private JLabel getOrCreateLabel(SourceInfo info, JMethod enclosingMethod, char[] name) {
- if (name == null) {
- return null;
- }
- String sname = String.valueOf(name);
- Map<String, JLabel> lblMap = this.labelMap.get(enclosingMethod);
- if (lblMap == null) {
- lblMap = new HashMap<String, JLabel>();
- this.labelMap.put(enclosingMethod, lblMap);
- }
- JLabel jlabel = lblMap.get(sname);
- if (jlabel == null) {
- jlabel = new JLabel(info, sname);
- lblMap.put(sname, jlabel);
- }
- return jlabel;
- }
-
- private JPrimitiveType getPrimitiveTypeForWrapperType(JClassType wrapperType) {
- String wrapperTypeName = wrapperType.getName();
- if ("java.lang.Integer".equals(wrapperTypeName)) {
- return program.getTypePrimitiveInt();
- } else if ("java.lang.Boolean".equals(wrapperTypeName)) {
- return program.getTypePrimitiveBoolean();
- } else if ("java.lang.Character".equals(wrapperTypeName)) {
- return program.getTypePrimitiveChar();
- } else if ("java.lang.Long".equals(wrapperTypeName)) {
- return program.getTypePrimitiveLong();
- } else if ("java.lang.Short".equals(wrapperTypeName)) {
- return program.getTypePrimitiveShort();
- } else if ("java.lang.Byte".equals(wrapperTypeName)) {
- return program.getTypePrimitiveByte();
- } else if ("java.lang.Double".equals(wrapperTypeName)) {
- return program.getTypePrimitiveDouble();
- } else if ("java.lang.Float".equals(wrapperTypeName)) {
- return program.getTypePrimitiveFloat();
- } else {
- return null;
- }
- }
-
- /**
- * Gets a JParameter iterator for a constructor method over its synthetic
- * local parameters.
- */
- private Iterator<JParameter> getSyntheticLocalsIterator() {
- return currentMethod.getParams().listIterator(currentMethod.getOriginalParamTypes().size());
- }
-
- private void implementMethod(JMethod method, JExpression returnValue) {
- assert method != null;
- JMethodBody body = (JMethodBody) method.getBody();
- JBlock block = body.getBlock();
-
- SourceInfo info;
- if (block.getStatements().size() > 0) {
- info = block.getStatements().get(0).getSourceInfo();
- } else {
- info = method.getSourceInfo();
- }
-
- block.clear();
- block.addStmt(new JReturnStatement(info, returnValue));
- }
-
- /*
- * Determine the destination type for an implicit conversion of the given
- * expression. Beware that when autoboxing, the type of the expression is
- * not necessarily the same as the type of the box to be created. The JDT
- * figures out what the necessary conversion is, depending on the context
- * the expression appears in, and stores it in
- * <code>x.implicitConversion</code>, so extract it from there.
- */
- private JPrimitiveType implicitConversionTargetType(Expression x)
- throws InternalCompilerException {
- /*
- * This algorithm for finding the target type is copied from
- * org.eclipse.jdt
- * .internal.compiler.codegen.CodeStream.generateReturnBytecode() .
- */
- switch ((x.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4) {
- case TypeIds.T_boolean:
- return program.getTypePrimitiveBoolean();
- case TypeIds.T_byte:
- return program.getTypePrimitiveByte();
- case TypeIds.T_char:
- return program.getTypePrimitiveChar();
- case TypeIds.T_double:
- return program.getTypePrimitiveDouble();
- case TypeIds.T_float:
- return program.getTypePrimitiveFloat();
- case TypeIds.T_int:
- return program.getTypePrimitiveInt();
- case TypeIds.T_long:
- return program.getTypePrimitiveLong();
- case TypeIds.T_short:
- return program.getTypePrimitiveShort();
- default:
- throw new InternalCompilerException("Could not determine the desired box type");
- }
- }
-
- /**
- * Check whether the specified type is definitely for an enum class.
- *
- * @param type The type being tested
- * @return whether it is certainly an enum
- */
- private boolean isEnumType(JType type) {
- if (type instanceof JClassType) {
- return ((JClassType) type).isEnumOrSubclass() != null;
- }
-
- if (type instanceof JNonNullType) {
- return isEnumType(((JNonNullType) type).getUnderlyingType());
- }
-
- return false;
- }
-
- private SourceInfo makeSourceInfo(Statement x) {
- int startLine =
- Util.getLineNumber(x.sourceStart, currentSeparatorPositions, 0,
- currentSeparatorPositions.length - 1);
- SourceOrigin toReturn =
- SourceOrigin.create(x.sourceStart, x.sourceEnd, startLine, currentFileName);
- if (currentMethod != null) {
- return currentMethod.getSourceInfo().makeChild(toReturn);
- }
- return toReturn;
- }
-
- private JExpression maybeCast(JType expected, JExpression expression) {
- if (expected != expression.getType()) {
- // Must be a generic; insert a cast operation.
- JReferenceType toType = (JReferenceType) expected;
- return new JCastOperation(expression.getSourceInfo(), toType, expression);
- } else {
- return expression;
- }
- }
-
- /**
- * Sometimes a variable reference can be to a local or parameter in an an
- * enclosing method. This is a tricky situation to detect. There's no
- * obvious way to tell, but the clue we can get from JDT is that the local's
- * containing method won't be the same as the method we're currently
- * processing.
- *
- * Once we have this clue, we can use getEmulationPath to compute the
- * current class's binding for that field.
- */
- private JVariable possiblyReferenceOuterLocal(JVariable variable, Binding binding) {
-
- if (variable instanceof JLocal || variable instanceof JParameter) {
- LocalVariableBinding localBinding = (LocalVariableBinding) binding;
- if (localBinding.declaringScope.methodScope() != currentMethodScope) {
- variable = null;
- VariableBinding[] vars = currentMethodScope.getEmulationPath(localBinding);
- if (vars == null) {
- return null;
- }
- assert (vars.length == 1);
- VariableBinding varBinding = vars[0];
-
- // See if there's an available parameter
- if (varBinding instanceof SyntheticArgumentBinding) {
- JType type = (JType) typeMap.get(varBinding.type);
- String name = String.valueOf(varBinding.name);
- for (int i = 0; i < currentMethod.getParams().size(); ++i) {
- JParameter param = currentMethod.getParams().get(i);
- if (type == param.getType() && name.equals(param.getName())) {
- variable = param;
- break;
- }
- }
- }
-
- // just use the field
- if (variable == null) {
- variable = (JField) typeMap.get(varBinding);
- }
-
- // now we have an updated variable that we can create our ref from
- }
- } else {
- assert variable instanceof JField;
- // In a constructor, prefer the ctor arg rather than the field.
- if (currentOuterThisRefParams != null) {
- JParameter ctorArg = currentOuterThisRefParams.get(variable);
- if (ctorArg != null) {
- variable = ctorArg;
- }
- }
- }
- return variable;
- }
-
- /**
- * Process a {@link ArtificialRescue.Rescue} element.
- */
- private void processArtificialRescue(RescueData rescue) {
- JReferenceType classType = (JReferenceType) program.getTypeFromJsniRef(rescue.getClassName());
- assert classType != null;
- if (rescue.isInstantiable()) {
- currentClass.addArtificialRescue(classType);
- }
-
- if (classType instanceof JDeclaredType) {
- List<String> toRescue = new ArrayList<String>();
- Collections.addAll(toRescue, rescue.getFields());
- Collections.addAll(toRescue, rescue.getMethods());
-
- for (String name : toRescue) {
- JsniRef ref = JsniRef.parse("@" + classType.getName() + "::" + name);
- final String[] errors = {null};
- JNode node =
- JsniRefLookup.findJsniRefTarget(ref, program, new JsniRefLookup.ErrorReporter() {
- public void reportError(String error) {
- errors[0] = error;
- }
- });
- if (errors[0] != null) {
- // Should have been caught by ArtificialRescueChecker
- throw new InternalCompilerException("Unable to artificially rescue " + name + ": "
- + errors[0]);
- }
-
- if (node instanceof JType) {
- // Already added the type above.
- } else {
- currentClass.addArtificialRescue(node);
- }
- if (node instanceof JField) {
- JField field = (JField) node;
- if (!field.isFinal()) {
- field.setVolatile();
- }
- }
- }
- }
- }
-
- private void processArtificialRescues(Annotation[] annotations) {
- if (annotations == null) {
- return;
- }
- RescueData[] rescues = RescueData.createFromAnnotations(annotations);
- for (RescueData rescue : rescues) {
- processArtificialRescue(rescue);
- }
- }
-
- /**
- * Helper for creating all JBinaryOperation. Several different JDT nodes can
- * result in binary operations: AND_AND_Expression, Assignment,
- * BinaryExpresion, CompoundAssignment, EqualExpression, and
- * OR_OR_Expression. Hopefully the specific operators that can result in
- * each different JDT type won't change between releases, because we only
- * look for the specific operators that we think should match each JDT node,
- * and throw an error if there's a mismatch.
- */
- private JExpression processBinaryOperation(SourceInfo info, JBinaryOperator op, JType type,
- Expression arg1, Expression arg2) {
- JExpression exprArg1 = dispProcessExpression(arg1);
- JExpression exprArg2 = dispProcessExpression(arg2);
- JBinaryOperation binaryOperation = new JBinaryOperation(info, type, op, exprArg1, exprArg2);
- return binaryOperation;
- }
-
- private JExpression processQualifiedThisOrSuperRef(QualifiedThisReference x, JClassType qualType) {
- /*
- * WEIRD: If a thisref or superref is qualified with the EXACT type of the
- * innermost type (in other words, a needless qualifier), it must refer to
- * that innermost type, because a class can never be nested inside of
- * itself. In this case, we must treat it as if it were not qualified.
- *
- * In all other cases, the qualified thisref or superref cannot possibly
- * refer to the innermost type (even if the innermost type could be cast
- * to a compatible type), so we must create a reference to some outer
- * type.
- */
- SourceInfo info = makeSourceInfo(x);
- if (qualType == currentClass) {
- return createThisRef(info, qualType);
- } else {
- return createQualifiedThisRef(info, qualType);
- }
- }
-
- private InternalCompilerException translateException(Object node, Throwable e) {
- if (e instanceof VirtualMachineError) {
- // Always rethrow VM errors (an attempt to wrap may fail).
- throw (VirtualMachineError) e;
- }
- InternalCompilerException ice;
- if (e instanceof InternalCompilerException) {
- ice = (InternalCompilerException) e;
- } else {
- ice = new InternalCompilerException("Error constructing Java AST", e);
- }
- String className = node.getClass().getName();
- String description = node.toString();
- SourceInfo sourceInfo = null;
- if (node instanceof Statement) {
- sourceInfo = makeSourceInfo((Statement) node);
- }
- ice.addNode(className, description, sourceInfo);
- return ice;
- }
-
- /**
- * For a given method, try to find all methods that it overrides/implements.
- * This version does not use JDT.
- */
- private void tryFindUpRefs(JMethod method) {
- List<JMethod> overrides = new ArrayList<JMethod>();
- tryFindUpRefs(method, overrides);
- method.addOverrides(overrides);
- }
-
- private void tryFindUpRefs(JMethod method, List<JMethod> overrides) {
- if (method.getEnclosingType() != null) {
- tryFindUpRefsRecursive(method, method.getEnclosingType(), overrides);
- }
- }
-
- /**
- * For a given method(and method binding), try to find all methods that it
- * overrides/implements.
- */
- private void tryFindUpRefs(JMethod method, MethodBinding binding) {
- // Should never get a parameterized instance here.
- assert binding == binding.original();
- tryFindUpRefsRecursive(method, binding, binding.declaringClass);
- }
-
- /**
- * For a given method(and method binding), recursively try to find all
- * methods that it overrides/implements.
- */
- private void tryFindUpRefsRecursive(JMethod method, JDeclaredType searchThisType,
- List<JMethod> overrides) {
-
- // See if this class has any uprefs, unless this class is myself
- if (method.getEnclosingType() != searchThisType) {
- for (JMethod upRef : searchThisType.getMethods()) {
- if (JTypeOracle.methodsDoMatch(method, upRef) && !overrides.contains(upRef)) {
- overrides.add(upRef);
- break;
- }
- }
- }
-
- // recurse super class
- if (searchThisType.getSuperClass() != null) {
- tryFindUpRefsRecursive(method, searchThisType.getSuperClass(), overrides);
- }
-
- // recurse super interfaces
- for (JInterfaceType intf : searchThisType.getImplements()) {
- tryFindUpRefsRecursive(method, intf, overrides);
- }
- }
-
- /**
- * For a given method(and method binding), recursively try to find all
- * methods that it overrides/implements.
- */
- private void tryFindUpRefsRecursive(JMethod method, MethodBinding binding,
- ReferenceBinding searchThisType) {
- /*
- * Always look for uprefs in the original, so we can correctly compare
- * erased signatures. The general design for uprefs is to model what the
- * JVM does in terms of matching up overrides based on binary match.
- */
- searchThisType = (ReferenceBinding) searchThisType.original();
-
- // See if this class has any uprefs, unless this class is myself
- if (binding.declaringClass != searchThisType) {
- for (MethodBinding tryMethod : searchThisType.getMethods(binding.selector)) {
- if (binding.returnType.erasure() == tryMethod.returnType.erasure()
- && binding.areParameterErasuresEqual(tryMethod)) {
- JMethod upRef = (JMethod) typeMap.get(tryMethod);
- if (!method.getOverrides().contains(upRef)) {
- method.addOverride(upRef);
- break;
- }
- }
- }
- }
-
- // recurse super class
- if (searchThisType.superclass() != null) {
- tryFindUpRefsRecursive(method, binding, searchThisType.superclass());
- }
-
- // recurse super interfaces
- if (searchThisType.superInterfaces() != null) {
- for (int i = 0; i < searchThisType.superInterfaces().length; i++) {
- ReferenceBinding intf = searchThisType.superInterfaces()[i];
- tryFindUpRefsRecursive(method, binding, intf);
- }
- }
- }
-
- private JExpression unbox(JExpression toUnbox, JClassType wrapperType) {
- JPrimitiveType primitiveType = getPrimitiveTypeForWrapperType(wrapperType);
- if (primitiveType == null) {
- throw new InternalCompilerException(toUnbox, "Attempt to unbox unexpected type '"
- + wrapperType.getName() + "'", null);
- }
-
- String valueMethodName = primitiveType.getName() + "Value";
- JMethod valueMethod = null;
- for (Object element : wrapperType.getMethods()) {
- JMethod method = (JMethod) element;
- if (method.getName().equals(valueMethodName)) {
- if (method.getParams().isEmpty()) {
- // It's a match!
- valueMethod = method;
- break;
- }
- }
- }
-
- if (valueMethod == null) {
- throw new InternalCompilerException(toUnbox, "Expected to find a method on '"
- + wrapperType.getName() + "' whose signature matches 'public "
- + primitiveType.getName() + " " + valueMethodName + "()'", null);
- }
-
- JMethodCall unboxCall = new JMethodCall(toUnbox.getSourceInfo(), toUnbox, valueMethod);
- return unboxCall;
- }
-
- private void writeEnumValueOfMethod(JEnumType type, JField valuesField) {
- JField mapField;
- {
- /*
- * Make an inner class to hold a lazy-init name-value map. We use a
- * class to take advantage of its clinit.
- *
- * class Map { $MAP = Enum.createValueOfMap($VALUES); }
- */
- SourceInfo typeInfo = type.getSourceInfo().makeChild();
- JClassType mapClass = program.createClass(typeInfo, type.getName() + "$Map", false, true);
- typeInfo.addCorrelation(typeInfo.getCorrelator().by(mapClass));
- mapClass.setSuperClass(program.getTypeJavaLangObject());
- SourceInfo fieldInfo = typeInfo.makeChild();
- mapField =
- program.createField(fieldInfo, "$MAP", mapClass, program.getJavaScriptObject(), true,
- Disposition.FINAL);
- fieldInfo.addCorrelation(fieldInfo.getCorrelator().by(mapField));
-
- SourceInfo methodInfo = typeInfo.makeChild();
- JMethodCall call =
- new JMethodCall(methodInfo, null, program.getIndexedMethod("Enum.createValueOfMap"));
- call.addArg(new JFieldRef(methodInfo, null, valuesField, type));
- JFieldRef mapRef = new JFieldRef(methodInfo, null, mapField, type);
- JDeclarationStatement declStmt = new JDeclarationStatement(methodInfo, mapRef, call);
- JMethod clinit =
- program.createMethod(methodInfo, "$clinit", mapClass, program.getTypeVoid(), false,
- true, true, AccessModifier.PRIVATE, false);
- clinit.freezeParamTypes();
- methodInfo.addCorrelation(methodInfo.getCorrelator().by(clinit));
- JBlock clinitBlock = ((JMethodBody) clinit.getBody()).getBlock();
- clinitBlock.addStmt(declStmt);
- mapField.setInitializer(declStmt);
- }
-
- /*
- * return Enum.valueOf(Enum$Map.Map.$MAP, name);
- */
- {
- SourceInfo sourceInfo = currentMethodBody.getSourceInfo();
- JFieldRef mapRef = new JFieldRef(sourceInfo, null, mapField, type);
- JVariableRef nameRef = createVariableRef(sourceInfo, currentMethod.getParams().get(0));
- JMethod delegateTo = program.getIndexedMethod("Enum.valueOf");
- JMethodCall call = new JMethodCall(sourceInfo, null, delegateTo);
- call.addArgs(mapRef, nameRef);
-
- currentMethodBody.getBlock().addStmt(new JReturnStatement(sourceInfo, call));
- }
- }
-
- private JField writeEnumValuesMethod(JEnumType type) {
- JField valuesField;
- {
- // $VALUES = new E[]{A,B,B};
- SourceInfo fieldInfo = type.getSourceInfo().makeChild();
- JArrayType enumArrayType = program.getTypeArray(type);
- valuesField =
- program.createField(fieldInfo, "$VALUES", type, enumArrayType, true, Disposition.FINAL);
- fieldInfo.addCorrelation(fieldInfo.getCorrelator().by(valuesField));
- List<JExpression> initializers = new ArrayList<JExpression>();
- for (JEnumField field : type.getEnumList()) {
- JFieldRef fieldRef = new JFieldRef(fieldInfo, null, field, type);
- initializers.add(fieldRef);
- }
- JNewArray newExpr = JNewArray.createInitializers(fieldInfo, enumArrayType, initializers);
- JFieldRef valuesRef = new JFieldRef(fieldInfo, null, valuesField, type);
- JDeclarationStatement declStmt = new JDeclarationStatement(fieldInfo, valuesRef, newExpr);
- JBlock clinitBlock = ((JMethodBody) type.getMethods().get(0).getBody()).getBlock();
-
- /*
- * HACKY: the $VALUES array must be initialized immediately after all of
- * the enum fields, but before any user initialization (which might rely
- * on $VALUES). The "1 + " is the statement containing the call to
- * Enum.$clinit().
- */
- int insertionPoint = 1 + initializers.size();
- assert clinitBlock.getStatements().size() >= initializers.size() + 1;
- clinitBlock.addStmt(insertionPoint, declStmt);
- valuesField.setInitializer(declStmt);
- }
- {
- // return $VALUES;
- SourceInfo sourceInfo = currentMethod.getSourceInfo();
- JFieldRef valuesRef = new JFieldRef(sourceInfo, null, valuesField, type);
- currentMethodBody.getBlock().addStmt(new JReturnStatement(sourceInfo, valuesRef));
- }
- return valuesField;
- }
- }
-
- /**
- * Resolve JSNI refs; replace with compile-time constants where appropriate.
- */
- private static class JsniRefGenerationVisitor extends JModVisitor {
-
- private class JsniRefResolver extends JsModVisitor {
- private final AbstractMethodDeclaration methodDecl;
- private final JsniMethodBody nativeMethodBody;
-
- private JsniRefResolver(AbstractMethodDeclaration methodDecl, JsniMethodBody nativeMethodBody) {
- this.methodDecl = methodDecl;
- this.nativeMethodBody = nativeMethodBody;
- }
-
- @Override
- public void endVisit(JsNameRef x, JsContext ctx) {
- String ident = x.getIdent();
- if (ident.charAt(0) == '@') {
- processNameRef(x, ctx);
- }
- }
-
- private JNode findJsniRefTarget(final SourceInfo info, String ident) {
- JsniRef parsed = JsniRef.parse(ident);
- if (parsed == null) {
- JsniCollector.reportJsniError(info, methodDecl, "Badly formatted native reference '"
- + ident + "'");
- return null;
- }
-
- JProgram prog = program;
-
- return JsniRefLookup.findJsniRefTarget(parsed, prog, new JsniRefLookup.ErrorReporter() {
- public void reportError(String error) {
- JsniCollector.reportJsniError(info, methodDecl, error);
- }
- });
- }
-
- private void processClassLiteral(JsNameRef nameRef, SourceInfo info, JType type, JsContext ctx) {
- assert !ctx.isLvalue();
- JsniClassLiteral classLiteral = new JsniClassLiteral(info, nameRef.getIdent(), type);
- nativeMethodBody.addClassRef(classLiteral);
- }
-
- private void processField(JsNameRef nameRef, SourceInfo info, JField field, JsContext ctx) {
- /*
- * We must replace any compile-time constants with the constant value of
- * the field.
- */
- if (field.isCompileTimeConstant()) {
- assert !ctx.isLvalue();
- JLiteral initializer = field.getConstInitializer();
- JType type = initializer.getType();
- if (type instanceof JPrimitiveType || program.isJavaLangString(type)) {
- GenerateJavaScriptLiterals generator = new GenerateJavaScriptLiterals();
- generator.accept(initializer);
- JsExpression result = generator.peek();
- assert (result != null);
- ctx.replaceMe(result);
- return;
- }
- }
-
- // Normal: create a jsniRef.
- JsniFieldRef fieldRef =
- new JsniFieldRef(info, nameRef.getIdent(), field, currentClass, ctx.isLvalue());
- nativeMethodBody.addJsniRef(fieldRef);
- }
-
- private void processMethod(JsNameRef nameRef, SourceInfo info, JMethod method, JsContext ctx) {
- assert !ctx.isLvalue();
- JsniMethodRef methodRef =
- new JsniMethodRef(info, nameRef.getIdent(), method, program.getJavaScriptObject());
- nativeMethodBody.addJsniRef(methodRef);
- }
-
- private void processNameRef(JsNameRef nameRef, JsContext ctx) {
- SourceInfo info = nativeMethodBody.getSourceInfo();
- // TODO: make this tighter when we have real source info
- // JSourceInfo info = translateInfo(nameRef.getInfo());
- String ident = nameRef.getIdent();
- JNode node = jsniMap.get(ident);
- if (node == null) {
- node = findJsniRefTarget(info, ident);
- if (node == null) {
- return; // already reported error
- }
- jsniMap.put(ident, node);
- }
-
- if (node instanceof JField) {
- processField(nameRef, info, (JField) node, ctx);
- } else if (node instanceof JMethod) {
- processMethod(nameRef, info, (JMethod) node, ctx);
- } else if (node instanceof JType) {
- processClassLiteral(nameRef, info, (JType) node, ctx);
- } else {
- throw new InternalCompilerException(node,
- "JSNI reference to something other than a class, field, or method?", null);
- }
- }
- }
-
- private JDeclaredType currentClass;
-
- private final Map<String, JNode> jsniMap = new HashMap<String, JNode>();
-
- private final Map<JsniMethodBody, AbstractMethodDeclaration> jsniMethodMap;
-
- private final JProgram program;
-
- public JsniRefGenerationVisitor(JProgram program,
- Map<JsniMethodBody, AbstractMethodDeclaration> jsniMethodMap) {
- this.program = program;
- this.jsniMethodMap = jsniMethodMap;
- }
-
- @Override
- public void endVisit(JClassType x, Context ctx) {
- currentClass = null;
- }
-
- @Override
- public void endVisit(JsniMethodBody x, Context ctx) {
- new JsniRefResolver(jsniMethodMap.get(x), x).accept(x.getFunc());
- }
-
- @Override
- public boolean visit(JClassType x, Context ctx) {
- currentClass = x;
- return true;
- }
-
- @Override
- public boolean visit(JMethodBody x, Context ctx) {
- return false;
- }
- }
-
- /**
- * Combines the information from the JDT type nodes and the type map to create
- * a JProgram structure.
- */
- public static void exec(TypeDeclaration[] types, TypeMap typeMap, JProgram jprogram,
- JJSOptions options) {
- Event generateJavaAstEvent = SpeedTracerLogger.start(CompilerEventType.GENERATE_JAVA_AST);
- // Construct the basic AST.
- JavaASTGenerationVisitor v = new JavaASTGenerationVisitor(typeMap, jprogram, options);
- for (TypeDeclaration type : types) {
- v.processType(type);
- }
- for (TypeDeclaration type : types) {
- v.addBridgeMethods(type.binding);
- }
- Collections.sort(jprogram.getDeclaredTypes(), new HasNameSort());
-
- // Process JSNI.
- Map<JsniMethodBody, AbstractMethodDeclaration> jsniMethodMap = v.getJsniMethodMap();
- new JsniRefGenerationVisitor(jprogram, jsniMethodMap).accept(jprogram);
- generateJavaAstEvent.end();
- }
-
- /**
- * Returns <code>true</code> if JDT optimized the condition to
- * <code>false</code>.
- */
- private static boolean isOptimizedFalse(Expression condition) {
- if (condition != null) {
- Constant cst = condition.optimizedBooleanConstant();
- if (cst != Constant.NotAConstant) {
- if (cst.booleanValue() == false) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Returns <code>true</code> if JDT optimized the condition to
- * <code>true</code>.
- */
- private static boolean isOptimizedTrue(Expression condition) {
- if (condition != null) {
- Constant cst = condition.optimizedBooleanConstant();
- if (cst != Constant.NotAConstant) {
- if (cst.booleanValue()) {
- return true;
- }
- }
- }
- return false;
- }
-
- private static boolean isScript(JProgram program) {
- return !program.getTypeJavaLangObject().isExternal();
- }
-}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
index c599720..b059bd8 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
@@ -1746,7 +1746,7 @@
* }
* </pre>
*/
- SourceInfo sourceInfo = program.createSourceInfoSynthetic(GenerateJavaScriptAST.class);
+ SourceInfo sourceInfo = SourceOrigin.UNKNOWN;
JsName entryName = topScope.declareName("$entry");
JsVar entryVar = new JsVar(sourceInfo, entryName);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
index 80fb3a3..1a8410c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java
@@ -1880,7 +1880,6 @@
* It's okay to defer creation of synthetic fields, they can't be
* referenced until we analyze the code.
*/
- int index = 0;
SourceTypeBinding binding = x.binding;
if (isNested(binding)) {
// add synthetic fields for outer this and locals
@@ -1889,7 +1888,7 @@
if (nestedBinding.enclosingInstances != null) {
for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) {
SyntheticArgumentBinding arg = nestedBinding.enclosingInstances[i];
- createSyntheticField(arg, type, index++, Disposition.THIS_REF);
+ createSyntheticField(arg, type, Disposition.THIS_REF);
}
}
@@ -1908,7 +1907,7 @@
}
}
}
- createSyntheticField(arg, type, index++, isReallyThisRef ? Disposition.THIS_REF
+ createSyntheticField(arg, type, isReallyThisRef ? Disposition.THIS_REF
: Disposition.FINAL);
}
}
@@ -2084,13 +2083,11 @@
}
private JField createSyntheticField(SyntheticArgumentBinding arg, JDeclaredType enclosingType,
- int index, Disposition disposition) {
+ Disposition disposition) {
JType type = typeMap.get(arg.type);
SourceInfo info = enclosingType.getSourceInfo();
JField field = new JField(info, intern(arg.name), enclosingType, type, false, disposition);
- // TODO: remove me, source identical for now!
- enclosingType.addField(index, field);
- // enclosingType.addField(field);
+ enclosingType.addField(field);
curClass.syntheticFields.put(arg, field);
if (arg.matchingField != null) {
typeMap.setField(arg.matchingField, field);
@@ -2758,8 +2755,6 @@
}
}
- public static boolean ENABLED = true;
-
/**
* Manually tracked version count.
*
@@ -2803,7 +2798,7 @@
*/
public static long getSerializationVersion() {
// TODO(zundel): something much awesomer.
- return ENABLED ? AST_VERSION : 0L;
+ return AST_VERSION;
}
static String dotify(char[][] name) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JsniRefLookup.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JsniRefLookup.java
index 33684c5..a6cd491 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/JsniRefLookup.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JsniRefLookup.java
@@ -35,7 +35,10 @@
/**
* A utility class that can look up a {@link JsniRef} in a {@link JProgram}.
+ *
+ * @deprecated find alternatives, only a couple of corner cases use this now.
*/
+@Deprecated
public class JsniRefLookup {
/**
* A callback used to indicate the reason for a failed JSNI lookup.
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JsoDevirtualizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JsoDevirtualizer.java
index 31d952b..680e19b 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/JsoDevirtualizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JsoDevirtualizer.java
@@ -243,8 +243,10 @@
jsoMethodInstances.put(polyMethod.getSignature(), methodCount);
String devirtualName = prefix + "__devirtual$";
JMethod newMethod =
- program.createMethod(sourceInfo, devirtualName, jsoType, polyMethod.getType(), false, true,
- true, AccessModifier.PUBLIC, false);
+ new JMethod(sourceInfo, devirtualName, jsoType, polyMethod.getType(), false, true, true,
+ AccessModifier.PUBLIC);
+ newMethod.setBody(new JMethodBody(sourceInfo));
+ jsoType.addMethod(newMethod);
newMethod.setSynthetic();
// Setup parameters.
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRebinds.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRebinds.java
deleted file mode 100644
index 94056ee..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRebinds.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed 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 com.google.gwt.dev.jjs.impl;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.dev.jdt.RebindPermutationOracle;
-import com.google.gwt.dev.jjs.InternalCompilerException;
-import com.google.gwt.dev.jjs.ast.Context;
-import com.google.gwt.dev.jjs.ast.HasName;
-import com.google.gwt.dev.jjs.ast.JClassLiteral;
-import com.google.gwt.dev.jjs.ast.JClassType;
-import com.google.gwt.dev.jjs.ast.JDeclaredType;
-import com.google.gwt.dev.jjs.ast.JExpression;
-import com.google.gwt.dev.jjs.ast.JGwtCreate;
-import com.google.gwt.dev.jjs.ast.JMethod;
-import com.google.gwt.dev.jjs.ast.JMethodCall;
-import com.google.gwt.dev.jjs.ast.JModVisitor;
-import com.google.gwt.dev.jjs.ast.JNameOf;
-import com.google.gwt.dev.jjs.ast.JNode;
-import com.google.gwt.dev.jjs.ast.JNullLiteral;
-import com.google.gwt.dev.jjs.ast.JProgram;
-import com.google.gwt.dev.jjs.ast.JReferenceType;
-import com.google.gwt.dev.jjs.ast.JStringLiteral;
-import com.google.gwt.dev.util.JsniRef;
-import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
-import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
-import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Replaces any "GWT.create()" calls with a special node.
- */
-public class ReplaceRebinds {
-
- private class RebindVisitor extends JModVisitor {
-
- private JDeclaredType currentClass;
- private final JMethod nameOfMethod;
- private final JMethod rebindCreateMethod;
-
- public RebindVisitor(JMethod nameOfMethod, JMethod rebindCreateMethod) {
- this.nameOfMethod = nameOfMethod;
- this.rebindCreateMethod = rebindCreateMethod;
- }
-
- @Override
- public void endVisit(JMethodCall x, Context ctx) {
- JMethod method = x.getTarget();
- if (method == nameOfMethod) {
- replaceImplNameOf(x, ctx);
-
- } else if (method == rebindCreateMethod) {
- replaceGwtCreate(x, ctx);
- }
- }
-
- @Override
- public boolean visit(JMethod x, Context ctx) {
- currentClass = x.getEnclosingType();
- return true;
- }
-
- private void replaceGwtCreate(JMethodCall x, Context ctx) {
- assert (x.getArgs().size() == 1);
- JExpression arg = x.getArgs().get(0);
- assert (arg instanceof JClassLiteral);
- JClassLiteral classLiteral = (JClassLiteral) arg;
- JReferenceType sourceType = (JReferenceType) classLiteral.getRefType();
- List<JClassType> allRebindResults = getAllPossibleRebindResults(sourceType);
- JGwtCreate gwtCreate =
- new JGwtCreate(x.getSourceInfo(), sourceType, allRebindResults, program
- .getTypeJavaLangObject(), currentClass);
- if (allRebindResults.size() == 1) {
- // Just replace with the instantiation expression.
- ctx.replaceMe(gwtCreate.getInstantiationExpressions().get(0));
- } else {
- ctx.replaceMe(gwtCreate);
- }
- }
-
- private void replaceImplNameOf(JMethodCall x, Context ctx) {
- JExpression arg0 = x.getArgs().get(0);
- assert arg0 instanceof JStringLiteral;
- JStringLiteral stringLiteral = (JStringLiteral) arg0;
- String stringValue = stringLiteral.getValue();
-
- JNode node = null;
-
- JDeclaredType refType;
- JsniRef ref = JsniRef.parse(stringValue);
-
- if (ref != null) {
- final List<String> errors = new ArrayList<String>();
- node = JsniRefLookup.findJsniRefTarget(ref, program, new JsniRefLookup.ErrorReporter() {
- public void reportError(String error) {
- errors.add(error);
- }
- });
- if (!errors.isEmpty()) {
- for (String error : errors) {
- logger.log(TreeLogger.ERROR, error);
- }
- }
- } else {
- // See if it's just @foo.Bar, which would result in the class seed
- node =
- program.getFromTypeMap(stringValue.charAt(0) == '@' ? stringValue.substring(1)
- : stringValue);
- }
- if (node == null) {
- // Not found, must be null
- ctx.replaceMe(JNullLiteral.INSTANCE);
- } else {
- ctx.replaceMe(new JNameOf(x.getSourceInfo(), program.getTypeJavaLangString(),
- (HasName) node));
- }
- }
- }
-
- public static boolean exec(TreeLogger logger, JProgram program, RebindPermutationOracle rpo) {
- Event replaceRebindsEvent = SpeedTracerLogger.start(CompilerEventType.REPLACE_REBINDS);
- boolean didChange = new ReplaceRebinds(logger, program, rpo).execImpl();
- replaceRebindsEvent.end();
- return didChange;
- }
-
- private final TreeLogger logger;
- private final JProgram program;
- private final RebindPermutationOracle rpo;
-
- private ReplaceRebinds(TreeLogger logger, JProgram program, RebindPermutationOracle rpo) {
- this.logger = logger;
- this.program = program;
- this.rpo = rpo;
- }
-
- protected List<JClassType> getAllPossibleRebindResults(JReferenceType type) {
- // Rebinds are always on a source type name.
- String reqType = type.getName().replace('$', '.');
- String[] answers;
- try {
- answers = rpo.getAllPossibleRebindAnswers(logger, reqType);
- } catch (UnableToCompleteException e) {
- // Should never happen.
- throw new InternalCompilerException("Unexpected failure to get possible rebind answers for '"
- + reqType + "'");
- }
- List<JClassType> rebindAnswers = new ArrayList<JClassType>();
- for (String answer : answers) {
- JReferenceType result = program.getFromTypeMap(answer);
- assert (result != null);
- rebindAnswers.add((JClassType) result);
- }
- assert rebindAnswers.size() > 0;
- return rebindAnswers;
- }
-
- private boolean execImpl() {
- RebindVisitor rebinder =
- new RebindVisitor(program.getIndexedMethod("Impl.getNameOf"), program
- .getIndexedMethod("GWT.create"));
- rebinder.accept(program);
- return rebinder.didChange();
- }
-
-}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ResolveRebinds.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ResolveRebinds.java
index 87d9b98..ba463cd 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ResolveRebinds.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ResolveRebinds.java
@@ -18,6 +18,7 @@
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.ast.AccessModifier;
+import com.google.gwt.dev.jjs.SourceOrigin;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JBlock;
import com.google.gwt.dev.jjs.ast.JCaseStatement;
@@ -53,7 +54,8 @@
if (isSoftRebind(x.getSourceType())) {
JMethod method =
- rebindMethod(x.getSourceType(), x.getResultTypes(), x.getInstantiationExpressions());
+ rebindMethod(x.getSourceInfo(), x.getSourceType(), x.getResultTypes(), x
+ .getInstantiationExpressions());
JMethodCall call = new JMethodCall(x.getSourceInfo(), null, method);
ctx.replaceMe(call);
return;
@@ -76,7 +78,9 @@
public void endVisit(JReboundEntryPoint x, Context ctx) {
if (isSoftRebind(x.getSourceType())) {
- JMethod method = rebindMethod(x.getSourceType(), x.getResultTypes(), x.getEntryCalls());
+ JMethod method =
+ rebindMethod(x.getSourceInfo(), x.getSourceType(), x.getResultTypes(), x
+ .getEntryCalls());
JMethodCall call = new JMethodCall(x.getSourceInfo(), null, method);
ctx.replaceMe(call.makeStatement());
return;
@@ -158,7 +162,7 @@
return !hardRebindAnswers.containsKey(requestType);
}
- private JMethod rebindMethod(String requestType, List<String> resultTypes,
+ private JMethod rebindMethod(SourceInfo info, String requestType, List<String> resultTypes,
List<JExpression> instantiationExpressions) {
assert resultTypes.size() == instantiationExpressions.size();
@@ -196,12 +200,13 @@
}
assert mostUsed != null;
+ info = info.makeChild(SourceOrigin.UNKNOWN);
// c_g_g_d_c_i_DOMImpl
- SourceInfo info = program.createSourceInfoSynthetic(getClass());
toReturn =
- program.createMethod(info, requestType.replace("_", "_1").replace('.', '_'), holderType,
- program.getTypeJavaLangObject().getNonNull(), false, true, true,
- AccessModifier.PUBLIC, false);
+ new JMethod(info, requestType.replace("_", "_1").replace('.', '_'), holderType, program
+ .getTypeJavaLangObject().getNonNull(), false, true, true, AccessModifier.PUBLIC);
+ toReturn.setBody(new JMethodBody(info));
+ holderType.addMethod(toReturn);
toReturn.freezeParamTypes();
info.addCorrelation(info.getCorrelator().by(toReturn));
rebindMethods.put(requestType, toReturn);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeLinker.java b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeLinker.java
deleted file mode 100644
index fd4ff5b..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeLinker.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed 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 com.google.gwt.dev.jjs.impl;
-
-/**
- * Provides linking information for types for separate compilation.
- */
-public interface TypeLinker {
-
- TypeLinker NULL_TYPE_LINKER = new TypeLinker() {
- public boolean isExternalType(String name) {
- return false;
- }
- };
-
- /**
- * Returns true if the type is external (source code not provided) to the
- * program.
- */
- boolean isExternalType(String name);
-}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeMap.java b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeMap.java
deleted file mode 100644
index cb2390d..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeMap.java
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed 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 com.google.gwt.dev.jjs.impl;
-
-import com.google.gwt.dev.jjs.InternalCompilerException;
-import com.google.gwt.dev.jjs.ast.JConstructor;
-import com.google.gwt.dev.jjs.ast.JDeclaredType;
-import com.google.gwt.dev.jjs.ast.JField;
-import com.google.gwt.dev.jjs.ast.JMethod;
-import com.google.gwt.dev.jjs.ast.JNode;
-import com.google.gwt.dev.jjs.ast.JProgram;
-import com.google.gwt.dev.jjs.ast.JType;
-import com.google.gwt.dev.util.collect.IdentityHashSet;
-
-import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
-import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
-import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ParameterizedFieldBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ParameterizedMethodBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
-import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
-import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.IdentityHashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Contains the list of the top-level and array types.
- */
-public class TypeMap {
-
- /**
- * Maps Eclipse AST nodes to our JNodes.
- */
- private final Map<Binding, JNode> crossRefMap = new IdentityHashMap<Binding, JNode>();
-
- private final Map<String, JDeclaredType> externalTypesByName =
- new HashMap<String, JDeclaredType>();
-
- /**
- * Centralizes creation and singleton management.
- */
- private final JProgram program;
-
- public TypeMap(JProgram program) {
- this.program = program;
- }
-
- public JNode get(Binding binding) {
- return get(binding, true);
- }
-
- public JProgram getProgram() {
- return program;
- }
-
- public void put(Binding binding, JNode to) {
- if (binding == null) {
- throw new InternalCompilerException("Trying to put null into typeMap.");
- }
-
- Object old = crossRefMap.put(binding, to);
- assert (old == null);
-
- if (to instanceof JDeclaredType) {
- JDeclaredType type = (JDeclaredType) to;
- if (type.isExternal()) {
- externalTypesByName.put(type.getName(), type);
- }
- }
- }
-
- public JNode tryGet(Binding binding) {
- return get(binding, false);
- }
-
- private boolean equals(MethodBinding binding, JMethod method) {
- if (!(method instanceof JConstructor && binding.isConstructor())
- && !method.getName().equals(String.valueOf(binding.constantPoolName()))) {
- return false;
- }
-
- List<JType> paramTypes = method.getOriginalParamTypes();
- TypeBinding[] bindingParams = binding.parameters;
-
- if (paramTypes.size() != bindingParams.length) {
- return false;
- }
-
- for (int i = 0; i < bindingParams.length; ++i) {
- TypeBinding bindingParam = bindingParams[i];
- if (paramTypes.get(i) != get(bindingParam)) {
- return false;
- }
- }
-
- return method.getType() == get(binding.returnType);
- }
-
- private JNode get(Binding binding, boolean failOnNull) {
- if (binding instanceof TypeVariableBinding) {
- TypeVariableBinding tvb = (TypeVariableBinding) binding;
- return get(tvb.erasure(), failOnNull);
- } else if (binding instanceof ParameterizedTypeBinding) {
- ParameterizedTypeBinding ptb = (ParameterizedTypeBinding) binding;
- return get(ptb.erasure(), failOnNull);
- } else if (binding instanceof ParameterizedMethodBinding) {
- ParameterizedMethodBinding pmb = (ParameterizedMethodBinding) binding;
- return get(pmb.original(), failOnNull);
- } else if (binding instanceof ParameterizedFieldBinding) {
- ParameterizedFieldBinding pfb = (ParameterizedFieldBinding) binding;
- return get(pfb.original(), failOnNull);
- } else if (binding instanceof WildcardBinding) {
- WildcardBinding wcb = (WildcardBinding) binding;
- return get(wcb.erasure(), failOnNull);
- }
- JNode result = internalGet(binding, failOnNull);
- if (result == null && failOnNull) {
- InternalCompilerException ice = new InternalCompilerException("Failed to get JNode");
- ice.addNode(binding.getClass().getName(), binding.toString(), null);
- throw ice;
- }
- return result;
- }
-
- private JField getFieldForBinding(JDeclaredType type, FieldBinding binding) {
- for (JField field : type.getFields()) {
- if (field.getName().equals(String.valueOf(binding.name))) {
- return field;
- }
- }
-
- return null;
- }
-
- private JMethod getMethodForBinding(JDeclaredType type, MethodBinding binding) {
- for (JMethod method : type.getMethods()) {
- if (equals(binding, method)) {
- return method;
- }
- }
-
- return null;
- }
-
- /**
- * Returns a list of JNodes that have the same name as the JDT Binding. This
- * method is only used during debugging sessions from the interactive
- * expression evaluator.
- */
- @SuppressWarnings("unused")
- private List<JNode> haveSameName(Binding binding) {
- IdentityHashSet<JNode> nodes = new IdentityHashSet<JNode>();
- for (Binding b : crossRefMap.keySet()) {
- if (String.valueOf(b.readableName()).equals(String.valueOf(binding.readableName()))) {
- nodes.add(crossRefMap.get(b));
- }
- }
- return new ArrayList<JNode>(nodes);
- }
-
- private JNode internalGet(Binding binding, boolean failOnNull) {
- JNode cached = crossRefMap.get(binding);
- if (cached != null) {
- return cached;
- } else if (binding instanceof BaseTypeBinding) {
- BaseTypeBinding baseTypeBinding = (BaseTypeBinding) binding;
- // see org.eclipse.jdt.internal.compiler.lookup.TypeIds constants
- switch (baseTypeBinding.id) {
- case TypeIds.T_JavaLangObject:
- // here for consistency, should already be cached
- return program.getTypeJavaLangObject();
- case TypeIds.T_char:
- return program.getTypePrimitiveChar();
- case TypeIds.T_byte:
- return program.getTypePrimitiveByte();
- case TypeIds.T_short:
- return program.getTypePrimitiveShort();
- case TypeIds.T_boolean:
- return program.getTypePrimitiveBoolean();
- case TypeIds.T_void:
- return program.getTypeVoid();
- case TypeIds.T_long:
- return program.getTypePrimitiveLong();
- case TypeIds.T_double:
- return program.getTypePrimitiveDouble();
- case TypeIds.T_float:
- return program.getTypePrimitiveFloat();
- case TypeIds.T_int:
- return program.getTypePrimitiveInt();
- case TypeIds.T_JavaLangString:
- // here for consistency, should already be cached
- return program.getTypeJavaLangString();
- case TypeIds.T_null:
- return program.getTypeNull();
- case TypeIds.T_undefined:
- default:
- return null;
- }
- } else if (binding instanceof ArrayBinding) {
- ArrayBinding arrayBinding = (ArrayBinding) binding;
- JType elementType = (JType) get(arrayBinding.elementsType(), failOnNull);
- if (elementType == null) {
- return null;
- }
- return program.getTypeArray(elementType);
- } else if (binding instanceof BinaryTypeBinding) {
- BinaryTypeBinding binaryBinding = (BinaryTypeBinding) binding;
- String name = BuildTypeMap.dotify(binaryBinding.compoundName);
-
- // There may be many BinaryTypeBindings for a single binary type
- JDeclaredType type = externalTypesByName.get(name);
- if (type != null) {
- put(binding, type);
- }
- return type;
- } else if (binding instanceof MethodBinding) {
- MethodBinding b = (MethodBinding) binding;
- JMethod cachedMethod = (JMethod) crossRefMap.get(b);
- if (cachedMethod == null) {
- JDeclaredType type = (JDeclaredType) get(b.declaringClass, failOnNull);
- if (type == null) {
- return type;
- }
- cachedMethod = getMethodForBinding(type, b);
- if (cachedMethod != null) {
- put(b, cachedMethod);
- }
- } else {
- // Happens sometimes when looking up the type to resolve the binding
- // causes us to also resolve the binding.
- }
-
- return cachedMethod;
- } else if (binding instanceof FieldBinding) {
- FieldBinding b = (FieldBinding) binding;
- JField cachedField = (JField) crossRefMap.get(b);
-
- if (cachedField == null) {
- JDeclaredType type = (JDeclaredType) get(b.declaringClass, failOnNull);
- if (type == null) {
- return null;
- }
- cachedField = getFieldForBinding(type, b);
- if (cachedField != null) {
- put(b, cachedField);
- }
- } else {
- // Happens sometimes when looking up the type to resolve the binding
- // causes us to also resolve the binding.
- }
-
- return cachedField;
- }
-
- return null;
- }
-}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/UnifyAst.java b/dev/core/src/com/google/gwt/dev/jjs/impl/UnifyAst.java
index a46ae10..06490a1 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/UnifyAst.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/UnifyAst.java
@@ -516,10 +516,13 @@
this.classFileMapBySource = rpo.getCompilationState().getClassFileMapBySource();
}
- public void addRootTypes(Collection<String> sourceTypeNames) {
+ public void addRootTypes(Collection<String> sourceTypeNames) throws UnableToCompleteException {
for (String sourceTypeName : sourceTypeNames) {
searchForTypeBySource(sourceTypeName);
}
+ if (errorsFound) {
+ throw new UnableToCompleteException();
+ }
}
/**
diff --git a/dev/core/test/com/google/gwt/dev/jjs/JjsTypeTest.java b/dev/core/test/com/google/gwt/dev/jjs/JjsTypeTest.java
index 5082227..3ed9a94 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/JjsTypeTest.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/JjsTypeTest.java
@@ -215,30 +215,31 @@
createSampleProgram();
}
- private JClassType createClass(String className, JClassType superClass,
- boolean isAbstract, boolean isFinal) {
- JClassType clazz = program.createClass(synthSource, className, isAbstract,
- isFinal);
- clazz.setSuperClass(superClass);
- return clazz;
+ private JClassType createClass(String className, JClassType superClass, boolean isAbstract,
+ boolean isFinal) {
+ JClassType x = new JClassType(synthSource, className, isAbstract, isFinal);
+ program.addType(x);
+ x.setSuperClass(superClass);
+ return x;
}
private JInterfaceType createInterface(String className) {
- JInterfaceType intf = program.createInterface(synthSource, className);
- return intf;
+ JInterfaceType x = new JInterfaceType(synthSource, className);
+ program.addType(x);
+ return x;
}
private void createSampleProgram() {
// Make the program itself
program = new JProgram();
typeOracle = program.typeOracle;
- synthSource = program.createSourceInfoSynthetic(JjsTypeTest.class);
+ synthSource = SourceOrigin.UNKNOWN;
classObject = createClass("java.lang.Object", null, false, false);
classString = createClass("java.lang.String", classObject, false, true);
createClass("com.google.gwt.lang.Array", classObject, false, true);
- classJso = createClass("com.google.gwt.core.client.JavaScriptObject",
- classObject, false, false);
+ classJso =
+ createClass("com.google.gwt.core.client.JavaScriptObject", classObject, false, false);
intfSerializable = createInterface("java.io.Serializable");
intfCloneable = createInterface("java.lang.Cloneable");
@@ -267,7 +268,7 @@
classJso1.addImplements(intfJ);
classJso2 = createClass("Jso2", classJso, false, false);
classJso2.addImplements(intfK);
-
+
program.typeOracle.computeBeforeAST();
// Save off some miscellaneous types to test against
@@ -287,8 +288,7 @@
arrayOfArrayOfB = program.getTypeArray(classB, 2);
}
- private JReferenceType generalizeTypes(JReferenceType type1,
- JReferenceType type2) {
+ private JReferenceType generalizeTypes(JReferenceType type1, JReferenceType type2) {
List<JReferenceType> types = new ArrayList<JReferenceType>(2);
types.add(type1);
types.add(type2);
diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/JJSTestBase.java b/dev/core/test/com/google/gwt/dev/jjs/impl/JJSTestBase.java
index a1087b0..39c0741 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/impl/JJSTestBase.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/impl/JJSTestBase.java
@@ -235,17 +235,13 @@
}
});
addBuiltinClasses(sourceOracle);
- boolean wasEnabled = GwtAstBuilder.ENABLED;
- try {
- GwtAstBuilder.ENABLED = true;
- CompilationState state = CompilationStateBuilder.buildFrom(logger,
- sourceOracle.getResources(), getAdditionalTypeProviderDelegate());
- JProgram program = JavaAstConstructor.construct(logger, state,
- "test.EntryPoint", "com.google.gwt.lang.Exceptions");
- return program;
- } finally {
- GwtAstBuilder.ENABLED = wasEnabled;
- }
+ CompilationState state =
+ CompilationStateBuilder.buildFrom(logger, sourceOracle.getResources(),
+ getAdditionalTypeProviderDelegate());
+ JProgram program =
+ JavaAstConstructor.construct(logger, state, "test.EntryPoint",
+ "com.google.gwt.lang.Exceptions");
+ return program;
}
protected void addBuiltinClasses(MockResourceOracle sourceOracle) {
diff --git a/user/test/com/google/gwt/dev/jjs/GwtAstBuilderTest.java b/user/test/com/google/gwt/dev/jjs/GwtAstBuilderTest.java
deleted file mode 100644
index e3ab41e..0000000
--- a/user/test/com/google/gwt/dev/jjs/GwtAstBuilderTest.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed 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 com.google.gwt.dev.jjs;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.dev.GwtAstBuilderUtil;
-import com.google.gwt.dev.cfg.ModuleDef;
-import com.google.gwt.dev.cfg.ModuleDefLoader;
-import com.google.gwt.dev.javac.CompilationState;
-import com.google.gwt.dev.javac.CompilationUnit;
-import com.google.gwt.dev.jjs.ast.JDeclaredType;
-import com.google.gwt.dev.jjs.ast.JProgram;
-import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
-
-import junit.framework.TestCase;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.PrintWriter;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Massive test for {@link com.google.gwt.dev.jjs.impl.GwtAstBuilder}.
- */
-public class GwtAstBuilderTest extends TestCase {
- /*
- * Reuse the module and compilation state between tests, because it takes a
- * long time to build them. This is fine as long as we don't mutate them.
- */
-
- private static CompilationState compilationState;
- private static PrintWriterTreeLogger logger;
- private static ModuleDef module;
-
- private static synchronized CompilationState getCompilationState()
- throws UnableToCompleteException {
- if (compilationState == null) {
- compilationState = GwtAstBuilderUtil.buildGwtAst(getLogger(), getTestModule());
- }
- return compilationState;
- }
-
- private static synchronized TreeLogger getLogger() {
- if (logger == null) {
- logger = new PrintWriterTreeLogger(new PrintWriter(System.err, true));
- logger.setMaxDetail(TreeLogger.ERROR);
- }
- return logger;
- }
-
- private static synchronized ModuleDef getTestModule() throws UnableToCompleteException {
- if (module == null) {
- module =
- ModuleDefLoader.createSyntheticModule(getLogger(),
- "com.google.gwt.dev.jjs.CompilerSuite.GwtAstBuilderTest", new String[]{
- "com.google.gwt.junit.JUnit", "com.google.gwt.dev.jjs.CompilerSuite"}, false);
- }
- return module;
- }
-
- /**
- * Tests source compatibility between
- * {@link com.google.gwt.dev.jjs.impl.GwtAstBuilder} and
- * {@link com.google.gwt.dev.jjs.impl.GenerateJavaAST}.
- */
- public void testGwtAstBuilder() throws UnableToCompleteException {
- CompilationState compilationState = getCompilationState();
- assertFalse(compilationState.hasErrors());
- JProgram jprogram =
- GwtAstBuilderUtil.buildGenerateJavaAst(getLogger(), getTestModule(), compilationState);
-
- Map<String, JDeclaredType> compStateTypes = new HashMap<String, JDeclaredType>();
- for (CompilationUnit unit : compilationState.getCompilationUnits()) {
- for (JDeclaredType type : unit.getTypes()) {
- compStateTypes.put(type.getName(), type);
- }
- }
-
- for (JDeclaredType genJavaAstType : jprogram.getDeclaredTypes()) {
- String typeName = genJavaAstType.getName();
- if ("com.google.gwt.core.client.GWT".equals(typeName)) {
- // Known mismatch; UnifyAst fills in the magic methods.
- continue;
- }
- if ("com.google.gwt.core.client.JavaScriptObject".equals(typeName)) {
- // Known mismatch; genJavaAst version implements all JSO interfaces.
- continue;
- }
- if ("com.google.gwt.dev.jjs.test.B$1".equals(typeName)) {
- // Known mismatch; genJavaAst is "wrong".
- continue;
- }
- if (typeName.startsWith("com.google.gwt.dev.jjs.test.CoverageTest$Inner$1")) {
- // Known mismatch; two different emulation paths do the same thing.
- continue;
- }
- JDeclaredType compStateType = compStateTypes.get(typeName);
- assertNotNull("No matching prebuilt type for '" + typeName + "'", compStateType);
- String oldSource = genJavaAstType.toSource();
- String newSource = compStateType.toSource();
- assertEquals("Mismatched output for '" + typeName + "'", oldSource, newSource);
- }
- }
-
- /**
- * Test that serialization doesn't crash and produces the same source tree.
- */
- public void testSerialization() throws UnableToCompleteException, IOException,
- ClassNotFoundException {
- CompilationState compilationState = getCompilationState();
- assertFalse(compilationState.hasErrors());
- for (CompilationUnit unit : compilationState.getCompilationUnits()) {
- Map<String, JDeclaredType> compStateTypes = new HashMap<String, JDeclaredType>();
- for (JDeclaredType type : unit.getTypes()) {
- compStateTypes.put(type.getName(), type);
- }
- byte[] bytes = unit.getTypesSerialized();
- ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
- ObjectInputStream ois = new ObjectInputStream(bais);
- List<JDeclaredType> deserializedTypes = JProgram.deserializeTypes(ois);
- assertEquals(compStateTypes.size(), deserializedTypes.size());
- for (JDeclaredType deserializedType : deserializedTypes) {
- String typeName = deserializedType.getName();
- JDeclaredType compStateType = compStateTypes.get(typeName);
- assertNotNull("No matching prebuilt type for '" + typeName + "'", compStateType);
- String oldSource = compStateType.toSource();
- String newSource = deserializedType.toSource();
- assertEquals("Mismatched output for '" + typeName + "'", oldSource, newSource);
- }
- }
- }
-}