Author: [email protected]
Date: Fri Jul  3 08:33:45 2009
New Revision: 5664

Modified:
    trunk/user/src/com/google/gwt/resources/client/CssResource.java
    trunk/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java
    trunk/user/test/com/google/gwt/resources/client/CSSResourceTest.java
    trunk/user/test/com/google/gwt/resources/client/deftest.css

Log:
Allows CSS @def declarations to be retrieved as a String in a CssResource
implementation.  Detection was added for colliding class names and @def  
names,
but you can dis-ambiguate them with the @ClassName() annotation.

Patch by: zundel
Review by: bobv


Modified: trunk/user/src/com/google/gwt/resources/client/CssResource.java
==============================================================================
--- trunk/user/src/com/google/gwt/resources/client/CssResource.java      
(original)
+++ trunk/user/src/com/google/gwt/resources/client/CssResource.java     Fri  
Jul  3 08:33:45 2009
@@ -32,9 +32,10 @@
   * <li>{...@code String someClassName();} will allow the css class
   * <code>.someClassName</code> to be obfuscated at runtime. The function  
will
   * return the obfuscated class name.</li>
- * <li>{...@code <primitive numeric type> someDefName();} will allow access  
to the
- * values defined by {...@literal @def} rules within the CSS file. The defined
- * value must be a raw number, a CSS length, or a percentage value.
+ * <li>{...@code <primitive numeric type or String> someDefName();} will allow
+ * access to the values defined by {...@literal @def} rules within the CSS  
file.
+ * The defined value must be a raw number, a CSS length, or a percentage  
value
+ * if it is to be returned as a numeric type.
   * </ul>
   *
   * <p>

Modified:  
trunk/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java
==============================================================================
--- trunk/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java        
 
(original)
+++ trunk/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java        
 
Fri Jul  3 08:33:45 2009
@@ -115,6 +115,7 @@
       */
      private final Map<String, Map<JMethod, String>>  
classReplacementsWithPrefix;
      private final Pattern classSelectorPattern =  
Pattern.compile("\\.([^ :>+#.]*)");
+    private final Set<String> cssDefs = new HashSet<String>();
      private final Set<String> externalClasses;
      private final TreeLogger logger;
      private final Set<JMethod> missingClasses;
@@ -137,6 +138,11 @@
      }

      @Override
