Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1653)

Unified Diff: mojo/public/dart/third_party/csslib/lib/src/tree.dart

Issue 1346773002: Stop running pub get at gclient sync time and fix build bugs (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: mojo/public/dart/third_party/csslib/lib/src/tree.dart
diff --git a/mojo/public/dart/third_party/csslib/lib/src/tree.dart b/mojo/public/dart/third_party/csslib/lib/src/tree.dart
new file mode 100644
index 0000000000000000000000000000000000000000..5dad435b48467053e18de2c236227ace717117fb
--- /dev/null
+++ b/mojo/public/dart/third_party/csslib/lib/src/tree.dart
@@ -0,0 +1,1425 @@
+// 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.
+
+part of csslib.visitor;
+
+/////////////////////////////////////////////////////////////////////////
+// CSS specific types:
+/////////////////////////////////////////////////////////////////////////
+
+class Identifier extends TreeNode {
+ String name;
+
+ Identifier(this.name, SourceSpan span) : super(span);
+
+ Identifier clone() => new Identifier(name, span);
+
+ visit(VisitorBase visitor) => visitor.visitIdentifier(this);
+
+ String toString() => name;
+}
+
+class Wildcard extends TreeNode {
+ Wildcard(SourceSpan span) : super(span);
+ Wildcard clone() => new Wildcard(span);
+ visit(VisitorBase visitor) => visitor.visitWildcard(this);
+
+ String get name => '*';
+}
+
+class ThisOperator extends TreeNode {
+ ThisOperator(SourceSpan span) : super(span);
+ ThisOperator clone() => new ThisOperator(span);
+ visit(VisitorBase visitor) => visitor.visitThisOperator(this);
+
+ String get name => '&';
+}
+
+class Negation extends TreeNode {
+ Negation(SourceSpan span) : super(span);
+ Negation clone() => new Negation(span);
+ visit(VisitorBase visitor) => visitor.visitNegation(this);
+
+ String get name => 'not';
+}
+
+// /* .... */
+class CssComment extends TreeNode {
+ final String comment;
+
+ CssComment(this.comment, SourceSpan span) : super(span);
+ CssComment clone() => new CssComment(comment, span);
+ visit(VisitorBase visitor) => visitor.visitCssComment(this);
+}
+
+// CDO/CDC (Comment Definition Open <!-- and Comment Definition Close -->).
+class CommentDefinition extends CssComment {
+ CommentDefinition(String comment, SourceSpan span) : super(comment, span);
+ CommentDefinition clone() => new CommentDefinition(comment, span);
+ visit(VisitorBase visitor) => visitor.visitCommentDefinition(this);
+}
+
+class SelectorGroup extends TreeNode {
+ final List<Selector> selectors;
+
+ SelectorGroup(this.selectors, SourceSpan span) : super(span);
+
+ SelectorGroup clone() => new SelectorGroup(selectors, span);
+
+ visit(VisitorBase visitor) => visitor.visitSelectorGroup(this);
+}
+
+class Selector extends TreeNode {
+ final List<SimpleSelectorSequence> simpleSelectorSequences;
+
+ Selector(this.simpleSelectorSequences, SourceSpan span) : super(span);
+
+ void add(SimpleSelectorSequence seq) => simpleSelectorSequences.add(seq);
+
+ int get length => simpleSelectorSequences.length;
+
+ Selector clone() {
+ var simpleSequences =
+ simpleSelectorSequences.map((ss) => ss.clone()).toList();
+
+ return new Selector(simpleSequences, span);
+ }
+
+ visit(VisitorBase visitor) => visitor.visitSelector(this);
+}
+
+class SimpleSelectorSequence extends TreeNode {
+ /** +, >, ~, NONE */
+ int combinator;
+ final SimpleSelector simpleSelector;
+
+ SimpleSelectorSequence(this.simpleSelector, SourceSpan span,
+ [int combinator = TokenKind.COMBINATOR_NONE])
+ : combinator = combinator,
+ super(span);
+
+ bool get isCombinatorNone => combinator == TokenKind.COMBINATOR_NONE;
+ bool get isCombinatorPlus => combinator == TokenKind.COMBINATOR_PLUS;
+ bool get isCombinatorGreater => combinator == TokenKind.COMBINATOR_GREATER;
+ bool get isCombinatorTilde => combinator == TokenKind.COMBINATOR_TILDE;
+ bool get isCombinatorDescendant =>
+ combinator == TokenKind.COMBINATOR_DESCENDANT;
+
+ String get _combinatorToString => isCombinatorDescendant
+ ? ' '
+ : isCombinatorPlus
+ ? ' + '
+ : isCombinatorGreater ? ' > ' : isCombinatorTilde ? ' ~ ' : '';
+
+ SimpleSelectorSequence clone() =>
+ new SimpleSelectorSequence(simpleSelector, span, combinator);
+
+ visit(VisitorBase visitor) => visitor.visitSimpleSelectorSequence(this);
+
+ String toString() => simpleSelector.name;
+}
+
+/* All other selectors (element, #id, .class, attribute, pseudo, negation,
+ * namespace, *) are derived from this selector.
+ */
+abstract class SimpleSelector extends TreeNode {
+ final _name; // Wildcard, ThisOperator, Identifier, Negation, others?
+
+ SimpleSelector(this._name, SourceSpan span) : super(span);
+
+ String get name => _name.name;
+
+ bool get isWildcard => _name is Wildcard;
+
+ bool get isThis => _name is ThisOperator;
+
+ visit(VisitorBase visitor) => visitor.visitSimpleSelector(this);
+}
+
+// element name
+class ElementSelector extends SimpleSelector {
+ ElementSelector(name, SourceSpan span) : super(name, span);
+ visit(VisitorBase visitor) => visitor.visitElementSelector(this);
+
+ ElementSelector clone() => new ElementSelector(_name, span);
+
+ String toString() => name;
+}
+
+// namespace|element
+class NamespaceSelector extends SimpleSelector {
+ final _namespace; // null, Wildcard or Identifier
+
+ NamespaceSelector(this._namespace, var name, SourceSpan span)
+ : super(name, span);
+
+ String get namespace =>
+ _namespace is Wildcard ? '*' : _namespace == null ? '' : _namespace.name;
+
+ bool get isNamespaceWildcard => _namespace is Wildcard;
+
+ SimpleSelector get nameAsSimpleSelector => _name;
+
+ NamespaceSelector clone() => new NamespaceSelector(_namespace, "", span);
+
+ visit(VisitorBase visitor) => visitor.visitNamespaceSelector(this);
+
+ String toString() => "$namespace|${nameAsSimpleSelector.name}";
+}
+
+// [attr op value]
+class AttributeSelector extends SimpleSelector {
+ final int _op;
+ final _value;
+
+ AttributeSelector(Identifier name, this._op, this._value, SourceSpan span)
+ : super(name, span);
+
+ int get operatorKind => _op;
+
+ get value => _value;
+
+ String matchOperator() {
+ switch (_op) {
+ case TokenKind.EQUALS:
+ return '=';
+ case TokenKind.INCLUDES:
+ return '~=';
+ case TokenKind.DASH_MATCH:
+ return '|=';
+ case TokenKind.PREFIX_MATCH:
+ return '^=';
+ case TokenKind.SUFFIX_MATCH:
+ return '\$=';
+ case TokenKind.SUBSTRING_MATCH:
+ return '*=';
+ case TokenKind.NO_MATCH:
+ return '';
+ }
+ }
+
+ // Return the TokenKind for operator used by visitAttributeSelector.
+ String matchOperatorAsTokenString() {
+ switch (_op) {
+ case TokenKind.EQUALS:
+ return 'EQUALS';
+ case TokenKind.INCLUDES:
+ return 'INCLUDES';
+ case TokenKind.DASH_MATCH:
+ return 'DASH_MATCH';
+ case TokenKind.PREFIX_MATCH:
+ return 'PREFIX_MATCH';
+ case TokenKind.SUFFIX_MATCH:
+ return 'SUFFIX_MATCH';
+ case TokenKind.SUBSTRING_MATCH:
+ return 'SUBSTRING_MATCH';
+ }
+ }
+
+ String valueToString() {
+ if (_value != null) {
+ if (_value is Identifier) {
+ return _value.name;
+ } else {
+ return '"${_value}"';
+ }
+ } else {
+ return '';
+ }
+ }
+
+ AttributeSelector clone() => new AttributeSelector(_name, _op, _value, span);
+
+ visit(VisitorBase visitor) => visitor.visitAttributeSelector(this);
+
+ String toString() => "[$name${matchOperator()}${valueToString()}]";
+}
+
+// #id
+class IdSelector extends SimpleSelector {
+ IdSelector(Identifier name, SourceSpan span) : super(name, span);
+ IdSelector clone() => new IdSelector(_name, span);
+ visit(VisitorBase visitor) => visitor.visitIdSelector(this);
+
+ String toString() => "#$_name";
+}
+
+// .class
+class ClassSelector extends SimpleSelector {
+ ClassSelector(Identifier name, SourceSpan span) : super(name, span);
+ ClassSelector clone() => new ClassSelector(_name, span);
+ visit(VisitorBase visitor) => visitor.visitClassSelector(this);
+
+ String toString() => ".$_name";
+}
+
+// :pseudoClass
+class PseudoClassSelector extends SimpleSelector {
+ PseudoClassSelector(Identifier name, SourceSpan span) : super(name, span);
+ visit(VisitorBase visitor) => visitor.visitPseudoClassSelector(this);
+
+ PseudoClassSelector clone() => new PseudoClassSelector(_name, span);
+
+ String toString() => ":$name";
+}
+
+// ::pseudoElement
+class PseudoElementSelector extends SimpleSelector {
+ PseudoElementSelector(Identifier name, SourceSpan span) : super(name, span);
+ visit(VisitorBase visitor) => visitor.visitPseudoElementSelector(this);
+
+ PseudoElementSelector clone() => new PseudoElementSelector(_name, span);
+
+ String toString() => "::$name";
+}
+
+// :pseudoClassFunction(expression)
+class PseudoClassFunctionSelector extends PseudoClassSelector {
+ final SelectorExpression expression;
+
+ PseudoClassFunctionSelector(Identifier name, this.expression, SourceSpan span)
+ : super(name, span);
+
+ PseudoClassFunctionSelector clone() =>
+ new PseudoClassFunctionSelector(_name, expression, span);
+
+ visit(VisitorBase visitor) => visitor.visitPseudoClassFunctionSelector(this);
+}
+
+// ::pseudoElementFunction(expression)
+class PseudoElementFunctionSelector extends PseudoElementSelector {
+ final SelectorExpression expression;
+
+ PseudoElementFunctionSelector(
+ Identifier name, this.expression, SourceSpan span)
+ : super(name, span);
+
+ PseudoElementFunctionSelector clone() =>
+ new PseudoElementFunctionSelector(_name, expression, span);
+
+ visit(VisitorBase visitor) =>
+ visitor.visitPseudoElementFunctionSelector(this);
+}
+
+class SelectorExpression extends TreeNode {
+ final List<Expression> expressions;
+
+ SelectorExpression(this.expressions, SourceSpan span) : super(span);
+
+ SelectorExpression clone() {
+ return new SelectorExpression(
+ expressions.map((e) => e.clone()).toList(), span);
+ }
+
+ visit(VisitorBase visitor) => visitor.visitSelectorExpression(this);
+}
+
+// :NOT(negation_arg)
+class NegationSelector extends SimpleSelector {
+ final SimpleSelector negationArg;
+
+ NegationSelector(this.negationArg, SourceSpan span)
+ : super(new Negation(span), span);
+
+ NegationSelector clone() => new NegationSelector(negationArg, span);
+
+ visit(VisitorBase visitor) => visitor.visitNegationSelector(this);
+}
+
+class NoOp extends TreeNode {
+ NoOp() : super(null);
+
+ NoOp clone() => new NoOp();
+
+ visit(VisitorBase visitor) => visitor.visitNoOp(this);
+}
+
+class StyleSheet extends TreeNode {
+ /**
+ * Contains charset, ruleset, directives (media, page, etc.), and selectors.
+ */
+ final List<TreeNode> topLevels;
+
+ StyleSheet(this.topLevels, SourceSpan span) : super(span) {
+ for (final node in topLevels) {
+ assert(node is TopLevelProduction || node is Directive);
+ }
+ }
+
+ /** Selectors only in this tree. */
+ StyleSheet.selector(this.topLevels, SourceSpan span) : super(span);
+
+ StyleSheet clone() {
+ var clonedTopLevels = topLevels.map((e) => e.clone()).toList();
+ return new StyleSheet(clonedTopLevels, span);
+ }
+
+ visit(VisitorBase visitor) => visitor.visitStyleSheet(this);
+}
+
+class TopLevelProduction extends TreeNode {
+ TopLevelProduction(SourceSpan span) : super(span);
+ TopLevelProduction clone() => new TopLevelProduction(span);
+ visit(VisitorBase visitor) => visitor.visitTopLevelProduction(this);
+}
+
+class RuleSet extends TopLevelProduction {
+ final SelectorGroup _selectorGroup;
+ final DeclarationGroup _declarationGroup;
+
+ RuleSet(this._selectorGroup, this._declarationGroup, SourceSpan span)
+ : super(span);
+
+ SelectorGroup get selectorGroup => _selectorGroup;
+ DeclarationGroup get declarationGroup => _declarationGroup;
+
+ RuleSet clone() {
+ var cloneSelectorGroup = _selectorGroup.clone();
+ var cloneDeclarationGroup = _declarationGroup.clone();
+ return new RuleSet(cloneSelectorGroup, cloneDeclarationGroup, span);
+ }
+
+ visit(VisitorBase visitor) => visitor.visitRuleSet(this);
+}
+
+class Directive extends TreeNode {
+ Directive(SourceSpan span) : super(span);
+
+ bool get isBuiltIn => true; // Known CSS directive?
+ bool get isExtension => false; // SCSS extension?
+
+ Directive clone() => new Directive(span);
+ visit(VisitorBase visitor) => visitor.visitDirective(this);
+}
+
+class ImportDirective extends Directive {
+ /** import name specified. */
+ final String import;
+
+ /** Any media queries for this import. */
+ final List<MediaQuery> mediaQueries;
+
+ ImportDirective(this.import, this.mediaQueries, SourceSpan span)
+ : super(span);
+
+ ImportDirective clone() {
+ var cloneMediaQueries = [];
+ for (var mediaQuery in mediaQueries) {
+ cloneMediaQueries.add(mediaQuery.clone());
+ }
+ return new ImportDirective(import, cloneMediaQueries, span);
+ }
+
+ visit(VisitorBase visitor) => visitor.visitImportDirective(this);
+}
+
+/**
+ * MediaExpression grammar:
+ * '(' S* media_feature S* [ ':' S* expr ]? ')' S*
+ */
+class MediaExpression extends TreeNode {
+ final bool andOperator;
+ final Identifier _mediaFeature;
+ final Expressions exprs;
+
+ MediaExpression(
+ this.andOperator, this._mediaFeature, this.exprs, SourceSpan span)
+ : super(span);
+
+ String get mediaFeature => _mediaFeature.name;
+
+ MediaExpression clone() {
+ var clonedExprs = exprs.clone();
+ return new MediaExpression(andOperator, _mediaFeature, clonedExprs, span);
+ }
+
+ visit(VisitorBase visitor) => visitor.visitMediaExpression(this);
+}
+
+/**
+ * MediaQuery grammar:
+ * : [ONLY | NOT]? S* media_type S* [ AND S* media_expression ]*
+ * | media_expression [ AND S* media_expression ]*
+ * media_type
+ * : IDENT
+ * media_expression
+ * : '(' S* media_feature S* [ ':' S* expr ]? ')' S*
+ * media_feature
+ * : IDENT
+ */
+class MediaQuery extends TreeNode {
+ /** not, only or no operator. */
+ final int _mediaUnary;
+ final Identifier _mediaType;
+ final List<MediaExpression> expressions;
+
+ MediaQuery(
+ this._mediaUnary, this._mediaType, this.expressions, SourceSpan span)
+ : super(span);
+
+ bool get hasMediaType => _mediaType != null;
+ String get mediaType => _mediaType.name;
+
+ bool get hasUnary => _mediaUnary != -1;
+ String get unary =>
+ TokenKind.idToValue(TokenKind.MEDIA_OPERATORS, _mediaUnary).toUpperCase();
+
+ MediaQuery clone() {
+ var cloneExpressions = [];
+ for (var expr in expressions) {
+ cloneExpressions.add(expr.clone());
+ }
+ return new MediaQuery(_mediaUnary, _mediaType, cloneExpressions, span);
+ }
+ visit(VisitorBase visitor) => visitor.visitMediaQuery(this);
+}
+
+class MediaDirective extends Directive {
+ final List<MediaQuery> mediaQueries;
+ final List<RuleSet> rulesets;
+
+ MediaDirective(this.mediaQueries, this.rulesets, SourceSpan span)
+ : super(span);
+
+ MediaDirective clone() {
+ var cloneQueries = [];
+ for (var mediaQuery in mediaQueries) {
+ cloneQueries.add(mediaQuery.clone());
+ }
+ var cloneRulesets = [];
+ for (var ruleset in rulesets) {
+ cloneRulesets.add(ruleset.clone());
+ }
+ return new MediaDirective(cloneQueries, cloneRulesets, span);
+ }
+
+ visit(VisitorBase visitor) => visitor.visitMediaDirective(this);
+}
+
+class HostDirective extends Directive {
+ final List<RuleSet> rulesets;
+
+ HostDirective(this.rulesets, SourceSpan span) : super(span);
+
+ HostDirective clone() {
+ var cloneRulesets = [];
+ for (var ruleset in rulesets) {
+ cloneRulesets.add(ruleset.clone());
+ }
+ return new HostDirective(cloneRulesets, span);
+ }
+
+ visit(VisitorBase visitor) => visitor.visitHostDirective(this);
+}
+
+class PageDirective extends Directive {
+ final String _ident;
+ final String _pseudoPage;
+ final List<DeclarationGroup> _declsMargin;
+
+ PageDirective(
+ this._ident, this._pseudoPage, this._declsMargin, SourceSpan span)
+ : super(span);
+
+ PageDirective clone() {
+ var cloneDeclsMargin = [];
+ for (var declMargin in _declsMargin) {
+ cloneDeclsMargin.add(declMargin.clone());
+ }
+ return new PageDirective(_ident, _pseudoPage, cloneDeclsMargin, span);
+ }
+
+ visit(VisitorBase visitor) => visitor.visitPageDirective(this);
+
+ bool get hasIdent => _ident != null && _ident.length > 0;
+ bool get hasPseudoPage => _pseudoPage != null && _pseudoPage.length > 0;
+}
+
+class CharsetDirective extends Directive {
+ final String charEncoding;
+
+ CharsetDirective(this.charEncoding, SourceSpan span) : super(span);
+ CharsetDirective clone() => new CharsetDirective(charEncoding, span);
+ visit(VisitorBase visitor) => visitor.visitCharsetDirective(this);
+}
+
+class KeyFrameDirective extends Directive {
+ /*
+ * Either @keyframe or keyframe prefixed with @-webkit-, @-moz-, @-ms-, @-o-.
+ */
+ final int _keyframeName;
+ final name;
+ final List<KeyFrameBlock> _blocks;
+
+ KeyFrameDirective(this._keyframeName, this.name, SourceSpan span)
+ : _blocks = [],
+ super(span);
+
+ add(KeyFrameBlock block) {
+ _blocks.add(block);
+ }
+
+ String get keyFrameName {
+ switch (_keyframeName) {
+ case TokenKind.DIRECTIVE_KEYFRAMES:
+ case TokenKind.DIRECTIVE_MS_KEYFRAMES:
+ return '@keyframes';
+ case TokenKind.DIRECTIVE_WEB_KIT_KEYFRAMES:
+ return '@-webkit-keyframes';
+ case TokenKind.DIRECTIVE_MOZ_KEYFRAMES:
+ return '@-moz-keyframes';
+ case TokenKind.DIRECTIVE_O_KEYFRAMES:
+ return '@-o-keyframes';
+ }
+ }
+
+ KeyFrameDirective clone() {
+ var cloneBlocks = [];
+ for (var block in _blocks) {
+ cloneBlocks.add(block.clone());
+ }
+ return new KeyFrameDirective(_keyframeName, cloneBlocks, span);
+ }
+ visit(VisitorBase visitor) => visitor.visitKeyFrameDirective(this);
+}
+
+class KeyFrameBlock extends Expression {
+ final Expressions _blockSelectors;
+ final DeclarationGroup _declarations;
+
+ KeyFrameBlock(this._blockSelectors, this._declarations, SourceSpan span)
+ : super(span);
+
+ KeyFrameBlock clone() =>
+ new KeyFrameBlock(_blockSelectors.clone(), _declarations.clone(), span);
+ visit(VisitorBase visitor) => visitor.visitKeyFrameBlock(this);
+}
+
+class FontFaceDirective extends Directive {
+ final DeclarationGroup _declarations;
+
+ FontFaceDirective(this._declarations, SourceSpan span) : super(span);
+
+ FontFaceDirective clone() =>
+ new FontFaceDirective(_declarations.clone(), span);
+ visit(VisitorBase visitor) => visitor.visitFontFaceDirective(this);
+}
+
+class StyletDirective extends Directive {
+ final String dartClassName;
+ final List<RuleSet> rulesets;
+
+ StyletDirective(this.dartClassName, this.rulesets, SourceSpan span)
+ : super(span);
+
+ bool get isBuiltIn => false;
+ bool get isExtension => true;
+
+ StyletDirective clone() {
+ var cloneRulesets = [];
+ for (var ruleset in rulesets) {
+ cloneRulesets.add(ruleset.clone());
+ }
+ return new StyletDirective(dartClassName, cloneRulesets, span);
+ }
+
+ visit(VisitorBase visitor) => visitor.visitStyletDirective(this);
+}
+
+class NamespaceDirective extends Directive {
+ /** Namespace prefix. */
+ final String _prefix;
+
+ /** URI associated with this namespace. */
+ final String _uri;
+
+ NamespaceDirective(this._prefix, this._uri, SourceSpan span) : super(span);
+
+ NamespaceDirective clone() => new NamespaceDirective(_prefix, _uri, span);
+
+ visit(VisitorBase visitor) => visitor.visitNamespaceDirective(this);
+
+ String get prefix => _prefix.length > 0 ? '$_prefix ' : '';
+}
+
+/** To support Less syntax @name: expression */
+class VarDefinitionDirective extends Directive {
+ final VarDefinition def;
+
+ VarDefinitionDirective(this.def, SourceSpan span) : super(span);
+
+ VarDefinitionDirective clone() =>
+ new VarDefinitionDirective(def.clone(), span);
+
+ visit(VisitorBase visitor) => visitor.visitVarDefinitionDirective(this);
+}
+
+class MixinDefinition extends Directive {
+ final String name;
+ final List definedArgs;
+ final bool varArgs;
+
+ MixinDefinition(this.name, this.definedArgs, this.varArgs, SourceSpan span)
+ : super(span);
+
+ MixinDefinition clone() {
+ var cloneDefinedArgs = [];
+ for (var definedArg in definedArgs) {
+ cloneDefinedArgs.add(definedArg.clone());
+ }
+ return new MixinDefinition(name, cloneDefinedArgs, varArgs, span);
+ }
+
+ visit(VisitorBase visitor) => visitor.visitMixinDefinition(this);
+}
+
+/** Support a Sass @mixin. See http://sass-lang.com for description. */
+class MixinRulesetDirective extends MixinDefinition {
+ final List<RuleSet> rulesets;
+
+ MixinRulesetDirective(String name, List<VarDefinitionDirective> args,
+ bool varArgs, this.rulesets, SourceSpan span)
+ : super(name, args, varArgs, span);
+
+ MixinRulesetDirective clone() {
+ var clonedArgs = [];
+ for (var arg in definedArgs) {
+ clonedArgs.add(arg.clone());
+ }
+ var clonedRulesets = [];
+ for (var ruleset in rulesets) {
+ clonedRulesets.add(ruleset.clone());
+ }
+ return new MixinRulesetDirective(
+ name, clonedArgs, varArgs, clonedRulesets, span);
+ }
+
+ visit(VisitorBase visitor) => visitor.visitMixinRulesetDirective(this);
+}
+
+class MixinDeclarationDirective extends MixinDefinition {
+ final DeclarationGroup declarations;
+
+ MixinDeclarationDirective(String name, List<VarDefinitionDirective> args,
+ bool varArgs, this.declarations, SourceSpan span)
+ : super(name, args, varArgs, span);
+
+ MixinDeclarationDirective clone() {
+ var clonedArgs = [];
+ for (var arg in definedArgs) {
+ clonedArgs.add(arg.clone());
+ }
+ return new MixinDeclarationDirective(
+ name, clonedArgs, varArgs, declarations.clone(), span);
+ }
+
+ visit(VisitorBase visitor) => visitor.visitMixinDeclarationDirective(this);
+}
+
+/** To support consuming a SASS mixin @include. */
+class IncludeDirective extends Directive {
+ final String name;
+ final List<List<TreeNode>> args;
+
+ IncludeDirective(this.name, this.args, SourceSpan span) : super(span);
+
+ IncludeDirective clone() {
+ var cloneArgs = [];
+ for (var arg in args) {
+ for (var term in arg) {
+ cloneArgs.add(term.clone());
+ }
+ }
+ return new IncludeDirective(name, cloneArgs, span);
+ }
+
+ visit(VisitorBase visitor) => visitor.visitIncludeDirective(this);
+}
+
+/** To support SASS @content. */
+class ContentDirective extends Directive {
+ ContentDirective(SourceSpan span) : super(span);
+
+ visit(VisitorBase visitor) => visitor.visitContentDirective(this);
+}
+
+class Declaration extends TreeNode {
+ final Identifier _property;
+ final Expression _expression;
+ /** Style exposed to Dart. */
+ dynamic dartStyle;
+ final bool important;
+
+ /**
+ * IE CSS hacks that can only be read by a particular IE version.
+ * 7 implies IE 7 or older property (e.g., *background: blue;)
+ * Note: IE 8 or older property (e.g., background: green\9;) is handled
+ * by IE8Term in declaration expression handling.
+ * Note: IE 6 only property with a leading underscore is a valid IDENT
+ * since an ident can start with underscore (e.g., _background: red;)
+ */
+ final bool isIE7;
+
+ Declaration(this._property, this._expression, this.dartStyle, SourceSpan span,
+ {important: false, ie7: false})
+ : this.important = important,
+ this.isIE7 = ie7,
+ super(span);
+
+ String get property => isIE7 ? '*${_property.name}' : _property.name;
+ Expression get expression => _expression;
+
+ bool get hasDartStyle => dartStyle != null;
+
+ Declaration clone() => new Declaration(
+ _property.clone(), _expression.clone(), dartStyle, span,
+ important: important);
+
+ visit(VisitorBase visitor) => visitor.visitDeclaration(this);
+}
+
+// TODO(terry): Consider 2 kinds of VarDefinitions static at top-level and
+// dynamic when in a declaration. Currently, Less syntax
+// '@foo: expression' and 'var-foo: expression' in a declaration
+// are statically resolved. Better solution, if @foo or var-foo
+// are top-level are then statically resolved and var-foo in a
+// declaration group (surrounded by a selector) would be dynamic.
+class VarDefinition extends Declaration {
+ bool badUsage = false;
+
+ VarDefinition(Identifier definedName, Expression expr, SourceSpan span)
+ : super(definedName, expr, null, span);
+
+ String get definedName => _property.name;
+
+ VarDefinition clone() => new VarDefinition(
+ _property.clone(), expression != null ? expression.clone() : null, span);
+
+ visit(VisitorBase visitor) => visitor.visitVarDefinition(this);
+}
+
+/**
+ * Node for usage of @include mixin[(args,...)] found in a declaration group
+ * instead of at a ruleset (toplevel) e.g.,
+ * div {
+ * @include mixin1;
+ * }
+ */
+class IncludeMixinAtDeclaration extends Declaration {
+ final IncludeDirective include;
+
+ IncludeMixinAtDeclaration(this.include, SourceSpan span)
+ : super(null, null, null, span);
+
+ IncludeMixinAtDeclaration clone() =>
+ new IncludeMixinAtDeclaration(include.clone(), span);
+
+ visit(VisitorBase visitor) => visitor.visitIncludeMixinAtDeclaration(this);
+}
+
+class ExtendDeclaration extends Declaration {
+ final List<TreeNode> selectors;
+
+ ExtendDeclaration(this.selectors, SourceSpan span)
+ : super(null, null, null, span);
+
+ ExtendDeclaration clone() {
+ var newSelector = selectors.map((s) => s.clone()).toList();
+ return new ExtendDeclaration(newSelector, span);
+ }
+
+ visit(VisitorBase visitor) => visitor.visitExtendDeclaration(this);
+}
+
+class DeclarationGroup extends TreeNode {
+ /** Can be either Declaration or RuleSet (if nested selector). */
+ final List declarations;
+
+ DeclarationGroup(this.declarations, SourceSpan span) : super(span);
+
+ DeclarationGroup clone() {
+ var clonedDecls = declarations.map((d) => d.clone()).toList();
+ return new DeclarationGroup(clonedDecls, span);
+ }
+
+ visit(VisitorBase visitor) => visitor.visitDeclarationGroup(this);
+}
+
+class MarginGroup extends DeclarationGroup {
+ final int margin_sym; // TokenType for for @margin sym.
+
+ MarginGroup(this.margin_sym, List<Declaration> decls, SourceSpan span)
+ : super(decls, span);
+ MarginGroup clone() =>
+ new MarginGroup(margin_sym, super.clone() as dynamic, span);
+ visit(VisitorBase visitor) => visitor.visitMarginGroup(this);
+}
+
+class VarUsage extends Expression {
+ final String name;
+ final List<Expression> defaultValues;
+
+ VarUsage(this.name, this.defaultValues, SourceSpan span) : super(span);
+
+ VarUsage clone() {
+ var clonedValues = [];
+ for (var expr in defaultValues) {
+ clonedValues.add(expr.clone());
+ }
+ return new VarUsage(name, clonedValues, span);
+ }
+
+ visit(VisitorBase visitor) => visitor.visitVarUsage(this);
+}
+
+class OperatorSlash extends Expression {
+ OperatorSlash(SourceSpan span) : super(span);
+ OperatorSlash clone() => new OperatorSlash(span);
+ visit(VisitorBase visitor) => visitor.visitOperatorSlash(this);
+}
+
+class OperatorComma extends Expression {
+ OperatorComma(SourceSpan span) : super(span);
+ OperatorComma clone() => new OperatorComma(span);
+ visit(VisitorBase visitor) => visitor.visitOperatorComma(this);
+}
+
+class OperatorPlus extends Expression {
+ OperatorPlus(SourceSpan span) : super(span);
+ OperatorPlus clone() => new OperatorPlus(span);
+ visit(VisitorBase visitor) => visitor.visitOperatorPlus(this);
+}
+
+class OperatorMinus extends Expression {
+ OperatorMinus(SourceSpan span) : super(span);
+ OperatorMinus clone() => new OperatorMinus(span);
+ visit(VisitorBase visitor) => visitor.visitOperatorMinus(this);
+}
+
+class UnicodeRangeTerm extends Expression {
+ final String first;
+ final String second;
+
+ UnicodeRangeTerm(this.first, this.second, SourceSpan span) : super(span);
+
+ bool get hasSecond => second != null;
+
+ UnicodeRangeTerm clone() => new UnicodeRangeTerm(first, second, span);
+
+ visit(VisitorBase visitor) => visitor.visitUnicodeRangeTerm(this);
+}
+
+class LiteralTerm extends Expression {
+ // TODO(terry): value and text fields can be made final once all CSS resources
+ // are copied/symlink'd in the build tool and UriVisitor in
+ // web_ui is removed.
+ dynamic value;
+ String text;
+
+ LiteralTerm(this.value, this.text, SourceSpan span) : super(span);
+
+ LiteralTerm clone() => new LiteralTerm(value, text, span);
+
+ visit(VisitorBase visitor) => visitor.visitLiteralTerm(this);
+}
+
+class NumberTerm extends LiteralTerm {
+ NumberTerm(value, String t, SourceSpan span) : super(value, t, span);
+ NumberTerm clone() => new NumberTerm(value, text, span);
+ visit(VisitorBase visitor) => visitor.visitNumberTerm(this);
+}
+
+class UnitTerm extends LiteralTerm {
+ final int unit;
+
+ UnitTerm(value, String t, SourceSpan span, this.unit) : super(value, t, span);
+
+ UnitTerm clone() => new UnitTerm(value, text, span, unit);
+
+ visit(VisitorBase visitor) => visitor.visitUnitTerm(this);
+
+ String unitToString() => TokenKind.unitToString(unit);
+
+ String toString() => '$text${unitToString()}';
+}
+
+class LengthTerm extends UnitTerm {
+ LengthTerm(value, String t, SourceSpan span,
+ [int unit = TokenKind.UNIT_LENGTH_PX])
+ : super(value, t, span, unit) {
+ assert(this.unit == TokenKind.UNIT_LENGTH_PX ||
+ this.unit == TokenKind.UNIT_LENGTH_CM ||
+ this.unit == TokenKind.UNIT_LENGTH_MM ||
+ this.unit == TokenKind.UNIT_LENGTH_IN ||
+ this.unit == TokenKind.UNIT_LENGTH_PT ||
+ this.unit == TokenKind.UNIT_LENGTH_PC);
+ }
+ LengthTerm clone() => new LengthTerm(value, text, span, unit);
+ visit(VisitorBase visitor) => visitor.visitLengthTerm(this);
+}
+
+class PercentageTerm extends LiteralTerm {
+ PercentageTerm(value, String t, SourceSpan span) : super(value, t, span);
+ PercentageTerm clone() => new PercentageTerm(value, text, span);
+ visit(VisitorBase visitor) => visitor.visitPercentageTerm(this);
+}
+
+class EmTerm extends LiteralTerm {
+ EmTerm(value, String t, SourceSpan span) : super(value, t, span);
+ EmTerm clone() => new EmTerm(value, text, span);
+ visit(VisitorBase visitor) => visitor.visitEmTerm(this);
+}
+
+class ExTerm extends LiteralTerm {
+ ExTerm(value, String t, SourceSpan span) : super(value, t, span);
+ ExTerm clone() => new ExTerm(value, text, span);
+ visit(VisitorBase visitor) => visitor.visitExTerm(this);
+}
+
+class AngleTerm extends UnitTerm {
+ AngleTerm(var value, String t, SourceSpan span,
+ [int unit = TokenKind.UNIT_LENGTH_PX])
+ : super(value, t, span, unit) {
+ assert(this.unit == TokenKind.UNIT_ANGLE_DEG ||
+ this.unit == TokenKind.UNIT_ANGLE_RAD ||
+ this.unit == TokenKind.UNIT_ANGLE_GRAD ||
+ this.unit == TokenKind.UNIT_ANGLE_TURN);
+ }
+
+ AngleTerm clone() => new AngleTerm(value, text, span, unit);
+ visit(VisitorBase visitor) => visitor.visitAngleTerm(this);
+}
+
+class TimeTerm extends UnitTerm {
+ TimeTerm(var value, String t, SourceSpan span,
+ [int unit = TokenKind.UNIT_LENGTH_PX])
+ : super(value, t, span, unit) {
+ assert(this.unit == TokenKind.UNIT_ANGLE_DEG ||
+ this.unit == TokenKind.UNIT_TIME_MS ||
+ this.unit == TokenKind.UNIT_TIME_S);
+ }
+
+ TimeTerm clone() => new TimeTerm(value, text, span, unit);
+ visit(VisitorBase visitor) => visitor.visitTimeTerm(this);
+}
+
+class FreqTerm extends UnitTerm {
+ FreqTerm(var value, String t, SourceSpan span,
+ [int unit = TokenKind.UNIT_LENGTH_PX])
+ : super(value, t, span, unit) {
+ assert(unit == TokenKind.UNIT_FREQ_HZ || unit == TokenKind.UNIT_FREQ_KHZ);
+ }
+
+ FreqTerm clone() => new FreqTerm(value, text, span, unit);
+ visit(VisitorBase visitor) => visitor.visitFreqTerm(this);
+}
+
+class FractionTerm extends LiteralTerm {
+ FractionTerm(var value, String t, SourceSpan span) : super(value, t, span);
+
+ FractionTerm clone() => new FractionTerm(value, text, span);
+ visit(VisitorBase visitor) => visitor.visitFractionTerm(this);
+}
+
+class UriTerm extends LiteralTerm {
+ UriTerm(String value, SourceSpan span) : super(value, value, span);
+
+ UriTerm clone() => new UriTerm(value, span);
+ visit(VisitorBase visitor) => visitor.visitUriTerm(this);
+}
+
+class ResolutionTerm extends UnitTerm {
+ ResolutionTerm(var value, String t, SourceSpan span,
+ [int unit = TokenKind.UNIT_LENGTH_PX])
+ : super(value, t, span, unit) {
+ assert(unit == TokenKind.UNIT_RESOLUTION_DPI ||
+ unit == TokenKind.UNIT_RESOLUTION_DPCM ||
+ unit == TokenKind.UNIT_RESOLUTION_DPPX);
+ }
+
+ ResolutionTerm clone() => new ResolutionTerm(value, text, span, unit);
+ visit(VisitorBase visitor) => visitor.visitResolutionTerm(this);
+}
+
+class ChTerm extends UnitTerm {
+ ChTerm(var value, String t, SourceSpan span,
+ [int unit = TokenKind.UNIT_LENGTH_PX])
+ : super(value, t, span, unit) {
+ assert(unit == TokenKind.UNIT_CH);
+ }
+
+ ChTerm clone() => new ChTerm(value, text, span, unit);
+ visit(VisitorBase visitor) => visitor.visitChTerm(this);
+}
+
+class RemTerm extends UnitTerm {
+ RemTerm(var value, String t, SourceSpan span,
+ [int unit = TokenKind.UNIT_LENGTH_PX])
+ : super(value, t, span, unit) {
+ assert(unit == TokenKind.UNIT_REM);
+ }
+
+ RemTerm clone() => new RemTerm(value, text, span, unit);
+ visit(VisitorBase visitor) => visitor.visitRemTerm(this);
+}
+
+class ViewportTerm extends UnitTerm {
+ ViewportTerm(var value, String t, SourceSpan span,
+ [int unit = TokenKind.UNIT_LENGTH_PX])
+ : super(value, t, span, unit) {
+ assert(unit == TokenKind.UNIT_VIEWPORT_VW ||
+ unit == TokenKind.UNIT_VIEWPORT_VH ||
+ unit == TokenKind.UNIT_VIEWPORT_VMIN ||
+ unit == TokenKind.UNIT_VIEWPORT_VMAX);
+ }
+
+ ViewportTerm clone() => new ViewportTerm(value, text, span, unit);
+ visit(VisitorBase visitor) => visitor.visitViewportTerm(this);
+}
+
+/** Type to signal a bad hex value for HexColorTerm.value. */
+class BAD_HEX_VALUE {}
+
+class HexColorTerm extends LiteralTerm {
+ HexColorTerm(var value, String t, SourceSpan span) : super(value, t, span);
+
+ HexColorTerm clone() => new HexColorTerm(value, text, span);
+ visit(VisitorBase visitor) => visitor.visitHexColorTerm(this);
+}
+
+class FunctionTerm extends LiteralTerm {
+ final Expressions _params;
+
+ FunctionTerm(var value, String t, this._params, SourceSpan span)
+ : super(value, t, span);
+
+ FunctionTerm clone() => new FunctionTerm(value, text, _params.clone(), span);
+ visit(VisitorBase visitor) => visitor.visitFunctionTerm(this);
+}
+
+/**
+ * A "\9" was encountered at the end of the expression and before a semi-colon.
+ * This is an IE trick to ignore a property or value except by IE 8 and older
+ * browsers.
+ */
+class IE8Term extends LiteralTerm {
+ IE8Term(SourceSpan span) : super('\\9', '\\9', span);
+ IE8Term clone() => new IE8Term(span);
+ visit(VisitorBase visitor) => visitor.visitIE8Term(this);
+}
+
+class GroupTerm extends Expression {
+ final List<LiteralTerm> _terms;
+
+ GroupTerm(SourceSpan span)
+ : _terms = [],
+ super(span);
+
+ void add(LiteralTerm term) {
+ _terms.add(term);
+ }
+
+ GroupTerm clone() => new GroupTerm(span);
+ visit(VisitorBase visitor) => visitor.visitGroupTerm(this);
+}
+
+class ItemTerm extends NumberTerm {
+ ItemTerm(var value, String t, SourceSpan span) : super(value, t, span);
+
+ ItemTerm clone() => new ItemTerm(value, text, span);
+ visit(VisitorBase visitor) => visitor.visitItemTerm(this);
+}
+
+class Expressions extends Expression {
+ final List<Expression> expressions = [];
+
+ Expressions(SourceSpan span) : super(span);
+
+ void add(Expression expression) {
+ expressions.add(expression);
+ }
+
+ Expressions clone() {
+ var clonedExprs = new Expressions(span);
+ for (var expr in expressions) {
+ clonedExprs.add(expr.clone());
+ }
+ return clonedExprs;
+ }
+ visit(VisitorBase visitor) => visitor.visitExpressions(this);
+}
+
+class BinaryExpression extends Expression {
+ final Token op;
+ final Expression x;
+ final Expression y;
+
+ BinaryExpression(this.op, this.x, this.y, SourceSpan span) : super(span);
+
+ BinaryExpression clone() =>
+ new BinaryExpression(op, x.clone(), y.clone(), span);
+ visit(VisitorBase visitor) => visitor.visitBinaryExpression(this);
+}
+
+class UnaryExpression extends Expression {
+ final Token op;
+ final Expression self;
+
+ UnaryExpression(this.op, this.self, SourceSpan span) : super(span);
+
+ UnaryExpression clone() => new UnaryExpression(op, self.clone(), span);
+ visit(VisitorBase visitor) => visitor.visitUnaryExpression(this);
+}
+
+abstract class DartStyleExpression extends TreeNode {
+ static const int unknownType = 0;
+ static const int fontStyle = 1;
+ static const int marginStyle = 2;
+ static const int borderStyle = 3;
+ static const int paddingStyle = 4;
+ static const int heightStyle = 5;
+ static const int widthStyle = 6;
+
+ final int _styleType;
+ int priority;
+
+ DartStyleExpression(this._styleType, SourceSpan span) : super(span);
+
+ /*
+ * Merges give 2 DartStyleExpression (or derived from DartStyleExpression,
+ * e.g., FontExpression, etc.) will merge if the two expressions are of the
+ * same property name (implies same exact type e.g, FontExpression).
+ */
+ merged(DartStyleExpression newDartExpr);
+
+ bool get isUnknown => _styleType == 0 || _styleType == null;
+ bool get isFont => _styleType == fontStyle;
+ bool get isMargin => _styleType == marginStyle;
+ bool get isBorder => _styleType == borderStyle;
+ bool get isPadding => _styleType == paddingStyle;
+ bool get isHeight => _styleType == heightStyle;
+ bool get isWidth => _styleType == widthStyle;
+ bool get isBoxExpression => isMargin || isBorder || isPadding;
+
+ bool isSame(DartStyleExpression other) => this._styleType == other._styleType;
+
+ visit(VisitorBase visitor) => visitor.visitDartStyleExpression(this);
+}
+
+class FontExpression extends DartStyleExpression {
+ final Font font;
+
+ // font-style font-variant font-weight font-size/line-height font-family
+ // TODO(terry): Only px/pt for now need to handle all possible units to
+ // support calc expressions on units.
+ FontExpression(SourceSpan span, {dynamic size, List<String> family,
+ int weight, String style, String variant, LineHeight lineHeight})
+ : font = new Font(
+ size: size is LengthTerm ? size.value : size,
+ family: family,
+ weight: weight,
+ style: style,
+ variant: variant,
+ lineHeight: lineHeight),
+ super(DartStyleExpression.fontStyle, span);
+
+ FontExpression merged(DartStyleExpression newFontExpr) {
+ if (newFontExpr is FontExpression && this.isFont && newFontExpr.isFont) {
+ return new FontExpression.merge(this, newFontExpr);
+ }
+ return null;
+ }
+
+ /**
+ * Merge the two FontExpression and return the result.
+ */
+ factory FontExpression.merge(FontExpression x, FontExpression y) {
+ return new FontExpression._merge(x, y, y.span);
+ }
+
+ FontExpression._merge(FontExpression x, FontExpression y, SourceSpan span)
+ : font = new Font.merge(x.font, y.font),
+ super(DartStyleExpression.fontStyle, span);
+
+ FontExpression clone() => new FontExpression(span,
+ size: font.size,
+ family: font.family,
+ weight: font.weight,
+ style: font.style,
+ variant: font.variant,
+ lineHeight: font.lineHeight);
+
+ visit(VisitorBase visitor) => visitor.visitFontExpression(this);
+}
+
+abstract class BoxExpression extends DartStyleExpression {
+ final BoxEdge box;
+
+ BoxExpression(int styleType, SourceSpan span, this.box)
+ : super(styleType, span);
+
+ visit(VisitorBase visitor) => visitor.visitBoxExpression(this);
+
+ String get formattedBoxEdge {
+ if (box.top == box.left && box.top == box.bottom && box.top == box.right) {
+ return '.uniform(${box.top})';
+ } else {
+ var left = box.left == null ? 0 : box.left;
+ var top = box.top == null ? 0 : box.top;
+ var right = box.right == null ? 0 : box.right;
+ var bottom = box.bottom == null ? 0 : box.bottom;
+ return '.clockwiseFromTop($top,$right,$bottom,$left)';
+ }
+ }
+}
+
+class MarginExpression extends BoxExpression {
+ // TODO(terry): Does auto for margin need to be exposed to Dart UI framework?
+ /** Margin expression ripped apart. */
+ MarginExpression(SourceSpan span, {num top, num right, num bottom, num left})
+ : super(DartStyleExpression.marginStyle, span,
+ new BoxEdge(left, top, right, bottom));
+
+ MarginExpression.boxEdge(SourceSpan span, BoxEdge box)
+ : super(DartStyleExpression.marginStyle, span, box);
+
+ merged(DartStyleExpression newMarginExpr) {
+ if (newMarginExpr is MarginExpression &&
+ this.isMargin &&
+ newMarginExpr.isMargin) {
+ return new MarginExpression.merge(this, newMarginExpr);
+ }
+
+ return null;
+ }
+
+ /**
+ * Merge the two MarginExpressions and return the result.
+ */
+ factory MarginExpression.merge(MarginExpression x, MarginExpression y) {
+ return new MarginExpression._merge(x, y, y.span);
+ }
+
+ MarginExpression._merge(
+ MarginExpression x, MarginExpression y, SourceSpan span)
+ : super(x._styleType, span, new BoxEdge.merge(x.box, y.box));
+
+ MarginExpression clone() => new MarginExpression(span,
+ top: box.top, right: box.right, bottom: box.bottom, left: box.left);
+
+ visit(VisitorBase visitor) => visitor.visitMarginExpression(this);
+}
+
+class BorderExpression extends BoxExpression {
+ /** Border expression ripped apart. */
+ BorderExpression(SourceSpan span, {num top, num right, num bottom, num left})
+ : super(DartStyleExpression.borderStyle, span,
+ new BoxEdge(left, top, right, bottom));
+
+ BorderExpression.boxEdge(SourceSpan span, BoxEdge box)
+ : super(DartStyleExpression.borderStyle, span, box);
+
+ merged(DartStyleExpression newBorderExpr) {
+ if (newBorderExpr is BorderExpression &&
+ this.isBorder &&
+ newBorderExpr.isBorder) {
+ return new BorderExpression.merge(this, newBorderExpr);
+ }
+
+ return null;
+ }
+
+ /**
+ * Merge the two BorderExpression and return the result.
+ */
+ factory BorderExpression.merge(BorderExpression x, BorderExpression y) {
+ return new BorderExpression._merge(x, y, y.span);
+ }
+
+ BorderExpression._merge(
+ BorderExpression x, BorderExpression y, SourceSpan span)
+ : super(DartStyleExpression.borderStyle, span,
+ new BoxEdge.merge(x.box, y.box));
+
+ BorderExpression clone() => new BorderExpression(span,
+ top: box.top, right: box.right, bottom: box.bottom, left: box.left);
+
+ visit(VisitorBase visitor) => visitor.visitBorderExpression(this);
+}
+
+class HeightExpression extends DartStyleExpression {
+ final height;
+
+ HeightExpression(SourceSpan span, this.height)
+ : super(DartStyleExpression.heightStyle, span);
+
+ merged(DartStyleExpression newHeightExpr) {
+ if (newHeightExpr is DartStyleExpression &&
+ this.isHeight &&
+ newHeightExpr.isHeight) {
+ return newHeightExpr;
+ }
+
+ return null;
+ }
+
+ HeightExpression clone() => new HeightExpression(span, height);
+ visit(VisitorBase visitor) => visitor.visitHeightExpression(this);
+}
+
+class WidthExpression extends DartStyleExpression {
+ final width;
+
+ WidthExpression(SourceSpan span, this.width)
+ : super(DartStyleExpression.widthStyle, span);
+
+ merged(DartStyleExpression newWidthExpr) {
+ if (newWidthExpr is WidthExpression &&
+ this.isWidth &&
+ newWidthExpr.isWidth) {
+ return newWidthExpr;
+ }
+
+ return null;
+ }
+
+ WidthExpression clone() => new WidthExpression(span, width);
+ visit(VisitorBase visitor) => visitor.visitWidthExpression(this);
+}
+
+class PaddingExpression extends BoxExpression {
+ /** Padding expression ripped apart. */
+ PaddingExpression(SourceSpan span, {num top, num right, num bottom, num left})
+ : super(DartStyleExpression.paddingStyle, span,
+ new BoxEdge(left, top, right, bottom));
+
+ PaddingExpression.boxEdge(SourceSpan span, BoxEdge box)
+ : super(DartStyleExpression.paddingStyle, span, box);
+
+ merged(DartStyleExpression newPaddingExpr) {
+ if (newPaddingExpr is PaddingExpression &&
+ this.isPadding &&
+ newPaddingExpr.isPadding) {
+ return new PaddingExpression.merge(this, newPaddingExpr);
+ }
+
+ return null;
+ }
+
+ /**
+ * Merge the two PaddingExpression and return the result.
+ */
+ factory PaddingExpression.merge(PaddingExpression x, PaddingExpression y) {
+ return new PaddingExpression._merge(x, y, y.span);
+ }
+
+ PaddingExpression._merge(
+ PaddingExpression x, PaddingExpression y, SourceSpan span)
+ : super(DartStyleExpression.paddingStyle, span,
+ new BoxEdge.merge(x.box, y.box));
+
+ PaddingExpression clone() => new PaddingExpression(span,
+ top: box.top, right: box.right, bottom: box.bottom, left: box.left);
+ visit(VisitorBase visitor) => visitor.visitPaddingExpression(this);
+}
« no previous file with comments | « mojo/public/dart/third_party/csslib/lib/src/tokenkind.dart ('k') | mojo/public/dart/third_party/csslib/lib/src/tree_base.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698