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

Side by Side Diff: csslib/lib/src/polyfill.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/options.dart ('k') | csslib/lib/src/property.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) 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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of csslib.parser;
6
7 /**
8 * CSS polyfill emits CSS to be understood by older parsers that which do not
9 * understand (var, calc, etc.).
10 */
11 class PolyFill {
12 final Messages _messages;
13 final bool _warningsAsErrors;
14 Map<String, VarDefinition> _allVarDefinitions =
15 new Map<String, VarDefinition>();
16
17 Set<StyleSheet> allStyleSheets = new Set<StyleSheet>();
18
19 /**
20 * [_pseudoElements] list of known pseudo attributes found in HTML, any
21 * CSS pseudo-elements 'name::custom-element' is mapped to the manged name
22 * associated with the pseudo-element key.
23 */
24 PolyFill(this._messages, this._warningsAsErrors);
25
26 /**
27 * Run the analyzer on every file that is a style sheet or any component that
28 * has a style tag.
29 */
30 void process(StyleSheet styleSheet, {List<StyleSheet> includes: null}) {
31 if (includes != null) {
32 processVarDefinitions(includes);
33 }
34 processVars(styleSheet);
35
36 // Remove all var definitions for this style sheet.
37 new _RemoveVarDefinitions().visitTree(styleSheet);
38 }
39
40 /** Process all includes looking for var definitions. */
41 void processVarDefinitions(List<StyleSheet> includes) {
42 for (var include in includes) {
43 _allVarDefinitions = (new _VarDefinitionsIncludes(_allVarDefinitions)
44 ..visitTree(include)).varDefs;
45 }
46 }
47
48 void processVars(StyleSheet styleSheet) {
49 // Build list of all var definitions.
50 var mainStyleSheetVarDefs = (new _VarDefAndUsage(
51 this._messages, _allVarDefinitions)..visitTree(styleSheet)).varDefs;
52
53 // Resolve all definitions to a non-VarUsage (terminal expression).
54 mainStyleSheetVarDefs.forEach((key, value) {
55 for (var _ in (value.expression as Expressions).expressions) {
56 mainStyleSheetVarDefs[key] =
57 _findTerminalVarDefinition(_allVarDefinitions, value);
58 }
59 });
60 }
61 }
62
63 /** Build list of all var definitions in all includes. */
64 class _VarDefinitionsIncludes extends Visitor {
65 final Map<String, VarDefinition> varDefs;
66
67 _VarDefinitionsIncludes(this.varDefs);
68
69 void visitTree(StyleSheet tree) {
70 visitStyleSheet(tree);
71 }
72
73 visitVarDefinition(VarDefinition node) {
74 // Replace with latest variable definition.
75 varDefs[node.definedName] = node;
76 super.visitVarDefinition(node);
77 }
78
79 void visitVarDefinitionDirective(VarDefinitionDirective node) {
80 visitVarDefinition(node.def);
81 }
82 }
83
84 /**
85 * Find var- definitions in a style sheet.
86 * [found] list of known definitions.
87 */
88 class _VarDefAndUsage extends Visitor {
89 final Messages _messages;
90 final Map<String, VarDefinition> _knownVarDefs;
91 final Map<String, VarDefinition> varDefs = new Map<String, VarDefinition>();
92
93 VarDefinition currVarDefinition;
94 List<Expression> currentExpressions;
95
96 _VarDefAndUsage(this._messages, this._knownVarDefs);
97
98 void visitTree(StyleSheet tree) {
99 visitStyleSheet(tree);
100 }
101
102 visitVarDefinition(VarDefinition node) {
103 // Replace with latest variable definition.
104 currVarDefinition = node;
105
106 _knownVarDefs[node.definedName] = node;
107 varDefs[node.definedName] = node;
108
109 super.visitVarDefinition(node);
110
111 currVarDefinition = null;
112 }
113
114 void visitVarDefinitionDirective(VarDefinitionDirective node) {
115 visitVarDefinition(node.def);
116 }
117
118 void visitExpressions(Expressions node) {
119 currentExpressions = node.expressions;
120 super.visitExpressions(node);
121 currentExpressions = null;
122 }
123
124 void visitVarUsage(VarUsage node) {
125 if (currVarDefinition != null && currVarDefinition.badUsage) return;
126
127 // Don't process other var() inside of a varUsage. That implies that the
128 // default is a var() too. Also, don't process any var() inside of a
129 // varDefinition (they're just place holders until we've resolved all real
130 // usages.
131 var expressions = currentExpressions;
132 var index = expressions.indexOf(node);
133 assert(index >= 0);
134 var def = _knownVarDefs[node.name];
135 if (def != null) {
136 if (def.badUsage) {
137 // Remove any expressions pointing to a bad var definition.
138 expressions.removeAt(index);
139 return;
140 }
141 _resolveVarUsage(currentExpressions, index,
142 _findTerminalVarDefinition(_knownVarDefs, def));
143 } else if (node.defaultValues.any((e) => e is VarUsage)) {
144 // Don't have a VarDefinition need to use default values resolve all
145 // default values.
146 var terminalDefaults = <Expression>[];
147 for (var defaultValue in node.defaultValues) {
148 terminalDefaults.addAll(resolveUsageTerminal(defaultValue));
149 }
150 expressions.replaceRange(index, index + 1, terminalDefaults);
151 } else if (node.defaultValues.isNotEmpty) {
152 // No VarDefinition but default value is a terminal expression; use it.
153 expressions.replaceRange(index, index + 1, node.defaultValues);
154 } else {
155 if (currVarDefinition != null) {
156 currVarDefinition.badUsage = true;
157 var mainStyleSheetDef = varDefs[node.name];
158 if (mainStyleSheetDef != null) {
159 varDefs.remove(currVarDefinition.property);
160 }
161 }
162 // Remove var usage that points at an undefined definition.
163 expressions.removeAt(index);
164 _messages.warning("Variable is not defined.", node.span);
165 }
166
167 var oldExpressions = currentExpressions;
168 currentExpressions = node.defaultValues;
169 super.visitVarUsage(node);
170 currentExpressions = oldExpressions;
171 }
172
173 List<Expression> resolveUsageTerminal(VarUsage usage) {
174 var result = [];
175
176 var varDef = _knownVarDefs[usage.name];
177 var expressions;
178 if (varDef == null) {
179 // VarDefinition not found try the defaultValues.
180 expressions = usage.defaultValues;
181 } else {
182 // Use the VarDefinition found.
183 expressions = (varDef.expression as Expressions).expressions;
184 }
185
186 for (var expr in expressions) {
187 if (expr is VarUsage) {
188 // Get terminal value.
189 result.addAll(resolveUsageTerminal(expr));
190 }
191 }
192
193 // We're at a terminal just return the VarDefinition expression.
194 if (result.isEmpty && varDef != null) {
195 result = (varDef.expression as Expressions).expressions;
196 }
197
198 return result;
199 }
200
201 _resolveVarUsage(List<Expression> expressions, int index, VarDefinition def) {
202 var defExpressions = (def.expression as Expressions).expressions;
203 expressions.replaceRange(index, index + 1, defExpressions);
204 }
205 }
206
207 /** Remove all var definitions. */
208 class _RemoveVarDefinitions extends Visitor {
209 void visitTree(StyleSheet tree) {
210 visitStyleSheet(tree);
211 }
212
213 void visitStyleSheet(StyleSheet ss) {
214 ss.topLevels.removeWhere((e) => e is VarDefinitionDirective);
215 super.visitStyleSheet(ss);
216 }
217
218 void visitDeclarationGroup(DeclarationGroup node) {
219 node.declarations.removeWhere((e) => e is VarDefinition);
220 super.visitDeclarationGroup(node);
221 }
222 }
223
224 /** Find terminal definition (non VarUsage implies real CSS value). */
225 VarDefinition _findTerminalVarDefinition(
226 Map<String, VarDefinition> varDefs, VarDefinition varDef) {
227 var expressions = varDef.expression as Expressions;
228 for (var expr in expressions.expressions) {
229 if (expr is VarUsage) {
230 var usageName = (expr as VarUsage).name;
231 var foundDef = varDefs[usageName];
232
233 // If foundDef is unknown check if defaultValues; if it exist then resolve
234 // to terminal value.
235 if (foundDef == null) {
236 // We're either a VarUsage or terminal definition if in varDefs;
237 // either way replace VarUsage with it's default value because the
238 // VarDefinition isn't found.
239 var defaultValues = (expr as VarUsage).defaultValues;
240 var replaceExprs = expressions.expressions;
241 assert(replaceExprs.length == 1);
242 replaceExprs.replaceRange(0, 1, defaultValues);
243 return varDef;
244 }
245 if (foundDef is VarDefinition) {
246 return _findTerminalVarDefinition(varDefs, foundDef);
247 }
248 } else {
249 // Return real CSS property.
250 return varDef;
251 }
252 }
253
254 // Didn't point to a var definition that existed.
255 return varDef;
256 }
OLDNEW
« no previous file with comments | « csslib/lib/src/options.dart ('k') | csslib/lib/src/property.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698