+    public void endVisit(CssDef x, Context ctx) {
+      cssDefs.add(x.getKey());
+    }
+
+    @Override
      public void endVisit(CssSelector x, Context ctx) {
        String sel = x.getSelector();

@@ -193,6 +199,19 @@
      @Override
      public void endVisit(CssStylesheet x, Context ctx) {
        boolean stop = false;
+
+      // Skip names corresponding to @def entries. They too can be  
declared as
+      // String accessors.
+      List<JMethod> toRemove = new ArrayList<JMethod>();
+      for (JMethod method : missingClasses) {
+        if (cssDefs.contains(method.getName())) {
+          toRemove.add(method);
+        }
+      }
+      for (JMethod method : toRemove) {
+        missingClasses.remove(method);
+      }
+
        if (!missingClasses.isEmpty()) {
          stop = true;
          TreeLogger errorLogger = logger.branch(TreeLogger.INFO,
@@ -231,6 +250,15 @@
      }
    }

+  static class DefsCollector extends CssVisitor {
+    private final Set<String> defs = new HashSet<String>();
+
+    @Override
+    public void endVisit(CssDef x, Context ctx) {
+      defs.add(x.getKey());
+    }
+  }
+
    /**
     * Collects all {...@code @external} declarations in the stylesheet.
     */
@@ -1212,8 +1240,8 @@
    private boolean prettyOutput;
    private Map<JClassType, Map<JMethod, String>>  
replacementsByClassAndMethod;
    private Map<JMethod, String> replacementsForSharedMethods;
-  private Map<JMethod, CssStylesheet> stylesheetMap;
    private JClassType stringType;
+  private Map<JMethod, CssStylesheet> stylesheetMap;

    @Override
    public String createAssignment(TreeLogger logger, ResourceContext  
context,
@@ -1701,34 +1729,39 @@

      NumberValue numberValue = def.getValues().get(0).isNumberValue();

-    if (numberValue == null) {
-      logger.log(TreeLogger.ERROR, "The define named " + name
-          + " does not define a numeric value");
-      throw new UnableToCompleteException();
+    String returnExpr = "";
+    JClassType classReturnType = toImplement.getReturnType().isClass();
+    if (classReturnType != null
+         
&& "java.lang.String".equals(classReturnType.getQualifiedSourceName())) {
+      returnExpr = "\"" +  
Generator.escape(def.getValues().get(0).toString())
+          + "\"";
+    } else {
+      JPrimitiveType returnType =  
toImplement.getReturnType().isPrimitive();
+      if (returnType == null) {
+        logger.log(TreeLogger.ERROR, toImplement.getName()
+            + ": Return type must be primitive type or String for "
+            + "@def accessors");
+        throw new UnableToCompleteException();
+      }
+      if (returnType == JPrimitiveType.INT || returnType ==  
JPrimitiveType.LONG) {
+        returnExpr = "" + Math.round(numberValue.getValue());
+      } else if (returnType == JPrimitiveType.FLOAT) {
+        returnExpr = numberValue.getValue() + "F";
+      } else if (returnType == JPrimitiveType.DOUBLE) {
+        returnExpr = "" + numberValue.getValue();
+      } else {
+        logger.log(TreeLogger.ERROR, returnType.getQualifiedSourceName()
+            + " is not a valid primitive return type for @def accessors");
+        throw new UnableToCompleteException();
+      }
      }
-
-    JPrimitiveType returnType = toImplement.getReturnType().isPrimitive();
-    assert returnType != null;
-
      sw.print(toImplement.getReadableDeclaration(false, false, false, false,
          true));
      sw.println(" {");
      sw.indent();
-    if (returnType == JPrimitiveType.INT || returnType ==  
JPrimitiveType.LONG) {
-      sw.println("return " + Math.round(numberValue.getValue()) + ";");
-    } else if (returnType == JPrimitiveType.FLOAT) {
-      sw.println("return " + numberValue.getValue() + "F;");
-    } else if (returnType == JPrimitiveType.DOUBLE) {
-      sw.println("return " + numberValue.getValue() + ";");
-    } else {
-      logger.log(TreeLogger.ERROR, returnType.getQualifiedSourceName()
-          + " is not a valid return type for @def accessors");
-      throw new UnableToCompleteException();
-    }
+    sw.println("return " + returnExpr + ";");
      sw.outdent();
      sw.println("}");
-
-    numberValue.getValue();
    }

    /**
@@ -1738,20 +1771,31 @@
        CssStylesheet sheet, JMethod[] methods,
        Map<JMethod, String> obfuscatedClassNames)
        throws UnableToCompleteException {
+
+    // Get list of @defs
+    DefsCollector collector = new DefsCollector();
+    collector.accept(sheet);
+
      for (JMethod toImplement : methods) {
        String name = toImplement.getName();
        if ("getName".equals(name) || "getText".equals(name)) {
          continue;
        }

-      if (toImplement.getReturnType().equals(stringType)
-          && toImplement.getParameters().length == 0) {
-        writeClassAssignment(sw, toImplement, obfuscatedClassNames);
+      // Bomb out if there is a collision between @def and a style name
+      if (collector.defs.contains(name)
+          && obfuscatedClassNames.containsKey(toImplement)) {
+        logger.log(TreeLogger.ERROR, "@def shadows CSS class name: " + name
+            + ". Fix by renaming the @def name or the CSS class name.");
+        throw new UnableToCompleteException();
+      }

-      } else if (toImplement.getReturnType().isPrimitive() != null
+      if (collector.defs.contains(toImplement.getName())
            && toImplement.getParameters().length == 0) {
          writeDefAssignment(logger, sw, toImplement, sheet);
-
+      } else if (toImplement.getReturnType().equals(stringType)
+          && toImplement.getParameters().length == 0) {
+        writeClassAssignment(sw, toImplement, obfuscatedClassNames);
        } else {
          logger.log(TreeLogger.ERROR, "Don't know how to implement method "
              + toImplement.getName());

Modified:  
trunk/user/test/com/google/gwt/resources/client/CSSResourceTest.java
==============================================================================
--- trunk/user/test/com/google/gwt/resources/client/CSSResourceTest.java        
 
(original)
+++ trunk/user/test/com/google/gwt/resources/client/CSSResourceTest.java        
 
Fri Jul  3 08:33:45 2009
@@ -35,10 +35,19 @@
    }

    interface CssWithDefines extends CssResource {
+    String colorString();
+
      double lengthFloat();

      int lengthInt();

+    String lengthString();
+
+    int overrideInt();
+
+    @ClassName("overrideInt")
+    String overrideIntClass();
+
      double percentFloat();

      int percentInt();
@@ -258,6 +267,14 @@

      assertEquals(50, defines.percentInt());
      assertEquals(50.5, defines.percentFloat());
+
+    assertEquals("100px", defines.lengthString());
+    assertEquals("#f00", defines.colorString());
+
+    assertEquals(10, defines.overrideInt());
+    assertNotNull(defines.overrideIntClass());
+    assertFalse("10px".equals(defines.overrideIntClass()));
+    assertFalse("10".equals(defines.overrideIntClass()));
    }

    public void testMultipleBundles() {

Modified: trunk/user/test/com/google/gwt/resources/client/deftest.css
==============================================================================
--- trunk/user/test/com/google/gwt/resources/client/deftest.css (original)
+++ trunk/user/test/com/google/gwt/resources/client/deftest.css Fri Jul  3  
08:33:45 2009
@@ -22,4 +22,24 @@
   @def percentFloat 50.5%;

   @def lengthInt 50px;
- @def lengthFloat 1.5px;
\ No newline at end of file
+ @def lengthFloat 1.5px;
+
+ @def lengthString 100px;
+ @def colorString #f00;
+
+ /* Uncomment this, and you should get an error about a @def shadowing a  
name */
+ /*
+ .colorString {
+   background-color: #f00;
+ }
+ */
+
+ /* Shouldn't get an error here because the method to access the style name
+  * is annotated with @ClassName()
+  */
+  @def overrideInt 10px;
+ .overrideInt {
+   width: 10px;
+ }
+
+
\ No newline at end of file

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to