Revision: 9968
Author:   unn...@google.com
Date:     Fri Apr  8 11:20:03 2011
Log:      Some small refactors to Css Resource Generation

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

http://code.google.com/p/google-web-toolkit/source/detail?r=9968

Deleted:
 /trunk/user/src/com/google/gwt/resources/client/CssResourceBase.java
 /trunk/user/src/com/google/gwt/resources/rg/CssObfuscationStyle.java
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/rg/CssTestCase.java

=======================================
--- /trunk/user/src/com/google/gwt/resources/client/CssResourceBase.java Thu Apr 7 11:55:26 2011
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2011 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.client;
-
-/**
- * Marker interface for all classes that should be obfuscated together in
- * Css Resource generation.
- * TODO(unnurg): Try to get rid of the global obfuscation scheme and delete
- * this interface.
- */
-public interface CssResourceBase extends ResourcePrototype { }
=======================================
--- /trunk/user/src/com/google/gwt/resources/rg/CssObfuscationStyle.java Thu Apr 7 11:55:26 2011
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2011 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.rg;
-
-import com.google.gwt.core.ext.typeinfo.JClassType;
-
-/**
- * Evaluates the obfuscation style the user selected and formats the obfuscated
- * name accordingly.
- */
-public enum CssObfuscationStyle {
-  VERBOSE (true, false, true, true),
-  STABLE_FULL_CLASSNAME (true, true, true, true),
-  STABLE_SHORT_CLASSNAME (true, true, true, false),
-  STABLE_NO_CLASSNAME (true, true, false, false),
-  OBFUSCATED (false, false, false, false);
-
-  static CssObfuscationStyle getObfuscationStyle(String name) {
-    if (name.equalsIgnoreCase("pretty")) {
-      return VERBOSE;
-    } else if (name.equalsIgnoreCase("stable")) {
-      return STABLE_FULL_CLASSNAME;
-    } else if (name.equalsIgnoreCase("stable-shorttype")) {
-      return STABLE_SHORT_CLASSNAME;
-    } else if (name.equalsIgnoreCase("stable-notype")) {
-      return STABLE_NO_CLASSNAME;
-    }
-    return OBFUSCATED;
-  }
-
-  private boolean isPretty;
-  private boolean isStable;
-  private boolean showClassName;
-  private boolean showPackageName;
-
- CssObfuscationStyle(boolean isPretty, boolean isStable, boolean showClassName,
-      boolean showPackageName) {
-    this.isPretty = isPretty;
-    this.isStable = isStable;
-    this.showClassName = showClassName;
-    this.showPackageName = showPackageName;
-  }
-
- public String getPrettyName(String method, JClassType type, String obfuscatedName) {
-    if (!isPretty()) {
-      return obfuscatedName;
-    }
-    String toReturn = method;
-
-    /*
-     * Note that by dropping the type, or using it's short name, you are
- * allowing name collisions in the css selector names. These options should - * only be used if you are sure that your GWT application is ensuring that
-     * there are no namespace collisions.
-     */
-    if (showClassName) {
-      if (showPackageName) {
- toReturn = type.getQualifiedSourceName().replaceAll("[.$]", "-") + "-" + toReturn;
-      } else {
-        toReturn = type.getName() + "-" + toReturn;
-      }
-    }
-
-    /*
- * For stable styles the obfuscated class name is dropped from the pretty
-     * output. This results in class names that are constant, no matter how
-     * many other selectors are added.
-     */
-    if (!isStable) {
-      toReturn = obfuscatedName += "-" + toReturn;
-    }
-    return toReturn;
-  }
-
-  public boolean isPretty() {
-    return isPretty;
-  }
-}
=======================================
--- /trunk/user/src/com/google/gwt/resources/client/CssResource.java Thu Apr 7 11:55:26 2011 +++ /trunk/user/src/com/google/gwt/resources/client/CssResource.java Fri Apr 8 11:20:03 2011
@@ -148,7 +148,7 @@
  */
 @DefaultExtensions(value = {".css"})
 @ResourceGeneratorType(CssResourceGenerator.class)
