Fixes camel case field refs sometimes not matching dashed counterparts.

E.g., this should work:

 <ui:style type='com.google.gwt.sample.mail.client.Contacts.Style'>
 .contacts-break {
   padding: 0.5em;
 }
 </ui:style>

 <g:FlowPanel styleName='{style.contactsBreak}' ui:field='panel'/>
</ui:UiBinder>

Reviewed by klpatfoot

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7078 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/uibinder/rebind/FieldWriterOfGeneratedCssResource.java b/user/src/com/google/gwt/uibinder/rebind/FieldWriterOfGeneratedCssResource.java
index 0ad2ae6..5669df5 100644
--- a/user/src/com/google/gwt/uibinder/rebind/FieldWriterOfGeneratedCssResource.java
+++ b/user/src/com/google/gwt/uibinder/rebind/FieldWriterOfGeneratedCssResource.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2009 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
@@ -18,12 +18,16 @@
 import com.google.gwt.core.ext.UnableToCompleteException;
 import com.google.gwt.core.ext.typeinfo.JClassType;
 import com.google.gwt.core.ext.typeinfo.JType;
+import com.google.gwt.uibinder.attributeparsers.CssNameConverter;
 import com.google.gwt.uibinder.rebind.model.ImplicitCssResource;
 
+import java.util.Set;
+
 /**
  * Implementation of FieldWriter for an {@link ImplicitCssResource}.
  */
 class FieldWriterOfGeneratedCssResource extends AbstractFieldWriter {
+  private static final CssNameConverter nameConverter = new CssNameConverter();
 
   private final ImplicitCssResource css;
   private final JType stringType;
@@ -51,8 +55,12 @@
   public JType getReturnType(String[] path, MonitoredLogger logger) {
     if (path.length == 2) {
       String maybeCssClass = path[1];
+      Set<String> cssClassNames = null;
       try {
-        if (css.getCssClassNames().contains(maybeCssClass)) {
+        cssClassNames = css.getCssClassNames();
+        if (cssClassNames.contains(maybeCssClass)
+            || cssClassNames.contains(nameConverter.convertName(maybeCssClass))
+            || css.getNormalizedCssClassNames().contains(maybeCssClass)) {
           return stringType;
         }
       } catch (UnableToCompleteException e) {
diff --git a/user/src/com/google/gwt/uibinder/rebind/model/ImplicitCssResource.java b/user/src/com/google/gwt/uibinder/rebind/model/ImplicitCssResource.java
index d046942..4ba585d 100644
--- a/user/src/com/google/gwt/uibinder/rebind/model/ImplicitCssResource.java
+++ b/user/src/com/google/gwt/uibinder/rebind/model/ImplicitCssResource.java
@@ -21,6 +21,7 @@
 import com.google.gwt.resources.css.GenerateCssAst;
 import com.google.gwt.resources.css.ast.CssStylesheet;
 import com.google.gwt.resources.ext.ResourceGeneratorUtil;
+import com.google.gwt.uibinder.attributeparsers.CssNameConverter;
 import com.google.gwt.uibinder.rebind.MortalLogger;
 
 import java.io.BufferedWriter;
@@ -41,6 +42,7 @@
  * Models a method returning a CssResource on a generated ClientBundle.
  */
 public class ImplicitCssResource {
+  private static final CssNameConverter nameConverter = new CssNameConverter();
   private final String packageName;
   private final String className;
   private final String name;
@@ -51,10 +53,15 @@
   private final Set<JClassType> imports;
 
   private File generatedFile;
+  private Set<String> cssClassNames;
+  private Set<String> normalizedCssClassNames;
 
-  ImplicitCssResource(String packageName, String className, String name,
+  /**
+   * Visible for testing only, get instances from {@link ImplicitClientBundle}.
+   */
+  public ImplicitCssResource(String packageName, String className, String name,
       String[] source, JClassType extendedInterface, String body,
-      MortalLogger logger, HashSet<JClassType> importTypes) {
+      MortalLogger logger, Set<JClassType> importTypes) {
     this.packageName = packageName;
     this.className = className;
     this.name = name;
@@ -80,21 +87,23 @@
    */
   public Set<String> getCssClassNames() throws UnableToCompleteException {
     List<URL> urls = getExternalCss();
-
-    final File bodyFile = getGeneratedFile();
-    if (bodyFile != null) {
-      try {
-        urls.add(bodyFile.toURI().toURL());
-      } catch (MalformedURLException e) {
-        throw new RuntimeException(e);
+    if (cssClassNames == null) {
+      final File bodyFile = getGeneratedFile();
+      if (bodyFile != null) {
+        try {
+          urls.add(bodyFile.toURI().toURL());
+        } catch (MalformedURLException e) {
+          throw new RuntimeException(e);
+        }
       }
-    }
-    assert urls.size() > 0;
+      assert urls.size() > 0;
 
-    CssStylesheet sheet = GenerateCssAst.exec(logger.getTreeLogger(),
-        urls.toArray(new URL[urls.size()]));
-    return ExtractClassNamesVisitor.exec(sheet,
-        imports.toArray(new JClassType[imports.size()]));
+      CssStylesheet sheet = GenerateCssAst.exec(logger.getTreeLogger(),
+          urls.toArray(new URL[urls.size()]));
+      cssClassNames = ExtractClassNamesVisitor.exec(sheet,
+          imports.toArray(new JClassType[imports.size()]));
+    }
+    return cssClassNames;
   }
 
   /**
@@ -104,6 +113,9 @@
     return extendedInterface;
   }
 
+  /**
+   * @return the set of CssResource types whose scopes are imported
+   */
   public Set<JClassType> getImports() {
     return imports;
   }
@@ -117,6 +129,21 @@
   }
 
   /**
+   * @return css class names with dashed-names normalized like so: dashedNames
+   */
+  public Set<String> getNormalizedCssClassNames()
+      throws UnableToCompleteException {
+    if (normalizedCssClassNames == null) {
+      Set<String> rawNames = getCssClassNames();
+      normalizedCssClassNames = new HashSet<String>();
+      for (String rawName : rawNames) {
+        normalizedCssClassNames.add(nameConverter.convertName(rawName));
+      }
+    }
+    return normalizedCssClassNames;
+  }
+
+  /**
    * @return the package in which the generated CssResource interface should
    *         reside
    */
@@ -124,6 +151,9 @@
     return packageName;
   }
 
+  /**
+   * @return name of the generated type
+   */
   public String getQualifiedSourceName() {
     if (packageName.length() == 0) {
       return name;
diff --git a/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java b/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java
index eac3f1c..62e7d51 100644
--- a/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java
+++ b/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java
@@ -28,6 +28,7 @@
 import com.google.gwt.uibinder.elementparsers.StackLayoutPanelParserTest;
 import com.google.gwt.uibinder.elementparsers.TabLayoutPanelParserTest;
 import com.google.gwt.uibinder.elementparsers.UIObjectParserTest;
+import com.google.gwt.uibinder.rebind.FieldWriterOfGeneratedCssResourceTest;
 import com.google.gwt.uibinder.rebind.GwtResourceEntityResolverTest;
 import com.google.gwt.uibinder.rebind.HandlerEvaluatorTest;
 import com.google.gwt.uibinder.rebind.TokenatorTest;
@@ -47,6 +48,7 @@
     TestSuite suite = new TestSuite("UiBinder tests that require the JRE");
 
     // rebind
+    suite.addTestSuite(FieldWriterOfGeneratedCssResourceTest.class);
     suite.addTestSuite(GwtResourceEntityResolverTest.class);
     suite.addTestSuite(HandlerEvaluatorTest.class);
     suite.addTestSuite(TokenatorTest.class);
diff --git a/user/test/com/google/gwt/uibinder/rebind/FieldWriterOfGeneratedCssResourceTest.java b/user/test/com/google/gwt/uibinder/rebind/FieldWriterOfGeneratedCssResourceTest.java
new file mode 100644
index 0000000..4e2f10e
--- /dev/null
+++ b/user/test/com/google/gwt/uibinder/rebind/FieldWriterOfGeneratedCssResourceTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2009 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.uibinder.rebind;
+
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.core.ext.typeinfo.TypeOracle;
+import com.google.gwt.dev.javac.CompilationState;
+import com.google.gwt.dev.javac.CompilationStateBuilder;
+import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
+import com.google.gwt.uibinder.rebind.model.ImplicitCssResource;
+import com.google.gwt.uibinder.test.UiJavaResources;
+
+import junit.framework.TestCase;
+
+import java.io.PrintWriter;
+import java.util.Collections;
+
+/**
+ * Eponymous test class.
+ */
+public class FieldWriterOfGeneratedCssResourceTest extends TestCase {
+  private TypeOracle types;
+
+  private static TreeLogger createCompileLogger() {
+    PrintWriterTreeLogger logger = new PrintWriterTreeLogger(new PrintWriter(
+        System.err, true));
+    logger.setMaxDetail(TreeLogger.ERROR);
+    return logger;
+  }
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+    CompilationState state = CompilationStateBuilder.buildFrom(
+        createCompileLogger(), UiJavaResources.getUiResources());
+    types = state.getTypeOracle();
+  }
+
+  public void testCamelMatchesDashes() {
+    JClassType stringType = types.findType("java.lang.String");
+    JClassType cssResourceType = stringType; // TODO(rjrjr) get real someday
+
+    ImplicitCssResource css = new ImplicitCssResource("package", "ClassName",
+        "fieldName", new String[] {}, cssResourceType, ".able-baker {}",
+        MortalLogger.NULL, Collections.<JClassType> emptySet());
+
+    FieldWriterOfGeneratedCssResource f = new FieldWriterOfGeneratedCssResource(
+        stringType, css, MortalLogger.NULL);
+
+    assertEquals(stringType, f.getReturnType(new String[] {
+        "fieldName", "ableBaker"}, new MonitoredLogger(TreeLogger.NULL)));
+  }
+
+  public void testDashesMatchesCamels() {
+    JClassType stringType = types.findType("java.lang.String");
+    JClassType cssResourceType = stringType; // TODO(rjrjr) get real someday
+
+    ImplicitCssResource css = new ImplicitCssResource("package", "ClassName",
+        "fieldName", new String[] {}, cssResourceType, ".ableBaker {}",
+        MortalLogger.NULL, Collections.<JClassType> emptySet());
+
+    FieldWriterOfGeneratedCssResource f = new FieldWriterOfGeneratedCssResource(
+        stringType, css, MortalLogger.NULL);
+
+    assertEquals(stringType, f.getReturnType(new String[] {
+        "fieldName", "able-baker"}, new MonitoredLogger(TreeLogger.NULL)));
+  }
+}