Invalidates Generators when input resources change.
When compiling per file:
Modifies ResourceOracle access so that requested resources can be
associated with a currently executing Generator.
Migrates existing Generators to almost always read resources from
ResourceOracle, instead of from ClassPath or URL, so that resource usage
for existing Generators can be tracked.
Starts storing rebinding type to rebound type relations (aka,
FooEntryPoint contains a GWT.create() call for Bar.class).
Starts storing relations from rebound type to resources that are
accessed by Generators invoked to rebind the type.
Starts tracking modified/added/removed resources between compiles.
Uses these relations and knowledge of modified resources to come up with
the list of types to invalidate to trigger reruns of affected
Generators.
Change-Id: I90bc27b472866a46917c8064f1af84889ba87638
Review-Link: https://gwt-review.googlesource.com/#/c/8811/
diff --git a/dev/core/src/com/google/gwt/core/ext/DelegatingGeneratorContext.java b/dev/core/src/com/google/gwt/core/ext/DelegatingGeneratorContext.java
index fa035a8..ff6c03a 100644
--- a/dev/core/src/com/google/gwt/core/ext/DelegatingGeneratorContext.java
+++ b/dev/core/src/com/google/gwt/core/ext/DelegatingGeneratorContext.java
@@ -91,6 +91,7 @@
public boolean isProdMode() {
return baseContext.isProdMode();
}
+
@Override
public PrintWriter tryCreate(TreeLogger logger, String packageName, String simpleName) {
return baseContext.tryCreate(logger, packageName, simpleName);
diff --git a/dev/core/src/com/google/gwt/core/ext/Generator.java b/dev/core/src/com/google/gwt/core/ext/Generator.java
index 9ef3cbf..bd7f2c9 100644
--- a/dev/core/src/com/google/gwt/core/ext/Generator.java
+++ b/dev/core/src/com/google/gwt/core/ext/Generator.java
@@ -25,6 +25,10 @@
* <p>
* If annotated by {@code @RunsLocal}, a generator can minimize its impact on compilation speed. See
* {@link RunsLocal} for details.
+ * <p>
+ * Resource reading should be done through the ResourceOracle in the provided GeneratorContext (not
+ * via ClassLoader.getResource(), File, or URL) so that Generator Resource dependencies can be
+ * detected and used to facilitate fast incremental recompiles.
*/
public abstract class Generator {
diff --git a/dev/core/src/com/google/gwt/core/ext/StubGeneratorContext.java b/dev/core/src/com/google/gwt/core/ext/StubGeneratorContext.java
index 949a38b..71ce4da 100644
--- a/dev/core/src/com/google/gwt/core/ext/StubGeneratorContext.java
+++ b/dev/core/src/com/google/gwt/core/ext/StubGeneratorContext.java
@@ -29,7 +29,7 @@
* selectively override individual methods. Useful for mocking and/or selective
* reuse of generator functionality.
*/
-public abstract class StubGeneratorContext implements GeneratorContext {
+public class StubGeneratorContext implements GeneratorContext {
@Override
public boolean checkRebindRuleAvailable(String sourceTypeName) {
diff --git a/dev/core/src/com/google/gwt/core/ext/impl/ResourceLocatorImpl.java b/dev/core/src/com/google/gwt/core/ext/impl/ResourceLocatorImpl.java
new file mode 100644
index 0000000..f73c09c
--- /dev/null
+++ b/dev/core/src/com/google/gwt/core/ext/impl/ResourceLocatorImpl.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.core.ext.impl;
+
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.dev.resource.Resource;
+import com.google.gwt.dev.resource.ResourceOracle;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+/**
+ * Temporary internal utility functions for locating Resources.
+ */
+public class ResourceLocatorImpl {
+
+ private static final int CLASS_LOADER_LOAD_REPORT_LIMIT = 10;
+
+ private static int classLoaderLoadCount;
+
+ public static void resetClassLoaderLoadWarningCount() {
+ classLoaderLoadCount = 0;
+ }
+
+ public static InputStream toStreamOrNull(Resource resource) {
+ if (resource == null) {
+ return null;
+ }
+ try {
+ return resource.openContents();
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns an InputStream for the given resource as found in the ResourceOracle.
+ * <p>
+ * Returns null if a resource is unavailable or the stream fails to open. Matching the
+ * ClassLoader.getResourceAsStream() semantic.
+ * <p>
+ * For backwards compatibility it will fallback on finding via ClassLoader and warn the user about
+ * the problems this can cause in per-file compiles.
+ * <p>
+ * Should only be used by internal Generators and only till ClassLoader fallback is deprecated.
+ */
+ // TODO(stalcup): migrate internal Generators away from needing ClassLoader fallback.
+ public static InputStream tryFindResourceAsStream(TreeLogger logger,
+ ResourceOracle resourceOracle, String resourceName) {
+ URL url = ResourceLocatorImpl.tryFindResourceUrl(logger, resourceOracle, resourceName);
+ if (url == null) {
+ return null;
+ }
+ try {
+ return url.openStream();
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns a URL for the given resource as found in the ResourceOracle.
+ * <p>
+ * For backwards compatibility it will fallback on finding via ClassLoader and warn the user about
+ * the problems this can cause in per-file compiles.
+ * <p>
+ * Should only be used by internal Generators and only till ClassLoader fallback is deprecated.
+ */
+ // TODO(stalcup): migrate internal Generators away from needing ClassLoader fallback.
+ public static URL tryFindResourceUrl(TreeLogger logger, ResourceOracle resourceOracle,
+ String resourceName) {
+ // Also associates the requested resource with the currently being rebound type (via
+ // RecordingResourceOracle).
+ Resource resource = resourceOracle.getResource(resourceName);
+ if (resource != null) {
+ return resource.getURL();
+ }
+
+ // Fall back on loading resources via ClassLoader. This is needed for backwards compatibility
+ // but should be avoided in favor of ResourceOracle loads since ResourceOracle loads so that
+ // Resource modifications can be noticed and reacted to in per-file compilation recompiles.
+ URL resourceUrl = Thread.currentThread().getContextClassLoader().getResource(resourceName);
+ if (resourceUrl != null) {
+ if (classLoaderLoadCount++ < CLASS_LOADER_LOAD_REPORT_LIMIT) {
+ logger.log(TreeLogger.WARN, "Resource '" + resourceName
+ + "' was located via ClassLoader. As a result changes in that resource will not be "
+ + "reflected in per-file recompiles. It should be registered via <source /> or "
+ + "<resource /> entry in your .gwt.xml. In a future version of GWT, we will remove "
+ + "this fallback and you application will stop compiling");
+ if (classLoaderLoadCount == CLASS_LOADER_LOAD_REPORT_LIMIT) {
+ logger.log(TreeLogger.WARN, "Suppressing further ClassLoader resource load warnings.");
+ }
+ }
+ return resourceUrl;
+ }
+
+ return null;
+ }
+}
diff --git a/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java b/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java
index 874e416..a5ecf06 100644
--- a/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java
+++ b/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java
@@ -16,6 +16,7 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.linker.ArtifactSet;
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.jjs.JsSourceMap;
@@ -24,13 +25,16 @@
import com.google.gwt.dev.jjs.ast.JTypeOracle.ImmediateTypeRelations;
import com.google.gwt.dev.jjs.impl.ResolveRuntimeTypeReferences.IntTypeIdGenerator;
import com.google.gwt.dev.js.JsPersistentPrettyNamer.PersistentPrettyNamerState;
+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.collect.HashMultimap;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableList;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Multimap;
import com.google.gwt.thirdparty.guava.common.collect.Sets;
+import com.google.gwt.thirdparty.guava.common.collect.Sets.SetView;
import java.io.Serializable;
import java.util.Collection;
@@ -64,9 +68,10 @@
typeNamesByReferencingTypeName.put(toTypeName, fromTypeName);
}
- public void clearJsAndStatements(String typeName) {
+ public void clearCachedTypeOutput(String typeName) {
jsByTypeName.remove(typeName);
statementRangesByTypeName.remove(typeName);
+ sourceMapsByTypeName.remove(typeName);
}
/**
@@ -99,14 +104,14 @@
return jsByTypeName.get(typeName);
}
- public StatementRanges getStatementRanges(String typeName) {
- return statementRangesByTypeName.get(typeName);
- }
-
public JsSourceMap getSourceMap(String typeName) {
return sourceMapsByTypeName.get(typeName);
}
+ public StatementRanges getStatementRanges(String typeName) {
+ return statementRangesByTypeName.get(typeName);
+ }
+
public void removeReferencesFrom(String fromTypeName) {
Collection<String> toTypeNames = referencedTypeNamesByTypeName.get(fromTypeName);
for (String toTypeName : toTypeNames) {
@@ -151,13 +156,17 @@
private final IntTypeIdGenerator intTypeIdGenerator = new IntTypeIdGenerator();
private final Set<String> jsoStatusChangedTypeNames = Sets.newHashSet();
private final Set<String> jsoTypeNames = Sets.newHashSet();
+ private final Map<String, Long> lastModifiedByResourcePath = Maps.newHashMap();
private final Set<String> modifiedCompilationUnitNames = Sets.newHashSet();
+ private final Set<String> modifiedResourcePaths = Sets.newHashSet();
private final Multimap<String, String> nestedTypeNamesByUnitTypeName = HashMultimap.create();
private final Map<Integer, PermutationRebuildCache> permutationRebuildCacheById =
Maps.newHashMap();
private final PersistentPrettyNamerState persistentPrettyNamerState =
new PersistentPrettyNamerState();
private final Set<String> preambleTypeNames = Sets.newHashSet();
+ private final Multimap<String, String> rebinderTypeNamesByReboundTypeName = HashMultimap.create();
+ private final Multimap<String, String> reboundTypeNamesByInputResource = HashMultimap.create();
private final Set<String> rootTypeNames = Sets.newHashSet();
private final Set<String> singleJsoImplInterfaceNames = Sets.newHashSet();
@@ -176,6 +185,15 @@
this.modifiedCompilationUnitNames.addAll(modifiedCompilationUnitNames);
}
+ /**
+ * Record that a Generator that was ran as a result of a GWT.create(ReboundType.class) call read a
+ * particular resource.
+ */
+ public void associateReboundTypeWithInputResource(String reboundTypeName,
+ String inputResourcePath) {
+ reboundTypeNamesByInputResource.put(inputResourcePath, reboundTypeName);
+ }
+
public void clearPerTypeJsCache() {
rootTypeNames.clear();
preambleTypeNames.clear();
@@ -184,8 +202,16 @@
permutationRebuildCacheById.clear();
}
+ public void clearRebinderTypeAssociations(String rebinderTypeName) {
+ rebinderTypeNamesByReboundTypeName.values().remove(rebinderTypeName);
+ }
+
+ public void clearReboundTypeAssociations(String reboundTypeName) {
+ reboundTypeNamesByInputResource.values().remove(reboundTypeName);
+ }
+
/**
- * Calculates the set of stale types and clears their cached Js and StatementRanges.
+ * Calculates the set of stale types and clears their cached Js, StatementRanges and SourceMaps.
* <p>
* The calculation of stale types starts with the list of known modified types and expands that
* set using various patterns intended to find any types whose output JS would be affected by the
@@ -206,8 +232,8 @@
Set<String> staleTypeNames = Sets.newHashSet();
Set<String> modifiedTypeNames = computeModifiedTypeNames();
- // Accumulate the names of stale types resulting from some known type modifications, using
- // various patterns (sub types, referencing types, etc).
+ // Accumulate the names of stale types resulting from some known type or resource modifications,
+ // using various patterns (sub types, referencing types, etc).
{
staleTypeNames.addAll(modifiedTypeNames);
appendSubTypes(staleTypeNames, modifiedTypeNames, typeOracle);
@@ -217,16 +243,21 @@
ImmutableList<String> modifiedTypeAndSubTypeNames = ImmutableList.copyOf(staleTypeNames);
appendReferencingTypes(staleTypeNames, modifiedTypeAndSubTypeNames);
appendReferencingTypes(staleTypeNames, jsoStatusChangedTypeNames);
- // TODO(stalcup): turn modifications of generator input resources into type staleness.
+ appendTypesThatRebindTypes(staleTypeNames, computeReboundTypesAffectedByModifiedResources());
+ // TODO(stalcup): turn modifications of generator input types into type staleness.
staleTypeNames.removeAll(JProgram.SYNTHETIC_TYPE_NAMES);
}
- logger.log(TreeLogger.DEBUG, "known modified types = " + modifiedTypeNames);
- logger.log(TreeLogger.DEBUG,
- "clearing cached JS for resulting stale types = " + staleTypeNames);
+ // These log lines can be expensive.
+ if (logger.isLoggable(TreeLogger.DEBUG)) {
+ logger.log(TreeLogger.DEBUG, "known modified types = " + modifiedTypeNames);
+ logger.log(TreeLogger.DEBUG, "known modified resources = " + modifiedResourcePaths);
+ logger.log(TreeLogger.DEBUG,
+ "clearing cached output for resulting stale types = " + staleTypeNames);
+ }
for (String staleTypeName : staleTypeNames) {
- clearJsAndStatements(staleTypeName);
+ clearCachedTypeOutput(staleTypeName);
}
return staleTypeNames;
@@ -317,6 +348,45 @@
return !preambleTypeNames.isEmpty();
}
+ /**
+ * Records the resource paths and modification dates of build resources in the current compile and
+ * builds a list of known modified resource paths by comparing the resource paths and modification
+ * dates of build resources in the previous compile with those of the current compile.
+ */
+ public void recordBuildResources(ModuleDef module) {
+ // To start lastModifiedByResourcePath is data about the previous compile and by the end it
+ // contains data about the current compile.
+
+ Set<Resource> currentResources = module.getBuildResourceOracle().getResources();
+
+ // Start with a from-scratch idea of which resources are modified.
+ modifiedResourcePaths.clear();
+
+ Set<String> currentResourcePaths = Sets.newHashSet();
+ for (Resource currentResource : currentResources) {
+ currentResourcePaths.add(currentResource.getPath());
+ Long lastKnownModified = lastModifiedByResourcePath.put(currentResource.getPath(),
+ currentResource.getLastModified());
+ if (!Objects.equal(lastKnownModified, currentResource.getLastModified())) {
+ // Added or Modified resource.
+ modifiedResourcePaths.add(currentResource.getPath());
+ }
+ }
+
+ // Removed resources.
+ {
+ // Figure out which resources were removed.
+ SetView<String> removedResourcePaths =
+ Sets.difference(lastModifiedByResourcePath.keySet(), currentResourcePaths);
+ // Log them as "modified".
+ modifiedResourcePaths.addAll(removedResourcePaths);
+ // Remove any resource path to modified date entries for them.
+ for (String removedResourcePath : removedResourcePaths) {
+ lastModifiedByResourcePath.remove(removedResourcePath);
+ }
+ }
+ }
+
@VisibleForTesting
public void recordNestedTypeName(String compilationUnitTypeName, String nestedTypeName) {
nestedTypeNamesByUnitTypeName.put(compilationUnitTypeName, nestedTypeName);
@@ -334,6 +404,13 @@
}
}
+ /**
+ * Records that rebinder type Foo contains a GWT.create(ReboundTypeBar.class) call.
+ */
+ public void recordRebinderTypeForReboundType(String reboundTypeName, String rebinderType) {
+ rebinderTypeNamesByReboundTypeName.put(reboundTypeName, rebinderType);
+ }
+
public void setAllCompilationUnitNames(TreeLogger logger,
Set<String> newAllCompilationUnitNames) {
deletedCompilationUnitNames.clear();
@@ -397,9 +474,32 @@
}
}
- private void clearJsAndStatements(String staleTypeName) {
- for (PermutationRebuildCache permutationRebuildCache : permutationRebuildCacheById.values()) {
- permutationRebuildCache.clearJsAndStatements(staleTypeName);
+ /**
+ * Adds to staleTypeNames the set of names of types that contain GWT.create(ReboundType.class)
+ * calls that rebind the given set of type names.
+ */
+ private void appendTypesThatRebindTypes(Set<String> staleTypeNames,
+ Set<String> reboundTypeNames) {
+ for (String reboundTypeName : reboundTypeNames) {
+ staleTypeNames.addAll(rebinderTypeNamesByReboundTypeName.get(reboundTypeName));
}
}
+
+ private void clearCachedTypeOutput(String staleTypeName) {
+ for (PermutationRebuildCache permutationRebuildCache : permutationRebuildCacheById.values()) {
+ permutationRebuildCache.clearCachedTypeOutput(staleTypeName);
+ }
+ }
+
+ /**
+ * Returns the set of names of types that when rebound trigger Generators that access resources
+ * which are known to have been modified.
+ */
+ private Set<String> computeReboundTypesAffectedByModifiedResources() {
+ Set<String> affectedRebindTypeNames = Sets.newHashSet();
+ for (String modifiedResourcePath : modifiedResourcePaths) {
+ affectedRebindTypeNames.addAll(reboundTypeNamesByInputResource.get(modifiedResourcePath));
+ }
+ return affectedRebindTypeNames;
+ }
}
diff --git a/dev/core/src/com/google/gwt/dev/Precompile.java b/dev/core/src/com/google/gwt/dev/Precompile.java
index 58ef3e7..b5e9846 100644
--- a/dev/core/src/com/google/gwt/dev/Precompile.java
+++ b/dev/core/src/com/google/gwt/dev/Precompile.java
@@ -242,6 +242,11 @@
try {
ModuleDef module = compilerContext.getModule();
PrecompileTaskOptions jjsOptions = compilerContext.getOptions();
+ if (jjsOptions.shouldCompilePerFile()) {
+ compilerContext.getMinimalRebuildCache().recordBuildResources(module);
+ // TODO(stalcup): record source resources here instead of in CompilationStateBuilder, for
+ // consistency.
+ }
CompilationState compilationState = module.getCompilationState(logger, compilerContext);
if (jjsOptions.isStrict() && compilationState.hasErrors()) {
abortDueToStrictMode(logger);
diff --git a/dev/core/src/com/google/gwt/dev/cfg/CombinedResourceOracle.java b/dev/core/src/com/google/gwt/dev/cfg/CombinedResourceOracle.java
index 23e9932..2dee4dc 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/CombinedResourceOracle.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/CombinedResourceOracle.java
@@ -13,12 +13,14 @@
*/
package com.google.gwt.dev.cfg;
+import com.google.gwt.core.ext.impl.ResourceLocatorImpl;
import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Sets;
+import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -61,6 +63,17 @@
}
@Override
+ public Resource getResource(String pathName) {
+ return getResourceMap().get(pathName);
+ }
+
+ @Override
+ public InputStream getResourceAsStream(String pathName) {
+ return ResourceLocatorImpl.toStreamOrNull(getResource(pathName));
+ }
+
+ @Deprecated
+ @Override
public Map<String, Resource> getResourceMap() {
if (buildResourcesByPath == null) {
buildResourcesByPath = Maps.newHashMap();
diff --git a/dev/core/src/com/google/gwt/dev/cfg/LibraryGroupBuildResourceOracle.java b/dev/core/src/com/google/gwt/dev/cfg/LibraryGroupBuildResourceOracle.java
index 92cf4c9..40b7cd1 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/LibraryGroupBuildResourceOracle.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/LibraryGroupBuildResourceOracle.java
@@ -15,12 +15,14 @@
*/
package com.google.gwt.dev.cfg;
+import com.google.gwt.core.ext.impl.ResourceLocatorImpl;
import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Sets;
+import java.io.InputStream;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
@@ -53,6 +55,17 @@
}
@Override
+ public Resource getResource(String pathName) {
+ return getResourceMap().get(pathName);
+ }
+
+ @Override
+ public InputStream getResourceAsStream(String pathName) {
+ return ResourceLocatorImpl.toStreamOrNull(getResource(pathName));
+ }
+
+ @Deprecated
+ @Override
public Map<String, Resource> getResourceMap() {
if (buildResourcesByPath == null) {
buildResourcesByPath = Maps.newHashMap();
diff --git a/dev/core/src/com/google/gwt/dev/cfg/LibraryGroupPublicResourceOracle.java b/dev/core/src/com/google/gwt/dev/cfg/LibraryGroupPublicResourceOracle.java
index bd41946..fd6d87b 100644
--- a/dev/core/src/com/google/gwt/dev/cfg/LibraryGroupPublicResourceOracle.java
+++ b/dev/core/src/com/google/gwt/dev/cfg/LibraryGroupPublicResourceOracle.java
@@ -15,12 +15,14 @@
*/
package com.google.gwt.dev.cfg;
+import com.google.gwt.core.ext.impl.ResourceLocatorImpl;
import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Sets;
+import java.io.InputStream;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
@@ -53,6 +55,17 @@
}
@Override
+ public Resource getResource(String pathName) {
+ return getResourceMap().get(pathName);
+ }
+
+ @Override
+ public InputStream getResourceAsStream(String pathName) {
+ return ResourceLocatorImpl.toStreamOrNull(getResource(pathName));
+ }
+
+ @Deprecated
+ @Override
public Map<String, Resource> getResourceMap() {
if (publicResourcesByPath == null) {
publicResourcesByPath = Maps.newHashMap();
diff --git a/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java b/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java
index baa34fa..56db2c0 100644
--- a/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java
+++ b/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java
@@ -25,6 +25,7 @@
import com.google.gwt.core.ext.SubsetFilteringPropertyOracle;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.impl.ResourceLocatorImpl;
import com.google.gwt.core.ext.linker.Artifact;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.linker.EmittedArtifact.Visibility;
@@ -34,6 +35,7 @@
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.CompilerContext;
import com.google.gwt.dev.cfg.RuleGenerateWith;
+import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.dev.util.DiskCache;
import com.google.gwt.dev.util.Util;
@@ -48,6 +50,7 @@
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -66,6 +69,51 @@
public class StandardGeneratorContext implements GeneratorContext {
/**
+ * Wraps a ResourceOracle to collect the paths of Resources read by Generators.
+ */
+ private class RecordingResourceOracle implements ResourceOracle {
+
+ private final ResourceOracle wrappedResourceOracle;
+
+ public RecordingResourceOracle(ResourceOracle wrappedResourceOracle) {
+ this.wrappedResourceOracle = wrappedResourceOracle;
+ }
+
+ @Override
+ public void clear() {
+ wrappedResourceOracle.clear();
+ }
+
+ @Override
+ public Set<String> getPathNames() {
+ return wrappedResourceOracle.getPathNames();
+ }
+
+ @Override
+ public Resource getResource(String pathName) {
+ compilerContext.getMinimalRebuildCache().associateReboundTypeWithInputResource(
+ currentRebindBinaryTypeName, pathName);
+ return wrappedResourceOracle.getResource(pathName);
+ }
+
+ @Deprecated
+ @Override
+ public Map<String, Resource> getResourceMap() {
+ return wrappedResourceOracle.getResourceMap();
+ }
+
+ @Override
+ public Set<Resource> getResources() {
+ return wrappedResourceOracle.getResources();
+ }
+
+ @Override
+ public InputStream getResourceAsStream(String pathName) {
+ return ResourceLocatorImpl.toStreamOrNull(getResource(pathName));
+ }
+ }
+
+ /**
* Extras added to {@link GeneratedUnit}.
*/
private static interface Generated extends GeneratedUnit {
@@ -309,6 +357,10 @@
private CompilerContext compilerContext;
+ private String currentRebindBinaryTypeName;
+
+ private final ResourceOracle buildResourceOracle;
+
/**
* Normally, the compiler host would be aware of the same types that are
* available in the supplied type oracle although it isn't strictly required.
@@ -320,6 +372,11 @@
this.genDir = compilerContext.getOptions().getGenDir();
this.allGeneratedArtifacts = allGeneratedArtifacts;
this.isProdMode = isProdMode;
+
+ this.buildResourceOracle =
+ new RecordingResourceOracle(compilerContext.getBuildResourceOracle());
+
+ ResourceLocatorImpl.resetClassLoaderLoadWarningCount();
}
/**
@@ -589,7 +646,7 @@
@Override
public ResourceOracle getResourcesOracle() {
- return compilerContext.getBuildResourceOracle();
+ return buildResourceOracle;
}
@Override
@@ -740,6 +797,10 @@
this.currentGenerator = currentGenerator;
}
+ public void setCurrentRebindBinaryTypeName(String currentRebindBinaryTypeName) {
+ this.currentRebindBinaryTypeName = currentRebindBinaryTypeName;
+ }
+
public void setGeneratorResultCachingEnabled(boolean enabled) {
this.generatorResultCachingEnabled = enabled;
}
@@ -900,12 +961,9 @@
}
// Warn the user about uncommitted resources.
- logger =
- logger
- .branch(
- TreeLogger.WARN,
- "The following resources will not be created because they were never committed (did you forget to call commit()?)",
- null);
+ logger = logger.branch(TreeLogger.WARN,
+ "The following resources will not be created because they were never "
+ + "committed (did you forget to call commit()?)", null);
for (Entry<String, PendingResource> entry : pendingResources.entrySet()) {
logger.log(TreeLogger.WARN, entry.getKey());
diff --git a/dev/core/src/com/google/gwt/dev/javac/testing/impl/MockResourceOracle.java b/dev/core/src/com/google/gwt/dev/javac/testing/impl/MockResourceOracle.java
index 2b6713c..1679375 100644
--- a/dev/core/src/com/google/gwt/dev/javac/testing/impl/MockResourceOracle.java
+++ b/dev/core/src/com/google/gwt/dev/javac/testing/impl/MockResourceOracle.java
@@ -69,6 +69,7 @@
return exportedMap.keySet();
}
+ @Deprecated
@Override
public Map<String, Resource> getResourceMap() {
return exportedMap;
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 70be973..0f0fc4d 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
@@ -457,7 +457,25 @@
private JExpression createStaticRebindExpression(JMethodCall gwtCreateCall,
JClassLiteral classLiteral) {
JDeclaredType type = (JDeclaredType) classLiteral.getRefType();
- String reqType = BinaryName.toSourceName(type.getName());
+ String reboundTypeName = type.getName();
+ // TODO(stalcup): below a MinimalRebuildCache pattern of "clear cache entries for a type" and
+ // "rebuild cache entries for that type" is followed. There is a danger that a compile error
+ // could occur between the two stages and leave the cache in an invalid state. Switch to a
+ // transactionally safe update pattern like always updating a copy and swapping out the
+ // original for the copy at the end of a successful compile.
+ if (compilePerFile) {
+ // If this is the first time we've rebound this type during this compile.
+ if (reboundTypeNames.add(reboundTypeName)) {
+ // The rebinding of this type will accumulate rebound type to input resource associations,
+ // but the accumulation should start from scratch, so clear any existing associations that
+ // might have been collected in previous compiles.
+ minimalRebuildCache.clearReboundTypeAssociations(reboundTypeName);
+ }
+ minimalRebuildCache.recordRebinderTypeForReboundType(reboundTypeName,
+ currentMethod.getEnclosingType().getName());
+ rpo.getGeneratorContext().setCurrentRebindBinaryTypeName(reboundTypeName);
+ }
+ String reqType = BinaryName.toSourceName(reboundTypeName);
List<String> answers;
try {
answers = Lists.create(rpo.getAllPossibleRebindAnswers(logger, reqType));
@@ -641,6 +659,7 @@
private final Map<String, JMethod> methodMap = new HashMap<String, JMethod>();
private final JProgram program;
private final RebindPermutationOracle rpo;
+ private final Set<String> reboundTypeNames = Sets.newHashSet();
/**
* The names of types whose per-file compilation cached Js and StatementRanges are known to no
@@ -1107,6 +1126,10 @@
private void fullFlowIntoType(JDeclaredType type) {
String typeName = type.getName();
if (!fullFlowTypes.contains(typeName) && !typeName.endsWith("package-info")) {
+ // 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.
+ minimalRebuildCache.clearRebinderTypeAssociations(type.getName());
fullFlowTypes.add(type.getName());
instantiate(type);
for (JField field : type.getFields()) {
diff --git a/dev/core/src/com/google/gwt/dev/resource/ResourceOracle.java b/dev/core/src/com/google/gwt/dev/resource/ResourceOracle.java
index 9bf1dc7..6e61fdb 100644
--- a/dev/core/src/com/google/gwt/dev/resource/ResourceOracle.java
+++ b/dev/core/src/com/google/gwt/dev/resource/ResourceOracle.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.dev.resource;
+import java.io.InputStream;
import java.util.Map;
import java.util.Set;
@@ -47,8 +48,24 @@
Set<String> getPathNames();
/**
- * Returns an unmodifiable map of abstract path name to resource.
+ * Returns the resource for the given path name or null if there is no such resource.
*/
+ Resource getResource(String pathName);
+
+ /**
+ * Returns the resource input stream for the given path name or null if there
+ * is no such resource.
+ */
+ InputStream getResourceAsStream(String pathName);
+
+ /**
+ * Returns an unmodifiable map of abstract path name to resource.
+ *
+ * @deprecated use {@link #getResource(String pathName)}, {@link #getResources()}, and
+ * {@link #getPathNames()} instead so that access to specific resources can be
+ * tracked.
+ */
+ @Deprecated
Map<String, Resource> getResourceMap();
/**
diff --git a/dev/core/src/com/google/gwt/dev/resource/impl/ResourceOracleImpl.java b/dev/core/src/com/google/gwt/dev/resource/impl/ResourceOracleImpl.java
index 9740a93..eaf0708 100644
--- a/dev/core/src/com/google/gwt/dev/resource/impl/ResourceOracleImpl.java
+++ b/dev/core/src/com/google/gwt/dev/resource/impl/ResourceOracleImpl.java
@@ -16,6 +16,7 @@
package com.google.gwt.dev.resource.impl;
import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.impl.ResourceLocatorImpl;
import com.google.gwt.dev.cfg.ResourceLoader;
import com.google.gwt.dev.cfg.ResourceLoaders;
import com.google.gwt.dev.resource.Resource;
@@ -464,12 +465,23 @@
return pathPrefixSet;
}
+ @Deprecated
@Override
public Map<String, Resource> getResourceMap() {
return exposedResourceMap;
}
@Override
+ public Resource getResource(String pathName) {
+ return getResourceMap().get(pathName);
+ }
+
+ @Override
+ public InputStream getResourceAsStream(String pathName) {
+ return ResourceLocatorImpl.toStreamOrNull(getResource(pathName));
+ }
+
+ @Override
public Set<Resource> getResources() {
return exposedResources;
}
diff --git a/dev/core/test/com/google/gwt/dev/CompilerTest.java b/dev/core/test/com/google/gwt/dev/CompilerTest.java
index 46a93b4..16acb14 100644
--- a/dev/core/test/com/google/gwt/dev/CompilerTest.java
+++ b/dev/core/test/com/google/gwt/dev/CompilerTest.java
@@ -144,6 +144,14 @@
"</generate-with>",
"</module>");
+ private MockResource classNameToGenerateResource =
+ JavaResourceBase.createMockResource("com/foo/generatedClassName.txt",
+ "FooReplacementOne");
+
+ private MockResource modifiedClassNameToGenerateResource =
+ JavaResourceBase.createMockResource("com/foo/generatedClassName.txt",
+ "FooReplacementTwo");
+
private MockJavaResource generatorEntryPointResource =
JavaResourceBase.createMockJavaResource("com.foo.TestEntryPoint",
"package com.foo;",
@@ -426,6 +434,14 @@
checkPerFileRecompile_dualJsoIntfDispatchChange(JsOutputOption.DETAILED);
}
+ public void testPerFileRecompile_generatorInputResourceChange() throws IOException,
+ UnableToCompleteException, InterruptedException {
+ // Not testing recompile equality with Pretty output since the Pretty namer'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.
+ checkPerFileRecompile_generatorInputResourceChange(JsOutputOption.DETAILED);
+ }
+
public void testPerFileRecompile_carriesOverGeneratorArtifacts() throws UnableToCompleteException,
IOException, InterruptedException {
// Foo Generator hasn't run yet.
@@ -433,7 +449,7 @@
CompilerOptions compilerOptions = new CompilerOptionsImpl();
List<MockResource> sharedResources = Lists.newArrayList(generatorModuleResource,
- generatorEntryPointResource, fooInterfaceResource);
+ generatorEntryPointResource, fooInterfaceResource, classNameToGenerateResource);
JsOutputOption output = JsOutputOption.PRETTY;
List<MockResource> originalResources = Lists.newArrayList(sharedResources);
@@ -548,6 +564,17 @@
output);
}
+ private void checkPerFileRecompile_generatorInputResourceChange(JsOutputOption outputOption)
+ throws IOException, UnableToCompleteException, InterruptedException {
+ CompilerOptions compilerOptions = new CompilerOptionsImpl();
+ compilerOptions.setUseDetailedTypeIds(true);
+
+ checkRecompiledModifiedApp(compilerOptions, "com.foo.SimpleModule", Lists.newArrayList(
+ generatorModuleResource, generatorEntryPointResource, fooInterfaceResource,
+ nonJsoFooResource), classNameToGenerateResource, modifiedClassNameToGenerateResource,
+ outputOption);
+ }
+
private void assertDeterministicBuild(CompilerOptions options)
throws UnableToCompleteException, IOException {
File firstCompileWorkDir = Utility.makeTemporaryDirectory(null, "hellowork");
@@ -588,16 +615,15 @@
}
private void checkRecompiledModifiedApp(String moduleName, List<MockResource> sharedResources,
- MockJavaResource originalResource, MockJavaResource modifiedResource, JsOutputOption output)
- throws IOException,
- UnableToCompleteException, InterruptedException {
+ MockResource originalResource, MockResource modifiedResource, JsOutputOption output)
+ throws IOException, UnableToCompleteException, InterruptedException {
checkRecompiledModifiedApp(new CompilerOptionsImpl(), moduleName, sharedResources,
originalResource, modifiedResource, output);
}
private void checkRecompiledModifiedApp(CompilerOptions compilerOptions, String moduleName,
- List<MockResource> sharedResources, MockJavaResource originalResource,
- MockJavaResource modifiedResource, JsOutputOption output) throws IOException,
+ List<MockResource> sharedResources, MockResource originalResource,
+ MockResource modifiedResource, JsOutputOption output) throws IOException,
UnableToCompleteException, InterruptedException {
List<MockResource> originalResources = Lists.newArrayList(sharedResources);
originalResources.add(originalResource);
diff --git a/dev/core/test/com/google/gwt/dev/FooResourceGenerator.java b/dev/core/test/com/google/gwt/dev/FooResourceGenerator.java
index 28807f6..e813dc5 100644
--- a/dev/core/test/com/google/gwt/dev/FooResourceGenerator.java
+++ b/dev/core/test/com/google/gwt/dev/FooResourceGenerator.java
@@ -18,13 +18,15 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.EmittedArtifact.Visibility;
+import com.google.gwt.dev.util.Util;
import com.google.gwt.thirdparty.guava.common.base.Charsets;
import java.io.IOException;
import java.io.OutputStream;
+import java.io.PrintWriter;
/**
- * A Generator that always creates a bar.txt resource.
+ * A Generator that creates a bar.txt resource and a class whose name depends on an input resource.
*/
public class FooResourceGenerator extends Generator {
@@ -34,16 +36,35 @@
public String generate(TreeLogger logger, GeneratorContext context, String typeName)
throws UnableToCompleteException {
runCount++;
+
+ // On first run generate a bar.txt resource that always has the same contents.
OutputStream barStream = context.tryCreateResource(logger, "bar.txt");
if (barStream != null) {
try {
barStream.write("here's some text.".getBytes(Charsets.UTF_8));
- context.commitResource(logger, barStream).setVisibility(
- Visibility.Public);
+ context.commitResource(logger, barStream).setVisibility(Visibility.Public);
} catch (IOException e) {
return null;
}
}
- return null;
+
+ // On first run generate a class whose name depends on the contents of a read input resource.
+ String generatedClassName;
+ try {
+ generatedClassName = Util.readStreamAsString(context.getResourcesOracle().getResource(
+ "com/foo/generatedClassName.txt").openContents()).trim();
+
+ PrintWriter pw = context.tryCreate(logger, "com.foo", generatedClassName);
+ if (pw != null) {
+ pw.write("package com.foo;");
+ pw.write("public class " + generatedClassName + " {}");
+
+ pw.close();
+ context.commit(logger, pw);
+ }
+ return "com.foo." + generatedClassName;
+ } catch (IOException e) {
+ return "";
+ }
}
}
diff --git a/user/src/com/google/gwt/i18n/rebind/AbstractLocalizableImplCreator.java b/user/src/com/google/gwt/i18n/rebind/AbstractLocalizableImplCreator.java
index 3890ffe..cd324f6 100644
--- a/user/src/com/google/gwt/i18n/rebind/AbstractLocalizableImplCreator.java
+++ b/user/src/com/google/gwt/i18n/rebind/AbstractLocalizableImplCreator.java
@@ -183,7 +183,7 @@
ResourceList resourceList = null;
try {
resourceList = ResourceFactory.getBundle(logger, targetClass, locale,
- assignableToConstants, context.getResourcesOracle().getResourceMap(), context);
+ assignableToConstants, context);
} catch (MissingResourceException e) {
throw error(logger,
"Localization failed; there must be at least one resource accessible through"
@@ -220,8 +220,8 @@
targetClass, resourceList, context.getTypeOracle());
c.emitClass(logger, generatedLocale);
} else {
- MessagesImplCreator messages = new MessagesImplCreator(logger, writer,
- targetClass, resourceList, context.getTypeOracle());
+ MessagesImplCreator messages = new MessagesImplCreator(logger, writer, targetClass,
+ resourceList, context.getTypeOracle(), context.getResourcesOracle());
messages.emitClass(logger, generatedLocale);
}
context.commit(logger, pw);
@@ -333,19 +333,8 @@
* Write translation source files to the old-style
* {@link MessageCatalogFormat}.
*
- * @param logger
- * @param context
- * @param locale
- * @param targetClass
- * @param seenError
- * @param resourceList
- * @param className
- * @param msgWriter
- * @param genPath
* @return true if an error occurred (already logged)
- * @throws UnableToCompleteException
*/
-
private static boolean generateToLegacyMsgCatFormat(TreeLogger logger,
GeneratorContext context, GwtLocale locale, JClassType targetClass,
boolean seenError, ResourceList resourceList, String className,
diff --git a/user/src/com/google/gwt/i18n/rebind/CurrencyListGenerator.java b/user/src/com/google/gwt/i18n/rebind/CurrencyListGenerator.java
index 9923b0c..fc120f3 100644
--- a/user/src/com/google/gwt/i18n/rebind/CurrencyListGenerator.java
+++ b/user/src/com/google/gwt/i18n/rebind/CurrencyListGenerator.java
@@ -22,9 +22,11 @@
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.impl.ResourceLocatorImpl;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
+import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.i18n.client.CurrencyList;
import com.google.gwt.i18n.client.impl.CurrencyDataImpl;
import com.google.gwt.i18n.shared.GwtLocale;
@@ -329,12 +331,13 @@
String lastDefaultCurrencyCode = null;
for (int i = searchList.size(); i-- > 0;) {
GwtLocale search = searchList.get(i);
- LocalizedProperties newExtra = getProperties(CURRENCY_EXTRA_PREFIX,
- search);
+ LocalizedProperties newExtra =
+ getProperties(logger, CURRENCY_EXTRA_PREFIX, search, context.getResourcesOracle());
if (newExtra != null) {
currencyExtra = newExtra;
}
- Map<String, String> currencyData = getCurrencyData(search);
+ Map<String, String> currencyData =
+ getCurrencyData(logger, search, context.getResourcesOracle());
Set<String> keySet = currencyData.keySet();
String[] currencies = new String[keySet.size()];
keySet.toArray(currencies);
@@ -348,7 +351,7 @@
currencyData.get(currencyCode), extraData));
}
- String defCurrencyCode = getDefaultCurrency(search);
+ String defCurrencyCode = getDefaultCurrency(logger, search, context.getResourcesOracle());
// If this locale specifies a particular locale, or the one that is
// inherited has been changed in this locale, re-specify the default
// currency so the method will be generated.
@@ -558,14 +561,12 @@
* If a symbol is not supplied, the currency code will be used If # of decimal
* digits is omitted, 2 is used If a currency is not generally used,
* not-used-flag=1 Trailing empty fields can be omitted
- *
- * @param locale
- * @return currency data map
*/
@SuppressWarnings("unchecked")
- private Map<String, String> getCurrencyData(GwtLocale locale) {
- LocalizedProperties currencyData = getProperties(CURRENCY_DATA_PREFIX,
- locale);
+ private Map<String, String> getCurrencyData(TreeLogger logger, GwtLocale locale,
+ ResourceOracle resourceOracle) {
+ LocalizedProperties currencyData =
+ getProperties(logger, CURRENCY_DATA_PREFIX, locale, resourceOracle);
if (currencyData == null) {
return Collections.emptyMap();
}
@@ -574,13 +575,12 @@
/**
* Returns the default currency code for the requested locale.
- *
- * @param locale
- * @return ISO4217 currency code
*/
- private String getDefaultCurrency(GwtLocale locale) {
+ private String getDefaultCurrency(TreeLogger logger, GwtLocale locale,
+ ResourceOracle resourceOracle) {
String defCurrencyCode = null;
- LocalizedProperties numberConstants = getProperties(NUMBER_CONSTANTS_PREFIX, locale);
+ LocalizedProperties numberConstants =
+ getProperties(logger, NUMBER_CONSTANTS_PREFIX, locale, resourceOracle);
if (numberConstants != null) {
defCurrencyCode = numberConstants.getProperty("defCurrencyCode");
}
@@ -593,23 +593,25 @@
/**
* Load a properties file for a given locale. Note that locale inheritance is
* the responsibility of the caller.
- *
+ * @param logger with which to log
* @param prefix classpath prefix of properties file
* @param locale locale to load
+ * @param resourceOracle with which to locate resources
+ *
* @return LocalizedProperties instance containing properties file or null if
* not found.
*/
- private LocalizedProperties getProperties(String prefix, GwtLocale locale) {
+ private LocalizedProperties getProperties(TreeLogger logger, String prefix,
+ GwtLocale locale, ResourceOracle resourceOracle) {
String propFile = prefix;
if (!locale.isDefault()) {
propFile += "_" + locale.getAsString();
}
propFile += ".properties";
InputStream str = null;
- ClassLoader classLoader = getClass().getClassLoader();
LocalizedProperties props = new LocalizedProperties();
try {
- str = classLoader.getResourceAsStream(propFile);
+ str = ResourceLocatorImpl.tryFindResourceAsStream(logger, resourceOracle, propFile);
if (str != null) {
props.load(str, "UTF-8");
return props;
diff --git a/user/src/com/google/gwt/i18n/rebind/LocaleInfoGenerator.java b/user/src/com/google/gwt/i18n/rebind/LocaleInfoGenerator.java
index b2fe8df..60aa404 100644
--- a/user/src/com/google/gwt/i18n/rebind/LocaleInfoGenerator.java
+++ b/user/src/com/google/gwt/i18n/rebind/LocaleInfoGenerator.java
@@ -24,6 +24,7 @@
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.impl.ResourceLocatorImpl;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
@@ -125,17 +126,19 @@
LocalizedProperties displayNames = new LocalizedProperties();
LocalizedProperties displayNamesManual = new LocalizedProperties();
LocalizedProperties displayNamesOverride = new LocalizedProperties();
- ClassLoader classLoader = getClass().getClassLoader();
try {
- InputStream str = classLoader.getResourceAsStream(GENERATED_LOCALE_NATIVE_DISPLAY_NAMES);
+ InputStream str = ResourceLocatorImpl.tryFindResourceAsStream(logger,
+ context.getResourcesOracle(), GENERATED_LOCALE_NATIVE_DISPLAY_NAMES);
if (str != null) {
displayNames.load(str, "UTF-8");
}
- str = classLoader.getResourceAsStream(MANUAL_LOCALE_NATIVE_DISPLAY_NAMES);
+ str = ResourceLocatorImpl.tryFindResourceAsStream(logger, context.getResourcesOracle(),
+ MANUAL_LOCALE_NATIVE_DISPLAY_NAMES);
if (str != null) {
displayNamesManual.load(str, "UTF-8");
}
- str = classLoader.getResourceAsStream(OVERRIDE_LOCALE_NATIVE_DISPLAY_NAMES);
+ str = ResourceLocatorImpl.tryFindResourceAsStream(logger, context.getResourcesOracle(),
+ OVERRIDE_LOCALE_NATIVE_DISPLAY_NAMES);
if (str != null) {
displayNamesOverride.load(str, "UTF-8");
}
diff --git a/user/src/com/google/gwt/i18n/rebind/MessagesImplCreator.java b/user/src/com/google/gwt/i18n/rebind/MessagesImplCreator.java
index 1aa72ab..445342e 100644
--- a/user/src/com/google/gwt/i18n/rebind/MessagesImplCreator.java
+++ b/user/src/com/google/gwt/i18n/rebind/MessagesImplCreator.java
@@ -1,12 +1,12 @@
/*
* Copyright 2008 Google Inc.
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -21,6 +21,7 @@
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
+import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.i18n.rebind.AbstractResource.ResourceList;
import com.google.gwt.i18n.shared.GwtLocale;
import com.google.gwt.safehtml.shared.SafeHtml;
@@ -34,20 +35,21 @@
/**
* Constructor for <code>MessagesImplCreator</code>.
- *
+ * @param logger logger to print errors
* @param writer <code>Writer</code> to print to
* @param localizableClass Class/Interface to conform to
* @param resourceList resource bundle used to generate the class
* @param oracle types
- * @param logger logger to print errors
+ * @param resourceOracle in which to locate resources
+ *
* @throws UnableToCompleteException
*/
- public MessagesImplCreator(TreeLogger logger, SourceWriter writer,
- JClassType localizableClass, ResourceList resourceList, TypeOracle oracle)
+ public MessagesImplCreator(TreeLogger logger, SourceWriter writer, JClassType localizableClass,
+ ResourceList resourceList, TypeOracle oracle, ResourceOracle resourceOracle)
throws UnableToCompleteException {
super(logger, writer, localizableClass, resourceList, false);
try {
- MessagesMethodCreator creator = new MessagesMethodCreator(this, writer);
+ MessagesMethodCreator creator = new MessagesMethodCreator(this, writer, resourceOracle);
JClassType stringClass = oracle.getType(String.class.getName());
register(stringClass, creator);
JClassType safeHtmlClass = oracle.getType(SafeHtml.class.getName());
@@ -61,7 +63,7 @@
/**
* Checks that the method has the right structure to implement
* <code>Messages</code>.
- *
+ *
* @param method
* @throws UnableToCompleteException
*/
@@ -81,7 +83,7 @@
/**
* Create the method body associated with the given method. Arguments are
* arg0...argN.
- *
+ *
* @param m method to emit
* @throws UnableToCompleteException
*/
diff --git a/user/src/com/google/gwt/i18n/rebind/MessagesMethodCreator.java b/user/src/com/google/gwt/i18n/rebind/MessagesMethodCreator.java
index 1f5f443..017ea83 100644
--- a/user/src/com/google/gwt/i18n/rebind/MessagesMethodCreator.java
+++ b/user/src/com/google/gwt/i18n/rebind/MessagesMethodCreator.java
@@ -18,6 +18,7 @@
import com.google.gwt.codegen.server.StringGenerator;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.impl.ResourceLocatorImpl;
import com.google.gwt.core.ext.typeinfo.JArrayType;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JEnumConstant;
@@ -29,6 +30,7 @@
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
+import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
import com.google.gwt.i18n.client.Messages.AlternateMessage;
@@ -82,7 +84,7 @@
private abstract static class AlternateFormSelector {
protected final int argNumber;
protected final JType argType;
-
+
public AlternateFormSelector(TreeLogger logger, int argNumber, JParameter[] params) {
this.argNumber = argNumber;
this.argType = params[argNumber].getType();
@@ -102,7 +104,7 @@
*/
public abstract void generateSelectMatchStart(SourceWriter out,
TreeLogger logger, String value) throws UnableToCompleteException;
-
+
public abstract void generateSelectStart(SourceWriter out,
boolean exactMatches);
@@ -167,7 +169,7 @@
* all non-exact matches.
*/
private static class ExactValueComparator implements Comparator<String> {
-
+
private static int compareOne(String a, String b) {
boolean aExact = a.startsWith("=");
boolean bExact = a.startsWith("=");
@@ -211,7 +213,7 @@
* @param m
* @param i
* @param params
- * @throws UnableToCompleteException
+ * @throws UnableToCompleteException
*/
public GenericSelector(TreeLogger logger, JMethod m, int i,
JParameter[] params) throws UnableToCompleteException {
@@ -268,7 +270,7 @@
}
out.println("}");
}
-
+
@Override
public void generateSelectMatchEnd(SourceWriter out, String value) {
if (!startedIfChain) {
@@ -571,7 +573,7 @@
/**
* Return the count of parameters.
- * @return the count of parameters
+ * @return the count of parameters
*/
int getCount();
@@ -595,7 +597,7 @@
* Return an expression to get the value of the requested parameter. Note
* that for arrays or lists this will return an expression giving the count
* of items in the array or list.
- *
+ *
* @param i index of the paramter, 0 .. getCount() - 1
* @return the source of code to access the parameter value
*/
@@ -673,7 +675,7 @@
return argName + "_count";
}
if (isArray[i]) {
- return argName + ".length";
+ return argName + ".length";
}
if (isList[i]) {
return argName + ".size()";
@@ -702,10 +704,10 @@
protected final PluralRule pluralRule;
private boolean hasExactMatches;
private boolean inExactMatches;
-
+
// used to generate unique case values for bogus plural forms
private int bogusCaseValue = 1000;
-
+
public PluralFormSelector(TreeLogger logger, JMethod method, int argNumber,
JParameter[] params, GwtLocale locale)
throws UnableToCompleteException {
@@ -724,7 +726,7 @@
missingPluralForms.add(form.getName());
}
}
-
+
Offset offsetAnnot = params[argNumber].getAnnotation(Offset.class);
int offset = 0;
if (offsetAnnot != null) {
@@ -798,7 +800,7 @@
out.outdent();
out.println("}");
}
-
+
@Override
public void generateSelectMatchEnd(SourceWriter out, String value) {
out.println("break;");
@@ -866,7 +868,7 @@
public PluralForm[] getPluralForms() {
return pluralRule.pluralForms();
}
-
+
@Override
public void issueWarnings(TreeLogger logger, JMethod m, GwtLocale locale) {
if (!missingPluralForms.isEmpty()) {
@@ -1049,22 +1051,22 @@
private SourceWriter writer;
+ private final ResourceOracle resourceOracle;
+
/**
* Constructor for <code>MessagesMethodCreator</code>.
- *
- * @param classCreator associated class creator
- * @param writer
*/
public MessagesMethodCreator(AbstractGeneratorClassCreator classCreator,
- SourceWriter writer) {
+ SourceWriter writer, ResourceOracle resourceOracle) {
super(classCreator);
listPatternCache = new HashMap<GwtLocale, Map<String, String>>();
this.writer = writer;
+ this.resourceOracle = resourceOracle;
}
/**
* Append an argument to the output without doing any formatting.
- *
+ *
* @param buf
* @param argExpr Java source for expression to produce argument value
* @param argType type of the argument being appended
@@ -1134,7 +1136,7 @@
}
// Generate code to format any lists
- // TODO(jat): handle messages with different list formats in alternate forms
+ // TODO(jat): handle messages with different list formats in alternate forms
try {
for (TemplateChunk chunk : MessageFormatParser.parse(template)) {
if (chunk instanceof ArgumentChunk) {
@@ -1178,7 +1180,7 @@
throw error(logger, "Error parsing '" + template + "'", pe);
}
- if (!seenPluralCount && !seenSelect
+ if (!seenPluralCount && !seenSelect
&& (m.getAnnotation(AlternateMessage.class) != null
|| m.getAnnotation(PluralText.class) != null)) {
logger.log(TreeLogger.WARN, "Unused @AlternateMessage or @PluralText on "
@@ -1194,7 +1196,7 @@
for (AlternateFormSelector selector : selectors) {
selector.generatePrepCode(writer);
}
-
+
// sort forms so that all exact-value forms come first
String[] forms = resourceForms.toArray(new String[resourceForms.size()]);
Arrays.sort(forms, new ExactValueComparator());
@@ -1432,7 +1434,7 @@
+ " 'other' values, @DefaultMessage will be used");
continue;
}
-
+
// find where the changes are
int firstDifferent = 0;
while (firstDifferent < numSelectors
@@ -1538,13 +1540,12 @@
private Map<String, String> getListPatternParts(TreeLogger logger, GwtLocale locale) {
Map<String, String> map = listPatternCache.get(locale);
if (map == null) {
- // TODO(jat): get these from ResourceOracle instead
String baseName = MessagesMethodCreator.class.getPackage().getName().replace('.', '/')
+ "/cldr/ListPatterns_";
- ClassLoader cl = MessagesMethodCreator.class.getClassLoader();
for (GwtLocale search : locale.getCompleteSearchList()) {
String propFile = baseName + search.getAsString() + ".properties";
- InputStream stream = cl.getResourceAsStream(propFile);
+ InputStream stream =
+ ResourceLocatorImpl.tryFindResourceAsStream(logger, resourceOracle, propFile);
if (stream != null) {
try {
LocalizedPropertiesLoader loader = new LocalizedPropertiesLoader(stream, "UTF-8");
diff --git a/user/src/com/google/gwt/i18n/rebind/ResourceFactory.java b/user/src/com/google/gwt/i18n/rebind/ResourceFactory.java
index df4303c..a2ba450 100644
--- a/user/src/com/google/gwt/i18n/rebind/ResourceFactory.java
+++ b/user/src/com/google/gwt/i18n/rebind/ResourceFactory.java
@@ -1,12 +1,12 @@
/*
* Copyright 2008 Google Inc.
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -21,6 +21,7 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.dev.resource.Resource;
+import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.dev.util.StringKey;
import com.google.gwt.dev.util.collect.IdentityHashSet;
import com.google.gwt.i18n.client.LocalizableResource.DefaultLocale;
@@ -71,21 +72,9 @@
loaders.add(new LocalizedPropertiesResource.Factory());
}
- /**
- *
- * @param logger
- * @param topClass
- * @param bundleLocale
- * @param isConstants
- * @param resourceMap a map of available {@link Resource Resources} by partial
- * path; obtain this by calling
- * {@link com.google.gwt.core.ext.GeneratorContext#getResourcesOracle()}.{@link com.google.gwt.dev.resource.ResourceOracle#getResourceMap() getResourceMap()}
- * @param genCtx
- * @return resource list
- */
public static synchronized ResourceList getBundle(TreeLogger logger,
JClassType topClass, GwtLocale bundleLocale, boolean isConstants,
- Map<String, Resource> resourceMap, GeneratorContext genCtx) {
+ GeneratorContext genCtx) {
List<GwtLocale> locales = bundleLocale.getCompleteSearchList();
List<JClassType> classes = new ArrayList<JClassType>();
Set<JClassType> seenClasses = new IdentityHashSet<JClassType>();
@@ -105,7 +94,7 @@
resources = localizableCtx.getResourceList(key);
if (resources == null) {
resources = new ResourceList();
- addFileResources(logger, clazz, locale, resourceMap, resources);
+ addFileResources(logger, clazz, locale, genCtx.getResourcesOracle(), resources);
AnnotationsResource annotationsResource = annotations.get(key);
if (annotationsResource != null) {
resources.add(annotationsResource);
@@ -135,7 +124,7 @@
}
private static void addFileResources(TreeLogger logger, JClassType clazz, GwtLocale locale,
- Map<String, Resource> resourceMap, ResourceList resources) {
+ ResourceOracle resourceOracle, ResourceList resources) {
// TODO: handle classes in the default package?
String targetPath = clazz.getPackage().getName() + '.'
+ getResourceName(clazz);
@@ -149,12 +138,12 @@
ResourceFactory element = loaders.get(i);
String ext = "." + element.getExt();
String path = partialPath + ext;
- Resource resource = resourceMap.get(path);
+ Resource resource = resourceOracle.getResource(path);
if (resource == null && partialPath.contains("$")) {
// Also look for A_B for inner classes, as $ in path names
// can cause issues for some build tools.
path = partialPath.replace('$', '_') + ext;
- resource = resourceMap.get(path);
+ resource = resourceOracle.getResource(path);
}
if (resource != null) {
InputStream resourceStream = null;
diff --git a/user/src/com/google/gwt/resources/ext/ResourceGeneratorUtil.java b/user/src/com/google/gwt/resources/ext/ResourceGeneratorUtil.java
index 58a5803..94a3866 100644
--- a/user/src/com/google/gwt/resources/ext/ResourceGeneratorUtil.java
+++ b/user/src/com/google/gwt/resources/ext/ResourceGeneratorUtil.java
@@ -22,13 +22,13 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.impl.ResourceGeneratorUtilImpl;
+import com.google.gwt.core.ext.impl.ResourceLocatorImpl;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JPackage;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
-import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.resources.client.ClientBundle.Source;
@@ -40,22 +40,28 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Map;
/**
* Utility methods for building ResourceGenerators.
*/
public final class ResourceGeneratorUtil {
- private static class ClassLoaderLocator implements Locator {
- private final ClassLoader classLoader;
+ /**
+ * A locator that uses ResourceLocatorImpl to locate resources either in the ResourceOracle or the
+ * ClassLoader.
+ */
+ private static class GeneralLocator implements Locator {
+ private final ResourceOracle resourceOracle;
+ private final TreeLogger logger;
- public ClassLoaderLocator(ClassLoader classLoader) {
- this.classLoader = classLoader;
+ public GeneralLocator(TreeLogger logger, ResourceOracle resourceOracle) {
+ this.logger = logger;
+ this.resourceOracle = resourceOracle;
}
+ @Override
public URL locate(String resourceName) {
- return classLoader.getResource(resourceName);
+ return ResourceLocatorImpl.tryFindResourceUrl(logger, resourceOracle, resourceName);
}
}
@@ -69,6 +75,7 @@
private NamedFileLocator() {
}
+ @Override
public URL locate(String resourceName) {
File f = ResourceGeneratorUtilImpl.getGeneratedFile(resourceName);
if (f != null && f.isFile() && f.canRead()) {
@@ -90,20 +97,6 @@
URL locate(String resourceName);
}
- private static class ResourceOracleLocator implements Locator {
- private final Map<String, Resource> resourceMap;
-
- public ResourceOracleLocator(ResourceOracle oracle) {
- resourceMap = oracle.getResourceMap();
- }
-
- @SuppressWarnings("deprecation")
- public URL locate(String resourceName) {
- Resource r = resourceMap.get(resourceName);
- return (r == null) ? null : r.getURL();
- }
- }
-
/**
* These are type names from previous APIs or from APIs with similar
* functionality that might be confusing.
@@ -185,41 +178,6 @@
* property and will attempt to use a best-match lookup by removing locale
* components.
* <p>
- * Loading through a ClassLoader with this method is much slower than the
- * other <code>findResources</code> methods which make use of the compiler's
- * ResourceOracle.
- *
- * @param logger a TreeLogger that will be used to report errors or warnings
- * @param context the ResourceContext in which the ResourceGenerator is
- * operating
- * @param classLoader the ClassLoader to use when locating resources
- * @param method the method to examine for {@link Source} annotations
- * @param defaultSuffixes if the supplied method does not have any
- * {@link Source} annotations, act as though a Source annotation was
- * specified, using the name of the method and each of supplied
- * extensions in the order in which they are specified
- * @return URLs for each {@link Source} annotation value defined on the
- * method.
- * @throws UnableToCompleteException if ore or more of the sources could not
- * be found. The error will be reported via the <code>logger</code>
- * provided to this method
- */
- public static URL[] findResources(TreeLogger logger, ClassLoader classLoader,
- ResourceContext context, JMethod method, String[] defaultSuffixes)
- throws UnableToCompleteException {
- return findResources(logger, new Locator[] {new ClassLoaderLocator(
- classLoader)}, context, method, defaultSuffixes);
- }
-
- /**
- * Find all resources referenced by a method in a bundle. The method's
- * {@link Source} annotation will be examined and the specified locations will
- * be expanded into URLs by which they may be accessed on the local system.
- * <p>
- * This method is sensitive to the <code>locale</code> deferred-binding
- * property and will attempt to use a best-match lookup by removing locale
- * components.
- * <p>
* The compiler's ResourceOracle will be used to resolve resource locations.
* If the desired resource cannot be found in the ResourceOracle, this method
* will fall back to using the current thread's context ClassLoader. If it is
@@ -286,7 +244,7 @@
public static URL[] findResources(TreeLogger logger, ResourceContext context,
JMethod method, String[] defaultSuffixes)
throws UnableToCompleteException {
- Locator[] locators = getDefaultLocators(context.getGeneratorContext());
+ Locator[] locators = getDefaultLocators(logger, context.getGeneratorContext());
URL[] toReturn = findResources(logger, locators, context, method,
defaultSuffixes);
return toReturn;
@@ -402,7 +360,7 @@
/**
* Try to find a resource with the given resourceName. It will use the default
* search order to locate the resource as is used by {@link #findResources}.
- *
+ *
* @param logger
* @param genContext
* @param resourceContext
@@ -413,7 +371,7 @@
GeneratorContext genContext, ResourceContext resourceContext,
String resourceName) {
String locale = getLocale(logger, genContext);
- Locator[] locators = getDefaultLocators(genContext);
+ Locator[] locators = getDefaultLocators(logger, genContext);
for (Locator locator : locators) {
URL toReturn = tryFindResource(locator, resourceContext, resourceName,
locale);
@@ -426,7 +384,7 @@
/**
* Add the type dependency requirements for a method, to the context.
- *
+ *
* @param context
* @param method
*/
@@ -548,22 +506,17 @@
/**
* Get default list of resource Locators, in the default order.
- *
- * @param genContext
+ *
* @return an ordered array of Locator[]
*/
- private static Locator[] getDefaultLocators(GeneratorContext genContext) {
- Locator[] locators = {
- NamedFileLocator.INSTANCE,
- new ResourceOracleLocator(genContext.getResourcesOracle()),
- new ClassLoaderLocator(Thread.currentThread().getContextClassLoader())};
-
- return locators;
+ private static Locator[] getDefaultLocators(TreeLogger logger, GeneratorContext genContext) {
+ return new Locator[] {
+ NamedFileLocator.INSTANCE, new GeneralLocator(logger, genContext.getResourcesOracle())};
}
/**
* Get the current locale string.
- *
+ *
* @param logger
* @param genContext
* @return the current locale
@@ -579,7 +532,7 @@
}
return locale;
}
-
+
/**
* Converts a package relative path into an absolute path.
*
diff --git a/user/src/com/google/gwt/uibinder/rebind/GwtResourceEntityResolver.java b/user/src/com/google/gwt/uibinder/rebind/GwtResourceEntityResolver.java
index 4cb43b7..a42dbb5 100644
--- a/user/src/com/google/gwt/uibinder/rebind/GwtResourceEntityResolver.java
+++ b/user/src/com/google/gwt/uibinder/rebind/GwtResourceEntityResolver.java
@@ -1,12 +1,12 @@
/*
* Copyright 2009 Google Inc.
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -28,7 +28,6 @@
import java.io.InputStream;
import java.io.StringReader;
import java.util.Collections;
-import java.util.Map;
import java.util.Set;
/**
@@ -51,7 +50,7 @@
private final ResourceOracle resourceOracle;
private final TreeLogger logger;
-
+
public GwtResourceEntityResolver(TreeLogger logger, ResourceOracle resourceOracle,
String pathBase) {
this.logger = logger;
@@ -64,14 +63,13 @@
String matchingPrefix = findMatchingPrefix(systemId);
Resource resource = null;
- Map<String, Resource> map = resourceOracle.getResourceMap();
if (matchingPrefix != null) {
- resource = map.get(RESOURCES
- + systemId.substring(matchingPrefix.length()));
+ resource =
+ resourceOracle.getResource(RESOURCES + systemId.substring(matchingPrefix.length()));
}
if (resource == null) {
- resource = map.get(pathBase + systemId);
+ resource = resourceOracle.getResource(pathBase + systemId);
}
if (resource != null) {
diff --git a/user/src/com/google/gwt/uibinder/rebind/UiBinderGenerator.java b/user/src/com/google/gwt/uibinder/rebind/UiBinderGenerator.java
index 6b65750..56e145c5 100644
--- a/user/src/com/google/gwt/uibinder/rebind/UiBinderGenerator.java
+++ b/user/src/com/google/gwt/uibinder/rebind/UiBinderGenerator.java
@@ -102,7 +102,6 @@
public String generate(TreeLogger logger, GeneratorContext genCtx,
String fqInterfaceName) throws UnableToCompleteException {
TypeOracle oracle = genCtx.getTypeOracle();
- ResourceOracle resourceOracle = genCtx.getResourcesOracle();
JClassType interfaceType;
try {
@@ -128,7 +127,7 @@
if (printWriter != null) {
generateOnce(interfaceType, implName, printWriter, logger, oracle,
- resourceOracle, genCtx.getPropertyOracle(), writers, designTime);
+ genCtx.getResourcesOracle(), genCtx.getPropertyOracle(), writers, designTime);
}
return packageName + "." + implName;
}
@@ -156,7 +155,7 @@
private void generateOnce(JClassType interfaceType, String implName,
PrintWriter binderPrintWriter, TreeLogger treeLogger, TypeOracle oracle,
ResourceOracle resourceOracle, PropertyOracle propertyOracle,
- PrintWriterManager writerManager, DesignTimeUtils designTime)
+ PrintWriterManager writerManager, DesignTimeUtils designTime)
throws UnableToCompleteException {
MortalLogger logger = new MortalLogger(treeLogger);
@@ -168,9 +167,10 @@
useLazyWidgetBuilders(logger, propertyOracle) && !designTime.isDesignTime();
FieldManager fieldManager = new FieldManager(oracle, logger, useLazyWidgetBuilders);
- UiBinderWriter uiBinderWriter = new UiBinderWriter(interfaceType, implName,
- templatePath, oracle, logger, fieldManager, messages, designTime, uiBinderCtx,
- useSafeHtmlTemplates(logger, propertyOracle), useLazyWidgetBuilders, BINDER_URI);
+ UiBinderWriter uiBinderWriter = new UiBinderWriter(interfaceType, implName, templatePath,
+ oracle, logger, fieldManager, messages, designTime, uiBinderCtx,
+ useSafeHtmlTemplates(logger, propertyOracle), useLazyWidgetBuilders, BINDER_URI,
+ resourceOracle);
Document doc = getW3cDoc(logger, designTime, resourceOracle, templatePath);
designTime.rememberPathForElements(doc);
@@ -191,7 +191,7 @@
ResourceOracle resourceOracle, String templatePath)
throws UnableToCompleteException {
- Resource resource = resourceOracle.getResourceMap().get(templatePath);
+ Resource resource = resourceOracle.getResource(templatePath);
if (null == resource) {
logger.die("Unable to find resource: " + templatePath);
}
diff --git a/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java b/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java
index d6dde8b..c1cd78b 100644
--- a/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java
+++ b/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java
@@ -1,12 +1,12 @@
/*
* Copyright 2009 Google Inc.
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -24,6 +24,7 @@
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.core.shared.impl.StringCase;
+import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.DataResource;
import com.google.gwt.resources.client.ImageResource;
@@ -109,10 +110,11 @@
private final JClassType dataResourceType;
private final String binderUri;
private final UiBinderContext uiBinderContext;
+ private final ResourceOracle resourceOracle;
public UiBinderParser(UiBinderWriter writer, MessagesWriter messagesWriter,
- FieldManager fieldManager, TypeOracle oracle,
- ImplicitClientBundle bundleClass, String binderUri, UiBinderContext uiBinderContext) {
+ FieldManager fieldManager, TypeOracle oracle, ImplicitClientBundle bundleClass,
+ String binderUri, UiBinderContext uiBinderContext, ResourceOracle resourceOracle) {
this.writer = writer;
this.oracle = oracle;
this.messagesWriter = messagesWriter;
@@ -123,6 +125,7 @@
this.imageResourceType = oracle.findType(ImageResource.class.getCanonicalName());
this.dataResourceType = oracle.findType(DataResource.class.getCanonicalName());
this.binderUri = binderUri;
+ this.resourceOracle = resourceOracle;
}
/**
@@ -325,7 +328,7 @@
writer.die(elem, "Could not infer type for field %s.", resourceName);
}
- // process ui:attributes child for property setting
+ // process ui:attributes child for property setting
boolean attributesChildFound = false;
// Use consumeChildElements(Interpreter) so no assertEmpty check is performed
for (XMLElement child : elem.consumeChildElements(new SimpleInterpeter<Boolean>(true))) {
@@ -443,7 +446,7 @@
}
ImplicitCssResource cssMethod = bundleClass.createCssResource(name, source,
- publicType, body, importTypes);
+ publicType, body, importTypes, resourceOracle);
FieldWriter field = fieldManager.registerFieldForGeneratedCssResource(cssMethod);
field.setInitializer(String.format("%s.%s()",
diff --git a/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java b/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
index 41414dd..63ce39c 100644
--- a/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
+++ b/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
@@ -25,6 +25,7 @@
import com.google.gwt.core.ext.typeinfo.JTypeParameter;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.core.shared.impl.StringCase;
+import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.TagName;
import com.google.gwt.event.dom.client.DomEvent;
@@ -358,11 +359,13 @@
private final String binderUri;
private final boolean isRenderer;
+ private final ResourceOracle resourceOracle;
+
public UiBinderWriter(JClassType baseClass, String implClassName, String templatePath,
TypeOracle oracle, MortalLogger logger, FieldManager fieldManager,
MessagesWriter messagesWriter, DesignTimeUtils designTime, UiBinderContext uiBinderCtx,
- boolean useSafeHtmlTemplates, boolean useLazyWidgetBuilders, String binderUri)
- throws UnableToCompleteException {
+ boolean useSafeHtmlTemplates, boolean useLazyWidgetBuilders, String binderUri,
+ ResourceOracle resourceOracle) throws UnableToCompleteException {
this.baseClass = baseClass;
this.implClassName = implClassName;
this.oracle = oracle;
@@ -375,6 +378,7 @@
this.useSafeHtmlTemplates = useSafeHtmlTemplates;
this.useLazyWidgetBuilders = useLazyWidgetBuilders;
this.binderUri = binderUri;
+ this.resourceOracle = resourceOracle;
this.htmlTemplates = new HtmlTemplatesWriter(fieldManager, logger);
@@ -1360,7 +1364,7 @@
// Allow GWT.create() to init the field, the default behavior
FieldWriter rootField = new UiBinderParser(this, messages, fieldManager, oracle, bundleClass,
- binderUri, uiBinderCtx).parse(elem);
+ binderUri, uiBinderCtx, resourceOracle).parse(elem);
fieldManager.validate();
diff --git a/user/src/com/google/gwt/uibinder/rebind/model/ImplicitClientBundle.java b/user/src/com/google/gwt/uibinder/rebind/model/ImplicitClientBundle.java
index a619512..3e98c33 100644
--- a/user/src/com/google/gwt/uibinder/rebind/model/ImplicitClientBundle.java
+++ b/user/src/com/google/gwt/uibinder/rebind/model/ImplicitClientBundle.java
@@ -1,12 +1,12 @@
/*
* Copyright 2009 Google Inc.
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -16,6 +16,7 @@
package com.google.gwt.uibinder.rebind.model;
import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.resources.client.ImageResource.RepeatStyle;
import com.google.gwt.uibinder.rebind.MortalLogger;
@@ -54,7 +55,7 @@
/**
* Called to declare a new CssResource accessor on this bundle.
- *
+ *
* @param name the method name and the ui:field name
* @param source path to the .css file resource
* @param extendedInterface the public interface implemented by this
@@ -62,12 +63,14 @@
* @param body the inline css text
* @param importTypes for the {@literal @}Import annotation, if any. LinkedHashSet
* to enforce deterministic order across recompiles
- * @return the newly-created CssResource
+ * @param resourceOracle from which to load resources
+ * @return the newly-created CssResource
*/
public ImplicitCssResource createCssResource(String name, String[] source,
- JClassType extendedInterface, String body, LinkedHashSet<JClassType> importTypes) {
- ImplicitCssResource css = new ImplicitCssResource(packageName, cssBaseName
- + name, name, source, extendedInterface, body, logger, importTypes);
+ JClassType extendedInterface, String body, LinkedHashSet<JClassType> importTypes,
+ ResourceOracle resourceOracle) {
+ ImplicitCssResource css = new ImplicitCssResource(packageName, cssBaseName + name, name, source,
+ extendedInterface, body, logger, importTypes, resourceOracle);
cssMethods.add(css);
return css;
}
@@ -75,7 +78,7 @@
/**
* Called to declare a new DataResource accessor on this bundle. All params
* must be non-null
- *
+ *
* @param name the method name and the ui:field name
* @param source path to the resource
* @return the newly-created DataResource
@@ -88,7 +91,7 @@
/**
* Called to declare a new ImageResource accessor on this bundle.
- *
+ *
* @param name the method name and the ui:field name
* @param source path to the image resource, or null if none was specified
* @param flipRtl value for the flipRtl ImageOption, or null if none was
diff --git a/user/src/com/google/gwt/uibinder/rebind/model/ImplicitCssResource.java b/user/src/com/google/gwt/uibinder/rebind/model/ImplicitCssResource.java
index 7431ac8..e3012ec 100644
--- a/user/src/com/google/gwt/uibinder/rebind/model/ImplicitCssResource.java
+++ b/user/src/com/google/gwt/uibinder/rebind/model/ImplicitCssResource.java
@@ -16,7 +16,9 @@
package com.google.gwt.uibinder.rebind.model;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.impl.ResourceLocatorImpl;
import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.resources.css.ExtractClassNamesVisitor;
import com.google.gwt.resources.css.GenerateCssAst;
import com.google.gwt.resources.css.ast.CssStylesheet;
@@ -52,6 +54,7 @@
private final String body;
private final MortalLogger logger;
private final Set<JClassType> imports;
+ private final ResourceOracle resourceOracle;
private File generatedFile;
private Set<String> cssClassNames;
@@ -62,7 +65,7 @@
*/
public ImplicitCssResource(String packageName, String className, String name,
String[] source, JClassType extendedInterface, String body,
- MortalLogger logger, Set<JClassType> importTypes) {
+ MortalLogger logger, Set<JClassType> importTypes, ResourceOracle resourceOracle) {
this.packageName = packageName;
this.className = className;
this.name = name;
@@ -70,6 +73,7 @@
this.body = body;
this.logger = logger;
this.imports = Collections.unmodifiableSet(importTypes);
+ this.resourceOracle = resourceOracle;
sources = Arrays.asList(source);
}
@@ -190,7 +194,6 @@
* this package
*/
- ClassLoader classLoader = ImplicitCssResource.class.getClassLoader();
String path = packageName.replace(".", "/");
List<URL> urls = new ArrayList<URL>();
@@ -198,13 +201,14 @@
for (String s : sources) {
String resourcePath = path + '/' + s;
// Try to find the resource relative to the package.
- URL found = classLoader.getResource(resourcePath);
+ URL found = ResourceLocatorImpl.tryFindResourceUrl(logger.getTreeLogger(), resourceOracle,
+ resourcePath);
/*
* If we didn't find the resource relative to the package, assume it
* is absolute.
*/
if (found == null) {
- found = classLoader.getResource(s);
+ found = ResourceLocatorImpl.tryFindResourceUrl(logger.getTreeLogger(), resourceOracle, s);
}
if (found == null) {
logger.die("Unable to find resource: " + resourcePath);
diff --git a/user/src/com/google/gwt/user/rebind/ui/ImageBundleGenerator.java b/user/src/com/google/gwt/user/rebind/ui/ImageBundleGenerator.java
index 710a3c9..d65351f 100644
--- a/user/src/com/google/gwt/user/rebind/ui/ImageBundleGenerator.java
+++ b/user/src/com/google/gwt/user/rebind/ui/ImageBundleGenerator.java
@@ -20,17 +20,18 @@
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.impl.ResourceLocatorImpl;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
+import com.google.gwt.thirdparty.guava.common.annotations.VisibleForTesting;
import com.google.gwt.user.client.ui.ImageBundle;
import com.google.gwt.user.client.ui.ImageBundle.Resource;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
import java.io.PrintWriter;
-import java.net.URL;
import java.util.ArrayList;
import java.util.List;
@@ -66,7 +67,8 @@
* Indirection around the act of looking up a resource that allows for unit
* test mocking.
*/
- /* private */interface ResourceLocator {
+ @VisibleForTesting
+ interface ResourceLocator {
/**
*
* @param resName the resource name in a format that could be passed to
@@ -83,21 +85,26 @@
this.delegate = delegate;
}
+ @Override
@SuppressWarnings("deprecation")
public Resource getAnnotation(Class<Resource> clazz) {
return delegate.getAnnotation(clazz);
}
+ @Override
public String getName() {
return delegate.getName();
}
+ @Override
public String getPackageName() {
return delegate.getEnclosingType().getPackage().getName();
}
}
- /* private */static final String MSG_NO_FILE_BASED_ON_METHOD_NAME = "No matching image resource was found; any of the following filenames would have matched had they been present:";
+ @VisibleForTesting
+ static final String MSG_NO_FILE_BASED_ON_METHOD_NAME = "No matching image resource was found; "
+ + "any of the following filenames would have matched had they been present:";
private static final String ABSTRACTIMAGEPROTOTYPE_QNAME = "com.google.gwt.user.client.ui.AbstractImagePrototype";
@@ -109,29 +116,36 @@
private static final String IMAGEBUNDLE_QNAME = "com.google.gwt.user.client.ui.ImageBundle";
- /* private */static String msgCannotFindImageFromMetaData(String imgResName) {
+ @VisibleForTesting
+ static String msgCannotFindImageFromMetaData(String imgResName) {
return "Unable to find image resource '" + imgResName + "'";
}
private final ResourceLocator resLocator;
+ private GeneratorContext context;
+
+ private TreeLogger logger;
+
/**
* Default constructor for image bundle. Locates resources using this class's
* own class loader.
*/
public ImageBundleGenerator() {
- this(new ResourceLocator() {
+ this.resLocator = new ResourceLocator() {
+ @Override
public boolean isResourcePresent(String resName) {
- URL url = getClass().getClassLoader().getResource(resName);
- return url != null;
+ return ResourceLocatorImpl.tryFindResourceUrl(logger, context.getResourcesOracle(), resName)
+ != null;
}
- });
+ };
}
/**
* Default access so that it can be accessed by unit tests.
*/
- /* private */ImageBundleGenerator(ResourceLocator resourceLocator) {
+ @VisibleForTesting
+ ImageBundleGenerator(ResourceLocator resourceLocator) {
assert (resourceLocator != null);
this.resLocator = resourceLocator;
}
@@ -139,6 +153,8 @@
@Override
public String generate(TreeLogger logger, GeneratorContext context,
String typeName) throws UnableToCompleteException {
+ this.logger = logger;
+ this.context = context;
TypeOracle typeOracle = context.getTypeOracle();
@@ -166,7 +182,8 @@
* @throws UnableToCompleteException thrown if a resource was specified but
* could not be found on the classpath
*/
- /* private */String getImageResourceName(TreeLogger logger,
+ @VisibleForTesting
+ String getImageResourceName(TreeLogger logger,
JMethodOracle method) throws UnableToCompleteException {
String imgName = tryGetImageNameFromMetaData(logger, method);
if (imgName != null) {
diff --git a/user/test/com/google/gwt/uibinder/elementparsers/ElementParserTester.java b/user/test/com/google/gwt/uibinder/elementparsers/ElementParserTester.java
index 37f0542..15ce2ac 100644
--- a/user/test/com/google/gwt/uibinder/elementparsers/ElementParserTester.java
+++ b/user/test/com/google/gwt/uibinder/elementparsers/ElementParserTester.java
@@ -111,7 +111,7 @@
templatePath, baseType.getPackage().getName(), implName);
writer = new MockUiBinderWriter(baseType, implName, templatePath, types,
- logger, fieldManager, messages, BINDER_URI);
+ logger, fieldManager, messages, BINDER_URI, new MockResourceOracle());
fieldManager.registerField(types.findType(parsedTypeName), FIELD_NAME);
parsedType = types.findType(parsedTypeName);
}
diff --git a/user/test/com/google/gwt/uibinder/elementparsers/MockUiBinderWriter.java b/user/test/com/google/gwt/uibinder/elementparsers/MockUiBinderWriter.java
index 8231ddd..c7b4af1 100644
--- a/user/test/com/google/gwt/uibinder/elementparsers/MockUiBinderWriter.java
+++ b/user/test/com/google/gwt/uibinder/elementparsers/MockUiBinderWriter.java
@@ -1,12 +1,12 @@
/*
* Copyright 2011 Google Inc.
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -18,6 +18,7 @@
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
+import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.uibinder.rebind.DesignTimeUtilsStub;
import com.google.gwt.uibinder.rebind.FieldManager;
import com.google.gwt.uibinder.rebind.FieldWriter;
@@ -35,9 +36,10 @@
public MockUiBinderWriter(JClassType baseClass, String implClassName, String templatePath,
TypeOracle oracle, MortalLogger logger, FieldManager fieldManager,
- MessagesWriter messagesWriter, String binderUri) throws UnableToCompleteException {
+ MessagesWriter messagesWriter, String binderUri, ResourceOracle resourceOracle)
+ throws UnableToCompleteException {
super(baseClass, implClassName, templatePath, oracle, logger, fieldManager, messagesWriter,
- DesignTimeUtilsStub.EMPTY, new UiBinderContext(), true, false, binderUri);
+ DesignTimeUtilsStub.EMPTY, new UiBinderContext(), true, false, binderUri, resourceOracle);
}
@Override
diff --git a/user/test/com/google/gwt/uibinder/rebind/AbstractUiBinderWriterTest.java b/user/test/com/google/gwt/uibinder/rebind/AbstractUiBinderWriterTest.java
index 29863fb..bc825b0 100644
--- a/user/test/com/google/gwt/uibinder/rebind/AbstractUiBinderWriterTest.java
+++ b/user/test/com/google/gwt/uibinder/rebind/AbstractUiBinderWriterTest.java
@@ -24,6 +24,7 @@
import com.google.gwt.dev.javac.testing.impl.MockJavaResource;
import com.google.gwt.dev.javac.testing.impl.MockResourceOracle;
import com.google.gwt.dev.resource.Resource;
+import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.dev.util.collect.HashSet;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
import com.google.gwt.uibinder.attributeparsers.AttributeParsers;
@@ -187,10 +188,11 @@
MessagesWriter messages =
new MessagesWriter(types, BINDER_URI, logger, rendererClass.getPath(), "rendererPackage",
"rendererClassName");
- writer =
- new UiBinderWriter(aClass, "foo", "", types, logger, fieldManager, messages,
- DesignTimeUtilsStub.EMPTY, uiBinderCtx, true, true, BINDER_URI);
- parser = new UiBinderParser(writer, messages, fieldManager, types, null, BINDER_URI, new UiBinderContext());
+ ResourceOracle resourceOracle = new MockResourceOracle();
+ writer = new UiBinderWriter(aClass, "foo", "", types, logger, fieldManager, messages,
+ DesignTimeUtilsStub.EMPTY, uiBinderCtx, true, true, BINDER_URI, resourceOracle);
+ parser = new UiBinderParser(writer, messages, fieldManager, types, null, BINDER_URI,
+ new UiBinderContext(), resourceOracle);
designTime.rememberPathForElements(doc);
}
}
\ No newline at end of file
diff --git a/user/test/com/google/gwt/uibinder/rebind/FieldWriterOfGeneratedCssResourceTest.java b/user/test/com/google/gwt/uibinder/rebind/FieldWriterOfGeneratedCssResourceTest.java
index a0c8451..eae9c83 100644
--- a/user/test/com/google/gwt/uibinder/rebind/FieldWriterOfGeneratedCssResourceTest.java
+++ b/user/test/com/google/gwt/uibinder/rebind/FieldWriterOfGeneratedCssResourceTest.java
@@ -21,6 +21,7 @@
import com.google.gwt.dev.CompilerContext;
import com.google.gwt.dev.javac.CompilationState;
import com.google.gwt.dev.javac.CompilationStateBuilder;
+import com.google.gwt.dev.javac.testing.impl.MockResourceOracle;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
import com.google.gwt.uibinder.rebind.model.ImplicitCssResource;
import com.google.gwt.uibinder.test.UiJavaResources;
@@ -57,7 +58,7 @@
ImplicitCssResource css = new ImplicitCssResource("package", "ClassName",
"fieldName", new String[] {}, cssResourceType, ".able-baker {}",
- MortalLogger.NULL, Collections.<JClassType> emptySet());
+ MortalLogger.NULL, Collections.<JClassType> emptySet(), new MockResourceOracle());
FieldWriterOfGeneratedCssResource f = new FieldWriterOfGeneratedCssResource(
null, stringType, css, MortalLogger.NULL);
@@ -73,7 +74,7 @@
ImplicitCssResource css = new ImplicitCssResource("package", "ClassName",
"fieldName", new String[] {}, cssResourceType, ".ableBaker {}",
- MortalLogger.NULL, Collections.<JClassType> emptySet());
+ MortalLogger.NULL, Collections.<JClassType> emptySet(), new MockResourceOracle());
FieldWriterOfGeneratedCssResource f = new FieldWriterOfGeneratedCssResource(
null, stringType, css, MortalLogger.NULL);
diff --git a/user/test/com/google/gwt/uibinder/rebind/UiBinderParserUiWithTest.java b/user/test/com/google/gwt/uibinder/rebind/UiBinderParserUiWithTest.java
index fd5d1ca..5359210 100644
--- a/user/test/com/google/gwt/uibinder/rebind/UiBinderParserUiWithTest.java
+++ b/user/test/com/google/gwt/uibinder/rebind/UiBinderParserUiWithTest.java
@@ -23,6 +23,7 @@
import com.google.gwt.dev.javac.testing.impl.MockJavaResource;
import com.google.gwt.dev.javac.testing.impl.MockResourceOracle;
import com.google.gwt.dev.resource.Resource;
+import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.dev.util.collect.HashSet;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
import com.google.gwt.uibinder.attributeparsers.AttributeParsers;
@@ -275,10 +276,11 @@
item = (Element) doc.getDocumentElement().getElementsByTagName("with").item(0);
elm = elemProvider.get(item);
JClassType aClass = types.findType(baseClass);
- writer =
- new UiBinderWriter(aClass, "foo", "", types, logger, fieldManager, null,
- DesignTimeUtilsStub.EMPTY, new UiBinderContext(), true, true, "");
- parser = new UiBinderParser(writer, null, fieldManager, types, null, "", new UiBinderContext());
+ ResourceOracle resourceOracle = new MockResourceOracle();
+ writer = new UiBinderWriter(aClass, "foo", "", types, logger, fieldManager, null,
+ DesignTimeUtilsStub.EMPTY, new UiBinderContext(), true, true, "", resourceOracle);
+ parser = new UiBinderParser(writer, null, fieldManager, types, null, "", new UiBinderContext(),
+ resourceOracle);
designTime.rememberPathForElements(doc);
UiBinderParser.Resource.WITH.create(parser, elm);
}