Add support to CssResource for unknown at-rules.
Include files missing in original commit.

Patch by: bobv
Review by: rjrjr


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7441 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/resources/css/CssGenerationVisitor.java b/user/src/com/google/gwt/resources/css/CssGenerationVisitor.java
index cb92453..39e4d89 100644
--- a/user/src/com/google/gwt/resources/css/CssGenerationVisitor.java
+++ b/user/src/com/google/gwt/resources/css/CssGenerationVisitor.java
@@ -29,6 +29,7 @@
 import com.google.gwt.resources.css.ast.CssRule;
 import com.google.gwt.resources.css.ast.CssSelector;
 import com.google.gwt.resources.css.ast.CssSprite;
+import com.google.gwt.resources.css.ast.CssUnknownAtRule;
 import com.google.gwt.resources.css.ast.CssUrl;
 import com.google.gwt.resources.css.ast.CssVisitor;
 
@@ -109,6 +110,12 @@
     }
   }
 
+  @Override
+  public void endVisit(CssUnknownAtRule x, Context ctx) {
+    out.printOpt("/* Unknown at-rule */\n");
+    out.print(x.getRule());
+  }
+
   public SortedMap<Integer, List<CssNode>> getSubstitutionPositions() {
     return substitutionPositions;
   }
diff --git a/user/src/com/google/gwt/resources/css/GenerateCssAst.java b/user/src/com/google/gwt/resources/css/GenerateCssAst.java
index e76e8c6..bec0fb7 100644
--- a/user/src/com/google/gwt/resources/css/GenerateCssAst.java
+++ b/user/src/com/google/gwt/resources/css/GenerateCssAst.java
@@ -30,6 +30,7 @@
 import com.google.gwt.resources.css.ast.CssSelector;
 import com.google.gwt.resources.css.ast.CssSprite;
 import com.google.gwt.resources.css.ast.CssStylesheet;
+import com.google.gwt.resources.css.ast.CssUnknownAtRule;
 import com.google.gwt.resources.css.ast.CssUrl;
 import com.google.gwt.resources.css.ast.HasNodes;
 import com.google.gwt.resources.css.ast.HasProperties;
