Fixes several potential crashes when dealing with units that have serious errors.
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2897 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/javac/CompilationState.java b/dev/core/src/com/google/gwt/dev/javac/CompilationState.java
index bdf9c2c..846c78c 100644
--- a/dev/core/src/com/google/gwt/dev/javac/CompilationState.java
+++ b/dev/core/src/com/google/gwt/dev/javac/CompilationState.java
@@ -22,6 +22,9 @@
import com.google.gwt.dev.javac.impl.SourceFileCompilationUnit;
import com.google.gwt.dev.js.ast.JsProgram;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ClassFile;
+
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -67,10 +70,29 @@
*/
public void compile(TreeLogger logger) throws UnableToCompleteException {
JdtCompiler.compile(getCompilationUnits());
+ Set<String> validBinaryTypeNames = new HashSet<String>();
+ for (CompilationUnit unit : getCompilationUnits()) {
+ switch (unit.getState()) {
+ case COMPILED:
+ for (ClassFile classFile : unit.getJdtCud().compilationResult().getClassFiles()) {
+ char[] binaryName = CharOperation.concatWith(
+ classFile.getCompoundName(), '/');
+ validBinaryTypeNames.add(String.valueOf(binaryName));
+ }
+ break;
+ case CHECKED:
+ for (CompiledClass compiledClass : unit.getCompiledClasses()) {
+ validBinaryTypeNames.add(compiledClass.getBinaryName());
+ }
+ break;
+ }
+ }
CompilationUnitInvalidator.validateCompilationUnits(getCompilationUnits(),
- getClassFileMap());
+ validBinaryTypeNames);
- // TODO: Move into validation & log errors?
+ CompilationUnitInvalidator.invalidateUnitsWithErrors(logger,
+ getCompilationUnits());
+
JsniCollector.collectJsniMethods(logger, getCompilationUnits(),
new JsProgram());
diff --git a/dev/core/src/com/google/gwt/dev/javac/CompilationUnitInvalidator.java b/dev/core/src/com/google/gwt/dev/javac/CompilationUnitInvalidator.java
index 8951234..9c01b74 100644
--- a/dev/core/src/com/google/gwt/dev/javac/CompilationUnitInvalidator.java
+++ b/dev/core/src/com/google/gwt/dev/javac/CompilationUnitInvalidator.java
@@ -24,11 +24,9 @@
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.Map;
+import java.util.Iterator;
import java.util.Set;
-import java.util.Map.Entry;
/**
* Helper class to invalidate units in a set based on errors or references to
@@ -45,11 +43,10 @@
// Start by removing units with a known problem.
boolean anyRemoved = false;
for (CompilationUnit unit : units) {
- CompilationUnitDeclaration cud = unit.getJdtCud();
- if (cud == null) {
+ if (unit.getState() != State.COMPILED) {
continue;
}
- CompilationResult result = cud.compilationResult();
+ CompilationResult result = unit.getJdtCud().compilationResult();
if (result.hasErrors()) {
anyRemoved = true;
@@ -92,63 +89,50 @@
public static void invalidateUnitsWithInvalidRefs(TreeLogger logger,
Set<CompilationUnit> units) {
- logger = logger.branch(TreeLogger.TRACE, "Removing invalidate units");
+ logger = logger.branch(TreeLogger.TRACE, "Removing invalidated units");
- // Map all units by file name.
- Map<String, CompilationUnit> unitsByFileName = new HashMap<String, CompilationUnit>();
+ // Assume all compiled units are valid at first.
+ boolean changed;
+ Set<CompilationUnit> validUnits = new HashSet<CompilationUnit>();
for (CompilationUnit unit : units) {
- unitsByFileName.put(unit.getDisplayLocation(), unit);
+ if (unit.isCompiled()) {
+ validUnits.add(unit);
+ }
}
- // First, compute a map from all targets all referents.
- Map<CompilationUnit, Set<CompilationUnit>> refTargetToReferents = new HashMap<CompilationUnit, Set<CompilationUnit>>();
- for (CompilationUnit referentUnit : units) {
- if (referentUnit.isCompiled()) {
- Set<String> fileNameRefs = referentUnit.getFileNameRefs();
- for (String fileNameRef : fileNameRefs) {
- CompilationUnit targetUnit = unitsByFileName.get(fileNameRef);
- if (targetUnit != null) {
- Set<CompilationUnit> referents = refTargetToReferents.get(targetUnit);
- if (referents == null) {
- referents = new HashSet<CompilationUnit>();
- refTargetToReferents.put(targetUnit, referents);
+ do {
+ changed = false;
+ Set<String> validRefs = new HashSet<String>();
+ for (CompilationUnit unit : validUnits) {
+ validRefs.add(unit.getDisplayLocation());
+ }
+ for (Iterator<CompilationUnit> it = validUnits.iterator(); it.hasNext();) {
+ CompilationUnit unit = it.next();
+ TreeLogger branch = null;
+ for (String ref : unit.getFileNameRefs()) {
+ if (!validRefs.contains(ref)) {
+ if (branch == null) {
+ branch = logger.branch(TreeLogger.WARN, "Compilation unit '"
+ + unit + "' is removed due to invalid reference(s):");
+ it.remove();
+ changed = true;
+ unit.setState(State.FRESH);
}
- // Add myself as a referent.
- referents.add(referentUnit);
+ branch.log(TreeLogger.WARN, ref);
}
}
}
- }
-
- // Now use the map to transitively blow away invalid units.
- for (Entry<CompilationUnit, Set<CompilationUnit>> entry : refTargetToReferents.entrySet()) {
- CompilationUnit maybeInvalidUnit = entry.getKey();
- if (!maybeInvalidUnit.isCompiled()) {
- // Invalidate all dependent units.
- Set<CompilationUnit> invalidReferentUnits = entry.getValue();
- TreeLogger branch = logger.branch(TreeLogger.TRACE,
- "Compilation unit '" + maybeInvalidUnit + "' is invalid");
- State why = maybeInvalidUnit.getState();
- for (CompilationUnit invalidReferentUnit : invalidReferentUnits) {
- if (invalidReferentUnit.isCompiled()) {
- // Set it to the same state as the unit it depends on.
- invalidReferentUnit.setState(why);
- branch.log(TreeLogger.TRACE, "Removing dependent unit '"
- + invalidReferentUnit + "'");
- }
- }
- }
- }
+ } while (changed);
}
public static void validateCompilationUnits(Set<CompilationUnit> units,
- Map<String, CompiledClass> compiledClasses) {
+ Set<String> validBinaryTypeNames) {
for (CompilationUnit unit : units) {
if (unit.getState() == State.COMPILED) {
CompilationUnitDeclaration jdtCud = unit.getJdtCud();
JSORestrictionsChecker.check(jdtCud);
LongFromJSNIChecker.check(jdtCud);
BinaryTypeReferenceRestrictionsChecker.check(jdtCud,
- compiledClasses.keySet());
+ validBinaryTypeNames);
}
}
}
diff --git a/dev/core/test/com/google/gwt/dev/javac/TypeOracleTestingUtils.java b/dev/core/test/com/google/gwt/dev/javac/TypeOracleTestingUtils.java
index dd71e22..2a08394 100644
--- a/dev/core/test/com/google/gwt/dev/javac/TypeOracleTestingUtils.java
+++ b/dev/core/test/com/google/gwt/dev/javac/TypeOracleTestingUtils.java
@@ -21,9 +21,7 @@
import com.google.gwt.dev.javac.impl.SourceFileCompilationUnit;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.Map;
import java.util.Set;
/**
@@ -52,13 +50,14 @@
public static TypeOracle buildTypeOracle(TreeLogger logger,
Set<CompilationUnit> units) throws UnableToCompleteException {
JdtCompiler.compile(units);
- Map<String, CompiledClass> classMap = new HashMap<String, CompiledClass>();
+ Set<String> validBinaryTypeNames = new HashSet<String>();
for (CompilationUnit unit : units) {
for (CompiledClass compiledClass : unit.getCompiledClasses()) {
- classMap.put(compiledClass.getBinaryName(), compiledClass);
+ validBinaryTypeNames.add(compiledClass.getBinaryName());
}
}
- CompilationUnitInvalidator.validateCompilationUnits(units, classMap);
+ CompilationUnitInvalidator.validateCompilationUnits(units,
+ validBinaryTypeNames);
CompilationUnitInvalidator.invalidateUnitsWithErrors(logger, units);
TypeOracleMediator mediator = new TypeOracleMediator();
mediator.refresh(logger, units);