/* * 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.common.css.compiler.passes; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import com.google.common.css.compiler.ast.CssBlockNode; import com.google.common.css.compiler.ast.CssCommentNode; import com.google.common.css.compiler.ast.CssDeclarationBlockNode; import com.google.common.css.compiler.ast.CssNode; import com.google.common.css.compiler.ast.CssRootNode; import com.google.common.css.compiler.ast.CssRulesetNode; import com.google.common.css.compiler.ast.CssSelectorListNode; import com.google.common.css.compiler.ast.CssSelectorNode; import com.google.common.css.compiler.ast.CssTree; import java.util.List; /** * Utility methods that can be useful for compiler passes. * * @author fbenz@google.com (Florian Benz) */ public class PassUtil { /** * Annotation to explicitly state that several consecutive declarations are * alternatives and it should be left up to the user agent to interpret * whichever is appropriate. The annotation excludes the declarations from * being treated as redundant. */ @VisibleForTesting public static final String ALTERNATE = "/* @alternate */"; /** * Prints a selector including the combinators and refiners but without * a block behind with the compact printer. */ public static String printSelector(CssSelectorNode selector) { CssTree t = createTreeWithSelector(selector); // Print the whole tree. String selectorString = compactPrintTree(t); // As the whole tree is printed, the output is the selector with an empty // declaration block (e.g. 'foo{}'). The two curly brackets are removed so // that only the selector remains. return selectorString.substring(0, selectorString.length() - 2); } /** * Prints a list of selector including the combinators and refiners but * without a block behind with the compact printer. */ public static String printSelectorList(CssSelectorListNode selectorList) { CssTree t = createTreeWithSelectorList(selectorList); // Print the whole tree. String selectorListString = compactPrintTree(t); // As the whole tree is printed, the output is the selector with an empty // declaration block (e.g. 'foo{}'). The two curly brackets are removed so // that only the selector remains. return selectorListString.substring(0, selectorListString.length() - 2); } /** * Prints a selector including the combinators and refiners but without * a block behind with the pretty printer. */ public static String prettyPrintSelector(CssSelectorNode selector) { CssTree t = createTreeWithSelector(selector); // Print the whole tree. PrettyPrinter prettyPrinter = new PrettyPrinter(t.getVisitController()); prettyPrinter.runPass(); String selectorString = prettyPrinter.getPrettyPrintedString(); // As the whole tree is printed, the output is the selector with an empty // declaration block (e.g. 'foo {\n}\n'). The two curly brackets are removed so // that only the selector remains. int index = selectorString.indexOf('{'); return selectorString.substring(0, index - 1); } private static CssTree createTreeWithSelector(CssSelectorNode selector) { // Create tree with only this selector. CssDeclarationBlockNode declarations = new CssDeclarationBlockNode(); CssRulesetNode rulesetNode = new CssRulesetNode(declarations); rulesetNode.addSelector(selector); return createTreeWithRuleset(rulesetNode); } private static CssTree createTreeWithSelectorList( CssSelectorListNode selectorList) { CssDeclarationBlockNode declarations = new CssDeclarationBlockNode(); CssRulesetNode rulesetNode = new CssRulesetNode(declarations); rulesetNode.setSelectors(selectorList); return createTreeWithRuleset(rulesetNode); } private static CssTree createTreeWithRuleset(CssRulesetNode rulesetNode) { List<CssNode> blockChildren = ImmutableList.of((CssNode) rulesetNode); CssBlockNode block = new CssBlockNode(false, blockChildren); CssRootNode root = new CssRootNode(block); return new CssTree(null, root); } private static String compactPrintTree(CssTree tree) { CompactPrinter compactPrinter = new CompactPrinter(tree); compactPrinter.runPass(); return compactPrinter.getCompactPrintedString(); } /** * Returns whether the ALTERNATE comment has been found among the comments of * the node. */ public static boolean hasAlternateAnnotation(CssNode node) { for (CssCommentNode comment : node.getComments()) { if (comment.getValue().equals(ALTERNATE)) { return true; } } return false; } }