Cleanup in UnifyAST.
Change-Id: Ie0c5a85f9334a4582498818c5f4e3bebedf974b6
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java
index 4851be5..b2ec0d0 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java
@@ -224,6 +224,7 @@
return isCompileTimeConstant;
}
+ @Override
public boolean isExternal() {
return getEnclosingType().isExternal();
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JMember.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JMember.java
index c0ab0e3..cc4e6dc 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JMember.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JMember.java
@@ -31,5 +31,7 @@
boolean isSynthetic();
+ boolean isExternal();
+
String getQualifiedName();
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
index 41f4bda..511b10f 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
@@ -644,6 +644,7 @@
return access == AccessModifier.DEFAULT.ordinal();
}
+ @Override
public boolean isExternal() {
return getEnclosingType().isExternal();
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JavaAstVerifier.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JavaAstVerifier.java
index 7537714..0cf679e 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/JavaAstVerifier.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JavaAstVerifier.java
@@ -54,7 +54,7 @@
JavaAstVerifier(JProgram program) {
this.program = program;
- for (JDeclaredType type :program.getModuleDeclaredTypes()) {
+ for (JDeclaredType type :program.getDeclaredTypes()) {
membersByType.putAll(type, type.getMethods());
membersByType.putAll(type, type.getFields());
}
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 9e902b0..ae9af27 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
@@ -18,6 +18,7 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.dev.CompilerContext;
import com.google.gwt.dev.MinimalRebuildCache;
import com.google.gwt.dev.cfg.ConfigurationProperty;
@@ -27,8 +28,8 @@
import com.google.gwt.dev.javac.CompilationUnit;
import com.google.gwt.dev.javac.CompiledClass;
import com.google.gwt.dev.jdt.RebindPermutationOracle;
-import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.PrecompilationContext;
+import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.SourceOrigin;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.HasName;
@@ -48,6 +49,7 @@
import com.google.gwt.dev.jjs.ast.JFieldRef;
import com.google.gwt.dev.jjs.ast.JInstanceOf;
import com.google.gwt.dev.jjs.ast.JInterfaceType;
+import com.google.gwt.dev.jjs.ast.JMember;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethod.Specialization;
import com.google.gwt.dev.jjs.ast.JMethodBody;
@@ -84,6 +86,7 @@
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
import com.google.gwt.thirdparty.guava.common.base.Predicates;
+import com.google.gwt.thirdparty.guava.common.collect.ImmutableMap;
import com.google.gwt.thirdparty.guava.common.collect.Iterables;
import com.google.gwt.thirdparty.guava.common.collect.LinkedListMultimap;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
@@ -236,25 +239,13 @@
}
@Override
- public void endVisit(JExpressionStatement x, Context ctx) {
- if (x.getExpr() instanceof JMethodCall) {
- JMethodCall call = (JMethodCall) x.getExpr();
- JMethod target = call.getTarget();
- if (GWT_DEBUGGER_METHOD_CALLS.contains(target.getQualifiedName())) {
- // We should see all calls here because GWT.debugger() returns void.
- ctx.replaceMe(new JDebuggerStatement(x.getSourceInfo()));
- }
- }
- }
-
- @Override
public void endVisit(JField x, Context ctx) {
assert false : "Should not get here";
}
@Override
public void endVisit(JFieldRef x, Context ctx) {
- JField field = translate(x.getField());
+ JField field = translate(x.getSourceInfo(), x.getField());
flowInto(field);
x.resolve(field);
// Should not have an overridden type at this point.
@@ -285,21 +276,7 @@
assert errorsFound;
return;
}
- String targetSignature = target.getQualifiedName();
- if (MAGIC_METHOD_CALLS.contains(targetSignature)) {
- if (GWT_DEBUGGER_METHOD_CALLS.contains(targetSignature)) {
- return; // handled in endVisit for JExpressionStatement
- }
- JExpression result = handleMagicMethodCall(x, targetSignature);
- if (result == null) {
- // Error of some sort.
- result = JNullLiteral.INSTANCE;
- }
- result = this.accept(result);
- ctx.replaceMe(result);
- return;
- }
- // Should not have an overridden type at this point.
+ // Should not have an overridden type at this point.
assert x instanceof JNewInstance || x.getType() == target.getType();
flowInto(target);
@@ -310,10 +287,8 @@
HasName node = x.getNode();
if (node instanceof JType) {
node = translate((JType) node);
- } else if (node instanceof JField) {
- node = translate((JField) node);
- } else if (node instanceof JMethod) {
- node = translate((JMethod) node);
+ } else if (node instanceof JMember) {
+ node = translate(x.getSourceInfo(), (JMember) node);
} else {
assert false : "Should not get here";
}
@@ -349,7 +324,7 @@
@Override
public void endVisit(JsniMethodRef x, Context ctx) {
- JMethod target = translate(x.getTarget());
+ JMethod target = translate(x.getSourceInfo(), x.getTarget());
x.resolve(target, program.getJavaScriptObject());
flowInto(target);
}
@@ -391,6 +366,19 @@
}
@Override
+ public boolean visit(JExpressionStatement x, Context ctx) {
+ if (x.getExpr() instanceof JMethodCall) {
+ JMethodCall call = (JMethodCall) x.getExpr();
+ JMethod target = call.getTarget();
+ if (GWT_DEBUGGER_METHOD_CALLS.contains(target.getQualifiedName())) {
+ // We should see all calls here because GWT.debugger() returns void.
+ ctx.replaceMe(new JDebuggerStatement(x.getSourceInfo()));
+ }
+ }
+ return true;
+ }
+
+ @Override
public boolean visit(JMethod x, Context ctx) {
currentMethod = x;
// Only visit contents of methods defined in types which are part of this compile. Visit
@@ -402,10 +390,40 @@
@Override
public boolean visit(JMethodCall x, Context ctx) {
- JMethod target = translate(x.getTarget());
+ JMethod target = translate(x.getSourceInfo(), x.getTarget());
x.resolve(target);
- // Special handling.
- return !MAGIC_METHOD_CALLS.contains(target.getQualifiedName());
+ // Special handling for magic method calls.
+ JExpression replacement = maybeHandleMagicMethodCall(x);
+ if (replacement != null) {
+ ctx.replaceMe(accept(replacement));
+ return false;
+ }
+ return true;
+ }
+
+ private JExpression maybeHandleMagicMethodCall(JMethodCall methodCall) {
+ JExpression result;
+ switch (methodCall.getTarget().getQualifiedName()) {
+ case GWT_CREATE:
+ case OLD_GWT_CREATE:
+ result = createRebindExpression(methodCall);
+ break;
+ case IMPL_GET_NAME_OF:
+ result = handleImplNameOf(methodCall);
+ break;
+ case SYSTEM_GET_PROPERTY:
+ case SYSTEM_GET_PROPERTY_WITH_DEFAULT:
+ result = handleSystemGetProperty(methodCall);
+ break;
+ default:
+ // Not a magic method call, return null so that it does not get replaced.
+ return null;
+ }
+ if (result == null) {
+ // Handled magic call possibly with an error.
+ return JNullLiteral.INSTANCE;
+ }
+ return result;
}
private JExpression handleSystemGetProperty(JMethodCall gwtGetPropertyCall) {
@@ -485,18 +503,21 @@
}
minimalRebuildCache.recordRebinderTypeForReboundType(reboundTypeName,
currentMethod.getEnclosingType().getName());
- rpo.getGeneratorContext().setCurrentRebindBinaryTypeName(reboundTypeName);
+ rebindPermutationOracle
+ .getGeneratorContext().setCurrentRebindBinaryTypeName(reboundTypeName);
}
- String reqType = BinaryName.toSourceName(reboundTypeName);
+ String requestedType = BinaryName.toSourceName(reboundTypeName);
List<String> answers;
try {
- answers = Lists.newArrayList(rpo.getAllPossibleRebindAnswers(logger, reqType));
+ answers = Lists.newArrayList(
+ rebindPermutationOracle.getAllPossibleRebindAnswers(logger, requestedType));
if (incrementalCompile) {
// Accumulate generated artifacts so that they can be output on recompiles even if no
// generators are run.
- minimalRebuildCache.addGeneratedArtifacts(rpo.getGeneratorContext().getArtifacts());
+ ArtifactSet artifacts = rebindPermutationOracle.getGeneratorContext().getArtifacts();
+ minimalRebuildCache.addGeneratedArtifacts(artifacts);
}
- rpo.getGeneratorContext().finish(logger);
+ rebindPermutationOracle.getGeneratorContext().finish(logger);
if (incrementalCompile) {
// There may be more types known to be modified after Generator execution, which would
// mean the previous stale types calculation was too small. Redo it.
@@ -506,7 +527,7 @@
fullFlowIntoRemainingStaleTypes();
}
} catch (UnableToCompleteException e) {
- error(gwtCreateCall, "Failed to resolve '" + reqType + "' via deferred binding");
+ error(gwtCreateCall, "Failed to resolve '" + requestedType + "' via deferred binding");
return null;
}
@@ -545,7 +566,7 @@
return instantiationExpressions.get(0);
}
return JPermutationDependentValue
- .createTypeRebind(program, gwtCreateCall.getSourceInfo(), reqType,
+ .createTypeRebind(program, gwtCreateCall.getSourceInfo(), requestedType,
answers, instantiationExpressions);
}
@@ -580,20 +601,6 @@
}
return new JNameOf(x.getSourceInfo(), program.getTypeJavaLangString(), (HasName) node);
}
-
- private JExpression handleMagicMethodCall(JMethodCall x, String targetSignature) {
- switch (targetSignature) {
- case GWT_CREATE:
- case OLD_GWT_CREATE:
- return createRebindExpression(x);
- case IMPL_GET_NAME_OF:
- return handleImplNameOf(x);
- case SYSTEM_GET_PROPERTY:
- case SYSTEM_GET_PROPERTY_WITH_DEFAULT:
- return handleSystemGetProperty(x);
- }
- throw new InternalCompilerException("Unknown magic method");
- }
}
private boolean isMultivaluedProperty(String propertyName) {
@@ -654,19 +661,9 @@
Sets.newLinkedHashSet(Arrays.asList(GWT_DEBUGGER_SHARED, GWT_DEBUGGER_CLIENT));
/**
- * Methods for which the call site must be replaced with magic AST nodes.
- */
- private static final Set<String> MAGIC_METHOD_CALLS = Sets.newLinkedHashSet(Arrays.asList(
- GWT_CREATE, GWT_DEBUGGER_SHARED, GWT_DEBUGGER_CLIENT, SYSTEM_GET_PROPERTY,
- SYSTEM_GET_PROPERTY_WITH_DEFAULT,
- OLD_GWT_CREATE, IMPL_GET_NAME_OF));
-
- /**
* Methods with magic implementations that the compiler must insert.
*/
- private static final Set<String> MAGIC_METHOD_IMPLS = Sets.newLinkedHashSet(Arrays.asList(
- GWT_IS_CLIENT, OLD_GWT_IS_CLIENT, GWT_IS_PROD_MODE, OLD_GWT_IS_PROD_MODE, GWT_IS_SCRIPT,
- OLD_GWT_IS_SCRIPT, CLASS_DESIRED_ASSERTION_STATUS, CLASS_IS_CLASS_METADATA_ENABLED));
+ private final Map<String, JBooleanLiteral> replacementValueByMagicMethodQualifiedName;
private final CompilationState compilationState;
private final Map<String, CompiledClass> compiledClassesByInternalName;
@@ -680,7 +677,6 @@
*/
private boolean errorsFound = false;
private final Set<CompilationUnit> unitsWithErrorsAlreadyReported = Sets.newIdentityHashSet();
- private final Map<String, JField> fieldMap = Maps.newHashMap();
/**
* The set of types currently known to be instantiable. Like
@@ -705,9 +701,9 @@
private final TreeLogger logger;
private final CompilerContext compilerContext;
- private final Map<String, JMethod> methodMap = Maps.newHashMap();
+ private final Map<String, JMember> resolvedMembersByQualifiedName = Maps.newHashMap();
private final JProgram program;
- private final RebindPermutationOracle rpo;
+ private final RebindPermutationOracle rebindPermutationOracle;
private final Set<String> reboundTypeNames = Sets.newHashSet();
/**
@@ -728,10 +724,11 @@
* A work queue of methods whose bodies we need to traverse. Prevents
* excessive stack use.
*/
- private final Queue<JMethod> todo = Lists.newLinkedList();
+ private final Queue<JMethod> methodsPending = Lists.newLinkedList();
- private final Set<String> virtualMethodsLive = Sets.newHashSet();
- private final Multimap<String, JMethod> virtualMethodsPending = LinkedListMultimap.create();
+ private final Set<String> liveVirtualMethods = Sets.newHashSet();
+ private final Multimap<String, JMethod> pendingVirtualMethodsBySignature =
+ LinkedListMultimap.create();
private NameBasedTypeLocator sourceNameBasedTypeLocator;
private NameBasedTypeLocator binaryNameBasedTypeLocator;
@@ -750,8 +747,8 @@
this.compilerContext = compilerContext;
this.program = program;
this.jsProgram = jsProgram;
- this.rpo = precompilationContext.getRebindPermutationOracle();
- this.compilationState = rpo.getCompilationState();
+ this.rebindPermutationOracle = precompilationContext.getRebindPermutationOracle();
+ this.compilationState = rebindPermutationOracle.getCompilationState();
this.compiledClassesByInternalName = compilationState.getClassFileMap();
this.compiledClassesBySourceName = compilationState.getClassFileMapBySource();
initializeNameBasedLocators();
@@ -761,6 +758,23 @@
minimalRebuildCache.computeAndClearStaleTypesCache(logger, program.typeOracle);
checkPreambleTypesStillFresh(logger);
}
+
+ // Magical methods are implemented by replacing their bodies during unification.
+ replacementValueByMagicMethodQualifiedName =
+ ImmutableMap.<String, JBooleanLiteral>builder()
+ .put(GWT_IS_CLIENT, JBooleanLiteral.TRUE)
+ .put(OLD_GWT_IS_CLIENT, JBooleanLiteral.TRUE)
+ .put(GWT_IS_PROD_MODE, JBooleanLiteral.TRUE)
+ .put(OLD_GWT_IS_PROD_MODE, JBooleanLiteral.TRUE)
+ .put(GWT_IS_SCRIPT, JBooleanLiteral.TRUE)
+ .put(OLD_GWT_IS_SCRIPT, JBooleanLiteral.TRUE)
+ .put(
+ CLASS_DESIRED_ASSERTION_STATUS,
+ JBooleanLiteral.get(compilerContext.getOptions().isEnableAssertions()))
+ .put(
+ CLASS_IS_CLASS_METADATA_ENABLED,
+ JBooleanLiteral.get(!compilerContext.getOptions().isClassMetadataDisabled()))
+ .build();
}
public void addRootTypes(Collection<String> rootTypeSourceNames) {
@@ -788,6 +802,7 @@
if (errorsFound) {
throw new UnableToCompleteException();
}
+ JavaAstVerifier.assertProgramIsConsistent(program);
}
/**
@@ -812,7 +827,6 @@
if (rootType == null) {
continue;
}
-
rootTypeBinaryNames.add(rootType.getName());
if (rootType.hasJsInteropEntryPoints()) {
fullFlowIntoType(rootType);
@@ -847,8 +861,8 @@
instantiate(program.getTypeJavaLangString());
// ControlFlowAnalyzer.rescueByConcat().
flowInto(program.getIndexedMethod(RuntimeConstants.OBJECT_TO_STRING));
- mapApi(program.getTypeJavaLangString());
- flowInto(methodMap.get("java.lang.String.valueOf(C)Ljava/lang/String;"));
+ flowInto((JMethod)
+ resolvedMembersByQualifiedName.get("java.lang.String.valueOf(C)Ljava/lang/String;"));
// FixAssignmentsToUnboxOrCast
AutoboxUtils autoboxUtils = new AutoboxUtils(program);
@@ -904,7 +918,7 @@
// pruned.
for (JMethod method : newStubMethods) {
if (instantiatedTypes.contains(method.getEnclosingType()) &&
- virtualMethodsLive.contains(method.getSignature())) {
+ liveVirtualMethods.contains(method.getSignature())) {
liveFieldsAndMethods.add(method);
}
}
@@ -917,6 +931,7 @@
// Already logged.
throw new UnableToCompleteException();
}
+ JavaAstVerifier.assertProgramIsConsistent(program);
}
/**
@@ -1000,16 +1015,17 @@
// TODO(zundel): ask for a recompile if deserialization fails?
List<JDeclaredType> types = unit.getTypes();
assert containsAllTypes(unit, types);
- for (JDeclaredType t : types) {
- program.addType(t);
+ for (JDeclaredType type : types) {
+ program.addType(type);
// If we're compiling per file and we already have currently valid output for this type.
- if (incrementalCompile && !needsNewJs(t)) {
+ if (incrementalCompile && !needsNewJs(type)) {
// Then make sure we don't output new Js for this type.
- program.addReferenceOnlyType(t);
+ program.addReferenceOnlyType(type);
}
}
- for (JDeclaredType t : types) {
- resolveType(t);
+ for (JDeclaredType type : types) {
+ resolveType(type);
+ processType(type);
}
// When compiling per file.
if (incrementalCompile) {
@@ -1090,13 +1106,17 @@
}
private void error(JNode x, String errorMessage) {
+ error(x.getSourceInfo(), errorMessage);
+ }
+
+ private void error(SourceInfo sourceInfo, String errorMessage) {
errorsFound = true;
TreeLogger branch =
logger
- .branch(TreeLogger.ERROR, "Errors in '" + x.getSourceInfo().getFileName() + "'", null);
+ .branch(TreeLogger.ERROR, "Errors in '" + sourceInfo.getFileName() + "'", null);
// Append 'Line #: msg' to the error message.
StringBuilder msgBuf = new StringBuilder();
- int line = x.getSourceInfo().getStartLine();
+ int line = sourceInfo.getStartLine();
if (line > 0) {
msgBuf.append("Line ");
msgBuf.append(line);
@@ -1169,36 +1189,29 @@
}
liveFieldsAndMethods.add(method);
- JType originalReturnType = translate(method.getOriginalReturnType());
- List<JType> originalParamTypes =
- Lists.newArrayListWithCapacity(method.getOriginalParamTypes().size());
- for (JType originalParamType : method.getOriginalParamTypes()) {
- originalParamTypes.add(translate(originalParamType));
- }
- JType returnType = translate(method.getType());
- List<JClassType> thrownExceptions =
- Lists.newArrayListWithCapacity(method.getThrownExceptions().size());
- for (JClassType thrownException : method.getThrownExceptions()) {
- thrownExceptions.add(translate(thrownException));
- }
- method.resolve(originalReturnType, originalParamTypes, returnType, thrownExceptions);
+
+ method.resolve(
+ translate(method.getOriginalReturnType()),
+ translate(method.getOriginalParamTypes()),
+ translate(method.getType()),
+ translate(method.getThrownExceptions()));
+
if (method.isStatic()) {
staticInitialize(method.getEnclosingType());
} else if (method.canBePolymorphic()) {
String signature = method.getSignature();
- if (!virtualMethodsLive.contains(signature)) {
- virtualMethodsLive.add(signature);
- Iterable<JMethod> pending = virtualMethodsPending.removeAll(signature);
- for (JMethod p : pending) {
- assert instantiatedTypes.contains(p.getEnclosingType());
- flowInto(p);
+ if (!liveVirtualMethods.contains(signature)) {
+ liveVirtualMethods.add(signature);
+ for (JMethod pendingMethod : pendingVirtualMethodsBySignature.removeAll(signature)) {
+ assert instantiatedTypes.contains(pendingMethod.getEnclosingType());
+ flowInto(pendingMethod);
}
}
}
resolveSpecialization(method);
- // Queue up visit / resolve on the body.
- todo.add(method);
+ // Queue up the method to resolve the method body.
+ methodsPending.add(method);
}
private void resolveSpecialization(JMethod method) {
@@ -1207,7 +1220,6 @@
return;
}
Specialization specialization = method.getSpecialization();
- List<JType> resolvedParams = Lists.newArrayList();
if (specialization.getParams() == null) {
logger.log(Type.ERROR, "Missing 'params' attribute at @SpecializeMethod for method "
+ method.getQualifiedName());
@@ -1215,26 +1227,25 @@
return;
}
- for (JType param : specialization.getParams()) {
- resolvedParams.add(translate(param));
- }
+ List<JType> resolvedParams = translate(specialization.getParams());
+
JType resolvedReturn = translate(specialization.getReturns());
String targetMethodSignature = JjsUtils.computeSignature(
specialization.getTarget(), resolvedParams, resolvedReturn, false);
- JMethod targetMethod = translate(JMethod.getExternalizedMethod(
- method.getEnclosingType().getName(), targetMethodSignature, false));
+ JMethod targetMethod = JMethod.getExternalizedMethod(
+ method.getEnclosingType().getName(), targetMethodSignature, false);
+ JMethod resolvedTargetMethod = translate(method.getSourceInfo(), targetMethod);
- if (targetMethod == null) {
- errorsFound = true;
- logger.log(Type.ERROR, "Unable to locate @SpecializeMethod target "
+ if (resolvedTargetMethod.isExternal()) {
+ error(method.getSourceInfo(), "Unable to locate @SpecializeMethod target "
+ targetMethodSignature + " for method " + method.getQualifiedName());
return;
}
- flowInto(targetMethod);
- specialization.resolve(resolvedParams, resolvedReturn, targetMethod);
+ flowInto(resolvedTargetMethod);
+ specialization.resolve(resolvedParams, resolvedReturn, resolvedTargetMethod);
}
public NameBasedTypeLocator getSourceNameBasedTypeLocator() {
@@ -1344,11 +1355,11 @@
}
String signature = method.getSignature();
- if (virtualMethodsLive.contains(signature)) {
- assert !virtualMethodsPending.containsKey(signature);
+ if (liveVirtualMethods.contains(signature)) {
+ assert !pendingVirtualMethodsBySignature.containsKey(signature);
flowInto(method);
} else {
- virtualMethodsPending.put(signature, method);
+ pendingVirtualMethodsBySignature.put(signature, method);
}
}
@@ -1380,40 +1391,28 @@
*/
private void mainLoop() {
UnifyVisitor visitor = new UnifyVisitor();
- while (!todo.isEmpty()) {
- visitor.accept(todo.poll());
+ while (!methodsPending.isEmpty()) {
+ visitor.accept(methodsPending.poll());
}
}
- private void mapApi(JDeclaredType type) {
+ private void processType(JDeclaredType type) {
assert !type.isExternal();
- for (JField field : type.getFields()) {
- String sig = type.getName() + '.' + field.getSignature();
- fieldMap.put(sig, field);
+ for (JMember member : type.getMembers()) {
+ String qualifiedName = member.getQualifiedName();
+ resolvedMembersByQualifiedName.put(qualifiedName, member);
+ replaceMagicMethodBodies(member);
}
- for (JMethod method : type.getMethods()) {
- String methodSignature = method.getQualifiedName();
- methodMap.put(methodSignature, method);
- if (!MAGIC_METHOD_IMPLS.contains(methodSignature)) {
- continue;
- }
- if (methodSignature.startsWith("com.google.gwt.core.client.GWT.")
- || methodSignature.startsWith("com.google.gwt.core.shared.GWT.")) {
- // GWT.isClient, GWT.isScript, GWT.isProdMode all true.
- JjsUtils.replaceMethodBody(method, JBooleanLiteral.TRUE);
- continue;
- }
- assert methodSignature.startsWith("java.lang.Class.");
- if (CLASS_DESIRED_ASSERTION_STATUS.equals(methodSignature)) {
- JjsUtils.replaceMethodBody(method,
- JBooleanLiteral.get(compilerContext.getOptions().isEnableAssertions()));
- } else if (CLASS_IS_CLASS_METADATA_ENABLED.equals(methodSignature)) {
- JjsUtils.replaceMethodBody(method,
- JBooleanLiteral.get(!compilerContext.getOptions().isClassMetadataDisabled()));
- } else {
- assert false;
- }
+ }
+
+ private void replaceMagicMethodBodies(JMember member) {
+ JExpression replacementExpression =
+ replacementValueByMagicMethodQualifiedName.get(member.getQualifiedName());
+ if (replacementExpression == null) {
+ // Not a special method that needs replacement
+ return;
}
+ JjsUtils.replaceMethodBody((JMethod) member, replacementExpression);
}
/**
@@ -1512,95 +1511,47 @@
}
/**
- * Replaces an external (stub) reference node to a particular class by the actual AST node if
- * necessary.
- */
- private JClassType translate(JClassType type) {
- return (JClassType) translate((JDeclaredType) type);
- }
-
- /**
* Replaces an external (stub) reference node to a particular type by the actual AST node if
* necessary.
*/
- private JDeclaredType translate(JDeclaredType type) {
+ private <T extends JDeclaredType> T translate(T type) {
if (!type.isExternal()) {
return type;
}
- String typeName = type.getName();
- JDeclaredType newType = internalFindType(typeName, binaryNameBasedTypeLocator, true);
- if (newType == null) {
+
+ T resolvedType = (T) internalFindType(type.getName(), binaryNameBasedTypeLocator, true);
+ if (resolvedType == null) {
assert errorsFound;
return type;
}
- assert !newType.isExternal();
- return newType;
+ assert !resolvedType.isExternal();
+ return resolvedType;
}
/**
- * Replaces an external (stub) reference node to a particular field by the actual AST node if
+ * Replaces an external (stub) reference node to a particular member by the actual AST node if
* necessary.
*/
- private JField translate(JField field) {
- if (!field.isExternal()) {
- return field;
+ private <T extends JMember> T translate(SourceInfo sourceInfo, T member) {
+ if (!member.isExternal()) {
+ return member;
}
- JDeclaredType enclosingType = field.getEnclosingType();
- String sig = enclosingType.getName() + '.' + field.getSignature();
- JField newField = fieldMap.get(sig);
- if (newField != null) {
- return newField;
- }
-
- enclosingType = translate(enclosingType);
+ JDeclaredType enclosingType = translate(member.getEnclosingType());
if (enclosingType.isExternal()) {
assert errorsFound;
- return field;
- }
- mapApi(enclosingType);
-
- // Now the field should be there.
- field = fieldMap.get(sig);
- if (field == null) {
- // TODO: error logging
- throw new NoSuchFieldError(sig);
+ return member;
}
- assert !field.isExternal();
- return field;
- }
-
- /**
- * Replaces an external (stub) reference node to a particular method by the actual AST node if
- * necessary.
- */
- private JMethod translate(JMethod method) {
- if (!method.isExternal()) {
- return method;
+ String qualifiedName = member.getQualifiedName();
+ T resolvedMember = (T) resolvedMembersByQualifiedName.get(qualifiedName);
+ if (resolvedMember == null) {
+ error(sourceInfo, "Reference to '" + qualifiedName + "' could not be resolved");
+ return member;
}
- String sig = method.getQualifiedName();
- JMethod newMethod = methodMap.get(sig);
- if (newMethod != null) {
- return newMethod;
- }
-
- JDeclaredType enclosingType = translate(method.getEnclosingType());
- if (enclosingType.isExternal()) {
- assert errorsFound;
- return method;
- }
- mapApi(enclosingType);
-
- // Now the method should be there.
- method = methodMap.get(sig);
- if (method == null) {
- // TODO: error logging
- throw new NoSuchMethodError(sig);
- }
- assert !method.isExternal();
- return method;
+ assert !resolvedMember.isExternal();
+ return resolvedMember;
}
/**
@@ -1632,4 +1583,12 @@
}
return translate((JReferenceType) type);
}
+
+ private <T extends JType> List<T> translate(List<T> types) {
+ List<T> translatedTypes = Lists.newArrayListWithCapacity(types.size());
+ for (T type : types) {
+ translatedTypes.add((T) translate(type));
+ }
+ return translatedTypes;
+ }
}