Choose the right resource file if gss is enabled.
In GWT 2.8, GSS will not be experimental anymore and we will still
support the old CssResource syntax.
This patch allow the compiler to choose the right resource file
(.gss or .css) according to whether GSS is enabled or not.
Change-Id: If003268aea185634fb3fb1b2191f47903f3421d2
diff --git a/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java b/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java
index bbdf3a2..3bb8e31 100644
--- a/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java
+++ b/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java
@@ -609,7 +609,7 @@
protected URL[] getResources(TreeLogger logger, ResourceContext context,
JMethod method) throws UnableToCompleteException {
- return ResourceGeneratorUtil.findResources(logger, context, method);
+ return GssResourceGenerator.findResources(logger, context, method, false);
}
/**
diff --git a/user/src/com/google/gwt/resources/rg/GssResourceGenerator.java b/user/src/com/google/gwt/resources/rg/GssResourceGenerator.java
index 89d6b52..a269345 100644
--- a/user/src/com/google/gwt/resources/rg/GssResourceGenerator.java
+++ b/user/src/com/google/gwt/resources/rg/GssResourceGenerator.java
@@ -31,6 +31,7 @@
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.util.Util;
import com.google.gwt.i18n.client.LocaleInfo;
+import com.google.gwt.resources.client.ClientBundle.Source;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.CssResource.ClassName;
import com.google.gwt.resources.client.CssResource.Import;
@@ -450,6 +451,77 @@
return true;
}
+ /**
+ * Temporary method needed when GSS and the old CSS syntax are both supported by the sdk.
+ * It aims to choose the right resource file according to whether gss is enabled or not. If gss is
+ * enabled, it will try to find the resource file ending by .gss first. If GSS is disabled it will
+ * try to find the .css file. This logic is applied even if a
+ * {@link com.google.gwt.resources.client.ClientBundle.Source} annotation is used to define
+ * the resource file.
+ * <p>
+ * This method can be deleted once the support for the old CssResource is removed and use directly
+ * ResourceGeneratorUtil.findResources().
+ */
+ static URL[] findResources(TreeLogger logger, ResourceContext context, JMethod method,
+ boolean gssEnabled) throws UnableToCompleteException {
+
+ boolean isSourceAnnotationUsed = method.getAnnotation(Source.class) != null;
+
+ if (!isSourceAnnotationUsed) {
+ // ResourceGeneratorUtil will try to find automatically the resource file. Give him the right
+ // extension to use first
+ String[] extensions = gssEnabled ?
+ new String[]{".gss", ".css"} : new String[]{".css", ".gss"};
+ return ResourceGeneratorUtil.findResources(logger, context, method, extensions);
+ }
+
+ // find the original resource files specified by the @Source annotation
+ URL[] originalResources = ResourceGeneratorUtil.findResources(logger, context, method);
+ URL[] resourcesToUse = new URL[originalResources.length];
+
+ String preferredExtension = gssEnabled ? ".gss" : ".css";
+
+ // Try to find all the resources by using the preferred extension according to whether gss is
+ // enabled or not. If one file with the preferred extension is missing, return the original
+ // resource files otherwise return the preferred files.
+ String[] sourceFiles = method.getAnnotation(Source.class).value();
+ for (int i = 0; i < sourceFiles.length; i++) {
+ String original = sourceFiles[i];
+
+ if (!original.endsWith(preferredExtension) && original.length() > 4) {
+ String preferredFile = original.substring(0, original.length() - 4) + preferredExtension;
+
+ // try to find the resource relative to the package
+ String path = method.getEnclosingType().getPackage().getName().replace('.', '/') + '/';
+ URL preferredUrl = ResourceGeneratorUtil
+ .tryFindResource(logger, context.getGeneratorContext(), context, path + preferredFile);
+
+ if (preferredUrl == null) {
+ // if it doesn't exist, assume it is absolute
+ preferredUrl = ResourceGeneratorUtil
+ .tryFindResource(logger, context.getGeneratorContext(), context, preferredFile);
+ }
+
+ if (preferredUrl == null) {
+ // avoid to mix gss and css, if one file with the preferred extension is missing
+ return originalResources;
+ }
+
+ logger.log(Type.INFO, "Preferred resource file found: " + preferredFile + ". This file " +
+ "will be used in replacement of " + original);
+
+ resourcesToUse[i] = preferredUrl;
+ } else {
+ // gss and css files shouldn't be used together for a same resource. So if one of the file
+ // is using the the preferred extension, return the original resources. If the dev has mixed
+ // gss and ccs files, that will fail later.
+ return originalResources;
+ }
+ }
+
+ return resourcesToUse;
+ }
+
private Map<JMethod, CssParsingResult> cssParsingResultMap;
private Set<String> allowedNonStandardFunctions;
private LoggerErrorManager errorManager;
@@ -654,7 +726,7 @@
throw new UnableToCompleteException();
}
- URL[] resourceUrls = ResourceGeneratorUtil.findResources(logger, context, method);
+ URL[] resourceUrls = findResources(logger, context, method, gssOptions.isEnabled());
if (resourceUrls.length == 0) {
logger.log(TreeLogger.ERROR, "At least one source must be specified");
throw new UnableToCompleteException();
diff --git a/user/test/com/google/gwt/resources/client/CSSResourceTest.java b/user/test/com/google/gwt/resources/client/CSSResourceTest.java
index 46dc196..001d37e 100644
--- a/user/test/com/google/gwt/resources/client/CSSResourceTest.java
+++ b/user/test/com/google/gwt/resources/client/CSSResourceTest.java
@@ -169,6 +169,14 @@
String replacement();
}
+ /**
+ * CssResource used to test that the compiler will pick up the right resource (.css or .gss)
+ * according to the module configuration.
+ */
+ interface ResourceFileChooser extends CssResource {
+ String myClass();
+ }
+
interface NestedResources extends ClientBundle {
@Source("32x32.png")
DataResource dataMethod();
@@ -213,6 +221,23 @@
@Source("16x16.png")
ImageResource spriteMethod();
+
+ ResourceFileChooser resourceFileChooser();
+
+ @Source("resourceFileChooser.css")
+ ResourceFileChooser resourceFileChooserWithSourceTargetingOneCssFile();
+
+ @Source("resourceFileChooser.gss")
+ ResourceFileChooser resourceFileChooserWithSourceTargetingOneGssFile();
+
+ @Source({"resourceFileChooser.css", "resourceFileChooser2.css"})
+ ResourceFileChooser resourceFileChooserWithSourceTargetingCssFiles();
+
+ @Source({"resourceFileChooser.gss", "resourceFileChooser2.gss"})
+ ResourceFileChooser resourceFileChooserWithSourceTargetingGssFiles();
+
+ @Source({"resourceFileChooser.css", "resourceFileChooser2.css", "resourceFileChooser3.css"})
+ ResourceFileChooser resourceFileChooserWithSourceTargetingCssFilesWithoutGssFile();
}
interface SharedBase extends CssResource {
@@ -411,6 +436,35 @@
assertTrue(r.empty().ensureInjected());
}
+ public void testFileChoice() {
+ // resource without @Source annotation
+ ResourceFileChooser css = Resources.INSTANCE.resourceFileChooser();
+ // should use the css file.
+ String expectedCss = "." + css.myClass() + "{width:5px;}";
+ assertEquals(expectedCss, css.getText());
+
+ // resource with @Source annotation targeting one .css file
+ css = Resources.INSTANCE.resourceFileChooserWithSourceTargetingOneCssFile();
+ // should use the css file.
+ assertEquals(expectedCss, css.getText());
+
+ // resource with @Source annotation targeting one .gss file
+ css = Resources.INSTANCE.resourceFileChooserWithSourceTargetingOneGssFile();
+ // should use the css file instead of the gss file
+ assertEquals(expectedCss, css.getText());
+
+ // resource with @Source annotation targeting several .css files
+ css = Resources.INSTANCE.resourceFileChooserWithSourceTargetingCssFiles();
+ // should use the css files.
+ expectedCss = "." + css.myClass() + "{width:5px;padding:5px;}";
+ assertEquals(expectedCss, css.getText());
+
+ // resource with @Source annotation targeting several .gss files
+ css = Resources.INSTANCE.resourceFileChooserWithSourceTargetingGssFiles();
+ // should use the css files instead of the gss files
+ assertEquals(expectedCss, css.getText());
+ }
+
public void testMultipleBundles() {
Resources r1 = GWT.create(Resources.class);
SiblingResources r2 = GWT.create(SiblingResources.class);
diff --git a/user/test/com/google/gwt/resources/client/CSSResourceWithGSSTest.java b/user/test/com/google/gwt/resources/client/CSSResourceWithGSSTest.java
index c61051e..bd0f4d1 100644
--- a/user/test/com/google/gwt/resources/client/CSSResourceWithGSSTest.java
+++ b/user/test/com/google/gwt/resources/client/CSSResourceWithGSSTest.java
@@ -126,4 +126,41 @@
// Test font-face contents
assertTrue(text.contains("url(Foo.otf) format(\"opentype\")"));
}
+
+ @Override
+ public void testFileChoice() {
+ // resource without @Source annotation
+ ResourceFileChooser css = Resources.INSTANCE.resourceFileChooser();
+ // should use the gss file.
+ String expectedCss = "." + css.myClass() + "{width:10px}";
+ assertEquals(expectedCss, css.getText());
+
+ // resource with @Source annotation targeting one .css file
+ css = Resources.INSTANCE.resourceFileChooserWithSourceTargetingOneCssFile();
+ // should use the gss file instead of the css file.
+ assertEquals(expectedCss, css.getText());
+
+ // resource with @Source annotation targeting one .gss file
+ css = Resources.INSTANCE.resourceFileChooserWithSourceTargetingOneGssFile();
+ // should use the gss file
+ assertEquals(expectedCss, css.getText());
+
+ // resource with @Source annotation targeting several .css files
+ css = Resources.INSTANCE.resourceFileChooserWithSourceTargetingCssFiles();
+ // should use the gss files instead of the css files
+ expectedCss = "." + css.myClass() + "{width:10px;margin:10px}";
+ assertEquals(expectedCss, css.getText());
+
+ // resource with @Source annotation targeting several .gss files
+ css = Resources.INSTANCE.resourceFileChooserWithSourceTargetingGssFiles();
+ // should use the gss files
+ assertEquals(expectedCss, css.getText());
+
+ // resource with @Source annotation targeting several .css files but one css file doesn't have
+ // a corresponding gss file.
+ css = Resources.INSTANCE.resourceFileChooserWithSourceTargetingCssFilesWithoutGssFile();
+ // should use the css file (will be auto-converted)
+ expectedCss = "." + css.myClass() + "{width:5px;padding:5px;height:5px}";
+ assertEquals(expectedCss, css.getText());
+ }
}
diff --git a/user/test/com/google/gwt/resources/client/resourceFileChooser.css b/user/test/com/google/gwt/resources/client/resourceFileChooser.css
new file mode 100644
index 0000000..08e4f54
--- /dev/null
+++ b/user/test/com/google/gwt/resources/client/resourceFileChooser.css
@@ -0,0 +1,5 @@
+@def MY_CONSTANT 5px;
+
+.myClass {
+ width: MY_CONSTANT;
+}
diff --git a/user/test/com/google/gwt/resources/client/resourceFileChooser.gss b/user/test/com/google/gwt/resources/client/resourceFileChooser.gss
new file mode 100644
index 0000000..d620db5
--- /dev/null
+++ b/user/test/com/google/gwt/resources/client/resourceFileChooser.gss
@@ -0,0 +1,5 @@
+@def MY_CONSTANT 10px;
+
+.myClass {
+ width: MY_CONSTANT;
+}
diff --git a/user/test/com/google/gwt/resources/client/resourceFileChooser2.css b/user/test/com/google/gwt/resources/client/resourceFileChooser2.css
new file mode 100644
index 0000000..ba3789d
--- /dev/null
+++ b/user/test/com/google/gwt/resources/client/resourceFileChooser2.css
@@ -0,0 +1,3 @@
+.myClass {
+ padding: MY_CONSTANT;
+}
diff --git a/user/test/com/google/gwt/resources/client/resourceFileChooser2.gss b/user/test/com/google/gwt/resources/client/resourceFileChooser2.gss
new file mode 100644
index 0000000..017b3e3
--- /dev/null
+++ b/user/test/com/google/gwt/resources/client/resourceFileChooser2.gss
@@ -0,0 +1,3 @@
+.myClass {
+ margin: MY_CONSTANT;
+}
diff --git a/user/test/com/google/gwt/resources/client/resourceFileChooser3.css b/user/test/com/google/gwt/resources/client/resourceFileChooser3.css
new file mode 100644
index 0000000..81d25e4
--- /dev/null
+++ b/user/test/com/google/gwt/resources/client/resourceFileChooser3.css
@@ -0,0 +1,3 @@
+.myClass {
+ height: MY_CONSTANT;
+}