Adds a -validateOnly flag to the compiler, which ensures that all code on the source path is translatable and there are no errors in deferred binding, but does not produce any output.
Suggested by: bruce
Review by: bobv
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1636 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/GWTCompiler.java b/dev/core/src/com/google/gwt/dev/GWTCompiler.java
index 49d031e..55935c5 100644
--- a/dev/core/src/com/google/gwt/dev/GWTCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/GWTCompiler.java
@@ -18,6 +18,7 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.TreeLogger.Type;
+import com.google.gwt.core.ext.typeinfo.CompilationUnitProvider;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.cfg.Compilation;
@@ -49,6 +50,7 @@
import com.google.gwt.dev.util.xml.ReflectiveParser;
import com.google.gwt.util.tools.ArgHandlerDisableAggressiveOptimization;
import com.google.gwt.util.tools.ArgHandlerExtra;
+import com.google.gwt.util.tools.ArgHandlerFlag;
import com.google.gwt.util.tools.ArgHandlerOutDir;
import com.google.gwt.util.tools.ToolBase;
import com.google.gwt.util.tools.Utility;
@@ -104,6 +106,25 @@
}
/**
+ * Argument handler for making the compiler run in "validation" mode.
+ */
+ private class ArgHandlerValidateOnlyFlag extends ArgHandlerFlag {
+
+ public String getPurpose() {
+ return "Validate all source code, but do not compile";
+ }
+
+ public String getTag() {
+ return "-validateOnly";
+ }
+
+ public boolean setFlag() {
+ validateOnly = true;
+ return true;
+ }
+ }
+
+ /**
* Used to smartly deal with rebind across the production of an entire
* permutation, including cache checking and recording the inputs and outputs
* into a {@link Compilation}.
@@ -225,6 +246,17 @@
System.exit(1);
}
+ /**
+ * Returns the fully-qualified main type name of a compilation unit.
+ */
+ private static String makeTypeName(CompilationUnitProvider cup) {
+ if (cup.getPackageName().length() > 0) {
+ return cup.getPackageName() + "." + cup.getMainTypeName();
+ } else {
+ return cup.getMainTypeName();
+ }
+ }
+
private final CacheManager cacheManager;
private Compilations compilations = new Compilations();
@@ -267,6 +299,8 @@
private boolean useGuiLogger;
+ private boolean validateOnly = false;
+
public GWTCompiler() {
this(null);
}
@@ -327,6 +361,9 @@
return true;
}
});
+
+ registerHandler(new ArgHandlerValidateOnlyFlag());
+
this.cacheManager = cacheManager;
}
@@ -343,20 +380,43 @@
rules = module.getRules();
typeOracle = module.getTypeOracle(logger);
sourceOracle = new StandardSourceOracle(typeOracle);
- declEntryPts = module.getEntryPointTypeNames();
+ if (validateOnly) {
+ // Pretend that every single compilation unit is an entry point.
+ CompilationUnitProvider[] compilationUnits = module.getCompilationUnits();
+ declEntryPts = new String[compilationUnits.length];
+ for (int i = 0; i < compilationUnits.length; ++i) {
+ CompilationUnitProvider cup = compilationUnits[i];
+ declEntryPts[i] = makeTypeName(cup);
+ }
+ } else {
+ // Use the real entry points.
+ declEntryPts = module.getEntryPointTypeNames();
+ }
rebindPermOracle = new DistillerRebindPermutationOracle();
properties = module.getProperties();
perms = new PropertyPermutations(properties);
WebModeCompilerFrontEnd frontEnd = new WebModeCompilerFrontEnd(
sourceOracle, rebindPermOracle);
jjs = new JavaToJavaScriptCompiler(logger, frontEnd, declEntryPts,
- obfuscate, prettyNames, aggressivelyOptimize);
- initCompilations(logger);
+ obfuscate, prettyNames, aggressivelyOptimize, validateOnly);
+
+ if (!validateOnly) {
+ /*
+ * See what permutations already exist on disk and are up to date. Skip
+ * this for validation mode since we want to recompile everything.
+ */
+ initCompilations(logger);
+ }
// Compile for every permutation of properties.
//
SelectionScriptGenerator selGen = compilePermutations(logger);
+ if (validateOnly) {
+ logger.log(TreeLogger.INFO, "Validation succeeded", null);
+ return;
+ }
+
// Generate a selection script to pick the right permutation.
//
writeSelectionScripts(logger, selGen);
@@ -418,8 +478,11 @@
prettyNames = true;
}
+ /**
+ * Ensure the module has at least one entry point (except in validation mode).
+ */
private void checkModule(TreeLogger logger) throws UnableToCompleteException {
- if (module.getEntryPointTypeNames().length == 0) {
+ if (!validateOnly && module.getEntryPointTypeNames().length == 0) {
logger.log(TreeLogger.ERROR, "Module has no entry points defined", null);
throw new UnableToCompleteException();
}
@@ -427,8 +490,11 @@
private SelectionScriptGenerator compilePermutations(TreeLogger logger)
throws UnableToCompleteException {
- logger = logger.branch(TreeLogger.INFO, "Output will be written into "
- + outDir, null);
+ if (validateOnly) {
+ logger = logger.branch(TreeLogger.INFO, "Validating compilation", null);
+ } else {
+ logger = logger.branch(TreeLogger.INFO, "Compiling into " + outDir, null);
+ }
Property[] orderedProps = perms.getOrderedProperties();
SelectionScriptGenerator selGen = new SelectionScriptGenerator(module,
orderedProps);
@@ -718,6 +784,11 @@
// Create JavaScript.
//
String js = jjs.compile(logger, rebindOracle);
+ if (validateOnly) {
+ // We're done, there's no actual script to write.
+ assert (js == null);
+ return null;
+ }
// Create a wrapper and an unambiguous name for the file.
//
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 70cf5cc..405d244 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -70,6 +70,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.TreeSet;
/**
* Compiles the Java <code>JProgram</code> representation into its
@@ -203,17 +204,18 @@
private final boolean obfuscate;
private final boolean prettyNames;
private final Set<IProblem> problemSet = new HashSet<IProblem>();
+ private boolean validateOnly;
- public JavaToJavaScriptCompiler(final TreeLogger logger,
- final WebModeCompilerFrontEnd compiler, final String[] declEntryPts)
+ public JavaToJavaScriptCompiler(TreeLogger logger,
+ WebModeCompilerFrontEnd compiler, String[] declEntryPts)
throws UnableToCompleteException {
- this(logger, compiler, declEntryPts, true, false, true);
+ this(logger, compiler, declEntryPts, true, false, true, false);
}
- public JavaToJavaScriptCompiler(final TreeLogger logger,
- final WebModeCompilerFrontEnd compiler, final String[] declEntryPts,
- boolean obfuscate, boolean prettyNames, boolean aggressivelyOptimize)
- throws UnableToCompleteException {
+ public JavaToJavaScriptCompiler(TreeLogger logger,
+ WebModeCompilerFrontEnd compiler, String[] declEntryPts,
+ boolean obfuscate, boolean prettyNames, boolean aggressivelyOptimize,
+ boolean validateOnly) throws UnableToCompleteException {
if (declEntryPts.length == 0) {
throw new IllegalArgumentException("entry point(s) required");
@@ -231,32 +233,28 @@
//
this.obfuscate = obfuscate;
this.prettyNames = prettyNames;
+ this.validateOnly = validateOnly;
- // Find all the possible rebound entry points.
- //
- RebindPermutationOracle rpo = compiler.getRebindPermutationOracle();
- Set<String> allEntryPoints = new HashSet<String>();
- for (String element : declEntryPts) {
- String[] all = rpo.getAllPossibleRebindAnswers(logger, element);
- Util.addAll(allEntryPoints, all);
+ if (!validateOnly) {
+ // Find all the possible rebound entry points.
+ RebindPermutationOracle rpo = compiler.getRebindPermutationOracle();
+ Set<String> allEntryPoints = new TreeSet<String>();
+ for (String element : declEntryPts) {
+ String[] all = rpo.getAllPossibleRebindAnswers(logger, element);
+ Util.addAll(allEntryPoints, all);
+ }
+ allEntryPoints.add("com.google.gwt.lang.Array");
+ allEntryPoints.add("com.google.gwt.lang.Cast");
+ allEntryPoints.add("com.google.gwt.lang.Exceptions");
+ allEntryPoints.add("java.lang.Object");
+ allEntryPoints.add("java.lang.String");
+ allEntryPoints.add("java.lang.Iterable");
+ declEntryPts = allEntryPoints.toArray(new String[0]);
}
- String[] entryPts = Util.toStringArray(allEntryPoints);
-
- // Add intrinsics needed for code generation.
- //
- int k = entryPts.length;
- String[] seedTypeNames = new String[k + 6];
- System.arraycopy(entryPts, 0, seedTypeNames, 0, k);
- seedTypeNames[k++] = "com.google.gwt.lang.Array";
- seedTypeNames[k++] = "com.google.gwt.lang.Cast";
- seedTypeNames[k++] = "com.google.gwt.lang.Exceptions";
- seedTypeNames[k++] = "java.lang.Object";
- seedTypeNames[k++] = "java.lang.String";
- seedTypeNames[k++] = "java.lang.Iterable";
// Compile the source and get the compiler so we can get the parse tree
//
- goldenCuds = compiler.getCompilationUnitDeclarations(logger, seedTypeNames);
+ goldenCuds = compiler.getCompilationUnitDeclarations(logger, declEntryPts);
// Check for compilation problems. We don't log here because any problems
// found here will have already been logged by AbstractCompiler.
@@ -331,6 +329,11 @@
// Fix up GWT.create() into new operations
ReplaceRebinds.exec(jprogram);
+ if (validateOnly) {
+ // That's it, we're done.
+ return null;
+ }
+
// Rebind each entry point.
//
findEntryPoints(logger, rebindOracle, declEntryPoints, jprogram);