// Copyright (c) 2012, 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. import 'package:source_span/source_span.dart'; import 'parser.dart'; part 'src/css_printer.dart'; part 'src/tree.dart'; part 'src/tree_base.dart'; part 'src/tree_printer.dart'; abstract class VisitorBase { dynamic visitCalcTerm(CalcTerm node); dynamic visitCssComment(CssComment node); dynamic visitCommentDefinition(CommentDefinition node); dynamic visitStyleSheet(StyleSheet node); dynamic visitNoOp(NoOp node); dynamic visitTopLevelProduction(TopLevelProduction node); dynamic visitDirective(Directive node); dynamic visitDocumentDirective(DocumentDirective node); dynamic visitSupportsDirective(SupportsDirective node); dynamic visitSupportsConditionInParens(SupportsConditionInParens node); dynamic visitSupportsNegation(SupportsNegation node); dynamic visitSupportsConjunction(SupportsConjunction node); dynamic visitSupportsDisjunction(SupportsDisjunction node); dynamic visitViewportDirective(ViewportDirective node); dynamic visitMediaExpression(MediaExpression node); dynamic visitMediaQuery(MediaQuery node); dynamic visitMediaDirective(MediaDirective node); dynamic visitHostDirective(HostDirective node); dynamic visitPageDirective(PageDirective node); dynamic visitCharsetDirective(CharsetDirective node); dynamic visitImportDirective(ImportDirective node); dynamic visitKeyFrameDirective(KeyFrameDirective node); dynamic visitKeyFrameBlock(KeyFrameBlock node); dynamic visitFontFaceDirective(FontFaceDirective node); dynamic visitStyletDirective(StyletDirective node); dynamic visitNamespaceDirective(NamespaceDirective node); dynamic visitVarDefinitionDirective(VarDefinitionDirective node); dynamic visitMixinDefinition(MixinDefinition node); dynamic visitMixinRulesetDirective(MixinRulesetDirective node); dynamic visitMixinDeclarationDirective(MixinDeclarationDirective node); dynamic visitIncludeDirective(IncludeDirective node); dynamic visitContentDirective(ContentDirective node); dynamic visitRuleSet(RuleSet node); dynamic visitDeclarationGroup(DeclarationGroup node); dynamic visitMarginGroup(MarginGroup node); dynamic visitDeclaration(Declaration node); dynamic visitVarDefinition(VarDefinition node); dynamic visitIncludeMixinAtDeclaration(IncludeMixinAtDeclaration node); dynamic visitExtendDeclaration(ExtendDeclaration node); dynamic visitSelectorGroup(SelectorGroup node); dynamic visitSelector(Selector node); dynamic visitSimpleSelectorSequence(SimpleSelectorSequence node); dynamic visitSimpleSelector(SimpleSelector node); dynamic visitElementSelector(ElementSelector node); dynamic visitNamespaceSelector(NamespaceSelector node); dynamic visitAttributeSelector(AttributeSelector node); dynamic visitIdSelector(IdSelector node); dynamic visitClassSelector(ClassSelector node); dynamic visitPseudoClassSelector(PseudoClassSelector node); dynamic visitPseudoElementSelector(PseudoElementSelector node); dynamic visitPseudoClassFunctionSelector(PseudoClassFunctionSelector node); dynamic visitPseudoElementFunctionSelector( PseudoElementFunctionSelector node); dynamic visitNegationSelector(NegationSelector node); dynamic visitSelectorExpression(SelectorExpression node); dynamic visitUnicodeRangeTerm(UnicodeRangeTerm node); dynamic visitLiteralTerm(LiteralTerm node); dynamic visitHexColorTerm(HexColorTerm node); dynamic visitNumberTerm(NumberTerm node); dynamic visitUnitTerm(UnitTerm node); dynamic visitLengthTerm(LengthTerm node); dynamic visitPercentageTerm(PercentageTerm node); dynamic visitEmTerm(EmTerm node); dynamic visitExTerm(ExTerm node); dynamic visitAngleTerm(AngleTerm node); dynamic visitTimeTerm(TimeTerm node); dynamic visitFreqTerm(FreqTerm node); dynamic visitFractionTerm(FractionTerm node); dynamic visitUriTerm(UriTerm node); dynamic visitResolutionTerm(ResolutionTerm node); dynamic visitChTerm(ChTerm node); dynamic visitRemTerm(RemTerm node); dynamic visitViewportTerm(ViewportTerm node); dynamic visitLineHeightTerm(LineHeightTerm node); dynamic visitFunctionTerm(FunctionTerm node); dynamic visitGroupTerm(GroupTerm node); dynamic visitItemTerm(ItemTerm node); dynamic visitIE8Term(IE8Term node); dynamic visitOperatorSlash(OperatorSlash node); dynamic visitOperatorComma(OperatorComma node); dynamic visitOperatorPlus(OperatorPlus node); dynamic visitOperatorMinus(OperatorMinus node); dynamic visitVarUsage(VarUsage node); dynamic visitExpressions(Expressions node); dynamic visitBinaryExpression(BinaryExpression node); dynamic visitUnaryExpression(UnaryExpression node); dynamic visitIdentifier(Identifier node); dynamic visitWildcard(Wildcard node); dynamic visitThisOperator(ThisOperator node); dynamic visitNegation(Negation node); dynamic visitDartStyleExpression(DartStyleExpression node); dynamic visitFontExpression(FontExpression node); dynamic visitBoxExpression(BoxExpression node); dynamic visitMarginExpression(MarginExpression node); dynamic visitBorderExpression(BorderExpression node); dynamic visitHeightExpression(HeightExpression node); dynamic visitPaddingExpression(PaddingExpression node); dynamic visitWidthExpression(WidthExpression node); } /// Base vistor class for the style sheet AST. class Visitor implements VisitorBase { /// Helper function to walk a list of nodes. void _visitNodeList(List list) { // Don't use iterable otherwise the list can't grow while using Visitor. // It certainly can't have items deleted before the index being iterated // but items could be added after the index. for (var index = 0; index < list.length; index++) { list[index].visit(this); } } dynamic visitTree(StyleSheet tree) => visitStyleSheet(tree); @override dynamic visitStyleSheet(StyleSheet ss) { _visitNodeList(ss.topLevels); } @override dynamic visitNoOp(NoOp node) {} @override dynamic visitTopLevelProduction(TopLevelProduction node) {} @override dynamic visitDirective(Directive node) {} @override dynamic visitCalcTerm(CalcTerm node) { visitLiteralTerm(node); visitLiteralTerm(node.expr); } @override dynamic visitCssComment(CssComment node) {} @override dynamic visitCommentDefinition(CommentDefinition node) {} @override dynamic visitMediaExpression(MediaExpression node) { visitExpressions(node.exprs); } @override dynamic visitMediaQuery(MediaQuery node) { for (var mediaExpr in node.expressions) { visitMediaExpression(mediaExpr); } } @override dynamic visitDocumentDirective(DocumentDirective node) { _visitNodeList(node.functions); _visitNodeList(node.groupRuleBody); } @override dynamic visitSupportsDirective(SupportsDirective node) { node.condition!.visit(this); _visitNodeList(node.groupRuleBody); } @override dynamic visitSupportsConditionInParens(SupportsConditionInParens node) { node.condition!.visit(this); } @override dynamic visitSupportsNegation(SupportsNegation node) { node.condition.visit(this); } @override dynamic visitSupportsConjunction(SupportsConjunction node) { _visitNodeList(node.conditions); } @override dynamic visitSupportsDisjunction(SupportsDisjunction node) { _visitNodeList(node.conditions); } @override dynamic visitViewportDirective(ViewportDirective node) { node.declarations.visit(this); } @override dynamic visitMediaDirective(MediaDirective node) { _visitNodeList(node.mediaQueries); _visitNodeList(node.rules); } @override dynamic visitHostDirective(HostDirective node) { _visitNodeList(node.rules); } @override dynamic visitPageDirective(PageDirective node) { for (var declGroup in node._declsMargin) { if (declGroup is MarginGroup) { visitMarginGroup(declGroup); } else { visitDeclarationGroup(declGroup); } } } @override dynamic visitCharsetDirective(CharsetDirective node) {} @override dynamic visitImportDirective(ImportDirective node) { for (var mediaQuery in node.mediaQueries) { visitMediaQuery(mediaQuery); } } @override dynamic visitKeyFrameDirective(KeyFrameDirective node) { visitIdentifier(node.name!); _visitNodeList(node._blocks); } @override dynamic visitKeyFrameBlock(KeyFrameBlock node) { visitExpressions(node._blockSelectors); visitDeclarationGroup(node._declarations); } @override dynamic visitFontFaceDirective(FontFaceDirective node) { visitDeclarationGroup(node._declarations); } @override dynamic visitStyletDirective(StyletDirective node) { _visitNodeList(node.rules); } @override dynamic visitNamespaceDirective(NamespaceDirective node) {} @override dynamic visitVarDefinitionDirective(VarDefinitionDirective node) { visitVarDefinition(node.def); } @override dynamic visitMixinRulesetDirective(MixinRulesetDirective node) { _visitNodeList(node.rulesets); } @override dynamic visitMixinDefinition(MixinDefinition node) {} @override dynamic visitMixinDeclarationDirective(MixinDeclarationDirective node) { visitDeclarationGroup(node.declarations); } @override dynamic visitIncludeDirective(IncludeDirective node) { for (var index = 0; index < node.args.length; index++) { var param = node.args[index]; _visitNodeList(param); } } @override dynamic visitContentDirective(ContentDirective node) { // TODO(terry): TBD } @override dynamic visitRuleSet(RuleSet node) { visitSelectorGroup(node.selectorGroup!); visitDeclarationGroup(node.declarationGroup); } @override dynamic visitDeclarationGroup(DeclarationGroup node) { _visitNodeList(node.declarations); } @override dynamic visitMarginGroup(MarginGroup node) => visitDeclarationGroup(node); @override dynamic visitDeclaration(Declaration node) { visitIdentifier(node._property!); if (node.expression != null) node.expression!.visit(this); } @override dynamic visitVarDefinition(VarDefinition node) { visitIdentifier(node._property!); if (node.expression != null) node.expression!.visit(this); } @override dynamic visitIncludeMixinAtDeclaration(IncludeMixinAtDeclaration node) { visitIncludeDirective(node.include); } @override dynamic visitExtendDeclaration(ExtendDeclaration node) { _visitNodeList(node.selectors); } @override dynamic visitSelectorGroup(SelectorGroup node) { _visitNodeList(node.selectors); } @override dynamic visitSelector(Selector node) { _visitNodeList(node.simpleSelectorSequences); } @override dynamic visitSimpleSelectorSequence(SimpleSelectorSequence node) { node.simpleSelector.visit(this); } @override dynamic visitSimpleSelector(SimpleSelector node) => (node._name as TreeNode).visit(this); @override dynamic visitNamespaceSelector(NamespaceSelector node) { if (node._namespace != null) (node._namespace as TreeNode).visit(this); if (node.nameAsSimpleSelector != null) { node.nameAsSimpleSelector!.visit(this); } } @override dynamic visitElementSelector(ElementSelector node) => visitSimpleSelector(node); @override dynamic visitAttributeSelector(AttributeSelector node) { visitSimpleSelector(node); } @override dynamic visitIdSelector(IdSelector node) => visitSimpleSelector(node); @override dynamic visitClassSelector(ClassSelector node) => visitSimpleSelector(node); @override dynamic visitPseudoClassSelector(PseudoClassSelector node) => visitSimpleSelector(node); @override dynamic visitPseudoElementSelector(PseudoElementSelector node) => visitSimpleSelector(node); @override dynamic visitPseudoClassFunctionSelector(PseudoClassFunctionSelector node) => visitSimpleSelector(node); @override dynamic visitPseudoElementFunctionSelector( PseudoElementFunctionSelector node) => visitSimpleSelector(node); @override dynamic visitNegationSelector(NegationSelector node) => visitSimpleSelector(node); @override dynamic visitSelectorExpression(SelectorExpression node) { _visitNodeList(node.expressions); } @override dynamic visitUnicodeRangeTerm(UnicodeRangeTerm node) {} @override dynamic visitLiteralTerm(LiteralTerm node) {} @override dynamic visitHexColorTerm(HexColorTerm node) {} @override dynamic visitNumberTerm(NumberTerm node) {} @override dynamic visitUnitTerm(UnitTerm node) {} @override dynamic visitLengthTerm(LengthTerm node) { visitUnitTerm(node); } @override dynamic visitPercentageTerm(PercentageTerm node) { visitLiteralTerm(node); } @override dynamic visitEmTerm(EmTerm node) { visitLiteralTerm(node); } @override dynamic visitExTerm(ExTerm node) { visitLiteralTerm(node); } @override dynamic visitAngleTerm(AngleTerm node) { visitUnitTerm(node); } @override dynamic visitTimeTerm(TimeTerm node) { visitUnitTerm(node); } @override dynamic visitFreqTerm(FreqTerm node) { visitUnitTerm(node); } @override dynamic visitFractionTerm(FractionTerm node) { visitLiteralTerm(node); } @override dynamic visitUriTerm(UriTerm node) { visitLiteralTerm(node); } @override dynamic visitResolutionTerm(ResolutionTerm node) { visitUnitTerm(node); } @override dynamic visitChTerm(ChTerm node) { visitUnitTerm(node); } @override dynamic visitRemTerm(RemTerm node) { visitUnitTerm(node); } @override dynamic visitViewportTerm(ViewportTerm node) { visitUnitTerm(node); } @override dynamic visitLineHeightTerm(LineHeightTerm node) { visitUnitTerm(node); } @override dynamic visitFunctionTerm(FunctionTerm node) { visitLiteralTerm(node); visitExpressions(node._params); } @override dynamic visitGroupTerm(GroupTerm node) { for (var term in node._terms) { term.visit(this); } } @override dynamic visitItemTerm(ItemTerm node) { visitNumberTerm(node); } @override dynamic visitIE8Term(IE8Term node) {} @override dynamic visitOperatorSlash(OperatorSlash node) {} @override dynamic visitOperatorComma(OperatorComma node) {} @override dynamic visitOperatorPlus(OperatorPlus node) {} @override dynamic visitOperatorMinus(OperatorMinus node) {} @override dynamic visitVarUsage(VarUsage node) { _visitNodeList(node.defaultValues); } @override dynamic visitExpressions(Expressions node) { _visitNodeList(node.expressions); } @override dynamic visitBinaryExpression(BinaryExpression node) { // TODO(terry): TBD throw UnimplementedError(); } @override dynamic visitUnaryExpression(UnaryExpression node) { // TODO(terry): TBD throw UnimplementedError(); } @override dynamic visitIdentifier(Identifier node) {} @override dynamic visitWildcard(Wildcard node) {} @override dynamic visitThisOperator(ThisOperator node) {} @override dynamic visitNegation(Negation node) {} @override dynamic visitDartStyleExpression(DartStyleExpression node) {} @override dynamic visitFontExpression(FontExpression node) { // TODO(terry): TBD throw UnimplementedError(); } @override dynamic visitBoxExpression(BoxExpression node) { // TODO(terry): TBD throw UnimplementedError(); } @override dynamic visitMarginExpression(MarginExpression node) { // TODO(terry): TBD throw UnimplementedError(); } @override dynamic visitBorderExpression(BorderExpression node) { // TODO(terry): TBD throw UnimplementedError(); } @override dynamic visitHeightExpression(HeightExpression node) { // TODO(terry): TB throw UnimplementedError(); } @override dynamic visitPaddingExpression(PaddingExpression node) { // TODO(terry): TBD throw UnimplementedError(); } @override dynamic visitWidthExpression(WidthExpression node) { // TODO(terry): TBD throw UnimplementedError(); } }