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

Side by Side Diff: lib/src/analyzer.dart

Issue 998843003: pkg/csslib: formatting (Closed) Base URL: https://github.com/dart-lang/csslib@master
Patch Set: Created 5 years, 9 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
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of csslib.parser; 5 part of csslib.parser;
6 6
7
8 // TODO(terry): Add optimizing phase to remove duplicated selectors in the same 7 // TODO(terry): Add optimizing phase to remove duplicated selectors in the same
9 // selector group (e.g., .btn, .btn { color: red; }). Also, look 8 // selector group (e.g., .btn, .btn { color: red; }). Also, look
10 // at simplifying selectors expressions too (much harder). 9 // at simplifying selectors expressions too (much harder).
11 // TODO(terry): Detect invalid directive usage. All @imports must occur before 10 // TODO(terry): Detect invalid directive usage. All @imports must occur before
12 // all rules other than @charset directive. Any @import directive 11 // all rules other than @charset directive. Any @import directive
13 // after any non @charset or @import directive are ignored. e.g., 12 // after any non @charset or @import directive are ignored. e.g.,
14 // @import "a.css"; 13 // @import "a.css";
15 // div { color: red; } 14 // div { color: red; }
16 // @import "b.css"; 15 // @import "b.css";
17 // becomes: 16 // becomes:
18 // @import "a.css"; 17 // @import "a.css";
19 // div { color: red; } 18 // div { color: red; }
20 // <http://www.w3.org/TR/css3-syntax/#at-rules> 19 // <http://www.w3.org/TR/css3-syntax/#at-rules>
21 20
22 /** 21 /**
23 * Analysis phase will validate/fixup any new CSS feature or any SASS style 22 * Analysis phase will validate/fixup any new CSS feature or any SASS style
24 * feature. 23 * feature.
25 */ 24 */
26 class Analyzer { 25 class Analyzer {
27 final List<StyleSheet> _styleSheets; 26 final List<StyleSheet> _styleSheets;
28 final Messages _messages; 27 final Messages _messages;
29 28
30 Analyzer(this._styleSheets, this._messages); 29 Analyzer(this._styleSheets, this._messages);
31 30
32 // TODO(terry): Currently each feature walks the AST each time. Once we have 31 // TODO(terry): Currently each feature walks the AST each time. Once we have
33 // our complete feature set consider benchmarking the cost and 32 // our complete feature set consider benchmarking the cost and
34 // possibly combine in one walk. 33 // possibly combine in one walk.
35 void run() { 34 void run() {
36 // Expand top-level @include. 35 // Expand top-level @include.
37 _styleSheets.forEach((styleSheet) => 36 _styleSheets.forEach(
38 TopLevelIncludes.expand(_messages, _styleSheets)); 37 (styleSheet) => TopLevelIncludes.expand(_messages, _styleSheets));
39 38
40 // Expand @include in declarations. 39 // Expand @include in declarations.
41 _styleSheets.forEach((styleSheet) => 40 _styleSheets.forEach(
42 DeclarationIncludes.expand(_messages, _styleSheets)); 41 (styleSheet) => DeclarationIncludes.expand(_messages, _styleSheets));
43 42
44 // Remove all @mixin and @include 43 // Remove all @mixin and @include
45 _styleSheets.forEach((styleSheet) => MixinsAndIncludes.remove(styleSheet)); 44 _styleSheets.forEach((styleSheet) => MixinsAndIncludes.remove(styleSheet));
46 45
47 // Expand any nested selectors using selector desendant combinator to 46 // Expand any nested selectors using selector desendant combinator to
48 // signal CSS inheritance notation. 47 // signal CSS inheritance notation.
49 _styleSheets.forEach((styleSheet) => new ExpandNestedSelectors() 48 _styleSheets.forEach((styleSheet) => new ExpandNestedSelectors()
50 ..visitStyleSheet(styleSheet) 49 ..visitStyleSheet(styleSheet)
51 ..flatten(styleSheet)); 50 ..flatten(styleSheet));
52 51
53 // Expand any @extend. 52 // Expand any @extend.
54 _styleSheets.forEach((styleSheet) { 53 _styleSheets.forEach((styleSheet) {
55 var allExtends = new AllExtends()..visitStyleSheet(styleSheet); 54 var allExtends = new AllExtends()..visitStyleSheet(styleSheet);
56 new InheritExtends(_messages, allExtends)..visitStyleSheet(styleSheet); 55 new InheritExtends(_messages, allExtends)..visitStyleSheet(styleSheet);
57 }); 56 });
58 } 57 }
59 } 58 }
60 59
61 /** 60 /**
62 * Traverse all rulesets looking for nested ones. If a ruleset is in a 61 * Traverse all rulesets looking for nested ones. If a ruleset is in a
63 * declaration group (implies nested selector) then generate new ruleset(s) at 62 * declaration group (implies nested selector) then generate new ruleset(s) at
64 * level 0 of CSS using selector inheritance syntax (flattens the nesting). 63 * level 0 of CSS using selector inheritance syntax (flattens the nesting).
65 * 64 *
66 * How the AST works for a rule [RuleSet] and nested rules. First of all a 65 * How the AST works for a rule [RuleSet] and nested rules. First of all a
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 _nestedSelectorGroup = _mergeToFlatten(node); 207 _nestedSelectorGroup = _mergeToFlatten(node);
209 } 208 }
210 209
211 _parentRuleSet = node; 210 _parentRuleSet = node;
212 211
213 super.visitRuleSet(node); 212 super.visitRuleSet(node);
214 213
215 _parentRuleSet = oldParent; 214 _parentRuleSet = oldParent;
216 215
217 // Remove nested rules; they're all flatten and in the _expandedRuleSets. 216 // Remove nested rules; they're all flatten and in the _expandedRuleSets.
218 node.declarationGroup.declarations.removeWhere((declaration) => 217 node.declarationGroup.declarations
219 declaration is RuleSet); 218 .removeWhere((declaration) => declaration is RuleSet);
220 219
221 _nestedSelectorGroup = oldNestedSelectorGroups; 220 _nestedSelectorGroup = oldNestedSelectorGroups;
222 221
223 // If any expandedRuleSets and we're back at the top-level rule set then 222 // If any expandedRuleSets and we're back at the top-level rule set then
224 // there were nested rule set(s). 223 // there were nested rule set(s).
225 if (_parentRuleSet == null) { 224 if (_parentRuleSet == null) {
226 if (!_expandedRuleSets.isEmpty) { 225 if (!_expandedRuleSets.isEmpty) {
227 // Remember ruleset to replace with these flattened rulesets. 226 // Remember ruleset to replace with these flattened rulesets.
228 _expansions[node] = _expandedRuleSets; 227 _expansions[node] = _expandedRuleSets;
229 _expandedRuleSets = []; 228 _expandedRuleSets = [];
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 * descendant. Used for nested selectors when the parent selector needs to 297 * descendant. Used for nested selectors when the parent selector needs to
299 * be prefixed to a nested selector or to substitute the this (&) with the 298 * be prefixed to a nested selector or to substitute the this (&) with the
300 * parent selector. 299 * parent selector.
301 */ 300 */
302 List<SimpleSelectorSequence> _convertToDescendentSequence( 301 List<SimpleSelectorSequence> _convertToDescendentSequence(
303 List<SimpleSelectorSequence> sequences) { 302 List<SimpleSelectorSequence> sequences) {
304 if (sequences.isEmpty) return sequences; 303 if (sequences.isEmpty) return sequences;
305 304
306 var newSequences = []; 305 var newSequences = [];
307 var first = sequences.first; 306 var first = sequences.first;
308 newSequences.add(new SimpleSelectorSequence(first.simpleSelector, 307 newSequences.add(new SimpleSelectorSequence(
309 first.span, TokenKind.COMBINATOR_DESCENDANT)); 308 first.simpleSelector, first.span, TokenKind.COMBINATOR_DESCENDANT));
310 newSequences.addAll(sequences.skip(1)); 309 newSequences.addAll(sequences.skip(1));
311 310
312 return newSequences; 311 return newSequences;
313 } 312 }
314 313
315 void visitDeclarationGroup(DeclarationGroup node) { 314 void visitDeclarationGroup(DeclarationGroup node) {
316 var span = node.span; 315 var span = node.span;
317 316
318 var currentGroup = new DeclarationGroup([], span); 317 var currentGroup = new DeclarationGroup([], span);
319 318
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 399
401 class _MediaRulesReplacer extends Visitor { 400 class _MediaRulesReplacer extends Visitor {
402 RuleSet _ruleSet; 401 RuleSet _ruleSet;
403 List<RuleSet> _newRules; 402 List<RuleSet> _newRules;
404 bool _foundAndReplaced = false; 403 bool _foundAndReplaced = false;
405 404
406 /** 405 /**
407 * Look for the [ruleSet] inside of an @media directive; if found then replace 406 * Look for the [ruleSet] inside of an @media directive; if found then replace
408 * with the [newRules]. If [ruleSet] is found and replaced return true. 407 * with the [newRules]. If [ruleSet] is found and replaced return true.
409 */ 408 */
410 static bool replace(StyleSheet styleSheet, RuleSet ruleSet, 409 static bool replace(
411 List<RuleSet>newRules) { 410 StyleSheet styleSheet, RuleSet ruleSet, List<RuleSet> newRules) {
412 var visitor = new _MediaRulesReplacer(ruleSet, newRules); 411 var visitor = new _MediaRulesReplacer(ruleSet, newRules);
413 visitor.visitStyleSheet(styleSheet); 412 visitor.visitStyleSheet(styleSheet);
414 return visitor._foundAndReplaced; 413 return visitor._foundAndReplaced;
415 } 414 }
416 415
417 _MediaRulesReplacer(this._ruleSet, this._newRules); 416 _MediaRulesReplacer(this._ruleSet, this._newRules);
418 417
419 visitMediaDirective(MediaDirective node) { 418 visitMediaDirective(MediaDirective node) {
420 var index = node.rulesets.indexOf(_ruleSet); 419 var index = node.rulesets.indexOf(_ruleSet);
421 if (index != -1) { 420 if (index != -1) {
(...skipping 30 matching lines...) Expand all
452 void visitStyleSheet(StyleSheet ss) { 451 void visitStyleSheet(StyleSheet ss) {
453 _styleSheet = ss; 452 _styleSheet = ss;
454 super.visitStyleSheet(ss); 453 super.visitStyleSheet(ss);
455 _styleSheet = null; 454 _styleSheet = null;
456 } 455 }
457 456
458 void visitIncludeDirective(IncludeDirective node) { 457 void visitIncludeDirective(IncludeDirective node) {
459 if (map.containsKey(node.name)) { 458 if (map.containsKey(node.name)) {
460 var mixinDef = map[node.name]; 459 var mixinDef = map[node.name];
461 if (mixinDef is MixinRulesetDirective) { 460 if (mixinDef is MixinRulesetDirective) {
462 _TopLevelIncludeReplacer.replace(_messages, _styleSheet, node, 461 _TopLevelIncludeReplacer.replace(
463 mixinDef.rulesets); 462 _messages, _styleSheet, node, mixinDef.rulesets);
464 } else if (currDef is MixinRulesetDirective && _anyRulesets(currDef)) { 463 } else if (currDef is MixinRulesetDirective && _anyRulesets(currDef)) {
465 // currDef is MixinRulesetDirective 464 // currDef is MixinRulesetDirective
466 MixinRulesetDirective mixinRuleset = currDef; 465 MixinRulesetDirective mixinRuleset = currDef;
467 int index = mixinRuleset.rulesets.indexOf(node as dynamic); 466 int index = mixinRuleset.rulesets.indexOf(node as dynamic);
468 mixinRuleset.rulesets.replaceRange(index, index + 1, [new NoOp()]); 467 mixinRuleset.rulesets.replaceRange(index, index + 1, [new NoOp()]);
469 _messages.warning( 468 _messages.warning(
470 'Using declaration mixin ${node.name} as top-level mixin', 469 'Using declaration mixin ${node.name} as top-level mixin',
471 node.span); 470 node.span);
472 } 471 }
473 } else { 472 } else {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
512 final Messages _messages; 511 final Messages _messages;
513 final IncludeDirective _include; 512 final IncludeDirective _include;
514 final List<RuleSet> _newRules; 513 final List<RuleSet> _newRules;
515 bool _foundAndReplaced = false; 514 bool _foundAndReplaced = false;
516 515
517 /** 516 /**
518 * Look for the [ruleSet] inside of an @media directive; if found then replace 517 * Look for the [ruleSet] inside of an @media directive; if found then replace
519 * with the [newRules]. If [ruleSet] is found and replaced return true. 518 * with the [newRules]. If [ruleSet] is found and replaced return true.
520 */ 519 */
521 static bool replace(Messages messages, StyleSheet styleSheet, 520 static bool replace(Messages messages, StyleSheet styleSheet,
522 IncludeDirective include, List<RuleSet>newRules) { 521 IncludeDirective include, List<RuleSet> newRules) {
523 var visitor = new _TopLevelIncludeReplacer(messages, include, newRules); 522 var visitor = new _TopLevelIncludeReplacer(messages, include, newRules);
524 visitor.visitStyleSheet(styleSheet); 523 visitor.visitStyleSheet(styleSheet);
525 return visitor._foundAndReplaced; 524 return visitor._foundAndReplaced;
526 } 525 }
527 526
528 _TopLevelIncludeReplacer(this._messages, this._include, this._newRules); 527 _TopLevelIncludeReplacer(this._messages, this._include, this._newRules);
529 528
530 visitStyleSheet(StyleSheet node) { 529 visitStyleSheet(StyleSheet node) {
531 var index = node.topLevels.indexOf(_include); 530 var index = node.topLevels.indexOf(_include);
532 if (index != -1) { 531 if (index != -1) {
(...skipping 15 matching lines...) Expand all
548 super.visitMixinRulesetDirective(node); 547 super.visitMixinRulesetDirective(node);
549 } 548 }
550 } 549 }
551 550
552 /** 551 /**
553 * Utility function to match an include to a list of either Declarations or 552 * Utility function to match an include to a list of either Declarations or
554 * RuleSets, depending on type of mixin (ruleset or declaration). The include 553 * RuleSets, depending on type of mixin (ruleset or declaration). The include
555 * can be an include in a declaration or an include directive (top-level). 554 * can be an include in a declaration or an include directive (top-level).
556 */ 555 */
557 int _findInclude(List list, var node) { 556 int _findInclude(List list, var node) {
558 IncludeDirective matchNode = (node is IncludeMixinAtDeclaration) ? 557 IncludeDirective matchNode =
559 node.include : node; 558 (node is IncludeMixinAtDeclaration) ? node.include : node;
560 559
561 var index = 0; 560 var index = 0;
562 for (var item in list) { 561 for (var item in list) {
563 var includeNode = (item is IncludeMixinAtDeclaration) ? 562 var includeNode = (item is IncludeMixinAtDeclaration) ? item.include : item;
564 item.include : item;
565 if (includeNode == matchNode) return index; 563 if (includeNode == matchNode) return index;
566 index++; 564 index++;
567 } 565 }
568 return -1; 566 return -1;
569 } 567 }
570 568
571 /** 569 /**
572 * Stamp out a mixin with the defined args substituted with the user's 570 * Stamp out a mixin with the defined args substituted with the user's
573 * parameters. 571 * parameters.
574 */ 572 */
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
717 DeclarationIncludes(this._messages, List<StyleSheet> styleSheets) { 715 DeclarationIncludes(this._messages, List<StyleSheet> styleSheets) {
718 for (var styleSheet in styleSheets) { 716 for (var styleSheet in styleSheets) {
719 visitTree(styleSheet); 717 visitTree(styleSheet);
720 } 718 }
721 } 719 }
722 720
723 bool _allIncludes(rulesets) => 721 bool _allIncludes(rulesets) =>
724 rulesets.every((rule) => rule is IncludeDirective || rule is NoOp); 722 rulesets.every((rule) => rule is IncludeDirective || rule is NoOp);
725 723
726 CallMixin _createCallDeclMixin(MixinDefinition mixinDef) { 724 CallMixin _createCallDeclMixin(MixinDefinition mixinDef) {
727 callMap.putIfAbsent(mixinDef.name, () => 725 callMap.putIfAbsent(mixinDef.name,
728 callMap[mixinDef.name] = new CallMixin(mixinDef, varDefs)); 726 () => callMap[mixinDef.name] = new CallMixin(mixinDef, varDefs));
729 return callMap[mixinDef.name]; 727 return callMap[mixinDef.name];
730 } 728 }
731 729
732 void visitStyleSheet(StyleSheet ss) { 730 void visitStyleSheet(StyleSheet ss) {
733 _styleSheet = ss; 731 _styleSheet = ss;
734 super.visitStyleSheet(ss); 732 super.visitStyleSheet(ss);
735 _styleSheet = null; 733 _styleSheet = null;
736 } 734 }
737 735
738 void visitDeclarationGroup(DeclarationGroup node) { 736 void visitDeclarationGroup(DeclarationGroup node) {
739 currDeclGroup = node; 737 currDeclGroup = node;
740 super.visitDeclarationGroup(node); 738 super.visitDeclarationGroup(node);
741 currDeclGroup = null; 739 currDeclGroup = null;
742 } 740 }
743 741
744 void visitIncludeMixinAtDeclaration(IncludeMixinAtDeclaration node) { 742 void visitIncludeMixinAtDeclaration(IncludeMixinAtDeclaration node) {
745 if (map.containsKey(node.include.name)) { 743 if (map.containsKey(node.include.name)) {
746 var mixinDef = map[node.include.name]; 744 var mixinDef = map[node.include.name];
747 745
748 // Fix up any mixin that is really a Declaration but has includes. 746 // Fix up any mixin that is really a Declaration but has includes.
749 if (mixinDef is MixinRulesetDirective) { 747 if (mixinDef is MixinRulesetDirective) {
750 if (!_allIncludes(mixinDef.rulesets) && currDeclGroup != null) { 748 if (!_allIncludes(mixinDef.rulesets) && currDeclGroup != null) {
751 var index = _findInclude(currDeclGroup.declarations, node); 749 var index = _findInclude(currDeclGroup.declarations, node);
752 if (index != -1) { 750 if (index != -1) {
753 currDeclGroup.declarations.replaceRange(index, index + 1, 751 currDeclGroup.declarations.replaceRange(
754 [new NoOp()]); 752 index, index + 1, [new NoOp()]);
755 } 753 }
756 _messages.warning( 754 _messages.warning(
757 "Using top-level mixin ${node.include.name} as a declaration", 755 "Using top-level mixin ${node.include.name} as a declaration",
758 node.span); 756 node.span);
759 } else { 757 } else {
760 // We're a list of @include(s) inside of a mixin ruleset - convert 758 // We're a list of @include(s) inside of a mixin ruleset - convert
761 // to a list of IncludeMixinAtDeclaration(s). 759 // to a list of IncludeMixinAtDeclaration(s).
762 var origRulesets = mixinDef.rulesets; 760 var origRulesets = mixinDef.rulesets;
763 var rulesets = []; 761 var rulesets = [];
764 if (origRulesets.every((ruleset) => ruleset is IncludeDirective)) { 762 if (origRulesets.every((ruleset) => ruleset is IncludeDirective)) {
765 origRulesets.forEach((ruleset) { 763 origRulesets.forEach((ruleset) {
766 rulesets.add(new IncludeMixinAtDeclaration(ruleset, 764 rulesets
767 ruleset.span)); 765 .add(new IncludeMixinAtDeclaration(ruleset, ruleset.span));
768 }); 766 });
769 _IncludeReplacer.replace(_styleSheet, node, rulesets); 767 _IncludeReplacer.replace(_styleSheet, node, rulesets);
770 } 768 }
771 } 769 }
772 } 770 }
773 771
774 if ( mixinDef.definedArgs.length > 0 && node.include.args.length > 0) { 772 if (mixinDef.definedArgs.length > 0 && node.include.args.length > 0) {
775 var callMixin = _createCallDeclMixin(mixinDef); 773 var callMixin = _createCallDeclMixin(mixinDef);
776 mixinDef = callMixin.transform(node.include.args); 774 mixinDef = callMixin.transform(node.include.args);
777 } 775 }
778 776
779 if (mixinDef is MixinDeclarationDirective) { 777 if (mixinDef is MixinDeclarationDirective) {
780 _IncludeReplacer.replace(_styleSheet, node, 778 _IncludeReplacer.replace(
781 mixinDef.declarations.declarations); 779 _styleSheet, node, mixinDef.declarations.declarations);
782 } 780 }
783 } else { 781 } else {
784 _messages.warning("Undefined mixin ${node.include.name}", node.span); 782 _messages.warning("Undefined mixin ${node.include.name}", node.span);
785 } 783 }
786 784
787 super.visitIncludeMixinAtDeclaration(node); 785 super.visitIncludeMixinAtDeclaration(node);
788 } 786 }
789 787
790 void visitIncludeDirective(IncludeDirective node) { 788 void visitIncludeDirective(IncludeDirective node) {
791 if (map.containsKey(node.name)) { 789 if (map.containsKey(node.name)) {
792 var mixinDef = map[node.name]; 790 var mixinDef = map[node.name];
793 if (currDef is MixinDeclarationDirective && 791 if (currDef is MixinDeclarationDirective &&
794 mixinDef is MixinDeclarationDirective) { 792 mixinDef is MixinDeclarationDirective) {
795 _IncludeReplacer.replace(_styleSheet, node, 793 _IncludeReplacer.replace(
796 mixinDef.declarations.declarations); 794 _styleSheet, node, mixinDef.declarations.declarations);
797 } else if (currDef is MixinDeclarationDirective) { 795 } else if (currDef is MixinDeclarationDirective) {
798 var decls = (currDef as MixinDeclarationDirective) 796 var decls =
799 .declarations.declarations; 797 (currDef as MixinDeclarationDirective).declarations.declarations;
800 var index = _findInclude(decls, node); 798 var index = _findInclude(decls, node);
801 if (index != -1) { 799 if (index != -1) {
802 decls.replaceRange(index, index + 1, [new NoOp()]); 800 decls.replaceRange(index, index + 1, [new NoOp()]);
803 } 801 }
804 } 802 }
805 } 803 }
806 804
807 super.visitIncludeDirective(node); 805 super.visitIncludeDirective(node);
808 } 806 }
809 807
(...skipping 18 matching lines...) Expand all
828 } 826 }
829 827
830 void visitVarDefinition(VarDefinition node) { 828 void visitVarDefinition(VarDefinition node) {
831 // Only record var definitions that have multiple expressions (comma 829 // Only record var definitions that have multiple expressions (comma
832 // separated for mixin parameter substitution. 830 // separated for mixin parameter substitution.
833 var exprs = (node.expression as Expressions).expressions; 831 var exprs = (node.expression as Expressions).expressions;
834 if (exprs.length > 1) { 832 if (exprs.length > 1) {
835 varDefs[node.definedName] = node; 833 varDefs[node.definedName] = node;
836 } 834 }
837 super.visitVarDefinition(node); 835 super.visitVarDefinition(node);
838 } 836 }
839 837
840 void visitVarDefinitionDirective(VarDefinitionDirective node) { 838 void visitVarDefinitionDirective(VarDefinitionDirective node) {
841 visitVarDefinition(node.def); 839 visitVarDefinition(node.def);
842 } 840 }
843 } 841 }
844 842
845 /** @include as a top-level with ruleset(s). */ 843 /** @include as a top-level with ruleset(s). */
846 class _IncludeReplacer extends Visitor { 844 class _IncludeReplacer extends Visitor {
847 final _include; 845 final _include;
848 final List<Declaration> _newDeclarations; 846 final List<Declaration> _newDeclarations;
849 bool _foundAndReplaced = false; 847 bool _foundAndReplaced = false;
850 848
851 /** 849 /**
852 * Look for the [ruleSet] inside of a @media directive; if found then replace 850 * Look for the [ruleSet] inside of a @media directive; if found then replace
853 * with the [newRules]. 851 * with the [newRules].
854 */ 852 */
855 static void replace(StyleSheet ss, var include, 853 static void replace(
856 List<Declaration> newDeclarations) { 854 StyleSheet ss, var include, List<Declaration> newDeclarations) {
857 var visitor = new _IncludeReplacer(include, newDeclarations); 855 var visitor = new _IncludeReplacer(include, newDeclarations);
858 visitor.visitStyleSheet(ss); 856 visitor.visitStyleSheet(ss);
859 } 857 }
860 858
861 _IncludeReplacer(this._include, this._newDeclarations); 859 _IncludeReplacer(this._include, this._newDeclarations);
862 860
863 void visitDeclarationGroup(DeclarationGroup node) { 861 void visitDeclarationGroup(DeclarationGroup node) {
864 var index = _findInclude(node.declarations, _include); 862 var index = _findInclude(node.declarations, _include);
865 if (index != -1) { 863 if (index != -1) {
866 node.declarations.insertAll(index + 1, _newDeclarations); 864 node.declarations.insertAll(index + 1, _newDeclarations);
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
966 /** 964 /**
967 * Changes any selector that matches @extend. 965 * Changes any selector that matches @extend.
968 */ 966 */
969 class InheritExtends extends Visitor { 967 class InheritExtends extends Visitor {
970 final Messages _messages; 968 final Messages _messages;
971 final AllExtends _allExtends; 969 final AllExtends _allExtends;
972 970
973 InheritExtends(this._messages, this._allExtends); 971 InheritExtends(this._messages, this._allExtends);
974 972
975 void visitSelectorGroup(SelectorGroup node) { 973 void visitSelectorGroup(SelectorGroup node) {
976 for (var selectorsIndex = 0; selectorsIndex < node.selectors.length; 974 for (var selectorsIndex = 0;
975 selectorsIndex < node.selectors.length;
977 selectorsIndex++) { 976 selectorsIndex++) {
978 var selectors = node.selectors[selectorsIndex]; 977 var selectors = node.selectors[selectorsIndex];
979 var isLastNone = false; 978 var isLastNone = false;
980 var selectorName = ""; 979 var selectorName = "";
981 for (var index = 0; index < selectors.simpleSelectorSequences.length; 980 for (var index = 0;
981 index < selectors.simpleSelectorSequences.length;
982 index++) { 982 index++) {
983 var simpleSeq = selectors.simpleSelectorSequences[index]; 983 var simpleSeq = selectors.simpleSelectorSequences[index];
984 var namePart = simpleSeq.simpleSelector.toString(); 984 var namePart = simpleSeq.simpleSelector.toString();
985 selectorName = (isLastNone) ? (selectorName + namePart) : namePart; 985 selectorName = (isLastNone) ? (selectorName + namePart) : namePart;
986 List<SelectorGroup> matches = _allExtends.inherits[selectorName]; 986 List<SelectorGroup> matches = _allExtends.inherits[selectorName];
987 if (matches != null) { 987 if (matches != null) {
988 for (var match in matches) { 988 for (var match in matches) {
989 // Create a new group. 989 // Create a new group.
990 var newSelectors = selectors.clone(); 990 var newSelectors = selectors.clone();
991 var newSeq = match.selectors[0].clone(); 991 var newSeq = match.selectors[0].clone();
992 if (isLastNone) { 992 if (isLastNone) {
993 // Add the inherited selector. 993 // Add the inherited selector.
994 node.selectors.add(newSeq); 994 node.selectors.add(newSeq);
995 } else { 995 } else {
996 // Replace the selector sequence to the left of the pseudo class 996 // Replace the selector sequence to the left of the pseudo class
997 // or pseudo element. 997 // or pseudo element.
998 998
999 // Make new selector seq combinator the same as the original. 999 // Make new selector seq combinator the same as the original.
1000 var orgCombinator = 1000 var orgCombinator =
1001 newSelectors.simpleSelectorSequences[index].combinator; 1001 newSelectors.simpleSelectorSequences[index].combinator;
1002 newSeq.simpleSelectorSequences[0].combinator = orgCombinator; 1002 newSeq.simpleSelectorSequences[0].combinator = orgCombinator;
1003 1003
1004 newSelectors.simpleSelectorSequences.replaceRange(index, 1004 newSelectors.simpleSelectorSequences.replaceRange(
1005 index + 1, newSeq.simpleSelectorSequences); 1005 index, index + 1, newSeq.simpleSelectorSequences);
1006 node.selectors.add(newSelectors); 1006 node.selectors.add(newSelectors);
1007 } 1007 }
1008 isLastNone = false; 1008 isLastNone = false;
1009 } 1009 }
1010 } else { 1010 } else {
1011 isLastNone = simpleSeq.isCombinatorNone; 1011 isLastNone = simpleSeq.isCombinatorNone;
1012 } 1012 }
1013 } 1013 }
1014 } 1014 }
1015 super.visitSelectorGroup(node); 1015 super.visitSelectorGroup(node);
1016 } 1016 }
1017 } 1017 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698