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

Side by Side Diff: observatory_pub_packages/csslib/src/polyfill.dart

Issue 816693004: Add observatory_pub_packages snapshot to third_party (Closed) Base URL: http://dart.googlecode.com/svn/third_party/
Patch Set: Created 6 years 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
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 =
51 (new _VarDefAndUsage(this._messages, _allVarDefinitions)
52 ..visitTree(styleSheet)).varDefs;
53
54 // Resolve all definitions to a non-VarUsage (terminal expression).
55 mainStyleSheetVarDefs.forEach((key, value) {
56 for (Expression expr in (value.expression as Expressions).expressions) {
57 mainStyleSheetVarDefs[key] =
58 _findTerminalVarDefinition(_allVarDefinitions, value);
59 }
60 });
61 }
62 }
63
64 /** Build list of all var definitions in all includes. */
65 class _VarDefinitionsIncludes extends Visitor {
66 final Map<String, VarDefinition> varDefs;
67
68 _VarDefinitionsIncludes(this.varDefs);
69
70 void visitTree(StyleSheet tree) {
71 visitStyleSheet(tree);
72 }
73
74 visitVarDefinition(VarDefinition node) {
75 // Replace with latest variable definition.
76 varDefs[node.definedName] = node;
77 super.visitVarDefinition(node);
78 }
79
80 void visitVarDefinitionDirective(VarDefinitionDirective node) {
81 visitVarDefinition(node.def);
82 }
83 }
84
85 /**
86 * Find var- definitions in a style sheet.
87 * [found] list of known definitions.
88 */
89 class _VarDefAndUsage extends Visitor {
90 final Messages _messages;
91 final Map<String, VarDefinition> _knownVarDefs;
92 final Map<String, VarDefinition> varDefs = new Map<String, VarDefinition>();
93
94 VarDefinition currVarDefinition;
95 List<Expression> currentExpressions;
96
97 _VarDefAndUsage(this._messages, this._knownVarDefs);
98
99 void visitTree(StyleSheet tree) {
100 visitStyleSheet(tree);
101 }
102
103 visitVarDefinition(VarDefinition node) {
104 // Replace with latest variable definition.
105 currVarDefinition = node;
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);
117 }
118
119 void visitExpressions(Expressions node) {
120 currentExpressions = node.expressions;
121 super.visitExpressions(node);
122 currentExpressions = null;
123 }
124
125 void visitVarUsage(VarUsage node) {
126 if (currVarDefinition != null && currVarDefinition.badUsage) return;
127
128 // Don't process other var() inside of a varUsage. That implies that the
129 // default is a var() too. Also, don't process any var() inside of a
130 // varDefinition (they're just place holders until we've resolved all real
131 // usages.
132 var expressions = currentExpressions;
133 var index = expressions.indexOf(node);
134 assert(index >= 0);
135 var def = _knownVarDefs[node.name];
136 if (def != null) {
137 if (def.badUsage) {
138 // Remove any expressions pointing to a bad var definition.
139 expressions.removeAt(index);
140 return;
141 }
142 _resolveVarUsage(currentExpressions, index,
143 _findTerminalVarDefinition(_knownVarDefs, def));
144 } else if (node.defaultValues.any((e) => e is VarUsage)) {
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);
161 }
162 }
163 // Remove var usage that points at an undefined definition.
164 expressions.removeAt(index);
165 _messages.warning("Variable is not defined.", node.span);
166 }
167
168 var oldExpressions = currentExpressions;
169 currentExpressions = node.defaultValues;
170 super.visitVarUsage(node);
171 currentExpressions = oldExpressions;
172 }
173
174 List<Expression> resolveUsageTerminal(VarUsage usage) {
175 var result = [];
176
177 var varDef = _knownVarDefs[usage.name];
178 var expressions;
179 if (varDef == null) {
180 // VarDefinition not found try the defaultValues.
181 expressions = usage.defaultValues;
182 } else {
183 // Use the VarDefinition found.
184 expressions = (varDef.expression as Expressions).expressions;
185 }
186
187 for (var expr in expressions) {
188 if (expr is VarUsage) {
189 // Get terminal value.
190 result.addAll(resolveUsageTerminal(expr));
191 }
192 }
193
194 // We're at a terminal just return the VarDefinition expression.
195 if (result.isEmpty && varDef != null) {
196 result = (varDef.expression as Expressions).expressions;
197 }
198
199 return result;
200 }
201
202 _resolveVarUsage(List<Expressions> expressions, int index,
203 VarDefinition def) {
204 var defExpressions = (def.expression as Expressions).expressions;
205 expressions.replaceRange(index, index + 1, defExpressions);
206 }
207 }
208
209 /** Remove all var definitions. */
210 class _RemoveVarDefinitions extends Visitor {
211 void visitTree(StyleSheet tree) {
212 visitStyleSheet(tree);
213 }
214
215 void visitStyleSheet(StyleSheet ss) {
216 ss.topLevels.removeWhere((e) => e is VarDefinitionDirective);
217 super.visitStyleSheet(ss);
218 }
219
220 void visitDeclarationGroup(DeclarationGroup node) {
221 node.declarations.removeWhere((e) => e is VarDefinition);
222 super.visitDeclarationGroup(node);
223 }
224 }
225
226 /** Find terminal definition (non VarUsage implies real CSS value). */
227 VarDefinition _findTerminalVarDefinition(Map<String, VarDefinition> varDefs,
228 VarDefinition varDef) {
229 var expressions = varDef.expression as Expressions;
230 for (var expr in expressions.expressions) {
231 if (expr is VarUsage) {
232 var usageName = (expr as VarUsage).name;
233 var foundDef = varDefs[usageName];
234
235 // If foundDef is unknown check if defaultValues; if it exist then resolve
236 // to terminal value.
237 if (foundDef == null) {
238 // We're either a VarUsage or terminal definition if in varDefs;
239 // either way replace VarUsage with it's default value because the
240 // VarDefinition isn't found.
241 var defaultValues = (expr as VarUsage).defaultValues;
242 var replaceExprs = expressions.expressions;
243 assert(replaceExprs.length == 1);
244 replaceExprs.replaceRange(0, 1, defaultValues);
245 return varDef;
246 }
247 if (foundDef is VarDefinition) {
248 return _findTerminalVarDefinition(varDefs, foundDef);
249 }
250 } else {
251 // Return real CSS property.
252 return varDef;
253 }
254 }
255
256 // Didn't point to a var definition that existed.
257 return varDef;
258 }
OLDNEW
« no previous file with comments | « observatory_pub_packages/csslib/src/options.dart ('k') | observatory_pub_packages/csslib/src/property.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698