blob: 0d184006b737b51c2997d11d06cdb51baa50502f [file] [log] [blame]
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of '../visitor.dart';
// TODO(terry): Enable class for debug only; when conditional imports enabled.
/// Helper function to dump the CSS AST.
String treeToDebugString(StyleSheet styleSheet, [bool useSpan = false]) {
var to = TreeOutput();
_TreePrinter(to, useSpan).visitTree(styleSheet);
return to.toString();
}
/// Tree dump for debug output of the CSS AST.
class _TreePrinter extends Visitor {
final TreeOutput output;
final bool useSpan;
_TreePrinter(this.output, this.useSpan) {
output.printer = this;
}
@override
void visitTree(StyleSheet tree) => visitStylesheet(tree);
void heading(String heading, node) {
if (useSpan) {
output.heading(heading, node.span);
} else {
output.heading(heading);
}
}
void visitStylesheet(StyleSheet node) {
heading('Stylesheet', node);
output.depth++;
super.visitStyleSheet(node);
output.depth--;
}
@override
void visitTopLevelProduction(TopLevelProduction node) {
heading('TopLevelProduction', node);
}
@override
void visitDirective(Directive node) {
heading('Directive', node);
}
@override
void visitCalcTerm(CalcTerm node) {
heading('CalcTerm', node);
output.depth++;
super.visitCalcTerm(node);
output.depth--;
}
@override
void visitCssComment(CssComment node) {
heading('Comment', node);
output.depth++;
output.writeValue('comment value', node.comment);
output.depth--;
}
@override
void visitCommentDefinition(CommentDefinition node) {
heading('CommentDefinition (CDO/CDC)', node);
output.depth++;
output.writeValue('comment value', node.comment);
output.depth--;
}
@override
void visitMediaExpression(MediaExpression node) {
heading('MediaExpression', node);
output.writeValue('feature', node.mediaFeature);
if (node.andOperator) output.writeValue('AND operator', '');
visitExpressions(node.exprs);
}
void visitMediaQueries(MediaQuery query) {
output.heading('MediaQueries');
output.writeValue('unary', query.unary);
output.writeValue('media type', query.mediaType);
output.writeNodeList('media expressions', query.expressions);
}
@override
void visitMediaDirective(MediaDirective node) {
heading('MediaDirective', node);
output.depth++;
output.writeNodeList('media queries', node.mediaQueries);
output.writeNodeList('rule sets', node.rules);
super.visitMediaDirective(node);
output.depth--;
}
@override
void visitDocumentDirective(DocumentDirective node) {
heading('DocumentDirective', node);
output.depth++;
output.writeNodeList('functions', node.functions);
output.writeNodeList('group rule body', node.groupRuleBody);
output.depth--;
}
@override
void visitSupportsDirective(SupportsDirective node) {
heading('SupportsDirective', node);
output.depth++;
output.writeNode('condition', node.condition);
output.writeNodeList('group rule body', node.groupRuleBody);
output.depth--;
}
@override
void visitSupportsConditionInParens(SupportsConditionInParens node) {
heading('SupportsConditionInParens', node);
output.depth++;
output.writeNode('condition', node.condition);
output.depth--;
}
@override
void visitSupportsNegation(SupportsNegation node) {
heading('SupportsNegation', node);
output.depth++;
output.writeNode('condition', node.condition);
output.depth--;
}
@override
void visitSupportsConjunction(SupportsConjunction node) {
heading('SupportsConjunction', node);
output.depth++;
output.writeNodeList('conditions', node.conditions);
output.depth--;
}
@override
void visitSupportsDisjunction(SupportsDisjunction node) {
heading('SupportsDisjunction', node);
output.depth++;
output.writeNodeList('conditions', node.conditions);
output.depth--;
}
@override
void visitViewportDirective(ViewportDirective node) {
heading('ViewportDirective', node);
output.depth++;
super.visitViewportDirective(node);
output.depth--;
}
@override
void visitPageDirective(PageDirective node) {
heading('PageDirective', node);
output.depth++;
output.writeValue('pseudo page', node._pseudoPage);
super.visitPageDirective(node);
output.depth;
}
@override
void visitCharsetDirective(CharsetDirective node) {
heading('Charset Directive', node);
output.writeValue('charset encoding', node.charEncoding);
}
@override
void visitImportDirective(ImportDirective node) {
heading('ImportDirective', node);
output.depth++;
output.writeValue('import', node.import);
super.visitImportDirective(node);
output.writeNodeList('media', node.mediaQueries);
output.depth--;
}
@override
void visitContentDirective(ContentDirective node) {
print('ContentDirective not implemented');
}
@override
void visitKeyFrameDirective(KeyFrameDirective node) {
heading('KeyFrameDirective', node);
output.depth++;
output.writeValue('keyframe', node.keyFrameName);
output.writeValue('name', node.name);
output.writeNodeList('blocks', node._blocks);
output.depth--;
}
@override
void visitKeyFrameBlock(KeyFrameBlock node) {
heading('KeyFrameBlock', node);
output.depth++;
super.visitKeyFrameBlock(node);
output.depth--;
}
@override
void visitFontFaceDirective(FontFaceDirective node) {
// TODO(terry): To Be Implemented
}
@override
void visitStyletDirective(StyletDirective node) {
heading('StyletDirective', node);
output.writeValue('dartClassName', node.dartClassName);
output.depth++;
output.writeNodeList('rulesets', node.rules);
output.depth--;
}
@override
void visitNamespaceDirective(NamespaceDirective node) {
heading('NamespaceDirective', node);
output.depth++;
output.writeValue('prefix', node._prefix);
output.writeValue('uri', node._uri);
output.depth--;
}
@override
void visitVarDefinitionDirective(VarDefinitionDirective node) {
heading('Less variable definition', node);
output.depth++;
visitVarDefinition(node.def);
output.depth--;
}
@override
void visitMixinRulesetDirective(MixinRulesetDirective node) {
heading('Mixin top-level ${node.name}', node);
output.writeNodeList('parameters', node.definedArgs);
output.depth++;
_visitNodeList(node.rulesets);
output.depth--;
}
@override
void visitMixinDeclarationDirective(MixinDeclarationDirective node) {
heading('Mixin declaration ${node.name}', node);
output.writeNodeList('parameters', node.definedArgs);
output.depth++;
visitDeclarationGroup(node.declarations);
output.depth--;
}
/// Added optional newLine for handling @include at top-level vs/ inside of
/// a declaration group.
@override
void visitIncludeDirective(IncludeDirective node) {
heading('IncludeDirective ${node.name}', node);
var flattened = node.args.expand((e) => e).toList();
output.writeNodeList('parameters', flattened);
}
@override
void visitIncludeMixinAtDeclaration(IncludeMixinAtDeclaration node) {
heading('IncludeMixinAtDeclaration ${node.include.name}', node);
output.depth++;
visitIncludeDirective(node.include);
output.depth--;
}
@override
void visitExtendDeclaration(ExtendDeclaration node) {
heading('ExtendDeclaration', node);
output.depth++;
_visitNodeList(node.selectors);
output.depth--;
}
@override
void visitRuleSet(RuleSet node) {
heading('Ruleset', node);
output.depth++;
super.visitRuleSet(node);
output.depth--;
}
@override
void visitDeclarationGroup(DeclarationGroup node) {
heading('DeclarationGroup', node);
output.depth++;
output.writeNodeList('declarations', node.declarations);
output.depth--;
}
@override
void visitMarginGroup(MarginGroup node) {
heading('MarginGroup', node);
output.depth++;
output.writeValue('@directive', node.margin_sym);
output.writeNodeList('declarations', node.declarations);
output.depth--;
}
@override
void visitDeclaration(Declaration node) {
heading('Declaration', node);
output.depth++;
if (node.isIE7) output.write('IE7 property');
output.write('property');
super.visitDeclaration(node);
output.writeNode('expression', node.expression);
if (node.important) {
output.writeValue('!important', 'true');
}
output.depth--;
}
@override
void visitVarDefinition(VarDefinition node) {
heading('Var', node);
output.depth++;
output.write('defintion');
super.visitVarDefinition(node);
output.writeNode('expression', node.expression);
output.depth--;
}
@override
void visitSelectorGroup(SelectorGroup node) {
heading('Selector Group', node);
output.depth++;
output.writeNodeList('selectors', node.selectors);
output.depth--;
}
@override
void visitSelector(Selector node) {
heading('Selector', node);
output.depth++;
output.writeNodeList(
'simpleSelectorsSequences', node.simpleSelectorSequences);
output.depth--;
}
@override
void visitSimpleSelectorSequence(SimpleSelectorSequence node) {
heading('SimpleSelectorSequence', node);
output.depth++;
if (node.isCombinatorNone) {
output.writeValue('combinator', 'NONE');
} else if (node.isCombinatorDescendant) {
output.writeValue('combinator', 'descendant');
} else if (node.isCombinatorPlus) {
output.writeValue('combinator', '+');
} else if (node.isCombinatorGreater) {
output.writeValue('combinator', '>');
} else if (node.isCombinatorTilde) {
output.writeValue('combinator', '~');
} else {
output.writeValue('combinator', 'ERROR UNKNOWN');
}
super.visitSimpleSelectorSequence(node);
output.depth--;
}
@override
void visitNamespaceSelector(NamespaceSelector node) {
heading('Namespace Selector', node);
output.depth++;
super.visitNamespaceSelector(node);
visitSimpleSelector(node.nameAsSimpleSelector!);
output.depth--;
}
@override
void visitElementSelector(ElementSelector node) {
heading('Element Selector', node);
output.depth++;
super.visitElementSelector(node);
output.depth--;
}
@override
void visitAttributeSelector(AttributeSelector node) {
heading('AttributeSelector', node);
output.depth++;
super.visitAttributeSelector(node);
var tokenStr = node.matchOperatorAsTokenString();
output.writeValue('operator', '${node.matchOperator()} ($tokenStr)');
output.writeValue('value', node.valueToString());
output.depth--;
}
@override
void visitIdSelector(IdSelector node) {
heading('Id Selector', node);
output.depth++;
super.visitIdSelector(node);
output.depth--;
}
@override
void visitClassSelector(ClassSelector node) {
heading('Class Selector', node);
output.depth++;
super.visitClassSelector(node);
output.depth--;
}
@override
void visitPseudoClassSelector(PseudoClassSelector node) {
heading('Pseudo Class Selector', node);
output.depth++;
super.visitPseudoClassSelector(node);
output.depth--;
}
@override
void visitPseudoElementSelector(PseudoElementSelector node) {
heading('Pseudo Element Selector', node);
output.depth++;
super.visitPseudoElementSelector(node);
output.depth--;
}
@override
void visitPseudoClassFunctionSelector(PseudoClassFunctionSelector node) {
heading('Pseudo Class Function Selector', node);
output.depth++;
node.argument.visit(this);
super.visitPseudoClassFunctionSelector(node);
output.depth--;
}
@override
void visitPseudoElementFunctionSelector(PseudoElementFunctionSelector node) {
heading('Pseudo Element Function Selector', node);
output.depth++;
visitSelectorExpression(node.expression);
super.visitPseudoElementFunctionSelector(node);
output.depth--;
}
@override
void visitSelectorExpression(SelectorExpression node) {
heading('Selector Expression', node);
output.depth++;
output.writeNodeList('expressions', node.expressions);
output.depth--;
}
@override
void visitNegationSelector(NegationSelector node) {
super.visitNegationSelector(node);
output.depth++;
heading('Negation Selector', node);
output.writeNode('Negation arg', node.negationArg);
output.depth--;
}
@override
void visitUnicodeRangeTerm(UnicodeRangeTerm node) {
heading('UnicodeRangeTerm', node);
output.depth++;
output.writeValue('1st value', node.first);
output.writeValue('2nd value', node.second);
output.depth--;
}
@override
void visitLiteralTerm(LiteralTerm node) {
heading('LiteralTerm', node);
output.depth++;
output.writeValue('value', node.text);
output.depth--;
}
@override
void visitHexColorTerm(HexColorTerm node) {
heading('HexColorTerm', node);
output.depth++;
output.writeValue('hex value', node.text);
output.writeValue('decimal value', node.value);
output.depth--;
}
@override
void visitNumberTerm(NumberTerm node) {
heading('NumberTerm', node);
output.depth++;
output.writeValue('value', node.text);
output.depth--;
}
@override
void visitUnitTerm(UnitTerm node) {
output.depth++;
output.writeValue('value', node.text);
output.writeValue('unit', node.unitToString());
output.depth--;
}
@override
void visitLengthTerm(LengthTerm node) {
heading('LengthTerm', node);
super.visitLengthTerm(node);
}
@override
void visitPercentageTerm(PercentageTerm node) {
heading('PercentageTerm', node);
output.depth++;
super.visitPercentageTerm(node);
output.depth--;
}
@override
void visitEmTerm(EmTerm node) {
heading('EmTerm', node);
output.depth++;
super.visitEmTerm(node);
output.depth--;
}
@override
void visitExTerm(ExTerm node) {
heading('ExTerm', node);
output.depth++;
super.visitExTerm(node);
output.depth--;
}
@override
void visitAngleTerm(AngleTerm node) {
heading('AngleTerm', node);
super.visitAngleTerm(node);
}
@override
void visitTimeTerm(TimeTerm node) {
heading('TimeTerm', node);
super.visitTimeTerm(node);
}
@override
void visitFreqTerm(FreqTerm node) {
heading('FreqTerm', node);
super.visitFreqTerm(node);
}
@override
void visitFractionTerm(FractionTerm node) {
heading('FractionTerm', node);
output.depth++;
super.visitFractionTerm(node);
output.depth--;
}
@override
void visitUriTerm(UriTerm node) {
heading('UriTerm', node);
output.depth++;
super.visitUriTerm(node);
output.depth--;
}
@override
void visitFunctionTerm(FunctionTerm node) {
heading('FunctionTerm', node);
output.depth++;
super.visitFunctionTerm(node);
output.depth--;
}
@override
void visitGroupTerm(GroupTerm node) {
heading('GroupTerm', node);
output.depth++;
output.writeNodeList('grouped terms', node._terms);
output.depth--;
}
@override
void visitItemTerm(ItemTerm node) {
heading('ItemTerm', node);
super.visitItemTerm(node);
}
@override
void visitIE8Term(IE8Term node) {
heading('IE8Term', node);
visitLiteralTerm(node);
}
@override
void visitOperatorSlash(OperatorSlash node) {
heading('OperatorSlash', node);
}
@override
void visitOperatorComma(OperatorComma node) {
heading('OperatorComma', node);
}
@override
void visitOperatorPlus(OperatorPlus node) {
heading('OperatorPlus', node);
}
@override
void visitOperatorMinus(OperatorMinus node) {
heading('OperatorMinus', node);
}
@override
void visitVarUsage(VarUsage node) {
heading('Var', node);
output.depth++;
output.write('usage ${node.name}');
output.writeNodeList('default values', node.defaultValues);
output.depth--;
}
@override
void visitExpressions(Expressions node) {
heading('Expressions', node);
output.depth++;
output.writeNodeList('expressions', node.expressions);
output.depth--;
}
@override
void visitBinaryExpression(BinaryExpression node) {
heading('BinaryExpression', node);
// TODO(terry): TBD
}
@override
void visitUnaryExpression(UnaryExpression node) {
heading('UnaryExpression', node);
// TODO(terry): TBD
}
@override
void visitIdentifier(Identifier node) {
heading('Identifier(${output.toValue(node.name)})', node);
}
@override
void visitWildcard(Wildcard node) {
heading('Wildcard(*)', node);
}
@override
void visitDartStyleExpression(DartStyleExpression node) {
heading('DartStyleExpression', node);
}
@override
void visitFontExpression(FontExpression node) {
heading('Dart Style FontExpression', node);
}
@override
void visitBoxExpression(BoxExpression node) {
heading('Dart Style BoxExpression', node);
}
@override
void visitMarginExpression(MarginExpression node) {
heading('Dart Style MarginExpression', node);
}
@override
void visitBorderExpression(BorderExpression node) {
heading('Dart Style BorderExpression', node);
}
@override
void visitHeightExpression(HeightExpression node) {
heading('Dart Style HeightExpression', node);
}
@override
void visitPaddingExpression(PaddingExpression node) {
heading('Dart Style PaddingExpression', node);
}
@override
void visitWidthExpression(WidthExpression node) {
heading('Dart Style WidthExpression', node);
}
}