Adds support for the CSS_ATTRIBUTE_START parse context to HtmlTemplateParser.

Review at http://gwt-code-reviews.appspot.com/1392801


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9912 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/safehtml/rebind/HtmlTemplateParser.java b/user/src/com/google/gwt/safehtml/rebind/HtmlTemplateParser.java
index 2ad6324..316a524 100644
--- a/user/src/com/google/gwt/safehtml/rebind/HtmlTemplateParser.java
+++ b/user/src/com/google/gwt/safehtml/rebind/HtmlTemplateParser.java
@@ -74,10 +74,14 @@
  * <dd>This context corresponds to a parameter that appears at the very start of
  * a URL-valued HTML attribute's value; in the above example this applies to
  * parameter #1.
+ * <dt>{@link HtmlContext.Type#CSS_ATTRIBUTE_START}
+ * <dd>This context corresponds to a parameter that appears at the very
+ * beginning of a {@code style} attribute's value; in the above example this
+ * applies to parameter #0.
  * <dt>{@link HtmlContext.Type#CSS_ATTRIBUTE}
  * <dd>This context corresponds to a parameter that appears in the context of a
- * {@code style} attribute; in the above example this applies to
- * parameter #0.
+ * {@code style} attribute, except at the very beginning of the attribute's
+ * value.
  * <dt>{@link HtmlContext.Type#ATTRIBUTE_VALUE}
  * <dd>This context corresponds to a parameter that appears within an attribute
  * and is not in one of the more specific in-attribute contexts above. In
@@ -210,7 +214,11 @@
    */
   private HtmlContext getHtmlContextFromParseState()
       throws UnableToCompleteException {
-
+    // TODO(xtof): Consider refactoring such that state related to the position
+    // of the template variable in an attribute is exposed separately (as
+    // HtmlContext#isAttributeStart(), etc). In doing so, consider trade off
+    // between combinatorial explosion of possible states vs. complexity of
+    // client code.
     if (streamHtmlParser.getState().equals(HtmlParser.STATE_ERROR)) {
       logger.log(TreeLogger.ERROR,
           "Parsing template resulted in parse error: "
@@ -250,7 +258,11 @@
       if (streamHtmlParser.isUrlStart()) {
         return new HtmlContext(HtmlContext.Type.URL_START, tag, attribute);
       } else if (streamHtmlParser.inCss()) {
-        return new HtmlContext(HtmlContext.Type.CSS_ATTRIBUTE, tag, attribute);
+        if (streamHtmlParser.getValueIndex() == 0) {
+          return new HtmlContext(HtmlContext.Type.CSS_ATTRIBUTE_START, tag, attribute);
+        } else {
+          return new HtmlContext(HtmlContext.Type.CSS_ATTRIBUTE, tag, attribute);
+        }
       } else {
         return new HtmlContext(
             HtmlContext.Type.ATTRIBUTE_VALUE, tag, attribute);
diff --git a/user/src/com/google/gwt/safehtml/rebind/ParsedHtmlTemplate.java b/user/src/com/google/gwt/safehtml/rebind/ParsedHtmlTemplate.java
index f517d2a..dd44da7 100644
--- a/user/src/com/google/gwt/safehtml/rebind/ParsedHtmlTemplate.java
+++ b/user/src/com/google/gwt/safehtml/rebind/ParsedHtmlTemplate.java
@@ -64,7 +64,11 @@
       /**
        * CSS (style) attribute context.
        */
-      CSS_ATTRIBUTE
+      CSS_ATTRIBUTE,
+      /**
+       * At the very start of a CSS (style) attribute context.
+       */
+      CSS_ATTRIBUTE_START
     }
 
     private final Type type;
diff --git a/user/test/com/google/gwt/safehtml/rebind/HtmlTemplateParserTest.java b/user/test/com/google/gwt/safehtml/rebind/HtmlTemplateParserTest.java
index 4d6fbb2..8ef9f53 100644
--- a/user/test/com/google/gwt/safehtml/rebind/HtmlTemplateParserTest.java
+++ b/user/test/com/google/gwt/safehtml/rebind/HtmlTemplateParserTest.java
@@ -134,10 +134,15 @@
     // Test correct detection of CSS context.
     assertParseTemplateResult(
         "[L(<div class=\"), P((ATTRIBUTE_VALUE,div,class),0), L(\" style=\"), "
-            + "P((CSS_ATTRIBUTE,div,style),2), L(\">Hello ), "
+            + "P((CSS_ATTRIBUTE_START,div,style),2), L(\">Hello ), "
             + "P((TEXT,null,null),1)]",
         "<div class=\"{0}\" style=\"{2}\">Hello {1}");
     assertParseTemplateResult(
+        "[L(<div class=\"), P((ATTRIBUTE_VALUE,div,class),0), L(\" style=\"color:green; ), "
+            + "P((CSS_ATTRIBUTE,div,style),2), L(\">Hello ), "
+            + "P((TEXT,null,null),1)]",
+        "<div class=\"{0}\" style=\"color:green; {2}\">Hello {1}");
+    assertParseTemplateResult(
         "[L(<div>), P((TEXT,null,null),0), L(<style>foo ), "
             + "P((CSS,null,null),1), L(</style>)]",
         "<div>{0}<style>foo {1}</style>");