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

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

Issue 1400473008: Roll Observatory packages and add a roll script (Closed) Base URL: git@github.com:dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years, 2 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 unified diff | Download patch
« no previous file with comments | « csslib/lib/src/tokenkind.dart ('k') | csslib/lib/src/tree_base.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 =
84 simpleSelectorSequences.map((ss) => ss.clone()).toList();
85
86 return new Selector(simpleSequences, span);
87 }
88
89 visit(VisitorBase visitor) => visitor.visitSelector(this);
90 }
91
92 class SimpleSelectorSequence extends TreeNode {
93 /** +, >, ~, NONE */
94 int combinator;
95 final SimpleSelector simpleSelector;
96
97 SimpleSelectorSequence(this.simpleSelector, SourceSpan span,
98 [int combinator = TokenKind.COMBINATOR_NONE])
99 : combinator = combinator,
100 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 => isCombinatorDescendant
110 ? ' '
111 : isCombinatorPlus
112 ? ' + '
113 : isCombinatorGreater ? ' > ' : 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, SourceSpan span)
177 : 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) => visitor.visitPseudoClassFunctionSelector(this);
288 }
289
290 // ::pseudoElementFunction(expression)
291 class PseudoElementFunctionSelector extends PseudoElementSelector {
292 final SelectorExpression expression;
293
294 PseudoElementFunctionSelector(
295 Identifier name, this.expression, SourceSpan span)
296 : super(name, span);
297
298 PseudoElementFunctionSelector clone() =>
299 new PseudoElementFunctionSelector(_name, expression, span);
300
301 visit(VisitorBase visitor) =>
302 visitor.visitPseudoElementFunctionSelector(this);
303 }
304
305 class SelectorExpression extends TreeNode {
306 final List<Expression> expressions;
307
308 SelectorExpression(this.expressions, SourceSpan span) : super(span);
309
310 SelectorExpression clone() {
311 return new SelectorExpression(
312 expressions.map((e) => e.clone()).toList(), span);
313 }
314
315 visit(VisitorBase visitor) => visitor.visitSelectorExpression(this);
316 }
317
318 // :NOT(negation_arg)
319 class NegationSelector extends SimpleSelector {
320 final SimpleSelector negationArg;
321
322 NegationSelector(this.negationArg, SourceSpan span)
323 : super(new Negation(span), span);
324
325 NegationSelector clone() => new NegationSelector(negationArg, span);
326
327 visit(VisitorBase visitor) => visitor.visitNegationSelector(this);
328 }
329
330 class NoOp extends TreeNode {
331 NoOp() : super(null);
332
333 NoOp clone() => new NoOp();
334
335 visit(VisitorBase visitor) => visitor.visitNoOp(this);
336 }
337
338 class StyleSheet extends TreeNode {
339 /**
340 * Contains charset, ruleset, directives (media, page, etc.), and selectors.
341 */
342 final List<TreeNode> topLevels;
343
344 StyleSheet(this.topLevels, SourceSpan span) : super(span) {
345 for (final node in topLevels) {
346 assert(node is TopLevelProduction || node is Directive);
347 }
348 }
349
350 /** Selectors only in this tree. */
351 StyleSheet.selector(this.topLevels, SourceSpan span) : super(span);
352
353 StyleSheet clone() {
354 var clonedTopLevels = topLevels.map((e) => e.clone()).toList();
355 return new StyleSheet(clonedTopLevels, span);
356 }
357
358 visit(VisitorBase visitor) => visitor.visitStyleSheet(this);
359 }
360
361 class TopLevelProduction extends TreeNode {
362 TopLevelProduction(SourceSpan span) : super(span);
363 TopLevelProduction clone() => new TopLevelProduction(span);
364 visit(VisitorBase visitor) => visitor.visitTopLevelProduction(this);
365 }
366
367 class RuleSet extends TopLevelProduction {
368 final SelectorGroup _selectorGroup;
369 final DeclarationGroup _declarationGroup;
370
371 RuleSet(this._selectorGroup, this._declarationGroup, SourceSpan span)
372 : super(span);
373
374 SelectorGroup get selectorGroup => _selectorGroup;
375 DeclarationGroup get declarationGroup => _declarationGroup;
376
377 RuleSet clone() {
378 var cloneSelectorGroup = _selectorGroup.clone();
379 var cloneDeclarationGroup = _declarationGroup.clone();
380 return new RuleSet(cloneSelectorGroup, cloneDeclarationGroup, span);
381 }
382
383 visit(VisitorBase visitor) => visitor.visitRuleSet(this);
384 }
385
386 class Directive extends TreeNode {
387 Directive(SourceSpan span) : super(span);
388
389 bool get isBuiltIn => true; // Known CSS directive?
390 bool get isExtension => false; // SCSS extension?
391
392 Directive clone() => new Directive(span);
393 visit(VisitorBase visitor) => visitor.visitDirective(this);
394 }
395
396 class ImportDirective extends Directive {
397 /** import name specified. */
398 final String import;
399
400 /** Any media queries for this import. */
401 final List<MediaQuery> mediaQueries;
402
403 ImportDirective(this.import, this.mediaQueries, SourceSpan span)
404 : super(span);
405
406 ImportDirective clone() {
407 var cloneMediaQueries = [];
408 for (var mediaQuery in mediaQueries) {
409 cloneMediaQueries.add(mediaQuery.clone());
410 }
411 return new ImportDirective(import, cloneMediaQueries, span);
412 }
413
414 visit(VisitorBase visitor) => visitor.visitImportDirective(this);
415 }
416
417 /**
418 * MediaExpression grammar:
419 * '(' S* media_feature S* [ ':' S* expr ]? ')' S*
420 */
421 class MediaExpression extends TreeNode {
422 final bool andOperator;
423 final Identifier _mediaFeature;
424 final Expressions exprs;
425
426 MediaExpression(
427 this.andOperator, this._mediaFeature, this.exprs, SourceSpan span)
428 : super(span);
429
430 String get mediaFeature => _mediaFeature.name;
431
432 MediaExpression clone() {
433 var clonedExprs = exprs.clone();
434 return new MediaExpression(andOperator, _mediaFeature, clonedExprs, span);
435 }
436
437 visit(VisitorBase visitor) => visitor.visitMediaExpression(this);
438 }
439
440 /**
441 * MediaQuery grammar:
442 * : [ONLY | NOT]? S* media_type S* [ AND S* media_expression ]*
443 * | media_expression [ AND S* media_expression ]*
444 * media_type
445 * : IDENT
446 * media_expression
447 * : '(' S* media_feature S* [ ':' S* expr ]? ')' S*
448 * media_feature
449 * : IDENT
450 */
451 class MediaQuery extends TreeNode {
452 /** not, only or no operator. */
453 final int _mediaUnary;
454 final Identifier _mediaType;
455 final List<MediaExpression> expressions;
456
457 MediaQuery(
458 this._mediaUnary, this._mediaType, this.expressions, SourceSpan span)
459 : super(span);
460
461 bool get hasMediaType => _mediaType != null;
462 String get mediaType => _mediaType.name;
463
464 bool get hasUnary => _mediaUnary != -1;
465 String get unary =>
466 TokenKind.idToValue(TokenKind.MEDIA_OPERATORS, _mediaUnary).toUpperCase();
467
468 MediaQuery clone() {
469 var cloneExpressions = [];
470 for (var expr in expressions) {
471 cloneExpressions.add(expr.clone());
472 }
473 return new MediaQuery(_mediaUnary, _mediaType, cloneExpressions, span);
474 }
475 visit(VisitorBase visitor) => visitor.visitMediaQuery(this);
476 }
477
478 class MediaDirective extends Directive {
479 final List<MediaQuery> mediaQueries;
480 final List<RuleSet> rulesets;
481
482 MediaDirective(this.mediaQueries, this.rulesets, SourceSpan span)
483 : super(span);
484
485 MediaDirective clone() {
486 var cloneQueries = [];
487 for (var mediaQuery in mediaQueries) {
488 cloneQueries.add(mediaQuery.clone());
489 }
490 var cloneRulesets = [];
491 for (var ruleset in rulesets) {
492 cloneRulesets.add(ruleset.clone());
493 }
494 return new MediaDirective(cloneQueries, cloneRulesets, span);
495 }
496
497 visit(VisitorBase visitor) => visitor.visitMediaDirective(this);
498 }
499
500 class HostDirective extends Directive {
501 final List<RuleSet> rulesets;
502
503 HostDirective(this.rulesets, SourceSpan span) : super(span);
504
505 HostDirective clone() {
506 var cloneRulesets = [];
507 for (var ruleset in rulesets) {
508 cloneRulesets.add(ruleset.clone());
509 }
510 return new HostDirective(cloneRulesets, span);
511 }
512
513 visit(VisitorBase visitor) => visitor.visitHostDirective(this);
514 }
515
516 class PageDirective extends Directive {
517 final String _ident;
518 final String _pseudoPage;
519 final List<DeclarationGroup> _declsMargin;
520
521 PageDirective(
522 this._ident, this._pseudoPage, this._declsMargin, SourceSpan span)
523 : 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 = [],
557 super(span);
558
559 add(KeyFrameBlock block) {
560 _blocks.add(block);
561 }
562
563 String get keyFrameName {
564 switch (_keyframeName) {
565 case TokenKind.DIRECTIVE_KEYFRAMES:
566 case TokenKind.DIRECTIVE_MS_KEYFRAMES:
567 return '@keyframes';
568 case TokenKind.DIRECTIVE_WEB_KIT_KEYFRAMES:
569 return '@-webkit-keyframes';
570 case TokenKind.DIRECTIVE_MOZ_KEYFRAMES:
571 return '@-moz-keyframes';
572 case TokenKind.DIRECTIVE_O_KEYFRAMES:
573 return '@-o-keyframes';
574 }
575 }
576
577 KeyFrameDirective clone() {
578 var cloneBlocks = [];
579 for (var block in _blocks) {
580 cloneBlocks.add(block.clone());
581 }
582 return new KeyFrameDirective(_keyframeName, cloneBlocks, span);
583 }
584 visit(VisitorBase visitor) => visitor.visitKeyFrameDirective(this);
585 }
586
587 class KeyFrameBlock extends Expression {
588 final Expressions _blockSelectors;
589 final DeclarationGroup _declarations;
590
591 KeyFrameBlock(this._blockSelectors, this._declarations, SourceSpan span)
592 : super(span);
593
594 KeyFrameBlock clone() =>
595 new KeyFrameBlock(_blockSelectors.clone(), _declarations.clone(), span);
596 visit(VisitorBase visitor) => visitor.visitKeyFrameBlock(this);
597 }
598
599 class FontFaceDirective extends Directive {
600 final DeclarationGroup _declarations;
601
602 FontFaceDirective(this._declarations, SourceSpan span) : super(span);
603
604 FontFaceDirective clone() =>
605 new FontFaceDirective(_declarations.clone(), span);
606 visit(VisitorBase visitor) => visitor.visitFontFaceDirective(this);
607 }
608
609 class StyletDirective extends Directive {
610 final String dartClassName;
611 final List<RuleSet> rulesets;
612
613 StyletDirective(this.dartClassName, this.rulesets, SourceSpan span)
614 : super(span);
615
616 bool get isBuiltIn => false;
617 bool get isExtension => true;
618
619 StyletDirective clone() {
620 var cloneRulesets = [];
621 for (var ruleset in rulesets) {
622 cloneRulesets.add(ruleset.clone());
623 }
624 return new StyletDirective(dartClassName, cloneRulesets, span);
625 }
626
627 visit(VisitorBase visitor) => visitor.visitStyletDirective(this);
628 }
629
630 class NamespaceDirective extends Directive {
631 /** Namespace prefix. */
632 final String _prefix;
633
634 /** URI associated with this namespace. */
635 final String _uri;
636
637 NamespaceDirective(this._prefix, this._uri, SourceSpan span) : super(span);
638
639 NamespaceDirective clone() => new NamespaceDirective(_prefix, _uri, span);
640
641 visit(VisitorBase visitor) => visitor.visitNamespaceDirective(this);
642
643 String get prefix => _prefix.length > 0 ? '$_prefix ' : '';
644 }
645
646 /** To support Less syntax @name: expression */
647 class VarDefinitionDirective extends Directive {
648 final VarDefinition def;
649
650 VarDefinitionDirective(this.def, SourceSpan span) : super(span);
651
652 VarDefinitionDirective clone() =>
653 new VarDefinitionDirective(def.clone(), span);
654
655 visit(VisitorBase visitor) => visitor.visitVarDefinitionDirective(this);
656 }
657
658 class MixinDefinition extends Directive {
659 final String name;
660 final List definedArgs;
661 final bool varArgs;
662
663 MixinDefinition(this.name, this.definedArgs, this.varArgs, SourceSpan span)
664 : super(span);
665
666 MixinDefinition clone() {
667 var cloneDefinedArgs = [];
668 for (var definedArg in definedArgs) {
669 cloneDefinedArgs.add(definedArg.clone());
670 }
671 return new MixinDefinition(name, cloneDefinedArgs, varArgs, span);
672 }
673
674 visit(VisitorBase visitor) => visitor.visitMixinDefinition(this);
675 }
676
677 /** Support a Sass @mixin. See http://sass-lang.com for description. */
678 class MixinRulesetDirective extends MixinDefinition {
679 final List<RuleSet> rulesets;
680
681 MixinRulesetDirective(String name, List<VarDefinitionDirective> args,
682 bool varArgs, this.rulesets, SourceSpan span)
683 : super(name, args, varArgs, span);
684
685 MixinRulesetDirective clone() {
686 var clonedArgs = [];
687 for (var arg in definedArgs) {
688 clonedArgs.add(arg.clone());
689 }
690 var clonedRulesets = [];
691 for (var ruleset in rulesets) {
692 clonedRulesets.add(ruleset.clone());
693 }
694 return new MixinRulesetDirective(
695 name, clonedArgs, varArgs, clonedRulesets, span);
696 }
697
698 visit(VisitorBase visitor) => visitor.visitMixinRulesetDirective(this);
699 }
700
701 class MixinDeclarationDirective extends MixinDefinition {
702 final DeclarationGroup declarations;
703
704 MixinDeclarationDirective(String name, List<VarDefinitionDirective> args,
705 bool varArgs, this.declarations, SourceSpan span)
706 : super(name, args, varArgs, span);
707
708 MixinDeclarationDirective clone() {
709 var clonedArgs = [];
710 for (var arg in definedArgs) {
711 clonedArgs.add(arg.clone());
712 }
713 return new MixinDeclarationDirective(
714 name, clonedArgs, varArgs, declarations.clone(), span);
715 }
716
717 visit(VisitorBase visitor) => visitor.visitMixinDeclarationDirective(this);
718 }
719
720 /** To support consuming a SASS mixin @include. */
721 class IncludeDirective extends Directive {
722 final String name;
723 final List<List<TreeNode>> args;
724
725 IncludeDirective(this.name, this.args, SourceSpan span) : super(span);
726
727 IncludeDirective clone() {
728 var cloneArgs = [];
729 for (var arg in args) {
730 for (var term in arg) {
731 cloneArgs.add(term.clone());
732 }
733 }
734 return new IncludeDirective(name, cloneArgs, span);
735 }
736
737 visit(VisitorBase visitor) => visitor.visitIncludeDirective(this);
738 }
739
740 /** To support SASS @content. */
741 class ContentDirective extends Directive {
742 ContentDirective(SourceSpan span) : super(span);
743
744 visit(VisitorBase visitor) => visitor.visitContentDirective(this);
745 }
746
747 class Declaration extends TreeNode {
748 final Identifier _property;
749 final Expression _expression;
750 /** Style exposed to Dart. */
751 dynamic dartStyle;
752 final bool important;
753
754 /**
755 * IE CSS hacks that can only be read by a particular IE version.
756 * 7 implies IE 7 or older property (e.g., *background: blue;)
757 * Note: IE 8 or older property (e.g., background: green\9;) is handled
758 * by IE8Term in declaration expression handling.
759 * Note: IE 6 only property with a leading underscore is a valid IDENT
760 * since an ident can start with underscore (e.g., _background: red;)
761 */
762 final bool isIE7;
763
764 Declaration(this._property, this._expression, this.dartStyle, SourceSpan span,
765 {important: false, ie7: false})
766 : this.important = important,
767 this.isIE7 = ie7,
768 super(span);
769
770 String get property => isIE7 ? '*${_property.name}' : _property.name;
771 Expression get expression => _expression;
772
773 bool get hasDartStyle => dartStyle != null;
774
775 Declaration clone() => new Declaration(
776 _property.clone(), _expression.clone(), dartStyle, span,
777 important: important);
778
779 visit(VisitorBase visitor) => visitor.visitDeclaration(this);
780 }
781
782 // TODO(terry): Consider 2 kinds of VarDefinitions static at top-level and
783 // dynamic when in a declaration. Currently, Less syntax
784 // '@foo: expression' and 'var-foo: expression' in a declaration
785 // are statically resolved. Better solution, if @foo or var-foo
786 // are top-level are then statically resolved and var-foo in a
787 // declaration group (surrounded by a selector) would be dynamic.
788 class VarDefinition extends Declaration {
789 bool badUsage = false;
790
791 VarDefinition(Identifier definedName, Expression expr, SourceSpan span)
792 : super(definedName, expr, null, span);
793
794 String get definedName => _property.name;
795
796 VarDefinition clone() => new VarDefinition(
797 _property.clone(), expression != null ? expression.clone() : null, span);
798
799 visit(VisitorBase visitor) => visitor.visitVarDefinition(this);
800 }
801
802 /**
803 * Node for usage of @include mixin[(args,...)] found in a declaration group
804 * instead of at a ruleset (toplevel) e.g.,
805 * div {
806 * @include mixin1;
807 * }
808 */
809 class IncludeMixinAtDeclaration extends Declaration {
810 final IncludeDirective include;
811
812 IncludeMixinAtDeclaration(this.include, SourceSpan span)
813 : super(null, null, null, span);
814
815 IncludeMixinAtDeclaration clone() =>
816 new IncludeMixinAtDeclaration(include.clone(), span);
817
818 visit(VisitorBase visitor) => visitor.visitIncludeMixinAtDeclaration(this);
819 }
820
821 class ExtendDeclaration extends Declaration {
822 final List<TreeNode> selectors;
823
824 ExtendDeclaration(this.selectors, SourceSpan span)
825 : super(null, null, null, span);
826
827 ExtendDeclaration clone() {
828 var newSelector = selectors.map((s) => s.clone()).toList();
829 return new ExtendDeclaration(newSelector, span);
830 }
831
832 visit(VisitorBase visitor) => visitor.visitExtendDeclaration(this);
833 }
834
835 class DeclarationGroup extends TreeNode {
836 /** Can be either Declaration or RuleSet (if nested selector). */
837 final List declarations;
838
839 DeclarationGroup(this.declarations, SourceSpan span) : super(span);
840
841 DeclarationGroup clone() {
842 var clonedDecls = declarations.map((d) => d.clone()).toList();
843 return new DeclarationGroup(clonedDecls, span);
844 }
845
846 visit(VisitorBase visitor) => visitor.visitDeclarationGroup(this);
847 }
848
849 class MarginGroup extends DeclarationGroup {
850 final int margin_sym; // TokenType for for @margin sym.
851
852 MarginGroup(this.margin_sym, List<Declaration> decls, SourceSpan span)
853 : super(decls, span);
854 MarginGroup clone() =>
855 new MarginGroup(margin_sym, super.clone() as dynamic, span);
856 visit(VisitorBase visitor) => visitor.visitMarginGroup(this);
857 }
858
859 class VarUsage extends Expression {
860 final String name;
861 final List<Expression> defaultValues;
862
863 VarUsage(this.name, this.defaultValues, SourceSpan span) : super(span);
864
865 VarUsage clone() {
866 var clonedValues = [];
867 for (var expr in defaultValues) {
868 clonedValues.add(expr.clone());
869 }
870 return new VarUsage(name, clonedValues, span);
871 }
872
873 visit(VisitorBase visitor) => visitor.visitVarUsage(this);
874 }
875
876 class OperatorSlash extends Expression {
877 OperatorSlash(SourceSpan span) : super(span);
878 OperatorSlash clone() => new OperatorSlash(span);
879 visit(VisitorBase visitor) => visitor.visitOperatorSlash(this);
880 }
881
882 class OperatorComma extends Expression {
883 OperatorComma(SourceSpan span) : super(span);
884 OperatorComma clone() => new OperatorComma(span);
885 visit(VisitorBase visitor) => visitor.visitOperatorComma(this);
886 }
887
888 class OperatorPlus extends Expression {
889 OperatorPlus(SourceSpan span) : super(span);
890 OperatorPlus clone() => new OperatorPlus(span);
891 visit(VisitorBase visitor) => visitor.visitOperatorPlus(this);
892 }
893
894 class OperatorMinus extends Expression {
895 OperatorMinus(SourceSpan span) : super(span);
896 OperatorMinus clone() => new OperatorMinus(span);
897 visit(VisitorBase visitor) => visitor.visitOperatorMinus(this);
898 }
899
900 class UnicodeRangeTerm extends Expression {
901 final String first;
902 final String second;
903
904 UnicodeRangeTerm(this.first, this.second, SourceSpan span) : super(span);
905
906 bool get hasSecond => second != null;
907
908 UnicodeRangeTerm clone() => new UnicodeRangeTerm(first, second, span);
909
910 visit(VisitorBase visitor) => visitor.visitUnicodeRangeTerm(this);
911 }
912
913 class LiteralTerm extends Expression {
914 // TODO(terry): value and text fields can be made final once all CSS resources
915 // are copied/symlink'd in the build tool and UriVisitor in
916 // web_ui is removed.
917 dynamic value;
918 String text;
919
920 LiteralTerm(this.value, this.text, SourceSpan span) : super(span);
921
922 LiteralTerm clone() => new LiteralTerm(value, text, span);
923
924 visit(VisitorBase visitor) => visitor.visitLiteralTerm(this);
925 }
926
927 class NumberTerm extends LiteralTerm {
928 NumberTerm(value, String t, SourceSpan span) : super(value, t, span);
929 NumberTerm clone() => new NumberTerm(value, text, span);
930 visit(VisitorBase visitor) => visitor.visitNumberTerm(this);
931 }
932
933 class UnitTerm extends LiteralTerm {
934 final int unit;
935
936 UnitTerm(value, String t, SourceSpan span, this.unit) : super(value, t, span);
937
938 UnitTerm clone() => new UnitTerm(value, text, span, unit);
939
940 visit(VisitorBase visitor) => visitor.visitUnitTerm(this);
941
942 String unitToString() => TokenKind.unitToString(unit);
943
944 String toString() => '$text${unitToString()}';
945 }
946
947 class LengthTerm extends UnitTerm {
948 LengthTerm(value, String t, SourceSpan span,
949 [int unit = TokenKind.UNIT_LENGTH_PX])
950 : super(value, t, span, unit) {
951 assert(this.unit == TokenKind.UNIT_LENGTH_PX ||
952 this.unit == TokenKind.UNIT_LENGTH_CM ||
953 this.unit == TokenKind.UNIT_LENGTH_MM ||
954 this.unit == TokenKind.UNIT_LENGTH_IN ||
955 this.unit == TokenKind.UNIT_LENGTH_PT ||
956 this.unit == TokenKind.UNIT_LENGTH_PC);
957 }
958 LengthTerm clone() => new LengthTerm(value, text, span, unit);
959 visit(VisitorBase visitor) => visitor.visitLengthTerm(this);
960 }
961
962 class PercentageTerm extends LiteralTerm {
963 PercentageTerm(value, String t, SourceSpan span) : super(value, t, span);
964 PercentageTerm clone() => new PercentageTerm(value, text, span);
965 visit(VisitorBase visitor) => visitor.visitPercentageTerm(this);
966 }
967
968 class EmTerm extends LiteralTerm {
969 EmTerm(value, String t, SourceSpan span) : super(value, t, span);
970 EmTerm clone() => new EmTerm(value, text, span);
971 visit(VisitorBase visitor) => visitor.visitEmTerm(this);
972 }
973
974 class ExTerm extends LiteralTerm {
975 ExTerm(value, String t, SourceSpan span) : super(value, t, span);
976 ExTerm clone() => new ExTerm(value, text, span);
977 visit(VisitorBase visitor) => visitor.visitExTerm(this);
978 }
979
980 class AngleTerm extends UnitTerm {
981 AngleTerm(var value, String t, SourceSpan span,
982 [int unit = TokenKind.UNIT_LENGTH_PX])
983 : super(value, t, span, unit) {
984 assert(this.unit == TokenKind.UNIT_ANGLE_DEG ||
985 this.unit == TokenKind.UNIT_ANGLE_RAD ||
986 this.unit == TokenKind.UNIT_ANGLE_GRAD ||
987 this.unit == TokenKind.UNIT_ANGLE_TURN);
988 }
989
990 AngleTerm clone() => new AngleTerm(value, text, span, unit);
991 visit(VisitorBase visitor) => visitor.visitAngleTerm(this);
992 }
993
994 class TimeTerm extends UnitTerm {
995 TimeTerm(var value, String t, SourceSpan span,
996 [int unit = TokenKind.UNIT_LENGTH_PX])
997 : super(value, t, span, unit) {
998 assert(this.unit == TokenKind.UNIT_ANGLE_DEG ||
999 this.unit == TokenKind.UNIT_TIME_MS ||
1000 this.unit == TokenKind.UNIT_TIME_S);
1001 }
1002
1003 TimeTerm clone() => new TimeTerm(value, text, span, unit);
1004 visit(VisitorBase visitor) => visitor.visitTimeTerm(this);
1005 }
1006
1007 class FreqTerm extends UnitTerm {
1008 FreqTerm(var value, String t, SourceSpan span,
1009 [int unit = TokenKind.UNIT_LENGTH_PX])
1010 : super(value, t, span, unit) {
1011 assert(unit == TokenKind.UNIT_FREQ_HZ || unit == TokenKind.UNIT_FREQ_KHZ);
1012 }
1013
1014 FreqTerm clone() => new FreqTerm(value, text, span, unit);
1015 visit(VisitorBase visitor) => visitor.visitFreqTerm(this);
1016 }
1017
1018 class FractionTerm extends LiteralTerm {
1019 FractionTerm(var value, String t, SourceSpan span) : super(value, t, span);
1020
1021 FractionTerm clone() => new FractionTerm(value, text, span);
1022 visit(VisitorBase visitor) => visitor.visitFractionTerm(this);
1023 }
1024
1025 class UriTerm extends LiteralTerm {
1026 UriTerm(String value, SourceSpan span) : super(value, value, span);
1027
1028 UriTerm clone() => new UriTerm(value, span);
1029 visit(VisitorBase visitor) => visitor.visitUriTerm(this);
1030 }
1031
1032 class ResolutionTerm extends UnitTerm {
1033 ResolutionTerm(var value, String t, SourceSpan span,
1034 [int unit = TokenKind.UNIT_LENGTH_PX])
1035 : super(value, t, span, unit) {
1036 assert(unit == TokenKind.UNIT_RESOLUTION_DPI ||
1037 unit == TokenKind.UNIT_RESOLUTION_DPCM ||
1038 unit == TokenKind.UNIT_RESOLUTION_DPPX);
1039 }
1040
1041 ResolutionTerm clone() => new ResolutionTerm(value, text, span, unit);
1042 visit(VisitorBase visitor) => visitor.visitResolutionTerm(this);
1043 }
1044
1045 class ChTerm extends UnitTerm {
1046 ChTerm(var value, String t, SourceSpan span,
1047 [int unit = TokenKind.UNIT_LENGTH_PX])
1048 : super(value, t, span, unit) {
1049 assert(unit == TokenKind.UNIT_CH);
1050 }
1051
1052 ChTerm clone() => new ChTerm(value, text, span, unit);
1053 visit(VisitorBase visitor) => visitor.visitChTerm(this);
1054 }
1055
1056 class RemTerm extends UnitTerm {
1057 RemTerm(var value, String t, SourceSpan span,
1058 [int unit = TokenKind.UNIT_LENGTH_PX])
1059 : super(value, t, span, unit) {
1060 assert(unit == TokenKind.UNIT_REM);
1061 }
1062
1063 RemTerm clone() => new RemTerm(value, text, span, unit);
1064 visit(VisitorBase visitor) => visitor.visitRemTerm(this);
1065 }
1066
1067 class ViewportTerm extends UnitTerm {
1068 ViewportTerm(var value, String t, SourceSpan span,
1069 [int unit = TokenKind.UNIT_LENGTH_PX])
1070 : super(value, t, span, unit) {
1071 assert(unit == TokenKind.UNIT_VIEWPORT_VW ||
1072 unit == TokenKind.UNIT_VIEWPORT_VH ||
1073 unit == TokenKind.UNIT_VIEWPORT_VMIN ||
1074 unit == TokenKind.UNIT_VIEWPORT_VMAX);
1075 }
1076
1077 ViewportTerm clone() => new ViewportTerm(value, text, span, unit);
1078 visit(VisitorBase visitor) => visitor.visitViewportTerm(this);
1079 }
1080
1081 /** Type to signal a bad hex value for HexColorTerm.value. */
1082 class BAD_HEX_VALUE {}
1083
1084 class HexColorTerm extends LiteralTerm {
1085 HexColorTerm(var value, String t, SourceSpan span) : super(value, t, span);
1086
1087 HexColorTerm clone() => new HexColorTerm(value, text, span);
1088 visit(VisitorBase visitor) => visitor.visitHexColorTerm(this);
1089 }
1090
1091 class FunctionTerm extends LiteralTerm {
1092 final Expressions _params;
1093
1094 FunctionTerm(var value, String t, this._params, SourceSpan span)
1095 : super(value, t, span);
1096
1097 FunctionTerm clone() => new FunctionTerm(value, text, _params.clone(), span);
1098 visit(VisitorBase visitor) => visitor.visitFunctionTerm(this);
1099 }
1100
1101 /**
1102 * A "\9" was encountered at the end of the expression and before a semi-colon.
1103 * This is an IE trick to ignore a property or value except by IE 8 and older
1104 * browsers.
1105 */
1106 class IE8Term extends LiteralTerm {
1107 IE8Term(SourceSpan span) : super('\\9', '\\9', span);
1108 IE8Term clone() => new IE8Term(span);
1109 visit(VisitorBase visitor) => visitor.visitIE8Term(this);
1110 }
1111
1112 class GroupTerm extends Expression {
1113 final List<LiteralTerm> _terms;
1114
1115 GroupTerm(SourceSpan span)
1116 : _terms = [],
1117 super(span);
1118
1119 void add(LiteralTerm term) {
1120 _terms.add(term);
1121 }
1122
1123 GroupTerm clone() => new GroupTerm(span);
1124 visit(VisitorBase visitor) => visitor.visitGroupTerm(this);
1125 }
1126
1127 class ItemTerm extends NumberTerm {
1128 ItemTerm(var value, String t, SourceSpan span) : super(value, t, span);
1129
1130 ItemTerm clone() => new ItemTerm(value, text, span);
1131 visit(VisitorBase visitor) => visitor.visitItemTerm(this);
1132 }
1133
1134 class Expressions extends Expression {
1135 final List<Expression> expressions = [];
1136
1137 Expressions(SourceSpan span) : super(span);
1138
1139 void add(Expression expression) {
1140 expressions.add(expression);
1141 }
1142
1143 Expressions clone() {
1144 var clonedExprs = new Expressions(span);
1145 for (var expr in expressions) {
1146 clonedExprs.add(expr.clone());
1147 }
1148 return clonedExprs;
1149 }
1150 visit(VisitorBase visitor) => visitor.visitExpressions(this);
1151 }
1152
1153 class BinaryExpression extends Expression {
1154 final Token op;
1155 final Expression x;
1156 final Expression y;
1157
1158 BinaryExpression(this.op, this.x, this.y, SourceSpan span) : super(span);
1159
1160 BinaryExpression clone() =>
1161 new BinaryExpression(op, x.clone(), y.clone(), span);
1162 visit(VisitorBase visitor) => visitor.visitBinaryExpression(this);
1163 }
1164
1165 class UnaryExpression extends Expression {
1166 final Token op;
1167 final Expression self;
1168
1169 UnaryExpression(this.op, this.self, SourceSpan span) : super(span);
1170
1171 UnaryExpression clone() => new UnaryExpression(op, self.clone(), span);
1172 visit(VisitorBase visitor) => visitor.visitUnaryExpression(this);
1173 }
1174
1175 abstract class DartStyleExpression extends TreeNode {
1176 static const int unknownType = 0;
1177 static const int fontStyle = 1;
1178 static const int marginStyle = 2;
1179 static const int borderStyle = 3;
1180 static const int paddingStyle = 4;
1181 static const int heightStyle = 5;
1182 static const int widthStyle = 6;
1183
1184 final int _styleType;
1185 int priority;
1186
1187 DartStyleExpression(this._styleType, SourceSpan span) : super(span);
1188
1189 /*
1190 * Merges give 2 DartStyleExpression (or derived from DartStyleExpression,
1191 * e.g., FontExpression, etc.) will merge if the two expressions are of the
1192 * same property name (implies same exact type e.g, FontExpression).
1193 */
1194 merged(DartStyleExpression newDartExpr);
1195
1196 bool get isUnknown => _styleType == 0 || _styleType == null;
1197 bool get isFont => _styleType == fontStyle;
1198 bool get isMargin => _styleType == marginStyle;
1199 bool get isBorder => _styleType == borderStyle;
1200 bool get isPadding => _styleType == paddingStyle;
1201 bool get isHeight => _styleType == heightStyle;
1202 bool get isWidth => _styleType == widthStyle;
1203 bool get isBoxExpression => isMargin || isBorder || isPadding;
1204
1205 bool isSame(DartStyleExpression other) => this._styleType == other._styleType;
1206
1207 visit(VisitorBase visitor) => visitor.visitDartStyleExpression(this);
1208 }
1209
1210 class FontExpression extends DartStyleExpression {
1211 final Font font;
1212
1213 // font-style font-variant font-weight font-size/line-height font-family
1214 // TODO(terry): Only px/pt for now need to handle all possible units to
1215 // support calc expressions on units.
1216 FontExpression(SourceSpan span, {dynamic size, List<String> family,
1217 int weight, String style, String variant, LineHeight lineHeight})
1218 : font = new Font(
1219 size: size is LengthTerm ? size.value : size,
1220 family: family,
1221 weight: weight,
1222 style: style,
1223 variant: variant,
1224 lineHeight: lineHeight),
1225 super(DartStyleExpression.fontStyle, span);
1226
1227 FontExpression merged(DartStyleExpression newFontExpr) {
1228 if (newFontExpr is FontExpression && this.isFont && newFontExpr.isFont) {
1229 return new FontExpression.merge(this, newFontExpr);
1230 }
1231 return null;
1232 }
1233
1234 /**
1235 * Merge the two FontExpression and return the result.
1236 */
1237 factory FontExpression.merge(FontExpression x, FontExpression y) {
1238 return new FontExpression._merge(x, y, y.span);
1239 }
1240
1241 FontExpression._merge(FontExpression x, FontExpression y, SourceSpan span)
1242 : font = new Font.merge(x.font, y.font),
1243 super(DartStyleExpression.fontStyle, span);
1244
1245 FontExpression clone() => new FontExpression(span,
1246 size: font.size,
1247 family: font.family,
1248 weight: font.weight,
1249 style: font.style,
1250 variant: font.variant,
1251 lineHeight: font.lineHeight);
1252
1253 visit(VisitorBase visitor) => visitor.visitFontExpression(this);
1254 }
1255
1256 abstract class BoxExpression extends DartStyleExpression {
1257 final BoxEdge box;
1258
1259 BoxExpression(int styleType, SourceSpan span, this.box)
1260 : super(styleType, span);
1261
1262 visit(VisitorBase visitor) => visitor.visitBoxExpression(this);
1263
1264 String get formattedBoxEdge {
1265 if (box.top == box.left && box.top == box.bottom && box.top == box.right) {
1266 return '.uniform(${box.top})';
1267 } else {
1268 var left = box.left == null ? 0 : box.left;
1269 var top = box.top == null ? 0 : box.top;
1270 var right = box.right == null ? 0 : box.right;
1271 var bottom = box.bottom == null ? 0 : box.bottom;
1272 return '.clockwiseFromTop($top,$right,$bottom,$left)';
1273 }
1274 }
1275 }
1276
1277 class MarginExpression extends BoxExpression {
1278 // TODO(terry): Does auto for margin need to be exposed to Dart UI framework?
1279 /** Margin expression ripped apart. */
1280 MarginExpression(SourceSpan span, {num top, num right, num bottom, num left})
1281 : super(DartStyleExpression.marginStyle, span,
1282 new BoxEdge(left, top, right, bottom));
1283
1284 MarginExpression.boxEdge(SourceSpan span, BoxEdge box)
1285 : super(DartStyleExpression.marginStyle, span, box);
1286
1287 merged(DartStyleExpression newMarginExpr) {
1288 if (newMarginExpr is MarginExpression &&
1289 this.isMargin &&
1290 newMarginExpr.isMargin) {
1291 return new MarginExpression.merge(this, newMarginExpr);
1292 }
1293
1294 return null;
1295 }
1296
1297 /**
1298 * Merge the two MarginExpressions and return the result.
1299 */
1300 factory MarginExpression.merge(MarginExpression x, MarginExpression y) {
1301 return new MarginExpression._merge(x, y, y.span);
1302 }
1303
1304 MarginExpression._merge(
1305 MarginExpression x, MarginExpression y, SourceSpan span)
1306 : super(x._styleType, span, new BoxEdge.merge(x.box, y.box));
1307
1308 MarginExpression clone() => new MarginExpression(span,
1309 top: box.top, right: box.right, bottom: box.bottom, left: box.left);
1310
1311 visit(VisitorBase visitor) => visitor.visitMarginExpression(this);
1312 }
1313
1314 class BorderExpression extends BoxExpression {
1315 /** Border expression ripped apart. */
1316 BorderExpression(SourceSpan span, {num top, num right, num bottom, num left})
1317 : super(DartStyleExpression.borderStyle, span,
1318 new BoxEdge(left, top, right, bottom));
1319
1320 BorderExpression.boxEdge(SourceSpan span, BoxEdge box)
1321 : super(DartStyleExpression.borderStyle, span, box);
1322
1323 merged(DartStyleExpression newBorderExpr) {
1324 if (newBorderExpr is BorderExpression &&
1325 this.isBorder &&
1326 newBorderExpr.isBorder) {
1327 return new BorderExpression.merge(this, newBorderExpr);
1328 }
1329
1330 return null;
1331 }
1332
1333 /**
1334 * Merge the two BorderExpression and return the result.
1335 */
1336 factory BorderExpression.merge(BorderExpression x, BorderExpression y) {
1337 return new BorderExpression._merge(x, y, y.span);
1338 }
1339
1340 BorderExpression._merge(
1341 BorderExpression x, BorderExpression y, SourceSpan span)
1342 : super(DartStyleExpression.borderStyle, span,
1343 new BoxEdge.merge(x.box, y.box));
1344
1345 BorderExpression clone() => new BorderExpression(span,
1346 top: box.top, right: box.right, bottom: box.bottom, left: box.left);
1347
1348 visit(VisitorBase visitor) => visitor.visitBorderExpression(this);
1349 }
1350
1351 class HeightExpression extends DartStyleExpression {
1352 final height;
1353
1354 HeightExpression(SourceSpan span, this.height)
1355 : super(DartStyleExpression.heightStyle, span);
1356
1357 merged(DartStyleExpression newHeightExpr) {
1358 if (newHeightExpr is DartStyleExpression &&
1359 this.isHeight &&
1360 newHeightExpr.isHeight) {
1361 return newHeightExpr;
1362 }
1363
1364 return null;
1365 }
1366
1367 HeightExpression clone() => new HeightExpression(span, height);
1368 visit(VisitorBase visitor) => visitor.visitHeightExpression(this);
1369 }
1370
1371 class WidthExpression extends DartStyleExpression {
1372 final width;
1373
1374 WidthExpression(SourceSpan span, this.width)
1375 : super(DartStyleExpression.widthStyle, span);
1376
1377 merged(DartStyleExpression newWidthExpr) {
1378 if (newWidthExpr is WidthExpression &&
1379 this.isWidth &&
1380 newWidthExpr.isWidth) {
1381 return newWidthExpr;
1382 }
1383
1384 return null;
1385 }
1386
1387 WidthExpression clone() => new WidthExpression(span, width);
1388 visit(VisitorBase visitor) => visitor.visitWidthExpression(this);
1389 }
1390
1391 class PaddingExpression extends BoxExpression {
1392 /** Padding expression ripped apart. */
1393 PaddingExpression(SourceSpan span, {num top, num right, num bottom, num left})
1394 : super(DartStyleExpression.paddingStyle, span,
1395 new BoxEdge(left, top, right, bottom));
1396
1397 PaddingExpression.boxEdge(SourceSpan span, BoxEdge box)
1398 : super(DartStyleExpression.paddingStyle, span, box);
1399
1400 merged(DartStyleExpression newPaddingExpr) {
1401 if (newPaddingExpr is PaddingExpression &&
1402 this.isPadding &&
1403 newPaddingExpr.isPadding) {
1404 return new PaddingExpression.merge(this, newPaddingExpr);
1405 }
1406
1407 return null;
1408 }
1409
1410 /**
1411 * Merge the two PaddingExpression and return the result.
1412 */
1413 factory PaddingExpression.merge(PaddingExpression x, PaddingExpression y) {
1414 return new PaddingExpression._merge(x, y, y.span);
1415 }
1416
1417 PaddingExpression._merge(
1418 PaddingExpression x, PaddingExpression y, SourceSpan span)
1419 : super(DartStyleExpression.paddingStyle, span,
1420 new BoxEdge.merge(x.box, y.box));
1421
1422 PaddingExpression clone() => new PaddingExpression(span,
1423 top: box.top, right: box.right, bottom: box.bottom, left: box.left);
1424 visit(VisitorBase visitor) => visitor.visitPaddingExpression(this);
1425 }
OLDNEW
« no previous file with comments | « csslib/lib/src/tokenkind.dart ('k') | csslib/lib/src/tree_base.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698