-public interface CssResource extends CssResourceBase {
+public interface CssResource extends ResourcePrototype {
   /**
    * The original CSS class name specified in the resource. This allows CSS
    * classes that do not correspond to Java identifiers to be mapped onto
=======================================
--- /trunk/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java Thu Apr 7 11:55:26 2011 +++ /trunk/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java Fri Apr 8 11:20:03 2011
@@ -28,6 +28,7 @@
 import com.google.gwt.core.ext.typeinfo.TypeOracle;
 import com.google.gwt.dev.util.DefaultTextOutput;
 import com.google.gwt.dev.util.Util;
+import com.google.gwt.dom.client.Element;
 import com.google.gwt.dom.client.StyleInjector;
 import com.google.gwt.i18n.client.LocaleInfo;
 import com.google.gwt.resources.client.CssResource;
@@ -36,7 +37,6 @@
 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.CssResourceBase;
 import com.google.gwt.resources.css.ClassRenamer;
 import com.google.gwt.resources.css.CssGenerationVisitor;
 import com.google.gwt.resources.css.DefsCollector;
@@ -245,7 +245,7 @@
    * given node. Visible only for testing.
    */
   static <T extends CssNode & HasNodes> String makeExpression(
-      TreeLogger logger, ResourceContext context,
+ TreeLogger logger, ResourceContext context, JClassType cssResourceType,
       T node, boolean prettyOutput) throws UnableToCompleteException {
     // Generate the CSS template
     DefaultTextOutput out = new DefaultTextOutput(!prettyOutput);
@@ -285,7 +285,7 @@

           // Generate the sub-expressions
           String expression = makeExpression(loopLogger, context,
-              new CollapsedNode(asIf), prettyOutput);
+              cssResourceType, new CollapsedNode(asIf), prettyOutput);

           String elseExpression;
           if (asIf.getElseNodes().isEmpty()) {
@@ -293,7 +293,8 @@
             elseExpression = "\"\"";
           } else {
             elseExpression = makeExpression(loopLogger, context,
-                new CollapsedNode(asIf.getElseNodes()), prettyOutput);
+                cssResourceType, new CollapsedNode(asIf.getElseNodes()),
+                prettyOutput);
           }

           // ((expr) ? "CSS" : "elseCSS") +
@@ -422,29 +423,54 @@
     }
   }

-  protected CssObfuscationStyle obfuscationStyle;
+  protected List<String> ignoredMethods = new ArrayList<String>();
+  protected Map<JMethod, CssStylesheet> stylesheetMap;
   private Counter classCounter;
+  private JClassType cssResourceType;
+  private JClassType elementType;
   private boolean enableMerge;
-  private List<String> ignoredMethods = new ArrayList<String>();
+  private boolean prettyOutput;
private Map<JClassType, Map<JMethod, String>> replacementsByClassAndMethod;
   private Map<JMethod, String> replacementsForSharedMethods;
-  private Map<JMethod, CssStylesheet> stylesheetMap;
+  private JClassType stringType;

   @Override