@@ -236,15 +237,22 @@
      * Reflectively invoke a method named parseRule on this instance.
      */
     public void ignorableAtRule(String atRule) throws CSSException {
-      String ruleName = atRule.substring(1, atRule.indexOf(" "));
+      int idx = atRule.indexOf(" ");
+      if (idx == -1) {
+        // Empty rule like @foo;
+        addNode(new CssUnknownAtRule(atRule));
+        return;
+      }
+      String ruleName = atRule.substring(1, idx);
       String methodName = "parse" + (Character.toUpperCase(ruleName.charAt(0)))
-          + ruleName.substring(1);
+          + ruleName.substring(1).toLowerCase();
       try {
         Method parseMethod = getClass().getDeclaredMethod(methodName,
             String.class);
         parseMethod.invoke(this, atRule);
       } catch (NoSuchMethodException e) {
-        errors.log(TreeLogger.WARN, "Ignoring @" + ruleName);
+        // A rule like @-webkit-keyframe {...} that we can't process
+        addNode(new CssUnknownAtRule(atRule));
       } catch (IllegalAccessException e) {
         errors.log(TreeLogger.ERROR, "Unable to invoke parse method ", e);
       } catch (InvocationTargetException e) {
diff --git a/user/src/com/google/gwt/resources/css/ast/CssNodeCloner.java b/user/src/com/google/gwt/resources/css/ast/CssNodeCloner.java
index da94bb0..9995015 100644
--- a/user/src/com/google/gwt/resources/css/ast/CssNodeCloner.java
+++ b/user/src/com/google/gwt/resources/css/ast/CssNodeCloner.java
@@ -246,6 +246,13 @@
     addToNodes(newUrl);
     return true;
   }
+  
+  @Override
+  public boolean visit(CssUnknownAtRule x, Context ctx) {
+    CssUnknownAtRule newRule = new CssUnknownAtRule(x.getRule());
+    addToNodes(newRule);
+    return true;
+  }
 
   /**
    * Add a cloned node instance to the output.
diff --git a/user/src/com/google/gwt/resources/css/ast/CssUnknownAtRule.java b/user/src/com/google/gwt/resources/css/ast/CssUnknownAtRule.java
new file mode 100644
index 0000000..0d94e57
--- /dev/null
+++ b/user/src/com/google/gwt/resources/css/ast/CssUnknownAtRule.java
@@ -0,0 +1,42 @@
+/*
+ * 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.ast;
+
+/**
+ * Represents a CSS at-rule that CssResource is unable to process.
+ */
+public class CssUnknownAtRule extends CssNode {
+
+  private final String rule;
+
+  public CssUnknownAtRule(String rule) {
+    this.rule = rule;
+  }
+
+  /**
+   * Returns the entire unprocessed at-rule declaration.
+   */
+  public String getRule() {
+    return rule;
+  }
+
+  public void traverse(CssVisitor visitor, Context context) {
+    if (visitor.visit(this, context)) {
+      // Do nothing
+    }
+    visitor.endVisit(this, context);
+  }
+}
diff --git a/user/src/com/google/gwt/resources/css/ast/CssVisitor.java b/user/src/com/google/gwt/resources/css/ast/CssVisitor.java
index 15012a6..a8520fc 100644
--- a/user/src/com/google/gwt/resources/css/ast/CssVisitor.java
+++ b/user/src/com/google/gwt/resources/css/ast/CssVisitor.java
@@ -157,6 +157,13 @@
   /**
    * @param x the node being visited
    * @param ctx the context for the visit
+   */
+  public void endVisit(CssUnknownAtRule x, Context ctx) {
+  }
+
+  /**
+   * @param x the node being visited
+   * @param ctx the context for the visit
    * @return
    */
   public boolean visit(CssDef x, Context ctx) {
@@ -271,6 +278,15 @@
     return true;
   }
 
+  /**
+   * @param x the node being visited
+   * @param ctx the context for the visit
+   * @return
+   */
+  public boolean visit(CssUnknownAtRule x, Context ctx) {
+    return true;
+  }
+
   protected void doAccept(List<? extends CssNode> list) {
     for (CssNode node : list) {
       doTraverse(node, UNMODIFIABLE_CONTEXT);
diff --git a/user/test/com/google/gwt/resources/ResourcesSuite.java b/user/test/com/google/gwt/resources/ResourcesSuite.java
index 5617781..7ab12b6 100644
--- a/user/test/com/google/gwt/resources/ResourcesSuite.java
+++ b/user/test/com/google/gwt/resources/ResourcesSuite.java
@@ -25,6 +25,7 @@
 import com.google.gwt.resources.css.CssReorderTest;
 import com.google.gwt.resources.css.CssRtlTest;
 import com.google.gwt.resources.css.ExtractClassNamesVisitorTest;
+import com.google.gwt.resources.css.UnknownAtRuleTest;
 import com.google.gwt.resources.ext.ResourceGeneratorUtilTest;
 
 import junit.framework.Test;
@@ -46,6 +47,7 @@
     suite.addTestSuite(NestedBundleTest.class);
     suite.addTestSuite(ResourceGeneratorUtilTest.class);
     suite.addTestSuite(TextResourceTest.class);
+    suite.addTestSuite(UnknownAtRuleTest.class);
     return suite;
   }
 }
diff --git a/user/test/com/google/gwt/resources/client/test.css b/user/test/com/google/gwt/resources/client/test.css
index 0d3efdb..148adb8 100644
--- a/user/test/com/google/gwt/resources/client/test.css
+++ b/user/test/com/google/gwt/resources/client/test.css
@@ -221,3 +221,8 @@
 /* The @external parser attempts to be flexible */
 @external externalA, .externalB externalC;
 .externalA .replacement, .externalB, .externalC {border: GREEN;}
+
+/* Check unknown at-rules */
+@dontIgnoreThis;
+@dontIgnoreThis { /* the space between the name and the { is important */ }
+@dontIgnoreThisToo{ some { random : content } }
diff --git a/user/test/com/google/gwt/resources/css/UnknownAtRuleTest.java b/user/test/com/google/gwt/resources/css/UnknownAtRuleTest.java
new file mode 100644
index 0000000..1fb5114
--- /dev/null
+++ b/user/test/com/google/gwt/resources/css/UnknownAtRuleTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.dev.util.DefaultTextOutput;
+import com.google.gwt.dev.util.TextOutput;
+import com.google.gwt.resources.css.ast.CssNode;
+import com.google.gwt.resources.css.ast.CssStylesheet;
+import com.google.gwt.resources.css.ast.CssUnknownAtRule;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+
+/**
+ * Tests how CssResource handles stylesheets with unknown at-rules.
+ */
+public class UnknownAtRuleTest extends TestCase {
+  private static final String COMPLEX = "@complex {\n  with: arbitrary;\n  stuff: inside;\n}";
+  private static final String EXTENDED = "@-extended-ident {\n  \n}";
+  private static final String SIMPLE = "@simple;";
+
+  public void test() throws UnableToCompleteException {
+    CssStylesheet sheet = GenerateCssAst.exec(TreeLogger.NULL,
+        getClass().getClassLoader().getResource(
+            "com/google/gwt/resources/css/unknownAtRule.css"));
+
+    List<CssNode> nodes = sheet.getNodes();
+    assertEquals(3, nodes.size());
+    assertEquals(SIMPLE, ((CssUnknownAtRule) nodes.get(0)).getRule());
+    assertEquals(COMPLEX, ((CssUnknownAtRule) nodes.get(1)).getRule());
+    assertEquals(EXTENDED, ((CssUnknownAtRule) nodes.get(2)).getRule());
+
+    TextOutput out = new DefaultTextOutput(true);
+    CssGenerationVisitor v = new CssGenerationVisitor(out);
+    v.accept(sheet);
+
+    assertEquals(SIMPLE + COMPLEX + EXTENDED, out.toString());
+  }
+}
diff --git a/user/test/com/google/gwt/resources/css/unknownAtRule.css b/user/test/com/google/gwt/resources/css/unknownAtRule.css
new file mode 100644
index 0000000..bef0cea
--- /dev/null
+++ b/user/test/com/google/gwt/resources/css/unknownAtRule.css
@@ -0,0 +1,8 @@
+@simple;
+@complex {
+  with: arbitrary;
+  stuff: inside;
+}
+@-extended-ident {
+  /* This should be dropped */
+}