Error reporting for UnifyAst.
Report errors cleanly and don't blow up.
http://gwt-code-reviews.appspot.com/1451814/
Review by: zundel@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10314 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/CompileTaskRunner.java b/dev/core/src/com/google/gwt/dev/CompileTaskRunner.java
index 60ba4ba..7c65f6e 100644
--- a/dev/core/src/com/google/gwt/dev/CompileTaskRunner.java
+++ b/dev/core/src/com/google/gwt/dev/CompileTaskRunner.java
@@ -17,6 +17,7 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.dev.javac.CompilationProblemReporter;
import com.google.gwt.dev.shell.log.SwingLoggerPanel;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
@@ -88,7 +89,7 @@
} catch (UnableToCompleteException e) {
// Assume logged.
} catch (Throwable e) {
- logger.log(TreeLogger.ERROR, "Unexpected", e);
+ CompilationProblemReporter.logAndTranslateException(logger, e);
}
return false;
}
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 b29358a..fff563d 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
@@ -17,6 +17,7 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.dev.javac.CompilationProblemReporter;
import com.google.gwt.dev.javac.CompilationUnit;
import com.google.gwt.dev.javac.CompiledClass;
import com.google.gwt.dev.jdt.RebindPermutationOracle;
@@ -70,6 +71,7 @@
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsRootScope;
import com.google.gwt.dev.util.JsniRef;
+import com.google.gwt.dev.util.Name;
import com.google.gwt.dev.util.Name.BinaryName;
import com.google.gwt.dev.util.Name.InternalName;
import com.google.gwt.dev.util.collect.IdentityHashSet;
@@ -189,7 +191,7 @@
@Override
public void endVisit(JExpression x, Context ctx) {
- assert !x.getType().isExternal();
+ assert !x.getType().isExternal() || errorsFound;
}
@Override
@@ -226,7 +228,10 @@
public void endVisit(JMethodCall x, Context ctx) {
// Already resolved during visit().
JMethod target = x.getTarget();
- assert !target.isExternal();
+ if (target.isExternal()) {
+ assert errorsFound;
+ return;
+ }
if (magicMethodCalls.contains(target)) {
JExpression result = handleMagicMethodCall(x);
if (result == null) {
@@ -399,7 +404,9 @@
JsniRef ref = JsniRef.parse(stringValue);
if (ref != null) {
- searchForType(ref.className());
+ if (Name.isBinaryName(ref.className())) {
+ searchForType(ref.className());
+ }
node = JsniRefLookup.findJsniRefTarget(ref, program, new JsniRefLookup.ErrorReporter() {
public void reportError(String errMsg) {
error(x, errMsg);
@@ -463,6 +470,7 @@
private final Map<String, CompiledClass> classFileMap;
private boolean errorsFound = false;
+ private final Set<CompilationUnit> failedUnits = new IdentityHashSet<CompilationUnit>();
private final Map<String, JField> fieldMap = new HashMap<String, JField>();
/**
@@ -518,7 +526,7 @@
}
assimilateUnit(cc.getUnit());
type = program.getFromTypeMap(sourceTypeName);
- assert type != null;
+ assert type != null || errorsFound;
}
}
}
@@ -650,8 +658,16 @@
}
private void assimilateUnit(CompilationUnit unit) {
- // TODO: error checking.
+ if (unit.isError()) {
+ if (failedUnits.add(unit)) {
+ CompilationProblemReporter.reportErrors(logger, unit, false);
+ errorsFound = true;
+ }
+ return;
+ }
+ // 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);
}
@@ -712,6 +728,19 @@
}
}
+ private boolean containsAllTypes(CompilationUnit unit, List<JDeclaredType> types) {
+ Set<String> binaryTypeNames = new HashSet<String>();
+ for (JDeclaredType type : types) {
+ binaryTypeNames.add(type.getName());
+ }
+ for (CompiledClass cc : unit.getCompiledClasses()) {
+ if (!binaryTypeNames.contains(InternalName.toBinaryName(cc.getInternalName()))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
private void error(JNode x, String errorMessage) {
errorsFound = true;
TreeLogger branch =
@@ -730,7 +759,11 @@
}
private void flowInto(JField field) {
- if (field == JField.NULL_FIELD || field.isExternal()) {
+ if (field.isExternal()) {
+ assert errorsFound;
+ return;
+ }
+ if (field == JField.NULL_FIELD) {
return;
}
if (!liveFieldsAndMethods.contains(field)) {
@@ -743,7 +776,11 @@
}
private void flowInto(JMethod method) {
- if (method == JMethod.NULL_METHOD || method.isExternal()) {
+ if (method.isExternal()) {
+ assert errorsFound;
+ return;
+ }
+ if (method == JMethod.NULL_METHOD) {
return;
}
if (!liveFieldsAndMethods.contains(method)) {
@@ -794,7 +831,10 @@
}
private void instantiate(JDeclaredType type) {
- assert !type.isExternal();
+ if (type.isExternal()) {
+ assert errorsFound;
+ return;
+ }
if (!instantiatedTypes.contains(type)) {
instantiatedTypes.add(type);
if (type.getSuperClass() != null) {
@@ -909,13 +949,16 @@
}
assimilateUnit(cc.getUnit());
type = program.getFromTypeMap(binaryTypeName);
+ assert type != null || errorsFound;
}
return type;
}
private void staticInitialize(JDeclaredType type) {
- // Make sure the type is already resolved.
- assert !type.isExternal();
+ if (type.isExternal()) {
+ assert errorsFound;
+ return;
+ }
JMethod clinit = type.getMethods().get(0);
if (!liveFieldsAndMethods.contains(clinit)) {
flowInto(clinit);
@@ -953,13 +996,13 @@
String typeName = type.getName();
JDeclaredType newType = searchForType(typeName);
- if (newType != null) {
- assert !newType.isExternal();
- return newType;
+ if (newType == null) {
+ assert errorsFound;
+ return type;
}
- // Error condition, should be logged.
- errorsFound = true;
- return type;
+
+ assert !newType.isExternal();
+ return newType;
}
private JField translate(JField field) {
@@ -976,7 +1019,7 @@
enclosingType = translate(enclosingType);
if (enclosingType.isExternal()) {
- // Error condition, should be logged.
+ assert errorsFound;
return field;
}
mapApi(enclosingType);
@@ -1006,7 +1049,7 @@
enclosingType = translate(enclosingType);
if (enclosingType.isExternal()) {
- // Error condition, should be logged.
+ assert errorsFound;
return method;
}
mapApi(enclosingType);
diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/AdditionalTypeProviderDelegateTest.java b/dev/core/test/com/google/gwt/dev/jjs/impl/AdditionalTypeProviderDelegateTest.java
index 03c9120..1962d88 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/impl/AdditionalTypeProviderDelegateTest.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/impl/AdditionalTypeProviderDelegateTest.java
@@ -123,40 +123,6 @@
return code;
}
});
-
- // Create a source file containing a reference to an unknown class.
- sourceOracle.addOrReplace(new MockJavaResource("test.C") {
- @Override
- public CharSequence getContent() {
- StringBuffer code = new StringBuffer();
- code.append("package test;\n");
- code.append("import myPackage.UnknownClass;");
- code.append("class C {\n");
- code.append(" int func() {\n");
- // Reference an unknown class.
- code.append(" return myPackage.UnknownClass.getSmallNumber();\n");
- code.append(" }\n");
- code.append("}\n");
- return code;
- }
- });
-
- // Create a final example with a reference to an unknown class and no
- // import statement.
- sourceOracle.addOrReplace(new MockJavaResource("test.D") {
- @Override
- public CharSequence getContent() {
- StringBuffer code = new StringBuffer();
- code.append("package test;\n");
- code.append("class D {\n");
- code.append(" int func() {\n");
- // Reference an unknown class.
- code.append(" return myPackage.UnknownClass.getSmallNumber();\n");
- code.append(" }\n");
- code.append("}\n");
- return code;
- }
- });
}
public void testInsertedClass() throws UnableToCompleteException {
@@ -187,14 +153,46 @@
}
public void testUnknownClass() {
+ // Create a source file containing a reference to an unknown class.
+ sourceOracle.addOrReplace(new MockJavaResource("test.C") {
+ @Override
+ public CharSequence getContent() {
+ StringBuffer code = new StringBuffer();
+ code.append("package test;\n");
+ code.append("import myPackage.UnknownClass;");
+ code.append("class C {\n");
+ code.append(" int func() {\n");
+ // Reference an unknown class.
+ code.append(" return myPackage.UnknownClass.getSmallNumber();\n");
+ code.append(" }\n");
+ code.append("}\n");
+ return code;
+ }
+ });
try {
compileSnippet("void", "new test.C();");
fail("Shouldn't have compiled");
} catch (UnableToCompleteException expected) {
}
}
-
+
public void testUnknownClassNoImport() {
+ // Create a source file with a reference to an unknown class and no
+ // import statement.
+ sourceOracle.addOrReplace(new MockJavaResource("test.D") {
+ @Override
+ public CharSequence getContent() {
+ StringBuffer code = new StringBuffer();
+ code.append("package test;\n");
+ code.append("class D {\n");
+ code.append(" int func() {\n");
+ // Reference an unknown class.
+ code.append(" return myPackage.UnknownClass.getSmallNumber();\n");
+ code.append(" }\n");
+ code.append("}\n");
+ return code;
+ }
+ });
try {
compileSnippet("void", "new test.D();");
fail("Shouldn't have compiled");