Adds intelligent rerun metadata to generators.
This is metadata (related property names and property/type output
instability) that can be used to determine when and on what scope
of input to run a particular generator during separate compilation.
Without this metadata the only safe way to run generators would
be to defer all of them to a global pass at the end of separate
compilation, which would eliminate any generator result caching and
generator execution parallelism.
As a result, having and using this generator metadata is an
important part of making separate compilation fast.
Change-Id: I763a02a41a5abfd522852b0ad29e200548316c6f
Review-Link: https://gwt-review.googlesource.com/#/c/5243/
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 524dddb..05b408b 100644
--- a/dev/core/src/com/google/gwt/core/ext/Generator.java
+++ b/dev/core/src/com/google/gwt/core/ext/Generator.java
@@ -1,31 +1,35 @@
/*
* Copyright 2006 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
- *
+ *
+ * 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
+ *
+ * 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;
+import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
+
/**
- * Generates source code for subclasses during deferred binding requests.
- * Subclasses must be thread-safe.
+ * Generates source code for subclasses during deferred binding requests. Subclasses must be
+ * thread-safe.<br />
+ *
+ * Well-behaved generators can speed up the separate compiles by overriding @{link
+ * #getAccessedPropertyNames}, @{link #contentDependsOnProperties}, and @{contentDependsOnTypes}".
+ * The compiler will use this information to run generators less often and cache their outputs.
*/
public abstract class Generator {
/**
* Escapes string content to be a valid string literal.
- *
- * @return an escaped version of <code>unescaped</code>, suitable for being
- * enclosed in double quotes in Java source
+ *
+ * @return an escaped version of <code>unescaped</code>, suitable for being enclosed in double
+ * quotes in Java source
*/
public static String escape(String unescaped) {
int extra = 0;
@@ -78,15 +82,45 @@
}
/**
- * Generate a default constructible subclass of the requested type. The
- * generator throws <code>UnableToCompleteException</code> if for any reason
- * it cannot provide a substitute class
- *
- * @return the name of a subclass to substitute for the requested class, or
- * return <code>null</code> to cause the requested type itself to be
- * used
- *
+ * Generate a default constructible subclass of the requested type. The generator throws
+ * <code>UnableToCompleteException</code> if for any reason it cannot provide a substitute class
+ *
+ * @return the name of a subclass to substitute for the requested class, or return
+ * <code>null</code> to cause the requested type itself to be used
*/
- public abstract String generate(TreeLogger logger, GeneratorContext context,
- String typeName) throws UnableToCompleteException;
+ public abstract String generate(TreeLogger logger, GeneratorContext context, String typeName)
+ throws UnableToCompleteException;
+
+ /**
+ * Returns the set of names of all properties that are accessed by generator execution and affect
+ * its behavior. Returning a null indicates that *all* properties are considered relevant.<br />
+ *
+ * Generators that don't need access to every property can override this method to speed up
+ * separate compiles.
+ */
+ public ImmutableSet<String> getAccessedPropertyNames() {
+ return null;
+ }
+
+ /**
+ * Whether the *content* of created files (not the list of files created) changes as the set value
+ * of configuration properties or the list of legal values of binding properties changes.<br />
+ *
+ * Generators whose output content is stable even when property values change can override this
+ * method to speed up separate compiles.
+ */
+ public boolean contentDependsOnProperties() {
+ return true;
+ }
+
+ /**
+ * Whether the *content* of created files (not the list of files created) changes as more types
+ * are created that match some subtype query.<br />
+ *
+ * Generators whose output content is stable even as new types are created can override this
+ * method to speed up separate compiles.
+ */
+ public boolean contentDependsOnTypes() {
+ return true;
+ }
}
diff --git a/dev/core/src/com/google/gwt/core/ext/SubsetFilteringPropertyOracle.java b/dev/core/src/com/google/gwt/core/ext/SubsetFilteringPropertyOracle.java
new file mode 100644
index 0000000..6d95c4b
--- /dev/null
+++ b/dev/core/src/com/google/gwt/core/ext/SubsetFilteringPropertyOracle.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2013 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;
+
+import com.google.gwt.thirdparty.guava.common.base.Preconditions;
+
+import java.util.Set;
+
+/**
+ * A property oracle that prevents access to any properties not named in its predefined set.<br />
+ *
+ * Used by the generator driver framework to limit property access for the purpose of
+ * forcing generators to accurately declare their property dependencies.
+ */
+public class SubsetFilteringPropertyOracle implements PropertyOracle {
+
+ private final Set<String> accessiblePropertyNames;
+ private final String accessViolationMessage;
+ private final PropertyOracle wrappedPropertyOracle;
+
+ public SubsetFilteringPropertyOracle(Set<String> accessiblePropertyNames,
+ PropertyOracle wrappedPropertyOracle, String accessViolationMessage) {
+ this.accessiblePropertyNames = accessiblePropertyNames;
+ this.wrappedPropertyOracle = wrappedPropertyOracle;
+ this.accessViolationMessage = accessViolationMessage;
+ }
+
+ @Override
+ public ConfigurationProperty getConfigurationProperty(String propertyName)
+ throws BadPropertyValueException {
+ Preconditions.checkState(
+ accessiblePropertyNames == null || accessiblePropertyNames.contains(propertyName),
+ "Access to configuration property '" + propertyName + "' is not allowed. "
+ + accessViolationMessage);
+ return wrappedPropertyOracle.getConfigurationProperty(propertyName);
+ }
+
+ @Override
+ public SelectionProperty getSelectionProperty(TreeLogger logger, String propertyName)
+ throws BadPropertyValueException {
+ Preconditions.checkState(
+ accessiblePropertyNames == null || accessiblePropertyNames.contains(propertyName),
+ "Access to binding property '" + propertyName + "' is not allowed. "
+ + accessViolationMessage);
+ return wrappedPropertyOracle.getSelectionProperty(logger, propertyName);
+ }
+}
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 18d0b91..65cbde2 100644
--- a/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java
+++ b/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java
@@ -22,6 +22,7 @@
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.RebindResult;
import com.google.gwt.core.ext.RebindRuleResolver;
+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.linker.Artifact;
@@ -292,7 +293,7 @@
private final Map<String, PendingResource> pendingResources =
new HashMap<String, PendingResource>();
- private transient PropertyOracle propOracle;
+ private transient PropertyOracle propertyOracle;
private RebindRuleResolver rebindRuleResolver;
@@ -561,7 +562,7 @@
@Override
public final PropertyOracle getPropertyOracle() {
- return propOracle;
+ return propertyOracle;
}
@Override
@@ -648,8 +649,15 @@
Event generatorEvent =
SpeedTracerLogger.start(type, "class", generatorClassName, "type", typeName);
+ PropertyOracle originalPropertyOracle = propertyOracle;
try {
RebindResult result;
+ // TODO(stalcup): refactor the Generator/PropertyOracle system (in a potentially backwards
+ // incompatible way) so that all Generators are forced to accurately declare the names of
+ // properties they care about.
+ propertyOracle = new SubsetFilteringPropertyOracle(
+ generator.getAccessedPropertyNames(), originalPropertyOracle,
+ generatorClassName + ".getAccessedPropertyNames() may need to be updated.");
if (generator instanceof IncrementalGenerator) {
IncrementalGenerator incGenerator = (IncrementalGenerator) generator;
@@ -694,6 +702,7 @@
+ "' threw an exception while rebinding '" + typeName + "'", e);
throw new UnableToCompleteException();
} finally {
+ propertyOracle = originalPropertyOracle;
generatorEvent.end();
}
}
@@ -717,8 +726,8 @@
* Sets the current transient property oracle to answer current property
* questions.
*/
- public void setPropertyOracle(PropertyOracle propOracle) {
- this.propOracle = propOracle;
+ public void setPropertyOracle(PropertyOracle propertyOracle) {
+ this.propertyOracle = propertyOracle;
}
public void setRebindRuleResolver(RebindRuleResolver resolver) {
diff --git a/user/src/com/google/gwt/editor/rebind/SimpleBeanEditorDriverGenerator.java b/user/src/com/google/gwt/editor/rebind/SimpleBeanEditorDriverGenerator.java
index 53f1a5e..85c4a91 100644
--- a/user/src/com/google/gwt/editor/rebind/SimpleBeanEditorDriverGenerator.java
+++ b/user/src/com/google/gwt/editor/rebind/SimpleBeanEditorDriverGenerator.java
@@ -19,6 +19,7 @@
import com.google.gwt.editor.client.impl.AbstractSimpleBeanEditorDriver;
import com.google.gwt.editor.client.impl.SimpleBeanEditorDelegate;
import com.google.gwt.editor.rebind.model.EditorData;
+import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
/**
* Generates implementations of {@link SimpleBeanEditorDriver}.
@@ -26,6 +27,23 @@
public class SimpleBeanEditorDriverGenerator extends
AbstractEditorDriverGenerator {
+ private static ImmutableSet<String> relevantPropertyNames = ImmutableSet.of();
+
+ @Override
+ public ImmutableSet<String> getAccessedPropertyNames() {
+ return relevantPropertyNames;
+ }
+
+ @Override
+ public boolean contentDependsOnProperties() {
+ return false;
+ }
+
+ @Override
+ public boolean contentDependsOnTypes() {
+ return false;
+ }
+
@Override
protected Class<?> getDriverInterfaceType() {
return SimpleBeanEditorDriver.class;
diff --git a/user/src/com/google/gwt/i18n/rebind/CurrencyListGenerator.java b/user/src/com/google/gwt/i18n/rebind/CurrencyListGenerator.java
index 214e1bb..d486ac6 100644
--- a/user/src/com/google/gwt/i18n/rebind/CurrencyListGenerator.java
+++ b/user/src/com/google/gwt/i18n/rebind/CurrencyListGenerator.java
@@ -27,6 +27,7 @@
import com.google.gwt.i18n.client.CurrencyList;
import com.google.gwt.i18n.client.impl.CurrencyDataImpl;
import com.google.gwt.i18n.shared.GwtLocale;
+import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
@@ -42,9 +43,9 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
-import java.util.Map.Entry;
import java.util.regex.Pattern;
/**
@@ -72,10 +73,10 @@
private final String portableSymbol;
- private final String symbol;
-
private String simpleSymbol;
+ private final String symbol;
+
/**
* Create an instance.
*
@@ -262,6 +263,9 @@
return str.replace("\"", "\\\"");
}
+ private static ImmutableSet<String> relevantPropertyNames =
+ ImmutableSet.of("locale.queryparam", "locale", "runtime.locales", "locale.cookie");
+
/**
* Generate an implementation for the given type.
*
@@ -298,6 +302,16 @@
runtimeLocales);
}
+ @Override
+ public ImmutableSet<String> getAccessedPropertyNames() {
+ return relevantPropertyNames;
+ }
+
+ @Override
+ public boolean contentDependsOnTypes() {
+ return false;
+ }
+
/**
* Generate an implementation class for the requested locale, including all
* parent classes along the inheritance chain. The data will be kept at the
diff --git a/user/src/com/google/gwt/i18n/rebind/CustomDateTimeFormatGenerator.java b/user/src/com/google/gwt/i18n/rebind/CustomDateTimeFormatGenerator.java
index d69f8b3..9dcea38 100644
--- a/user/src/com/google/gwt/i18n/rebind/CustomDateTimeFormatGenerator.java
+++ b/user/src/com/google/gwt/i18n/rebind/CustomDateTimeFormatGenerator.java
@@ -29,6 +29,7 @@
import com.google.gwt.i18n.shared.CustomDateTimeFormat.Pattern;
import com.google.gwt.i18n.shared.DateTimeFormat;
import com.google.gwt.i18n.shared.GwtLocale;
+import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
@@ -41,6 +42,9 @@
*/
public class CustomDateTimeFormatGenerator extends Generator {
+ private static ImmutableSet<String> relevantPropertyNames =
+ ImmutableSet.of("locale.queryparam", "locale", "runtime.locales", "locale.cookie");
+
/**
* Generate an implementation for the given type.
*
@@ -142,4 +146,14 @@
}
return packageName + "." + className;
}
+
+ @Override
+ public ImmutableSet<String> getAccessedPropertyNames() {
+ return relevantPropertyNames;
+ }
+
+ @Override
+ public boolean contentDependsOnProperties() {
+ return false;
+ }
}
diff --git a/user/src/com/google/gwt/i18n/rebind/LocaleInfoGenerator.java b/user/src/com/google/gwt/i18n/rebind/LocaleInfoGenerator.java
index a73f0e3..0efd8cb 100644
--- a/user/src/com/google/gwt/i18n/rebind/LocaleInfoGenerator.java
+++ b/user/src/com/google/gwt/i18n/rebind/LocaleInfoGenerator.java
@@ -29,6 +29,7 @@
import com.google.gwt.i18n.client.impl.LocaleInfoImpl;
import com.google.gwt.i18n.server.GwtLocaleImpl;
import com.google.gwt.i18n.shared.GwtLocale;
+import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
@@ -83,6 +84,9 @@
RTL_LOCALES.add("ur");
}
+ private static ImmutableSet<String> relevantPropertyNames =
+ ImmutableSet.of("locale.queryparam", "locale", "runtime.locales", "locale.cookie");
+
/**
* Generate an implementation for the given type.
*
@@ -313,6 +317,16 @@
return packageName + "." + className;
}
+ @Override
+ public ImmutableSet<String> getAccessedPropertyNames() {
+ return relevantPropertyNames;
+ }
+
+ @Override
+ public boolean contentDependsOnTypes() {
+ return false;
+ }
+
/**
* @param logger
* @param context
diff --git a/user/src/com/google/gwt/i18n/rebind/LocalizableGenerator.java b/user/src/com/google/gwt/i18n/rebind/LocalizableGenerator.java
index 756afd4..a0ac13b 100644
--- a/user/src/com/google/gwt/i18n/rebind/LocalizableGenerator.java
+++ b/user/src/com/google/gwt/i18n/rebind/LocalizableGenerator.java
@@ -37,6 +37,7 @@
import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.i18n.client.Messages;
import com.google.gwt.i18n.shared.GwtLocale;
+import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
import java.util.ArrayList;
import java.util.Arrays;
@@ -89,20 +90,23 @@
}
}
- /**
+ public static final String CONSTANTS_NAME = Constants.class.getName();
+
+ public static final String CONSTANTS_WITH_LOOKUP_NAME = ConstantsWithLookup.class.getName();
+
+ /**
* Obsolete comment for GWT metadata - needs to be removed once all
* references have been removed.
*/
public static final String GWT_KEY = "gwt.key";
- public static final String CONSTANTS_NAME = Constants.class.getName();
-
- public static final String CONSTANTS_WITH_LOOKUP_NAME = ConstantsWithLookup.class.getName();
-
public static final String MESSAGES_NAME = Messages.class.getName();
private LocalizableLinkageCreator linkageCreator = new LocalizableLinkageCreator();
+ private static ImmutableSet<String> relevantPropertyNames =
+ ImmutableSet.of("locale.queryparam", "locale", "runtime.locales", "locale.cookie");
+
/**
* Generate an implementation for the given type.
*
@@ -182,6 +186,21 @@
return returnedClass;
}
+ @Override
+ public ImmutableSet<String> getAccessedPropertyNames() {
+ return relevantPropertyNames;
+ }
+
+ @Override
+ public boolean contentDependsOnProperties() {
+ return false;
+ }
+
+ @Override
+ public boolean contentDependsOnTypes() {
+ return false;
+ }
+
/**
* Generate a runtime-selection implementation of the target class if needed,
* delegating all overridable methods to an instance chosen at runtime based
diff --git a/user/src/com/google/gwt/resources/rebind/context/InlineClientBundleGenerator.java b/user/src/com/google/gwt/resources/rebind/context/InlineClientBundleGenerator.java
index baa3e97..222abe7 100644
--- a/user/src/com/google/gwt/resources/rebind/context/InlineClientBundleGenerator.java
+++ b/user/src/com/google/gwt/resources/rebind/context/InlineClientBundleGenerator.java
@@ -18,6 +18,7 @@
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
/**
* This is a refinement that will use data urls for browsers that support them.
@@ -29,9 +30,25 @@
public final class InlineClientBundleGenerator extends
AbstractClientBundleGenerator {
+ private static ImmutableSet<String> relevantPropertyNames = ImmutableSet.of(
+ "CssResource.obfuscationPrefix", "user.agent", "CssResource.mergeEnabled",
+ "ClientBundle.enableInlining", "locale", "CssResource.style",
+ "CssResource.reservedClassPrefixes", "ClientBundle.enableRenaming",
+ "ExternalTextResource.useJsonp");
+
private final ClientBundleContext clientBundleCtx = new ClientBundleContext();
@Override
+ public ImmutableSet<String> getAccessedPropertyNames() {
+ return relevantPropertyNames;
+ }
+
+ @Override
+ public boolean contentDependsOnTypes() {
+ return false;
+ }
+
+ @Override
protected AbstractResourceContext createResourceContext(TreeLogger logger,
GeneratorContext context, JClassType resourceBundleType) {
return new InlineResourceContext(logger.branch(TreeLogger.DEBUG,
diff --git a/user/src/com/google/gwt/safehtml/rebind/SafeHtmlTemplatesGenerator.java b/user/src/com/google/gwt/safehtml/rebind/SafeHtmlTemplatesGenerator.java
index 1f0ec8a..1d90979 100644
--- a/user/src/com/google/gwt/safehtml/rebind/SafeHtmlTemplatesGenerator.java
+++ b/user/src/com/google/gwt/safehtml/rebind/SafeHtmlTemplatesGenerator.java
@@ -22,6 +22,7 @@
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.thirdparty.guava.common.collect.ImmutableSet;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
@@ -33,6 +34,8 @@
*/
public class SafeHtmlTemplatesGenerator extends Generator {
+ private static ImmutableSet<String> relevantPropertyNames = ImmutableSet.of();
+
@Override
public String generate(TreeLogger logger, GeneratorContext genCtx,
String fqInterfaceName) throws UnableToCompleteException {
@@ -66,4 +69,19 @@
}
return packageName + "." + implName;
}
+
+ @Override
+ public ImmutableSet<String> getAccessedPropertyNames() {
+ return relevantPropertyNames;
+ }
+
+ @Override
+ public boolean contentDependsOnProperties() {
+ return false;
+ }
+
+ @Override
+ public boolean contentDependsOnTypes() {
+ return false;
+ }
}
diff --git a/user/src/com/google/gwt/uibinder/rebind/UiBinderGenerator.java b/user/src/com/google/gwt/uibinder/rebind/UiBinderGenerator.java
index 1beb0b3..9420c9f 100644
--- a/user/src/com/google/gwt/uibinder/rebind/UiBinderGenerator.java
+++ b/user/src/com/google/gwt/uibinder/rebind/UiBinderGenerator.java
@@ -27,6 +27,7 @@
import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.dev.util.Util;
+import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
import com.google.gwt.uibinder.client.UiTemplate;
import com.google.gwt.uibinder.rebind.messages.MessagesWriter;
import com.google.gwt.uibinder.rebind.model.ImplicitClientBundle;
@@ -46,13 +47,13 @@
private static final String BINDER_URI = "urn:ui:com.google.gwt.uibinder";
- private static final String TEMPLATE_SUFFIX = ".ui.xml";
+ private static boolean gaveLazyBuildersWarning;
- private static final String XSS_SAFE_CONFIG_PROPERTY = "UiBinder.useSafeHtmlTemplates";
+ private static boolean gaveSafeHtmlWarning;
private static final String LAZY_WIDGET_BUILDERS_PROPERTY = "UiBinder.useLazyWidgetBuilders";
- private static boolean gaveSafeHtmlWarning;
- private static boolean gaveLazyBuildersWarning;
+ private static final String TEMPLATE_SUFFIX = ".ui.xml";
+ private static final String XSS_SAFE_CONFIG_PROPERTY = "UiBinder.useSafeHtmlTemplates";
/**
* Given a UiBinder interface, return the path to its ui.xml file, suitable
@@ -95,6 +96,9 @@
return s.replace(".", "/").replace("$", ".");
}
+ private static ImmutableSet<String> relevantPropertyNames =
+ ImmutableSet.of("UiBinder.useSafeHtmlTemplates", "UiBinder.useLazyWidgetBuilders");
+
private final UiBinderContext uiBinderCtx = new UiBinderContext();
@Override
@@ -132,6 +136,16 @@
return packageName + "." + implName;
}
+ @Override
+ public ImmutableSet<String> getAccessedPropertyNames() {
+ return relevantPropertyNames;
+ }
+
+ @Override
+ public boolean contentDependsOnTypes() {
+ return false;
+ }
+
private Boolean extractConfigProperty(MortalLogger logger,
PropertyOracle propertyOracle, String configProperty, boolean defaultValue) {
List<String> values;
diff --git a/user/src/com/google/gwt/user/rebind/AsyncProxyGenerator.java b/user/src/com/google/gwt/user/rebind/AsyncProxyGenerator.java
index 1ecddb4..d598ebb 100644
--- a/user/src/com/google/gwt/user/rebind/AsyncProxyGenerator.java
+++ b/user/src/com/google/gwt/user/rebind/AsyncProxyGenerator.java
@@ -28,6 +28,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.thirdparty.guava.common.collect.ImmutableSet;
import com.google.gwt.user.client.AsyncProxy;
import com.google.gwt.user.client.AsyncProxy.AllowNonVoid;
import com.google.gwt.user.client.AsyncProxy.ConcreteType;
@@ -43,6 +44,8 @@
*/
public class AsyncProxyGenerator extends Generator {
+ private static ImmutableSet<String> relevantPropertyNames = ImmutableSet.of();
+
@Override
public String generate(TreeLogger logger, GeneratorContext generatorContext,
String typeName) throws UnableToCompleteException {
@@ -208,6 +211,21 @@
return createdClassName;
}
+ @Override
+ public ImmutableSet<String> getAccessedPropertyNames() {
+ return relevantPropertyNames;
+ }
+
+ @Override
+ public boolean contentDependsOnProperties() {
+ return false;
+ }
+
+ @Override
+ public boolean contentDependsOnTypes() {
+ return false;
+ }
+
private JClassType getConcreteType(TreeLogger logger, TypeOracle typeOracle,
JClassType sourceType) throws UnableToCompleteException {
JClassType concreteType;
diff --git a/user/src/com/google/gwt/user/rebind/DocumentModeGenerator.java b/user/src/com/google/gwt/user/rebind/DocumentModeGenerator.java
index 18f58fa..4518a26 100644
--- a/user/src/com/google/gwt/user/rebind/DocumentModeGenerator.java
+++ b/user/src/com/google/gwt/user/rebind/DocumentModeGenerator.java
@@ -26,6 +26,7 @@
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.thirdparty.guava.common.collect.ImmutableSet;
import com.google.gwt.user.client.DocumentModeAsserter;
import com.google.gwt.user.client.DocumentModeAsserter.Severity;
@@ -38,6 +39,9 @@
*/
public class DocumentModeGenerator extends Generator {
+ private static ImmutableSet<String> relevantPropertyNames =
+ ImmutableSet.of("document.compatMode", "document.compatMode.severity");
+
@Override
public String generate(TreeLogger logger, GeneratorContext context, String typeName)
throws UnableToCompleteException {
@@ -126,4 +130,14 @@
}
return composerFactory.getCreatedClassName();
}
+
+ @Override
+ public ImmutableSet<String> getAccessedPropertyNames() {
+ return relevantPropertyNames;
+ }
+
+ @Override
+ public boolean contentDependsOnTypes() {
+ return false;
+ }
}
diff --git a/user/src/com/google/gwt/user/rebind/rpc/ServiceInterfaceProxyGenerator.java b/user/src/com/google/gwt/user/rebind/rpc/ServiceInterfaceProxyGenerator.java
index 2e9026a..a5a32de 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/ServiceInterfaceProxyGenerator.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/ServiceInterfaceProxyGenerator.java
@@ -22,6 +22,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.thirdparty.guava.common.collect.ImmutableSet;
/**
* Generator for producing the asynchronous version of a
@@ -38,6 +39,10 @@
*/
private static final long GENERATOR_VERSION_ID = 1L;
+ private static ImmutableSet<String> relevantPropertyNames = ImmutableSet.of(
+ "gwt.elideTypeNamesFromRPC", "rpc.enhancedClasses", "gwt.suppressNonStaticFinalFieldWarnings",
+ "rpc.blacklist");
+
@Override
public RebindResult generateIncrementally(TreeLogger logger, GeneratorContext ctx,
String requestedClass) throws UnableToCompleteException {
@@ -68,6 +73,11 @@
}
@Override
+ public ImmutableSet<String> getAccessedPropertyNames() {
+ return relevantPropertyNames;
+ }
+
+ @Override
public long getVersionId() {
return GENERATOR_VERSION_ID;
}
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 eefb238..85e5147 100644
--- a/user/src/com/google/gwt/user/rebind/ui/ImageBundleGenerator.java
+++ b/user/src/com/google/gwt/user/rebind/ui/ImageBundleGenerator.java
@@ -23,6 +23,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.thirdparty.guava.common.collect.ImmutableSet;
import com.google.gwt.user.client.ui.ImageBundle;
import com.google.gwt.user.client.ui.ImageBundle.Resource;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
@@ -107,6 +108,8 @@
private static final String IMAGEBUNDLE_QNAME = "com.google.gwt.user.client.ui.ImageBundle";
+ private static ImmutableSet<String> relevantPropertyNames = ImmutableSet.of();
+
/* private */static String msgCannotFindImageFromMetaData(String imgResName) {
return "Unable to find image resource '" + imgResName + "'";
}
@@ -151,6 +154,21 @@
return resultName;
}
+ @Override
+ public ImmutableSet<String> getAccessedPropertyNames() {
+ return relevantPropertyNames;
+ }
+
+ @Override
+ public boolean contentDependsOnProperties() {
+ return false;
+ }
+
+ @Override
+ public boolean contentDependsOnTypes() {
+ return false;
+ }
+
/**
* Gets the resource name of the image associated with the specified image
* bundle method in a form that can be passed to
diff --git a/user/src/com/google/gwt/useragent/rebind/UserAgentGenerator.java b/user/src/com/google/gwt/useragent/rebind/UserAgentGenerator.java
index 8e3ef85..622573d 100644
--- a/user/src/com/google/gwt/useragent/rebind/UserAgentGenerator.java
+++ b/user/src/com/google/gwt/useragent/rebind/UserAgentGenerator.java
@@ -26,6 +26,7 @@
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.thirdparty.guava.common.collect.ImmutableSet;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
@@ -37,6 +38,9 @@
public class UserAgentGenerator extends Generator {
static final String PROPERTY_USER_AGENT = "user.agent";
+ private static ImmutableSet<String> relevantPropertyNames =
+ ImmutableSet.of("user.agent", "user.agent.runtimeWarning");
+
@Override
public String generate(TreeLogger logger, GeneratorContext context, String typeName)
throws UnableToCompleteException {
@@ -102,4 +106,14 @@
}
return composerFactory.getCreatedClassName();
}
+
+ @Override
+ public ImmutableSet<String> getAccessedPropertyNames() {
+ return relevantPropertyNames;
+ }
+
+ @Override
+ public boolean contentDependsOnTypes() {
+ return false;
+ }
}
diff --git a/user/test/com/google/gwt/core/ext/test/GeneratorTest.java b/user/test/com/google/gwt/core/ext/test/GeneratorTest.java
new file mode 100644
index 0000000..af4b0ab
--- /dev/null
+++ b/user/test/com/google/gwt/core/ext/test/GeneratorTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2013 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.test;
+
+import com.google.gwt.core.ext.Generator;
+import com.google.gwt.core.ext.GeneratorContext;
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests the Generator base class.
+ */
+public class GeneratorTest extends TestCase {
+
+ private class SimpleGenerator extends Generator {
+
+ @Override
+ public String generate(TreeLogger logger, GeneratorContext context, String typeName)
+ throws UnableToCompleteException {
+ return null;
+ }
+ }
+
+ public void testDefaultPropertyValueStability() {
+ SimpleGenerator simpleGenerator = new SimpleGenerator();
+ // Defaults to the worst case of claiming that generator output content is unstable and will
+ // change as property values change.
+ assertTrue(simpleGenerator.contentDependsOnProperties());
+ }
+
+ public void testDefaultRelevantPropertyNames() {
+ SimpleGenerator simpleGenerator = new SimpleGenerator();
+ // Defaults to the worst case of claiming that generator output content is affected by all
+ // properties (that is the meaning of returning null as opposed to a specific list of property
+ // names).
+ assertNull(simpleGenerator.getAccessedPropertyNames());
+ }
+
+ public void testDefaultTypeStability() {
+ SimpleGenerator simpleGenerator = new SimpleGenerator();
+ // Defaults to the worst case of claiming that generator output content is unstable and will
+ // change as the list of available types changes.
+ assertTrue(simpleGenerator.contentDependsOnTypes());
+ }
+}