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

Side by Side Diff: pkg/csslib/lib/src/polyfill.dart

Issue 23819036: Support for @mixin, @include and @extend (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: All changes ready to commit Created 7 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 | Annotate | Revision Log
« no previous file with comments | « pkg/csslib/lib/src/options.dart ('k') | pkg/csslib/lib/src/tokenkind.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 /** 7 /**
8 * CSS polyfill emits CSS to be understood by older parsers that which do not 8 * CSS polyfill emits CSS to be understood by older parsers that which do not
9 * understand (var, calc, etc.). 9 * understand (var, calc, etc.).
10 */ 10 */
11 class PolyFill { 11 class PolyFill {
12 final Messages _messages; 12 final Messages _messages;
13 final bool _warningsAsErrors; 13 final bool _warningsAsErrors;
14 Map<String, VarDefinition> _allVarDefinitions =
15 new Map<String, VarDefinition>();
14 16
15 Set<StyleSheet> allStyleSheets = new Set<StyleSheet>(); 17 Set<StyleSheet> allStyleSheets = new Set<StyleSheet>();
16 18
17 /** 19 /**
18 * [_pseudoElements] list of known pseudo attributes found in HTML, any 20 * [_pseudoElements] list of known pseudo attributes found in HTML, any
19 * CSS pseudo-elements 'name::custom-element' is mapped to the manged name 21 * CSS pseudo-elements 'name::custom-element' is mapped to the manged name
20 * associated with the pseudo-element key. 22 * associated with the pseudo-element key.
21 */ 23 */
22 PolyFill(this._messages, this._warningsAsErrors); 24 PolyFill(this._messages, this._warningsAsErrors);
23 25
24 /** 26 /**
25 * Run the analyzer on every file that is a style sheet or any component that 27 * Run the analyzer on every file that is a style sheet or any component that
26 * has a style tag. 28 * has a style tag.
27 */ 29 */
28 void process(StyleSheet stylesheet) { 30 void process(StyleSheet styleSheet, {List<StyleSheet> includes: null}) {
29 // TODO(terry): Process all imported stylesheets. 31 if (includes != null) {
32 processVarDefinitions(includes);
33 }
34 processVars(styleSheet);
30 35
31 var styleSheets = processVars([stylesheet]); 36 // Remove all var definitions for this style sheet.
32 allStyleSheets.addAll(styleSheets); 37 new _RemoveVarDefinitions().visitTree(styleSheet);
33
34 normalize();
35 } 38 }
36 39
37 void normalize() { 40 /** Process all includes looking for var definitions. */
38 // Remove all var definitions for all style sheets analyzed. 41 void processVarDefinitions(List<StyleSheet> includes) {
39 for (var tree in allStyleSheets) 42 for (var include in includes) {
40 new _RemoveVarDefinitions().visitTree(tree); 43 _allVarDefinitions = (new _VarDefinitionsIncludes(_allVarDefinitions)
44 ..visitTree(include)).varDefs;
45 }
41 } 46 }
42 47
43 List<StyleSheet> processVars(List<StyleSheet> styleSheets) { 48 void processVars(StyleSheet styleSheet) {
44 // TODO(terry): Process all dependencies.
45 // Build list of all var definitions. 49 // Build list of all var definitions.
46 Map varDefs = new Map(); 50 var mainStyleSheetVarDefs =
47 for (var tree in styleSheets) { 51 (new _VarDefAndUsage(this._messages, _allVarDefinitions)
48 var allDefs = (new _VarDefinitions()..visitTree(tree)).found; 52 ..visitTree(styleSheet)).varDefs;
49 allDefs.forEach((key, value) {
50 varDefs[key] = value;
51 });
52 }
53 53
54 // Resolve all definitions to a non-VarUsage (terminal expression). 54 // Resolve all definitions to a non-VarUsage (terminal expression).
55 varDefs.forEach((key, value) { 55 mainStyleSheetVarDefs.forEach((key, value) {
56 for (var expr in (value.expression as Expressions).expressions) { 56 for (Expression expr in (value.expression as Expressions).expressions) {
57 var def = _findTerminalVarDefinition(varDefs, value); 57 mainStyleSheetVarDefs[key] =
58 varDefs[key] = def; 58 _findTerminalVarDefinition(_allVarDefinitions, value);
59 } 59 }
60 }); 60 });
61
62 // Resolve all var usages.
63 for (var tree in styleSheets) {
64 new _ResolveVarUsages(varDefs).visitTree(tree);
65 }
66
67 return styleSheets;
68 } 61 }
69 } 62 }
70 63
71 /** 64 /** Build list of all var definitions in all includes. */
72 * Find var- definitions in a style sheet. 65 class _VarDefinitionsIncludes extends Visitor {
73 * [found] list of known definitions. 66 final Map<String, VarDefinition> varDefs;
74 */ 67
75 class _VarDefinitions extends Visitor { 68 _VarDefinitionsIncludes(this.varDefs);
76 final Map<String, VarDefinition> found = new Map();
77 69
78 void visitTree(StyleSheet tree) { 70 void visitTree(StyleSheet tree) {
79 visitStyleSheet(tree); 71 visitStyleSheet(tree);
80 } 72 }
81 73
82 visitVarDefinition(VarDefinition node) { 74 visitVarDefinition(VarDefinition node) {
83 // Replace with latest variable definition. 75 // Replace with latest variable definition.
84 found[node.definedName] = node; 76 varDefs[node.definedName] = node;
85 super.visitVarDefinition(node); 77 super.visitVarDefinition(node);
86 } 78 }
87 79
88 void visitVarDefinitionDirective(VarDefinitionDirective node) { 80 void visitVarDefinitionDirective(VarDefinitionDirective node) {
89 visitVarDefinition(node.def); 81 visitVarDefinition(node.def);
90 } 82 }
91 } 83 }
92 84
93 /** 85 /**
94 * Resolve any CSS expression which contains a var() usage to the ultimate real 86 * Find var- definitions in a style sheet.
95 * CSS expression value e.g., 87 * [found] list of known definitions.
96 *
97 * var-one: var(two);
98 * var-two: #ff00ff;
99 *
100 * .test {
101 * color: var(one);
102 * }
103 *
104 * then .test's color would be #ff00ff
105 */ 88 */
106 class _ResolveVarUsages extends Visitor { 89 class _VarDefAndUsage extends Visitor {
107 final Map<String, VarDefinition> varDefs; 90 final Messages _messages;
108 bool inVarDefinition = false; 91 final Map<String, VarDefinition> _knownVarDefs;
109 bool inUsage = false; 92 final Map<String, VarDefinition> varDefs = new Map<String, VarDefinition>();
110 Expressions currentExpressions;
111 93
112 _ResolveVarUsages(this.varDefs); 94 VarDefinition currVarDefinition;
95 List<Expression> currentExpressions;
96
97 _VarDefAndUsage(this._messages, this._knownVarDefs);
113 98
114 void visitTree(StyleSheet tree) { 99 void visitTree(StyleSheet tree) {
115 visitStyleSheet(tree); 100 visitStyleSheet(tree);
116 } 101 }
117 102
118 void visitVarDefinition(VarDefinition varDef) { 103 visitVarDefinition(VarDefinition node) {
119 inVarDefinition = true; 104 // Replace with latest variable definition.
120 super.visitVarDefinition(varDef); 105 currVarDefinition = node;
121 inVarDefinition = false; 106
107 _knownVarDefs[node.definedName] = node;
108 varDefs[node.definedName] = node;
109
110 super.visitVarDefinition(node);
111
112 currVarDefinition = null;
113 }
114
115 void visitVarDefinitionDirective(VarDefinitionDirective node) {
116 visitVarDefinition(node.def);
122 } 117 }
123 118
124 void visitExpressions(Expressions node) { 119 void visitExpressions(Expressions node) {
125 currentExpressions = node; 120 currentExpressions = node.expressions;
126 super.visitExpressions(node); 121 super.visitExpressions(node);
127 currentExpressions = null; 122 currentExpressions = null;
128 } 123 }
129 124
130 void visitVarUsage(VarUsage node) { 125 void visitVarUsage(VarUsage node) {
126 if (currVarDefinition != null && currVarDefinition.badUsage) return;
127
131 // Don't process other var() inside of a varUsage. That implies that the 128 // Don't process other var() inside of a varUsage. That implies that the
132 // default is a var() too. Also, don't process any var() inside of a 129 // default is a var() too. Also, don't process any var() inside of a
133 // varDefinition (they're just place holders until we've resolved all real 130 // varDefinition (they're just place holders until we've resolved all real
134 // usages. 131 // usages.
135 if (!inUsage && !inVarDefinition && currentExpressions != null) { 132 var expressions = currentExpressions;
136 var expressions = currentExpressions.expressions; 133 var index = expressions.indexOf(node);
137 var index = expressions.indexOf(node); 134 assert(index >= 0);
138 assert(index >= 0); 135 var def = _knownVarDefs[node.name];
139 var def = varDefs[node.name]; 136 if (def != null) {
140 if (def != null) { 137 if (def.badUsage) {
141 // Found a VarDefinition use it. 138 // Remove any expressions pointing to a bad var definition.
142 _resolveVarUsage(currentExpressions.expressions, index, def); 139 expressions.removeAt(index);
143 } else if (node.defaultValues.any((e) => e is VarUsage)) { 140 return;
144 // Don't have a VarDefinition need to use default values resolve all 141 }
145 // default values. 142 _resolveVarUsage(currentExpressions, index,
146 var terminalDefaults = []; 143 _findTerminalVarDefinition(_knownVarDefs, def));
147 for (var defaultValue in node.defaultValues) { 144 } else if (node.defaultValues.any((e) => e is VarUsage)) {
148 terminalDefaults.addAll(resolveUsageTerminal(defaultValue)); 145 // Don't have a VarDefinition need to use default values resolve all
146 // default values.
147 var terminalDefaults = [];
148 for (var defaultValue in node.defaultValues) {
149 terminalDefaults.addAll(resolveUsageTerminal(defaultValue));
150 }
151 expressions.replaceRange(index, index + 1, terminalDefaults);
152 } else if (node.defaultValues.isNotEmpty){
153 // No VarDefinition but default value is a terminal expression; use it.
154 expressions.replaceRange(index, index + 1, node.defaultValues);
155 } else {
156 if (currVarDefinition != null) {
157 currVarDefinition.badUsage = true;
158 var mainStyleSheetDef = varDefs[node.name];
159 if (mainStyleSheetDef != null) {
160 varDefs.remove(currVarDefinition.property);
149 } 161 }
150 expressions.replaceRange(index, index + 1, terminalDefaults);
151 } else {
152 // No VarDefinition but default value is a terminal expression; use it.
153 expressions.replaceRange(index, index + 1, node.defaultValues);
154 } 162 }
163 // Remove var usage that points at an undefined definition.
164 expressions.removeAt(index);
165 _messages.warning("Variable is not defined.", node.span);
155 } 166 }
156 167
157 inUsage = true; 168 var oldExpressions = currentExpressions;
169 currentExpressions = node.defaultValues;
158 super.visitVarUsage(node); 170 super.visitVarUsage(node);
159 inUsage = false; 171 currentExpressions = oldExpressions;
160 } 172 }
161 173
162 List<Expression> resolveUsageTerminal(VarUsage usage) { 174 List<Expression> resolveUsageTerminal(VarUsage usage) {
163 var result = []; 175 var result = [];
164 176
165 var varDef = varDefs[usage.name]; 177 var varDef = _knownVarDefs[usage.name];
166 var expressions; 178 var expressions;
167 if (varDef == null) { 179 if (varDef == null) {
168 // VarDefinition not found try the defaultValues. 180 // VarDefinition not found try the defaultValues.
169 expressions = usage.defaultValues; 181 expressions = usage.defaultValues;
170 } else { 182 } else {
171 // Use the VarDefinition found. 183 // Use the VarDefinition found.
172 expressions = (varDef.expression as Expressions).expressions; 184 expressions = (varDef.expression as Expressions).expressions;
173 } 185 }
174 186
175 for (var expr in expressions) { 187 for (var expr in expressions) {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 } 249 }
238 } else { 250 } else {
239 // Return real CSS property. 251 // Return real CSS property.
240 return varDef; 252 return varDef;
241 } 253 }
242 } 254 }
243 255
244 // Didn't point to a var definition that existed. 256 // Didn't point to a var definition that existed.
245 return varDef; 257 return varDef;
246 } 258 }
OLDNEW
« no previous file with comments | « pkg/csslib/lib/src/options.dart ('k') | pkg/csslib/lib/src/tokenkind.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698