public String createAssignment(TreeLogger logger, ResourceContext context,
       JMethod method) throws UnableToCompleteException {
+
+    TypeOracle typeOracle = context.getGeneratorContext().getTypeOracle();
+    SourceWriter sw = new StringSourceWriter();
+    // Write the expression to create the subtype.
+    sw.println("new " + method.getReturnType().getQualifiedSourceName()
+        + "() {");
+    sw.indent();
+
     JClassType cssResourceSubtype = method.getReturnType().isInterface();
     assert cssResourceSubtype != null;
-    CssStylesheet stylesheet = stylesheetMap.get(method);
-
-    // Optimize the stylesheet, recording the class selector obfuscations
- Map<JMethod, String> actualReplacements = optimize(logger, context, method);
-
-    outputAdditionalArtifacts(logger, context, method, actualReplacements,
-        cssResourceSubtype, stylesheet);
-
- return getResourceImplAsString(logger, context, method, actualReplacements,
-        cssResourceSubtype, stylesheet);
+
+    // Compute the local effective namespace
+ Map<String, Map<JMethod, String>> replacementsWithPrefix = processImports(
+        logger, typeOracle, cssResourceSubtype, method, context);
+
+    // Methods defined by CssResource interface
+    writeEnsureInjected(sw);
+    writeGetName(method, sw);
+
+    // Create the Java expression that generates the CSS
+    Map<JMethod, String> actualReplacements = writeGetText(logger, context,
+        method, sw, cssResourceSubtype, replacementsWithPrefix);
+
+    /*
+     * getOverridableMethods is used to handle CssResources extending
+ * non-CssResource types. See the discussion in computeReplacementsForType.
+     */
+    writeUserMethods(logger, sw, stylesheetMap.get(method),
+        cssResourceSubtype.getOverridableMethods(), actualReplacements);
+
+    sw.outdent();
+    sw.println("}");
+
+    return sw.toString();
   }

   @Override
@@ -456,9 +482,9 @@
         context.getGeneratorContext().getPropertyOracle();
       ConfigurationProperty styleProp =
         propertyOracle.getConfigurationProperty(KEY_STYLE);
-      obfuscationStyle = CssObfuscationStyle.getObfuscationStyle(
-          styleProp.getValues().get(0));
-
+      String style = styleProp.getValues().get(0);
+      prettyOutput = style.equals("pretty");
+
       ConfigurationProperty mergeProp =
         propertyOracle.getConfigurationProperty(KEY_MERGE_ENABLED);
       String merge = mergeProp.getValues().get(0);
@@ -479,18 +505,16 @@
     }

     TypeOracle typeOracle = context.getGeneratorContext().getTypeOracle();
- JClassType superInterface = typeOracle.findType(getSuperclassInterfaceName()); - JClassType baseInterface = typeOracle.findType(getBaseclassInterfaceName());
-
-    for (JMethod m : superInterface.getInheritableMethods()) {
+    JClassType baseInterface = typeOracle.findType(getBaseInterfaceName());
+    for (JMethod m : baseInterface.getInheritableMethods()) {
       ignoredMethods.add(m.getName());
     }

+    // Find all of the types that we care about in the type system
+    checkTypes(context, typeOracle);
     stylesheetMap = new IdentityHashMap<JMethod, CssStylesheet>();

-    SortedSet<JClassType> cssResourceSubtypes =
-      computeOperableTypes(logger, baseInterface);
-    initReplacements(logger, context, classPrefix, cssResourceSubtypes);
+    initReplacements(logger, context, classPrefix);
   }

   @Override
@@ -503,7 +527,9 @@
       throw new UnableToCompleteException();
     }

-    URL[] resources = getResources(logger, context, method);
+    URL[] resources = ResourceGeneratorUtil.findResources(logger, context,
+        method);
+
     if (resources.length == 0) {
logger.log(TreeLogger.ERROR, "At least one source must be specified");
       throw new UnableToCompleteException();
@@ -511,81 +537,120 @@

     // Create the AST and do a quick scan for requirements
     CssStylesheet sheet = GenerateCssAst.exec(logger, resources);
-    checkSheet(logger, sheet);
     stylesheetMap.put(method, sheet);
(new RequirementsCollector(logger, context.getRequirements())).accept(sheet);
   }
