Add tail-globs to CssResource's @external declarations.
http://gwt-code-reviews.appspot.com/243803
Suggested by: gak
Patch by: bobv
Review by: rjrjr
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7774 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/resources/css/ExternalClassesCollector.java b/user/src/com/google/gwt/resources/css/ExternalClassesCollector.java
index d6cb7bf..7a15f5e 100644
--- a/user/src/com/google/gwt/resources/css/ExternalClassesCollector.java
+++ b/user/src/com/google/gwt/resources/css/ExternalClassesCollector.java
@@ -17,23 +17,73 @@
import com.google.gwt.resources.css.ast.Context;
import com.google.gwt.resources.css.ast.CssExternalSelectors;
+import com.google.gwt.resources.css.ast.CssSelector;
import com.google.gwt.resources.css.ast.CssVisitor;
import java.util.HashSet;
import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.regex.Matcher;
/**
- * Collects all {@code @external} declarations in the stylesheet.
+ * Collects all {@code @external} declarations in the stylesheet. This visitor
+ * will expand tail-globs.
*/
public class ExternalClassesCollector extends CssVisitor {
- private final Set<String> classes = new HashSet<String>();
+ public static final String GLOB_STRING = "*";
+
+ private final SortedSet<String> allClasses = new TreeSet<String>();
+ private final SortedSet<String> externalClasses = new TreeSet<String>();
+ private final Set<String> globs = new HashSet<String>();
+
+ /**
+ * This is a short-circuit for <code>{@literal @external} *</code>.
+ */
+ private boolean matchAll;
@Override
public void endVisit(CssExternalSelectors x, Context ctx) {
- classes.addAll(x.getClasses());
+ if (matchAll) {
+ return;
+ }
+
+ for (String selector : x.getClasses()) {
+ if (selector.equals(GLOB_STRING)) {
+ matchAll = true;
+ return;
+ } else if (selector.endsWith(GLOB_STRING)) {
+ globs.add(selector.substring(0, selector.length() - 1));
+ } else {
+ externalClasses.add(selector);
+ }
+ }
}
- public Set<String> getClasses() {
- return classes;
+ @Override
+ public void endVisit(CssSelector x, Context ctx) {
+ Matcher m = CssSelector.CLASS_SELECTOR_PATTERN.matcher(x.getSelector());
+
+ while (m.find()) {
+ allClasses.add(m.group(1));
+ }
}
-}
\ No newline at end of file
+
+ public SortedSet<String> getClasses() {
+ if (matchAll) {
+ return allClasses;
+ }
+
+ glob : for (String glob : globs) {
+ for (String clazz : allClasses.tailSet(glob)) {
+ if (clazz.startsWith(glob)) {
+ externalClasses.add(clazz);
+ } else {
+ continue glob;
+ }
+ }
+ }
+
+ return externalClasses;
+ }
+}
diff --git a/user/test/com/google/gwt/resources/ResourcesSuite.java b/user/test/com/google/gwt/resources/ResourcesSuite.java
index 7ab12b6..35ecb35 100644
--- a/user/test/com/google/gwt/resources/ResourcesSuite.java
+++ b/user/test/com/google/gwt/resources/ResourcesSuite.java
@@ -21,6 +21,7 @@
import com.google.gwt.resources.client.ImageResourceTest;
import com.google.gwt.resources.client.NestedBundleTest;
import com.google.gwt.resources.client.TextResourceTest;
+import com.google.gwt.resources.css.CssExternalTest;
import com.google.gwt.resources.css.CssNodeClonerTest;
import com.google.gwt.resources.css.CssReorderTest;
import com.google.gwt.resources.css.CssRtlTest;
@@ -37,6 +38,7 @@
public static Test suite() {
GWTTestSuite suite = new GWTTestSuite("Test for com.google.gwt.resources");
+ suite.addTestSuite(CssExternalTest.class);
suite.addTestSuite(CSSResourceTest.class);
suite.addTestSuite(CssReorderTest.class);
suite.addTestSuite(CssRtlTest.class);
diff --git a/user/test/com/google/gwt/resources/css/CssExternalTest.java b/user/test/com/google/gwt/resources/css/CssExternalTest.java
new file mode 100644
index 0000000..8e76008
--- /dev/null
+++ b/user/test/com/google/gwt/resources/css/CssExternalTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2010 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.resources.css;
+
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.resources.css.ast.CssStylesheet;
+import com.google.gwt.resources.rg.CssTestCase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Tests {@link ExternalClassesCollector}.
+ */
+public class CssExternalTest extends CssTestCase {
+
+ public void testExternal() throws UnableToCompleteException {
+ CssStylesheet sheet = GenerateCssAst.exec(TreeLogger.NULL,
+ getClass().getClassLoader().getResource(
+ "com/google/gwt/resources/css/external.css"));
+ assertNotNull(sheet);
+
+ ExternalClassesCollector v = new ExternalClassesCollector();
+ v.accept(sheet);
+
+ assertEquals(Arrays.asList("a", "b", "c", "glob-a", "glob-b", "no*effect"),
+ new ArrayList<String>(v.getClasses()));
+ }
+
+ /**
+ * Make sure the short-circuit logic for <code>{@literal @external} *</code> works correctly.
+ */
+ public void testExternalStar() throws UnableToCompleteException {
+ CssStylesheet sheet = GenerateCssAst.exec(TreeLogger.NULL,
+ getClass().getClassLoader().getResource(
+ "com/google/gwt/resources/css/external_star.css"),
+ getClass().getClassLoader().getResource(
+ "com/google/gwt/resources/css/external.css"));
+ assertNotNull(sheet);
+
+ ExternalClassesCollector v = new ExternalClassesCollector();
+ v.accept(sheet);
+
+ assertEquals(Arrays.asList("a", "c", "d", "glob-a", "glob-b", "no-effect"),
+ new ArrayList<String>(v.getClasses()));
+ }
+}
diff --git a/user/test/com/google/gwt/resources/css/external.css b/user/test/com/google/gwt/resources/css/external.css
new file mode 100644
index 0000000..35a3528
--- /dev/null
+++ b/user/test/com/google/gwt/resources/css/external.css
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2010 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.
+ */
+
+/* Always collected */
+@external a .b, c;
+
+.a{}
+/* Ignore b */
+.c:content{}
+/* d should also be ignored */
+.d{}
+
+/* Will be expanded */
+@external glob-*;
+.glob-a {}
+.glob-b {}
+
+/* No effect */
+@external nothing-*;
+
+/* Internal stars don't do anything */
+@external no*effect;
+.no-effect {}
diff --git a/user/test/com/google/gwt/resources/css/external_star.css b/user/test/com/google/gwt/resources/css/external_star.css
new file mode 100644
index 0000000..696a71d
--- /dev/null
+++ b/user/test/com/google/gwt/resources/css/external_star.css
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2010 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.
+ */
+
+ /* Collect all */
+@external *;