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);
}