From e38eff2ff08a90bf2a7335b300b571f0bccd4b1a Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Sun, 26 Apr 2026 20:25:09 -0500 Subject: [PATCH 01/12] LOts of debug logs, and a few possible steps that might fix this --- .../google/gwt/dev/MinimalRebuildCache.java | 107 +- .../gwt/dev/jjs/impl/GwtAstBuilder.java | 10 +- .../impl/ResolveRuntimeTypeReferences.java | 45 +- .../com/google/gwt/dev/jjs/impl/UnifyAst.java | 53 +- .../test/com/google/gwt/dev/CompilerTest.java | 2675 +++++++++-------- 5 files changed, 1695 insertions(+), 1195 deletions(-) diff --git a/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java b/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java index eea03414547..8cb0cd08afa 100644 --- a/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java +++ b/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java @@ -33,6 +33,7 @@ import com.google.gwt.thirdparty.guava.common.annotations.VisibleForTesting; import com.google.gwt.thirdparty.guava.common.base.Objects; import com.google.gwt.thirdparty.guava.common.base.Predicates; +import com.google.gwt.dev.jjs.ast.JDeclaredType; import com.google.gwt.thirdparty.guava.common.collect.HashMultimap; import com.google.gwt.thirdparty.guava.common.collect.ImmutableList; import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet; @@ -300,6 +301,30 @@ public Set computeAndClearStaleTypesCache(TreeLogger logger, JTypeOracle Set modifiedTypeNames = computeModifiedTypeNames(); + // DIAG: trace methodref types through the stale type computation pipeline + Set methodrefTypes = Sets.newHashSet(); + for (String name : modifiedTypeNames) { + if (name.contains("methodref")) { + methodrefTypes.add(name); + } + } + if (!methodrefTypes.isEmpty()) { + logger.log(TreeLogger.WARN, "DIAG: methodref types in modifiedTypeNames = " + methodrefTypes); + } else { + // Check if they exist in the nested types map at all + for (String cuName : modifiedCompilationUnitNames) { + Collection nested = nestedTypeNamesByUnitTypeName.get(cuName); + for (String n : nested) { + if (n.contains("methodref")) { + logger.log(TreeLogger.WARN, "DIAG: methodref nested type '" + n + + "' found under CU '" + cuName + "' but NOT in modifiedTypeNames"); + } + } + } + logger.log(TreeLogger.WARN, "DIAG: no methodref types in modifiedTypeNames. " + + "modifiedCompilationUnitNames = " + modifiedCompilationUnitNames); + } + // Accumulate the names of stale types resulting from some known type or resource modifications, // using various patterns (sub types, referencing types, etc). { @@ -321,16 +346,82 @@ public Set computeAndClearStaleTypesCache(TreeLogger logger, JTypeOracle // probably make GWTRPC output incompatible with a server anyway (and thus already forces a // restart). + // DIAG: check if methodref types are being removed as synthetic + Set methodrefInStale = Sets.newHashSet(); + for (String name : staleTypeNames) { + if (name.contains("methodref")) { + methodrefInStale.add(name); + } + } + if (!methodrefInStale.isEmpty()) { + logger.log(TreeLogger.WARN, "DIAG: methodref types in staleTypeNames before synthetic removal = " + + methodrefInStale); + logger.log(TreeLogger.WARN, "DIAG: SYNTHETIC_TYPE_NAMES contains any? = " + + !Sets.intersection(JProgram.SYNTHETIC_TYPE_NAMES, methodrefInStale).isEmpty()); + } + staleTypeNames.removeAll(JProgram.SYNTHETIC_TYPE_NAMES); } + // DIAG: check reachability filtering + Set methodrefBeforeReachability = Sets.newHashSet(); + for (String name : staleTypeNames) { + if (name.contains("methodref")) { + methodrefBeforeReachability.add(name); + } + } + /* * Filter for just those stale types that are actually reachable. Since if they're not reachable * we don't want to artificially traverse them and unnecessarily reveal dependency problems. And * if they have become reachable, since they're missing JS, they will already be fully traversed * when seen in Unify. + * + * However, directly modified types must always remain stale regardless of reachability. + * Types with no runtime type ID (e.g. classes used only for static method calls) are not + * tracked by RapidTypeAnalyzer and would be incorrectly filtered out, causing their cached JS + * to never be cleared and stale output to be reused. */ - copyCollection(filterUnreachableTypeNames(staleTypeNames), staleTypeNames); + Set filteredStaleTypeNames = filterUnreachableTypeNames(staleTypeNames); + filteredStaleTypeNames.addAll(modifiedTypeNames); + copyCollection(filteredStaleTypeNames, staleTypeNames); + + if (!methodrefBeforeReachability.isEmpty()) { + Set methodrefAfterReachability = Sets.newHashSet(); + for (String name : staleTypeNames) { + if (name.contains("methodref")) { + methodrefAfterReachability.add(name); + } + } + Set filteredOut = Sets.difference(methodrefBeforeReachability, methodrefAfterReachability); + if (!filteredOut.isEmpty()) { + logger.log(TreeLogger.WARN, "DIAG: methodref types FILTERED as unreachable = " + filteredOut); + logger.log(TreeLogger.WARN, "DIAG: lastReachableTypeNames contains them? "); + for (String name : filteredOut) { + logger.log(TreeLogger.WARN, "DIAG: " + name + " in lastReachableTypeNames = " + + lastReachableTypeNames.contains(name)); + } + } else { + logger.log(TreeLogger.WARN, "DIAG: methodref types survived reachability filter = " + + methodrefAfterReachability); + } + } + + // DIAG: log full stale types set and check for specific types + { + Set appTypes = Sets.newHashSet(); + for (String name : staleTypeNames) { + if (name.startsWith("com.foo.")) { + appTypes.add(name); + } + } + logger.log(TreeLogger.WARN, "DIAG: final staleTypeNames (com.foo.*) = " + appTypes); + logger.log(TreeLogger.WARN, "DIAG: Helper in staleTypeNames = " + staleTypeNames.contains("com.foo.Helper")); + logger.log(TreeLogger.WARN, "DIAG: Helper in lastReachableTypeNames = " + lastReachableTypeNames.contains("com.foo.Helper")); + // Check what references Helper + Collection refsToHelper = typeNamesByReferencingTypeName.get("com.foo.Helper"); + logger.log(TreeLogger.WARN, "DIAG: types referencing Helper = " + refsToHelper); + } // These log lines can be expensive. if (logger.isLoggable(TreeLogger.DEBUG)) { @@ -663,11 +754,25 @@ public void recordNestedTypeNamesPerType(CompilationUnit compilationUnit) { // For the root type in the compilation unit the source name and binary name are the same. String compilationUnitTypeName = compilationUnit.getTypeName(); + // Clean up the reverse map for old nested type names before removing them. + Collection oldNestedTypeNames = nestedTypeNamesByUnitTypeName.get(compilationUnitTypeName); + for (String oldNestedTypeName : oldNestedTypeNames) { + compilationUnitTypeNameByNestedTypeName.remove(oldNestedTypeName); + System.out.println("removed: " + oldNestedTypeName); + } nestedTypeNamesByUnitTypeName.removeAll(compilationUnitTypeName); for (CompiledClass compiledClass : compilationUnit.getCompiledClasses()) { String nestedTypeName = InternalName.toBinaryName(compiledClass.getInternalName()); recordNestedTypeName(compilationUnitTypeName, nestedTypeName); } + // Also record synthetic types created at the GWT AST level (e.g. lambda and method reference + // inner classes) that don't have corresponding CompiledClass entries from JDT. + for (JDeclaredType type : compilationUnit.getTypes()) { + String typeName = type.getName(); + if (!nestedTypeNamesByUnitTypeName.containsEntry(compilationUnitTypeName, typeName)) { + recordNestedTypeName(compilationUnitTypeName, typeName); + } + } } /** 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 eb8b806cc27..60b40b78f0e 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 @@ -1943,11 +1943,13 @@ public void endVisit(ReferenceExpression x, BlockScope blockScope) { JMethod referredMethod = typeMap.get(referredMethodBinding); boolean hasQualifier = hasQualifier(x); - // Constructors, overloading and generics means that the safest approach is to consider - // each different member reference as a different lambda implementation. + // Use a positional counter for the synthetic class name (like lambdas) rather than + // embedding the method selector. The counter alone ensures uniqueness within the + // enclosing class, and a stable name is needed for incremental compilation: if the + // method reference target changes, the synthetic class name must stay the same so that + // the MinimalRebuildCache and IntTypeMapper can correctly track and invalidate it. String lambdaImplementationClassShortName = - String.valueOf(nextReferenceExpressionId++) + "methodref$" - + (x.binding.isConstructor() ? "ctor" : String.valueOf(x.binding.selector)); + String.valueOf(nextReferenceExpressionId++) + "methodref"; List enclosingThisRefs = Lists.newArrayList(); // Create an inner class to hold the implementation of the interface diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ResolveRuntimeTypeReferences.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ResolveRuntimeTypeReferences.java index ffd620eff02..ce3dbaf0c3e 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/ResolveRuntimeTypeReferences.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ResolveRuntimeTypeReferences.java @@ -37,12 +37,15 @@ import com.google.gwt.thirdparty.guava.common.collect.Maps; import com.google.gwt.thirdparty.guava.common.collect.Multiset; import com.google.gwt.thirdparty.guava.common.collect.Multisets; +import com.google.gwt.thirdparty.guava.common.collect.Sets; import java.io.Serializable; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; /** * Assigns and replaces JRuntimeTypeReference nodes with a type id literal. @@ -77,6 +80,7 @@ public static class IntTypeMapper implements Serializable, TypeMapper typeIdByTypeName = Maps.newHashMap(); + private final List recycledIds = Lists.newArrayList(); private int nextAvailableId = 0; @Override @@ -89,6 +93,8 @@ public void copyFrom(TypeMapper that) { this.nextAvailableId = from.nextAvailableId; this.typeIdByTypeName.clear(); this.typeIdByTypeName.putAll(from.typeIdByTypeName); + this.recycledIds.clear(); + this.recycledIds.addAll(from.recycledIds); } @VisibleForTesting @@ -107,12 +113,33 @@ public JIntLiteral get(JType type) { public JIntLiteral getOrCreateTypeId(JType type) { String typeName = type.getName(); if (!typeIdByTypeName.containsKey(typeName)) { - int nextId = nextAvailableId++; + int nextId; + if (!recycledIds.isEmpty()) { + nextId = recycledIds.remove(recycledIds.size() - 1); + } else { + nextId = nextAvailableId++; + } typeIdByTypeName.put(typeName, nextId); } return get(type); } + + /** + * Removes entries for types not in the given set and makes their IDs available for reuse. + * Existing live type IDs are not changed, preserving cached JS validity. + */ + public void pruneDeadTypes(Set liveTypeNames) { + Iterator> it = typeIdByTypeName.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry entry = it.next(); + if (!liveTypeNames.contains(entry.getKey())) { + recycledIds.add(entry.getValue()); + it.remove(); + } + } + Collections.sort(recycledIds); + } } /** @@ -270,6 +297,22 @@ private void execImpl() { runtimeTypeCollector.accept(program.getTypeClassLiteralHolder()); // TODO(stalcup): each module should have it's own ClassLiteralHolder or some agreed upon // location that is default accessible to all. +// +// // Prune dead type entries from the IntTypeMapper before assigning types. Dead entries +// // accumulate when types are removed between incremental compiles (e.g. renamed synthetic +// // method reference types). Their IDs are recycled for new types, preventing ID drift that +// // would cause incremental output to diverge from fresh compile output. +// if (typeMapper instanceof IntTypeMapper) { +// Set liveTypeNames = Sets.newHashSet(); +// for (JReferenceType type : runtimeTypeCollector.typesRequiringRuntimeIds.elementSet()) { +// liveTypeNames.add(type.getName()); +// } +// // Include the special types that assignTypes always registers first. +// liveTypeNames.add(program.getJavaScriptObject().getName()); +// liveTypeNames.add(program.getTypeJavaLangObject().getName()); +// liveTypeNames.add(program.getTypeJavaLangString().getName()); +// ((IntTypeMapper) typeMapper).pruneDeadTypes(liveTypeNames); +// } assignTypes(runtimeTypeCollector.typesRequiringRuntimeIds); 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 c9bcd2ead4e..84f4ea83e72 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 @@ -928,6 +928,17 @@ public void exec() throws UnableToCompleteException { + "Generator has legitimately stopped creating these types."); } // Record the list of names of stale types that were processed, for test assertion purposes. + Set methodrefInFullFlow = Sets.newHashSet(); + for (String name : fullFlowTypes) { + if (name.contains("methodref")) { + methodrefInFullFlow.add(name); + } + } + if (methodrefInFullFlow.isEmpty()) { + logger.log(TreeLogger.WARN, "DIAG: setProcessedStaleTypeNames: NO methodref types in fullFlowTypes"); + } else { + logger.log(TreeLogger.WARN, "DIAG: setProcessedStaleTypeNames: methodref in fullFlowTypes = " + methodrefInFullFlow); + } minimalRebuildCache.setProcessedStaleTypeNames(fullFlowTypes); } @@ -962,16 +973,35 @@ public void exec() throws UnableToCompleteException { * temporarily ignored. */ private void fullFlowIntoRemainingStaleTypes() { - for (String staleTypeName : computeRemainingStaleTypeNames()) { + Set remaining = computeRemainingStaleTypeNames(); + logger.log(TreeLogger.WARN, "DIAG: fullFlowIntoRemainingStaleTypes remaining = " + remaining); + for (String name : remaining) { + if (name.contains("methodref")) { + logger.log(TreeLogger.WARN, "DIAG: fullFlowIntoRemainingStaleTypes considering: " + name); + } + } + for (String staleTypeName : remaining) { JDeclaredType staleType = internalFindType(staleTypeName, binaryNameBasedTypeLocator, false); if (staleType == null) { + if (staleTypeName.contains("methodref") || staleTypeName.contains("Helper")) { + logger.log(TreeLogger.WARN, "DIAG: fullFlowIntoRemainingStaleTypes: " + staleTypeName + + " NOT FOUND by internalFindType"); + } // The type is Generator output and so is not usually available in the list of types // provided from initial JDT compilation. The staleness marking process has already // handled this type by cascading the staleness marking onto the types that contain the // GWT.create() calls that process that create this type. continue; } + if (staleTypeName.contains("methodref")) { + logger.log(TreeLogger.WARN, "DIAG: fullFlowIntoRemainingStaleTypes: " + staleTypeName + + " FOUND, calling fullFlowIntoType"); + } + if (staleTypeName.contains("Helper")) { + logger.log(TreeLogger.WARN, "DIAG: fullFlowIntoRemainingStaleTypes: " + staleTypeName + + " FOUND, calling fullFlowIntoType"); + } // It's possible that the type was previously loaded before it was discovered to be stale (it // became stale as a result of a Generator execution). If this happens then the type will have // already been marked "reference only" in JProgram. This needs to be undone. @@ -1040,8 +1070,17 @@ private void assimilateSourceUnit(CompilationUnit unit, boolean reportErrors) { program.addType(type); // If we're compiling per file and we already have currently valid output for this type. if (incrementalCompile && !needsNewJs(type)) { + if (type.getName().contains("methodref") || type.getName().contains("Helper")) { + logger.log(TreeLogger.WARN, "DIAG: assimilateSourceUnit: " + type.getName() + + " has cached JS, marking reference-only"); + } // Then make sure we don't output new Js for this type. program.addReferenceOnlyType(type); + } else if (incrementalCompile) { + if (type.getName().contains("methodref") || type.getName().contains("Helper")) { + logger.log(TreeLogger.WARN, "DIAG: assimilateSourceUnit: " + type.getName() + + " needsNewJs=true (hasJs=" + minimalRebuildCache.hasJs(type.getName()) + ")"); + } } } for (JDeclaredType type : types) { @@ -1056,7 +1095,16 @@ private void assimilateSourceUnit(CompilationUnit unit, boolean reportErrors) { // Such a type won't have any cached JS and will need a full traversal to ensure it is // output (the full type with all fields and methods) as new JS. if (needsNewJs(type)) { + if (type.getName().contains("methodref")) { + logger.log(TreeLogger.WARN, "DIAG: assimilateSourceUnit: " + type.getName() + + " needsNewJs=true, calling fullFlowIntoType"); + } fullFlowIntoType(type); + } else { + if (type.getName().contains("methodref")) { + logger.log(TreeLogger.WARN, "DIAG: assimilateSourceUnit: " + type.getName() + + " needsNewJs=false, NOT calling fullFlowIntoType"); + } } } } @@ -1157,6 +1205,9 @@ private void fullFlowIntoType(JDeclaredType type) { if (fullFlowTypes.contains(typeName) || typeName.endsWith("package-info")) { return; } + if (typeName.contains("Helper") || typeName.contains("methodref")) { + logger.log(TreeLogger.WARN, "DIAG: fullFlowIntoType ADDING: " + typeName); + } // The traversal of this type will accumulate rebinder type to rebound type associations, but // the accumulation should start from scratch, so clear any existing associations that might // have been collected in previous compiles. diff --git a/dev/core/test/com/google/gwt/dev/CompilerTest.java b/dev/core/test/com/google/gwt/dev/CompilerTest.java index 751522c9614..85f04ddf8c7 100644 --- a/dev/core/test/com/google/gwt/dev/CompilerTest.java +++ b/dev/core/test/com/google/gwt/dev/CompilerTest.java @@ -864,1192 +864,1231 @@ protected void setUp() throws Exception { CauseShortRebindGenerator.runCount = 0; } - public void testAllValidArgs() { - CompilerOptionsImpl options = new CompilerOptionsImpl(); - Compiler.ArgProcessor argProcessor = new Compiler.ArgProcessor(options); - - assertProcessSuccess(argProcessor, new String[] {"-logLevel", "DEBUG", "-style", - "PRETTY", "-ea", "-gen", "myGen", - "-war", "myWar", "-workDir", "myWork", "-extra", "myExtra", "-incremental", - "-localWorkers", "2", "-sourceLevel", "1.8", "c.g.g.h.H", "my.Module"}); - - assertEquals(new File("myGen").getAbsoluteFile(), - options.getGenDir().getAbsoluteFile()); - assertEquals(new File("myWar"), options.getWarDir()); - assertEquals(new File("myWork"), options.getWorkDir()); - assertEquals(new File("myExtra"), options.getExtraDir()); - - assertEquals(2, options.getLocalWorkers()); - - assertEquals(TreeLogger.DEBUG, options.getLogLevel()); - assertEquals(JsOutputOption.PRETTY, options.getOutput()); - assertTrue(options.isEnableAssertions()); - assertTrue(options.shouldClusterSimilarFunctions()); - assertTrue(options.shouldInlineLiteralParameters()); - assertFalse(options.shouldOptimizeDataflow()); - assertTrue(options.shouldOrdinalizeEnums()); - assertTrue(options.shouldRemoveDuplicateFunctions()); - assertTrue(options.isIncrementalCompileEnabled()); - - assertEquals(SourceLevel.JAVA8, options.getSourceLevel()); - - assertEquals(2, options.getModuleNames().size()); - assertEquals("c.g.g.h.H", options.getModuleNames().get(0)); - assertEquals("my.Module", options.getModuleNames().get(1)); - } - - public void testDefaultArgs() { - CompilerOptionsImpl options = new CompilerOptionsImpl(); - Compiler.ArgProcessor argProcessor = new Compiler.ArgProcessor(options); - - assertProcessSuccess(argProcessor, new String[]{"c.g.g.h.H"}); - - assertEquals(null, options.getGenDir()); - assertEquals(new File("war").getAbsoluteFile(), - options.getWarDir().getAbsoluteFile()); - assertEquals(null, options.getWorkDir()); - assertEquals(null, options.getExtraDir()); - - assertEquals(TreeLogger.INFO, options.getLogLevel()); - assertEquals(JsOutputOption.OBFUSCATED, options.getOutput()); - assertFalse(options.isEnableAssertions()); - assertTrue(options.shouldClusterSimilarFunctions()); - assertTrue(options.shouldInlineLiteralParameters()); - assertFalse(options.shouldOptimizeDataflow()); - assertTrue(options.shouldOrdinalizeEnums()); - assertTrue(options.shouldRemoveDuplicateFunctions()); - assertFalse(options.isIncrementalCompileEnabled()); - - assertEquals(1, options.getLocalWorkers()); - - assertEquals(1, options.getModuleNames().size()); - assertEquals("c.g.g.h.H", options.getModuleNames().get(0)); - } - - public void testForbiddenArgs() { - CompilerOptionsImpl options = new CompilerOptionsImpl(); - Compiler.ArgProcessor argProcessor = new Compiler.ArgProcessor(options); - - assertProcessFailure(argProcessor, "Unknown argument", new String[]{"-out", "www"}); - assertProcessFailure(argProcessor, "Source level must be one of", - new String[]{"-sourceLevel", "ssss"}); - assertProcessFailure(argProcessor, "Source level must be one of", - new String[]{"-sourceLevel", "1.5"}); - } - - /** - * Tests ordering for emum {@link SourceLevel}. - */ - public void testSourceLevelOrdering() { - SourceLevel[] sourceLevels = SourceLevel.values(); - SourceLevel previousSourceLevel = sourceLevels[0]; - for (int i = 1; i < sourceLevels.length; i++) { - assertTrue(SourceLevel.versionCompare(previousSourceLevel.getStringValue(), - sourceLevels[i].getStringValue()) < 0); - previousSourceLevel = sourceLevels[i]; - } - } - - public void testSourceLevelSelection() { - assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.4")); - assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.5")); - assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.6")); - assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.6_26")); - - assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.7")); - assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.8")); - assertEquals(SourceLevel.JAVA9, SourceLevel.getBestMatchingVersion("9")); - assertEquals(SourceLevel.JAVA10, SourceLevel.getBestMatchingVersion("10")); - assertEquals(SourceLevel.JAVA11, SourceLevel.getBestMatchingVersion("11")); - - // not proper version strings => default to JAVA8. - assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.6u3")); - assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.6b3")); - assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.7b3")); - } - - public void testSourceLevelHighestVersion() { - assertEquals(SourceLevel.values()[SourceLevel.values().length - 1], SourceLevel.getHighest()); - } - - /** - * Verify that a compile with a @JsType at least compiles successfully. - */ - public void testGwtCreateJsTypeRebindResult() throws Exception { - CompilerOptions compilerOptions = new CompilerOptionsImpl(); - compileToJs(compilerOptions, createTempDir(), "com.foo.SimpleModule", - Lists.newArrayList(simpleModuleResource, gwtCreateEntryPointResource), - new MinimalRebuildCache(), emptySet, JsOutputOption.OBFUSCATED); - } - - /** - * Test that some lightly referenced interface through a @JsFunction is included in the output. - */ - public void testReferenceThroughJsFunction() throws Exception { - MockJavaResource someJsFunction = - JavaResourceBase.createMockJavaResource( - "com.foo.SomeJsFunction", - "package com.foo;", - "import jsinterop.annotations.JsFunction;", - "@JsFunction", - "public interface SomeJsFunction {", - " void m();", - "}"); - - MockJavaResource jsFunctionInterfaceImplementation = - JavaResourceBase.createMockJavaResource( - "com.foo.Impl", - "package com.foo;", - "public final class Impl implements SomeJsFunction {", - " public void m() { SomeInterface.class.getName(); } ", - "}"); - - MockJavaResource someInterface = - JavaResourceBase.createMockJavaResource( - "com.foo.SomeInterface", - "package com.foo;", - "public interface SomeInterface {", - "}"); - - MockJavaResource testEntryPoint = - JavaResourceBase.createMockJavaResource( - "com.foo.TestEntryPoint", - "package com.foo;", - "import com.google.gwt.core.client.EntryPoint;", - "public class TestEntryPoint implements EntryPoint {", - " private static native void f(SomeJsFunction f) /*-{}-*/;", - " public void onModuleLoad() {", - // Create Impl and pass it to JS but do not explicitly call m - " f(new Impl());", - " }", - "}"); - - MockResource moduleResource = - JavaResourceBase.createMockResource( - "com/foo/TestEntryPoint.gwt.xml", - "", - " ", - " ", - ""); - - CompilerOptions compilerOptions = new CompilerOptionsImpl(); - String js = compileToJs(compilerOptions, createTempDir(), testEntryPoint.getTypeName(), - Lists.newArrayList(moduleResource, testEntryPoint, someJsFunction, - jsFunctionInterfaceImplementation, someInterface), - new MinimalRebuildCache(), emptySet, JsOutputOption.DETAILED); - // Make sure the referenced class literals ends up being included in the resulting JS. - String classliteralHolderVarName = - JjsUtils.mangleMemberName("com.google.gwt.lang.ClassLiteralHolder", - JjsUtils.classLiteralFieldNameFromJavahTypeSignatureName( - JjsUtils.javahSignatureFromName(someInterface.getTypeName()))); - assertTrue(js.contains("var " + classliteralHolderVarName + " = ")); - } - - /** - * Tests that changing Js namespace name on an exported method comes out accurately. - * - *

An unrelated and non-updated @JsType is also included in each compile to verify that updated - * exports do not forget non-edited items in a recompile. - */ - public void testChangeJsNamespaceOnMethod() throws Exception { - CompilerOptions compilerOptions = new CompilerOptionsImpl(); - compilerOptions.setUseDetailedTypeIds(true); - compilerOptions.setGenerateJsInteropExports(true); - - MockJavaResource jsNamespaceFooResource = - JavaResourceBase.createMockJavaResource( - "com.foo.Foo", - "package com.foo;", - "import jsinterop.annotations.JsMethod;", - "import jsinterop.annotations.JsType;", - "@JsType public class Foo {", - " @JsMethod(namespace=\"spazz\") public static void doStaticBar() {}", - "}"); - - MockJavaResource regularFooResource = - JavaResourceBase.createMockJavaResource( - "com.foo.Foo", - "package com.foo;", - "import jsinterop.annotations.JsType;", - "@JsType public class Foo {", - " public static void doStaticBar() {}", - "}"); - - checkRecompiledModifiedApp( - compilerOptions, - "com.foo.SimpleModule", - Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), - regularFooResource, - jsNamespaceFooResource, - stringSet("com.foo.Bar", "com.foo.Foo"), - JsOutputOption.DETAILED); - } - - /** - * Tests that changing Js namespace on a class comes out accurately. - * - *

An unrelated and non-updated @JsType is also included in each compile to verify that updated - * exports do not forget non-edited items in a recompile. - */ - public void testChangeJsNamespaceOnClass() throws Exception { - CompilerOptions compilerOptions = new CompilerOptionsImpl(); - compilerOptions.setUseDetailedTypeIds(true); - compilerOptions.setGenerateJsInteropExports(true); - - MockJavaResource jsNamespaceFooResource = - JavaResourceBase.createMockJavaResource( - "com.foo.Foo", - "package com.foo;", - "import jsinterop.annotations.JsType;", - "@JsType(namespace=\"spazz\") public class Foo {", - " public static void doStaticBar() {}", - "}"); - - MockJavaResource regularFooResource = - JavaResourceBase.createMockJavaResource( - "com.foo.Foo", - "package com.foo;", - "import jsinterop.annotations.JsType;", - "@JsType public class Foo {", - " public static void doStaticBar() {}", - "}"); - - checkRecompiledModifiedApp( - compilerOptions, - "com.foo.SimpleModule", - Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), - regularFooResource, - jsNamespaceFooResource, - stringSet("com.foo.Bar", "com.foo.Foo"), - JsOutputOption.DETAILED); - } - - /** - * Tests that changing @JsFunction name on an interface comes out accurately. - * - *

An unrelated and non-updated @JsType is also included in each compile to verify that updated - * exports do not forget non-edited items in a recompile. - */ - public void testChangeJsFunction() throws Exception { - CompilerOptions compilerOptions = new CompilerOptionsImpl(); - compilerOptions.setUseDetailedTypeIds(true); - compilerOptions.setGenerateJsInteropExports(true); - - MockJavaResource jsFunctionIFooResource = - JavaResourceBase.createMockJavaResource( - "com.foo.IFoo", - "package com.foo;", - "import jsinterop.annotations.JsFunction;", - "@JsFunction public interface IFoo {", - " int foo(int x);", - "}"); - - MockJavaResource regularIFooResource = - JavaResourceBase.createMockJavaResource( - "com.foo.IFoo", - "package com.foo;", - "public interface IFoo {", - " int foo(int x);", - "}"); - - MockJavaResource fooResource = - JavaResourceBase.createMockJavaResource( - "com.foo.Foo", - "package com.foo;", - "public final class Foo implements IFoo {", - " @Override public int foo(int x) { return 0; }", - "}"); - - checkRecompiledModifiedApp( - compilerOptions, - "com.foo.SimpleModule", - Lists.newArrayList( - simpleModuleResource, entryPointResourceForFoo, fooResource, jsTypeBarResource), - regularIFooResource, - jsFunctionIFooResource, - stringSet("com.foo.Bar", "com.foo.Foo", "com.foo.IFoo", "com.foo.TestEntryPoint"), - JsOutputOption.DETAILED); - } - - /** - * Tests that toggling JsProperty methods in an interface comes out accurately. - * - *

An unrelated and non-updated @JsType is also included in each compile to verify that updated - * exports do not forget non-edited items in a recompile. - */ - public void testChangeJsProperty() throws Exception { - CompilerOptions compilerOptions = new CompilerOptionsImpl(); - compilerOptions.setUseDetailedTypeIds(true); - compilerOptions.setGenerateJsInteropExports(true); - - MockJavaResource jsPropertyIFooResource = - JavaResourceBase.createMockJavaResource( - "com.foo.IFoo", - "package com.foo;", - "import jsinterop.annotations.JsProperty;", - "import jsinterop.annotations.JsType;", - "@JsType public interface IFoo {", - " @JsProperty int getX();", - " @JsProperty int getY();", - "}"); - - MockJavaResource regularIFooResource = - JavaResourceBase.createMockJavaResource( - "com.foo.IFoo", - "package com.foo;", - "import jsinterop.annotations.JsType;", - "@JsType public interface IFoo {", - " int getX();", - " int getY();", - "}"); - - MockJavaResource fooResource = - JavaResourceBase.createMockJavaResource( - "com.foo.Foo", - "package com.foo;", - "public class Foo implements IFoo {", - " @Override public int getX() { return 0; }", - " @Override public int getY() { return 0; }", - "}"); - - checkRecompiledModifiedApp( - compilerOptions, - "com.foo.SimpleModule", - Lists.newArrayList( - simpleModuleResource, entryPointResourceForFoo, fooResource, jsTypeBarResource), - regularIFooResource, - jsPropertyIFooResource, - stringSet("com.foo.Bar", "com.foo.Foo", "com.foo.IFoo", "com.foo.TestEntryPoint"), - JsOutputOption.DETAILED); - } - - /** - * Tests that adding a @JsType annotation on a class comes out accurately and that removing it - * comes out accurately as well. - * - *

An unrelated and non-updated @JsType is also included in each compile to verify that updated - * exports do not forget non-edited items in a recompile. - */ - public void testChangeJsType() throws Exception { - CompilerOptions compilerOptions = new CompilerOptionsImpl(); - compilerOptions.setUseDetailedTypeIds(true); - compilerOptions.setGenerateJsInteropExports(true); - - MockJavaResource jsTypeFooResource = - JavaResourceBase.createMockJavaResource( - "com.foo.Foo", - "package com.foo;", - "import jsinterop.annotations.JsType;", - "@JsType public class Foo {", - " void doInstanceBar() {}", - " public static void doStaticBar() {}", - "}"); - - MockJavaResource regularFooResource = - JavaResourceBase.createMockJavaResource( - "com.foo.Foo", "package com.foo;", "public class Foo {}"); - - checkRecompiledModifiedApp( - compilerOptions, - "com.foo.SimpleModule", - Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), - regularFooResource, - jsTypeFooResource, - stringSet("com.foo.Bar", "com.foo.Foo"), - JsOutputOption.DETAILED); - } - - /** - * Tests that changing a prototype on a @JsType annotated class comes out accurately. - * - *

An unrelated and non-updated @JsType is also included in each compile to verify that updated - * exports do not forget non-edited items in a recompile. - */ - public void testChangeJsTypeNative() throws Exception { - CompilerOptions compilerOptions = new CompilerOptionsImpl(); - compilerOptions.setUseDetailedTypeIds(true); - compilerOptions.setGenerateJsInteropExports(true); - - MockJavaResource nativeFooResource = - JavaResourceBase.createMockJavaResource( - "com.foo.Foo", - "package com.foo;", - "import jsinterop.annotations.JsType;", - "@JsType(isNative=true) public class Foo {", - " public static native void doStaticBar();", - "}"); - - MockJavaResource regularFooResource = - JavaResourceBase.createMockJavaResource( - "com.foo.Foo", - "package com.foo;", - "import jsinterop.annotations.JsType;", - "@JsType public class Foo {", - " public static void doStaticBar() {}", - "}"); - - checkRecompiledModifiedApp( - compilerOptions, - "com.foo.SimpleModule", - Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), - regularFooResource, - nativeFooResource, - stringSet("com.foo.Bar", "com.foo.Foo"), - JsOutputOption.DETAILED); - } - - /** - * Tests that adding a @JsIgnore annotation on a method comes out accurately and that removing - * it comes out accurately as well. - * - *

An unrelated and non-updated @JsType is also included in each compile to verify that updated - * exports do not forget non-edited items in a recompile. - */ - public void testChangeJsIgnore() throws Exception { - CompilerOptions compilerOptions = new CompilerOptionsImpl(); - compilerOptions.setUseDetailedTypeIds(true); - compilerOptions.setGenerateJsInteropExports(true); - - MockJavaResource jsIgnoreFooResource = - JavaResourceBase.createMockJavaResource( - "com.foo.Foo", - "package com.foo;", - "import jsinterop.annotations.JsIgnore;", - "import jsinterop.annotations.JsType;", - "@JsType public class Foo {", - " @JsIgnore public static void doStaticBar() {}", - "}"); - - MockJavaResource regularFooResource = - JavaResourceBase.createMockJavaResource( - "com.foo.Foo", - "package com.foo;", - "import jsinterop.annotations.JsType;", - "@JsType public class Foo {", - " public static void doStaticBar() {}", - "}"); - - checkRecompiledModifiedApp( - compilerOptions, - "com.foo.SimpleModule", - Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), - regularFooResource, - jsIgnoreFooResource, - stringSet("com.foo.Bar", "com.foo.Foo"), - JsOutputOption.DETAILED); - } - - public void testJsInteropNameCollision() throws Exception { - MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache(); - File applicationDir = Files.createTempDirectory("JsInteropNameCollision").toFile(); - CompilerOptions compilerOptions = new CompilerOptionsImpl(); - compilerOptions.setGenerateJsInteropExports(true); - - // Simple compile with one dialog.alert() export succeeds. - compileToJs(compilerOptions, applicationDir, "com.foo.SimpleModule", Lists.newArrayList( - simpleModuleResource, dialogEntryPointResource, simpleDialogResourceWithExport, - complexDialogResourceSansExport), minimalRebuildCache, emptySet, JsOutputOption.OBFUSCATED); - - try { - // Exporting a second dialog.alert() fails with an exported name collision. - compileToJs(compilerOptions, applicationDir, "com.foo.SimpleModule", - Lists. newArrayList(complexDialogResourceWithExport), minimalRebuildCache, - emptySet, JsOutputOption.OBFUSCATED); - fail("Compile should have failed"); - } catch (UnableToCompleteException e) { - // success - } - - // Reverting to just a single dialog.alert() starts succeeding again. - compileToJs(compilerOptions, applicationDir, "com.foo.SimpleModule", - Lists.newArrayList(complexDialogResourceSansExport), minimalRebuildCache, - stringSet("com.foo.SimpleDialog", "com.foo.ComplexDialog", "com.foo.TestEntryPoint"), - JsOutputOption.OBFUSCATED); - } - - public void testGwtCreateJsoRebindResult() throws Exception { - try { - compileToJs(createTempDir(), "com.foo.SimpleModule", - Lists.newArrayList(simpleModuleResource, brokenGwtCreateEntryPointResource), - new MinimalRebuildCache(), emptySet, JsOutputOption.OBFUSCATED); - fail("Compile should have failed"); - } catch (UnableToCompleteException e) { - // success - } - } - - public void testNonZeroArgConstructorEntryPoint() throws Exception { - MockResource moduleResource = - JavaResourceBase.createMockResource( - "com/foo/NonZeroArgConstructor.gwt.xml", - "", - " ", - " ", - ""); - - MockJavaResource entryPointResource = - JavaResourceBase.createMockJavaResource( - "com.foo.NonZeroArgConstructorEntryPoint", - "package com.foo;", - "import com.google.gwt.core.client.EntryPoint;", - "public class NonZeroArgConstructorEntryPoint implements EntryPoint {", - " public NonZeroArgConstructorEntryPoint(String s) {", - " }", - " public void onModuleLoad() {", - " }", - "}"); - - MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache(); - File applicationDir = createTempDir(); - CompilerOptions compilerOptions = new CompilerOptionsImpl(); - - UnitTestTreeLogger.Builder builder = new UnitTestTreeLogger.Builder(); - builder.setLowestLogLevel(TreeLogger.ERROR); - builder.expectError(Pattern.compile("Errors in .*"), null); - builder.expectError("Line 3: Rebind result 'com.foo.NonZeroArgConstructorEntryPoint' " - + "has no default (zero argument) constructors", null); - UnitTestTreeLogger errorLogger = builder.createLogger(); - try { - // Simple compile with one dialog.alert() export succeeds. - - compileToJs(errorLogger, compilerOptions, applicationDir, "com.foo.NonZeroArgConstructor", - Lists.newArrayList(moduleResource, entryPointResource), minimalRebuildCache, - emptySet, JsOutputOption.OBFUSCATED); - fail("Compile should have failed"); - } catch (UnableToCompleteException expected) { - errorLogger.assertCorrectLogEntries(); - } - } - - public void testDeterministicBuild_Draft_StackModeStrip() throws - UnableToCompleteException, IOException { - assertDeterministicBuild(HELLO_MODULE_STACKMODE_STRIP, 0); - } - - public void testDeterministicBuild_Optimized_StackModeStrip() throws - UnableToCompleteException, IOException { - assertDeterministicBuild(HELLO_MODULE_STACKMODE_STRIP, 9); - } - - public void testDeterministicBuild_Draft() throws UnableToCompleteException, IOException { - assertDeterministicBuild(HELLO_MODULE, 0); - } - - public void testDeterministicBuild_Optimized() throws UnableToCompleteException, IOException { - assertDeterministicBuild(HELLO_MODULE, 9); - } - - public void testSuccessfulCompile_jsoClassLiteralOrder() throws Exception { - // Crafted resource to make sure the a native subclass is compiled before the JSO class, - // In the case of native sublcasses the class hierarchy does not match the class literal - // hierarchy. - MockJavaResource nativeClassAndSubclass = - JavaResourceBase.createMockJavaResource( - "com.foo.MyNativeSubclass", - "package com.foo;", - "import jsinterop.annotations.JsType;", - "@JsType(isNative=true)", - "class NativeClass {", - "}", - "public class MyNativeSubclass extends NativeClass {", - "}"); - - MockJavaResource testEntryPoint = - JavaResourceBase.createMockJavaResource( - "com.foo.MyEntryPoint", - "package com.foo;", - "import com.foo.MyNativeSubclass;", - "public class MyEntryPoint extends MyNativeSubclass {", - " public void onModuleLoad() {", - " Object o = new Object();", - " if (MyNativeSubclass.class.getName() == null) ", - " o = new MyNativeSubclass();", - // Make .clazz reachable so that class literals are emmitted with the respective - // classses. - " o.getClass();", - " }", - "}"); - - MockResource moduleResource = - JavaResourceBase.createMockResource( - "com/foo/MyEntryPoint.gwt.xml", - "", - " ", - " ", - ""); - - CompilerOptions compilerOptions = new CompilerOptionsImpl(); - // Make sure it compiles successfully with no assertions - compilerOptions.setEnableAssertions(true); - compilerOptions.setGenerateJsInteropExports(true); - compilerOptions.setOutput(JsOutputOption.PRETTY); - compilerOptions.setOptimizationLevel(9); - assertCompileSucceeds(compilerOptions, testEntryPoint.getTypeName(), - Lists.newArrayList(moduleResource, nativeClassAndSubclass, testEntryPoint)); - } - - // TODO(stalcup): add recompile tests for file deletion. - - public void testIncrementalRecompile_noop() throws UnableToCompleteException, IOException, - InterruptedException { - checkIncrementalRecompile_noop(JsOutputOption.OBFUSCATED); - checkIncrementalRecompile_noop(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_dateStampChange() throws UnableToCompleteException, - IOException, InterruptedException { - checkIncrementalRecompile_dateStampChange(JsOutputOption.OBFUSCATED); - checkIncrementalRecompile_dateStampChange(JsOutputOption.DETAILED); - } - - // Repro for bug #9518 - public void testIncrementalRecompile_jsPropertyConsistencyCheck() - throws UnableToCompleteException, - IOException, InterruptedException { - // Supertype defines the getter. - MockJavaResource superType = - JavaResourceBase.createMockJavaResource( - "com.foo.SuperType", - "package com.foo;", - "import jsinterop.annotations.JsProperty;", - "public class SuperType {", - " @JsProperty String getString() { return null; }", - "}"); - - // Subtype defines the setter. - MockJavaResource subType = - JavaResourceBase.createMockJavaResource( - "com.foo.SubType", - "package com.foo;", - "import jsinterop.annotations.JsProperty;", - "public class SubType extends SuperType {", - " @JsProperty void setString(String s) {}", - "}"); - - MockJavaResource testEntryPoint = - JavaResourceBase.createMockJavaResource( - "com.foo.TestEntryPoint", - "package com.foo;", - "import com.google.gwt.core.client.EntryPoint;", - "public class TestEntryPoint implements EntryPoint {", - " public void onModuleLoad() {", - // Create Impl and pass it to JS but do not explicitly call m - " new SubType();", - " }", - "}"); - - MockResource moduleResource = - JavaResourceBase.createMockResource( - "com/foo/TestModule.gwt.xml", - "", - " ", - " ", - ""); - - MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); - File relinkApplicationDir = createTempDir(); - - // Perform a first compile. - compileToJs(relinkApplicationDir, "com.foo.TestModule", - Lists.newArrayList(moduleResource, testEntryPoint, subType, superType), - relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); - - // Invalidate ONLY the subtype. The types referred by the parameters of supertype methods are - // going to be reference only which means that the supertype property will have a reference - // to a JClassType for "java.lang.String" that isExternal() and is different from the - // (non external) reference in the supertype. - relinkMinimalRebuildCache.markSourceFileStale("com/foo/SubType.java"); - compileToJs(relinkApplicationDir, "com.foo.TestModule", Lists. newArrayList(), - relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); - } - - public void testIncrementalRecompile_invalidatePreamble() throws UnableToCompleteException, - IOException, InterruptedException { - MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); - File relinkApplicationDir = createTempDir(); - - // Perform a first compile. - compileToJs(relinkApplicationDir, "com.foo.SimpleModule", - Lists.newArrayList(simpleModuleResource, emptyEntryPointResource), - relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); - // On first compile nothing is explicitly stale, only implicitly stale. - assertEquals(0, relinkMinimalRebuildCache.getStaleTypeNames().size()); - - // Recompile with a deep change that invalidates the preamble. - relinkMinimalRebuildCache.markSourceFileStale("java/lang/Object.java"); - compileToJs(relinkApplicationDir, "com.foo.SimpleModule", Lists. newArrayList(), - relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); - // Show that preamble invalidation marks everything stale. - assertTrue(relinkMinimalRebuildCache.getProcessedStaleTypeNames().size() > 100); - - // Recompile again with a tiny change. Prove that it's not stuck repeatedly invalidating the - // whole world. - compileToJs(relinkApplicationDir, "com.foo.SimpleModule", - Lists. newArrayList(emptyEntryPointResource), relinkMinimalRebuildCache, null, - JsOutputOption.OBFUSCATED); - // Show that only this little change is stale, not the whole world. - assertEquals(2, getStaleTypeNames(relinkMinimalRebuildCache).size()); - } - - public void testIncrementalRecompile_bridgeMethodOverrideChain() - throws UnableToCompleteException, IOException, InterruptedException { - MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); - File relinkApplicationDir = createTempDir(); - - // Perform a first compile. - compileToJs(relinkApplicationDir, "com.foo.SimpleModule", Lists.newArrayList( - simpleModuleResource, overriddenMethodChainEntryPointResource, topResource, middleResource, - bottomResource), relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); - // On first compile nothing is explicitly stale, only implicitly stale. - assertEquals(0, relinkMinimalRebuildCache.getStaleTypeNames().size()); - - // Recompile with a change to Bottom. - relinkMinimalRebuildCache.markSourceFileStale("com/foo/Bottom.java"); - compileToJs(relinkApplicationDir, "com.foo.SimpleModule", Lists. newArrayList(), - relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); - // Show that the third level bridge method override of Top.run() is seen to be live and thus - // makes type com.foo.Bottom$Value live. - assertTrue( - relinkMinimalRebuildCache.getProcessedStaleTypeNames().contains("com.foo.Bottom$Value")); - } - - public void testIncrementalRecompile_classLiteralNewReference() - throws UnableToCompleteException, IOException, InterruptedException { - checkIncrementalRecompile_classLiteralNewReference(JsOutputOption.OBFUSCATED); - checkIncrementalRecompile_classLiteralNewReference(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_primitiveClassLiteralReference() - throws UnableToCompleteException, IOException, InterruptedException { - checkIncrementalRecompile_primitiveClassLiteralReference(JsOutputOption.OBFUSCATED); - checkIncrementalRecompile_primitiveClassLiteralReference(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_superClassOrder() - throws UnableToCompleteException, IOException, InterruptedException { - // Linked output is sorted alphabetically except that super-classes come before sub-classes. If - // on recompile a sub-class -> super-class relationship is lost then a sub-class with an - // alphabetically earlier name might start linking out before the super-class. - checkIncrementalRecompile_superClassOrder(JsOutputOption.OBFUSCATED); - checkIncrementalRecompile_superClassOrder(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_superFromStaleInner() - throws UnableToCompleteException, IOException, InterruptedException { - checkIncrementalRecompile_superFromStaleInner(JsOutputOption.OBFUSCATED); - checkIncrementalRecompile_superFromStaleInner(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_deterministicUiBinder() throws UnableToCompleteException, - IOException, InterruptedException { - checkIncrementalRecompile_deterministicUiBinder(JsOutputOption.OBFUSCATED); - checkIncrementalRecompile_deterministicUiBinder(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_uiBinderCssChange() throws UnableToCompleteException, - IOException, InterruptedException { - checkIncrementalRecompile_uiBinderCssChange(JsOutputOption.OBFUSCATED); - checkIncrementalRecompile_uiBinderCssChange(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_unstableGeneratorReferencesModifiedType() - throws UnableToCompleteException, IOException, InterruptedException { - checkIncrementalRecompile_unstableGeneratorReferencesModifiedType(JsOutputOption.OBFUSCATED); - checkIncrementalRecompile_unstableGeneratorReferencesModifiedType(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_withErrors() - throws UnableToCompleteException, IOException, InterruptedException { - MockResource moduleResource = - JavaResourceBase.createMockResource( - "com/foo/Errors.gwt.xml", - "", - " ", - " ", - ""); - - MockJavaResource entryPointResource = - JavaResourceBase.createMockJavaResource( - "com.foo.ErrorsEntryPoint", - "package com.foo;", - "import com.google.gwt.core.client.EntryPoint;", - "public class ErrorsEntryPoint implements EntryPoint {", - " public void onModuleLoad() {", - " Foo.foo();", - " }", - "}"); - - MockJavaResource fooResource = - JavaResourceBase.createMockJavaResource( - "com.foo.Foo", - "package com.foo;", - "public class Foo {", - " public static void foo() {", - " }", - "}"); - - MockJavaResource fooResourceWithErrors = - JavaResourceBase.createMockJavaResource( - "com.foo.Foo", - "package com.foo;", - "public class Foo {", - " public static void foo() {", - " // x() method is not defined anywhere, should result in a compile error.", - " x();", - " }", - "}"); - - MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache(); - File applicationDir = createTempDir(); - CompilerOptions compilerOptions = new CompilerOptionsImpl(); - compilerOptions.setUseDetailedTypeIds(true); - compilerOptions.setSourceLevel(SourceLevel.JAVA11); - - // Compile the application with no errors. - compileToJs(TreeLogger.NULL, compilerOptions, applicationDir, "com.foo.Errors", - Lists.newArrayList(moduleResource, entryPointResource, fooResource), minimalRebuildCache, - emptySet, JsOutputOption.OBFUSCATED); - - // Recompile and expect error reporting. - UnitTestTreeLogger.Builder builder = new UnitTestTreeLogger.Builder(); - builder.setLowestLogLevel(TreeLogger.ERROR); - builder.expectError("Line 5: The method x() is undefined for the type Foo", null); - UnitTestTreeLogger errorLogger = builder.createLogger(); - try { - // Recompile but now the changed file has an error - compileToJs(errorLogger, compilerOptions, applicationDir, "com.foo.Errors", - Lists.newArrayList(moduleResource, entryPointResource, fooResourceWithErrors), - minimalRebuildCache, - emptySet, JsOutputOption.OBFUSCATED); - fail("Compile should have failed"); - } catch (UnableToCompleteException expected) { - errorLogger.assertLogEntriesContainExpected(); - } - } - - public void testIncrementalRecompile_representedAsNative() - throws UnableToCompleteException, IOException, InterruptedException { - MockResource moduleResource = - JavaResourceBase.createMockResource( - "com/foo/RepresentedAsNative.gwt.xml", - "", - " ", - " ", - ""); - - MockResource entryPointResource = - JavaResourceBase.createMockJavaResource( - "com.foo.RepresentedAsNativeEntryPoint", - "package com.foo;", - "import com.google.gwt.core.client.EntryPoint;", - "public class RepresentedAsNativeEntryPoint implements EntryPoint {", - " public void onModuleLoad() {", - " Double d = new Double(1d);", - " }", - "}"); - - MockResource modifiedEntryPointResource = - JavaResourceBase.createMockJavaResource( - "com.foo.RepresentedAsNativeEntryPoint", - "package com.foo;", - "import com.google.gwt.core.client.EntryPoint;", - "public class RepresentedAsNativeEntryPoint implements EntryPoint {", - " public void onModuleLoad() {", - " Double d = new Double(\"1\");", - " }", - "}"); - - PrintWriterTreeLogger logger = new PrintWriterTreeLogger(); - logger.setMaxDetail(TreeLogger.ERROR); - - MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache(); - File applicationDir = createTempDir(); - CompilerOptions compilerOptions = new CompilerOptionsImpl(); - compilerOptions.setUseDetailedTypeIds(true); - compilerOptions.setSourceLevel(SourceLevel.JAVA11); - compilerOptions.setGenerateJsInteropExports(false); - - // Compile the application with no errors. - compileToJs(logger, compilerOptions, applicationDir, "com.foo.RepresentedAsNative", - Lists.newArrayList(moduleResource, entryPointResource), minimalRebuildCache, - emptySet, JsOutputOption.OBFUSCATED); - - // Recompile but now the changed file has an error - compileToJs(logger, compilerOptions, applicationDir, "com.foo.RepresentedAsNative", - Lists.newArrayList(modifiedEntryPointResource), - minimalRebuildCache, - stringSet( - "com.foo.RepresentedAsNativeEntryPoint", - getEntryMethodHolderTypeName("com.foo.RepresentedAsNative")), - JsOutputOption.OBFUSCATED); - } - - public void testIncrementalRecompile_functionSignatureChange() throws UnableToCompleteException, - IOException, InterruptedException { - // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's - // behavior is order dependent, and while still correct, will come out different in a recompile - // with this change versus a from scratch compile with this change. - checkIncrementalRecompile_functionSignatureChange(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_compileTimeConstantChange() throws UnableToCompleteException, - IOException, InterruptedException { - checkIncrementalRecompile_compileTimeConstantChange(JsOutputOption.DETAILED); - checkIncrementalRecompile_compileTimeConstantChange(JsOutputOption.OBFUSCATED); - } - - public void testIncrementalRecompile_transitivelyFoldableConstant() - throws UnableToCompleteException, - IOException, InterruptedException { - checkIncrementalRecompile_transitivelyFoldableConstant(JsOutputOption.DETAILED); - checkIncrementalRecompile_transitivelyFoldableConstant(JsOutputOption.OBFUSCATED); - } - - public void testIncrementalRecompile_packagePrivateDispatch() throws UnableToCompleteException, - IOException, InterruptedException { - checkIncrementalRecompile_packagePrivateOverride(JsOutputOption.OBFUSCATED); - checkIncrementalRecompile_packagePrivateOverride(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_prettyOutput() - throws UnableToCompleteException, IOException, InterruptedException { - // Nominal tests for pretty output. Pretty and Obfuscated output share most of the same code - // paths. - checkIncrementalRecompile_typeHierarchyChange(JsOutputOption.PRETTY); - checkIncrementalRecompile_unreachableIncompatibleChange(JsOutputOption.PRETTY); - } - - public void testIncrementalRecompile_regularClassMadeIntoJsoClass() - throws UnableToCompleteException, IOException, InterruptedException { - // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's - // behavior is order dependent, and while still correct, will come out different in a recompile - // with this change versus a from scratch compile with this change. - checkIncrementalRecompile_regularClassMadeIntoJsoClass(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_unreachableIncompatibleChange() - throws UnableToCompleteException, IOException, InterruptedException { - // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's - // behavior is order dependent, and while still correct, will come out different in a recompile - // with this change versus a from scratch compile with this change. - checkIncrementalRecompile_unreachableIncompatibleChange(JsOutputOption.OBFUSCATED); - checkIncrementalRecompile_unreachableIncompatibleChange(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_typeHierarchyChange() - throws UnableToCompleteException, IOException, InterruptedException { - checkIncrementalRecompile_typeHierarchyChange(JsOutputOption.OBFUSCATED); - checkIncrementalRecompile_typeHierarchyChange(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_defaultMethod() - throws UnableToCompleteException, IOException, InterruptedException { - // Tests that default method on superclasses are correctly constructed - checkIncrementalRecompile_defaultMethod(JsOutputOption.OBFUSCATED); - checkIncrementalRecompile_defaultMethod(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_devirtualizeUnchangedJso() - throws UnableToCompleteException, IOException, InterruptedException { - // Tests that a JSO calls through interfaces are correctly devirtualized when compiling per file - // and the JSOs nor their single impl interfaces are not stale. - checkIncrementalRecompile_devirtualizeUnchangedJso(JsOutputOption.OBFUSCATED); - checkIncrementalRecompile_devirtualizeUnchangedJso(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_devirtualizeString() - throws UnableToCompleteException, IOException, InterruptedException { - // Tests that String calls through interfaces are correctly devirtualized when compiling per - // file and neither String nor CharSequence interface are stale. - checkIncrementalRecompile_devirtualizeString(JsOutputOption.OBFUSCATED); - checkIncrementalRecompile_devirtualizeString(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_devirtualizeComparable() - throws UnableToCompleteException, IOException, InterruptedException { - // Tests that Doublecalls through interfaces are correctly devirtualized when compiling per - // file and neither String nor CharSequence interface are stale. - checkIncrementalRecompile_devirtualizeComparable(JsOutputOption.OBFUSCATED); - checkIncrementalRecompile_devirtualizeComparable(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_multipleClassGenerator() - throws UnableToCompleteException, IOException, InterruptedException { - // Tests that a Generated type that is not directly referenced from the rebound GWT.create() - // call is still marked stale, regenerated, retraversed and output as JS. - checkIncrementalRecompile_multipleClassGenerator(JsOutputOption.OBFUSCATED); - checkIncrementalRecompile_multipleClassGenerator(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_singleJsoIntfDispatchChange() - throws UnableToCompleteException, - IOException, InterruptedException { - // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's - // behavior is order dependent, and while still correct, will come out different in a recompile - // with this change versus a from scratch compile with this change. - checkIncrementalRecompile_singleJsoIntfDispatchChange(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_dualJsoIntfDispatchChange() throws UnableToCompleteException, - IOException, InterruptedException { - // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's - // behavior is order dependent, and while still correct, will come out different in a recompile - // with this change versus a from scratch compile with this change. - checkIncrementalRecompile_dualJsoIntfDispatchChange(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_generatorInputResourceChange() throws IOException, - UnableToCompleteException, InterruptedException { - // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's - // behavior is order dependent, and while still correct, will come out different in a recompile - // with this change versus a from scratch compile with this change. - checkIncrementalRecompile_generatorInputResourceChange(JsOutputOption.DETAILED); - } - - public void testIncrementalRecompile_invalidatedGeneratorOutputRerunsGenerator() - throws UnableToCompleteException, IOException, InterruptedException { - // BarReferencesFoo Generator hasn't run yet. - assertEquals(0, BarReferencesFooGenerator.runCount); - - CompilerOptions compilerOptions = new CompilerOptionsImpl(); - List sharedResources = - Lists.newArrayList(barReferencesFooGeneratorModuleResource, generatorEntryPointResource); - JsOutputOption output = JsOutputOption.OBFUSCATED; - - List originalResources = Lists.newArrayList(sharedResources); - originalResources.add(fooResource); - - // Compile the app with original files, modify a file and do a per-file recompile. - MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); - File relinkApplicationDir = createTempDir(); - compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", originalResources, - relinkMinimalRebuildCache, emptySet, output); - - // BarReferencesFoo Generator has now been run once. - assertEquals(1, BarReferencesFooGenerator.runCount); - - // Recompile with no changes, which should not trigger any Generator runs. - compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", - Lists.newArrayList(), relinkMinimalRebuildCache, emptySet, output); - - // Since there were no changes BarReferencesFoo Generator was not run again. - assertEquals(1, BarReferencesFooGenerator.runCount); - - // Recompile with a modified Foo class, which should invalidate Bar which was generated by a - // GWT.create() call in the entry point. - compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", - Lists.newArrayList(fooResource), relinkMinimalRebuildCache, - stringSet("com.foo.TestEntryPoint", "com.foo.Foo", "com.foo.Bar"), output); - - // BarReferencesFoo Generator was run again. - assertEquals(2, BarReferencesFooGenerator.runCount); - } - - public void testIncrementalRecompile_invalidatedGeneratorOutputRerunsCascadedGenerators() - throws UnableToCompleteException, IOException, InterruptedException { - // Generators haven't run yet. - assertEquals(0, CauseStringRebindGenerator.runCount); - assertEquals(0, CauseShortRebindGenerator.runCount); - assertEquals(0, FooResourceGenerator.runCount); - - CompilerOptions compilerOptions = new CompilerOptionsImpl(); - List sharedResources = Lists.newArrayList(cascadingGeneratorModuleResource, - generatorEntryPointResource, classNameToGenerateResource); - JsOutputOption output = JsOutputOption.OBFUSCATED; - - List originalResources = Lists.newArrayList(sharedResources); - - // Compile the app with original files. - MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); - File relinkApplicationDir = createTempDir(); - compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", originalResources, - relinkMinimalRebuildCache, emptySet, output); - - // Generators have now been run once. - assertEquals(1, CauseStringRebindGenerator.runCount); - assertEquals(1, CauseShortRebindGenerator.runCount); - assertEquals(1, FooResourceGenerator.runCount); - - // Recompile with no changes, which should not trigger any Generator runs. - compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", - Lists.newArrayList(), relinkMinimalRebuildCache, emptySet, output); - - // Since there were no changes Generators were not run again. - assertEquals(1, CauseStringRebindGenerator.runCount); - assertEquals(1, CauseShortRebindGenerator.runCount); - assertEquals(1, FooResourceGenerator.runCount); - - // Recompile with a modified resource, which should invalidate the output of the - // FooResourceGenerator and cascade the invalidate the Generators that triggered - // FooResourceGenerator. - compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", - Lists.newArrayList(modifiedClassNameToGenerateResource), - relinkMinimalRebuildCache, stringSet("com.foo.TestEntryPoint", "com.foo.Baz$InnerBaz", - "com.foo.Bar", "com.foo.HasCustomContent", "com.foo.FooReplacementTwo"), output); - - // Generators were run again. - assertEquals(2, CauseStringRebindGenerator.runCount); - assertEquals(2, CauseShortRebindGenerator.runCount); - assertEquals(2, FooResourceGenerator.runCount); - } - - public void testIncrementalRecompile_carriesOverGeneratorArtifacts() - throws UnableToCompleteException, - IOException, InterruptedException { - // Foo Generator hasn't run yet. - assertEquals(0, FooResourceGenerator.runCount); - - CompilerOptions compilerOptions = new CompilerOptionsImpl(); - List sharedResources = Lists.newArrayList(resourceReadingGeneratorModuleResource, - referencesBarAndGeneratorEntryPointResource, classNameToGenerateResource, - barReferencesFooResource); - JsOutputOption output = JsOutputOption.OBFUSCATED; - - List originalResources = Lists.newArrayList(sharedResources); - originalResources.add(fooResource); - - // Compile the app with original files. - MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); - File relinkApplicationDir = createTempDir(); - compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", originalResources, - relinkMinimalRebuildCache, emptySet, output); - - // Foo Generator has now been run once. - assertEquals(1, FooResourceGenerator.runCount); - // The bar.txt artifact was output. - File barFile = new File(relinkApplicationDir.getPath() + File.separator + "com.foo.SimpleModule" - + File.separator + "bar.txt"); - assertTrue(barFile.exists()); - - // Recompile with just 1 file change, which should not trigger any Generator runs. - compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", - Lists. newArrayList(fooResource), relinkMinimalRebuildCache, - stringSet("com.foo.Foo", "com.foo.Bar"), output); - - // Foo Generator was not run again. - assertEquals(1, FooResourceGenerator.runCount); - // But the bar.txt artifact was still output. - barFile = new File(relinkApplicationDir.getPath() + File.separator + "com.foo.SimpleModule" - + File.separator + "bar.txt"); - assertTrue(barFile.exists()); - } - - /** - * Regression test for UnifyAST assertion failure problem in incremental SDM. - */ - public void testIncrementalRecompile_unifyASTAssertionRegression() - throws UnableToCompleteException, IOException, InterruptedException { - - CompilerOptions compilerOptions = new CompilerOptionsImpl(); - List originalResources = Lists.newArrayList(helloEntryPointResource, - helloModuleResource); - JsOutputOption output = JsOutputOption.OBFUSCATED; - - // Compile the app with original files. - MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); - File relinkApplicationDir = createTempDir(); - compileToJs(compilerOptions, relinkApplicationDir, "com.foo.Hello", - originalResources, relinkMinimalRebuildCache, emptySet, output); +// public void testAllValidArgs() { +// CompilerOptionsImpl options = new CompilerOptionsImpl(); +// Compiler.ArgProcessor argProcessor = new Compiler.ArgProcessor(options); +// +// assertProcessSuccess(argProcessor, new String[] {"-logLevel", "DEBUG", "-style", +// "PRETTY", "-ea", "-gen", "myGen", +// "-war", "myWar", "-workDir", "myWork", "-extra", "myExtra", "-incremental", +// "-localWorkers", "2", "-sourceLevel", "1.8", "c.g.g.h.H", "my.Module"}); +// +// assertEquals(new File("myGen").getAbsoluteFile(), +// options.getGenDir().getAbsoluteFile()); +// assertEquals(new File("myWar"), options.getWarDir()); +// assertEquals(new File("myWork"), options.getWorkDir()); +// assertEquals(new File("myExtra"), options.getExtraDir()); +// +// assertEquals(2, options.getLocalWorkers()); +// +// assertEquals(TreeLogger.DEBUG, options.getLogLevel()); +// assertEquals(JsOutputOption.PRETTY, options.getOutput()); +// assertTrue(options.isEnableAssertions()); +// assertTrue(options.shouldClusterSimilarFunctions()); +// assertTrue(options.shouldInlineLiteralParameters()); +// assertFalse(options.shouldOptimizeDataflow()); +// assertTrue(options.shouldOrdinalizeEnums()); +// assertTrue(options.shouldRemoveDuplicateFunctions()); +// assertTrue(options.isIncrementalCompileEnabled()); +// +// assertEquals(SourceLevel.JAVA8, options.getSourceLevel()); +// +// assertEquals(2, options.getModuleNames().size()); +// assertEquals("c.g.g.h.H", options.getModuleNames().get(0)); +// assertEquals("my.Module", options.getModuleNames().get(1)); +// } +// +// public void testDefaultArgs() { +// CompilerOptionsImpl options = new CompilerOptionsImpl(); +// Compiler.ArgProcessor argProcessor = new Compiler.ArgProcessor(options); +// +// assertProcessSuccess(argProcessor, new String[]{"c.g.g.h.H"}); +// +// assertEquals(null, options.getGenDir()); +// assertEquals(new File("war").getAbsoluteFile(), +// options.getWarDir().getAbsoluteFile()); +// assertEquals(null, options.getWorkDir()); +// assertEquals(null, options.getExtraDir()); +// +// assertEquals(TreeLogger.INFO, options.getLogLevel()); +// assertEquals(JsOutputOption.OBFUSCATED, options.getOutput()); +// assertFalse(options.isEnableAssertions()); +// assertTrue(options.shouldClusterSimilarFunctions()); +// assertTrue(options.shouldInlineLiteralParameters()); +// assertFalse(options.shouldOptimizeDataflow()); +// assertTrue(options.shouldOrdinalizeEnums()); +// assertTrue(options.shouldRemoveDuplicateFunctions()); +// assertFalse(options.isIncrementalCompileEnabled()); +// +// assertEquals(1, options.getLocalWorkers()); +// +// assertEquals(1, options.getModuleNames().size()); +// assertEquals("c.g.g.h.H", options.getModuleNames().get(0)); +// } +// +// public void testForbiddenArgs() { +// CompilerOptionsImpl options = new CompilerOptionsImpl(); +// Compiler.ArgProcessor argProcessor = new Compiler.ArgProcessor(options); +// +// assertProcessFailure(argProcessor, "Unknown argument", new String[]{"-out", "www"}); +// assertProcessFailure(argProcessor, "Source level must be one of", +// new String[]{"-sourceLevel", "ssss"}); +// assertProcessFailure(argProcessor, "Source level must be one of", +// new String[]{"-sourceLevel", "1.5"}); +// } +// +// /** +// * Tests ordering for emum {@link SourceLevel}. +// */ +// public void testSourceLevelOrdering() { +// SourceLevel[] sourceLevels = SourceLevel.values(); +// SourceLevel previousSourceLevel = sourceLevels[0]; +// for (int i = 1; i < sourceLevels.length; i++) { +// assertTrue(SourceLevel.versionCompare(previousSourceLevel.getStringValue(), +// sourceLevels[i].getStringValue()) < 0); +// previousSourceLevel = sourceLevels[i]; +// } +// } +// +// public void testSourceLevelSelection() { +// assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.4")); +// assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.5")); +// assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.6")); +// assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.6_26")); +// +// assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.7")); +// assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.8")); +// assertEquals(SourceLevel.JAVA9, SourceLevel.getBestMatchingVersion("9")); +// assertEquals(SourceLevel.JAVA10, SourceLevel.getBestMatchingVersion("10")); +// assertEquals(SourceLevel.JAVA11, SourceLevel.getBestMatchingVersion("11")); +// +// // not proper version strings => default to JAVA8. +// assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.6u3")); +// assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.6b3")); +// assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.7b3")); +// } +// +// public void testSourceLevelHighestVersion() { +// assertEquals(SourceLevel.values()[SourceLevel.values().length - 1], SourceLevel.getHighest()); +// } +// +// /** +// * Verify that a compile with a @JsType at least compiles successfully. +// */ +// public void testGwtCreateJsTypeRebindResult() throws Exception { +// CompilerOptions compilerOptions = new CompilerOptionsImpl(); +// compileToJs(compilerOptions, createTempDir(), "com.foo.SimpleModule", +// Lists.newArrayList(simpleModuleResource, gwtCreateEntryPointResource), +// new MinimalRebuildCache(), emptySet, JsOutputOption.OBFUSCATED); +// } +// +// /** +// * Test that some lightly referenced interface through a @JsFunction is included in the output. +// */ +// public void testReferenceThroughJsFunction() throws Exception { +// MockJavaResource someJsFunction = +// JavaResourceBase.createMockJavaResource( +// "com.foo.SomeJsFunction", +// "package com.foo;", +// "import jsinterop.annotations.JsFunction;", +// "@JsFunction", +// "public interface SomeJsFunction {", +// " void m();", +// "}"); +// +// MockJavaResource jsFunctionInterfaceImplementation = +// JavaResourceBase.createMockJavaResource( +// "com.foo.Impl", +// "package com.foo;", +// "public final class Impl implements SomeJsFunction {", +// " public void m() { SomeInterface.class.getName(); } ", +// "}"); +// +// MockJavaResource someInterface = +// JavaResourceBase.createMockJavaResource( +// "com.foo.SomeInterface", +// "package com.foo;", +// "public interface SomeInterface {", +// "}"); +// +// MockJavaResource testEntryPoint = +// JavaResourceBase.createMockJavaResource( +// "com.foo.TestEntryPoint", +// "package com.foo;", +// "import com.google.gwt.core.client.EntryPoint;", +// "public class TestEntryPoint implements EntryPoint {", +// " private static native void f(SomeJsFunction f) /*-{}-*/;", +// " public void onModuleLoad() {", +// // Create Impl and pass it to JS but do not explicitly call m +// " f(new Impl());", +// " }", +// "}"); +// +// MockResource moduleResource = +// JavaResourceBase.createMockResource( +// "com/foo/TestEntryPoint.gwt.xml", +// "", +// " ", +// " ", +// ""); +// +// CompilerOptions compilerOptions = new CompilerOptionsImpl(); +// String js = compileToJs(compilerOptions, createTempDir(), testEntryPoint.getTypeName(), +// Lists.newArrayList(moduleResource, testEntryPoint, someJsFunction, +// jsFunctionInterfaceImplementation, someInterface), +// new MinimalRebuildCache(), emptySet, JsOutputOption.DETAILED); +// // Make sure the referenced class literals ends up being included in the resulting JS. +// String classliteralHolderVarName = +// JjsUtils.mangleMemberName("com.google.gwt.lang.ClassLiteralHolder", +// JjsUtils.classLiteralFieldNameFromJavahTypeSignatureName( +// JjsUtils.javahSignatureFromName(someInterface.getTypeName()))); +// assertTrue(js.contains("var " + classliteralHolderVarName + " = ")); +// } +// +// /** +// * Tests that changing Js namespace name on an exported method comes out accurately. +// * +// *

An unrelated and non-updated @JsType is also included in each compile to verify that updated +// * exports do not forget non-edited items in a recompile. +// */ +// public void testChangeJsNamespaceOnMethod() throws Exception { +// CompilerOptions compilerOptions = new CompilerOptionsImpl(); +// compilerOptions.setUseDetailedTypeIds(true); +// compilerOptions.setGenerateJsInteropExports(true); +// +// MockJavaResource jsNamespaceFooResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.Foo", +// "package com.foo;", +// "import jsinterop.annotations.JsMethod;", +// "import jsinterop.annotations.JsType;", +// "@JsType public class Foo {", +// " @JsMethod(namespace=\"spazz\") public static void doStaticBar() {}", +// "}"); +// +// MockJavaResource regularFooResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.Foo", +// "package com.foo;", +// "import jsinterop.annotations.JsType;", +// "@JsType public class Foo {", +// " public static void doStaticBar() {}", +// "}"); +// +// checkRecompiledModifiedApp( +// compilerOptions, +// "com.foo.SimpleModule", +// Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), +// regularFooResource, +// jsNamespaceFooResource, +// stringSet("com.foo.Bar", "com.foo.Foo"), +// JsOutputOption.DETAILED); +// } +// +// /** +// * Tests that changing Js namespace on a class comes out accurately. +// * +// *

An unrelated and non-updated @JsType is also included in each compile to verify that updated +// * exports do not forget non-edited items in a recompile. +// */ +// public void testChangeJsNamespaceOnClass() throws Exception { +// CompilerOptions compilerOptions = new CompilerOptionsImpl(); +// compilerOptions.setUseDetailedTypeIds(true); +// compilerOptions.setGenerateJsInteropExports(true); +// +// MockJavaResource jsNamespaceFooResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.Foo", +// "package com.foo;", +// "import jsinterop.annotations.JsType;", +// "@JsType(namespace=\"spazz\") public class Foo {", +// " public static void doStaticBar() {}", +// "}"); +// +// MockJavaResource regularFooResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.Foo", +// "package com.foo;", +// "import jsinterop.annotations.JsType;", +// "@JsType public class Foo {", +// " public static void doStaticBar() {}", +// "}"); +// +// checkRecompiledModifiedApp( +// compilerOptions, +// "com.foo.SimpleModule", +// Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), +// regularFooResource, +// jsNamespaceFooResource, +// stringSet("com.foo.Bar", "com.foo.Foo"), +// JsOutputOption.DETAILED); +// } +// +// /** +// * Tests that changing @JsFunction name on an interface comes out accurately. +// * +// *

An unrelated and non-updated @JsType is also included in each compile to verify that updated +// * exports do not forget non-edited items in a recompile. +// */ +// public void testChangeJsFunction() throws Exception { +// CompilerOptions compilerOptions = new CompilerOptionsImpl(); +// compilerOptions.setUseDetailedTypeIds(true); +// compilerOptions.setGenerateJsInteropExports(true); +// +// MockJavaResource jsFunctionIFooResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.IFoo", +// "package com.foo;", +// "import jsinterop.annotations.JsFunction;", +// "@JsFunction public interface IFoo {", +// " int foo(int x);", +// "}"); +// +// MockJavaResource regularIFooResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.IFoo", +// "package com.foo;", +// "public interface IFoo {", +// " int foo(int x);", +// "}"); +// +// MockJavaResource fooResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.Foo", +// "package com.foo;", +// "public final class Foo implements IFoo {", +// " @Override public int foo(int x) { return 0; }", +// "}"); +// +// checkRecompiledModifiedApp( +// compilerOptions, +// "com.foo.SimpleModule", +// Lists.newArrayList( +// simpleModuleResource, entryPointResourceForFoo, fooResource, jsTypeBarResource), +// regularIFooResource, +// jsFunctionIFooResource, +// stringSet("com.foo.Bar", "com.foo.Foo", "com.foo.IFoo", "com.foo.TestEntryPoint"), +// JsOutputOption.DETAILED); +// } +// +// /** +// * Tests that toggling JsProperty methods in an interface comes out accurately. +// * +// *

An unrelated and non-updated @JsType is also included in each compile to verify that updated +// * exports do not forget non-edited items in a recompile. +// */ +// public void testChangeJsProperty() throws Exception { +// CompilerOptions compilerOptions = new CompilerOptionsImpl(); +// compilerOptions.setUseDetailedTypeIds(true); +// compilerOptions.setGenerateJsInteropExports(true); +// +// MockJavaResource jsPropertyIFooResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.IFoo", +// "package com.foo;", +// "import jsinterop.annotations.JsProperty;", +// "import jsinterop.annotations.JsType;", +// "@JsType public interface IFoo {", +// " @JsProperty int getX();", +// " @JsProperty int getY();", +// "}"); +// +// MockJavaResource regularIFooResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.IFoo", +// "package com.foo;", +// "import jsinterop.annotations.JsType;", +// "@JsType public interface IFoo {", +// " int getX();", +// " int getY();", +// "}"); +// +// MockJavaResource fooResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.Foo", +// "package com.foo;", +// "public class Foo implements IFoo {", +// " @Override public int getX() { return 0; }", +// " @Override public int getY() { return 0; }", +// "}"); +// +// checkRecompiledModifiedApp( +// compilerOptions, +// "com.foo.SimpleModule", +// Lists.newArrayList( +// simpleModuleResource, entryPointResourceForFoo, fooResource, jsTypeBarResource), +// regularIFooResource, +// jsPropertyIFooResource, +// stringSet("com.foo.Bar", "com.foo.Foo", "com.foo.IFoo", "com.foo.TestEntryPoint"), +// JsOutputOption.DETAILED); +// } +// +// /** +// * Tests that adding a @JsType annotation on a class comes out accurately and that removing it +// * comes out accurately as well. +// * +// *

An unrelated and non-updated @JsType is also included in each compile to verify that updated +// * exports do not forget non-edited items in a recompile. +// */ +// public void testChangeJsType() throws Exception { +// CompilerOptions compilerOptions = new CompilerOptionsImpl(); +// compilerOptions.setUseDetailedTypeIds(true); +// compilerOptions.setGenerateJsInteropExports(true); +// +// MockJavaResource jsTypeFooResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.Foo", +// "package com.foo;", +// "import jsinterop.annotations.JsType;", +// "@JsType public class Foo {", +// " void doInstanceBar() {}", +// " public static void doStaticBar() {}", +// "}"); +// +// MockJavaResource regularFooResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.Foo", "package com.foo;", "public class Foo {}"); +// +// checkRecompiledModifiedApp( +// compilerOptions, +// "com.foo.SimpleModule", +// Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), +// regularFooResource, +// jsTypeFooResource, +// stringSet("com.foo.Bar", "com.foo.Foo"), +// JsOutputOption.DETAILED); +// } +// +// /** +// * Tests that changing a prototype on a @JsType annotated class comes out accurately. +// * +// *

An unrelated and non-updated @JsType is also included in each compile to verify that updated +// * exports do not forget non-edited items in a recompile. +// */ +// public void testChangeJsTypeNative() throws Exception { +// CompilerOptions compilerOptions = new CompilerOptionsImpl(); +// compilerOptions.setUseDetailedTypeIds(true); +// compilerOptions.setGenerateJsInteropExports(true); +// +// MockJavaResource nativeFooResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.Foo", +// "package com.foo;", +// "import jsinterop.annotations.JsType;", +// "@JsType(isNative=true) public class Foo {", +// " public static native void doStaticBar();", +// "}"); +// +// MockJavaResource regularFooResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.Foo", +// "package com.foo;", +// "import jsinterop.annotations.JsType;", +// "@JsType public class Foo {", +// " public static void doStaticBar() {}", +// "}"); +// +// checkRecompiledModifiedApp( +// compilerOptions, +// "com.foo.SimpleModule", +// Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), +// regularFooResource, +// nativeFooResource, +// stringSet("com.foo.Bar", "com.foo.Foo"), +// JsOutputOption.DETAILED); +// } +// +// /** +// * Tests that adding a @JsIgnore annotation on a method comes out accurately and that removing +// * it comes out accurately as well. +// * +// *

An unrelated and non-updated @JsType is also included in each compile to verify that updated +// * exports do not forget non-edited items in a recompile. +// */ +// public void testChangeJsIgnore() throws Exception { +// CompilerOptions compilerOptions = new CompilerOptionsImpl(); +// compilerOptions.setUseDetailedTypeIds(true); +// compilerOptions.setGenerateJsInteropExports(true); +// +// MockJavaResource jsIgnoreFooResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.Foo", +// "package com.foo;", +// "import jsinterop.annotations.JsIgnore;", +// "import jsinterop.annotations.JsType;", +// "@JsType public class Foo {", +// " @JsIgnore public static void doStaticBar() {}", +// "}"); +// +// MockJavaResource regularFooResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.Foo", +// "package com.foo;", +// "import jsinterop.annotations.JsType;", +// "@JsType public class Foo {", +// " public static void doStaticBar() {}", +// "}"); +// +// checkRecompiledModifiedApp( +// compilerOptions, +// "com.foo.SimpleModule", +// Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), +// regularFooResource, +// jsIgnoreFooResource, +// stringSet("com.foo.Bar", "com.foo.Foo"), +// JsOutputOption.DETAILED); +// } +// +// public void testJsInteropNameCollision() throws Exception { +// MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache(); +// File applicationDir = Files.createTempDirectory("JsInteropNameCollision").toFile(); +// CompilerOptions compilerOptions = new CompilerOptionsImpl(); +// compilerOptions.setGenerateJsInteropExports(true); +// +// // Simple compile with one dialog.alert() export succeeds. +// compileToJs(compilerOptions, applicationDir, "com.foo.SimpleModule", Lists.newArrayList( +// simpleModuleResource, dialogEntryPointResource, simpleDialogResourceWithExport, +// complexDialogResourceSansExport), minimalRebuildCache, emptySet, JsOutputOption.OBFUSCATED); +// +// try { +// // Exporting a second dialog.alert() fails with an exported name collision. +// compileToJs(compilerOptions, applicationDir, "com.foo.SimpleModule", +// Lists. newArrayList(complexDialogResourceWithExport), minimalRebuildCache, +// emptySet, JsOutputOption.OBFUSCATED); +// fail("Compile should have failed"); +// } catch (UnableToCompleteException e) { +// // success +// } +// +// // Reverting to just a single dialog.alert() starts succeeding again. +// compileToJs(compilerOptions, applicationDir, "com.foo.SimpleModule", +// Lists.newArrayList(complexDialogResourceSansExport), minimalRebuildCache, +// stringSet("com.foo.SimpleDialog", "com.foo.ComplexDialog", "com.foo.TestEntryPoint"), +// JsOutputOption.OBFUSCATED); +// } +// +// public void testGwtCreateJsoRebindResult() throws Exception { +// try { +// compileToJs(createTempDir(), "com.foo.SimpleModule", +// Lists.newArrayList(simpleModuleResource, brokenGwtCreateEntryPointResource), +// new MinimalRebuildCache(), emptySet, JsOutputOption.OBFUSCATED); +// fail("Compile should have failed"); +// } catch (UnableToCompleteException e) { +// // success +// } +// } +// +// public void testNonZeroArgConstructorEntryPoint() throws Exception { +// MockResource moduleResource = +// JavaResourceBase.createMockResource( +// "com/foo/NonZeroArgConstructor.gwt.xml", +// "", +// " ", +// " ", +// ""); +// +// MockJavaResource entryPointResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.NonZeroArgConstructorEntryPoint", +// "package com.foo;", +// "import com.google.gwt.core.client.EntryPoint;", +// "public class NonZeroArgConstructorEntryPoint implements EntryPoint {", +// " public NonZeroArgConstructorEntryPoint(String s) {", +// " }", +// " public void onModuleLoad() {", +// " }", +// "}"); +// +// MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache(); +// File applicationDir = createTempDir(); +// CompilerOptions compilerOptions = new CompilerOptionsImpl(); +// +// UnitTestTreeLogger.Builder builder = new UnitTestTreeLogger.Builder(); +// builder.setLowestLogLevel(TreeLogger.ERROR); +// builder.expectError(Pattern.compile("Errors in .*"), null); +// builder.expectError("Line 3: Rebind result 'com.foo.NonZeroArgConstructorEntryPoint' " +// + "has no default (zero argument) constructors", null); +// UnitTestTreeLogger errorLogger = builder.createLogger(); +// try { +// // Simple compile with one dialog.alert() export succeeds. +// +// compileToJs(errorLogger, compilerOptions, applicationDir, "com.foo.NonZeroArgConstructor", +// Lists.newArrayList(moduleResource, entryPointResource), minimalRebuildCache, +// emptySet, JsOutputOption.OBFUSCATED); +// fail("Compile should have failed"); +// } catch (UnableToCompleteException expected) { +// errorLogger.assertCorrectLogEntries(); +// } +// } +// +// public void testDeterministicBuild_Draft_StackModeStrip() throws +// UnableToCompleteException, IOException { +// assertDeterministicBuild(HELLO_MODULE_STACKMODE_STRIP, 0); +// } +// +// public void testDeterministicBuild_Optimized_StackModeStrip() throws +// UnableToCompleteException, IOException { +// assertDeterministicBuild(HELLO_MODULE_STACKMODE_STRIP, 9); +// } +// +// public void testDeterministicBuild_Draft() throws UnableToCompleteException, IOException { +// assertDeterministicBuild(HELLO_MODULE, 0); +// } +// +// public void testDeterministicBuild_Optimized() throws UnableToCompleteException, IOException { +// assertDeterministicBuild(HELLO_MODULE, 9); +// } +// +// public void testSuccessfulCompile_jsoClassLiteralOrder() throws Exception { +// // Crafted resource to make sure the a native subclass is compiled before the JSO class, +// // In the case of native sublcasses the class hierarchy does not match the class literal +// // hierarchy. +// MockJavaResource nativeClassAndSubclass = +// JavaResourceBase.createMockJavaResource( +// "com.foo.MyNativeSubclass", +// "package com.foo;", +// "import jsinterop.annotations.JsType;", +// "@JsType(isNative=true)", +// "class NativeClass {", +// "}", +// "public class MyNativeSubclass extends NativeClass {", +// "}"); +// +// MockJavaResource testEntryPoint = +// JavaResourceBase.createMockJavaResource( +// "com.foo.MyEntryPoint", +// "package com.foo;", +// "import com.foo.MyNativeSubclass;", +// "public class MyEntryPoint extends MyNativeSubclass {", +// " public void onModuleLoad() {", +// " Object o = new Object();", +// " if (MyNativeSubclass.class.getName() == null) ", +// " o = new MyNativeSubclass();", +// // Make .clazz reachable so that class literals are emmitted with the respective +// // classses. +// " o.getClass();", +// " }", +// "}"); +// +// MockResource moduleResource = +// JavaResourceBase.createMockResource( +// "com/foo/MyEntryPoint.gwt.xml", +// "", +// " ", +// " ", +// ""); +// +// CompilerOptions compilerOptions = new CompilerOptionsImpl(); +// // Make sure it compiles successfully with no assertions +// compilerOptions.setEnableAssertions(true); +// compilerOptions.setGenerateJsInteropExports(true); +// compilerOptions.setOutput(JsOutputOption.PRETTY); +// compilerOptions.setOptimizationLevel(9); +// assertCompileSucceeds(compilerOptions, testEntryPoint.getTypeName(), +// Lists.newArrayList(moduleResource, nativeClassAndSubclass, testEntryPoint)); +// } +// +// // TODO(stalcup): add recompile tests for file deletion. +// +// public void testIncrementalRecompile_noop() throws UnableToCompleteException, IOException, +// InterruptedException { +// checkIncrementalRecompile_noop(JsOutputOption.OBFUSCATED); +// checkIncrementalRecompile_noop(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_dateStampChange() throws UnableToCompleteException, +// IOException, InterruptedException { +// checkIncrementalRecompile_dateStampChange(JsOutputOption.OBFUSCATED); +// checkIncrementalRecompile_dateStampChange(JsOutputOption.DETAILED); +// } +// +// // Repro for bug #9518 +// public void testIncrementalRecompile_jsPropertyConsistencyCheck() +// throws UnableToCompleteException, +// IOException, InterruptedException { +// // Supertype defines the getter. +// MockJavaResource superType = +// JavaResourceBase.createMockJavaResource( +// "com.foo.SuperType", +// "package com.foo;", +// "import jsinterop.annotations.JsProperty;", +// "public class SuperType {", +// " @JsProperty String getString() { return null; }", +// "}"); +// +// // Subtype defines the setter. +// MockJavaResource subType = +// JavaResourceBase.createMockJavaResource( +// "com.foo.SubType", +// "package com.foo;", +// "import jsinterop.annotations.JsProperty;", +// "public class SubType extends SuperType {", +// " @JsProperty void setString(String s) {}", +// "}"); +// +// MockJavaResource testEntryPoint = +// JavaResourceBase.createMockJavaResource( +// "com.foo.TestEntryPoint", +// "package com.foo;", +// "import com.google.gwt.core.client.EntryPoint;", +// "public class TestEntryPoint implements EntryPoint {", +// " public void onModuleLoad() {", +// // Create Impl and pass it to JS but do not explicitly call m +// " new SubType();", +// " }", +// "}"); +// +// MockResource moduleResource = +// JavaResourceBase.createMockResource( +// "com/foo/TestModule.gwt.xml", +// "", +// " ", +// " ", +// ""); +// +// MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); +// File relinkApplicationDir = createTempDir(); +// +// // Perform a first compile. +// compileToJs(relinkApplicationDir, "com.foo.TestModule", +// Lists.newArrayList(moduleResource, testEntryPoint, subType, superType), +// relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); +// +// // Invalidate ONLY the subtype. The types referred by the parameters of supertype methods are +// // going to be reference only which means that the supertype property will have a reference +// // to a JClassType for "java.lang.String" that isExternal() and is different from the +// // (non external) reference in the supertype. +// relinkMinimalRebuildCache.markSourceFileStale("com/foo/SubType.java"); +// compileToJs(relinkApplicationDir, "com.foo.TestModule", Lists. newArrayList(), +// relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); +// } +// +// public void testIncrementalRecompile_invalidatePreamble() throws UnableToCompleteException, +// IOException, InterruptedException { +// MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); +// File relinkApplicationDir = createTempDir(); +// +// // Perform a first compile. +// compileToJs(relinkApplicationDir, "com.foo.SimpleModule", +// Lists.newArrayList(simpleModuleResource, emptyEntryPointResource), +// relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); +// // On first compile nothing is explicitly stale, only implicitly stale. +// assertEquals(0, relinkMinimalRebuildCache.getStaleTypeNames().size()); +// +// // Recompile with a deep change that invalidates the preamble. +// relinkMinimalRebuildCache.markSourceFileStale("java/lang/Object.java"); +// compileToJs(relinkApplicationDir, "com.foo.SimpleModule", Lists. newArrayList(), +// relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); +// // Show that preamble invalidation marks everything stale. +// assertTrue(relinkMinimalRebuildCache.getProcessedStaleTypeNames().size() > 100); +// +// // Recompile again with a tiny change. Prove that it's not stuck repeatedly invalidating the +// // whole world. +// compileToJs(relinkApplicationDir, "com.foo.SimpleModule", +// Lists. newArrayList(emptyEntryPointResource), relinkMinimalRebuildCache, null, +// JsOutputOption.OBFUSCATED); +// // Show that only this little change is stale, not the whole world. +// assertEquals(2, getStaleTypeNames(relinkMinimalRebuildCache).size()); +// } +// +// public void testIncrementalRecompile_bridgeMethodOverrideChain() +// throws UnableToCompleteException, IOException, InterruptedException { +// MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); +// File relinkApplicationDir = createTempDir(); +// +// // Perform a first compile. +// compileToJs(relinkApplicationDir, "com.foo.SimpleModule", Lists.newArrayList( +// simpleModuleResource, overriddenMethodChainEntryPointResource, topResource, middleResource, +// bottomResource), relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); +// // On first compile nothing is explicitly stale, only implicitly stale. +// assertEquals(0, relinkMinimalRebuildCache.getStaleTypeNames().size()); +// +// // Recompile with a change to Bottom. +// relinkMinimalRebuildCache.markSourceFileStale("com/foo/Bottom.java"); +// compileToJs(relinkApplicationDir, "com.foo.SimpleModule", Lists. newArrayList(), +// relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); +// // Show that the third level bridge method override of Top.run() is seen to be live and thus +// // makes type com.foo.Bottom$Value live. +// assertTrue( +// relinkMinimalRebuildCache.getProcessedStaleTypeNames().contains("com.foo.Bottom$Value")); +// } +// +// public void testIncrementalRecompile_classLiteralNewReference() +// throws UnableToCompleteException, IOException, InterruptedException { +// checkIncrementalRecompile_classLiteralNewReference(JsOutputOption.OBFUSCATED); +// checkIncrementalRecompile_classLiteralNewReference(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_primitiveClassLiteralReference() +// throws UnableToCompleteException, IOException, InterruptedException { +// checkIncrementalRecompile_primitiveClassLiteralReference(JsOutputOption.OBFUSCATED); +// checkIncrementalRecompile_primitiveClassLiteralReference(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_superClassOrder() +// throws UnableToCompleteException, IOException, InterruptedException { +// // Linked output is sorted alphabetically except that super-classes come before sub-classes. If +// // on recompile a sub-class -> super-class relationship is lost then a sub-class with an +// // alphabetically earlier name might start linking out before the super-class. +// checkIncrementalRecompile_superClassOrder(JsOutputOption.OBFUSCATED); +// checkIncrementalRecompile_superClassOrder(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_superFromStaleInner() +// throws UnableToCompleteException, IOException, InterruptedException { +// checkIncrementalRecompile_superFromStaleInner(JsOutputOption.OBFUSCATED); +// checkIncrementalRecompile_superFromStaleInner(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_deterministicUiBinder() throws UnableToCompleteException, +// IOException, InterruptedException { +// checkIncrementalRecompile_deterministicUiBinder(JsOutputOption.OBFUSCATED); +// checkIncrementalRecompile_deterministicUiBinder(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_uiBinderCssChange() throws UnableToCompleteException, +// IOException, InterruptedException { +// checkIncrementalRecompile_uiBinderCssChange(JsOutputOption.OBFUSCATED); +// checkIncrementalRecompile_uiBinderCssChange(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_unstableGeneratorReferencesModifiedType() +// throws UnableToCompleteException, IOException, InterruptedException { +// checkIncrementalRecompile_unstableGeneratorReferencesModifiedType(JsOutputOption.OBFUSCATED); +// checkIncrementalRecompile_unstableGeneratorReferencesModifiedType(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_withErrors() +// throws UnableToCompleteException, IOException, InterruptedException { +// MockResource moduleResource = +// JavaResourceBase.createMockResource( +// "com/foo/Errors.gwt.xml", +// "", +// " ", +// " ", +// ""); +// +// MockJavaResource entryPointResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.ErrorsEntryPoint", +// "package com.foo;", +// "import com.google.gwt.core.client.EntryPoint;", +// "public class ErrorsEntryPoint implements EntryPoint {", +// " public void onModuleLoad() {", +// " Foo.foo();", +// " }", +// "}"); +// +// MockJavaResource fooResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.Foo", +// "package com.foo;", +// "public class Foo {", +// " public static void foo() {", +// " }", +// "}"); +// +// MockJavaResource fooResourceWithErrors = +// JavaResourceBase.createMockJavaResource( +// "com.foo.Foo", +// "package com.foo;", +// "public class Foo {", +// " public static void foo() {", +// " // x() method is not defined anywhere, should result in a compile error.", +// " x();", +// " }", +// "}"); +// +// MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache(); +// File applicationDir = createTempDir(); +// CompilerOptions compilerOptions = new CompilerOptionsImpl(); +// compilerOptions.setUseDetailedTypeIds(true); +// compilerOptions.setSourceLevel(SourceLevel.JAVA11); +// +// // Compile the application with no errors. +// compileToJs(TreeLogger.NULL, compilerOptions, applicationDir, "com.foo.Errors", +// Lists.newArrayList(moduleResource, entryPointResource, fooResource), minimalRebuildCache, +// emptySet, JsOutputOption.OBFUSCATED); +// +// // Recompile and expect error reporting. +// UnitTestTreeLogger.Builder builder = new UnitTestTreeLogger.Builder(); +// builder.setLowestLogLevel(TreeLogger.ERROR); +// builder.expectError("Line 5: The method x() is undefined for the type Foo", null); +// UnitTestTreeLogger errorLogger = builder.createLogger(); +// try { +// // Recompile but now the changed file has an error +// compileToJs(errorLogger, compilerOptions, applicationDir, "com.foo.Errors", +// Lists.newArrayList(moduleResource, entryPointResource, fooResourceWithErrors), +// minimalRebuildCache, +// emptySet, JsOutputOption.OBFUSCATED); +// fail("Compile should have failed"); +// } catch (UnableToCompleteException expected) { +// errorLogger.assertLogEntriesContainExpected(); +// } +// } +// +// public void testIncrementalRecompile_representedAsNative() +// throws UnableToCompleteException, IOException, InterruptedException { +// MockResource moduleResource = +// JavaResourceBase.createMockResource( +// "com/foo/RepresentedAsNative.gwt.xml", +// "", +// " ", +// " ", +// ""); +// +// MockResource entryPointResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.RepresentedAsNativeEntryPoint", +// "package com.foo;", +// "import com.google.gwt.core.client.EntryPoint;", +// "public class RepresentedAsNativeEntryPoint implements EntryPoint {", +// " public void onModuleLoad() {", +// " Double d = new Double(1d);", +// " }", +// "}"); +// +// MockResource modifiedEntryPointResource = +// JavaResourceBase.createMockJavaResource( +// "com.foo.RepresentedAsNativeEntryPoint", +// "package com.foo;", +// "import com.google.gwt.core.client.EntryPoint;", +// "public class RepresentedAsNativeEntryPoint implements EntryPoint {", +// " public void onModuleLoad() {", +// " Double d = new Double(\"1\");", +// " }", +// "}"); +// +// PrintWriterTreeLogger logger = new PrintWriterTreeLogger(); +// logger.setMaxDetail(TreeLogger.ERROR); +// +// MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache(); +// File applicationDir = createTempDir(); +// CompilerOptions compilerOptions = new CompilerOptionsImpl(); +// compilerOptions.setUseDetailedTypeIds(true); +// compilerOptions.setSourceLevel(SourceLevel.JAVA11); +// compilerOptions.setGenerateJsInteropExports(false); +// +// // Compile the application with no errors. +// compileToJs(logger, compilerOptions, applicationDir, "com.foo.RepresentedAsNative", +// Lists.newArrayList(moduleResource, entryPointResource), minimalRebuildCache, +// emptySet, JsOutputOption.OBFUSCATED); +// +// // Recompile but now the changed file has an error +// compileToJs(logger, compilerOptions, applicationDir, "com.foo.RepresentedAsNative", +// Lists.newArrayList(modifiedEntryPointResource), +// minimalRebuildCache, +// stringSet( +// "com.foo.RepresentedAsNativeEntryPoint", +// getEntryMethodHolderTypeName("com.foo.RepresentedAsNative")), +// JsOutputOption.OBFUSCATED); +// } +// +// public void testIncrementalRecompile_functionSignatureChange() throws UnableToCompleteException, +// IOException, InterruptedException { +// // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's +// // behavior is order dependent, and while still correct, will come out different in a recompile +// // with this change versus a from scratch compile with this change. +// checkIncrementalRecompile_functionSignatureChange(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_compileTimeConstantChange() throws UnableToCompleteException, +// IOException, InterruptedException { +// checkIncrementalRecompile_compileTimeConstantChange(JsOutputOption.DETAILED); +// checkIncrementalRecompile_compileTimeConstantChange(JsOutputOption.OBFUSCATED); +// } +// +// public void testIncrementalRecompile_transitivelyFoldableConstant() +// throws UnableToCompleteException, +// IOException, InterruptedException { +// checkIncrementalRecompile_transitivelyFoldableConstant(JsOutputOption.DETAILED); +// checkIncrementalRecompile_transitivelyFoldableConstant(JsOutputOption.OBFUSCATED); +// } +// +// public void testIncrementalRecompile_packagePrivateDispatch() throws UnableToCompleteException, +// IOException, InterruptedException { +// checkIncrementalRecompile_packagePrivateOverride(JsOutputOption.OBFUSCATED); +// checkIncrementalRecompile_packagePrivateOverride(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_prettyOutput() +// throws UnableToCompleteException, IOException, InterruptedException { +// // Nominal tests for pretty output. Pretty and Obfuscated output share most of the same code +// // paths. +// checkIncrementalRecompile_typeHierarchyChange(JsOutputOption.PRETTY); +// checkIncrementalRecompile_unreachableIncompatibleChange(JsOutputOption.PRETTY); +// } +// +// public void testIncrementalRecompile_regularClassMadeIntoJsoClass() +// throws UnableToCompleteException, IOException, InterruptedException { +// // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's +// // behavior is order dependent, and while still correct, will come out different in a recompile +// // with this change versus a from scratch compile with this change. +// checkIncrementalRecompile_regularClassMadeIntoJsoClass(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_unreachableIncompatibleChange() +// throws UnableToCompleteException, IOException, InterruptedException { +// // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's +// // behavior is order dependent, and while still correct, will come out different in a recompile +// // with this change versus a from scratch compile with this change. +// checkIncrementalRecompile_unreachableIncompatibleChange(JsOutputOption.OBFUSCATED); +// checkIncrementalRecompile_unreachableIncompatibleChange(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_typeHierarchyChange() +// throws UnableToCompleteException, IOException, InterruptedException { +// checkIncrementalRecompile_typeHierarchyChange(JsOutputOption.OBFUSCATED); +// checkIncrementalRecompile_typeHierarchyChange(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_defaultMethod() +// throws UnableToCompleteException, IOException, InterruptedException { +// // Tests that default method on superclasses are correctly constructed +// checkIncrementalRecompile_defaultMethod(JsOutputOption.OBFUSCATED); +// checkIncrementalRecompile_defaultMethod(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_devirtualizeUnchangedJso() +// throws UnableToCompleteException, IOException, InterruptedException { +// // Tests that a JSO calls through interfaces are correctly devirtualized when compiling per file +// // and the JSOs nor their single impl interfaces are not stale. +// checkIncrementalRecompile_devirtualizeUnchangedJso(JsOutputOption.OBFUSCATED); +// checkIncrementalRecompile_devirtualizeUnchangedJso(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_devirtualizeString() +// throws UnableToCompleteException, IOException, InterruptedException { +// // Tests that String calls through interfaces are correctly devirtualized when compiling per +// // file and neither String nor CharSequence interface are stale. +// checkIncrementalRecompile_devirtualizeString(JsOutputOption.OBFUSCATED); +// checkIncrementalRecompile_devirtualizeString(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_devirtualizeComparable() +// throws UnableToCompleteException, IOException, InterruptedException { +// // Tests that Doublecalls through interfaces are correctly devirtualized when compiling per +// // file and neither String nor CharSequence interface are stale. +// checkIncrementalRecompile_devirtualizeComparable(JsOutputOption.OBFUSCATED); +// checkIncrementalRecompile_devirtualizeComparable(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_multipleClassGenerator() +// throws UnableToCompleteException, IOException, InterruptedException { +// // Tests that a Generated type that is not directly referenced from the rebound GWT.create() +// // call is still marked stale, regenerated, retraversed and output as JS. +// checkIncrementalRecompile_multipleClassGenerator(JsOutputOption.OBFUSCATED); +// checkIncrementalRecompile_multipleClassGenerator(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_singleJsoIntfDispatchChange() +// throws UnableToCompleteException, +// IOException, InterruptedException { +// // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's +// // behavior is order dependent, and while still correct, will come out different in a recompile +// // with this change versus a from scratch compile with this change. +// checkIncrementalRecompile_singleJsoIntfDispatchChange(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_dualJsoIntfDispatchChange() throws UnableToCompleteException, +// IOException, InterruptedException { +// // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's +// // behavior is order dependent, and while still correct, will come out different in a recompile +// // with this change versus a from scratch compile with this change. +// checkIncrementalRecompile_dualJsoIntfDispatchChange(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_generatorInputResourceChange() throws IOException, +// UnableToCompleteException, InterruptedException { +// // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's +// // behavior is order dependent, and while still correct, will come out different in a recompile +// // with this change versus a from scratch compile with this change. +// checkIncrementalRecompile_generatorInputResourceChange(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_invalidatedGeneratorOutputRerunsGenerator() +// throws UnableToCompleteException, IOException, InterruptedException { +// // BarReferencesFoo Generator hasn't run yet. +// assertEquals(0, BarReferencesFooGenerator.runCount); +// +// CompilerOptions compilerOptions = new CompilerOptionsImpl(); +// List sharedResources = +// Lists.newArrayList(barReferencesFooGeneratorModuleResource, generatorEntryPointResource); +// JsOutputOption output = JsOutputOption.OBFUSCATED; +// +// List originalResources = Lists.newArrayList(sharedResources); +// originalResources.add(fooResource); +// +// // Compile the app with original files, modify a file and do a per-file recompile. +// MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); +// File relinkApplicationDir = createTempDir(); +// compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", originalResources, +// relinkMinimalRebuildCache, emptySet, output); +// +// // BarReferencesFoo Generator has now been run once. +// assertEquals(1, BarReferencesFooGenerator.runCount); +// +// // Recompile with no changes, which should not trigger any Generator runs. +// compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", +// Lists.newArrayList(), relinkMinimalRebuildCache, emptySet, output); +// +// // Since there were no changes BarReferencesFoo Generator was not run again. +// assertEquals(1, BarReferencesFooGenerator.runCount); +// +// // Recompile with a modified Foo class, which should invalidate Bar which was generated by a +// // GWT.create() call in the entry point. +// compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", +// Lists.newArrayList(fooResource), relinkMinimalRebuildCache, +// stringSet("com.foo.TestEntryPoint", "com.foo.Foo", "com.foo.Bar"), output); +// +// // BarReferencesFoo Generator was run again. +// assertEquals(2, BarReferencesFooGenerator.runCount); +// } +// +// public void testIncrementalRecompile_invalidatedGeneratorOutputRerunsCascadedGenerators() +// throws UnableToCompleteException, IOException, InterruptedException { +// // Generators haven't run yet. +// assertEquals(0, CauseStringRebindGenerator.runCount); +// assertEquals(0, CauseShortRebindGenerator.runCount); +// assertEquals(0, FooResourceGenerator.runCount); +// +// CompilerOptions compilerOptions = new CompilerOptionsImpl(); +// List sharedResources = Lists.newArrayList(cascadingGeneratorModuleResource, +// generatorEntryPointResource, classNameToGenerateResource); +// JsOutputOption output = JsOutputOption.OBFUSCATED; +// +// List originalResources = Lists.newArrayList(sharedResources); +// +// // Compile the app with original files. +// MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); +// File relinkApplicationDir = createTempDir(); +// compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", originalResources, +// relinkMinimalRebuildCache, emptySet, output); +// +// // Generators have now been run once. +// assertEquals(1, CauseStringRebindGenerator.runCount); +// assertEquals(1, CauseShortRebindGenerator.runCount); +// assertEquals(1, FooResourceGenerator.runCount); +// +// // Recompile with no changes, which should not trigger any Generator runs. +// compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", +// Lists.newArrayList(), relinkMinimalRebuildCache, emptySet, output); +// +// // Since there were no changes Generators were not run again. +// assertEquals(1, CauseStringRebindGenerator.runCount); +// assertEquals(1, CauseShortRebindGenerator.runCount); +// assertEquals(1, FooResourceGenerator.runCount); +// +// // Recompile with a modified resource, which should invalidate the output of the +// // FooResourceGenerator and cascade the invalidate the Generators that triggered +// // FooResourceGenerator. +// compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", +// Lists.newArrayList(modifiedClassNameToGenerateResource), +// relinkMinimalRebuildCache, stringSet("com.foo.TestEntryPoint", "com.foo.Baz$InnerBaz", +// "com.foo.Bar", "com.foo.HasCustomContent", "com.foo.FooReplacementTwo"), output); +// +// // Generators were run again. +// assertEquals(2, CauseStringRebindGenerator.runCount); +// assertEquals(2, CauseShortRebindGenerator.runCount); +// assertEquals(2, FooResourceGenerator.runCount); +// } +// +// public void testIncrementalRecompile_carriesOverGeneratorArtifacts() +// throws UnableToCompleteException, +// IOException, InterruptedException { +// // Foo Generator hasn't run yet. +// assertEquals(0, FooResourceGenerator.runCount); +// +// CompilerOptions compilerOptions = new CompilerOptionsImpl(); +// List sharedResources = Lists.newArrayList(resourceReadingGeneratorModuleResource, +// referencesBarAndGeneratorEntryPointResource, classNameToGenerateResource, +// barReferencesFooResource); +// JsOutputOption output = JsOutputOption.OBFUSCATED; +// +// List originalResources = Lists.newArrayList(sharedResources); +// originalResources.add(fooResource); +// +// // Compile the app with original files. +// MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); +// File relinkApplicationDir = createTempDir(); +// compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", originalResources, +// relinkMinimalRebuildCache, emptySet, output); +// +// // Foo Generator has now been run once. +// assertEquals(1, FooResourceGenerator.runCount); +// // The bar.txt artifact was output. +// File barFile = new File(relinkApplicationDir.getPath() + File.separator + "com.foo.SimpleModule" +// + File.separator + "bar.txt"); +// assertTrue(barFile.exists()); +// +// // Recompile with just 1 file change, which should not trigger any Generator runs. +// compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", +// Lists. newArrayList(fooResource), relinkMinimalRebuildCache, +// stringSet("com.foo.Foo", "com.foo.Bar"), output); +// +// // Foo Generator was not run again. +// assertEquals(1, FooResourceGenerator.runCount); +// // But the bar.txt artifact was still output. +// barFile = new File(relinkApplicationDir.getPath() + File.separator + "com.foo.SimpleModule" +// + File.separator + "bar.txt"); +// assertTrue(barFile.exists()); +// } +// +// /** +// * Regression test for UnifyAST assertion failure problem in incremental SDM. +// */ +// public void testIncrementalRecompile_unifyASTAssertionRegression() +// throws UnableToCompleteException, IOException, InterruptedException { +// +// CompilerOptions compilerOptions = new CompilerOptionsImpl(); +// List originalResources = Lists.newArrayList(helloEntryPointResource, +// helloModuleResource); +// JsOutputOption output = JsOutputOption.OBFUSCATED; +// +// // Compile the app with original files. +// MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); +// File relinkApplicationDir = createTempDir(); +// compileToJs(compilerOptions, relinkApplicationDir, "com.foo.Hello", +// originalResources, relinkMinimalRebuildCache, emptySet, output); +// } +// +// public void testIncrementalRecompile_ctorReferenceChange() +// throws InterruptedException, IOException, UnableToCompleteException { +//// System.out.println("===== TEST: testIncrementalRecompile_ctorReferenceChange PRETTY ====="); +// checkIncrementalRecompile_ctorReferenceChange(JsOutputOption.PRETTY); +//// System.out.println("===== TEST: testIncrementalRecompile_ctorReferenceChange DETAILED ====="); +// checkIncrementalRecompile_ctorReferenceChange(JsOutputOption.DETAILED); +// } +// +// public void testIncrementalRecompile_methodReferenceChange() +// throws InterruptedException, IOException, UnableToCompleteException { +//// System.out.println("===== TEST: testIncrementalRecompile_methodReferenceChange PRETTY ====="); +// checkIncrementalRecompile_methodReferenceChange(JsOutputOption.PRETTY); +//// System.out.println("===== TEST: testIncrementalRecompile_methodReferenceChange DETAILED ====="); +// checkIncrementalRecompile_methodReferenceChange(JsOutputOption.DETAILED); +// } +// +// // passes +// public void testIncrementalRecompile_lambdaChange() +// throws InterruptedException, IOException, UnableToCompleteException { +//// System.out.println("===== TEST: testIncrementalRecompile_lambdaChange OBFUSCATED ====="); +// checkIncrementalRecompile_lambdaChange(JsOutputOption.OBFUSCATED); +//// System.out.println("===== TEST: testIncrementalRecompile_lambdaChange DETAILED ====="); +// checkIncrementalRecompile_lambdaChange(JsOutputOption.DETAILED); +// } +// +// // Method reference to a static method on another class; the reference target changes. +// public void testIncrementalRecompile_externalMethodReferenceChange() +// throws InterruptedException, IOException, UnableToCompleteException { +// checkIncrementalRecompile_externalMethodReferenceChange(JsOutputOption.PRETTY); +// checkIncrementalRecompile_externalMethodReferenceChange(JsOutputOption.DETAILED); +// } + + // Method reference to a static method on another class; that other class's implementation changes. + public void testIncrementalRecompile_externalMethodReferenceTargetChange() + throws InterruptedException, IOException, UnableToCompleteException { + checkIncrementalRecompile_externalMethodReferenceTargetChange(JsOutputOption.PRETTY); + checkIncrementalRecompile_externalMethodReferenceTargetChange(JsOutputOption.DETAILED); } private void checkIncrementalRecompile_noop(JsOutputOption output) throws UnableToCompleteException, @@ -2387,6 +2426,263 @@ private void checkIncrementalRecompile_typeHierarchyChange(JsOutputOption output stringSet("com.foo.TestEntryPoint", "com.foo.ModelC", "com.foo.ModelD"), output); } + private void checkIncrementalRecompile_ctorReferenceChange(JsOutputOption output) throws InterruptedException, IOException, UnableToCompleteException { + MockResource samInterface = JavaResourceBase.createMockJavaResource( + "com.foo.Producer", + "package com.foo;", + "public interface Producer {", + " Object get();", + "}" + ); + MockResource classA = JavaResourceBase.createMockJavaResource( + "com.foo.A", + "package com.foo;", + "public class A {", + " public A() {}", + "}" + ); + MockResource classB = JavaResourceBase.createMockJavaResource( + "com.foo.B", + "package com.foo;", + "public class B {", + " public B() {}", + "}" + ); + MockResource staticMethod = JavaResourceBase.createMockJavaResource( + "com.foo.Stream", + "package com.foo;", + "public class Stream {", + " public static Stream generate(Producer p) {", + " return new Stream();", + " }", + "}" + ); + MockJavaResource before = JavaResourceBase.createMockJavaResource( + "com.foo.TestEntryPoint", + "package com.foo;", + "import com.google.gwt.core.client.EntryPoint;", + "public class TestEntryPoint implements EntryPoint {", + " A a = new A();", + " B b = new B();", + " public void onModuleLoad() {", + " Stream.generate(A::new);", + " }", + "}" + ); + MockJavaResource after = JavaResourceBase.createMockJavaResource( + "com.foo.TestEntryPoint", + "package com.foo;", + "import com.google.gwt.core.client.EntryPoint;", + "public class TestEntryPoint implements EntryPoint {", + " A a = new A();", + " B b = new B();", + " public void onModuleLoad() {", + " Stream.generate(B::new);", + " }", + "}" + ); + checkRecompiledModifiedApp("com.foo.SimpleModule", Lists.newArrayList(simpleModuleResource, samInterface, classA, classB, staticMethod), before, after, stringSet("com.foo.TestEntryPoint", "com.foo.TestEntryPoint$0methodref$Type", getEntryMethodHolderTypeName("com.foo.SimpleModule")), output); + } + + private void checkIncrementalRecompile_methodReferenceChange(JsOutputOption output) throws InterruptedException, IOException, UnableToCompleteException { + MockResource samInterface = JavaResourceBase.createMockJavaResource( + "com.foo.Producer", + "package com.foo;", + "public interface Producer {", + " Object get();", + "}" + ); + MockResource staticMethod = JavaResourceBase.createMockJavaResource( + "com.foo.Stream", + "package com.foo;", + "public class Stream {", + " public static Stream generate(Producer p) {", + " return new Stream();", + " }", + "}" + ); + MockJavaResource before = JavaResourceBase.createMockJavaResource( + "com.foo.TestEntryPoint", + "package com.foo;", + "import com.google.gwt.core.client.EntryPoint;", + "public class TestEntryPoint implements EntryPoint {", + " public void onModuleLoad() {", + " Stream.generate(this::a);", + " }", + " public Object a() {", + " return null;", + " }", + " public String b() {", + " return null;", + " }", + "}" + ); + MockJavaResource after = JavaResourceBase.createMockJavaResource( + "com.foo.TestEntryPoint", + "package com.foo;", + "import com.google.gwt.core.client.EntryPoint;", + "public class TestEntryPoint implements EntryPoint {", + " public void onModuleLoad() {", + " Stream.generate(this::b);", + " }", + " public Object a() {", + " return null;", + " }", + " public String b() {", + " return null;", + " }", + "}" + ); + checkRecompiledModifiedApp("com.foo.SimpleModule", Lists.newArrayList(simpleModuleResource, samInterface, staticMethod), before, after, stringSet("com.foo.TestEntryPoint", "com.foo.TestEntryPoint$0methodref$Type", getEntryMethodHolderTypeName("com.foo.SimpleModule")), output); + } + + private void checkIncrementalRecompile_lambdaChange(JsOutputOption output) throws InterruptedException, IOException, UnableToCompleteException { + MockResource samInterface = JavaResourceBase.createMockJavaResource( + "com.foo.Producer", + "package com.foo;", + "public interface Producer {", + " Object get();", + "}" + ); + MockResource staticMethod = JavaResourceBase.createMockJavaResource( + "com.foo.Stream", + "package com.foo;", + "public class Stream {", + " public static Stream generate(Producer p) {", + " return new Stream();", + " }", + "}" + ); + MockJavaResource before = JavaResourceBase.createMockJavaResource( + "com.foo.TestEntryPoint", + "package com.foo;", + "import com.google.gwt.core.client.EntryPoint;", + "public class TestEntryPoint implements EntryPoint {", + " public void onModuleLoad() {", + " Stream.generate(() -> new Object());", + " }", + "}" + ); + MockJavaResource after = JavaResourceBase.createMockJavaResource( + "com.foo.TestEntryPoint", + "package com.foo;", + "import com.google.gwt.core.client.EntryPoint;", + "public class TestEntryPoint implements EntryPoint {", + " public void onModuleLoad() {", + " Stream.generate(() -> new String());", + " }", + "}" + ); + checkRecompiledModifiedApp("com.foo.SimpleModule", Lists.newArrayList(simpleModuleResource, samInterface, staticMethod), before, after, stringSet("com.foo.TestEntryPoint", "com.foo.TestEntryPoint$lambda$0$Type", getEntryMethodHolderTypeName("com.foo.SimpleModule")), output); + } + + // Method reference to a static method on another class; the reference target changes. + private void checkIncrementalRecompile_externalMethodReferenceChange(JsOutputOption output) + throws InterruptedException, IOException, UnableToCompleteException { + MockResource samInterface = JavaResourceBase.createMockJavaResource( + "com.foo.Producer", + "package com.foo;", + "public interface Producer {", + " Object get();", + "}" + ); + MockResource helper = JavaResourceBase.createMockJavaResource( + "com.foo.Helper", + "package com.foo;", + "public class Helper {", + " public static Object a() { return null; }", + " public static String b() { return null; }", + "}" + ); + MockResource staticMethod = JavaResourceBase.createMockJavaResource( + "com.foo.Stream", + "package com.foo;", + "public class Stream {", + " public static Stream generate(Producer p) {", + " return new Stream();", + " }", + "}" + ); + MockJavaResource before = JavaResourceBase.createMockJavaResource( + "com.foo.TestEntryPoint", + "package com.foo;", + "import com.google.gwt.core.client.EntryPoint;", + "public class TestEntryPoint implements EntryPoint {", + " public void onModuleLoad() {", + " Stream.generate(Helper::a);", + " }", + "}" + ); + MockJavaResource after = JavaResourceBase.createMockJavaResource( + "com.foo.TestEntryPoint", + "package com.foo;", + "import com.google.gwt.core.client.EntryPoint;", + "public class TestEntryPoint implements EntryPoint {", + " public void onModuleLoad() {", + " Stream.generate(Helper::b);", + " }", + "}" + ); + checkRecompiledModifiedApp("com.foo.SimpleModule", + Lists.newArrayList(simpleModuleResource, samInterface, helper, staticMethod), + before, after, + stringSet("com.foo.TestEntryPoint", + "com.foo.TestEntryPoint$0methodref$Type", + getEntryMethodHolderTypeName("com.foo.SimpleModule")), + output); + } + + // Method reference to a static method on another class; that other class's implementation changes. + private void checkIncrementalRecompile_externalMethodReferenceTargetChange(JsOutputOption output) + throws InterruptedException, IOException, UnableToCompleteException { + MockResource samInterface = JavaResourceBase.createMockJavaResource( + "com.foo.Producer", + "package com.foo;", + "public interface Producer {", + " Object get();", + "}" + ); + MockResource staticMethod = JavaResourceBase.createMockJavaResource( + "com.foo.Stream", + "package com.foo;", + "public class Stream {", + " public static Stream generate(Producer p) {", + " return new Stream();", + " }", + "}" + ); + MockResource entryPoint = JavaResourceBase.createMockJavaResource( + "com.foo.TestEntryPoint", + "package com.foo;", + "import com.google.gwt.core.client.EntryPoint;", + "public class TestEntryPoint implements EntryPoint {", + " public void onModuleLoad() {", + " Stream.generate(Helper::make);", + " }", + "}" + ); + MockJavaResource before = JavaResourceBase.createMockJavaResource( + "com.foo.Helper", + "package com.foo;", + "public class Helper {", + " public static Object make() { return new Object(); }", + "}" + ); + MockJavaResource after = JavaResourceBase.createMockJavaResource( + "com.foo.Helper", + "package com.foo;", + "public class Helper {", + " public static Object make() { return \"changed\"; }", + "}" + ); + checkRecompiledModifiedApp("com.foo.SimpleModule", + Lists.newArrayList(simpleModuleResource, samInterface, staticMethod, entryPoint), + before, after, + stringSet("com.foo.Helper", + "com.foo.TestEntryPoint$0methodref$Type"), + output); + } + private void checkIncrementalRecompile_singleJsoIntfDispatchChange(JsOutputOption output) throws UnableToCompleteException, IOException, InterruptedException { CompilerOptions compilerOptions = new CompilerOptionsImpl(); @@ -2632,8 +2928,10 @@ private void checkRecompiledModifiedApp( // Compile the app with original files, modify a file and do a per-file recompile. MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); File relinkApplicationDir = createTempDir(); + System.out.println("--- compile #1: original from-scratch ---"); String originalAppFromScratchJs = compileToJs(compilerOptions, relinkApplicationDir, moduleName, originalResources, relinkMinimalRebuildCache, emptySet, output); + System.out.println("--- compile #2: incremental recompile ---"); String modifiedAppRelinkedJs = compileToJs(compilerOptions, relinkApplicationDir, moduleName, Lists. newArrayList(modifiedResource), relinkMinimalRebuildCache, expectedStaleTypeNamesOnModify, output); @@ -2641,6 +2939,7 @@ Lists. newArrayList(modifiedResource), relinkMinimalRebuildCache, // Compile the app from scratch with the modified file. MinimalRebuildCache fromScratchMinimalRebuildCache = new MinimalRebuildCache(); File fromScratchApplicationDir = createTempDir(); + System.out.println("--- compile #3: modified from-scratch ---"); String modifiedAppFromScratchJs = compileToJs(compilerOptions, fromScratchApplicationDir, moduleName, modifiedResources, fromScratchMinimalRebuildCache, emptySet, output); @@ -2656,7 +2955,7 @@ Lists. newArrayList(modifiedResource), relinkMinimalRebuildCache, // If per-file compiles properly avoids global-knowledge dependencies and correctly invalidates // referencing types when a type changes, then the relinked and from scratch JS will be // identical. - assertTrue(modifiedAppRelinkedJs.equals(modifiedAppFromScratchJs)); + assertEquals(modifiedAppRelinkedJs, modifiedAppFromScratchJs); } private String compileToJs(File applicationDir, String moduleName, @@ -2673,7 +2972,7 @@ private String compileToJs(CompilerOptions compilerOptions, File applicationDir, JsOutputOption output) throws IOException, UnableToCompleteException, InterruptedException { PrintWriterTreeLogger logger = new PrintWriterTreeLogger(); - logger.setMaxDetail(TreeLogger.ERROR); + logger.setMaxDetail(TreeLogger.WARN); return compileToJs(logger, compilerOptions, applicationDir, moduleName, applicationResources, minimalRebuildCache, expectedProcessedStaleTypeNames, output); } From d257f0b584f8dd292a142c34ae70855fd082563d Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Wed, 20 May 2026 13:50:31 -0500 Subject: [PATCH 02/12] Roll back logging --- .../google/gwt/dev/MinimalRebuildCache.java | 83 ------------------- .../com/google/gwt/dev/jjs/impl/UnifyAst.java | 53 +----------- 2 files changed, 1 insertion(+), 135 deletions(-) diff --git a/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java b/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java index 8cb0cd08afa..d8ad7256ad2 100644 --- a/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java +++ b/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java @@ -301,30 +301,6 @@ public Set computeAndClearStaleTypesCache(TreeLogger logger, JTypeOracle Set modifiedTypeNames = computeModifiedTypeNames(); - // DIAG: trace methodref types through the stale type computation pipeline - Set methodrefTypes = Sets.newHashSet(); - for (String name : modifiedTypeNames) { - if (name.contains("methodref")) { - methodrefTypes.add(name); - } - } - if (!methodrefTypes.isEmpty()) { - logger.log(TreeLogger.WARN, "DIAG: methodref types in modifiedTypeNames = " + methodrefTypes); - } else { - // Check if they exist in the nested types map at all - for (String cuName : modifiedCompilationUnitNames) { - Collection nested = nestedTypeNamesByUnitTypeName.get(cuName); - for (String n : nested) { - if (n.contains("methodref")) { - logger.log(TreeLogger.WARN, "DIAG: methodref nested type '" + n - + "' found under CU '" + cuName + "' but NOT in modifiedTypeNames"); - } - } - } - logger.log(TreeLogger.WARN, "DIAG: no methodref types in modifiedTypeNames. " - + "modifiedCompilationUnitNames = " + modifiedCompilationUnitNames); - } - // Accumulate the names of stale types resulting from some known type or resource modifications, // using various patterns (sub types, referencing types, etc). { @@ -346,31 +322,9 @@ public Set computeAndClearStaleTypesCache(TreeLogger logger, JTypeOracle // probably make GWTRPC output incompatible with a server anyway (and thus already forces a // restart). - // DIAG: check if methodref types are being removed as synthetic - Set methodrefInStale = Sets.newHashSet(); - for (String name : staleTypeNames) { - if (name.contains("methodref")) { - methodrefInStale.add(name); - } - } - if (!methodrefInStale.isEmpty()) { - logger.log(TreeLogger.WARN, "DIAG: methodref types in staleTypeNames before synthetic removal = " - + methodrefInStale); - logger.log(TreeLogger.WARN, "DIAG: SYNTHETIC_TYPE_NAMES contains any? = " - + !Sets.intersection(JProgram.SYNTHETIC_TYPE_NAMES, methodrefInStale).isEmpty()); - } - staleTypeNames.removeAll(JProgram.SYNTHETIC_TYPE_NAMES); } - // DIAG: check reachability filtering - Set methodrefBeforeReachability = Sets.newHashSet(); - for (String name : staleTypeNames) { - if (name.contains("methodref")) { - methodrefBeforeReachability.add(name); - } - } - /* * Filter for just those stale types that are actually reachable. Since if they're not reachable * we don't want to artificially traverse them and unnecessarily reveal dependency problems. And @@ -386,43 +340,6 @@ public Set computeAndClearStaleTypesCache(TreeLogger logger, JTypeOracle filteredStaleTypeNames.addAll(modifiedTypeNames); copyCollection(filteredStaleTypeNames, staleTypeNames); - if (!methodrefBeforeReachability.isEmpty()) { - Set methodrefAfterReachability = Sets.newHashSet(); - for (String name : staleTypeNames) { - if (name.contains("methodref")) { - methodrefAfterReachability.add(name); - } - } - Set filteredOut = Sets.difference(methodrefBeforeReachability, methodrefAfterReachability); - if (!filteredOut.isEmpty()) { - logger.log(TreeLogger.WARN, "DIAG: methodref types FILTERED as unreachable = " + filteredOut); - logger.log(TreeLogger.WARN, "DIAG: lastReachableTypeNames contains them? "); - for (String name : filteredOut) { - logger.log(TreeLogger.WARN, "DIAG: " + name + " in lastReachableTypeNames = " - + lastReachableTypeNames.contains(name)); - } - } else { - logger.log(TreeLogger.WARN, "DIAG: methodref types survived reachability filter = " - + methodrefAfterReachability); - } - } - - // DIAG: log full stale types set and check for specific types - { - Set appTypes = Sets.newHashSet(); - for (String name : staleTypeNames) { - if (name.startsWith("com.foo.")) { - appTypes.add(name); - } - } - logger.log(TreeLogger.WARN, "DIAG: final staleTypeNames (com.foo.*) = " + appTypes); - logger.log(TreeLogger.WARN, "DIAG: Helper in staleTypeNames = " + staleTypeNames.contains("com.foo.Helper")); - logger.log(TreeLogger.WARN, "DIAG: Helper in lastReachableTypeNames = " + lastReachableTypeNames.contains("com.foo.Helper")); - // Check what references Helper - Collection refsToHelper = typeNamesByReferencingTypeName.get("com.foo.Helper"); - logger.log(TreeLogger.WARN, "DIAG: types referencing Helper = " + refsToHelper); - } - // These log lines can be expensive. if (logger.isLoggable(TreeLogger.DEBUG)) { logger.log(TreeLogger.DEBUG, "known modified types = " + modifiedTypeNames); 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 84f4ea83e72..c9bcd2ead4e 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 @@ -928,17 +928,6 @@ public void exec() throws UnableToCompleteException { + "Generator has legitimately stopped creating these types."); } // Record the list of names of stale types that were processed, for test assertion purposes. - Set methodrefInFullFlow = Sets.newHashSet(); - for (String name : fullFlowTypes) { - if (name.contains("methodref")) { - methodrefInFullFlow.add(name); - } - } - if (methodrefInFullFlow.isEmpty()) { - logger.log(TreeLogger.WARN, "DIAG: setProcessedStaleTypeNames: NO methodref types in fullFlowTypes"); - } else { - logger.log(TreeLogger.WARN, "DIAG: setProcessedStaleTypeNames: methodref in fullFlowTypes = " + methodrefInFullFlow); - } minimalRebuildCache.setProcessedStaleTypeNames(fullFlowTypes); } @@ -973,35 +962,16 @@ public void exec() throws UnableToCompleteException { * temporarily ignored. */ private void fullFlowIntoRemainingStaleTypes() { - Set remaining = computeRemainingStaleTypeNames(); - logger.log(TreeLogger.WARN, "DIAG: fullFlowIntoRemainingStaleTypes remaining = " + remaining); - for (String name : remaining) { - if (name.contains("methodref")) { - logger.log(TreeLogger.WARN, "DIAG: fullFlowIntoRemainingStaleTypes considering: " + name); - } - } - for (String staleTypeName : remaining) { + for (String staleTypeName : computeRemainingStaleTypeNames()) { JDeclaredType staleType = internalFindType(staleTypeName, binaryNameBasedTypeLocator, false); if (staleType == null) { - if (staleTypeName.contains("methodref") || staleTypeName.contains("Helper")) { - logger.log(TreeLogger.WARN, "DIAG: fullFlowIntoRemainingStaleTypes: " + staleTypeName - + " NOT FOUND by internalFindType"); - } // The type is Generator output and so is not usually available in the list of types // provided from initial JDT compilation. The staleness marking process has already // handled this type by cascading the staleness marking onto the types that contain the // GWT.create() calls that process that create this type. continue; } - if (staleTypeName.contains("methodref")) { - logger.log(TreeLogger.WARN, "DIAG: fullFlowIntoRemainingStaleTypes: " + staleTypeName - + " FOUND, calling fullFlowIntoType"); - } - if (staleTypeName.contains("Helper")) { - logger.log(TreeLogger.WARN, "DIAG: fullFlowIntoRemainingStaleTypes: " + staleTypeName - + " FOUND, calling fullFlowIntoType"); - } // It's possible that the type was previously loaded before it was discovered to be stale (it // became stale as a result of a Generator execution). If this happens then the type will have // already been marked "reference only" in JProgram. This needs to be undone. @@ -1070,17 +1040,8 @@ private void assimilateSourceUnit(CompilationUnit unit, boolean reportErrors) { program.addType(type); // If we're compiling per file and we already have currently valid output for this type. if (incrementalCompile && !needsNewJs(type)) { - if (type.getName().contains("methodref") || type.getName().contains("Helper")) { - logger.log(TreeLogger.WARN, "DIAG: assimilateSourceUnit: " + type.getName() - + " has cached JS, marking reference-only"); - } // Then make sure we don't output new Js for this type. program.addReferenceOnlyType(type); - } else if (incrementalCompile) { - if (type.getName().contains("methodref") || type.getName().contains("Helper")) { - logger.log(TreeLogger.WARN, "DIAG: assimilateSourceUnit: " + type.getName() - + " needsNewJs=true (hasJs=" + minimalRebuildCache.hasJs(type.getName()) + ")"); - } } } for (JDeclaredType type : types) { @@ -1095,16 +1056,7 @@ private void assimilateSourceUnit(CompilationUnit unit, boolean reportErrors) { // Such a type won't have any cached JS and will need a full traversal to ensure it is // output (the full type with all fields and methods) as new JS. if (needsNewJs(type)) { - if (type.getName().contains("methodref")) { - logger.log(TreeLogger.WARN, "DIAG: assimilateSourceUnit: " + type.getName() - + " needsNewJs=true, calling fullFlowIntoType"); - } fullFlowIntoType(type); - } else { - if (type.getName().contains("methodref")) { - logger.log(TreeLogger.WARN, "DIAG: assimilateSourceUnit: " + type.getName() - + " needsNewJs=false, NOT calling fullFlowIntoType"); - } } } } @@ -1205,9 +1157,6 @@ private void fullFlowIntoType(JDeclaredType type) { if (fullFlowTypes.contains(typeName) || typeName.endsWith("package-info")) { return; } - if (typeName.contains("Helper") || typeName.contains("methodref")) { - logger.log(TreeLogger.WARN, "DIAG: fullFlowIntoType ADDING: " + typeName); - } // The traversal of this type will accumulate rebinder type to rebound type associations, but // the accumulation should start from scratch, so clear any existing associations that might // have been collected in previous compiles. From 0e03397a71fbce08f225cd442eee48f5766ccd9d Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Wed, 20 May 2026 14:43:09 -0500 Subject: [PATCH 03/12] FIx the tests so they actually reference the code they should --- dev/core/test/com/google/gwt/dev/CompilerTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dev/core/test/com/google/gwt/dev/CompilerTest.java b/dev/core/test/com/google/gwt/dev/CompilerTest.java index 85f04ddf8c7..56c90c838d5 100644 --- a/dev/core/test/com/google/gwt/dev/CompilerTest.java +++ b/dev/core/test/com/google/gwt/dev/CompilerTest.java @@ -2453,6 +2453,7 @@ private void checkIncrementalRecompile_ctorReferenceChange(JsOutputOption output "package com.foo;", "public class Stream {", " public static Stream generate(Producer p) {", + " p.get();", " return new Stream();", " }", "}" @@ -2497,6 +2498,7 @@ private void checkIncrementalRecompile_methodReferenceChange(JsOutputOption outp "package com.foo;", "public class Stream {", " public static Stream generate(Producer p) {", + " p.get();", " return new Stream();", " }", "}" @@ -2549,6 +2551,7 @@ private void checkIncrementalRecompile_lambdaChange(JsOutputOption output) throw "package com.foo;", "public class Stream {", " public static Stream generate(Producer p) {", + " p.get();", " return new Stream();", " }", "}" @@ -2599,6 +2602,7 @@ private void checkIncrementalRecompile_externalMethodReferenceChange(JsOutputOpt "package com.foo;", "public class Stream {", " public static Stream generate(Producer p) {", + " p.get();", " return new Stream();", " }", "}" @@ -2647,6 +2651,7 @@ private void checkIncrementalRecompile_externalMethodReferenceTargetChange(JsOut "package com.foo;", "public class Stream {", " public static Stream generate(Producer p) {", + " p.get();", " return new Stream();", " }", "}" From f68e40275d673d5bb46ff435eae1bd8501a5f57a Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Wed, 20 May 2026 15:22:05 -0500 Subject: [PATCH 04/12] Restore all test for this bug, put the expected fixes back --- .../google/gwt/dev/MinimalRebuildCache.java | 9 +-- .../impl/ResolveRuntimeTypeReferences.java | 49 +++++++------- .../test/com/google/gwt/dev/CompilerTest.java | 64 +++++++++---------- 3 files changed, 62 insertions(+), 60 deletions(-) diff --git a/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java b/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java index d8ad7256ad2..f336986767b 100644 --- a/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java +++ b/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java @@ -22,6 +22,7 @@ import com.google.gwt.dev.javac.GeneratedUnit; import com.google.gwt.dev.javac.Shared; import com.google.gwt.dev.jjs.JsSourceMap; +import com.google.gwt.dev.jjs.ast.JDeclaredType; import com.google.gwt.dev.jjs.ast.JProgram; import com.google.gwt.dev.jjs.ast.JTypeOracle; import com.google.gwt.dev.jjs.ast.JTypeOracle.ImmediateTypeRelations; @@ -33,7 +34,6 @@ import com.google.gwt.thirdparty.guava.common.annotations.VisibleForTesting; import com.google.gwt.thirdparty.guava.common.base.Objects; import com.google.gwt.thirdparty.guava.common.base.Predicates; -import com.google.gwt.dev.jjs.ast.JDeclaredType; import com.google.gwt.thirdparty.guava.common.collect.HashMultimap; import com.google.gwt.thirdparty.guava.common.collect.ImmutableList; import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet; @@ -336,9 +336,10 @@ public Set computeAndClearStaleTypesCache(TreeLogger logger, JTypeOracle * tracked by RapidTypeAnalyzer and would be incorrectly filtered out, causing their cached JS * to never be cleared and stale output to be reused. */ - Set filteredStaleTypeNames = filterUnreachableTypeNames(staleTypeNames); - filteredStaleTypeNames.addAll(modifiedTypeNames); - copyCollection(filteredStaleTypeNames, staleTypeNames); +// Set filteredStaleTypeNames = filterUnreachableTypeNames(staleTypeNames); +// filteredStaleTypeNames.addAll(modifiedTypeNames); +// copyCollection(filteredStaleTypeNames, staleTypeNames); + copyCollection(filterUnreachableTypeNames(staleTypeNames), staleTypeNames); // These log lines can be expensive. if (logger.isLoggable(TreeLogger.DEBUG)) { diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ResolveRuntimeTypeReferences.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ResolveRuntimeTypeReferences.java index ce3dbaf0c3e..9762734a6fc 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/ResolveRuntimeTypeReferences.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ResolveRuntimeTypeReferences.java @@ -80,7 +80,7 @@ public static class IntTypeMapper implements Serializable, TypeMapper typeIdByTypeName = Maps.newHashMap(); - private final List recycledIds = Lists.newArrayList(); +// private final List recycledIds = Lists.newArrayList(); private int nextAvailableId = 0; @Override @@ -93,8 +93,8 @@ public void copyFrom(TypeMapper that) { this.nextAvailableId = from.nextAvailableId; this.typeIdByTypeName.clear(); this.typeIdByTypeName.putAll(from.typeIdByTypeName); - this.recycledIds.clear(); - this.recycledIds.addAll(from.recycledIds); +// this.recycledIds.clear(); +// this.recycledIds.addAll(from.recycledIds); } @VisibleForTesting @@ -113,33 +113,34 @@ public JIntLiteral get(JType type) { public JIntLiteral getOrCreateTypeId(JType type) { String typeName = type.getName(); if (!typeIdByTypeName.containsKey(typeName)) { - int nextId; - if (!recycledIds.isEmpty()) { - nextId = recycledIds.remove(recycledIds.size() - 1); - } else { - nextId = nextAvailableId++; - } +// int nextId; +// if (!recycledIds.isEmpty()) { +// nextId = recycledIds.remove(recycledIds.size() - 1); +// } else { +// nextId = nextAvailableId++; +// } + int nextId = nextAvailableId++; typeIdByTypeName.put(typeName, nextId); } return get(type); } - /** - * Removes entries for types not in the given set and makes their IDs available for reuse. - * Existing live type IDs are not changed, preserving cached JS validity. - */ - public void pruneDeadTypes(Set liveTypeNames) { - Iterator> it = typeIdByTypeName.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = it.next(); - if (!liveTypeNames.contains(entry.getKey())) { - recycledIds.add(entry.getValue()); - it.remove(); - } - } - Collections.sort(recycledIds); - } +// /** +// * Removes entries for types not in the given set and makes their IDs available for reuse. +// * Existing live type IDs are not changed, preserving cached JS validity. +// */ +// public void pruneDeadTypes(Set liveTypeNames) { +// Iterator> it = typeIdByTypeName.entrySet().iterator(); +// while (it.hasNext()) { +// Map.Entry entry = it.next(); +// if (!liveTypeNames.contains(entry.getKey())) { +// recycledIds.add(entry.getValue()); +// it.remove(); +// } +// } +// Collections.sort(recycledIds); +// } } /** diff --git a/dev/core/test/com/google/gwt/dev/CompilerTest.java b/dev/core/test/com/google/gwt/dev/CompilerTest.java index 56c90c838d5..729f9a4e749 100644 --- a/dev/core/test/com/google/gwt/dev/CompilerTest.java +++ b/dev/core/test/com/google/gwt/dev/CompilerTest.java @@ -2051,38 +2051,38 @@ protected void setUp() throws Exception { // compileToJs(compilerOptions, relinkApplicationDir, "com.foo.Hello", // originalResources, relinkMinimalRebuildCache, emptySet, output); // } -// -// public void testIncrementalRecompile_ctorReferenceChange() -// throws InterruptedException, IOException, UnableToCompleteException { -//// System.out.println("===== TEST: testIncrementalRecompile_ctorReferenceChange PRETTY ====="); -// checkIncrementalRecompile_ctorReferenceChange(JsOutputOption.PRETTY); -//// System.out.println("===== TEST: testIncrementalRecompile_ctorReferenceChange DETAILED ====="); -// checkIncrementalRecompile_ctorReferenceChange(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_methodReferenceChange() -// throws InterruptedException, IOException, UnableToCompleteException { -//// System.out.println("===== TEST: testIncrementalRecompile_methodReferenceChange PRETTY ====="); -// checkIncrementalRecompile_methodReferenceChange(JsOutputOption.PRETTY); -//// System.out.println("===== TEST: testIncrementalRecompile_methodReferenceChange DETAILED ====="); -// checkIncrementalRecompile_methodReferenceChange(JsOutputOption.DETAILED); -// } -// -// // passes -// public void testIncrementalRecompile_lambdaChange() -// throws InterruptedException, IOException, UnableToCompleteException { -//// System.out.println("===== TEST: testIncrementalRecompile_lambdaChange OBFUSCATED ====="); -// checkIncrementalRecompile_lambdaChange(JsOutputOption.OBFUSCATED); -//// System.out.println("===== TEST: testIncrementalRecompile_lambdaChange DETAILED ====="); -// checkIncrementalRecompile_lambdaChange(JsOutputOption.DETAILED); -// } -// -// // Method reference to a static method on another class; the reference target changes. -// public void testIncrementalRecompile_externalMethodReferenceChange() -// throws InterruptedException, IOException, UnableToCompleteException { -// checkIncrementalRecompile_externalMethodReferenceChange(JsOutputOption.PRETTY); -// checkIncrementalRecompile_externalMethodReferenceChange(JsOutputOption.DETAILED); -// } + + public void testIncrementalRecompile_ctorReferenceChange() + throws InterruptedException, IOException, UnableToCompleteException { +// System.out.println("===== TEST: testIncrementalRecompile_ctorReferenceChange PRETTY ====="); + checkIncrementalRecompile_ctorReferenceChange(JsOutputOption.PRETTY); +// System.out.println("===== TEST: testIncrementalRecompile_ctorReferenceChange DETAILED ====="); + checkIncrementalRecompile_ctorReferenceChange(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_methodReferenceChange() + throws InterruptedException, IOException, UnableToCompleteException { +// System.out.println("===== TEST: testIncrementalRecompile_methodReferenceChange PRETTY ====="); + checkIncrementalRecompile_methodReferenceChange(JsOutputOption.PRETTY); +// System.out.println("===== TEST: testIncrementalRecompile_methodReferenceChange DETAILED ====="); + checkIncrementalRecompile_methodReferenceChange(JsOutputOption.DETAILED); + } + + // passes + public void testIncrementalRecompile_lambdaChange() + throws InterruptedException, IOException, UnableToCompleteException { +// System.out.println("===== TEST: testIncrementalRecompile_lambdaChange OBFUSCATED ====="); + checkIncrementalRecompile_lambdaChange(JsOutputOption.OBFUSCATED); +// System.out.println("===== TEST: testIncrementalRecompile_lambdaChange DETAILED ====="); + checkIncrementalRecompile_lambdaChange(JsOutputOption.DETAILED); + } + + // Method reference to a static method on another class; the reference target changes. + public void testIncrementalRecompile_externalMethodReferenceChange() + throws InterruptedException, IOException, UnableToCompleteException { + checkIncrementalRecompile_externalMethodReferenceChange(JsOutputOption.PRETTY); + checkIncrementalRecompile_externalMethodReferenceChange(JsOutputOption.DETAILED); + } // Method reference to a static method on another class; that other class's implementation changes. public void testIncrementalRecompile_externalMethodReferenceTargetChange() From 078ba418f576f7d2291d53a29948f0a929240fbe Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Wed, 27 May 2026 11:28:55 -0500 Subject: [PATCH 05/12] Another test of determinism --- .../test/com/google/gwt/dev/CompilerTest.java | 83 ++++++++++++++++++- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/dev/core/test/com/google/gwt/dev/CompilerTest.java b/dev/core/test/com/google/gwt/dev/CompilerTest.java index 729f9a4e749..afe6c26ea83 100644 --- a/dev/core/test/com/google/gwt/dev/CompilerTest.java +++ b/dev/core/test/com/google/gwt/dev/CompilerTest.java @@ -854,6 +854,7 @@ public class CompilerTest extends ArgProcessorTestBase { "}"); private Set emptySet = stringSet(); + private boolean requireDeterministicJs = true; @Override protected void setUp() throws Exception { @@ -2091,6 +2092,18 @@ public void testIncrementalRecompile_externalMethodReferenceTargetChange() checkIncrementalRecompile_externalMethodReferenceTargetChange(JsOutputOption.DETAILED); } + // Adding or removing a method reference changes the type set; type IDs drift but compilation succeeds. + public void testIncrementalRecompile_methodReferenceCountChange() + throws InterruptedException, IOException, UnableToCompleteException { + // Disable the requirement of deterministic JS, since this results in adding/removing types, + // which will result in more/fewer types each run. This leaves "holes" in our typeId space, so + // the generated JS will not be the same despite having the same input Java. The rest of the + // test method still has value though, so we only disable that one check. + requireDeterministicJs = false; + checkIncrementalRecompile_methodReferenceCountChange(JsOutputOption.PRETTY); + checkIncrementalRecompile_methodReferenceCountChange(JsOutputOption.DETAILED); + } + private void checkIncrementalRecompile_noop(JsOutputOption output) throws UnableToCompleteException, IOException, InterruptedException { MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); @@ -2688,6 +2701,68 @@ private void checkIncrementalRecompile_externalMethodReferenceTargetChange(JsOut output); } + private void checkIncrementalRecompile_methodReferenceCountChange(JsOutputOption output) + throws InterruptedException, IOException, UnableToCompleteException { + MockResource samInterface = JavaResourceBase.createMockJavaResource( + "com.foo.Producer", + "package com.foo;", + "public interface Producer {", + " Object get();", + "}" + ); + MockResource staticMethod = JavaResourceBase.createMockJavaResource( + "com.foo.Stream", + "package com.foo;", + "public class Stream {", + " public static Stream generate(Producer p) {", + " p.get();", + " return new Stream();", + " }", + "}" + ); + MockJavaResource oneRef = JavaResourceBase.createMockJavaResource( + "com.foo.TestEntryPoint", + "package com.foo;", + "import com.google.gwt.core.client.EntryPoint;", + "public class TestEntryPoint implements EntryPoint {", + " public void onModuleLoad() {", + " Stream.generate(this::a);", + " }", + " public Object a() { return null; }", + " public String b() { return null; }", + "}" + ); + MockJavaResource twoRefs = JavaResourceBase.createMockJavaResource( + "com.foo.TestEntryPoint", + "package com.foo;", + "import com.google.gwt.core.client.EntryPoint;", + "public class TestEntryPoint implements EntryPoint {", + " public void onModuleLoad() {", + " Stream.generate(this::a);", + " Stream.generate(this::b);", + " }", + " public Object a() { return null; }", + " public String b() { return null; }", + "}" + ); + List shared = Lists.newArrayList(simpleModuleResource, samInterface, staticMethod); + + // Add a new method reference before the existing one, both methodref types change + checkRecompiledModifiedApp("com.foo.SimpleModule", shared, oneRef, twoRefs, + stringSet("com.foo.TestEntryPoint", + "com.foo.TestEntryPoint$0methodref$Type", + "com.foo.TestEntryPoint$1methodref$Type", + getEntryMethodHolderTypeName("com.foo.SimpleModule")), + output); + + // Remove an earlier method reference, only the retained methodref type exists anymore + checkRecompiledModifiedApp("com.foo.SimpleModule", shared, twoRefs, oneRef, + stringSet("com.foo.TestEntryPoint", + "com.foo.TestEntryPoint$0methodref$Type", + getEntryMethodHolderTypeName("com.foo.SimpleModule")), + output); + } + private void checkIncrementalRecompile_singleJsoIntfDispatchChange(JsOutputOption output) throws UnableToCompleteException, IOException, InterruptedException { CompilerOptions compilerOptions = new CompilerOptionsImpl(); @@ -2959,8 +3034,12 @@ Lists. newArrayList(modifiedResource), relinkMinimalRebuildCache, // If per-file compiles properly avoids global-knowledge dependencies and correctly invalidates // referencing types when a type changes, then the relinked and from scratch JS will be - // identical. - assertEquals(modifiedAppRelinkedJs, modifiedAppFromScratchJs); + // identical. When the set of types changes (additions/removals), type IDs may drift because + // new types are appended to the ID space rather than inserted alphabetically; in that case + // we only verify that the output changed, not that it matches a fresh compile. + if (requireDeterministicJs) { + assertEquals(modifiedAppRelinkedJs, modifiedAppFromScratchJs); + } } private String compileToJs(File applicationDir, String moduleName, From 2084b4f3d83f32fac6392b203206868516bbbf63 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Wed, 27 May 2026 11:41:02 -0500 Subject: [PATCH 06/12] remove other attempted llm fixes --- .../google/gwt/dev/MinimalRebuildCache.java | 8 ---- .../impl/ResolveRuntimeTypeReferences.java | 44 ------------------- 2 files changed, 52 deletions(-) diff --git a/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java b/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java index f336986767b..c8a4143eb4d 100644 --- a/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java +++ b/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java @@ -330,15 +330,7 @@ public Set computeAndClearStaleTypesCache(TreeLogger logger, JTypeOracle * we don't want to artificially traverse them and unnecessarily reveal dependency problems. And * if they have become reachable, since they're missing JS, they will already be fully traversed * when seen in Unify. - * - * However, directly modified types must always remain stale regardless of reachability. - * Types with no runtime type ID (e.g. classes used only for static method calls) are not - * tracked by RapidTypeAnalyzer and would be incorrectly filtered out, causing their cached JS - * to never be cleared and stale output to be reused. */ -// Set filteredStaleTypeNames = filterUnreachableTypeNames(staleTypeNames); -// filteredStaleTypeNames.addAll(modifiedTypeNames); -// copyCollection(filteredStaleTypeNames, staleTypeNames); copyCollection(filterUnreachableTypeNames(staleTypeNames), staleTypeNames); // These log lines can be expensive. diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ResolveRuntimeTypeReferences.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ResolveRuntimeTypeReferences.java index 9762734a6fc..ffd620eff02 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/ResolveRuntimeTypeReferences.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ResolveRuntimeTypeReferences.java @@ -37,15 +37,12 @@ import com.google.gwt.thirdparty.guava.common.collect.Maps; import com.google.gwt.thirdparty.guava.common.collect.Multiset; import com.google.gwt.thirdparty.guava.common.collect.Multisets; -import com.google.gwt.thirdparty.guava.common.collect.Sets; import java.io.Serializable; import java.util.Collections; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Set; /** * Assigns and replaces JRuntimeTypeReference nodes with a type id literal. @@ -80,7 +77,6 @@ public static class IntTypeMapper implements Serializable, TypeMapper typeIdByTypeName = Maps.newHashMap(); -// private final List recycledIds = Lists.newArrayList(); private int nextAvailableId = 0; @Override @@ -93,8 +89,6 @@ public void copyFrom(TypeMapper that) { this.nextAvailableId = from.nextAvailableId; this.typeIdByTypeName.clear(); this.typeIdByTypeName.putAll(from.typeIdByTypeName); -// this.recycledIds.clear(); -// this.recycledIds.addAll(from.recycledIds); } @VisibleForTesting @@ -113,34 +107,12 @@ public JIntLiteral get(JType type) { public JIntLiteral getOrCreateTypeId(JType type) { String typeName = type.getName(); if (!typeIdByTypeName.containsKey(typeName)) { -// int nextId; -// if (!recycledIds.isEmpty()) { -// nextId = recycledIds.remove(recycledIds.size() - 1); -// } else { -// nextId = nextAvailableId++; -// } int nextId = nextAvailableId++; typeIdByTypeName.put(typeName, nextId); } return get(type); } - -// /** -// * Removes entries for types not in the given set and makes their IDs available for reuse. -// * Existing live type IDs are not changed, preserving cached JS validity. -// */ -// public void pruneDeadTypes(Set liveTypeNames) { -// Iterator> it = typeIdByTypeName.entrySet().iterator(); -// while (it.hasNext()) { -// Map.Entry entry = it.next(); -// if (!liveTypeNames.contains(entry.getKey())) { -// recycledIds.add(entry.getValue()); -// it.remove(); -// } -// } -// Collections.sort(recycledIds); -// } } /** @@ -298,22 +270,6 @@ private void execImpl() { runtimeTypeCollector.accept(program.getTypeClassLiteralHolder()); // TODO(stalcup): each module should have it's own ClassLiteralHolder or some agreed upon // location that is default accessible to all. -// -// // Prune dead type entries from the IntTypeMapper before assigning types. Dead entries -// // accumulate when types are removed between incremental compiles (e.g. renamed synthetic -// // method reference types). Their IDs are recycled for new types, preventing ID drift that -// // would cause incremental output to diverge from fresh compile output. -// if (typeMapper instanceof IntTypeMapper) { -// Set liveTypeNames = Sets.newHashSet(); -// for (JReferenceType type : runtimeTypeCollector.typesRequiringRuntimeIds.elementSet()) { -// liveTypeNames.add(type.getName()); -// } -// // Include the special types that assignTypes always registers first. -// liveTypeNames.add(program.getJavaScriptObject().getName()); -// liveTypeNames.add(program.getTypeJavaLangObject().getName()); -// liveTypeNames.add(program.getTypeJavaLangString().getName()); -// ((IntTypeMapper) typeMapper).pruneDeadTypes(liveTypeNames); -// } assignTypes(runtimeTypeCollector.typesRequiringRuntimeIds); From 0caa428373345446b042899109ea532d891d334d Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Wed, 27 May 2026 12:18:49 -0500 Subject: [PATCH 07/12] restore tests, log level --- .../test/com/google/gwt/dev/CompilerTest.java | 2376 ++++++++--------- 1 file changed, 1188 insertions(+), 1188 deletions(-) diff --git a/dev/core/test/com/google/gwt/dev/CompilerTest.java b/dev/core/test/com/google/gwt/dev/CompilerTest.java index afe6c26ea83..eaa0d6830e9 100644 --- a/dev/core/test/com/google/gwt/dev/CompilerTest.java +++ b/dev/core/test/com/google/gwt/dev/CompilerTest.java @@ -865,1193 +865,1193 @@ protected void setUp() throws Exception { CauseShortRebindGenerator.runCount = 0; } -// public void testAllValidArgs() { -// CompilerOptionsImpl options = new CompilerOptionsImpl(); -// Compiler.ArgProcessor argProcessor = new Compiler.ArgProcessor(options); -// -// assertProcessSuccess(argProcessor, new String[] {"-logLevel", "DEBUG", "-style", -// "PRETTY", "-ea", "-gen", "myGen", -// "-war", "myWar", "-workDir", "myWork", "-extra", "myExtra", "-incremental", -// "-localWorkers", "2", "-sourceLevel", "1.8", "c.g.g.h.H", "my.Module"}); -// -// assertEquals(new File("myGen").getAbsoluteFile(), -// options.getGenDir().getAbsoluteFile()); -// assertEquals(new File("myWar"), options.getWarDir()); -// assertEquals(new File("myWork"), options.getWorkDir()); -// assertEquals(new File("myExtra"), options.getExtraDir()); -// -// assertEquals(2, options.getLocalWorkers()); -// -// assertEquals(TreeLogger.DEBUG, options.getLogLevel()); -// assertEquals(JsOutputOption.PRETTY, options.getOutput()); -// assertTrue(options.isEnableAssertions()); -// assertTrue(options.shouldClusterSimilarFunctions()); -// assertTrue(options.shouldInlineLiteralParameters()); -// assertFalse(options.shouldOptimizeDataflow()); -// assertTrue(options.shouldOrdinalizeEnums()); -// assertTrue(options.shouldRemoveDuplicateFunctions()); -// assertTrue(options.isIncrementalCompileEnabled()); -// -// assertEquals(SourceLevel.JAVA8, options.getSourceLevel()); -// -// assertEquals(2, options.getModuleNames().size()); -// assertEquals("c.g.g.h.H", options.getModuleNames().get(0)); -// assertEquals("my.Module", options.getModuleNames().get(1)); -// } -// -// public void testDefaultArgs() { -// CompilerOptionsImpl options = new CompilerOptionsImpl(); -// Compiler.ArgProcessor argProcessor = new Compiler.ArgProcessor(options); -// -// assertProcessSuccess(argProcessor, new String[]{"c.g.g.h.H"}); -// -// assertEquals(null, options.getGenDir()); -// assertEquals(new File("war").getAbsoluteFile(), -// options.getWarDir().getAbsoluteFile()); -// assertEquals(null, options.getWorkDir()); -// assertEquals(null, options.getExtraDir()); -// -// assertEquals(TreeLogger.INFO, options.getLogLevel()); -// assertEquals(JsOutputOption.OBFUSCATED, options.getOutput()); -// assertFalse(options.isEnableAssertions()); -// assertTrue(options.shouldClusterSimilarFunctions()); -// assertTrue(options.shouldInlineLiteralParameters()); -// assertFalse(options.shouldOptimizeDataflow()); -// assertTrue(options.shouldOrdinalizeEnums()); -// assertTrue(options.shouldRemoveDuplicateFunctions()); -// assertFalse(options.isIncrementalCompileEnabled()); -// -// assertEquals(1, options.getLocalWorkers()); -// -// assertEquals(1, options.getModuleNames().size()); -// assertEquals("c.g.g.h.H", options.getModuleNames().get(0)); -// } -// -// public void testForbiddenArgs() { -// CompilerOptionsImpl options = new CompilerOptionsImpl(); -// Compiler.ArgProcessor argProcessor = new Compiler.ArgProcessor(options); -// -// assertProcessFailure(argProcessor, "Unknown argument", new String[]{"-out", "www"}); -// assertProcessFailure(argProcessor, "Source level must be one of", -// new String[]{"-sourceLevel", "ssss"}); -// assertProcessFailure(argProcessor, "Source level must be one of", -// new String[]{"-sourceLevel", "1.5"}); -// } -// -// /** -// * Tests ordering for emum {@link SourceLevel}. -// */ -// public void testSourceLevelOrdering() { -// SourceLevel[] sourceLevels = SourceLevel.values(); -// SourceLevel previousSourceLevel = sourceLevels[0]; -// for (int i = 1; i < sourceLevels.length; i++) { -// assertTrue(SourceLevel.versionCompare(previousSourceLevel.getStringValue(), -// sourceLevels[i].getStringValue()) < 0); -// previousSourceLevel = sourceLevels[i]; -// } -// } -// -// public void testSourceLevelSelection() { -// assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.4")); -// assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.5")); -// assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.6")); -// assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.6_26")); -// -// assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.7")); -// assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.8")); -// assertEquals(SourceLevel.JAVA9, SourceLevel.getBestMatchingVersion("9")); -// assertEquals(SourceLevel.JAVA10, SourceLevel.getBestMatchingVersion("10")); -// assertEquals(SourceLevel.JAVA11, SourceLevel.getBestMatchingVersion("11")); -// -// // not proper version strings => default to JAVA8. -// assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.6u3")); -// assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.6b3")); -// assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.7b3")); -// } -// -// public void testSourceLevelHighestVersion() { -// assertEquals(SourceLevel.values()[SourceLevel.values().length - 1], SourceLevel.getHighest()); -// } -// -// /** -// * Verify that a compile with a @JsType at least compiles successfully. -// */ -// public void testGwtCreateJsTypeRebindResult() throws Exception { -// CompilerOptions compilerOptions = new CompilerOptionsImpl(); -// compileToJs(compilerOptions, createTempDir(), "com.foo.SimpleModule", -// Lists.newArrayList(simpleModuleResource, gwtCreateEntryPointResource), -// new MinimalRebuildCache(), emptySet, JsOutputOption.OBFUSCATED); -// } -// -// /** -// * Test that some lightly referenced interface through a @JsFunction is included in the output. -// */ -// public void testReferenceThroughJsFunction() throws Exception { -// MockJavaResource someJsFunction = -// JavaResourceBase.createMockJavaResource( -// "com.foo.SomeJsFunction", -// "package com.foo;", -// "import jsinterop.annotations.JsFunction;", -// "@JsFunction", -// "public interface SomeJsFunction {", -// " void m();", -// "}"); -// -// MockJavaResource jsFunctionInterfaceImplementation = -// JavaResourceBase.createMockJavaResource( -// "com.foo.Impl", -// "package com.foo;", -// "public final class Impl implements SomeJsFunction {", -// " public void m() { SomeInterface.class.getName(); } ", -// "}"); -// -// MockJavaResource someInterface = -// JavaResourceBase.createMockJavaResource( -// "com.foo.SomeInterface", -// "package com.foo;", -// "public interface SomeInterface {", -// "}"); -// -// MockJavaResource testEntryPoint = -// JavaResourceBase.createMockJavaResource( -// "com.foo.TestEntryPoint", -// "package com.foo;", -// "import com.google.gwt.core.client.EntryPoint;", -// "public class TestEntryPoint implements EntryPoint {", -// " private static native void f(SomeJsFunction f) /*-{}-*/;", -// " public void onModuleLoad() {", -// // Create Impl and pass it to JS but do not explicitly call m -// " f(new Impl());", -// " }", -// "}"); -// -// MockResource moduleResource = -// JavaResourceBase.createMockResource( -// "com/foo/TestEntryPoint.gwt.xml", -// "", -// " ", -// " ", -// ""); -// -// CompilerOptions compilerOptions = new CompilerOptionsImpl(); -// String js = compileToJs(compilerOptions, createTempDir(), testEntryPoint.getTypeName(), -// Lists.newArrayList(moduleResource, testEntryPoint, someJsFunction, -// jsFunctionInterfaceImplementation, someInterface), -// new MinimalRebuildCache(), emptySet, JsOutputOption.DETAILED); -// // Make sure the referenced class literals ends up being included in the resulting JS. -// String classliteralHolderVarName = -// JjsUtils.mangleMemberName("com.google.gwt.lang.ClassLiteralHolder", -// JjsUtils.classLiteralFieldNameFromJavahTypeSignatureName( -// JjsUtils.javahSignatureFromName(someInterface.getTypeName()))); -// assertTrue(js.contains("var " + classliteralHolderVarName + " = ")); -// } -// -// /** -// * Tests that changing Js namespace name on an exported method comes out accurately. -// * -// *

An unrelated and non-updated @JsType is also included in each compile to verify that updated -// * exports do not forget non-edited items in a recompile. -// */ -// public void testChangeJsNamespaceOnMethod() throws Exception { -// CompilerOptions compilerOptions = new CompilerOptionsImpl(); -// compilerOptions.setUseDetailedTypeIds(true); -// compilerOptions.setGenerateJsInteropExports(true); -// -// MockJavaResource jsNamespaceFooResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.Foo", -// "package com.foo;", -// "import jsinterop.annotations.JsMethod;", -// "import jsinterop.annotations.JsType;", -// "@JsType public class Foo {", -// " @JsMethod(namespace=\"spazz\") public static void doStaticBar() {}", -// "}"); -// -// MockJavaResource regularFooResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.Foo", -// "package com.foo;", -// "import jsinterop.annotations.JsType;", -// "@JsType public class Foo {", -// " public static void doStaticBar() {}", -// "}"); -// -// checkRecompiledModifiedApp( -// compilerOptions, -// "com.foo.SimpleModule", -// Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), -// regularFooResource, -// jsNamespaceFooResource, -// stringSet("com.foo.Bar", "com.foo.Foo"), -// JsOutputOption.DETAILED); -// } -// -// /** -// * Tests that changing Js namespace on a class comes out accurately. -// * -// *

An unrelated and non-updated @JsType is also included in each compile to verify that updated -// * exports do not forget non-edited items in a recompile. -// */ -// public void testChangeJsNamespaceOnClass() throws Exception { -// CompilerOptions compilerOptions = new CompilerOptionsImpl(); -// compilerOptions.setUseDetailedTypeIds(true); -// compilerOptions.setGenerateJsInteropExports(true); -// -// MockJavaResource jsNamespaceFooResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.Foo", -// "package com.foo;", -// "import jsinterop.annotations.JsType;", -// "@JsType(namespace=\"spazz\") public class Foo {", -// " public static void doStaticBar() {}", -// "}"); -// -// MockJavaResource regularFooResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.Foo", -// "package com.foo;", -// "import jsinterop.annotations.JsType;", -// "@JsType public class Foo {", -// " public static void doStaticBar() {}", -// "}"); -// -// checkRecompiledModifiedApp( -// compilerOptions, -// "com.foo.SimpleModule", -// Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), -// regularFooResource, -// jsNamespaceFooResource, -// stringSet("com.foo.Bar", "com.foo.Foo"), -// JsOutputOption.DETAILED); -// } -// -// /** -// * Tests that changing @JsFunction name on an interface comes out accurately. -// * -// *

An unrelated and non-updated @JsType is also included in each compile to verify that updated -// * exports do not forget non-edited items in a recompile. -// */ -// public void testChangeJsFunction() throws Exception { -// CompilerOptions compilerOptions = new CompilerOptionsImpl(); -// compilerOptions.setUseDetailedTypeIds(true); -// compilerOptions.setGenerateJsInteropExports(true); -// -// MockJavaResource jsFunctionIFooResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.IFoo", -// "package com.foo;", -// "import jsinterop.annotations.JsFunction;", -// "@JsFunction public interface IFoo {", -// " int foo(int x);", -// "}"); -// -// MockJavaResource regularIFooResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.IFoo", -// "package com.foo;", -// "public interface IFoo {", -// " int foo(int x);", -// "}"); -// -// MockJavaResource fooResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.Foo", -// "package com.foo;", -// "public final class Foo implements IFoo {", -// " @Override public int foo(int x) { return 0; }", -// "}"); -// -// checkRecompiledModifiedApp( -// compilerOptions, -// "com.foo.SimpleModule", -// Lists.newArrayList( -// simpleModuleResource, entryPointResourceForFoo, fooResource, jsTypeBarResource), -// regularIFooResource, -// jsFunctionIFooResource, -// stringSet("com.foo.Bar", "com.foo.Foo", "com.foo.IFoo", "com.foo.TestEntryPoint"), -// JsOutputOption.DETAILED); -// } -// -// /** -// * Tests that toggling JsProperty methods in an interface comes out accurately. -// * -// *

An unrelated and non-updated @JsType is also included in each compile to verify that updated -// * exports do not forget non-edited items in a recompile. -// */ -// public void testChangeJsProperty() throws Exception { -// CompilerOptions compilerOptions = new CompilerOptionsImpl(); -// compilerOptions.setUseDetailedTypeIds(true); -// compilerOptions.setGenerateJsInteropExports(true); -// -// MockJavaResource jsPropertyIFooResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.IFoo", -// "package com.foo;", -// "import jsinterop.annotations.JsProperty;", -// "import jsinterop.annotations.JsType;", -// "@JsType public interface IFoo {", -// " @JsProperty int getX();", -// " @JsProperty int getY();", -// "}"); -// -// MockJavaResource regularIFooResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.IFoo", -// "package com.foo;", -// "import jsinterop.annotations.JsType;", -// "@JsType public interface IFoo {", -// " int getX();", -// " int getY();", -// "}"); -// -// MockJavaResource fooResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.Foo", -// "package com.foo;", -// "public class Foo implements IFoo {", -// " @Override public int getX() { return 0; }", -// " @Override public int getY() { return 0; }", -// "}"); -// -// checkRecompiledModifiedApp( -// compilerOptions, -// "com.foo.SimpleModule", -// Lists.newArrayList( -// simpleModuleResource, entryPointResourceForFoo, fooResource, jsTypeBarResource), -// regularIFooResource, -// jsPropertyIFooResource, -// stringSet("com.foo.Bar", "com.foo.Foo", "com.foo.IFoo", "com.foo.TestEntryPoint"), -// JsOutputOption.DETAILED); -// } -// -// /** -// * Tests that adding a @JsType annotation on a class comes out accurately and that removing it -// * comes out accurately as well. -// * -// *

An unrelated and non-updated @JsType is also included in each compile to verify that updated -// * exports do not forget non-edited items in a recompile. -// */ -// public void testChangeJsType() throws Exception { -// CompilerOptions compilerOptions = new CompilerOptionsImpl(); -// compilerOptions.setUseDetailedTypeIds(true); -// compilerOptions.setGenerateJsInteropExports(true); -// -// MockJavaResource jsTypeFooResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.Foo", -// "package com.foo;", -// "import jsinterop.annotations.JsType;", -// "@JsType public class Foo {", -// " void doInstanceBar() {}", -// " public static void doStaticBar() {}", -// "}"); -// -// MockJavaResource regularFooResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.Foo", "package com.foo;", "public class Foo {}"); -// -// checkRecompiledModifiedApp( -// compilerOptions, -// "com.foo.SimpleModule", -// Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), -// regularFooResource, -// jsTypeFooResource, -// stringSet("com.foo.Bar", "com.foo.Foo"), -// JsOutputOption.DETAILED); -// } -// -// /** -// * Tests that changing a prototype on a @JsType annotated class comes out accurately. -// * -// *

An unrelated and non-updated @JsType is also included in each compile to verify that updated -// * exports do not forget non-edited items in a recompile. -// */ -// public void testChangeJsTypeNative() throws Exception { -// CompilerOptions compilerOptions = new CompilerOptionsImpl(); -// compilerOptions.setUseDetailedTypeIds(true); -// compilerOptions.setGenerateJsInteropExports(true); -// -// MockJavaResource nativeFooResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.Foo", -// "package com.foo;", -// "import jsinterop.annotations.JsType;", -// "@JsType(isNative=true) public class Foo {", -// " public static native void doStaticBar();", -// "}"); -// -// MockJavaResource regularFooResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.Foo", -// "package com.foo;", -// "import jsinterop.annotations.JsType;", -// "@JsType public class Foo {", -// " public static void doStaticBar() {}", -// "}"); -// -// checkRecompiledModifiedApp( -// compilerOptions, -// "com.foo.SimpleModule", -// Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), -// regularFooResource, -// nativeFooResource, -// stringSet("com.foo.Bar", "com.foo.Foo"), -// JsOutputOption.DETAILED); -// } -// -// /** -// * Tests that adding a @JsIgnore annotation on a method comes out accurately and that removing -// * it comes out accurately as well. -// * -// *

An unrelated and non-updated @JsType is also included in each compile to verify that updated -// * exports do not forget non-edited items in a recompile. -// */ -// public void testChangeJsIgnore() throws Exception { -// CompilerOptions compilerOptions = new CompilerOptionsImpl(); -// compilerOptions.setUseDetailedTypeIds(true); -// compilerOptions.setGenerateJsInteropExports(true); -// -// MockJavaResource jsIgnoreFooResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.Foo", -// "package com.foo;", -// "import jsinterop.annotations.JsIgnore;", -// "import jsinterop.annotations.JsType;", -// "@JsType public class Foo {", -// " @JsIgnore public static void doStaticBar() {}", -// "}"); -// -// MockJavaResource regularFooResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.Foo", -// "package com.foo;", -// "import jsinterop.annotations.JsType;", -// "@JsType public class Foo {", -// " public static void doStaticBar() {}", -// "}"); -// -// checkRecompiledModifiedApp( -// compilerOptions, -// "com.foo.SimpleModule", -// Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), -// regularFooResource, -// jsIgnoreFooResource, -// stringSet("com.foo.Bar", "com.foo.Foo"), -// JsOutputOption.DETAILED); -// } -// -// public void testJsInteropNameCollision() throws Exception { -// MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache(); -// File applicationDir = Files.createTempDirectory("JsInteropNameCollision").toFile(); -// CompilerOptions compilerOptions = new CompilerOptionsImpl(); -// compilerOptions.setGenerateJsInteropExports(true); -// -// // Simple compile with one dialog.alert() export succeeds. -// compileToJs(compilerOptions, applicationDir, "com.foo.SimpleModule", Lists.newArrayList( -// simpleModuleResource, dialogEntryPointResource, simpleDialogResourceWithExport, -// complexDialogResourceSansExport), minimalRebuildCache, emptySet, JsOutputOption.OBFUSCATED); -// -// try { -// // Exporting a second dialog.alert() fails with an exported name collision. -// compileToJs(compilerOptions, applicationDir, "com.foo.SimpleModule", -// Lists. newArrayList(complexDialogResourceWithExport), minimalRebuildCache, -// emptySet, JsOutputOption.OBFUSCATED); -// fail("Compile should have failed"); -// } catch (UnableToCompleteException e) { -// // success -// } -// -// // Reverting to just a single dialog.alert() starts succeeding again. -// compileToJs(compilerOptions, applicationDir, "com.foo.SimpleModule", -// Lists.newArrayList(complexDialogResourceSansExport), minimalRebuildCache, -// stringSet("com.foo.SimpleDialog", "com.foo.ComplexDialog", "com.foo.TestEntryPoint"), -// JsOutputOption.OBFUSCATED); -// } -// -// public void testGwtCreateJsoRebindResult() throws Exception { -// try { -// compileToJs(createTempDir(), "com.foo.SimpleModule", -// Lists.newArrayList(simpleModuleResource, brokenGwtCreateEntryPointResource), -// new MinimalRebuildCache(), emptySet, JsOutputOption.OBFUSCATED); -// fail("Compile should have failed"); -// } catch (UnableToCompleteException e) { -// // success -// } -// } -// -// public void testNonZeroArgConstructorEntryPoint() throws Exception { -// MockResource moduleResource = -// JavaResourceBase.createMockResource( -// "com/foo/NonZeroArgConstructor.gwt.xml", -// "", -// " ", -// " ", -// ""); -// -// MockJavaResource entryPointResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.NonZeroArgConstructorEntryPoint", -// "package com.foo;", -// "import com.google.gwt.core.client.EntryPoint;", -// "public class NonZeroArgConstructorEntryPoint implements EntryPoint {", -// " public NonZeroArgConstructorEntryPoint(String s) {", -// " }", -// " public void onModuleLoad() {", -// " }", -// "}"); -// -// MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache(); -// File applicationDir = createTempDir(); -// CompilerOptions compilerOptions = new CompilerOptionsImpl(); -// -// UnitTestTreeLogger.Builder builder = new UnitTestTreeLogger.Builder(); -// builder.setLowestLogLevel(TreeLogger.ERROR); -// builder.expectError(Pattern.compile("Errors in .*"), null); -// builder.expectError("Line 3: Rebind result 'com.foo.NonZeroArgConstructorEntryPoint' " -// + "has no default (zero argument) constructors", null); -// UnitTestTreeLogger errorLogger = builder.createLogger(); -// try { -// // Simple compile with one dialog.alert() export succeeds. -// -// compileToJs(errorLogger, compilerOptions, applicationDir, "com.foo.NonZeroArgConstructor", -// Lists.newArrayList(moduleResource, entryPointResource), minimalRebuildCache, -// emptySet, JsOutputOption.OBFUSCATED); -// fail("Compile should have failed"); -// } catch (UnableToCompleteException expected) { -// errorLogger.assertCorrectLogEntries(); -// } -// } -// -// public void testDeterministicBuild_Draft_StackModeStrip() throws -// UnableToCompleteException, IOException { -// assertDeterministicBuild(HELLO_MODULE_STACKMODE_STRIP, 0); -// } -// -// public void testDeterministicBuild_Optimized_StackModeStrip() throws -// UnableToCompleteException, IOException { -// assertDeterministicBuild(HELLO_MODULE_STACKMODE_STRIP, 9); -// } -// -// public void testDeterministicBuild_Draft() throws UnableToCompleteException, IOException { -// assertDeterministicBuild(HELLO_MODULE, 0); -// } -// -// public void testDeterministicBuild_Optimized() throws UnableToCompleteException, IOException { -// assertDeterministicBuild(HELLO_MODULE, 9); -// } -// -// public void testSuccessfulCompile_jsoClassLiteralOrder() throws Exception { -// // Crafted resource to make sure the a native subclass is compiled before the JSO class, -// // In the case of native sublcasses the class hierarchy does not match the class literal -// // hierarchy. -// MockJavaResource nativeClassAndSubclass = -// JavaResourceBase.createMockJavaResource( -// "com.foo.MyNativeSubclass", -// "package com.foo;", -// "import jsinterop.annotations.JsType;", -// "@JsType(isNative=true)", -// "class NativeClass {", -// "}", -// "public class MyNativeSubclass extends NativeClass {", -// "}"); -// -// MockJavaResource testEntryPoint = -// JavaResourceBase.createMockJavaResource( -// "com.foo.MyEntryPoint", -// "package com.foo;", -// "import com.foo.MyNativeSubclass;", -// "public class MyEntryPoint extends MyNativeSubclass {", -// " public void onModuleLoad() {", -// " Object o = new Object();", -// " if (MyNativeSubclass.class.getName() == null) ", -// " o = new MyNativeSubclass();", -// // Make .clazz reachable so that class literals are emmitted with the respective -// // classses. -// " o.getClass();", -// " }", -// "}"); -// -// MockResource moduleResource = -// JavaResourceBase.createMockResource( -// "com/foo/MyEntryPoint.gwt.xml", -// "", -// " ", -// " ", -// ""); -// -// CompilerOptions compilerOptions = new CompilerOptionsImpl(); -// // Make sure it compiles successfully with no assertions -// compilerOptions.setEnableAssertions(true); -// compilerOptions.setGenerateJsInteropExports(true); -// compilerOptions.setOutput(JsOutputOption.PRETTY); -// compilerOptions.setOptimizationLevel(9); -// assertCompileSucceeds(compilerOptions, testEntryPoint.getTypeName(), -// Lists.newArrayList(moduleResource, nativeClassAndSubclass, testEntryPoint)); -// } -// -// // TODO(stalcup): add recompile tests for file deletion. -// -// public void testIncrementalRecompile_noop() throws UnableToCompleteException, IOException, -// InterruptedException { -// checkIncrementalRecompile_noop(JsOutputOption.OBFUSCATED); -// checkIncrementalRecompile_noop(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_dateStampChange() throws UnableToCompleteException, -// IOException, InterruptedException { -// checkIncrementalRecompile_dateStampChange(JsOutputOption.OBFUSCATED); -// checkIncrementalRecompile_dateStampChange(JsOutputOption.DETAILED); -// } -// -// // Repro for bug #9518 -// public void testIncrementalRecompile_jsPropertyConsistencyCheck() -// throws UnableToCompleteException, -// IOException, InterruptedException { -// // Supertype defines the getter. -// MockJavaResource superType = -// JavaResourceBase.createMockJavaResource( -// "com.foo.SuperType", -// "package com.foo;", -// "import jsinterop.annotations.JsProperty;", -// "public class SuperType {", -// " @JsProperty String getString() { return null; }", -// "}"); -// -// // Subtype defines the setter. -// MockJavaResource subType = -// JavaResourceBase.createMockJavaResource( -// "com.foo.SubType", -// "package com.foo;", -// "import jsinterop.annotations.JsProperty;", -// "public class SubType extends SuperType {", -// " @JsProperty void setString(String s) {}", -// "}"); -// -// MockJavaResource testEntryPoint = -// JavaResourceBase.createMockJavaResource( -// "com.foo.TestEntryPoint", -// "package com.foo;", -// "import com.google.gwt.core.client.EntryPoint;", -// "public class TestEntryPoint implements EntryPoint {", -// " public void onModuleLoad() {", -// // Create Impl and pass it to JS but do not explicitly call m -// " new SubType();", -// " }", -// "}"); -// -// MockResource moduleResource = -// JavaResourceBase.createMockResource( -// "com/foo/TestModule.gwt.xml", -// "", -// " ", -// " ", -// ""); -// -// MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); -// File relinkApplicationDir = createTempDir(); -// -// // Perform a first compile. -// compileToJs(relinkApplicationDir, "com.foo.TestModule", -// Lists.newArrayList(moduleResource, testEntryPoint, subType, superType), -// relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); -// -// // Invalidate ONLY the subtype. The types referred by the parameters of supertype methods are -// // going to be reference only which means that the supertype property will have a reference -// // to a JClassType for "java.lang.String" that isExternal() and is different from the -// // (non external) reference in the supertype. -// relinkMinimalRebuildCache.markSourceFileStale("com/foo/SubType.java"); -// compileToJs(relinkApplicationDir, "com.foo.TestModule", Lists. newArrayList(), -// relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); -// } -// -// public void testIncrementalRecompile_invalidatePreamble() throws UnableToCompleteException, -// IOException, InterruptedException { -// MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); -// File relinkApplicationDir = createTempDir(); -// -// // Perform a first compile. -// compileToJs(relinkApplicationDir, "com.foo.SimpleModule", -// Lists.newArrayList(simpleModuleResource, emptyEntryPointResource), -// relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); -// // On first compile nothing is explicitly stale, only implicitly stale. -// assertEquals(0, relinkMinimalRebuildCache.getStaleTypeNames().size()); -// -// // Recompile with a deep change that invalidates the preamble. -// relinkMinimalRebuildCache.markSourceFileStale("java/lang/Object.java"); -// compileToJs(relinkApplicationDir, "com.foo.SimpleModule", Lists. newArrayList(), -// relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); -// // Show that preamble invalidation marks everything stale. -// assertTrue(relinkMinimalRebuildCache.getProcessedStaleTypeNames().size() > 100); -// -// // Recompile again with a tiny change. Prove that it's not stuck repeatedly invalidating the -// // whole world. -// compileToJs(relinkApplicationDir, "com.foo.SimpleModule", -// Lists. newArrayList(emptyEntryPointResource), relinkMinimalRebuildCache, null, -// JsOutputOption.OBFUSCATED); -// // Show that only this little change is stale, not the whole world. -// assertEquals(2, getStaleTypeNames(relinkMinimalRebuildCache).size()); -// } -// -// public void testIncrementalRecompile_bridgeMethodOverrideChain() -// throws UnableToCompleteException, IOException, InterruptedException { -// MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); -// File relinkApplicationDir = createTempDir(); -// -// // Perform a first compile. -// compileToJs(relinkApplicationDir, "com.foo.SimpleModule", Lists.newArrayList( -// simpleModuleResource, overriddenMethodChainEntryPointResource, topResource, middleResource, -// bottomResource), relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); -// // On first compile nothing is explicitly stale, only implicitly stale. -// assertEquals(0, relinkMinimalRebuildCache.getStaleTypeNames().size()); -// -// // Recompile with a change to Bottom. -// relinkMinimalRebuildCache.markSourceFileStale("com/foo/Bottom.java"); -// compileToJs(relinkApplicationDir, "com.foo.SimpleModule", Lists. newArrayList(), -// relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); -// // Show that the third level bridge method override of Top.run() is seen to be live and thus -// // makes type com.foo.Bottom$Value live. -// assertTrue( -// relinkMinimalRebuildCache.getProcessedStaleTypeNames().contains("com.foo.Bottom$Value")); -// } -// -// public void testIncrementalRecompile_classLiteralNewReference() -// throws UnableToCompleteException, IOException, InterruptedException { -// checkIncrementalRecompile_classLiteralNewReference(JsOutputOption.OBFUSCATED); -// checkIncrementalRecompile_classLiteralNewReference(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_primitiveClassLiteralReference() -// throws UnableToCompleteException, IOException, InterruptedException { -// checkIncrementalRecompile_primitiveClassLiteralReference(JsOutputOption.OBFUSCATED); -// checkIncrementalRecompile_primitiveClassLiteralReference(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_superClassOrder() -// throws UnableToCompleteException, IOException, InterruptedException { -// // Linked output is sorted alphabetically except that super-classes come before sub-classes. If -// // on recompile a sub-class -> super-class relationship is lost then a sub-class with an -// // alphabetically earlier name might start linking out before the super-class. -// checkIncrementalRecompile_superClassOrder(JsOutputOption.OBFUSCATED); -// checkIncrementalRecompile_superClassOrder(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_superFromStaleInner() -// throws UnableToCompleteException, IOException, InterruptedException { -// checkIncrementalRecompile_superFromStaleInner(JsOutputOption.OBFUSCATED); -// checkIncrementalRecompile_superFromStaleInner(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_deterministicUiBinder() throws UnableToCompleteException, -// IOException, InterruptedException { -// checkIncrementalRecompile_deterministicUiBinder(JsOutputOption.OBFUSCATED); -// checkIncrementalRecompile_deterministicUiBinder(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_uiBinderCssChange() throws UnableToCompleteException, -// IOException, InterruptedException { -// checkIncrementalRecompile_uiBinderCssChange(JsOutputOption.OBFUSCATED); -// checkIncrementalRecompile_uiBinderCssChange(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_unstableGeneratorReferencesModifiedType() -// throws UnableToCompleteException, IOException, InterruptedException { -// checkIncrementalRecompile_unstableGeneratorReferencesModifiedType(JsOutputOption.OBFUSCATED); -// checkIncrementalRecompile_unstableGeneratorReferencesModifiedType(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_withErrors() -// throws UnableToCompleteException, IOException, InterruptedException { -// MockResource moduleResource = -// JavaResourceBase.createMockResource( -// "com/foo/Errors.gwt.xml", -// "", -// " ", -// " ", -// ""); -// -// MockJavaResource entryPointResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.ErrorsEntryPoint", -// "package com.foo;", -// "import com.google.gwt.core.client.EntryPoint;", -// "public class ErrorsEntryPoint implements EntryPoint {", -// " public void onModuleLoad() {", -// " Foo.foo();", -// " }", -// "}"); -// -// MockJavaResource fooResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.Foo", -// "package com.foo;", -// "public class Foo {", -// " public static void foo() {", -// " }", -// "}"); -// -// MockJavaResource fooResourceWithErrors = -// JavaResourceBase.createMockJavaResource( -// "com.foo.Foo", -// "package com.foo;", -// "public class Foo {", -// " public static void foo() {", -// " // x() method is not defined anywhere, should result in a compile error.", -// " x();", -// " }", -// "}"); -// -// MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache(); -// File applicationDir = createTempDir(); -// CompilerOptions compilerOptions = new CompilerOptionsImpl(); -// compilerOptions.setUseDetailedTypeIds(true); -// compilerOptions.setSourceLevel(SourceLevel.JAVA11); -// -// // Compile the application with no errors. -// compileToJs(TreeLogger.NULL, compilerOptions, applicationDir, "com.foo.Errors", -// Lists.newArrayList(moduleResource, entryPointResource, fooResource), minimalRebuildCache, -// emptySet, JsOutputOption.OBFUSCATED); -// -// // Recompile and expect error reporting. -// UnitTestTreeLogger.Builder builder = new UnitTestTreeLogger.Builder(); -// builder.setLowestLogLevel(TreeLogger.ERROR); -// builder.expectError("Line 5: The method x() is undefined for the type Foo", null); -// UnitTestTreeLogger errorLogger = builder.createLogger(); -// try { -// // Recompile but now the changed file has an error -// compileToJs(errorLogger, compilerOptions, applicationDir, "com.foo.Errors", -// Lists.newArrayList(moduleResource, entryPointResource, fooResourceWithErrors), -// minimalRebuildCache, -// emptySet, JsOutputOption.OBFUSCATED); -// fail("Compile should have failed"); -// } catch (UnableToCompleteException expected) { -// errorLogger.assertLogEntriesContainExpected(); -// } -// } -// -// public void testIncrementalRecompile_representedAsNative() -// throws UnableToCompleteException, IOException, InterruptedException { -// MockResource moduleResource = -// JavaResourceBase.createMockResource( -// "com/foo/RepresentedAsNative.gwt.xml", -// "", -// " ", -// " ", -// ""); -// -// MockResource entryPointResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.RepresentedAsNativeEntryPoint", -// "package com.foo;", -// "import com.google.gwt.core.client.EntryPoint;", -// "public class RepresentedAsNativeEntryPoint implements EntryPoint {", -// " public void onModuleLoad() {", -// " Double d = new Double(1d);", -// " }", -// "}"); -// -// MockResource modifiedEntryPointResource = -// JavaResourceBase.createMockJavaResource( -// "com.foo.RepresentedAsNativeEntryPoint", -// "package com.foo;", -// "import com.google.gwt.core.client.EntryPoint;", -// "public class RepresentedAsNativeEntryPoint implements EntryPoint {", -// " public void onModuleLoad() {", -// " Double d = new Double(\"1\");", -// " }", -// "}"); -// -// PrintWriterTreeLogger logger = new PrintWriterTreeLogger(); -// logger.setMaxDetail(TreeLogger.ERROR); -// -// MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache(); -// File applicationDir = createTempDir(); -// CompilerOptions compilerOptions = new CompilerOptionsImpl(); -// compilerOptions.setUseDetailedTypeIds(true); -// compilerOptions.setSourceLevel(SourceLevel.JAVA11); -// compilerOptions.setGenerateJsInteropExports(false); -// -// // Compile the application with no errors. -// compileToJs(logger, compilerOptions, applicationDir, "com.foo.RepresentedAsNative", -// Lists.newArrayList(moduleResource, entryPointResource), minimalRebuildCache, -// emptySet, JsOutputOption.OBFUSCATED); -// -// // Recompile but now the changed file has an error -// compileToJs(logger, compilerOptions, applicationDir, "com.foo.RepresentedAsNative", -// Lists.newArrayList(modifiedEntryPointResource), -// minimalRebuildCache, -// stringSet( -// "com.foo.RepresentedAsNativeEntryPoint", -// getEntryMethodHolderTypeName("com.foo.RepresentedAsNative")), -// JsOutputOption.OBFUSCATED); -// } -// -// public void testIncrementalRecompile_functionSignatureChange() throws UnableToCompleteException, -// IOException, InterruptedException { -// // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's -// // behavior is order dependent, and while still correct, will come out different in a recompile -// // with this change versus a from scratch compile with this change. -// checkIncrementalRecompile_functionSignatureChange(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_compileTimeConstantChange() throws UnableToCompleteException, -// IOException, InterruptedException { -// checkIncrementalRecompile_compileTimeConstantChange(JsOutputOption.DETAILED); -// checkIncrementalRecompile_compileTimeConstantChange(JsOutputOption.OBFUSCATED); -// } -// -// public void testIncrementalRecompile_transitivelyFoldableConstant() -// throws UnableToCompleteException, -// IOException, InterruptedException { -// checkIncrementalRecompile_transitivelyFoldableConstant(JsOutputOption.DETAILED); -// checkIncrementalRecompile_transitivelyFoldableConstant(JsOutputOption.OBFUSCATED); -// } -// -// public void testIncrementalRecompile_packagePrivateDispatch() throws UnableToCompleteException, -// IOException, InterruptedException { -// checkIncrementalRecompile_packagePrivateOverride(JsOutputOption.OBFUSCATED); -// checkIncrementalRecompile_packagePrivateOverride(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_prettyOutput() -// throws UnableToCompleteException, IOException, InterruptedException { -// // Nominal tests for pretty output. Pretty and Obfuscated output share most of the same code -// // paths. -// checkIncrementalRecompile_typeHierarchyChange(JsOutputOption.PRETTY); -// checkIncrementalRecompile_unreachableIncompatibleChange(JsOutputOption.PRETTY); -// } -// -// public void testIncrementalRecompile_regularClassMadeIntoJsoClass() -// throws UnableToCompleteException, IOException, InterruptedException { -// // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's -// // behavior is order dependent, and while still correct, will come out different in a recompile -// // with this change versus a from scratch compile with this change. -// checkIncrementalRecompile_regularClassMadeIntoJsoClass(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_unreachableIncompatibleChange() -// throws UnableToCompleteException, IOException, InterruptedException { -// // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's -// // behavior is order dependent, and while still correct, will come out different in a recompile -// // with this change versus a from scratch compile with this change. -// checkIncrementalRecompile_unreachableIncompatibleChange(JsOutputOption.OBFUSCATED); -// checkIncrementalRecompile_unreachableIncompatibleChange(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_typeHierarchyChange() -// throws UnableToCompleteException, IOException, InterruptedException { -// checkIncrementalRecompile_typeHierarchyChange(JsOutputOption.OBFUSCATED); -// checkIncrementalRecompile_typeHierarchyChange(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_defaultMethod() -// throws UnableToCompleteException, IOException, InterruptedException { -// // Tests that default method on superclasses are correctly constructed -// checkIncrementalRecompile_defaultMethod(JsOutputOption.OBFUSCATED); -// checkIncrementalRecompile_defaultMethod(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_devirtualizeUnchangedJso() -// throws UnableToCompleteException, IOException, InterruptedException { -// // Tests that a JSO calls through interfaces are correctly devirtualized when compiling per file -// // and the JSOs nor their single impl interfaces are not stale. -// checkIncrementalRecompile_devirtualizeUnchangedJso(JsOutputOption.OBFUSCATED); -// checkIncrementalRecompile_devirtualizeUnchangedJso(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_devirtualizeString() -// throws UnableToCompleteException, IOException, InterruptedException { -// // Tests that String calls through interfaces are correctly devirtualized when compiling per -// // file and neither String nor CharSequence interface are stale. -// checkIncrementalRecompile_devirtualizeString(JsOutputOption.OBFUSCATED); -// checkIncrementalRecompile_devirtualizeString(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_devirtualizeComparable() -// throws UnableToCompleteException, IOException, InterruptedException { -// // Tests that Doublecalls through interfaces are correctly devirtualized when compiling per -// // file and neither String nor CharSequence interface are stale. -// checkIncrementalRecompile_devirtualizeComparable(JsOutputOption.OBFUSCATED); -// checkIncrementalRecompile_devirtualizeComparable(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_multipleClassGenerator() -// throws UnableToCompleteException, IOException, InterruptedException { -// // Tests that a Generated type that is not directly referenced from the rebound GWT.create() -// // call is still marked stale, regenerated, retraversed and output as JS. -// checkIncrementalRecompile_multipleClassGenerator(JsOutputOption.OBFUSCATED); -// checkIncrementalRecompile_multipleClassGenerator(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_singleJsoIntfDispatchChange() -// throws UnableToCompleteException, -// IOException, InterruptedException { -// // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's -// // behavior is order dependent, and while still correct, will come out different in a recompile -// // with this change versus a from scratch compile with this change. -// checkIncrementalRecompile_singleJsoIntfDispatchChange(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_dualJsoIntfDispatchChange() throws UnableToCompleteException, -// IOException, InterruptedException { -// // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's -// // behavior is order dependent, and while still correct, will come out different in a recompile -// // with this change versus a from scratch compile with this change. -// checkIncrementalRecompile_dualJsoIntfDispatchChange(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_generatorInputResourceChange() throws IOException, -// UnableToCompleteException, InterruptedException { -// // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's -// // behavior is order dependent, and while still correct, will come out different in a recompile -// // with this change versus a from scratch compile with this change. -// checkIncrementalRecompile_generatorInputResourceChange(JsOutputOption.DETAILED); -// } -// -// public void testIncrementalRecompile_invalidatedGeneratorOutputRerunsGenerator() -// throws UnableToCompleteException, IOException, InterruptedException { -// // BarReferencesFoo Generator hasn't run yet. -// assertEquals(0, BarReferencesFooGenerator.runCount); -// -// CompilerOptions compilerOptions = new CompilerOptionsImpl(); -// List sharedResources = -// Lists.newArrayList(barReferencesFooGeneratorModuleResource, generatorEntryPointResource); -// JsOutputOption output = JsOutputOption.OBFUSCATED; -// -// List originalResources = Lists.newArrayList(sharedResources); -// originalResources.add(fooResource); -// -// // Compile the app with original files, modify a file and do a per-file recompile. -// MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); -// File relinkApplicationDir = createTempDir(); -// compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", originalResources, -// relinkMinimalRebuildCache, emptySet, output); -// -// // BarReferencesFoo Generator has now been run once. -// assertEquals(1, BarReferencesFooGenerator.runCount); -// -// // Recompile with no changes, which should not trigger any Generator runs. -// compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", -// Lists.newArrayList(), relinkMinimalRebuildCache, emptySet, output); -// -// // Since there were no changes BarReferencesFoo Generator was not run again. -// assertEquals(1, BarReferencesFooGenerator.runCount); -// -// // Recompile with a modified Foo class, which should invalidate Bar which was generated by a -// // GWT.create() call in the entry point. -// compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", -// Lists.newArrayList(fooResource), relinkMinimalRebuildCache, -// stringSet("com.foo.TestEntryPoint", "com.foo.Foo", "com.foo.Bar"), output); -// -// // BarReferencesFoo Generator was run again. -// assertEquals(2, BarReferencesFooGenerator.runCount); -// } -// -// public void testIncrementalRecompile_invalidatedGeneratorOutputRerunsCascadedGenerators() -// throws UnableToCompleteException, IOException, InterruptedException { -// // Generators haven't run yet. -// assertEquals(0, CauseStringRebindGenerator.runCount); -// assertEquals(0, CauseShortRebindGenerator.runCount); -// assertEquals(0, FooResourceGenerator.runCount); -// -// CompilerOptions compilerOptions = new CompilerOptionsImpl(); -// List sharedResources = Lists.newArrayList(cascadingGeneratorModuleResource, -// generatorEntryPointResource, classNameToGenerateResource); -// JsOutputOption output = JsOutputOption.OBFUSCATED; -// -// List originalResources = Lists.newArrayList(sharedResources); -// -// // Compile the app with original files. -// MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); -// File relinkApplicationDir = createTempDir(); -// compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", originalResources, -// relinkMinimalRebuildCache, emptySet, output); -// -// // Generators have now been run once. -// assertEquals(1, CauseStringRebindGenerator.runCount); -// assertEquals(1, CauseShortRebindGenerator.runCount); -// assertEquals(1, FooResourceGenerator.runCount); -// -// // Recompile with no changes, which should not trigger any Generator runs. -// compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", -// Lists.newArrayList(), relinkMinimalRebuildCache, emptySet, output); -// -// // Since there were no changes Generators were not run again. -// assertEquals(1, CauseStringRebindGenerator.runCount); -// assertEquals(1, CauseShortRebindGenerator.runCount); -// assertEquals(1, FooResourceGenerator.runCount); -// -// // Recompile with a modified resource, which should invalidate the output of the -// // FooResourceGenerator and cascade the invalidate the Generators that triggered -// // FooResourceGenerator. -// compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", -// Lists.newArrayList(modifiedClassNameToGenerateResource), -// relinkMinimalRebuildCache, stringSet("com.foo.TestEntryPoint", "com.foo.Baz$InnerBaz", -// "com.foo.Bar", "com.foo.HasCustomContent", "com.foo.FooReplacementTwo"), output); -// -// // Generators were run again. -// assertEquals(2, CauseStringRebindGenerator.runCount); -// assertEquals(2, CauseShortRebindGenerator.runCount); -// assertEquals(2, FooResourceGenerator.runCount); -// } -// -// public void testIncrementalRecompile_carriesOverGeneratorArtifacts() -// throws UnableToCompleteException, -// IOException, InterruptedException { -// // Foo Generator hasn't run yet. -// assertEquals(0, FooResourceGenerator.runCount); -// -// CompilerOptions compilerOptions = new CompilerOptionsImpl(); -// List sharedResources = Lists.newArrayList(resourceReadingGeneratorModuleResource, -// referencesBarAndGeneratorEntryPointResource, classNameToGenerateResource, -// barReferencesFooResource); -// JsOutputOption output = JsOutputOption.OBFUSCATED; -// -// List originalResources = Lists.newArrayList(sharedResources); -// originalResources.add(fooResource); -// -// // Compile the app with original files. -// MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); -// File relinkApplicationDir = createTempDir(); -// compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", originalResources, -// relinkMinimalRebuildCache, emptySet, output); -// -// // Foo Generator has now been run once. -// assertEquals(1, FooResourceGenerator.runCount); -// // The bar.txt artifact was output. -// File barFile = new File(relinkApplicationDir.getPath() + File.separator + "com.foo.SimpleModule" -// + File.separator + "bar.txt"); -// assertTrue(barFile.exists()); -// -// // Recompile with just 1 file change, which should not trigger any Generator runs. -// compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", -// Lists. newArrayList(fooResource), relinkMinimalRebuildCache, -// stringSet("com.foo.Foo", "com.foo.Bar"), output); -// -// // Foo Generator was not run again. -// assertEquals(1, FooResourceGenerator.runCount); -// // But the bar.txt artifact was still output. -// barFile = new File(relinkApplicationDir.getPath() + File.separator + "com.foo.SimpleModule" -// + File.separator + "bar.txt"); -// assertTrue(barFile.exists()); -// } -// -// /** -// * Regression test for UnifyAST assertion failure problem in incremental SDM. -// */ -// public void testIncrementalRecompile_unifyASTAssertionRegression() -// throws UnableToCompleteException, IOException, InterruptedException { -// -// CompilerOptions compilerOptions = new CompilerOptionsImpl(); -// List originalResources = Lists.newArrayList(helloEntryPointResource, -// helloModuleResource); -// JsOutputOption output = JsOutputOption.OBFUSCATED; -// -// // Compile the app with original files. -// MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); -// File relinkApplicationDir = createTempDir(); -// compileToJs(compilerOptions, relinkApplicationDir, "com.foo.Hello", -// originalResources, relinkMinimalRebuildCache, emptySet, output); -// } + public void testAllValidArgs() { + CompilerOptionsImpl options = new CompilerOptionsImpl(); + Compiler.ArgProcessor argProcessor = new Compiler.ArgProcessor(options); + + assertProcessSuccess(argProcessor, new String[] {"-logLevel", "DEBUG", "-style", + "PRETTY", "-ea", "-gen", "myGen", + "-war", "myWar", "-workDir", "myWork", "-extra", "myExtra", "-incremental", + "-localWorkers", "2", "-sourceLevel", "1.8", "c.g.g.h.H", "my.Module"}); + + assertEquals(new File("myGen").getAbsoluteFile(), + options.getGenDir().getAbsoluteFile()); + assertEquals(new File("myWar"), options.getWarDir()); + assertEquals(new File("myWork"), options.getWorkDir()); + assertEquals(new File("myExtra"), options.getExtraDir()); + + assertEquals(2, options.getLocalWorkers()); + + assertEquals(TreeLogger.DEBUG, options.getLogLevel()); + assertEquals(JsOutputOption.PRETTY, options.getOutput()); + assertTrue(options.isEnableAssertions()); + assertTrue(options.shouldClusterSimilarFunctions()); + assertTrue(options.shouldInlineLiteralParameters()); + assertFalse(options.shouldOptimizeDataflow()); + assertTrue(options.shouldOrdinalizeEnums()); + assertTrue(options.shouldRemoveDuplicateFunctions()); + assertTrue(options.isIncrementalCompileEnabled()); + + assertEquals(SourceLevel.JAVA8, options.getSourceLevel()); + + assertEquals(2, options.getModuleNames().size()); + assertEquals("c.g.g.h.H", options.getModuleNames().get(0)); + assertEquals("my.Module", options.getModuleNames().get(1)); + } + + public void testDefaultArgs() { + CompilerOptionsImpl options = new CompilerOptionsImpl(); + Compiler.ArgProcessor argProcessor = new Compiler.ArgProcessor(options); + + assertProcessSuccess(argProcessor, new String[]{"c.g.g.h.H"}); + + assertEquals(null, options.getGenDir()); + assertEquals(new File("war").getAbsoluteFile(), + options.getWarDir().getAbsoluteFile()); + assertEquals(null, options.getWorkDir()); + assertEquals(null, options.getExtraDir()); + + assertEquals(TreeLogger.INFO, options.getLogLevel()); + assertEquals(JsOutputOption.OBFUSCATED, options.getOutput()); + assertFalse(options.isEnableAssertions()); + assertTrue(options.shouldClusterSimilarFunctions()); + assertTrue(options.shouldInlineLiteralParameters()); + assertFalse(options.shouldOptimizeDataflow()); + assertTrue(options.shouldOrdinalizeEnums()); + assertTrue(options.shouldRemoveDuplicateFunctions()); + assertFalse(options.isIncrementalCompileEnabled()); + + assertEquals(1, options.getLocalWorkers()); + + assertEquals(1, options.getModuleNames().size()); + assertEquals("c.g.g.h.H", options.getModuleNames().get(0)); + } + + public void testForbiddenArgs() { + CompilerOptionsImpl options = new CompilerOptionsImpl(); + Compiler.ArgProcessor argProcessor = new Compiler.ArgProcessor(options); + + assertProcessFailure(argProcessor, "Unknown argument", new String[]{"-out", "www"}); + assertProcessFailure(argProcessor, "Source level must be one of", + new String[]{"-sourceLevel", "ssss"}); + assertProcessFailure(argProcessor, "Source level must be one of", + new String[]{"-sourceLevel", "1.5"}); + } + + /** + * Tests ordering for emum {@link SourceLevel}. + */ + public void testSourceLevelOrdering() { + SourceLevel[] sourceLevels = SourceLevel.values(); + SourceLevel previousSourceLevel = sourceLevels[0]; + for (int i = 1; i < sourceLevels.length; i++) { + assertTrue(SourceLevel.versionCompare(previousSourceLevel.getStringValue(), + sourceLevels[i].getStringValue()) < 0); + previousSourceLevel = sourceLevels[i]; + } + } + + public void testSourceLevelSelection() { + assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.4")); + assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.5")); + assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.6")); + assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.6_26")); + + assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.7")); + assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.8")); + assertEquals(SourceLevel.JAVA9, SourceLevel.getBestMatchingVersion("9")); + assertEquals(SourceLevel.JAVA10, SourceLevel.getBestMatchingVersion("10")); + assertEquals(SourceLevel.JAVA11, SourceLevel.getBestMatchingVersion("11")); + + // not proper version strings => default to JAVA8. + assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.6u3")); + assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.6b3")); + assertEquals(SourceLevel.JAVA8, SourceLevel.getBestMatchingVersion("1.7b3")); + } + + public void testSourceLevelHighestVersion() { + assertEquals(SourceLevel.values()[SourceLevel.values().length - 1], SourceLevel.getHighest()); + } + + /** + * Verify that a compile with a @JsType at least compiles successfully. + */ + public void testGwtCreateJsTypeRebindResult() throws Exception { + CompilerOptions compilerOptions = new CompilerOptionsImpl(); + compileToJs(compilerOptions, createTempDir(), "com.foo.SimpleModule", + Lists.newArrayList(simpleModuleResource, gwtCreateEntryPointResource), + new MinimalRebuildCache(), emptySet, JsOutputOption.OBFUSCATED); + } + + /** + * Test that some lightly referenced interface through a @JsFunction is included in the output. + */ + public void testReferenceThroughJsFunction() throws Exception { + MockJavaResource someJsFunction = + JavaResourceBase.createMockJavaResource( + "com.foo.SomeJsFunction", + "package com.foo;", + "import jsinterop.annotations.JsFunction;", + "@JsFunction", + "public interface SomeJsFunction {", + " void m();", + "}"); + + MockJavaResource jsFunctionInterfaceImplementation = + JavaResourceBase.createMockJavaResource( + "com.foo.Impl", + "package com.foo;", + "public final class Impl implements SomeJsFunction {", + " public void m() { SomeInterface.class.getName(); } ", + "}"); + + MockJavaResource someInterface = + JavaResourceBase.createMockJavaResource( + "com.foo.SomeInterface", + "package com.foo;", + "public interface SomeInterface {", + "}"); + + MockJavaResource testEntryPoint = + JavaResourceBase.createMockJavaResource( + "com.foo.TestEntryPoint", + "package com.foo;", + "import com.google.gwt.core.client.EntryPoint;", + "public class TestEntryPoint implements EntryPoint {", + " private static native void f(SomeJsFunction f) /*-{}-*/;", + " public void onModuleLoad() {", + // Create Impl and pass it to JS but do not explicitly call m + " f(new Impl());", + " }", + "}"); + + MockResource moduleResource = + JavaResourceBase.createMockResource( + "com/foo/TestEntryPoint.gwt.xml", + "", + " ", + " ", + ""); + + CompilerOptions compilerOptions = new CompilerOptionsImpl(); + String js = compileToJs(compilerOptions, createTempDir(), testEntryPoint.getTypeName(), + Lists.newArrayList(moduleResource, testEntryPoint, someJsFunction, + jsFunctionInterfaceImplementation, someInterface), + new MinimalRebuildCache(), emptySet, JsOutputOption.DETAILED); + // Make sure the referenced class literals ends up being included in the resulting JS. + String classliteralHolderVarName = + JjsUtils.mangleMemberName("com.google.gwt.lang.ClassLiteralHolder", + JjsUtils.classLiteralFieldNameFromJavahTypeSignatureName( + JjsUtils.javahSignatureFromName(someInterface.getTypeName()))); + assertTrue(js.contains("var " + classliteralHolderVarName + " = ")); + } + + /** + * Tests that changing Js namespace name on an exported method comes out accurately. + * + *

An unrelated and non-updated @JsType is also included in each compile to verify that updated + * exports do not forget non-edited items in a recompile. + */ + public void testChangeJsNamespaceOnMethod() throws Exception { + CompilerOptions compilerOptions = new CompilerOptionsImpl(); + compilerOptions.setUseDetailedTypeIds(true); + compilerOptions.setGenerateJsInteropExports(true); + + MockJavaResource jsNamespaceFooResource = + JavaResourceBase.createMockJavaResource( + "com.foo.Foo", + "package com.foo;", + "import jsinterop.annotations.JsMethod;", + "import jsinterop.annotations.JsType;", + "@JsType public class Foo {", + " @JsMethod(namespace=\"spazz\") public static void doStaticBar() {}", + "}"); + + MockJavaResource regularFooResource = + JavaResourceBase.createMockJavaResource( + "com.foo.Foo", + "package com.foo;", + "import jsinterop.annotations.JsType;", + "@JsType public class Foo {", + " public static void doStaticBar() {}", + "}"); + + checkRecompiledModifiedApp( + compilerOptions, + "com.foo.SimpleModule", + Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), + regularFooResource, + jsNamespaceFooResource, + stringSet("com.foo.Bar", "com.foo.Foo"), + JsOutputOption.DETAILED); + } + + /** + * Tests that changing Js namespace on a class comes out accurately. + * + *

An unrelated and non-updated @JsType is also included in each compile to verify that updated + * exports do not forget non-edited items in a recompile. + */ + public void testChangeJsNamespaceOnClass() throws Exception { + CompilerOptions compilerOptions = new CompilerOptionsImpl(); + compilerOptions.setUseDetailedTypeIds(true); + compilerOptions.setGenerateJsInteropExports(true); + + MockJavaResource jsNamespaceFooResource = + JavaResourceBase.createMockJavaResource( + "com.foo.Foo", + "package com.foo;", + "import jsinterop.annotations.JsType;", + "@JsType(namespace=\"spazz\") public class Foo {", + " public static void doStaticBar() {}", + "}"); + + MockJavaResource regularFooResource = + JavaResourceBase.createMockJavaResource( + "com.foo.Foo", + "package com.foo;", + "import jsinterop.annotations.JsType;", + "@JsType public class Foo {", + " public static void doStaticBar() {}", + "}"); + + checkRecompiledModifiedApp( + compilerOptions, + "com.foo.SimpleModule", + Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), + regularFooResource, + jsNamespaceFooResource, + stringSet("com.foo.Bar", "com.foo.Foo"), + JsOutputOption.DETAILED); + } + + /** + * Tests that changing @JsFunction name on an interface comes out accurately. + * + *

An unrelated and non-updated @JsType is also included in each compile to verify that updated + * exports do not forget non-edited items in a recompile. + */ + public void testChangeJsFunction() throws Exception { + CompilerOptions compilerOptions = new CompilerOptionsImpl(); + compilerOptions.setUseDetailedTypeIds(true); + compilerOptions.setGenerateJsInteropExports(true); + + MockJavaResource jsFunctionIFooResource = + JavaResourceBase.createMockJavaResource( + "com.foo.IFoo", + "package com.foo;", + "import jsinterop.annotations.JsFunction;", + "@JsFunction public interface IFoo {", + " int foo(int x);", + "}"); + + MockJavaResource regularIFooResource = + JavaResourceBase.createMockJavaResource( + "com.foo.IFoo", + "package com.foo;", + "public interface IFoo {", + " int foo(int x);", + "}"); + + MockJavaResource fooResource = + JavaResourceBase.createMockJavaResource( + "com.foo.Foo", + "package com.foo;", + "public final class Foo implements IFoo {", + " @Override public int foo(int x) { return 0; }", + "}"); + + checkRecompiledModifiedApp( + compilerOptions, + "com.foo.SimpleModule", + Lists.newArrayList( + simpleModuleResource, entryPointResourceForFoo, fooResource, jsTypeBarResource), + regularIFooResource, + jsFunctionIFooResource, + stringSet("com.foo.Bar", "com.foo.Foo", "com.foo.IFoo", "com.foo.TestEntryPoint"), + JsOutputOption.DETAILED); + } + + /** + * Tests that toggling JsProperty methods in an interface comes out accurately. + * + *

An unrelated and non-updated @JsType is also included in each compile to verify that updated + * exports do not forget non-edited items in a recompile. + */ + public void testChangeJsProperty() throws Exception { + CompilerOptions compilerOptions = new CompilerOptionsImpl(); + compilerOptions.setUseDetailedTypeIds(true); + compilerOptions.setGenerateJsInteropExports(true); + + MockJavaResource jsPropertyIFooResource = + JavaResourceBase.createMockJavaResource( + "com.foo.IFoo", + "package com.foo;", + "import jsinterop.annotations.JsProperty;", + "import jsinterop.annotations.JsType;", + "@JsType public interface IFoo {", + " @JsProperty int getX();", + " @JsProperty int getY();", + "}"); + + MockJavaResource regularIFooResource = + JavaResourceBase.createMockJavaResource( + "com.foo.IFoo", + "package com.foo;", + "import jsinterop.annotations.JsType;", + "@JsType public interface IFoo {", + " int getX();", + " int getY();", + "}"); + + MockJavaResource fooResource = + JavaResourceBase.createMockJavaResource( + "com.foo.Foo", + "package com.foo;", + "public class Foo implements IFoo {", + " @Override public int getX() { return 0; }", + " @Override public int getY() { return 0; }", + "}"); + + checkRecompiledModifiedApp( + compilerOptions, + "com.foo.SimpleModule", + Lists.newArrayList( + simpleModuleResource, entryPointResourceForFoo, fooResource, jsTypeBarResource), + regularIFooResource, + jsPropertyIFooResource, + stringSet("com.foo.Bar", "com.foo.Foo", "com.foo.IFoo", "com.foo.TestEntryPoint"), + JsOutputOption.DETAILED); + } + + /** + * Tests that adding a @JsType annotation on a class comes out accurately and that removing it + * comes out accurately as well. + * + *

An unrelated and non-updated @JsType is also included in each compile to verify that updated + * exports do not forget non-edited items in a recompile. + */ + public void testChangeJsType() throws Exception { + CompilerOptions compilerOptions = new CompilerOptionsImpl(); + compilerOptions.setUseDetailedTypeIds(true); + compilerOptions.setGenerateJsInteropExports(true); + + MockJavaResource jsTypeFooResource = + JavaResourceBase.createMockJavaResource( + "com.foo.Foo", + "package com.foo;", + "import jsinterop.annotations.JsType;", + "@JsType public class Foo {", + " void doInstanceBar() {}", + " public static void doStaticBar() {}", + "}"); + + MockJavaResource regularFooResource = + JavaResourceBase.createMockJavaResource( + "com.foo.Foo", "package com.foo;", "public class Foo {}"); + + checkRecompiledModifiedApp( + compilerOptions, + "com.foo.SimpleModule", + Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), + regularFooResource, + jsTypeFooResource, + stringSet("com.foo.Bar", "com.foo.Foo"), + JsOutputOption.DETAILED); + } + + /** + * Tests that changing a prototype on a @JsType annotated class comes out accurately. + * + *

An unrelated and non-updated @JsType is also included in each compile to verify that updated + * exports do not forget non-edited items in a recompile. + */ + public void testChangeJsTypeNative() throws Exception { + CompilerOptions compilerOptions = new CompilerOptionsImpl(); + compilerOptions.setUseDetailedTypeIds(true); + compilerOptions.setGenerateJsInteropExports(true); + + MockJavaResource nativeFooResource = + JavaResourceBase.createMockJavaResource( + "com.foo.Foo", + "package com.foo;", + "import jsinterop.annotations.JsType;", + "@JsType(isNative=true) public class Foo {", + " public static native void doStaticBar();", + "}"); + + MockJavaResource regularFooResource = + JavaResourceBase.createMockJavaResource( + "com.foo.Foo", + "package com.foo;", + "import jsinterop.annotations.JsType;", + "@JsType public class Foo {", + " public static void doStaticBar() {}", + "}"); + + checkRecompiledModifiedApp( + compilerOptions, + "com.foo.SimpleModule", + Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), + regularFooResource, + nativeFooResource, + stringSet("com.foo.Bar", "com.foo.Foo"), + JsOutputOption.DETAILED); + } + + /** + * Tests that adding a @JsIgnore annotation on a method comes out accurately and that removing + * it comes out accurately as well. + * + *

An unrelated and non-updated @JsType is also included in each compile to verify that updated + * exports do not forget non-edited items in a recompile. + */ + public void testChangeJsIgnore() throws Exception { + CompilerOptions compilerOptions = new CompilerOptionsImpl(); + compilerOptions.setUseDetailedTypeIds(true); + compilerOptions.setGenerateJsInteropExports(true); + + MockJavaResource jsIgnoreFooResource = + JavaResourceBase.createMockJavaResource( + "com.foo.Foo", + "package com.foo;", + "import jsinterop.annotations.JsIgnore;", + "import jsinterop.annotations.JsType;", + "@JsType public class Foo {", + " @JsIgnore public static void doStaticBar() {}", + "}"); + + MockJavaResource regularFooResource = + JavaResourceBase.createMockJavaResource( + "com.foo.Foo", + "package com.foo;", + "import jsinterop.annotations.JsType;", + "@JsType public class Foo {", + " public static void doStaticBar() {}", + "}"); + + checkRecompiledModifiedApp( + compilerOptions, + "com.foo.SimpleModule", + Lists.newArrayList(simpleModuleResource, emptyEntryPointResource, jsTypeBarResource), + regularFooResource, + jsIgnoreFooResource, + stringSet("com.foo.Bar", "com.foo.Foo"), + JsOutputOption.DETAILED); + } + + public void testJsInteropNameCollision() throws Exception { + MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache(); + File applicationDir = Files.createTempDirectory("JsInteropNameCollision").toFile(); + CompilerOptions compilerOptions = new CompilerOptionsImpl(); + compilerOptions.setGenerateJsInteropExports(true); + + // Simple compile with one dialog.alert() export succeeds. + compileToJs(compilerOptions, applicationDir, "com.foo.SimpleModule", Lists.newArrayList( + simpleModuleResource, dialogEntryPointResource, simpleDialogResourceWithExport, + complexDialogResourceSansExport), minimalRebuildCache, emptySet, JsOutputOption.OBFUSCATED); + + try { + // Exporting a second dialog.alert() fails with an exported name collision. + compileToJs(compilerOptions, applicationDir, "com.foo.SimpleModule", + Lists. newArrayList(complexDialogResourceWithExport), minimalRebuildCache, + emptySet, JsOutputOption.OBFUSCATED); + fail("Compile should have failed"); + } catch (UnableToCompleteException e) { + // success + } + + // Reverting to just a single dialog.alert() starts succeeding again. + compileToJs(compilerOptions, applicationDir, "com.foo.SimpleModule", + Lists.newArrayList(complexDialogResourceSansExport), minimalRebuildCache, + stringSet("com.foo.SimpleDialog", "com.foo.ComplexDialog", "com.foo.TestEntryPoint"), + JsOutputOption.OBFUSCATED); + } + + public void testGwtCreateJsoRebindResult() throws Exception { + try { + compileToJs(createTempDir(), "com.foo.SimpleModule", + Lists.newArrayList(simpleModuleResource, brokenGwtCreateEntryPointResource), + new MinimalRebuildCache(), emptySet, JsOutputOption.OBFUSCATED); + fail("Compile should have failed"); + } catch (UnableToCompleteException e) { + // success + } + } + + public void testNonZeroArgConstructorEntryPoint() throws Exception { + MockResource moduleResource = + JavaResourceBase.createMockResource( + "com/foo/NonZeroArgConstructor.gwt.xml", + "", + " ", + " ", + ""); + + MockJavaResource entryPointResource = + JavaResourceBase.createMockJavaResource( + "com.foo.NonZeroArgConstructorEntryPoint", + "package com.foo;", + "import com.google.gwt.core.client.EntryPoint;", + "public class NonZeroArgConstructorEntryPoint implements EntryPoint {", + " public NonZeroArgConstructorEntryPoint(String s) {", + " }", + " public void onModuleLoad() {", + " }", + "}"); + + MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache(); + File applicationDir = createTempDir(); + CompilerOptions compilerOptions = new CompilerOptionsImpl(); + + UnitTestTreeLogger.Builder builder = new UnitTestTreeLogger.Builder(); + builder.setLowestLogLevel(TreeLogger.ERROR); + builder.expectError(Pattern.compile("Errors in .*"), null); + builder.expectError("Line 3: Rebind result 'com.foo.NonZeroArgConstructorEntryPoint' " + + "has no default (zero argument) constructors", null); + UnitTestTreeLogger errorLogger = builder.createLogger(); + try { + // Simple compile with one dialog.alert() export succeeds. + + compileToJs(errorLogger, compilerOptions, applicationDir, "com.foo.NonZeroArgConstructor", + Lists.newArrayList(moduleResource, entryPointResource), minimalRebuildCache, + emptySet, JsOutputOption.OBFUSCATED); + fail("Compile should have failed"); + } catch (UnableToCompleteException expected) { + errorLogger.assertCorrectLogEntries(); + } + } + + public void testDeterministicBuild_Draft_StackModeStrip() throws + UnableToCompleteException, IOException { + assertDeterministicBuild(HELLO_MODULE_STACKMODE_STRIP, 0); + } + + public void testDeterministicBuild_Optimized_StackModeStrip() throws + UnableToCompleteException, IOException { + assertDeterministicBuild(HELLO_MODULE_STACKMODE_STRIP, 9); + } + + public void testDeterministicBuild_Draft() throws UnableToCompleteException, IOException { + assertDeterministicBuild(HELLO_MODULE, 0); + } + + public void testDeterministicBuild_Optimized() throws UnableToCompleteException, IOException { + assertDeterministicBuild(HELLO_MODULE, 9); + } + + public void testSuccessfulCompile_jsoClassLiteralOrder() throws Exception { + // Crafted resource to make sure the a native subclass is compiled before the JSO class, + // In the case of native sublcasses the class hierarchy does not match the class literal + // hierarchy. + MockJavaResource nativeClassAndSubclass = + JavaResourceBase.createMockJavaResource( + "com.foo.MyNativeSubclass", + "package com.foo;", + "import jsinterop.annotations.JsType;", + "@JsType(isNative=true)", + "class NativeClass {", + "}", + "public class MyNativeSubclass extends NativeClass {", + "}"); + + MockJavaResource testEntryPoint = + JavaResourceBase.createMockJavaResource( + "com.foo.MyEntryPoint", + "package com.foo;", + "import com.foo.MyNativeSubclass;", + "public class MyEntryPoint extends MyNativeSubclass {", + " public void onModuleLoad() {", + " Object o = new Object();", + " if (MyNativeSubclass.class.getName() == null) ", + " o = new MyNativeSubclass();", + // Make .clazz reachable so that class literals are emmitted with the respective + // classses. + " o.getClass();", + " }", + "}"); + + MockResource moduleResource = + JavaResourceBase.createMockResource( + "com/foo/MyEntryPoint.gwt.xml", + "", + " ", + " ", + ""); + + CompilerOptions compilerOptions = new CompilerOptionsImpl(); + // Make sure it compiles successfully with no assertions + compilerOptions.setEnableAssertions(true); + compilerOptions.setGenerateJsInteropExports(true); + compilerOptions.setOutput(JsOutputOption.PRETTY); + compilerOptions.setOptimizationLevel(9); + assertCompileSucceeds(compilerOptions, testEntryPoint.getTypeName(), + Lists.newArrayList(moduleResource, nativeClassAndSubclass, testEntryPoint)); + } + + // TODO(stalcup): add recompile tests for file deletion. + + public void testIncrementalRecompile_noop() throws UnableToCompleteException, IOException, + InterruptedException { + checkIncrementalRecompile_noop(JsOutputOption.OBFUSCATED); + checkIncrementalRecompile_noop(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_dateStampChange() throws UnableToCompleteException, + IOException, InterruptedException { + checkIncrementalRecompile_dateStampChange(JsOutputOption.OBFUSCATED); + checkIncrementalRecompile_dateStampChange(JsOutputOption.DETAILED); + } + + // Repro for bug #9518 + public void testIncrementalRecompile_jsPropertyConsistencyCheck() + throws UnableToCompleteException, + IOException, InterruptedException { + // Supertype defines the getter. + MockJavaResource superType = + JavaResourceBase.createMockJavaResource( + "com.foo.SuperType", + "package com.foo;", + "import jsinterop.annotations.JsProperty;", + "public class SuperType {", + " @JsProperty String getString() { return null; }", + "}"); + + // Subtype defines the setter. + MockJavaResource subType = + JavaResourceBase.createMockJavaResource( + "com.foo.SubType", + "package com.foo;", + "import jsinterop.annotations.JsProperty;", + "public class SubType extends SuperType {", + " @JsProperty void setString(String s) {}", + "}"); + + MockJavaResource testEntryPoint = + JavaResourceBase.createMockJavaResource( + "com.foo.TestEntryPoint", + "package com.foo;", + "import com.google.gwt.core.client.EntryPoint;", + "public class TestEntryPoint implements EntryPoint {", + " public void onModuleLoad() {", + // Create Impl and pass it to JS but do not explicitly call m + " new SubType();", + " }", + "}"); + + MockResource moduleResource = + JavaResourceBase.createMockResource( + "com/foo/TestModule.gwt.xml", + "", + " ", + " ", + ""); + + MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); + File relinkApplicationDir = createTempDir(); + + // Perform a first compile. + compileToJs(relinkApplicationDir, "com.foo.TestModule", + Lists.newArrayList(moduleResource, testEntryPoint, subType, superType), + relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); + + // Invalidate ONLY the subtype. The types referred by the parameters of supertype methods are + // going to be reference only which means that the supertype property will have a reference + // to a JClassType for "java.lang.String" that isExternal() and is different from the + // (non external) reference in the supertype. + relinkMinimalRebuildCache.markSourceFileStale("com/foo/SubType.java"); + compileToJs(relinkApplicationDir, "com.foo.TestModule", Lists. newArrayList(), + relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); + } + + public void testIncrementalRecompile_invalidatePreamble() throws UnableToCompleteException, + IOException, InterruptedException { + MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); + File relinkApplicationDir = createTempDir(); + + // Perform a first compile. + compileToJs(relinkApplicationDir, "com.foo.SimpleModule", + Lists.newArrayList(simpleModuleResource, emptyEntryPointResource), + relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); + // On first compile nothing is explicitly stale, only implicitly stale. + assertEquals(0, relinkMinimalRebuildCache.getStaleTypeNames().size()); + + // Recompile with a deep change that invalidates the preamble. + relinkMinimalRebuildCache.markSourceFileStale("java/lang/Object.java"); + compileToJs(relinkApplicationDir, "com.foo.SimpleModule", Lists. newArrayList(), + relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); + // Show that preamble invalidation marks everything stale. + assertTrue(relinkMinimalRebuildCache.getProcessedStaleTypeNames().size() > 100); + + // Recompile again with a tiny change. Prove that it's not stuck repeatedly invalidating the + // whole world. + compileToJs(relinkApplicationDir, "com.foo.SimpleModule", + Lists. newArrayList(emptyEntryPointResource), relinkMinimalRebuildCache, null, + JsOutputOption.OBFUSCATED); + // Show that only this little change is stale, not the whole world. + assertEquals(2, getStaleTypeNames(relinkMinimalRebuildCache).size()); + } + + public void testIncrementalRecompile_bridgeMethodOverrideChain() + throws UnableToCompleteException, IOException, InterruptedException { + MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); + File relinkApplicationDir = createTempDir(); + + // Perform a first compile. + compileToJs(relinkApplicationDir, "com.foo.SimpleModule", Lists.newArrayList( + simpleModuleResource, overriddenMethodChainEntryPointResource, topResource, middleResource, + bottomResource), relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); + // On first compile nothing is explicitly stale, only implicitly stale. + assertEquals(0, relinkMinimalRebuildCache.getStaleTypeNames().size()); + + // Recompile with a change to Bottom. + relinkMinimalRebuildCache.markSourceFileStale("com/foo/Bottom.java"); + compileToJs(relinkApplicationDir, "com.foo.SimpleModule", Lists. newArrayList(), + relinkMinimalRebuildCache, null, JsOutputOption.OBFUSCATED); + // Show that the third level bridge method override of Top.run() is seen to be live and thus + // makes type com.foo.Bottom$Value live. + assertTrue( + relinkMinimalRebuildCache.getProcessedStaleTypeNames().contains("com.foo.Bottom$Value")); + } + + public void testIncrementalRecompile_classLiteralNewReference() + throws UnableToCompleteException, IOException, InterruptedException { + checkIncrementalRecompile_classLiteralNewReference(JsOutputOption.OBFUSCATED); + checkIncrementalRecompile_classLiteralNewReference(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_primitiveClassLiteralReference() + throws UnableToCompleteException, IOException, InterruptedException { + checkIncrementalRecompile_primitiveClassLiteralReference(JsOutputOption.OBFUSCATED); + checkIncrementalRecompile_primitiveClassLiteralReference(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_superClassOrder() + throws UnableToCompleteException, IOException, InterruptedException { + // Linked output is sorted alphabetically except that super-classes come before sub-classes. If + // on recompile a sub-class -> super-class relationship is lost then a sub-class with an + // alphabetically earlier name might start linking out before the super-class. + checkIncrementalRecompile_superClassOrder(JsOutputOption.OBFUSCATED); + checkIncrementalRecompile_superClassOrder(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_superFromStaleInner() + throws UnableToCompleteException, IOException, InterruptedException { + checkIncrementalRecompile_superFromStaleInner(JsOutputOption.OBFUSCATED); + checkIncrementalRecompile_superFromStaleInner(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_deterministicUiBinder() throws UnableToCompleteException, + IOException, InterruptedException { + checkIncrementalRecompile_deterministicUiBinder(JsOutputOption.OBFUSCATED); + checkIncrementalRecompile_deterministicUiBinder(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_uiBinderCssChange() throws UnableToCompleteException, + IOException, InterruptedException { + checkIncrementalRecompile_uiBinderCssChange(JsOutputOption.OBFUSCATED); + checkIncrementalRecompile_uiBinderCssChange(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_unstableGeneratorReferencesModifiedType() + throws UnableToCompleteException, IOException, InterruptedException { + checkIncrementalRecompile_unstableGeneratorReferencesModifiedType(JsOutputOption.OBFUSCATED); + checkIncrementalRecompile_unstableGeneratorReferencesModifiedType(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_withErrors() + throws UnableToCompleteException, IOException, InterruptedException { + MockResource moduleResource = + JavaResourceBase.createMockResource( + "com/foo/Errors.gwt.xml", + "", + " ", + " ", + ""); + + MockJavaResource entryPointResource = + JavaResourceBase.createMockJavaResource( + "com.foo.ErrorsEntryPoint", + "package com.foo;", + "import com.google.gwt.core.client.EntryPoint;", + "public class ErrorsEntryPoint implements EntryPoint {", + " public void onModuleLoad() {", + " Foo.foo();", + " }", + "}"); + + MockJavaResource fooResource = + JavaResourceBase.createMockJavaResource( + "com.foo.Foo", + "package com.foo;", + "public class Foo {", + " public static void foo() {", + " }", + "}"); + + MockJavaResource fooResourceWithErrors = + JavaResourceBase.createMockJavaResource( + "com.foo.Foo", + "package com.foo;", + "public class Foo {", + " public static void foo() {", + " // x() method is not defined anywhere, should result in a compile error.", + " x();", + " }", + "}"); + + MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache(); + File applicationDir = createTempDir(); + CompilerOptions compilerOptions = new CompilerOptionsImpl(); + compilerOptions.setUseDetailedTypeIds(true); + compilerOptions.setSourceLevel(SourceLevel.JAVA11); + + // Compile the application with no errors. + compileToJs(TreeLogger.NULL, compilerOptions, applicationDir, "com.foo.Errors", + Lists.newArrayList(moduleResource, entryPointResource, fooResource), minimalRebuildCache, + emptySet, JsOutputOption.OBFUSCATED); + + // Recompile and expect error reporting. + UnitTestTreeLogger.Builder builder = new UnitTestTreeLogger.Builder(); + builder.setLowestLogLevel(TreeLogger.ERROR); + builder.expectError("Line 5: The method x() is undefined for the type Foo", null); + UnitTestTreeLogger errorLogger = builder.createLogger(); + try { + // Recompile but now the changed file has an error + compileToJs(errorLogger, compilerOptions, applicationDir, "com.foo.Errors", + Lists.newArrayList(moduleResource, entryPointResource, fooResourceWithErrors), + minimalRebuildCache, + emptySet, JsOutputOption.OBFUSCATED); + fail("Compile should have failed"); + } catch (UnableToCompleteException expected) { + errorLogger.assertLogEntriesContainExpected(); + } + } + + public void testIncrementalRecompile_representedAsNative() + throws UnableToCompleteException, IOException, InterruptedException { + MockResource moduleResource = + JavaResourceBase.createMockResource( + "com/foo/RepresentedAsNative.gwt.xml", + "", + " ", + " ", + ""); + + MockResource entryPointResource = + JavaResourceBase.createMockJavaResource( + "com.foo.RepresentedAsNativeEntryPoint", + "package com.foo;", + "import com.google.gwt.core.client.EntryPoint;", + "public class RepresentedAsNativeEntryPoint implements EntryPoint {", + " public void onModuleLoad() {", + " Double d = new Double(1d);", + " }", + "}"); + + MockResource modifiedEntryPointResource = + JavaResourceBase.createMockJavaResource( + "com.foo.RepresentedAsNativeEntryPoint", + "package com.foo;", + "import com.google.gwt.core.client.EntryPoint;", + "public class RepresentedAsNativeEntryPoint implements EntryPoint {", + " public void onModuleLoad() {", + " Double d = new Double(\"1\");", + " }", + "}"); + + PrintWriterTreeLogger logger = new PrintWriterTreeLogger(); + logger.setMaxDetail(TreeLogger.ERROR); + + MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache(); + File applicationDir = createTempDir(); + CompilerOptions compilerOptions = new CompilerOptionsImpl(); + compilerOptions.setUseDetailedTypeIds(true); + compilerOptions.setSourceLevel(SourceLevel.JAVA11); + compilerOptions.setGenerateJsInteropExports(false); + + // Compile the application with no errors. + compileToJs(logger, compilerOptions, applicationDir, "com.foo.RepresentedAsNative", + Lists.newArrayList(moduleResource, entryPointResource), minimalRebuildCache, + emptySet, JsOutputOption.OBFUSCATED); + + // Recompile but now the changed file has an error + compileToJs(logger, compilerOptions, applicationDir, "com.foo.RepresentedAsNative", + Lists.newArrayList(modifiedEntryPointResource), + minimalRebuildCache, + stringSet( + "com.foo.RepresentedAsNativeEntryPoint", + getEntryMethodHolderTypeName("com.foo.RepresentedAsNative")), + JsOutputOption.OBFUSCATED); + } + + public void testIncrementalRecompile_functionSignatureChange() throws UnableToCompleteException, + IOException, InterruptedException { + // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's + // behavior is order dependent, and while still correct, will come out different in a recompile + // with this change versus a from scratch compile with this change. + checkIncrementalRecompile_functionSignatureChange(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_compileTimeConstantChange() throws UnableToCompleteException, + IOException, InterruptedException { + checkIncrementalRecompile_compileTimeConstantChange(JsOutputOption.DETAILED); + checkIncrementalRecompile_compileTimeConstantChange(JsOutputOption.OBFUSCATED); + } + + public void testIncrementalRecompile_transitivelyFoldableConstant() + throws UnableToCompleteException, + IOException, InterruptedException { + checkIncrementalRecompile_transitivelyFoldableConstant(JsOutputOption.DETAILED); + checkIncrementalRecompile_transitivelyFoldableConstant(JsOutputOption.OBFUSCATED); + } + + public void testIncrementalRecompile_packagePrivateDispatch() throws UnableToCompleteException, + IOException, InterruptedException { + checkIncrementalRecompile_packagePrivateOverride(JsOutputOption.OBFUSCATED); + checkIncrementalRecompile_packagePrivateOverride(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_prettyOutput() + throws UnableToCompleteException, IOException, InterruptedException { + // Nominal tests for pretty output. Pretty and Obfuscated output share most of the same code + // paths. + checkIncrementalRecompile_typeHierarchyChange(JsOutputOption.PRETTY); + checkIncrementalRecompile_unreachableIncompatibleChange(JsOutputOption.PRETTY); + } + + public void testIncrementalRecompile_regularClassMadeIntoJsoClass() + throws UnableToCompleteException, IOException, InterruptedException { + // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's + // behavior is order dependent, and while still correct, will come out different in a recompile + // with this change versus a from scratch compile with this change. + checkIncrementalRecompile_regularClassMadeIntoJsoClass(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_unreachableIncompatibleChange() + throws UnableToCompleteException, IOException, InterruptedException { + // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's + // behavior is order dependent, and while still correct, will come out different in a recompile + // with this change versus a from scratch compile with this change. + checkIncrementalRecompile_unreachableIncompatibleChange(JsOutputOption.OBFUSCATED); + checkIncrementalRecompile_unreachableIncompatibleChange(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_typeHierarchyChange() + throws UnableToCompleteException, IOException, InterruptedException { + checkIncrementalRecompile_typeHierarchyChange(JsOutputOption.OBFUSCATED); + checkIncrementalRecompile_typeHierarchyChange(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_defaultMethod() + throws UnableToCompleteException, IOException, InterruptedException { + // Tests that default method on superclasses are correctly constructed + checkIncrementalRecompile_defaultMethod(JsOutputOption.OBFUSCATED); + checkIncrementalRecompile_defaultMethod(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_devirtualizeUnchangedJso() + throws UnableToCompleteException, IOException, InterruptedException { + // Tests that a JSO calls through interfaces are correctly devirtualized when compiling per file + // and the JSOs nor their single impl interfaces are not stale. + checkIncrementalRecompile_devirtualizeUnchangedJso(JsOutputOption.OBFUSCATED); + checkIncrementalRecompile_devirtualizeUnchangedJso(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_devirtualizeString() + throws UnableToCompleteException, IOException, InterruptedException { + // Tests that String calls through interfaces are correctly devirtualized when compiling per + // file and neither String nor CharSequence interface are stale. + checkIncrementalRecompile_devirtualizeString(JsOutputOption.OBFUSCATED); + checkIncrementalRecompile_devirtualizeString(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_devirtualizeComparable() + throws UnableToCompleteException, IOException, InterruptedException { + // Tests that Doublecalls through interfaces are correctly devirtualized when compiling per + // file and neither String nor CharSequence interface are stale. + checkIncrementalRecompile_devirtualizeComparable(JsOutputOption.OBFUSCATED); + checkIncrementalRecompile_devirtualizeComparable(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_multipleClassGenerator() + throws UnableToCompleteException, IOException, InterruptedException { + // Tests that a Generated type that is not directly referenced from the rebound GWT.create() + // call is still marked stale, regenerated, retraversed and output as JS. + checkIncrementalRecompile_multipleClassGenerator(JsOutputOption.OBFUSCATED); + checkIncrementalRecompile_multipleClassGenerator(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_singleJsoIntfDispatchChange() + throws UnableToCompleteException, + IOException, InterruptedException { + // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's + // behavior is order dependent, and while still correct, will come out different in a recompile + // with this change versus a from scratch compile with this change. + checkIncrementalRecompile_singleJsoIntfDispatchChange(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_dualJsoIntfDispatchChange() throws UnableToCompleteException, + IOException, InterruptedException { + // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's + // behavior is order dependent, and while still correct, will come out different in a recompile + // with this change versus a from scratch compile with this change. + checkIncrementalRecompile_dualJsoIntfDispatchChange(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_generatorInputResourceChange() throws IOException, + UnableToCompleteException, InterruptedException { + // Not testing recompile equality with Pretty/Obfuscated output since the JsIncrementalNamer's + // behavior is order dependent, and while still correct, will come out different in a recompile + // with this change versus a from scratch compile with this change. + checkIncrementalRecompile_generatorInputResourceChange(JsOutputOption.DETAILED); + } + + public void testIncrementalRecompile_invalidatedGeneratorOutputRerunsGenerator() + throws UnableToCompleteException, IOException, InterruptedException { + // BarReferencesFoo Generator hasn't run yet. + assertEquals(0, BarReferencesFooGenerator.runCount); + + CompilerOptions compilerOptions = new CompilerOptionsImpl(); + List sharedResources = + Lists.newArrayList(barReferencesFooGeneratorModuleResource, generatorEntryPointResource); + JsOutputOption output = JsOutputOption.OBFUSCATED; + + List originalResources = Lists.newArrayList(sharedResources); + originalResources.add(fooResource); + + // Compile the app with original files, modify a file and do a per-file recompile. + MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); + File relinkApplicationDir = createTempDir(); + compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", originalResources, + relinkMinimalRebuildCache, emptySet, output); + + // BarReferencesFoo Generator has now been run once. + assertEquals(1, BarReferencesFooGenerator.runCount); + + // Recompile with no changes, which should not trigger any Generator runs. + compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", + Lists.newArrayList(), relinkMinimalRebuildCache, emptySet, output); + + // Since there were no changes BarReferencesFoo Generator was not run again. + assertEquals(1, BarReferencesFooGenerator.runCount); + + // Recompile with a modified Foo class, which should invalidate Bar which was generated by a + // GWT.create() call in the entry point. + compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", + Lists.newArrayList(fooResource), relinkMinimalRebuildCache, + stringSet("com.foo.TestEntryPoint", "com.foo.Foo", "com.foo.Bar"), output); + + // BarReferencesFoo Generator was run again. + assertEquals(2, BarReferencesFooGenerator.runCount); + } + + public void testIncrementalRecompile_invalidatedGeneratorOutputRerunsCascadedGenerators() + throws UnableToCompleteException, IOException, InterruptedException { + // Generators haven't run yet. + assertEquals(0, CauseStringRebindGenerator.runCount); + assertEquals(0, CauseShortRebindGenerator.runCount); + assertEquals(0, FooResourceGenerator.runCount); + + CompilerOptions compilerOptions = new CompilerOptionsImpl(); + List sharedResources = Lists.newArrayList(cascadingGeneratorModuleResource, + generatorEntryPointResource, classNameToGenerateResource); + JsOutputOption output = JsOutputOption.OBFUSCATED; + + List originalResources = Lists.newArrayList(sharedResources); + + // Compile the app with original files. + MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); + File relinkApplicationDir = createTempDir(); + compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", originalResources, + relinkMinimalRebuildCache, emptySet, output); + + // Generators have now been run once. + assertEquals(1, CauseStringRebindGenerator.runCount); + assertEquals(1, CauseShortRebindGenerator.runCount); + assertEquals(1, FooResourceGenerator.runCount); + + // Recompile with no changes, which should not trigger any Generator runs. + compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", + Lists.newArrayList(), relinkMinimalRebuildCache, emptySet, output); + + // Since there were no changes Generators were not run again. + assertEquals(1, CauseStringRebindGenerator.runCount); + assertEquals(1, CauseShortRebindGenerator.runCount); + assertEquals(1, FooResourceGenerator.runCount); + + // Recompile with a modified resource, which should invalidate the output of the + // FooResourceGenerator and cascade the invalidate the Generators that triggered + // FooResourceGenerator. + compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", + Lists.newArrayList(modifiedClassNameToGenerateResource), + relinkMinimalRebuildCache, stringSet("com.foo.TestEntryPoint", "com.foo.Baz$InnerBaz", + "com.foo.Bar", "com.foo.HasCustomContent", "com.foo.FooReplacementTwo"), output); + + // Generators were run again. + assertEquals(2, CauseStringRebindGenerator.runCount); + assertEquals(2, CauseShortRebindGenerator.runCount); + assertEquals(2, FooResourceGenerator.runCount); + } + + public void testIncrementalRecompile_carriesOverGeneratorArtifacts() + throws UnableToCompleteException, + IOException, InterruptedException { + // Foo Generator hasn't run yet. + assertEquals(0, FooResourceGenerator.runCount); + + CompilerOptions compilerOptions = new CompilerOptionsImpl(); + List sharedResources = Lists.newArrayList(resourceReadingGeneratorModuleResource, + referencesBarAndGeneratorEntryPointResource, classNameToGenerateResource, + barReferencesFooResource); + JsOutputOption output = JsOutputOption.OBFUSCATED; + + List originalResources = Lists.newArrayList(sharedResources); + originalResources.add(fooResource); + + // Compile the app with original files. + MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); + File relinkApplicationDir = createTempDir(); + compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", originalResources, + relinkMinimalRebuildCache, emptySet, output); + + // Foo Generator has now been run once. + assertEquals(1, FooResourceGenerator.runCount); + // The bar.txt artifact was output. + File barFile = new File(relinkApplicationDir.getPath() + File.separator + "com.foo.SimpleModule" + + File.separator + "bar.txt"); + assertTrue(barFile.exists()); + + // Recompile with just 1 file change, which should not trigger any Generator runs. + compileToJs(compilerOptions, relinkApplicationDir, "com.foo.SimpleModule", + Lists. newArrayList(fooResource), relinkMinimalRebuildCache, + stringSet("com.foo.Foo", "com.foo.Bar"), output); + + // Foo Generator was not run again. + assertEquals(1, FooResourceGenerator.runCount); + // But the bar.txt artifact was still output. + barFile = new File(relinkApplicationDir.getPath() + File.separator + "com.foo.SimpleModule" + + File.separator + "bar.txt"); + assertTrue(barFile.exists()); + } + + /** + * Regression test for UnifyAST assertion failure problem in incremental SDM. + */ + public void testIncrementalRecompile_unifyASTAssertionRegression() + throws UnableToCompleteException, IOException, InterruptedException { + + CompilerOptions compilerOptions = new CompilerOptionsImpl(); + List originalResources = Lists.newArrayList(helloEntryPointResource, + helloModuleResource); + JsOutputOption output = JsOutputOption.OBFUSCATED; + + // Compile the app with original files. + MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); + File relinkApplicationDir = createTempDir(); + compileToJs(compilerOptions, relinkApplicationDir, "com.foo.Hello", + originalResources, relinkMinimalRebuildCache, emptySet, output); + } public void testIncrementalRecompile_ctorReferenceChange() throws InterruptedException, IOException, UnableToCompleteException { @@ -3056,7 +3056,7 @@ private String compileToJs(CompilerOptions compilerOptions, File applicationDir, JsOutputOption output) throws IOException, UnableToCompleteException, InterruptedException { PrintWriterTreeLogger logger = new PrintWriterTreeLogger(); - logger.setMaxDetail(TreeLogger.WARN); + logger.setMaxDetail(TreeLogger.ERROR); return compileToJs(logger, compilerOptions, applicationDir, moduleName, applicationResources, minimalRebuildCache, expectedProcessedStaleTypeNames, output); } From c8dbe6bf43b1778fad970d9399a4ecc804772fea Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Wed, 27 May 2026 12:25:23 -0500 Subject: [PATCH 08/12] Remove test logging --- dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java b/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java index c8a4143eb4d..cf6fec7a23e 100644 --- a/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java +++ b/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java @@ -668,7 +668,6 @@ public void recordNestedTypeNamesPerType(CompilationUnit compilationUnit) { Collection oldNestedTypeNames = nestedTypeNamesByUnitTypeName.get(compilationUnitTypeName); for (String oldNestedTypeName : oldNestedTypeNames) { compilationUnitTypeNameByNestedTypeName.remove(oldNestedTypeName); - System.out.println("removed: " + oldNestedTypeName); } nestedTypeNamesByUnitTypeName.removeAll(compilationUnitTypeName); for (CompiledClass compiledClass : compilationUnit.getCompiledClasses()) { From 3eb24f29098556980c04da5cb3b7576c69d69083 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Wed, 27 May 2026 14:18:11 -0500 Subject: [PATCH 09/12] Remove the extra loop, ensure we don't deserialize twice --- .../com/google/gwt/dev/MinimalRebuildCache.java | 16 +++++----------- .../src/com/google/gwt/dev/NullRebuildCache.java | 4 +++- .../com/google/gwt/dev/jjs/impl/UnifyAst.java | 6 +++--- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java b/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java index cf6fec7a23e..77cf84e1926 100644 --- a/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java +++ b/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java @@ -18,7 +18,6 @@ import com.google.gwt.core.ext.linker.StatementRanges; import com.google.gwt.dev.cfg.ModuleDef; import com.google.gwt.dev.javac.CompilationUnit; -import com.google.gwt.dev.javac.CompiledClass; import com.google.gwt.dev.javac.GeneratedUnit; import com.google.gwt.dev.javac.Shared; import com.google.gwt.dev.jjs.JsSourceMap; @@ -30,7 +29,6 @@ import com.google.gwt.dev.jjs.impl.ResolveRuntimeTypeReferences.IntTypeMapper; import com.google.gwt.dev.js.JsIncrementalNamer.JsIncrementalNamerState; import com.google.gwt.dev.resource.Resource; -import com.google.gwt.dev.util.Name.InternalName; import com.google.gwt.thirdparty.guava.common.annotations.VisibleForTesting; import com.google.gwt.thirdparty.guava.common.base.Objects; import com.google.gwt.thirdparty.guava.common.base.Predicates; @@ -660,23 +658,19 @@ public void recordNestedTypeName(String compilationUnitTypeName, String nestedTy compilationUnitTypeNameByNestedTypeName.put(nestedTypeName, compilationUnitTypeName); } - public void recordNestedTypeNamesPerType(CompilationUnit compilationUnit) { + public void recordNestedTypeNamesPerType(CompilationUnit compilationUnit, List types) { // For the root type in the compilation unit the source name and binary name are the same. String compilationUnitTypeName = compilationUnit.getTypeName(); - // Clean up the reverse map for old nested type names before removing them. + // Clean up the reverse map for old nested type names, then clear all entries Collection oldNestedTypeNames = nestedTypeNamesByUnitTypeName.get(compilationUnitTypeName); for (String oldNestedTypeName : oldNestedTypeNames) { compilationUnitTypeNameByNestedTypeName.remove(oldNestedTypeName); } nestedTypeNamesByUnitTypeName.removeAll(compilationUnitTypeName); - for (CompiledClass compiledClass : compilationUnit.getCompiledClasses()) { - String nestedTypeName = InternalName.toBinaryName(compiledClass.getInternalName()); - recordNestedTypeName(compilationUnitTypeName, nestedTypeName); - } - // Also record synthetic types created at the GWT AST level (e.g. lambda and method reference - // inner classes) that don't have corresponding CompiledClass entries from JDT. - for (JDeclaredType type : compilationUnit.getTypes()) { + + // Record all GWT types that were derived from that compilation unit + for (JDeclaredType type : types) { String typeName = type.getName(); if (!nestedTypeNamesByUnitTypeName.containsEntry(compilationUnitTypeName, typeName)) { recordNestedTypeName(compilationUnitTypeName, typeName); diff --git a/dev/core/src/com/google/gwt/dev/NullRebuildCache.java b/dev/core/src/com/google/gwt/dev/NullRebuildCache.java index 7accb814bd4..84dee1f668c 100644 --- a/dev/core/src/com/google/gwt/dev/NullRebuildCache.java +++ b/dev/core/src/com/google/gwt/dev/NullRebuildCache.java @@ -20,11 +20,13 @@ import com.google.gwt.dev.javac.CompilationUnit; import com.google.gwt.dev.javac.GeneratedUnit; import com.google.gwt.dev.jjs.JsSourceMap; +import com.google.gwt.dev.jjs.ast.JDeclaredType; import com.google.gwt.dev.jjs.ast.JTypeOracle; import com.google.gwt.dev.jjs.impl.ResolveRuntimeTypeReferences.IntTypeMapper; import com.google.gwt.dev.js.JsIncrementalNamer.JsIncrementalNamerState; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.Set; @@ -176,7 +178,7 @@ public void recordNestedTypeName(String compilationUnitTypeName, String nestedTy } @Override - public void recordNestedTypeNamesPerType(CompilationUnit compilationUnit) { + public void recordNestedTypeNamesPerType(CompilationUnit compilationUnit, List types) { } @Override 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 c9bcd2ead4e..d9c9ac9728b 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 @@ -1030,11 +1030,11 @@ private void assimilateSourceUnit(CompilationUnit unit, boolean reportErrors) { } // Staleness calculations need to be able to trace from CompilationUnit name to the names of // immediately nested types. So record those associations now. - if (incrementalCompile) { - compilerContext.getMinimalRebuildCache().recordNestedTypeNamesPerType(unit); - } // TODO(zundel): ask for a recompile if deserialization fails? List types = unit.getTypes(); + if (incrementalCompile) { + compilerContext.getMinimalRebuildCache().recordNestedTypeNamesPerType(unit, types); + } assert containsAllTypes(unit, types); for (JDeclaredType type : types) { program.addType(type); From 66b50c65cf93ac9326a991abc7d32e024b50841e Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Wed, 27 May 2026 15:48:14 -0500 Subject: [PATCH 10/12] More consistent naming, better comment --- .../com/google/gwt/dev/jjs/impl/GwtAstBuilder.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) 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 60b40b78f0e..a1b81d9f648 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 @@ -1943,13 +1943,10 @@ public void endVisit(ReferenceExpression x, BlockScope blockScope) { JMethod referredMethod = typeMap.get(referredMethodBinding); boolean hasQualifier = hasQualifier(x); - // Use a positional counter for the synthetic class name (like lambdas) rather than - // embedding the method selector. The counter alone ensures uniqueness within the - // enclosing class, and a stable name is needed for incremental compilation: if the - // method reference target changes, the synthetic class name must stay the same so that - // the MinimalRebuildCache and IntTypeMapper can correctly track and invalidate it. - String lambdaImplementationClassShortName = - String.valueOf(nextReferenceExpressionId++) + "methodref"; + // Give the methodref synthetic class a unique, consistent name. JDT names both lambdas and + // method references as "lambda$N" for the Nth lambda in the enclosing type - we add the + // string "methodref" instead to make it somewhat clearer which impl we're referencing. + String lambdaImplementationClassShortName = "methodref$" + nextReferenceExpressionId++; List enclosingThisRefs = Lists.newArrayList(); // Create an inner class to hold the implementation of the interface From 1a3f0d753debfe0445e4acab4c2d4a820db81be1 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Wed, 27 May 2026 16:03:57 -0500 Subject: [PATCH 11/12] Tidy up test, use new naming --- .../test/com/google/gwt/dev/CompilerTest.java | 179 +++++------------- 1 file changed, 52 insertions(+), 127 deletions(-) diff --git a/dev/core/test/com/google/gwt/dev/CompilerTest.java b/dev/core/test/com/google/gwt/dev/CompilerTest.java index eaa0d6830e9..614e052e388 100644 --- a/dev/core/test/com/google/gwt/dev/CompilerTest.java +++ b/dev/core/test/com/google/gwt/dev/CompilerTest.java @@ -853,6 +853,24 @@ public class CompilerTest extends ArgProcessorTestBase { " }", "}"); + private MockJavaResource producerResource = JavaResourceBase.createMockJavaResource( + "com.foo.Producer", + "package com.foo;", + "public interface Producer {", + " Object get();", + "}" + ); + private MockJavaResource streamResource = JavaResourceBase.createMockJavaResource( + "com.foo.Stream", + "package com.foo;", + "public class Stream {", + " public static Stream generate(Producer p) {", + " p.get();", + " return new Stream();", + " }", + "}" + ); + private Set emptySet = stringSet(); private boolean requireDeterministicJs = true; @@ -2055,44 +2073,34 @@ public void testIncrementalRecompile_unifyASTAssertionRegression() public void testIncrementalRecompile_ctorReferenceChange() throws InterruptedException, IOException, UnableToCompleteException { -// System.out.println("===== TEST: testIncrementalRecompile_ctorReferenceChange PRETTY ====="); checkIncrementalRecompile_ctorReferenceChange(JsOutputOption.PRETTY); -// System.out.println("===== TEST: testIncrementalRecompile_ctorReferenceChange DETAILED ====="); checkIncrementalRecompile_ctorReferenceChange(JsOutputOption.DETAILED); } public void testIncrementalRecompile_methodReferenceChange() throws InterruptedException, IOException, UnableToCompleteException { -// System.out.println("===== TEST: testIncrementalRecompile_methodReferenceChange PRETTY ====="); checkIncrementalRecompile_methodReferenceChange(JsOutputOption.PRETTY); -// System.out.println("===== TEST: testIncrementalRecompile_methodReferenceChange DETAILED ====="); checkIncrementalRecompile_methodReferenceChange(JsOutputOption.DETAILED); } - // passes public void testIncrementalRecompile_lambdaChange() throws InterruptedException, IOException, UnableToCompleteException { -// System.out.println("===== TEST: testIncrementalRecompile_lambdaChange OBFUSCATED ====="); checkIncrementalRecompile_lambdaChange(JsOutputOption.OBFUSCATED); -// System.out.println("===== TEST: testIncrementalRecompile_lambdaChange DETAILED ====="); checkIncrementalRecompile_lambdaChange(JsOutputOption.DETAILED); } - // Method reference to a static method on another class; the reference target changes. public void testIncrementalRecompile_externalMethodReferenceChange() throws InterruptedException, IOException, UnableToCompleteException { checkIncrementalRecompile_externalMethodReferenceChange(JsOutputOption.PRETTY); checkIncrementalRecompile_externalMethodReferenceChange(JsOutputOption.DETAILED); } - // Method reference to a static method on another class; that other class's implementation changes. public void testIncrementalRecompile_externalMethodReferenceTargetChange() throws InterruptedException, IOException, UnableToCompleteException { checkIncrementalRecompile_externalMethodReferenceTargetChange(JsOutputOption.PRETTY); checkIncrementalRecompile_externalMethodReferenceTargetChange(JsOutputOption.DETAILED); } - // Adding or removing a method reference changes the type set; type IDs drift but compilation succeeds. public void testIncrementalRecompile_methodReferenceCountChange() throws InterruptedException, IOException, UnableToCompleteException { // Disable the requirement of deterministic JS, since this results in adding/removing types, @@ -2439,14 +2447,8 @@ private void checkIncrementalRecompile_typeHierarchyChange(JsOutputOption output stringSet("com.foo.TestEntryPoint", "com.foo.ModelC", "com.foo.ModelD"), output); } - private void checkIncrementalRecompile_ctorReferenceChange(JsOutputOption output) throws InterruptedException, IOException, UnableToCompleteException { - MockResource samInterface = JavaResourceBase.createMockJavaResource( - "com.foo.Producer", - "package com.foo;", - "public interface Producer {", - " Object get();", - "}" - ); + private void checkIncrementalRecompile_ctorReferenceChange(JsOutputOption output) + throws InterruptedException, IOException, UnableToCompleteException { MockResource classA = JavaResourceBase.createMockJavaResource( "com.foo.A", "package com.foo;", @@ -2461,16 +2463,7 @@ private void checkIncrementalRecompile_ctorReferenceChange(JsOutputOption output " public B() {}", "}" ); - MockResource staticMethod = JavaResourceBase.createMockJavaResource( - "com.foo.Stream", - "package com.foo;", - "public class Stream {", - " public static Stream generate(Producer p) {", - " p.get();", - " return new Stream();", - " }", - "}" - ); + MockJavaResource before = JavaResourceBase.createMockJavaResource( "com.foo.TestEntryPoint", "package com.foo;", @@ -2495,27 +2488,16 @@ private void checkIncrementalRecompile_ctorReferenceChange(JsOutputOption output " }", "}" ); - checkRecompiledModifiedApp("com.foo.SimpleModule", Lists.newArrayList(simpleModuleResource, samInterface, classA, classB, staticMethod), before, after, stringSet("com.foo.TestEntryPoint", "com.foo.TestEntryPoint$0methodref$Type", getEntryMethodHolderTypeName("com.foo.SimpleModule")), output); + checkRecompiledModifiedApp("com.foo.SimpleModule", + Lists.newArrayList(simpleModuleResource, producerResource, classA, classB, streamResource), + before, after, + stringSet("com.foo.TestEntryPoint", "com.foo.TestEntryPoint$methodref$0$Type", + getEntryMethodHolderTypeName("com.foo.SimpleModule")), + output); } - private void checkIncrementalRecompile_methodReferenceChange(JsOutputOption output) throws InterruptedException, IOException, UnableToCompleteException { - MockResource samInterface = JavaResourceBase.createMockJavaResource( - "com.foo.Producer", - "package com.foo;", - "public interface Producer {", - " Object get();", - "}" - ); - MockResource staticMethod = JavaResourceBase.createMockJavaResource( - "com.foo.Stream", - "package com.foo;", - "public class Stream {", - " public static Stream generate(Producer p) {", - " p.get();", - " return new Stream();", - " }", - "}" - ); + private void checkIncrementalRecompile_methodReferenceChange(JsOutputOption output) + throws InterruptedException, IOException, UnableToCompleteException { MockJavaResource before = JavaResourceBase.createMockJavaResource( "com.foo.TestEntryPoint", "package com.foo;", @@ -2548,27 +2530,16 @@ private void checkIncrementalRecompile_methodReferenceChange(JsOutputOption outp " }", "}" ); - checkRecompiledModifiedApp("com.foo.SimpleModule", Lists.newArrayList(simpleModuleResource, samInterface, staticMethod), before, after, stringSet("com.foo.TestEntryPoint", "com.foo.TestEntryPoint$0methodref$Type", getEntryMethodHolderTypeName("com.foo.SimpleModule")), output); + checkRecompiledModifiedApp("com.foo.SimpleModule", + Lists.newArrayList(simpleModuleResource, producerResource, streamResource), + before, after, + stringSet("com.foo.TestEntryPoint", "com.foo.TestEntryPoint$methodref$0$Type", + getEntryMethodHolderTypeName("com.foo.SimpleModule")), + output); } - private void checkIncrementalRecompile_lambdaChange(JsOutputOption output) throws InterruptedException, IOException, UnableToCompleteException { - MockResource samInterface = JavaResourceBase.createMockJavaResource( - "com.foo.Producer", - "package com.foo;", - "public interface Producer {", - " Object get();", - "}" - ); - MockResource staticMethod = JavaResourceBase.createMockJavaResource( - "com.foo.Stream", - "package com.foo;", - "public class Stream {", - " public static Stream generate(Producer p) {", - " p.get();", - " return new Stream();", - " }", - "}" - ); + private void checkIncrementalRecompile_lambdaChange(JsOutputOption output) + throws InterruptedException, IOException, UnableToCompleteException { MockJavaResource before = JavaResourceBase.createMockJavaResource( "com.foo.TestEntryPoint", "package com.foo;", @@ -2589,19 +2560,17 @@ private void checkIncrementalRecompile_lambdaChange(JsOutputOption output) throw " }", "}" ); - checkRecompiledModifiedApp("com.foo.SimpleModule", Lists.newArrayList(simpleModuleResource, samInterface, staticMethod), before, after, stringSet("com.foo.TestEntryPoint", "com.foo.TestEntryPoint$lambda$0$Type", getEntryMethodHolderTypeName("com.foo.SimpleModule")), output); + checkRecompiledModifiedApp("com.foo.SimpleModule", + Lists.newArrayList(simpleModuleResource, producerResource, streamResource), + before, after, + stringSet("com.foo.TestEntryPoint", "com.foo.TestEntryPoint$lambda$0$Type", + getEntryMethodHolderTypeName("com.foo.SimpleModule")), + output); } // Method reference to a static method on another class; the reference target changes. private void checkIncrementalRecompile_externalMethodReferenceChange(JsOutputOption output) throws InterruptedException, IOException, UnableToCompleteException { - MockResource samInterface = JavaResourceBase.createMockJavaResource( - "com.foo.Producer", - "package com.foo;", - "public interface Producer {", - " Object get();", - "}" - ); MockResource helper = JavaResourceBase.createMockJavaResource( "com.foo.Helper", "package com.foo;", @@ -2610,16 +2579,6 @@ private void checkIncrementalRecompile_externalMethodReferenceChange(JsOutputOpt " public static String b() { return null; }", "}" ); - MockResource staticMethod = JavaResourceBase.createMockJavaResource( - "com.foo.Stream", - "package com.foo;", - "public class Stream {", - " public static Stream generate(Producer p) {", - " p.get();", - " return new Stream();", - " }", - "}" - ); MockJavaResource before = JavaResourceBase.createMockJavaResource( "com.foo.TestEntryPoint", "package com.foo;", @@ -2641,10 +2600,10 @@ private void checkIncrementalRecompile_externalMethodReferenceChange(JsOutputOpt "}" ); checkRecompiledModifiedApp("com.foo.SimpleModule", - Lists.newArrayList(simpleModuleResource, samInterface, helper, staticMethod), + Lists.newArrayList(simpleModuleResource, helper, producerResource, streamResource), before, after, stringSet("com.foo.TestEntryPoint", - "com.foo.TestEntryPoint$0methodref$Type", + "com.foo.TestEntryPoint$methodref$0$Type", getEntryMethodHolderTypeName("com.foo.SimpleModule")), output); } @@ -2652,23 +2611,6 @@ private void checkIncrementalRecompile_externalMethodReferenceChange(JsOutputOpt // Method reference to a static method on another class; that other class's implementation changes. private void checkIncrementalRecompile_externalMethodReferenceTargetChange(JsOutputOption output) throws InterruptedException, IOException, UnableToCompleteException { - MockResource samInterface = JavaResourceBase.createMockJavaResource( - "com.foo.Producer", - "package com.foo;", - "public interface Producer {", - " Object get();", - "}" - ); - MockResource staticMethod = JavaResourceBase.createMockJavaResource( - "com.foo.Stream", - "package com.foo;", - "public class Stream {", - " public static Stream generate(Producer p) {", - " p.get();", - " return new Stream();", - " }", - "}" - ); MockResource entryPoint = JavaResourceBase.createMockJavaResource( "com.foo.TestEntryPoint", "package com.foo;", @@ -2694,32 +2636,14 @@ private void checkIncrementalRecompile_externalMethodReferenceTargetChange(JsOut "}" ); checkRecompiledModifiedApp("com.foo.SimpleModule", - Lists.newArrayList(simpleModuleResource, samInterface, staticMethod, entryPoint), + Lists.newArrayList(simpleModuleResource, producerResource, streamResource, entryPoint), before, after, - stringSet("com.foo.Helper", - "com.foo.TestEntryPoint$0methodref$Type"), + stringSet("com.foo.Helper", "com.foo.TestEntryPoint$methodref$0$Type"), output); } private void checkIncrementalRecompile_methodReferenceCountChange(JsOutputOption output) throws InterruptedException, IOException, UnableToCompleteException { - MockResource samInterface = JavaResourceBase.createMockJavaResource( - "com.foo.Producer", - "package com.foo;", - "public interface Producer {", - " Object get();", - "}" - ); - MockResource staticMethod = JavaResourceBase.createMockJavaResource( - "com.foo.Stream", - "package com.foo;", - "public class Stream {", - " public static Stream generate(Producer p) {", - " p.get();", - " return new Stream();", - " }", - "}" - ); MockJavaResource oneRef = JavaResourceBase.createMockJavaResource( "com.foo.TestEntryPoint", "package com.foo;", @@ -2745,20 +2669,21 @@ private void checkIncrementalRecompile_methodReferenceCountChange(JsOutputOption " public String b() { return null; }", "}" ); - List shared = Lists.newArrayList(simpleModuleResource, samInterface, staticMethod); + List shared = Lists.newArrayList(simpleModuleResource, producerResource, + streamResource); // Add a new method reference before the existing one, both methodref types change checkRecompiledModifiedApp("com.foo.SimpleModule", shared, oneRef, twoRefs, stringSet("com.foo.TestEntryPoint", - "com.foo.TestEntryPoint$0methodref$Type", - "com.foo.TestEntryPoint$1methodref$Type", + "com.foo.TestEntryPoint$methodref$0$Type", + "com.foo.TestEntryPoint$methodref$1$Type", getEntryMethodHolderTypeName("com.foo.SimpleModule")), output); // Remove an earlier method reference, only the retained methodref type exists anymore checkRecompiledModifiedApp("com.foo.SimpleModule", shared, twoRefs, oneRef, stringSet("com.foo.TestEntryPoint", - "com.foo.TestEntryPoint$0methodref$Type", + "com.foo.TestEntryPoint$methodref$0$Type", getEntryMethodHolderTypeName("com.foo.SimpleModule")), output); } From 951e95a3d439120d3143ebf0e7bdfad155ef1f6f Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Wed, 27 May 2026 16:05:44 -0500 Subject: [PATCH 12/12] Remove more debug logging --- dev/core/test/com/google/gwt/dev/CompilerTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/dev/core/test/com/google/gwt/dev/CompilerTest.java b/dev/core/test/com/google/gwt/dev/CompilerTest.java index 614e052e388..bd871feeee8 100644 --- a/dev/core/test/com/google/gwt/dev/CompilerTest.java +++ b/dev/core/test/com/google/gwt/dev/CompilerTest.java @@ -2933,10 +2933,8 @@ private void checkRecompiledModifiedApp( // Compile the app with original files, modify a file and do a per-file recompile. MinimalRebuildCache relinkMinimalRebuildCache = new MinimalRebuildCache(); File relinkApplicationDir = createTempDir(); - System.out.println("--- compile #1: original from-scratch ---"); String originalAppFromScratchJs = compileToJs(compilerOptions, relinkApplicationDir, moduleName, originalResources, relinkMinimalRebuildCache, emptySet, output); - System.out.println("--- compile #2: incremental recompile ---"); String modifiedAppRelinkedJs = compileToJs(compilerOptions, relinkApplicationDir, moduleName, Lists. newArrayList(modifiedResource), relinkMinimalRebuildCache, expectedStaleTypeNamesOnModify, output); @@ -2944,7 +2942,6 @@ Lists. newArrayList(modifiedResource), relinkMinimalRebuildCache, // Compile the app from scratch with the modified file. MinimalRebuildCache fromScratchMinimalRebuildCache = new MinimalRebuildCache(); File fromScratchApplicationDir = createTempDir(); - System.out.println("--- compile #3: modified from-scratch ---"); String modifiedAppFromScratchJs = compileToJs(compilerOptions, fromScratchApplicationDir, moduleName, modifiedResources, fromScratchMinimalRebuildCache, emptySet, output);