OLD | NEW |
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 // 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 |
8 // selector group (e.g., .btn, .btn { color: red; }). Also, look | 8 // selector group (e.g., .btn, .btn { color: red; }). Also, look |
9 // at simplifying selectors expressions too (much harder). | 9 // at simplifying selectors expressions too (much harder). |
10 // TODO(terry): Detect invalid directive usage. All @imports must occur before | 10 // TODO(terry): Detect invalid directive usage. All @imports must occur before |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 * Build up the list of all inherited sequences from the parent selector | 236 * Build up the list of all inherited sequences from the parent selector |
237 * [node] is the current nested selector and it's parent is the last entry in | 237 * [node] is the current nested selector and it's parent is the last entry in |
238 * the [_nestedSelectorGroup]. | 238 * the [_nestedSelectorGroup]. |
239 */ | 239 */ |
240 SelectorGroup _mergeToFlatten(RuleSet node) { | 240 SelectorGroup _mergeToFlatten(RuleSet node) { |
241 // Create a new SelectorGroup for this nesting level. | 241 // Create a new SelectorGroup for this nesting level. |
242 var nestedSelectors = _nestedSelectorGroup.selectors; | 242 var nestedSelectors = _nestedSelectorGroup.selectors; |
243 var selectors = node.selectorGroup.selectors; | 243 var selectors = node.selectorGroup.selectors; |
244 | 244 |
245 // Create a merged set of previous parent selectors and current selectors. | 245 // Create a merged set of previous parent selectors and current selectors. |
246 var newSelectors = []; | 246 var newSelectors = <Selector>[]; |
247 for (Selector selector in selectors) { | 247 for (Selector selector in selectors) { |
248 for (Selector nestedSelector in nestedSelectors) { | 248 for (Selector nestedSelector in nestedSelectors) { |
249 var seq = _mergeNestedSelector(nestedSelector.simpleSelectorSequences, | 249 var seq = _mergeNestedSelector(nestedSelector.simpleSelectorSequences, |
250 selector.simpleSelectorSequences); | 250 selector.simpleSelectorSequences); |
251 newSelectors.add(new Selector(seq, node.span)); | 251 newSelectors.add(new Selector(seq, node.span)); |
252 } | 252 } |
253 } | 253 } |
254 | 254 |
255 return new SelectorGroup(newSelectors, node.span); | 255 return new SelectorGroup(newSelectors, node.span); |
256 } | 256 } |
257 | 257 |
258 /** | 258 /** |
259 * Merge the nested selector sequences [current] to the [parent] sequences or | 259 * Merge the nested selector sequences [current] to the [parent] sequences or |
260 * substitue any & with the parent selector. | 260 * substitue any & with the parent selector. |
261 */ | 261 */ |
262 List<SimpleSelectorSequence> _mergeNestedSelector( | 262 List<SimpleSelectorSequence> _mergeNestedSelector( |
263 List<SimpleSelectorSequence> parent, | 263 List<SimpleSelectorSequence> parent, |
264 List<SimpleSelectorSequence> current) { | 264 List<SimpleSelectorSequence> current) { |
265 | 265 |
266 // If any & operator then the parent selector will be substituted otherwise | 266 // If any & operator then the parent selector will be substituted otherwise |
267 // the parent selector is pre-pended to the current selector. | 267 // the parent selector is pre-pended to the current selector. |
268 var hasThis = current.any((s) => s.simpleSelector.isThis); | 268 var hasThis = current.any((s) => s.simpleSelector.isThis); |
269 | 269 |
270 var newSequence = []; | 270 var newSequence = <SimpleSelectorSequence>[]; |
271 | 271 |
272 if (!hasThis) { | 272 if (!hasThis) { |
273 // If no & in the sector group then prefix with the parent selector. | 273 // If no & in the sector group then prefix with the parent selector. |
274 newSequence.addAll(parent); | 274 newSequence.addAll(parent); |
275 newSequence.addAll(_convertToDescendentSequence(current)); | 275 newSequence.addAll(_convertToDescendentSequence(current)); |
276 } else { | 276 } else { |
277 for (var sequence in current) { | 277 for (var sequence in current) { |
278 if (sequence.simpleSelector.isThis) { | 278 if (sequence.simpleSelector.isThis) { |
279 // Substitue the & with the parent selector and only use a combinator | 279 // Substitue the & with the parent selector and only use a combinator |
280 // descendant if & is prefix by a sequence with an empty name e.g., | 280 // descendant if & is prefix by a sequence with an empty name e.g., |
(...skipping 14 matching lines...) Expand all Loading... |
295 /** | 295 /** |
296 * Return selector sequences with first sequence combinator being a | 296 * Return selector sequences with first sequence combinator being a |
297 * descendant. Used for nested selectors when the parent selector needs to | 297 * descendant. Used for nested selectors when the parent selector needs to |
298 * 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 |
299 * parent selector. | 299 * parent selector. |
300 */ | 300 */ |
301 List<SimpleSelectorSequence> _convertToDescendentSequence( | 301 List<SimpleSelectorSequence> _convertToDescendentSequence( |
302 List<SimpleSelectorSequence> sequences) { | 302 List<SimpleSelectorSequence> sequences) { |
303 if (sequences.isEmpty) return sequences; | 303 if (sequences.isEmpty) return sequences; |
304 | 304 |
305 var newSequences = []; | 305 var newSequences = <SimpleSelectorSequence>[]; |
306 var first = sequences.first; | 306 var first = sequences.first; |
307 newSequences.add(new SimpleSelectorSequence( | 307 newSequences.add(new SimpleSelectorSequence( |
308 first.simpleSelector, first.span, TokenKind.COMBINATOR_DESCENDANT)); | 308 first.simpleSelector, first.span, TokenKind.COMBINATOR_DESCENDANT)); |
309 newSequences.addAll(sequences.skip(1)); | 309 newSequences.addAll(sequences.skip(1)); |
310 | 310 |
311 return newSequences; | 311 return newSequences; |
312 } | 312 } |
313 | 313 |
314 void visitDeclarationGroup(DeclarationGroup node) { | 314 void visitDeclarationGroup(DeclarationGroup node) { |
315 var span = node.span; | 315 var span = node.span; |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
585 visitMixinRulesetDirective(mixinDef); | 585 visitMixinRulesetDirective(mixinDef); |
586 } else { | 586 } else { |
587 visitMixinDeclarationDirective(mixinDef); | 587 visitMixinDeclarationDirective(mixinDef); |
588 } | 588 } |
589 } | 589 } |
590 | 590 |
591 /** | 591 /** |
592 * Given a mixin's defined arguments return a cloned mixin defintion that has | 592 * Given a mixin's defined arguments return a cloned mixin defintion that has |
593 * replaced all defined arguments with user's supplied VarUsages. | 593 * replaced all defined arguments with user's supplied VarUsages. |
594 */ | 594 */ |
595 MixinDefinition transform(List callArgs) { | 595 MixinDefinition transform(List<List<Expression>> callArgs) { |
596 // TODO(terry): Handle default arguments and varArgs. | 596 // TODO(terry): Handle default arguments and varArgs. |
597 // Transform mixin with callArgs. | 597 // Transform mixin with callArgs. |
598 for (var index = 0; index < _definedArgs.length; index++) { | 598 for (var index = 0; index < _definedArgs.length; index++) { |
599 var definedArg = _definedArgs[index]; | 599 var definedArg = _definedArgs[index]; |
600 VarDefinition varDef; | 600 VarDefinition varDef; |
601 if (definedArg is VarDefinition) { | 601 if (definedArg is VarDefinition) { |
602 varDef = definedArg; | 602 varDef = definedArg; |
603 } else if (definedArg is VarDefinitionDirective) { | 603 } else if (definedArg is VarDefinitionDirective) { |
604 VarDefinitionDirective varDirective = definedArg; | 604 VarDefinitionDirective varDirective = definedArg; |
605 varDef = varDirective.def; | 605 varDef = varDirective.def; |
(...skipping 15 matching lines...) Expand all Loading... |
621 k.expressions.replaceRange(usagesIndex, usagesIndex + 1, callArg); | 621 k.expressions.replaceRange(usagesIndex, usagesIndex + 1, callArg); |
622 } | 622 } |
623 }); | 623 }); |
624 } | 624 } |
625 | 625 |
626 // Clone the mixin | 626 // Clone the mixin |
627 return mixinDef.clone(); | 627 return mixinDef.clone(); |
628 } | 628 } |
629 | 629 |
630 /** Rip apart var def with multiple parameters. */ | 630 /** Rip apart var def with multiple parameters. */ |
631 List<List<TreeNode>> _varDefsAsCallArgs(var callArg) { | 631 List<List<Expression>> _varDefsAsCallArgs(var callArg) { |
632 var defArgs = []; | 632 var defArgs = <List<Expression>>[]; |
633 if (callArg is List && callArg[0] is VarUsage) { | 633 if (callArg is List && callArg[0] is VarUsage) { |
634 var varDef = varDefs[callArg[0].name]; | 634 var varDef = varDefs[callArg[0].name]; |
635 var expressions = varDef.expression.expressions; | 635 var expressions = (varDef.expression as Expressions).expressions; |
636 assert(expressions.length > 1); | 636 assert(expressions.length > 1); |
637 for (var expr in expressions) { | 637 for (var expr in expressions) { |
638 if (expr is! OperatorComma) { | 638 if (expr is! OperatorComma) { |
639 defArgs.add([expr]); | 639 defArgs.add([expr]); |
640 } | 640 } |
641 } | 641 } |
642 } | 642 } |
643 return defArgs; | 643 return defArgs; |
644 } | 644 } |
645 | 645 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 currDeclGroup.declarations.replaceRange( | 749 currDeclGroup.declarations.replaceRange( |
750 index, index + 1, [new NoOp()]); | 750 index, index + 1, [new NoOp()]); |
751 } | 751 } |
752 _messages.warning( | 752 _messages.warning( |
753 "Using top-level mixin ${node.include.name} as a declaration", | 753 "Using top-level mixin ${node.include.name} as a declaration", |
754 node.span); | 754 node.span); |
755 } else { | 755 } else { |
756 // We're a list of @include(s) inside of a mixin ruleset - convert | 756 // We're a list of @include(s) inside of a mixin ruleset - convert |
757 // to a list of IncludeMixinAtDeclaration(s). | 757 // to a list of IncludeMixinAtDeclaration(s). |
758 var origRulesets = mixinDef.rulesets; | 758 var origRulesets = mixinDef.rulesets; |
759 var rulesets = []; | 759 var rulesets = <Declaration>[]; |
760 if (origRulesets.every((ruleset) => ruleset is IncludeDirective)) { | 760 if (origRulesets.every((ruleset) => ruleset is IncludeDirective)) { |
761 origRulesets.forEach((ruleset) { | 761 origRulesets.forEach((ruleset) { |
762 rulesets | 762 rulesets.add(new IncludeMixinAtDeclaration( |
763 .add(new IncludeMixinAtDeclaration(ruleset, ruleset.span)); | 763 ruleset as IncludeDirective, ruleset.span)); |
764 }); | 764 }); |
765 _IncludeReplacer.replace(_styleSheet, node, rulesets); | 765 _IncludeReplacer.replace(_styleSheet, node, rulesets); |
766 } | 766 } |
767 } | 767 } |
768 } | 768 } |
769 | 769 |
770 if (mixinDef.definedArgs.length > 0 && node.include.args.length > 0) { | 770 if (mixinDef.definedArgs.length > 0 && node.include.args.length > 0) { |
771 var callMixin = _createCallDeclMixin(mixinDef); | 771 var callMixin = _createCallDeclMixin(mixinDef); |
772 mixinDef = callMixin.transform(node.include.args); | 772 mixinDef = callMixin.transform(node.include.args); |
773 } | 773 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
834 } | 834 } |
835 | 835 |
836 void visitVarDefinitionDirective(VarDefinitionDirective node) { | 836 void visitVarDefinitionDirective(VarDefinitionDirective node) { |
837 visitVarDefinition(node.def); | 837 visitVarDefinition(node.def); |
838 } | 838 } |
839 } | 839 } |
840 | 840 |
841 /** @include as a top-level with ruleset(s). */ | 841 /** @include as a top-level with ruleset(s). */ |
842 class _IncludeReplacer extends Visitor { | 842 class _IncludeReplacer extends Visitor { |
843 final _include; | 843 final _include; |
844 final List<Declaration> _newDeclarations; | 844 final List<TreeNode> _newDeclarations; |
845 bool _foundAndReplaced = false; | 845 bool _foundAndReplaced = false; |
846 | 846 |
847 /** | 847 /** |
848 * Look for the [ruleSet] inside of a @media directive; if found then replace | 848 * Look for the [ruleSet] inside of a @media directive; if found then replace |
849 * with the [newRules]. | 849 * with the [newRules]. |
850 */ | 850 */ |
851 static void replace( | 851 static void replace( |
852 StyleSheet ss, var include, List<Declaration> newDeclarations) { | 852 StyleSheet ss, var include, List<TreeNode> newDeclarations) { |
853 var visitor = new _IncludeReplacer(include, newDeclarations); | 853 var visitor = new _IncludeReplacer(include, newDeclarations); |
854 visitor.visitStyleSheet(ss); | 854 visitor.visitStyleSheet(ss); |
855 } | 855 } |
856 | 856 |
857 _IncludeReplacer(this._include, this._newDeclarations); | 857 _IncludeReplacer(this._include, this._newDeclarations); |
858 | 858 |
859 void visitDeclarationGroup(DeclarationGroup node) { | 859 void visitDeclarationGroup(DeclarationGroup node) { |
860 var index = _findInclude(node.declarations, _include); | 860 var index = _findInclude(node.declarations, _include); |
861 if (index != -1) { | 861 if (index != -1) { |
862 node.declarations.insertAll(index + 1, _newDeclarations); | 862 node.declarations.insertAll(index + 1, _newDeclarations); |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1005 isLastNone = false; | 1005 isLastNone = false; |
1006 } | 1006 } |
1007 } else { | 1007 } else { |
1008 isLastNone = simpleSeq.isCombinatorNone; | 1008 isLastNone = simpleSeq.isCombinatorNone; |
1009 } | 1009 } |
1010 } | 1010 } |
1011 } | 1011 } |
1012 super.visitSelectorGroup(node); | 1012 super.visitSelectorGroup(node); |
1013 } | 1013 } |
1014 } | 1014 } |
OLD | NEW |