Some small refactors to Css Resource Generation Review at http://gwt-code-reviews.appspot.com/1406802 git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9968 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 c55cb20..1578095 100644 --- a/user/src/com/google/gwt/resources/client/CssResource.java +++ b/user/src/com/google/gwt/resources/client/CssResource.java
@@ -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
diff --git a/user/src/com/google/gwt/resources/client/CssResourceBase.java b/user/src/com/google/gwt/resources/client/CssResourceBase.java deleted file mode 100644 index 49f17a4..0000000 --- a/user/src/com/google/gwt/resources/client/CssResourceBase.java +++ /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 { }
diff --git a/user/src/com/google/gwt/resources/rg/CssObfuscationStyle.java b/user/src/com/google/gwt/resources/rg/CssObfuscationStyle.java deleted file mode 100644 index fc582ae..0000000 --- a/user/src/com/google/gwt/resources/rg/CssObfuscationStyle.java +++ /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; - } -}
diff --git a/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java b/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java index fd44dbf..0a30503 100644 --- a/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java +++ b/user/src/com/google/gwt/resources/rg/CssResourceGenerator.java
@@ -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 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 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 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); - } - - /** - * Return the name of the class which is the direct superclass of the - * interface being implemented. - */ - protected String getSuperclassInterfaceName() { + protected String getBaseInterfaceName() { 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 String makeExpressionForSheet( + TreeLogger logger, ResourceContext context, JClassType cssResourceType, + CssStylesheet sheet, boolean prettyOutput) throws UnableToCompleteException { + return makeExpression(logger, context, cssResourceType, sheet, prettyOutput); } - protected void writeGetName(JMethod method, SourceWriter sw) { - sw.println("public String getName() {"); + 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); + } + } + + /** + * Process the Import annotation on the associated JMethod and return a map of + * prefixes to JMethods to locally obfuscated names. + */ + 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 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 { @@ -631,7 +695,6 @@ } } - /** * Determine the class prefix that will be used. If a value is automatically * computed, the <code>reservedPrefixes</code> set will be cleared because the @@ -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()); @@ -771,6 +831,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; @@ -950,97 +1030,6 @@ } } - 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; } }
diff --git a/user/test/com/google/gwt/resources/rg/CssTestCase.java b/user/test/com/google/gwt/resources/rg/CssTestCase.java index 9ad51c2..6b46164 100644 --- a/user/test/com/google/gwt/resources/rg/CssTestCase.java +++ b/user/test/com/google/gwt/resources/rg/CssTestCase.java
@@ -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); }