Begin migration of CssResource to strict-by-default behavior.
Add a @NotStrict annotation.
Warn unless one of @Strict or @NotStrict annotation is present or the CssResource.strictAccessors module property is set.
Update tests to compile without warnings.

Patch by: bob
Review by: rjrjr

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5480 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/resources/client/CssResource.java b/user/src/com/google/gwt/resources/client/CssResource.java
index f56efdc..e566e53 100644
--- a/user/src/com/google/gwt/resources/client/CssResource.java
+++ b/user/src/com/google/gwt/resources/client/CssResource.java
@@ -175,6 +175,18 @@
   }
 
   /**
+   * The presence of this annotation on a CssResource accessor method indicates
+   * that any class selectors that do not correspond with a String accessor
+   * method in the return type or an {@code @external} declaration should not
+   * trigger a compilation error. This annotation is not recommended for new
+   * code.
+   */
+  @Documented
+  @Target(ElementType.METHOD)
+  public @interface NotStrict {
+  }
+
+  /**
    * Indicates that the String accessor methods defined in a CssResource will
    * return the same values across all implementations of that type.
    * <p>
diff --git a/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java b/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java
index 70c4b2c..26b5c6c 100644
--- a/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java
+++ b/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java
@@ -38,6 +38,7 @@
 import com.google.gwt.resources.client.CssResource.ClassName;
 import com.google.gwt.resources.client.CssResource.Import;
 import com.google.gwt.resources.client.CssResource.ImportedWithPrefix;
+import com.google.gwt.resources.client.CssResource.NotStrict;
 import com.google.gwt.resources.client.CssResource.Shared;
 import com.google.gwt.resources.client.CssResource.Strict;
 import com.google.gwt.resources.client.ImageResource.ImageOptions;
@@ -215,6 +216,9 @@
         for (String s : unknownClasses) {
           errorLogger.log(TreeLogger.ERROR, s);
         }
+        errorLogger.log(TreeLogger.INFO, "Fix by adding String accessor "
+            + "method(s) to the CssResource interface for obfuscated classes, "
+            + "or using an @external declaration for unobfuscated classes.");
       }
 
       if (stop) {
@@ -1504,12 +1508,22 @@
 
   private boolean isStrict(TreeLogger logger, ResourceContext context,
       JMethod method) {
-    boolean strict = method.getAnnotation(Strict.class) != null;
-    if (!strict) {
+    Strict strictAnnotation = method.getAnnotation(Strict.class);
+    NotStrict nonStrictAnnotation = method.getAnnotation(NotStrict.class);
+    boolean strict = false;
+
+    if (strictAnnotation != null && nonStrictAnnotation != null) {
+      // Both annotations
+      logger.log(TreeLogger.WARN, "Contradictory annotations "
+          + Strict.class.getName() + " and " + NotStrict.class.getName()
+          + " applied to the CssResource accessor method; assuming strict");
+      strict = true;
+
+    } else if (strictAnnotation == null && nonStrictAnnotation == null) {
+      // Neither annotation
+
       /*
-       * The developer may choose to force strict behavior onto the system. If
-       * the method does not already have an @Strict annotation, print a
-       * warning.
+       * Fall back to using the to-be-deprecated strictAccessor property.
        */
       try {
         PropertyOracle propertyOracle = context.getGeneratorContext().getPropertyOracle();
@@ -1524,7 +1538,24 @@
       } catch (BadPropertyValueException e) {
         // Ignore
       }
+
+      if (!strict) {
+        // This is a temporary warning during the transitional phase
+        logger.log(TreeLogger.WARN, "Accessor does not specify "
+            + Strict.class.getName() + " or " + NotStrict.class.getName()
+            + ". The default behavior will change from non-strict "
+            + "to strict in a future revision.");
+      }
+
+    } else if (nonStrictAnnotation != null) {
+      // Only the non-strict annotation
+      strict = false;
+
+    } else if (strictAnnotation != null) {
+      // Only the strict annotation
+      strict = true;
     }
+
     return strict;
   }
 
diff --git a/user/test/com/google/gwt/resources/client/CSSResourceTest.java b/user/test/com/google/gwt/resources/client/CSSResourceTest.java
index d966472..a07e86c 100644
--- a/user/test/com/google/gwt/resources/client/CSSResourceTest.java
+++ b/user/test/com/google/gwt/resources/client/CSSResourceTest.java
@@ -19,6 +19,7 @@
 import com.google.gwt.junit.client.GWTTestCase;
 import com.google.gwt.resources.client.CssResource.Import;
 import com.google.gwt.resources.client.CssResource.ImportedWithPrefix;
+import com.google.gwt.resources.client.CssResource.NotStrict;
 import com.google.gwt.resources.client.CssResource.Shared;
 import com.google.gwt.resources.client.CssResource.Strict;
 
@@ -29,6 +30,7 @@
 
   interface ConcatenatedResources extends ClientBundle {
     @Source(value = {"concatenatedA.css", "concatenatedB.css"})
+    @Strict
     CssResource css();
   }
 
@@ -94,18 +96,22 @@
     Resources INSTANCE = GWT.create(Resources.class);
 
     @Source("siblingTestA.css")
+    @Strict
     MyCssResourceA a();
 
     @Source("siblingTestB.css")
+    @Strict
     MyCssResourceB b();
 
     @Source("test.css")
+    @NotStrict
     MyCssResourceWithSprite css();
 
     @Source("32x32.png")
     DataResource dataMethod();
 
     // Test default extensions
+    @Strict
     CssWithDefines deftest();
 
     @Source("unrelatedDescendants.css")
@@ -131,9 +137,11 @@
 
   interface SiblingResources extends ClientBundle {
     @Source("siblingTestA.css")
+    @Strict
     MyCssResourceA a();
 
     @Source("siblingTestB.css")
+    @Strict
     MyCssResourceB b();
   }
 
diff --git a/user/test/com/google/gwt/resources/client/concatenatedA.css b/user/test/com/google/gwt/resources/client/concatenatedA.css
index 6b1c69e..8754562 100644
--- a/user/test/com/google/gwt/resources/client/concatenatedA.css
+++ b/user/test/com/google/gwt/resources/client/concatenatedA.css
@@ -13,6 +13,9 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
+ 
+ /* Ensure that @external carries over between concatenations. */
+ @external partA partB;
 .partA {
   background: blue;
 }
\ No newline at end of file
diff --git a/user/test/com/google/gwt/resources/client/siblingTestA.css b/user/test/com/google/gwt/resources/client/siblingTestA.css
index 9a6711e..2c8c6f2 100644
--- a/user/test/com/google/gwt/resources/client/siblingTestA.css
+++ b/user/test/com/google/gwt/resources/client/siblingTestA.css
@@ -15,6 +15,7 @@
  */
  
 /* This is the first half of the sibling test. */
+@external other;
 .replacement { background:red; }
 .replacement-not-java-ident {color: blue;}
 .local {background: green; }
diff --git a/user/test/com/google/gwt/resources/client/siblingTestB.css b/user/test/com/google/gwt/resources/client/siblingTestB.css
index 15f05f1..b895842 100644
--- a/user/test/com/google/gwt/resources/client/siblingTestB.css
+++ b/user/test/com/google/gwt/resources/client/siblingTestB.css
@@ -15,6 +15,7 @@
  */
  
 /* This is the other half of the sibling test. */
+@external other;
 .other {background: blue; }
 .replacement-not-java-ident {color: blue;}
 .replacement { background:red; }