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

Side by Side Diff: observatory_pub_packages/csslib/src/tree.dart

Issue 816693004: Add observatory_pub_packages snapshot to third_party (Closed) Base URL: http://dart.googlecode.com/svn/third_party/
Patch Set: Created 6 years 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of csslib.visitor;
6
7 /////////////////////////////////////////////////////////////////////////
8 // CSS specific types:
9 /////////////////////////////////////////////////////////////////////////
10
11 class Identifier extends TreeNode {
12 String name;
13
14 Identifier(this.name, SourceSpan span): super(span);
15
16 Identifier clone() => new Identifier(name, span);
17
18 visit(VisitorBase visitor) => visitor.visitIdentifier(this);
19
20 String toString() => name;
21 }
22
23 class Wildcard extends TreeNode {
24 Wildcard(SourceSpan span): super(span);
25 Wildcard clone() => new Wildcard(span);
26 visit(VisitorBase visitor) => visitor.visitWildcard(this);
27
28 String get name => '*';
29 }
30
31 class ThisOperator extends TreeNode {
32 ThisOperator(SourceSpan span): super(span);
33 ThisOperator clone() => new ThisOperator(span);
34 visit(VisitorBase visitor) => visitor.visitThisOperator(this);
35
36 String get name => '&';
37 }
38
39 class Negation extends TreeNode {
40 Negation(SourceSpan span): super(span);
41 Negation clone() => new Negation(span);
42 visit(VisitorBase visitor) => visitor.visitNegation(this);
43
44 String get name => 'not';
45 }
46
47 // /* .... */
48 class CssComment extends TreeNode {
49 final String comment;
50
51 CssComment(this.comment, SourceSpan span): super(span);
52 CssComment clone() => new CssComment(comment, span);
53 visit(VisitorBase visitor) => visitor.visitCssComment(this);
54 }
55
56 // CDO/CDC (Comment Definition Open <!-- and Comment Definition Close -->).
57 class CommentDefinition extends CssComment {
58 CommentDefinition(String comment, SourceSpan span): super(comment, span);
59 CommentDefinition clone() => new CommentDefinition(comment, span);
60 visit(VisitorBase visitor) => visitor.visitCommentDefinition(this);
61 }
62
63 class SelectorGroup extends TreeNode {
64 final List<Selector> selectors;
65
66 SelectorGroup(this.selectors, SourceSpan span): super(span);
67
68 SelectorGroup clone() => new SelectorGroup(selectors, span);
69
70 visit(VisitorBase visitor) => visitor.visitSelectorGroup(this);
71 }
72
73 class Selector extends TreeNode {
74 final List<SimpleSelectorSequence> simpleSelectorSequences;
75
76 Selector(this.simpleSelectorSequences, SourceSpan span) : super(span);
77
78 void add(SimpleSelectorSequence seq) => simpleSelectorSequences.add(seq);
79
80 int get length => simpleSelectorSequences.length;
81
82 Selector clone() {
83 var simpleSequences = simpleSelectorSequences
84 .map((ss) => ss.clone())
85 .toList();
86
87 return new Selector(simpleSequences, span);
88 }
89
90 visit(VisitorBase visitor) => visitor.visitSelector(this);
91 }
92
93 class SimpleSelectorSequence extends TreeNode {
94 /** +, >, ~, NONE */
95 int combinator;
96 final SimpleSelector simpleSelector;
97
98 SimpleSelectorSequence(this.simpleSelector, SourceSpan span,
99 [int combinator = TokenKind.COMBINATOR_NONE])
100 : combinator = combinator, super(span);
101
102 bool get isCombinatorNone => combinator == TokenKind.COMBINATOR_NONE;
103 bool get isCombinatorPlus => combinator == TokenKind.COMBINATOR_PLUS;
104 bool get isCombinatorGreater => combinator == TokenKind.COMBINATOR_GREATER;
105 bool get isCombinatorTilde => combinator == TokenKind.COMBINATOR_TILDE;
106 bool get isCombinatorDescendant =>
107 combinator == TokenKind.COMBINATOR_DESCENDANT;
108
109 String get _combinatorToString =>
110 isCombinatorDescendant ? ' ' :
111 isCombinatorPlus ? ' + ' :
112 isCombinatorGreater ? ' > ' :
113 isCombinatorTilde ? ' ~ ' : '';
114
115 SimpleSelectorSequence clone() =>
116 new SimpleSelectorSequence(simpleSelector, span, combinator);
117
118 visit(VisitorBase visitor) => visitor.visitSimpleSelectorSequence(this);
119
120 String toString() => simpleSelector.name;
121 }
122
123 /* All other selectors (element, #id, .class, attribute, pseudo, negation,
124 * namespace, *) are derived from this selector.
125 */
126 abstract class SimpleSelector extends TreeNode {
127 final _name; // Wildcard, ThisOperator, Identifier, Negation, others?
128
129 SimpleSelector(this._name, SourceSpan span) : super(span);
130
131 String get name => _name.name;
132
133 bool get isWildcard => _name is Wildcard;
134
135 bool get isThis => _name is ThisOperator;
136
137 visit(VisitorBase visitor) => visitor.visitSimpleSelector(this);
138 }
139
140 // element name
141 class ElementSelector extends SimpleSelector {
142 ElementSelector(name, SourceSpan span) : super(name, span);
143 visit(VisitorBase visitor) => visitor.visitElementSelector(this);
144
145 ElementSelector clone() => new ElementSelector(_name, span);
146
147 String toString() => name;
148 }
149
150 // namespace|element
151 class NamespaceSelector extends SimpleSelector {
152 final _namespace; // null, Wildcard or Identifier
153
154 NamespaceSelector(this._namespace, var name, SourceSpan span)
155 : super(name, span);
156
157 String get namespace =>
158 _namespace is Wildcard ? '*' : _namespace == null ? '' : _namespace.name;
159
160 bool get isNamespaceWildcard => _namespace is Wildcard;
161
162 SimpleSelector get nameAsSimpleSelector => _name;
163
164 NamespaceSelector clone() => new NamespaceSelector(_namespace, "", span);
165
166 visit(VisitorBase visitor) => visitor.visitNamespaceSelector(this);
167
168 String toString() => "$namespace|${nameAsSimpleSelector.name}";
169 }
170
171 // [attr op value]
172 class AttributeSelector extends SimpleSelector {
173 final int _op;
174 final _value;
175
176 AttributeSelector(Identifier name, this._op, this._value,
177 SourceSpan span) : super(name, span);
178
179 int get operatorKind => _op;
180
181 get value => _value;
182
183 String matchOperator() {
184 switch (_op) {
185 case TokenKind.EQUALS:
186 return '=';
187 case TokenKind.INCLUDES:
188 return '~=';
189 case TokenKind.DASH_MATCH:
190 return '|=';
191 case TokenKind.PREFIX_MATCH:
192 return '^=';
193 case TokenKind.SUFFIX_MATCH:
194 return '\$=';
195 case TokenKind.SUBSTRING_MATCH:
196 return '*=';
197 case TokenKind.NO_MATCH:
198 return '';
199 }
200 }
201
202 // Return the TokenKind for operator used by visitAttributeSelector.
203 String matchOperatorAsTokenString() {
204 switch (_op) {
205 case TokenKind.EQUALS:
206 return 'EQUALS';
207 case TokenKind.INCLUDES:
208 return 'INCLUDES';
209 case TokenKind.DASH_MATCH:
210 return 'DASH_MATCH';
211 case TokenKind.PREFIX_MATCH:
212 return 'PREFIX_MATCH';
213 case TokenKind.SUFFIX_MATCH:
214 return 'SUFFIX_MATCH';
215 case TokenKind.SUBSTRING_MATCH:
216 return 'SUBSTRING_MATCH';
217 }
218 }
219
220 String valueToString() {
221 if (_value != null) {
222 if (_value is Identifier) {
223 return _value.name;
224 } else {
225 return '"${_value}"';
226 }
227 } else {
228 return '';
229 }
230 }
231
232 AttributeSelector clone() => new AttributeSelector(_name, _op, _value, span);
233
234 visit(VisitorBase visitor) => visitor.visitAttributeSelector(this);
235
236 String toString() => "[$name${matchOperator()}${valueToString()}]";
237 }
238
239 // #id
240 class IdSelector extends SimpleSelector {
241 IdSelector(Identifier name, SourceSpan span) : super(name, span);
242 IdSelector clone() => new IdSelector(_name, span);
243 visit(VisitorBase visitor) => visitor.visitIdSelector(this);
244
245 String toString() => "#$_name";
246 }
247
248 // .class
249 class ClassSelector extends SimpleSelector {
250 ClassSelector(Identifier name, SourceSpan span) : super(name, span);
251 ClassSelector clone() => new ClassSelector(_name, span);
252 visit(VisitorBase visitor) => visitor.visitClassSelector(this);
253
254 String toString() => ".$_name";
255 }
256
257 // :pseudoClass
258 class PseudoClassSelector extends SimpleSelector {
259 PseudoClassSelector(Identifier name, SourceSpan span) : super(name, span);
260 visit(VisitorBase visitor) => visitor.visitPseudoClassSelector(this);
261
262 PseudoClassSelector clone() => new PseudoClassSelector(_name, span);
263
264 String toString() => ":$name";
265 }
266
267 // ::pseudoElement
268 class PseudoElementSelector extends SimpleSelector {
269 PseudoElementSelector(Identifier name, SourceSpan span) : super(name, span);
270 visit(VisitorBase visitor) => visitor.visitPseudoElementSelector(this);
271
272 PseudoElementSelector clone() => new PseudoElementSelector(_name, span);
273
274 String toString() => "::$name";
275 }
276
277 // :pseudoClassFunction(expression)
278 class PseudoClassFunctionSelector extends PseudoClassSelector {
279 final SelectorExpression expression;
280
281 PseudoClassFunctionSelector(Identifier name, this.expression, SourceSpan span)
282 : super(name, span);
283
284 PseudoClassFunctionSelector clone() =>
285 new PseudoClassFunctionSelector(_name, expression, span);
286
287 visit(VisitorBase visitor) =>
288 visitor.visitPseudoClassFunctionSelector(this);
289 }
290
291 // ::pseudoElementFunction(expression)
292 class PseudoElementFunctionSelector extends PseudoElementSelector {
293 final SelectorExpression expression;
294
295 PseudoElementFunctionSelector(Identifier name, this.expression,
296 SourceSpan span)
297 : super(name, span);
298
299 PseudoElementFunctionSelector clone() =>
300 new PseudoElementFunctionSelector(_name, expression, span);
301
302 visit(VisitorBase visitor) =>
303 visitor.visitPseudoElementFunctionSelector(this);
304 }
305
306 class SelectorExpression extends TreeNode {
307 final List<Expression> expressions;
308
309 SelectorExpression(this.expressions, SourceSpan span): super(span);
310
311 SelectorExpression clone() {
312 return new SelectorExpression(
313 expressions.map((e) => e.clone()).toList(), span);
314 }
315
316 visit(VisitorBase visitor) => visitor.visitSelectorExpression(this);
317 }
318
319 // :NOT(negation_arg)
320 class NegationSelector extends SimpleSelector {
321 final SimpleSelector negationArg;
322
323 NegationSelector(this.negationArg, SourceSpan span)
324 : super(new Negation(span), span);
325
326 NegationSelector clone() => new NegationSelector(negationArg, span);
327
328 visit(VisitorBase visitor) => visitor.visitNegationSelector(this);
329 }
330
331 class NoOp extends TreeNode {
332 NoOp() : super(null);
333
334 NoOp clone() => new NoOp();
335
336 visit(VisitorBase visitor) => visitor.visitNoOp(this);
337 }
338
339 class StyleSheet extends TreeNode {
340 /**
341 * Contains charset, ruleset, directives (media, page, etc.), and selectors.
342 */
343 final List<TreeNode> topLevels;
344
345 StyleSheet(this.topLevels, SourceSpan span) : super(span) {
346 for (final node in topLevels) {
347 assert(node is TopLevelProduction || node is Directive);
348 }
349 }
350
351 /** Selectors only in this tree. */
352 StyleSheet.selector(this.topLevels, SourceSpan span) : super(span);
353
354 StyleSheet clone() {
355 var clonedTopLevels = topLevels.map((e) => e.clone()).toList();
356 return new StyleSheet(clonedTopLevels, span);
357 }
358
359 visit(VisitorBase visitor) => visitor.visitStyleSheet(this);
360 }
361
362 class TopLevelProduction extends TreeNode {
363 TopLevelProduction(SourceSpan span) : super(span);
364 TopLevelProduction clone() => new TopLevelProduction(span);
365 visit(VisitorBase visitor) => visitor.visitTopLevelProduction(this);
366 }
367
368 class RuleSet extends TopLevelProduction {
369 final SelectorGroup _selectorGroup;
370 final DeclarationGroup _declarationGroup;
371
372 RuleSet(this._selectorGroup, this._declarationGroup, SourceSpan span)
373 : super(span);
374
375 SelectorGroup get selectorGroup => _selectorGroup;
376 DeclarationGroup get declarationGroup => _declarationGroup;
377
378 RuleSet clone() {
379 var cloneSelectorGroup = _selectorGroup.clone();
380 var cloneDeclarationGroup = _declarationGroup.clone();
381 return new RuleSet(cloneSelectorGroup, cloneDeclarationGroup, span);
382 }
383
384 visit(VisitorBase visitor) => visitor.visitRuleSet(this);
385 }
386
387 class Directive extends TreeNode {
388 Directive(SourceSpan span) : super(span);
389
390 bool get isBuiltIn => true; // Known CSS directive?
391 bool get isExtension => false; // SCSS extension?
392
393 Directive clone() => new Directive(span);
394 visit(VisitorBase visitor) => visitor.visitDirective(this);
395 }
396
397 class ImportDirective extends Directive {
398 /** import name specified. */
399 final String import;
400
401 /** Any media queries for this import. */
402 final List<MediaQuery> mediaQueries;
403
404 ImportDirective(this.import, this.mediaQueries, SourceSpan span)
405 : super(span);
406
407 ImportDirective clone() {
408 var cloneMediaQueries = [];
409 for (var mediaQuery in mediaQueries) {
410 cloneMediaQueries.add(mediaQuery.clone());
411 }
412 return new ImportDirective(import, cloneMediaQueries, span);
413 }
414
415 visit(VisitorBase visitor) => visitor.visitImportDirective(this);
416 }
417
418 /**
419 * MediaExpression grammar:
420 * '(' S* media_feature S* [ ':' S* expr ]? ')' S*
421 */
422 class MediaExpression extends TreeNode {
423 final bool andOperator;
424 final Identifier _mediaFeature;
425 final Expressions exprs;
426
427 MediaExpression(this.andOperator, this._mediaFeature, this.exprs,
428 SourceSpan span)
429 : super(span);
430
431 String get mediaFeature => _mediaFeature.name;
432
433 MediaExpression clone() {
434 var clonedExprs = exprs.clone();
435 return new MediaExpression(andOperator, _mediaFeature, clonedExprs, span);
436 }
437
438 visit(VisitorBase visitor) => visitor.visitMediaExpression(this);
439 }
440
441 /**
442 * MediaQuery grammar:
443 * : [ONLY | NOT]? S* media_type S* [ AND S* media_expression ]*
444 * | media_expression [ AND S* media_expression ]*
445 * media_type
446 * : IDENT
447 * media_expression
448 * : '(' S* media_feature S* [ ':' S* expr ]? ')' S*
449 * media_feature
450 * : IDENT
451 */
452 class MediaQuery extends TreeNode {
453 /** not, only or no operator. */
454 final int _mediaUnary;
455 final Identifier _mediaType;
456 final List<MediaExpression> expressions;
457
458 MediaQuery(this._mediaUnary, this._mediaType, this.expressions,
459 SourceSpan span)
460 : super(span);
461
462 bool get hasMediaType => _mediaType != null;
463 String get mediaType => _mediaType.name;
464
465 bool get hasUnary => _mediaUnary != -1;
466 String get unary =>
467 TokenKind.idToValue(TokenKind.MEDIA_OPERATORS, _mediaUnary).toUpperCase();
468
469 MediaQuery clone() {
470 var cloneExpressions = [];
471 for (var expr in expressions) {
472 cloneExpressions.add(expr.clone());
473 }
474 return new MediaQuery(_mediaUnary, _mediaType, cloneExpressions, span);
475 }
476 visit(VisitorBase visitor) => visitor.visitMediaQuery(this);
477 }
478
479 class MediaDirective extends Directive {
480 final List<MediaQuery> mediaQueries;
481 final List<RuleSet> rulesets;
482
483 MediaDirective(this.mediaQueries, this.rulesets, SourceSpan span)
484 : super(span);
485
486 MediaDirective clone() {
487 var cloneQueries = [];
488 for (var mediaQuery in mediaQueries) {
489 cloneQueries.add(mediaQuery.clone());
490 }
491 var cloneRulesets = [];
492 for (var ruleset in rulesets) {
493 cloneRulesets.add(ruleset.clone());
494 }
495 return new MediaDirective(cloneQueries, cloneRulesets, span);
496 }
497
498 visit(VisitorBase visitor) => visitor.visitMediaDirective(this);
499 }
500
501 class HostDirective extends Directive {
502 final List<RuleSet> rulesets;
503
504 HostDirective(this.rulesets, SourceSpan span) : super(span);
505
506 HostDirective clone() {
507 var cloneRulesets = [];
508 for (var ruleset in rulesets) {
509 cloneRulesets.add(ruleset.clone());
510 }
511 return new HostDirective(cloneRulesets, span);
512 }
513
514 visit(VisitorBase visitor) => visitor.visitHostDirective(this);
515 }
516
517 class PageDirective extends Directive {
518 final String _ident;
519 final String _pseudoPage;
520 final List<DeclarationGroup> _declsMargin;
521
522 PageDirective(this._ident, this._pseudoPage, this._declsMargin,
523 SourceSpan span) : super(span);
524
525 PageDirective clone() {
526 var cloneDeclsMargin = [];
527 for (var declMargin in _declsMargin) {
528 cloneDeclsMargin.add(declMargin.clone());
529 }
530 return new PageDirective(_ident, _pseudoPage, cloneDeclsMargin, span);
531 }
532
533 visit(VisitorBase visitor) => visitor.visitPageDirective(this);
534
535 bool get hasIdent => _ident != null && _ident.length > 0;
536 bool get hasPseudoPage => _pseudoPage != null && _pseudoPage.length > 0;
537 }
538
539 class CharsetDirective extends Directive {
540 final String charEncoding;
541
542 CharsetDirective(this.charEncoding, SourceSpan span) : super(span);
543 CharsetDirective clone() => new CharsetDirective(charEncoding, span);
544 visit(VisitorBase visitor) => visitor.visitCharsetDirective(this);
545 }
546
547 class KeyFrameDirective extends Directive {
548 /*
549 * Either @keyframe or keyframe prefixed with @-webkit-, @-moz-, @-ms-, @-o-.
550 */
551 final int _keyframeName;
552 final name;
553 final List<KeyFrameBlock> _blocks;
554
555 KeyFrameDirective(this._keyframeName, this.name, SourceSpan span)
556 : _blocks = [], super(span);
557
558 add(KeyFrameBlock block) {
559 _blocks.add(block);
560 }
561
562 String get keyFrameName {
563 switch (_keyframeName) {
564 case TokenKind.DIRECTIVE_KEYFRAMES:
565 case TokenKind.DIRECTIVE_MS_KEYFRAMES:
566 return '@keyframes';
567 case TokenKind.DIRECTIVE_WEB_KIT_KEYFRAMES: return '@-webkit-keyframes';
568 case TokenKind.DIRECTIVE_MOZ_KEYFRAMES: return '@-moz-keyframes';
569 case TokenKind.DIRECTIVE_O_KEYFRAMES: return '@-o-keyframes';
570 }
571 }
572
573 KeyFrameDirective clone() {
574 var cloneBlocks = [];
575 for (var block in _blocks) {
576 cloneBlocks.add(block.clone());
577 }
578 return new KeyFrameDirective(_keyframeName, cloneBlocks, span);
579 }
580 visit(VisitorBase visitor) => visitor.visitKeyFrameDirective(this);
581 }
582
583 class KeyFrameBlock extends Expression {
584 final Expressions _blockSelectors;
585 final DeclarationGroup _declarations;
586
587 KeyFrameBlock(this._blockSelectors, this._declarations, SourceSpan span)
588 : super(span);
589
590 KeyFrameBlock clone() =>
591 new KeyFrameBlock(_blockSelectors.clone(), _declarations.clone(), span);
592 visit(VisitorBase visitor) => visitor.visitKeyFrameBlock(this);
593 }
594
595 class FontFaceDirective extends Directive {
596 final DeclarationGroup _declarations;
597
598 FontFaceDirective(this._declarations, SourceSpan span) : super(span);
599
600 FontFaceDirective clone() =>
601 new FontFaceDirective(_declarations.clone(), span);
602 visit(VisitorBase visitor) => visitor.visitFontFaceDirective(this);
603 }
604
605 class StyletDirective extends Directive {
606 final String dartClassName;
607 final List<RuleSet> rulesets;
608
609 StyletDirective(this.dartClassName, this.rulesets, SourceSpan span)
610 : super(span);
611
612 bool get isBuiltIn => false;
613 bool get isExtension => true;
614
615 StyletDirective clone() {
616 var cloneRulesets = [];
617 for (var ruleset in rulesets) {
618 cloneRulesets.add(ruleset.clone());
619 }
620 return new StyletDirective(dartClassName, cloneRulesets, span);
621 }
622
623 visit(VisitorBase visitor) => visitor.visitStyletDirective(this);
624 }
625
626 class NamespaceDirective extends Directive {
627 /** Namespace prefix. */
628 final String _prefix;
629
630 /** URI associated with this namespace. */
631 final String _uri;
632
633 NamespaceDirective(this._prefix, this._uri, SourceSpan span) : super(span);
634
635 NamespaceDirective clone() => new NamespaceDirective(_prefix, _uri, span);
636
637 visit(VisitorBase visitor) => visitor.visitNamespaceDirective(this);
638
639 String get prefix => _prefix.length > 0 ? '$_prefix ' : '';
640 }
641
642 /** To support Less syntax @name: expression */
643 class VarDefinitionDirective extends Directive {
644 final VarDefinition def;
645
646 VarDefinitionDirective(this.def, SourceSpan span) : super(span);
647
648 VarDefinitionDirective clone() =>
649 new VarDefinitionDirective(def.clone(), span);
650
651 visit(VisitorBase visitor) => visitor.visitVarDefinitionDirective(this);
652 }
653
654 class MixinDefinition extends Directive {
655 final String name;
656 final List definedArgs;
657 final bool varArgs;
658
659 MixinDefinition(this.name, this.definedArgs, this.varArgs, SourceSpan span)
660 : super(span);
661
662 MixinDefinition clone() {
663 var cloneDefinedArgs = [];
664 for (var definedArg in definedArgs) {
665 cloneDefinedArgs.add(definedArg.clone());
666 }
667 return new MixinDefinition(name, cloneDefinedArgs, varArgs, span);
668 }
669
670 visit(VisitorBase visitor) => visitor.visitMixinDefinition(this);
671 }
672
673 /** Support a Sass @mixin. See http://sass-lang.com for description. */
674 class MixinRulesetDirective extends MixinDefinition {
675 final List<RuleSet> rulesets;
676
677 MixinRulesetDirective(String name, List<VarDefinitionDirective> args,
678 bool varArgs, this.rulesets, SourceSpan span) :
679 super(name, args, varArgs, span);
680
681 MixinRulesetDirective clone() {
682 var clonedArgs = [];
683 for (var arg in definedArgs) {
684 clonedArgs.add(arg.clone());
685 }
686 var clonedRulesets = [];
687 for (var ruleset in rulesets) {
688 clonedRulesets.add(ruleset.clone());
689 }
690 return new MixinRulesetDirective(name, clonedArgs, varArgs, clonedRulesets,
691 span);
692 }
693
694 visit(VisitorBase visitor) => visitor.visitMixinRulesetDirective(this);
695 }
696
697 class MixinDeclarationDirective extends MixinDefinition {
698 final DeclarationGroup declarations;
699
700 MixinDeclarationDirective(String name, List<VarDefinitionDirective> args,
701 bool varArgs, this.declarations, SourceSpan span) :
702 super(name, args, varArgs, span);
703
704 MixinDeclarationDirective clone() {
705 var clonedArgs = [];
706 for (var arg in definedArgs) {
707 clonedArgs.add(arg.clone());
708 }
709 return new MixinDeclarationDirective(name, clonedArgs, varArgs,
710 declarations.clone(), span);
711 }
712
713 visit(VisitorBase visitor) => visitor.visitMixinDeclarationDirective(this);
714 }
715
716 /** To support consuming a SASS mixin @include. */
717 class IncludeDirective extends Directive {
718 final String name;
719 final List<List<TreeNode>> args;
720
721 IncludeDirective(this.name, this.args, SourceSpan span) : super(span);
722
723 IncludeDirective clone() {
724 var cloneArgs = [];
725 for (var arg in args) {
726 for (var term in arg) {
727 cloneArgs.add(term.clone());
728 }
729 }
730 return new IncludeDirective(name, cloneArgs, span);
731 }
732
733 visit(VisitorBase visitor) => visitor.visitIncludeDirective(this);
734 }
735
736 /** To support SASS @content. */
737 class ContentDirective extends Directive {
738 ContentDirective(SourceSpan span) : super(span);
739
740 visit(VisitorBase visitor) => visitor.visitContentDirective(this);
741 }
742
743 class Declaration extends TreeNode {
744 final Identifier _property;
745 final Expression _expression;
746 /** Style exposed to Dart. */
747 dynamic dartStyle;
748 final bool important;
749
750 /**
751 * IE CSS hacks that can only be read by a particular IE version.
752 * 7 implies IE 7 or older property (e.g., *background: blue;)
753 * Note: IE 8 or older property (e.g., background: green\9;) is handled
754 * by IE8Term in declaration expression handling.
755 * Note: IE 6 only property with a leading underscore is a valid IDENT
756 * since an ident can start with underscore (e.g., _background: red;)
757 */
758 final bool isIE7;
759
760 Declaration(this._property, this._expression, this.dartStyle, SourceSpan span,
761 {important: false, ie7: false})
762 : this.important = important, this.isIE7 = ie7, super(span);
763
764 String get property => isIE7 ? '*${_property.name}' : _property.name;
765 Expression get expression => _expression;
766
767 bool get hasDartStyle => dartStyle != null;
768
769 Declaration clone() =>
770 new Declaration(_property.clone(), _expression.clone(), dartStyle, span,
771 important: important);
772
773 visit(VisitorBase visitor) => visitor.visitDeclaration(this);
774 }
775
776 // TODO(terry): Consider 2 kinds of VarDefinitions static at top-level and
777 // dynamic when in a declaration. Currently, Less syntax
778 // '@foo: expression' and 'var-foo: expression' in a declaration
779 // are statically resolved. Better solution, if @foo or var-foo
780 // are top-level are then statically resolved and var-foo in a
781 // declaration group (surrounded by a selector) would be dynamic.
782 class VarDefinition extends Declaration {
783 bool badUsage = false;
784
785 VarDefinition(Identifier definedName, Expression expr, SourceSpan span)
786 : super(definedName, expr, null, span);
787
788 String get definedName => _property.name;
789
790 VarDefinition clone() =>
791 new VarDefinition(_property.clone(),
792 expression != null ? expression.clone() : null, span);
793
794 visit(VisitorBase visitor) => visitor.visitVarDefinition(this);
795 }
796
797 /**
798 * Node for usage of @include mixin[(args,...)] found in a declaration group
799 * instead of at a ruleset (toplevel) e.g.,
800 * div {
801 * @include mixin1;
802 * }
803 */
804 class IncludeMixinAtDeclaration extends Declaration {
805 final IncludeDirective include;
806
807 IncludeMixinAtDeclaration(this.include, SourceSpan span)
808 : super(null, null, null, span);
809
810 IncludeMixinAtDeclaration clone() =>
811 new IncludeMixinAtDeclaration(include.clone(), span);
812
813 visit(VisitorBase visitor) =>
814 visitor.visitIncludeMixinAtDeclaration(this);
815 }
816
817 class ExtendDeclaration extends Declaration {
818 final List<TreeNode> selectors;
819
820 ExtendDeclaration(this.selectors, SourceSpan span) :
821 super(null, null, null, span);
822
823 ExtendDeclaration clone() {
824 var newSelector = selectors.map((s) => s.clone()).toList();
825 return new ExtendDeclaration(newSelector, span);
826 }
827
828 visit(VisitorBase visitor) => visitor.visitExtendDeclaration(this);
829 }
830
831 class DeclarationGroup extends TreeNode {
832 /** Can be either Declaration or RuleSet (if nested selector). */
833 final List declarations;
834
835 DeclarationGroup(this.declarations, SourceSpan span) : super(span);
836
837 DeclarationGroup clone() {
838 var clonedDecls = declarations.map((d) => d.clone()).toList();
839 return new DeclarationGroup(clonedDecls, span);
840 }
841
842 visit(VisitorBase visitor) => visitor.visitDeclarationGroup(this);
843 }
844
845 class MarginGroup extends DeclarationGroup {
846 final int margin_sym; // TokenType for for @margin sym.
847
848 MarginGroup(this.margin_sym, List<Declaration> decls, SourceSpan span)
849 : super(decls, span);
850 MarginGroup clone() =>
851 new MarginGroup(margin_sym, super.clone() as dynamic, span);
852 visit(VisitorBase visitor) => visitor.visitMarginGroup(this);
853 }
854
855 class VarUsage extends Expression {
856 final String name;
857 final List<Expression> defaultValues;
858
859 VarUsage(this.name, this.defaultValues, SourceSpan span) : super(span);
860
861 VarUsage clone() {
862 var clonedValues = [];
863 for (var expr in defaultValues) {
864 clonedValues.add(expr.clone());
865 }
866 return new VarUsage(name, clonedValues, span);
867 }
868
869 visit(VisitorBase visitor) => visitor.visitVarUsage(this);
870 }
871
872 class OperatorSlash extends Expression {
873 OperatorSlash(SourceSpan span) : super(span);
874 OperatorSlash clone() => new OperatorSlash(span);
875 visit(VisitorBase visitor) => visitor.visitOperatorSlash(this);
876 }
877
878 class OperatorComma extends Expression {
879 OperatorComma(SourceSpan span) : super(span);
880 OperatorComma clone() => new OperatorComma(span);
881 visit(VisitorBase visitor) => visitor.visitOperatorComma(this);
882 }
883
884 class OperatorPlus extends Expression {
885 OperatorPlus(SourceSpan span) : super(span);
886 OperatorPlus clone() => new OperatorPlus(span);
887 visit(VisitorBase visitor) => visitor.visitOperatorPlus(this);
888 }
889
890 class OperatorMinus extends Expression {
891 OperatorMinus(SourceSpan span) : super(span);
892 OperatorMinus clone() => new OperatorMinus(span);
893 visit(VisitorBase visitor) => visitor.visitOperatorMinus(this);
894 }
895
896 class UnicodeRangeTerm extends Expression {
897 final String first;
898 final String second;
899
900 UnicodeRangeTerm(this.first, this.second, SourceSpan span) : super(span);
901
902 bool get hasSecond => second != null;
903
904 UnicodeRangeTerm clone() => new UnicodeRangeTerm(first, second, span);
905
906 visit(VisitorBase visitor) => visitor.visitUnicodeRangeTerm(this);
907 }
908
909 class LiteralTerm extends Expression {
910 // TODO(terry): value and text fields can be made final once all CSS resources
911 // are copied/symlink'd in the build tool and UriVisitor in
912 // web_ui is removed.
913 dynamic value;
914 String text;
915
916 LiteralTerm(this.value, this.text, SourceSpan span) : super(span);
917
918 LiteralTerm clone() => new LiteralTerm(value, text, span);
919
920 visit(VisitorBase visitor) => visitor.visitLiteralTerm(this);
921 }
922
923 class NumberTerm extends LiteralTerm {
924 NumberTerm(value, String t, SourceSpan span) : super(value, t, span);
925 NumberTerm clone() => new NumberTerm(value, text, span);
926 visit(VisitorBase visitor) => visitor.visitNumberTerm(this);
927 }
928
929 class UnitTerm extends LiteralTerm {
930 final int unit;
931
932 UnitTerm(value, String t, SourceSpan span, this.unit) : super(value, t, span);
933
934 UnitTerm clone() => new UnitTerm(value, text, span, unit);
935
936 visit(VisitorBase visitor) => visitor.visitUnitTerm(this);
937
938 String unitToString() => TokenKind.unitToString(unit);
939
940 String toString() => '$text${unitToString()}';
941 }
942
943 class LengthTerm extends UnitTerm {
944 LengthTerm(value, String t, SourceSpan span,
945 [int unit = TokenKind.UNIT_LENGTH_PX]) : super(value, t, span, unit) {
946 assert(this.unit == TokenKind.UNIT_LENGTH_PX ||
947 this.unit == TokenKind.UNIT_LENGTH_CM ||
948 this.unit == TokenKind.UNIT_LENGTH_MM ||
949 this.unit == TokenKind.UNIT_LENGTH_IN ||
950 this.unit == TokenKind.UNIT_LENGTH_PT ||
951 this.unit == TokenKind.UNIT_LENGTH_PC);
952 }
953 LengthTerm clone() => new LengthTerm(value, text, span, unit);
954 visit(VisitorBase visitor) => visitor.visitLengthTerm(this);
955 }
956
957 class PercentageTerm extends LiteralTerm {
958 PercentageTerm(value, String t, SourceSpan span) : super(value, t, span);
959 PercentageTerm clone() => new PercentageTerm(value, text, span);
960 visit(VisitorBase visitor) => visitor.visitPercentageTerm(this);
961 }
962
963 class EmTerm extends LiteralTerm {
964 EmTerm(value, String t, SourceSpan span) : super(value, t, span);
965 EmTerm clone() => new EmTerm(value, text, span);
966 visit(VisitorBase visitor) => visitor.visitEmTerm(this);
967 }
968
969 class ExTerm extends LiteralTerm {
970 ExTerm(value, String t, SourceSpan span) : super(value, t, span);
971 ExTerm clone() => new ExTerm(value, text, span);
972 visit(VisitorBase visitor) => visitor.visitExTerm(this);
973 }
974
975 class AngleTerm extends UnitTerm {
976 AngleTerm(var value, String t, SourceSpan span,
977 [int unit = TokenKind.UNIT_LENGTH_PX]) : super(value, t, span, unit) {
978 assert(this.unit == TokenKind.UNIT_ANGLE_DEG ||
979 this.unit == TokenKind.UNIT_ANGLE_RAD ||
980 this.unit == TokenKind.UNIT_ANGLE_GRAD ||
981 this.unit == TokenKind.UNIT_ANGLE_TURN);
982 }
983
984 AngleTerm clone() => new AngleTerm(value, text, span, unit);
985 visit(VisitorBase visitor) => visitor.visitAngleTerm(this);
986 }
987
988 class TimeTerm extends UnitTerm {
989 TimeTerm(var value, String t, SourceSpan span,
990 [int unit = TokenKind.UNIT_LENGTH_PX]) : super(value, t, span, unit) {
991 assert(this.unit == TokenKind.UNIT_ANGLE_DEG ||
992 this.unit == TokenKind.UNIT_TIME_MS ||
993 this.unit == TokenKind.UNIT_TIME_S);
994 }
995
996 TimeTerm clone() => new TimeTerm(value, text, span, unit);
997 visit(VisitorBase visitor) => visitor.visitTimeTerm(this);
998 }
999
1000 class FreqTerm extends UnitTerm {
1001 FreqTerm(var value, String t, SourceSpan span,
1002 [int unit = TokenKind.UNIT_LENGTH_PX]) : super(value, t, span, unit) {
1003 assert(unit == TokenKind.UNIT_FREQ_HZ || unit == TokenKind.UNIT_FREQ_KHZ);
1004 }
1005
1006 FreqTerm clone() => new FreqTerm(value, text, span, unit);
1007 visit(VisitorBase visitor) => visitor.visitFreqTerm(this);
1008 }
1009
1010 class FractionTerm extends LiteralTerm {
1011 FractionTerm(var value, String t, SourceSpan span) : super(value, t, span);
1012
1013 FractionTerm clone() => new FractionTerm(value, text, span);
1014 visit(VisitorBase visitor) => visitor.visitFractionTerm(this);
1015 }
1016
1017 class UriTerm extends LiteralTerm {
1018 UriTerm(String value, SourceSpan span) : super(value, value, span);
1019
1020 UriTerm clone() => new UriTerm(value, span);
1021 visit(VisitorBase visitor) => visitor.visitUriTerm(this);
1022 }
1023
1024 class ResolutionTerm extends UnitTerm {
1025 ResolutionTerm(var value, String t, SourceSpan span,
1026 [int unit = TokenKind.UNIT_LENGTH_PX]) : super(value, t, span, unit) {
1027 assert(unit == TokenKind.UNIT_RESOLUTION_DPI ||
1028 unit == TokenKind.UNIT_RESOLUTION_DPCM ||
1029 unit == TokenKind.UNIT_RESOLUTION_DPPX);
1030 }
1031
1032 ResolutionTerm clone() => new ResolutionTerm(value, text, span, unit);
1033 visit(VisitorBase visitor) => visitor.visitResolutionTerm(this);
1034 }
1035
1036 class ChTerm extends UnitTerm {
1037 ChTerm(var value, String t, SourceSpan span,
1038 [int unit = TokenKind.UNIT_LENGTH_PX]) : super(value, t, span, unit) {
1039 assert(unit == TokenKind.UNIT_CH);
1040 }
1041
1042 ChTerm clone() => new ChTerm(value, text, span, unit);
1043 visit(VisitorBase visitor) => visitor.visitChTerm(this);
1044 }
1045
1046 class RemTerm extends UnitTerm {
1047 RemTerm(var value, String t, SourceSpan span,
1048 [int unit = TokenKind.UNIT_LENGTH_PX]) : super(value, t, span, unit) {
1049 assert(unit == TokenKind.UNIT_REM);
1050 }
1051
1052 RemTerm clone() => new RemTerm(value, text, span, unit);
1053 visit(VisitorBase visitor) => visitor.visitRemTerm(this);
1054 }
1055
1056 class ViewportTerm extends UnitTerm {
1057 ViewportTerm(var value, String t, SourceSpan span,
1058 [int unit = TokenKind.UNIT_LENGTH_PX]) : super(value, t, span, unit) {
1059 assert(unit == TokenKind.UNIT_VIEWPORT_VW ||
1060 unit == TokenKind.UNIT_VIEWPORT_VH ||
1061 unit == TokenKind.UNIT_VIEWPORT_VMIN ||
1062 unit == TokenKind.UNIT_VIEWPORT_VMAX);
1063 }
1064
1065 ViewportTerm clone() => new ViewportTerm(value, text, span, unit);
1066 visit(VisitorBase visitor) => visitor.visitViewportTerm(this);
1067 }
1068
1069 /** Type to signal a bad hex value for HexColorTerm.value. */
1070 class BAD_HEX_VALUE { }
1071
1072 class HexColorTerm extends LiteralTerm {
1073 HexColorTerm(var value, String t, SourceSpan span) : super(value, t, span);
1074
1075 HexColorTerm clone() => new HexColorTerm(value, text, span);
1076 visit(VisitorBase visitor) => visitor.visitHexColorTerm(this);
1077 }
1078
1079 class FunctionTerm extends LiteralTerm {
1080 final Expressions _params;
1081
1082 FunctionTerm(var value, String t, this._params, SourceSpan span)
1083 : super(value, t, span);
1084
1085 FunctionTerm clone() => new FunctionTerm(value, text, _params.clone(), span);
1086 visit(VisitorBase visitor) => visitor.visitFunctionTerm(this);
1087 }
1088
1089 /**
1090 * A "\9" was encountered at the end of the expression and before a semi-colon.
1091 * This is an IE trick to ignore a property or value except by IE 8 and older
1092 * browsers.
1093 */
1094 class IE8Term extends LiteralTerm {
1095 IE8Term(SourceSpan span) : super('\\9', '\\9', span);
1096 IE8Term clone() => new IE8Term(span);
1097 visit(VisitorBase visitor) => visitor.visitIE8Term(this);
1098 }
1099
1100 class GroupTerm extends Expression {
1101 final List<LiteralTerm> _terms;
1102
1103 GroupTerm(SourceSpan span) : _terms = [], super(span);
1104
1105 void add(LiteralTerm term) {
1106 _terms.add(term);
1107 }
1108
1109 GroupTerm clone() => new GroupTerm(span);
1110 visit(VisitorBase visitor) => visitor.visitGroupTerm(this);
1111 }
1112
1113 class ItemTerm extends NumberTerm {
1114 ItemTerm(var value, String t, SourceSpan span) : super(value, t, span);
1115
1116 ItemTerm clone() => new ItemTerm(value, text, span);
1117 visit(VisitorBase visitor) => visitor.visitItemTerm(this);
1118 }
1119
1120 class Expressions extends Expression {
1121 final List<Expression> expressions = [];
1122
1123 Expressions(SourceSpan span): super(span);
1124
1125 void add(Expression expression) {
1126 expressions.add(expression);
1127 }
1128
1129 Expressions clone() {
1130 var clonedExprs = new Expressions(span);
1131 for (var expr in expressions) {
1132 clonedExprs.add(expr.clone());
1133 }
1134 return clonedExprs;
1135 }
1136 visit(VisitorBase visitor) => visitor.visitExpressions(this);
1137 }
1138
1139 class BinaryExpression extends Expression {
1140 final Token op;
1141 final Expression x;
1142 final Expression y;
1143
1144 BinaryExpression(this.op, this.x, this.y, SourceSpan span): super(span);
1145
1146 BinaryExpression clone() =>
1147 new BinaryExpression(op, x.clone(), y.clone(), span);
1148 visit(VisitorBase visitor) => visitor.visitBinaryExpression(this);
1149 }
1150
1151 class UnaryExpression extends Expression {
1152 final Token op;
1153 final Expression self;
1154
1155 UnaryExpression(this.op, this.self, SourceSpan span): super(span);
1156
1157 UnaryExpression clone() => new UnaryExpression(op, self.clone(), span);
1158 visit(VisitorBase visitor) => visitor.visitUnaryExpression(this);
1159 }
1160
1161 abstract class DartStyleExpression extends TreeNode {
1162 static const int unknownType = 0;
1163 static const int fontStyle = 1;
1164 static const int marginStyle = 2;
1165 static const int borderStyle = 3;
1166 static const int paddingStyle = 4;
1167 static const int heightStyle = 5;
1168 static const int widthStyle = 6;
1169
1170 final int _styleType;
1171 int priority;
1172
1173 DartStyleExpression(this._styleType, SourceSpan span) : super(span);
1174
1175 /*
1176 * Merges give 2 DartStyleExpression (or derived from DartStyleExpression,
1177 * e.g., FontExpression, etc.) will merge if the two expressions are of the
1178 * same property name (implies same exact type e.g, FontExpression).
1179 */
1180 merged(DartStyleExpression newDartExpr);
1181
1182 bool get isUnknown => _styleType == 0 || _styleType == null;
1183 bool get isFont => _styleType == fontStyle;
1184 bool get isMargin => _styleType == marginStyle;
1185 bool get isBorder => _styleType == borderStyle;
1186 bool get isPadding => _styleType == paddingStyle;
1187 bool get isHeight => _styleType == heightStyle;
1188 bool get isWidth => _styleType == widthStyle;
1189 bool get isBoxExpression => isMargin || isBorder || isPadding;
1190
1191 bool isSame(DartStyleExpression other) => this._styleType == other._styleType;
1192
1193 visit(VisitorBase visitor) => visitor.visitDartStyleExpression(this);
1194 }
1195
1196 class FontExpression extends DartStyleExpression {
1197 final Font font;
1198
1199 // font-style font-variant font-weight font-size/line-height font-family
1200 // TODO(terry): Only px/pt for now need to handle all possible units to
1201 // support calc expressions on units.
1202 FontExpression(SourceSpan span, {dynamic size, List<String> family,
1203 int weight, String style, String variant, LineHeight lineHeight}) :
1204 font = new Font(size : size is LengthTerm ? size.value : size,
1205 family: family, weight: weight, style: style, variant: variant,
1206 lineHeight: lineHeight),
1207 super(DartStyleExpression.fontStyle, span);
1208
1209 FontExpression merged(FontExpression newFontExpr) {
1210 if (this.isFont && newFontExpr.isFont) {
1211 return new FontExpression.merge(this, newFontExpr);
1212 }
1213
1214 return null;
1215 }
1216
1217 /**
1218 * Merge the two FontExpression and return the result.
1219 */
1220 factory FontExpression.merge(FontExpression x, FontExpression y) {
1221 return new FontExpression._merge(x, y, y.span);
1222 }
1223
1224 FontExpression._merge(FontExpression x, FontExpression y, SourceSpan span)
1225 : super(DartStyleExpression.fontStyle, span),
1226 font = new Font.merge(x.font, y.font);
1227
1228 FontExpression clone() =>
1229 new FontExpression(span, size: font.size, family: font.family,
1230 weight: font.weight, style: font.style, variant: font.variant,
1231 lineHeight: font.lineHeight);
1232
1233 visit(VisitorBase visitor) => visitor.visitFontExpression(this);
1234 }
1235
1236 abstract class BoxExpression extends DartStyleExpression {
1237 final BoxEdge box;
1238
1239 BoxExpression(int styleType, SourceSpan span, this.box)
1240 : super(styleType, span);
1241
1242 /*
1243 * Merges give 2 DartStyleExpression (or derived from DartStyleExpression,
1244 * e.g., FontExpression, etc.) will merge if the two expressions are of the
1245 * same property name (implies same exact type e.g, FontExpression).
1246 */
1247 merged(BoxExpression newDartExpr);
1248
1249 visit(VisitorBase visitor) => visitor.visitBoxExpression(this);
1250
1251 String get formattedBoxEdge {
1252 if (box.top == box.left && box.top == box.bottom &&
1253 box.top== box.right) {
1254 return '.uniform(${box.top})';
1255 } else {
1256 var left = box.left == null ? 0 : box.left;
1257 var top = box.top == null ? 0 : box.top;
1258 var right = box.right == null ? 0 : box.right;
1259 var bottom = box.bottom == null ? 0 : box.bottom;
1260 return '.clockwiseFromTop($top,$right,$bottom,$left)';
1261 }
1262 }
1263 }
1264
1265 class MarginExpression extends BoxExpression {
1266 // TODO(terry): Does auto for margin need to be exposed to Dart UI framework?
1267 /** Margin expression ripped apart. */
1268 MarginExpression(SourceSpan span, {num top, num right, num bottom, num left})
1269 : super(DartStyleExpression.marginStyle, span,
1270 new BoxEdge(left, top, right, bottom));
1271
1272 MarginExpression.boxEdge(SourceSpan span, BoxEdge box)
1273 : super(DartStyleExpression.marginStyle, span, box);
1274
1275 merged(MarginExpression newMarginExpr) {
1276 if (this.isMargin && newMarginExpr.isMargin) {
1277 return new MarginExpression.merge(this, newMarginExpr);
1278 }
1279
1280 return null;
1281 }
1282
1283 /**
1284 * Merge the two MarginExpressions and return the result.
1285 */
1286 factory MarginExpression.merge(MarginExpression x, MarginExpression y) {
1287 return new MarginExpression._merge(x, y, y.span);
1288 }
1289
1290 MarginExpression._merge(MarginExpression x, MarginExpression y,
1291 SourceSpan span)
1292 : super(x._styleType, span, new BoxEdge.merge(x.box, y.box));
1293
1294 MarginExpression clone() =>
1295 new MarginExpression(span, top: box.top, right: box.right,
1296 bottom: box.bottom, left: box.left);
1297
1298 visit(VisitorBase visitor) => visitor.visitMarginExpression(this);
1299 }
1300
1301 class BorderExpression extends BoxExpression {
1302 /** Border expression ripped apart. */
1303 BorderExpression(SourceSpan span, {num top, num right, num bottom, num left})
1304 : super(DartStyleExpression.borderStyle, span,
1305 new BoxEdge(left, top, right, bottom));
1306
1307 BorderExpression.boxEdge(SourceSpan span, BoxEdge box)
1308 : super(DartStyleExpression.borderStyle, span, box);
1309
1310 merged(BorderExpression newBorderExpr) {
1311 if (this.isBorder && newBorderExpr.isBorder) {
1312 return new BorderExpression.merge(this, newBorderExpr);
1313 }
1314
1315 return null;
1316 }
1317
1318 /**
1319 * Merge the two BorderExpression and return the result.
1320 */
1321 factory BorderExpression.merge(BorderExpression x, BorderExpression y) {
1322 return new BorderExpression._merge(x, y, y.span);
1323 }
1324
1325 BorderExpression._merge(BorderExpression x, BorderExpression y,
1326 SourceSpan span)
1327 : super(DartStyleExpression.borderStyle, span,
1328 new BoxEdge.merge(x.box, y.box));
1329
1330 BorderExpression clone() =>
1331 new BorderExpression(span, top: box.top, right: box.right,
1332 bottom: box.bottom, left: box.left);
1333
1334 visit(VisitorBase visitor) => visitor.visitBorderExpression(this);
1335 }
1336
1337 class HeightExpression extends DartStyleExpression {
1338 final height;
1339
1340 HeightExpression(SourceSpan span, this.height)
1341 : super(DartStyleExpression.heightStyle, span);
1342
1343 merged(HeightExpression newHeightExpr) {
1344 if (this.isHeight && newHeightExpr.isHeight) {
1345 return newHeightExpr;
1346 }
1347
1348 return null;
1349 }
1350
1351 HeightExpression clone() => new HeightExpression(span, height);
1352 visit(VisitorBase visitor) => visitor.visitHeightExpression(this);
1353 }
1354
1355 class WidthExpression extends DartStyleExpression {
1356 final width;
1357
1358 WidthExpression(SourceSpan span, this.width)
1359 : super(DartStyleExpression.widthStyle, span);
1360
1361 merged(WidthExpression newWidthExpr) {
1362 if (this.isWidth && newWidthExpr.isWidth) {
1363 return newWidthExpr;
1364 }
1365
1366 return null;
1367 }
1368
1369 WidthExpression clone() => new WidthExpression(span, width);
1370 visit(VisitorBase visitor) => visitor.visitWidthExpression(this);
1371 }
1372
1373 class PaddingExpression extends BoxExpression {
1374 /** Padding expression ripped apart. */
1375 PaddingExpression(SourceSpan span, {num top, num right, num bottom, num left})
1376 : super(DartStyleExpression.paddingStyle, span,
1377 new BoxEdge(left, top, right, bottom));
1378
1379 PaddingExpression.boxEdge(SourceSpan span, BoxEdge box)
1380 : super(DartStyleExpression.paddingStyle, span, box);
1381
1382 merged(PaddingExpression newPaddingExpr) {
1383 if (this.isPadding && newPaddingExpr.isPadding) {
1384 return new PaddingExpression.merge(this, newPaddingExpr);
1385 }
1386
1387 return null;
1388 }
1389
1390 /**
1391 * Merge the two PaddingExpression and return the result.
1392 */
1393 factory PaddingExpression.merge(PaddingExpression x, PaddingExpression y) {
1394 return new PaddingExpression._merge(x, y, y.span);
1395 }
1396
1397 PaddingExpression._merge(PaddingExpression x, PaddingExpression y,
1398 SourceSpan span)
1399 : super(DartStyleExpression.paddingStyle, span,
1400 new BoxEdge.merge(x.box, y.box));
1401
1402 PaddingExpression clone() =>
1403 new PaddingExpression(span, top: box.top, right: box.right,
1404 bottom: box.bottom, left: box.left);
1405 visit(VisitorBase visitor) => visitor.visitPaddingExpression(this);
1406 }
OLDNEW
« no previous file with comments | « observatory_pub_packages/csslib/src/tokenkind.dart ('k') | observatory_pub_packages/csslib/src/tree_base.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698