-
-  protected void checkSheet(TreeLogger logger, CssStylesheet stylesheet)
-  throws UnableToCompleteException {
-    // Do nothing
-  }
-
-  /**
-   * Return the name of the class which is at the base of the CssResource
- * generation tree. Since obfuscation is done globally, this should be the - * base class for all resources in the compilation that should be included
-   * in the global obfuscation.
-   */
-  protected String getBaseclassInterfaceName() {
-    return CssResourceBase.class.getCanonicalName();
+
+ protected void checkTypes(ResourceContext context, TypeOracle typeOracle) {
+    cssResourceType = typeOracle.findType(CssResource.class.getName());
+    assert cssResourceType != null;
+
+    elementType = typeOracle.findType(Element.class.getName());
+    assert elementType != null;
+
+    stringType = typeOracle.findType(String.class.getName());
+    assert stringType != null;
+  }
+
+  protected String getBaseInterfaceName() {
+    return CssResource.class.getCanonicalName();
+  }
+
+  protected String makeExpressionForSheet(
+ TreeLogger logger, ResourceContext context, JClassType cssResourceType, + CssStylesheet sheet, boolean prettyOutput) throws UnableToCompleteException { + return makeExpression(logger, context, cssResourceType, sheet, prettyOutput);
   }

- protected String getResourceImplAsString(TreeLogger logger, ResourceContext context,
-      JMethod method, Map<JMethod, String> actualReplacements,
-      JClassType cssResourceSubtype,
-      CssStylesheet stylesheet) throws UnableToCompleteException {
-    SourceWriter sw = new StringSourceWriter();
-    // Write the expression to create the subtype.
-    sw.println("new " + method.getReturnType().getQualifiedSourceName()
-        + "() {");
-    sw.indent();
-
-    // Methods defined by CssResource interface
-    writeEnsureInjected(sw);
-    writeGetName(method, sw);
-
-    // Create the Java expression that generates the CSS
-    writeGetText(logger, context, method, sw);
-
-    // getOverridableMethods is used to handle CssResources extending
- // non-CssResource types. See the discussion in computeReplacementsForType.
-    writeUserMethods(logger, sw, stylesheet,
-        cssResourceSubtype.getOverridableMethods(), actualReplacements);
-
-    sw.outdent();
-    sw.println("}");
-
-    return sw.toString();
-  }
-
-  protected URL[] getResources(TreeLogger logger, ResourceContext context,
-      JMethod method) throws UnableToCompleteException {
-    return ResourceGeneratorUtil.findResources(logger, context, method);
+  protected void optimize(TreeLogger logger, ResourceContext context,
+      JMethod method,
+      Map<String, Map<JMethod, String>> classReplacementsWithPrefix,
+      Map<JMethod, String> actualReplacements) {
+    boolean strict = isStrict(logger, method);
+    CssStylesheet sheet = stylesheetMap.get(method);
+
+    // Create CSS sprites
+    (new Spriter(logger, context)).accept(sheet);
+
+    // Perform @def and @eval substitutions
+    SubstitutionCollector collector = new SubstitutionCollector();
+    collector.accept(sheet);
+
+ (new SubstitutionReplacer(logger, context, collector.getSubstitutions()))
+    .accept(sheet);
+
+    // Evaluate @if statements based on deferred binding properties
+    (new IfEvaluator(logger,
+        context.getGeneratorContext().getPropertyOracle())).accept(sheet);
+
+ // Rename css .class selectors. We look for all @external declarations in
+    // the stylesheet and then compute the per-instance replacements.
+ ExternalClassesCollector externalClasses = new ExternalClassesCollector();
+    externalClasses.accept(sheet);
+    ClassRenamer renamer = new ClassRenamer(logger,
+        classReplacementsWithPrefix, strict, externalClasses.getClasses());
+    renamer.accept(sheet);
+    actualReplacements.putAll(renamer.getReplacements());
+
+    // Combine rules with identical selectors
+    if (enableMerge) {
+      (new SplitRulesVisitor()).accept(sheet);
+      (new MergeIdenticalSelectorsVisitor()).accept(sheet);
+      (new MergeRulesByContentVisitor()).accept(sheet);
+    }
   }

   /**
-   * Return the name of the class which is the direct superclass of the
-   * interface being implemented.
+ * Process the Import annotation on the associated JMethod and return a map of
+   * prefixes to JMethods to locally obfuscated names.
    */
-  protected String getSuperclassInterfaceName() {
-    return CssResource.class.getCanonicalName();
-  }
-
-  /**
- * Output additional artifacts. Does nothing in this baseclass, but is a hook
-   * for subclasses to do so.
-   */
-  protected void outputAdditionalArtifacts(TreeLogger logger,
-      ResourceContext context, JMethod method,
- Map<JMethod, String> actualReplacements, JClassType cssResourceSubtype,
-      CssStylesheet stylesheet) throws UnableToCompleteException {
+ protected Map<String, Map<JMethod, String>> processImports(TreeLogger logger,
+      TypeOracle typeOracle, JClassType cssResourceSubtype, JMethod method,
+      ResourceContext context)
+      throws UnableToCompleteException {
+    Map<String, Map<JMethod, String>> replacementsWithPrefix =
+      new HashMap<String, Map<JMethod, String>>();
+
+    replacementsWithPrefix.put("",
+        computeReplacementsForType(cssResourceSubtype));
+    Import imp = method.getAnnotation(Import.class);
+    if (imp != null) {
+      boolean fail = false;
+      for (Class<? extends CssResource> clazz : imp.value()) {
+ JClassType importType = typeOracle.findType(clazz.getName().replace(
+            '$', '.'));
+        assert importType != null : "TypeOracle does not have type "
+            + clazz.getName();
+
+        // add this import type as a requirement for this generator
+        context.getRequirements().addTypeHierarchy(importType);
+
+        String prefix = getImportPrefix(importType);
+
+        if (replacementsWithPrefix.put(prefix,
+            computeReplacementsForType(importType)) != null) {
+          logger.log(TreeLogger.ERROR,
+              "Multiple imports that would use the prefix " + prefix);
+          fail = true;
+        }
+      }
+      if (fail) {
+        throw new UnableToCompleteException();
+      }
+    }
+    return replacementsWithPrefix;
   }

-  protected void writeGetName(JMethod method, SourceWriter sw) {
-    sw.println("public String getName() {");
+  protected void writeEnsureInjected(SourceWriter sw) {
+    sw.println("private boolean injected;");
+    sw.println("public boolean ensureInjected() {");
     sw.indent();
-    sw.println("return \"" + method.getName() + "\";");
+    sw.println("if (!injected) {");
+    sw.indentln("injected = true;");
+    sw.indentln(StyleInjector.class.getName() + ".inject(getText());");
+    sw.indentln("return true;");
+    sw.println("}");
+    sw.println("return false;");
     sw.outdent();
     sw.println("}");
   }
@@ -619,8 +684,7 @@
       if (defs.contains(toImplement.getName())
           && toImplement.getParameters().length == 0) {
         writeDefAssignment(logger, sw, toImplement, sheet);
-      } else if (toImplement.getReturnType().getQualifiedSourceName()
-          .equals("java.lang.String")
+      } else if (toImplement.getReturnType().equals(stringType)
           && toImplement.getParameters().length == 0) {
         writeClassAssignment(sw, toImplement, obfuscatedClassNames);
       } else {
@@ -630,7 +694,6 @@
       }
     }
   }
-

   /**
* Determine the class prefix that will be used. If a value is automatically
@@ -700,16 +763,14 @@
           name = classNameOverride.value();
         }

-        /*
-         * Short name, based off a counter that is shared by all of the
-         * obfuscated css names in this compile.
-         */
String obfuscatedClassName = computeObfuscatedClassName(classPrefix,
             classCounter, reservedPrefixes);
-
-        // Modify the name based on the obfuscation style requested
-        obfuscatedClassName = obfuscationStyle.getPrettyName(name, type,
-              obfuscatedClassName);
+
+        if (prettyOutput) {
+          obfuscatedClassName += "-"
+              + type.getQualifiedSourceName().replaceAll("[.$]", "-") + "-"
+              + name;
+        }

         replacements.put(method, obfuscatedClassName);

@@ -741,15 +802,14 @@
* there is presently no way to determine when, or by what means, a type was
    * added to the TypeOracle.
    */
-  private SortedSet<JClassType> computeOperableTypes(TreeLogger logger,
-      JClassType baseInterface) {
+  private SortedSet<JClassType> computeOperableTypes(TreeLogger logger) {
     logger = logger.branch(TreeLogger.DEBUG,
         "Finding operable CssResource subtypes");

     SortedSet<JClassType> toReturn = new TreeSet<JClassType>(
         new JClassOrderComparator());

-    JClassType[] cssResourceSubtypes = baseInterface.getSubtypes();
+    JClassType[] cssResourceSubtypes = cssResourceType.getSubtypes();
     for (JClassType type : cssResourceSubtypes) {
       if (type.isInterface() != null) {
logger.log(TreeLogger.SPAM, "Added " + type.getQualifiedSourceName());
@@ -770,6 +830,16 @@
    */
private Map<JMethod, String> computeReplacementsForType(JClassType type) {
     Map<JMethod, String> toReturn = new IdentityHashMap<JMethod, String>();
+
+    /*
+ * We check to see if the type is derived from CssResource so that we can
+     * handle the case of a CssResource type being derived from a
+ * non-CssResource base type. This basically collapses the non-CssResource
+     * base types into their least-derived CssResource subtypes.
+     */
+    if (type == null || !derivedFromCssResource(type)) {
+      return toReturn;
+    }

     if (replacementsByClassAndMethod.containsKey(type)) {
       toReturn.putAll(replacementsByClassAndMethod.get(type));
@@ -788,11 +858,11 @@

     return toReturn;
   }
-
+
   /**
    * Determine if a type is derived from CssResource.
    */
- private boolean derivedFromCssResource(JClassType type, JClassType cssResourceType) {
+  private boolean derivedFromCssResource(JClassType type) {
List<JClassType> superInterfaces = Arrays.asList(type.getImplementedInterfaces());
     if (superInterfaces.contains(cssResourceType)) {
       return true;
@@ -800,13 +870,13 @@

     JClassType superClass = type.getSuperclass();
     if (superClass != null) {
-      if (derivedFromCssResource(superClass, cssResourceType)) {
+      if (derivedFromCssResource(superClass)) {
         return true;
       }
     }

     for (JClassType superInterface : superInterfaces) {
-      if (derivedFromCssResource(superInterface, cssResourceType)) {
+      if (derivedFromCssResource(superInterface)) {
         return true;
       }
     }
@@ -819,7 +889,7 @@
    */
   @SuppressWarnings("unchecked")
   private void initReplacements(TreeLogger logger, ResourceContext context,
-      String classPrefix, SortedSet<JClassType> operableTypes) {
+      String classPrefix) {
     /*
      * This code was originally written to take a snapshot of all the
* CssResource descendants in the TypeOracle on its first run and calculate
@@ -833,7 +903,9 @@
* so the old gymnastics aren't really justified anyway. It would probably
      * be be worth the effort to simplify this.
      */
-
+
+ SortedSet<JClassType> cssResourceSubtypes = computeOperableTypes(logger);
+
if (context.getCachedData(KEY_HAS_CACHED_DATA, Boolean.class) != Boolean.TRUE) {

       ConfigurationProperty prop;
@@ -865,7 +937,7 @@
       }

       String computedPrefix = computeClassPrefix(classPrefix,
-          operableTypes, reservedPrefixes);
+          cssResourceSubtypes, reservedPrefixes);

       context.putCachedData(KEY_BY_CLASS_AND_METHOD,
           new IdentityHashMap<JClassType, Map<JMethod, String>>());
@@ -888,7 +960,7 @@
         KEY_RESERVED_PREFIXES, SortedSet.class);

     computeObfuscatedNames(logger, classPrefix, reservedPrefixes,
-        operableTypes);
+        cssResourceSubtypes);
   }

   /**
@@ -928,12 +1000,20 @@
    *          modifications encoded in the source CSS file
    */
   private String makeExpression(TreeLogger logger, ResourceContext context,
-      CssStylesheet sheet)
+      JClassType cssResourceType, CssStylesheet sheet,
+      Map<String, Map<JMethod, String>> classReplacementsWithPrefix,
+      JMethod method, Map<JMethod, String> actualReplacements)
       throws UnableToCompleteException {
+
     try {
- String standard = makeExpression(logger, context, sheet, obfuscationStyle.isPretty());
+      optimize(logger, context, method, classReplacementsWithPrefix,
+          actualReplacements);
+
+ String standard = makeExpressionForSheet(logger, context, cssResourceType,
+          sheet, prettyOutput);
       (new RtlVisitor()).accept(sheet);
- String reversed = makeExpression(logger, context, sheet, obfuscationStyle.isPretty()); + String reversed = makeExpressionForSheet(logger, context, cssResourceType,
+          sheet, prettyOutput);

       if (standard.equals(reversed)) {
         return standard;
@@ -949,97 +1029,6 @@
       throw new UnableToCompleteException();
     }
   }
-
-  private Map<JMethod, String> optimize(TreeLogger logger,
- ResourceContext context, JMethod method) throws UnableToCompleteException {
-
-    TypeOracle typeOracle = context.getGeneratorContext().getTypeOracle();
-    JClassType cssResourceSubtype = method.getReturnType().isInterface();
-    assert cssResourceSubtype != null;
-    assert derivedFromCssResource(cssResourceSubtype,
-        typeOracle.findType(getBaseclassInterfaceName()));
-
-    // Compute the local effective namespace
- Map<String, Map<JMethod, String>> classReplacementsWithPrefix = processImports(
-        logger, typeOracle, cssResourceSubtype, method, context);
-
-    boolean strict = isStrict(logger, method);
-    CssStylesheet sheet = stylesheetMap.get(method);
-
-    // Create CSS sprites
-    (new Spriter(logger, context)).accept(sheet);
-
-    // Perform @def and @eval substitutions
-    SubstitutionCollector collector = new SubstitutionCollector();
-    collector.accept(sheet);
-
- (new SubstitutionReplacer(logger, context, collector.getSubstitutions()))
-    .accept(sheet);
-
-    // Evaluate @if statements based on deferred binding properties
-    (new IfEvaluator(logger,
-        context.getGeneratorContext().getPropertyOracle())).accept(sheet);
-
- // Rename css .class selectors. We look for all @external declarations in
-    // the stylesheet and then compute the per-instance replacements.
- ExternalClassesCollector externalClasses = new ExternalClassesCollector();
-    externalClasses.accept(sheet);
-    ClassRenamer renamer = new ClassRenamer(logger,
-        classReplacementsWithPrefix, strict, externalClasses.getClasses());
-    renamer.accept(sheet);
- Map<JMethod, String> actualReplacements = new HashMap<JMethod, String>();
-    actualReplacements.putAll(renamer.getReplacements());
-
-    // Combine rules with identical selectors
-    if (enableMerge) {
-      (new SplitRulesVisitor()).accept(sheet);
-      (new MergeIdenticalSelectorsVisitor()).accept(sheet);
-      (new MergeRulesByContentVisitor()).accept(sheet);
-    }
-
-    return actualReplacements;
-  }
-
-  /**
- * Process the Import annotation on the associated JMethod and return a map of
-   * prefixes to JMethods to locally obfuscated names.
-   */
- private Map<String, Map<JMethod, String>> processImports(TreeLogger logger,
-      TypeOracle typeOracle, JClassType cssResourceSubtype, JMethod method,
-      ResourceContext context)
-      throws UnableToCompleteException {
-    Map<String, Map<JMethod, String>> replacementsWithPrefix =
-      new HashMap<String, Map<JMethod, String>>();
-
-    replacementsWithPrefix.put("",
-        computeReplacementsForType(cssResourceSubtype));
-    Import imp = method.getAnnotation(Import.class);
-    if (imp != null) {
-      boolean fail = false;
-      for (Class<? extends CssResource> clazz : imp.value()) {
- JClassType importType = typeOracle.findType(clazz.getName().replace(
-            '$', '.'));
-        assert importType != null : "TypeOracle does not have type "
-            + clazz.getName();
-
-        // add this import type as a requirement for this generator
-        context.getRequirements().addTypeHierarchy(importType);
-
-        String prefix = getImportPrefix(importType);
-
-        if (replacementsWithPrefix.put(prefix,
-            computeReplacementsForType(importType)) != null) {
-          logger.log(TreeLogger.ERROR,
-              "Multiple imports that would use the prefix " + prefix);
-          fail = true;
-        }
-      }
-      if (fail) {
-        throw new UnableToCompleteException();
-      }
-    }
-    return replacementsWithPrefix;
-  }

   /**
    * Write the CssResource accessor method for simple String return values.
@@ -1118,29 +1107,28 @@
     sw.println("}");
   }

-  private void writeEnsureInjected(SourceWriter sw) {
-    sw.println("private boolean injected;");
-    sw.println("public boolean ensureInjected() {");
+  private void writeGetName(JMethod method, SourceWriter sw) {
+    sw.println("public String getName() {");
     sw.indent();
-    sw.println("if (!injected) {");
-    sw.indentln("injected = true;");
-    sw.indentln(StyleInjector.class.getName() + ".inject(getText());");
-    sw.indentln("return true;");
-    sw.println("}");
-    sw.println("return false;");
+    sw.println("return \"" + method.getName() + "\";");
     sw.outdent();
     sw.println("}");
   }

-  private void writeGetText(TreeLogger logger,
-      ResourceContext context, JMethod method, SourceWriter sw)
+  private Map<JMethod, String> writeGetText(TreeLogger logger,
+      ResourceContext context, JMethod method, SourceWriter sw,
+      JClassType cssResourceSubtype,
+      Map<String, Map<JMethod, String>> replacementsWithPrefix)
       throws UnableToCompleteException {
     sw.println("public String getText() {");
     sw.indent();
-    String cssExpression = makeExpression(logger, context,
-        stylesheetMap.get(method));
+ Map<JMethod, String> actualReplacements = new IdentityHashMap<JMethod, String>(); + String cssExpression = makeExpression(logger, context, cssResourceSubtype,
+        stylesheetMap.get(method), replacementsWithPrefix, method,
+        actualReplacements);
     sw.println("return " + cssExpression + ";");
     sw.outdent();
     sw.println("}");
+    return actualReplacements;
   }
 }
=======================================
--- /trunk/user/test/com/google/gwt/resources/rg/CssTestCase.java Thu Apr 7 11:55:26 2011 +++ /trunk/user/test/com/google/gwt/resources/rg/CssTestCase.java Fri Apr 8 11:20:03 2011
@@ -131,9 +131,9 @@
   protected static <T extends CssNode & HasNodes> void assertEquals(
TreeLogger logger, T expected, T test) throws UnableToCompleteException {
     String expectedCss = CssResourceGenerator.makeExpression(logger,
-        new FakeContext(), expected, false);
+        new FakeContext(), null, expected, false);
     String testCss = CssResourceGenerator.makeExpression(logger,
-        new FakeContext(), test, false);
+        new FakeContext(), null, test, false);
     assertEquals(expectedCss, testCss);
   }

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

Reply via email to