OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | |
5 WebInspector.SASSSupport = {}; | 4 WebInspector.SASSSupport = {}; |
6 | 5 |
7 /** | 6 /** |
8 * @param {string} url | 7 * @param {string} url |
9 * @param {string} content | 8 * @param {string} content |
10 * @return {!Promise<!WebInspector.SASSSupport.AST>} | 9 * @return {!Promise<!WebInspector.SASSSupport.AST>} |
11 */ | 10 */ |
12 WebInspector.SASSSupport.parseSCSS = function(url, content) | 11 WebInspector.SASSSupport.parseSCSS = function(url, content) { |
13 { | 12 var text = new WebInspector.Text(content); |
14 var text = new WebInspector.Text(content); | 13 var document = new WebInspector.SASSSupport.ASTDocument(url, text); |
15 var document = new WebInspector.SASSSupport.ASTDocument(url, text); | 14 |
16 | 15 return WebInspector.formatterWorkerPool.runTask('parseSCSS', {content: content
}).then(onParsed); |
17 return WebInspector.formatterWorkerPool.runTask("parseSCSS", {content: conte
nt}).then(onParsed); | 16 |
18 | 17 /** |
19 /** | 18 * @param {?MessageEvent} event |
20 * @param {?MessageEvent} event | 19 * @return {!WebInspector.SASSSupport.AST} |
21 * @return {!WebInspector.SASSSupport.AST} | 20 */ |
22 */ | 21 function onParsed(event) { |
23 function onParsed(event) | 22 if (!event) |
24 { | 23 return new WebInspector.SASSSupport.AST(document, []); |
25 if (!event) | 24 var data = /** @type {!Array<!Object>} */ (event.data); |
26 return new WebInspector.SASSSupport.AST(document, []); | 25 var rules = []; |
27 var data = /** @type {!Array<!Object>} */(event.data); | 26 for (var i = 0; i < data.length; ++i) { |
28 var rules = []; | 27 var rulePayload = data[i]; |
29 for (var i = 0; i < data.length; ++i) { | 28 var selectors = rulePayload.selectors.map(createTextNode); |
30 var rulePayload = data[i]; | 29 var properties = rulePayload.properties.map(createProperty); |
31 var selectors = rulePayload.selectors.map(createTextNode); | 30 var range = WebInspector.TextRange.fromObject(rulePayload.styleRange); |
32 var properties = rulePayload.properties.map(createProperty); | 31 var rule = new WebInspector.SASSSupport.Rule(document, selectors, range, p
roperties); |
33 var range = WebInspector.TextRange.fromObject(rulePayload.styleRange
); | 32 rules.push(rule); |
34 var rule = new WebInspector.SASSSupport.Rule(document, selectors, ra
nge, properties); | 33 } |
35 rules.push(rule); | 34 return new WebInspector.SASSSupport.AST(document, rules); |
36 } | 35 } |
37 return new WebInspector.SASSSupport.AST(document, rules); | 36 |
38 } | 37 /** |
39 | 38 * @param {!Object} payload |
40 /** | 39 */ |
41 * @param {!Object} payload | 40 function createTextNode(payload) { |
42 */ | 41 var range = WebInspector.TextRange.fromObject(payload); |
43 function createTextNode(payload) | 42 var value = text.extract(range); |
44 { | 43 return new WebInspector.SASSSupport.TextNode(document, text.extract(range),
range); |
45 var range = WebInspector.TextRange.fromObject(payload); | 44 } |
46 var value = text.extract(range); | 45 |
47 return new WebInspector.SASSSupport.TextNode(document, text.extract(rang
e), range); | 46 /** |
48 } | 47 * @param {!Object} payload |
49 | 48 */ |
50 /** | 49 function createProperty(payload) { |
51 * @param {!Object} payload | 50 var name = createTextNode(payload.name); |
52 */ | 51 var value = createTextNode(payload.value); |
53 function createProperty(payload) | 52 return new WebInspector.SASSSupport.Property( |
54 { | 53 document, name, value, WebInspector.TextRange.fromObject(payload.range),
payload.disabled); |
55 var name = createTextNode(payload.name); | 54 } |
56 var value = createTextNode(payload.value); | 55 }; |
57 return new WebInspector.SASSSupport.Property(document, name, value, WebI
nspector.TextRange.fromObject(payload.range), payload.disabled); | 56 |
58 } | 57 /** |
59 }; | 58 * @unrestricted |
60 | 59 */ |
61 /** | 60 WebInspector.SASSSupport.ASTDocument = class { |
62 * @constructor | 61 /** |
63 * @param {string} url | 62 * @param {string} url |
64 * @param {!WebInspector.Text} text | 63 * @param {!WebInspector.Text} text |
65 */ | 64 */ |
66 WebInspector.SASSSupport.ASTDocument = function(url, text) | 65 constructor(url, text) { |
67 { | |
68 this.url = url; | 66 this.url = url; |
69 this.text = text; | 67 this.text = text; |
70 this.edits = []; | 68 this.edits = []; |
71 }; | 69 } |
72 | 70 |
73 WebInspector.SASSSupport.ASTDocument.prototype = { | 71 /** |
| 72 * @return {!WebInspector.SASSSupport.ASTDocument} |
| 73 */ |
| 74 clone() { |
| 75 return new WebInspector.SASSSupport.ASTDocument(this.url, this.text); |
| 76 } |
| 77 |
| 78 /** |
| 79 * @return {boolean} |
| 80 */ |
| 81 hasChanged() { |
| 82 return !!this.edits.length; |
| 83 } |
| 84 |
| 85 /** |
| 86 * @return {!WebInspector.Text} |
| 87 */ |
| 88 newText() { |
| 89 this.edits.stableSort(sequentialOrder); |
| 90 var text = this.text; |
| 91 for (var i = this.edits.length - 1; i >= 0; --i) { |
| 92 var range = this.edits[i].oldRange; |
| 93 var newText = this.edits[i].newText; |
| 94 text = new WebInspector.Text(text.replaceRange(range, newText)); |
| 95 } |
| 96 return text; |
| 97 |
74 /** | 98 /** |
75 * @return {!WebInspector.SASSSupport.ASTDocument} | 99 * @param {!WebInspector.SourceEdit} edit1 |
| 100 * @param {!WebInspector.SourceEdit} edit2 |
| 101 * @return {number} |
76 */ | 102 */ |
77 clone: function() | 103 function sequentialOrder(edit1, edit2) { |
78 { | 104 var range1 = edit1.oldRange.collapseToStart(); |
79 return new WebInspector.SASSSupport.ASTDocument(this.url, this.text); | 105 var range2 = edit2.oldRange.collapseToStart(); |
80 }, | 106 if (range1.equal(range2)) |
81 | 107 return 0; |
82 /** | 108 return range1.follows(range2) ? 1 : -1; |
83 * @return {boolean} | 109 } |
84 */ | 110 } |
85 hasChanged: function() | 111 }; |
86 { | 112 |
87 return !!this.edits.length; | 113 /** |
88 }, | 114 * @unrestricted |
89 | 115 */ |
90 /** | 116 WebInspector.SASSSupport.Node = class { |
91 * @return {!WebInspector.Text} | 117 /** |
92 */ | 118 * @param {!WebInspector.SASSSupport.ASTDocument} document |
93 newText: function() | 119 */ |
94 { | 120 constructor(document) { |
95 this.edits.stableSort(sequentialOrder); | |
96 var text = this.text; | |
97 for (var i = this.edits.length - 1; i >= 0; --i) { | |
98 var range = this.edits[i].oldRange; | |
99 var newText = this.edits[i].newText; | |
100 text = new WebInspector.Text(text.replaceRange(range, newText)); | |
101 } | |
102 return text; | |
103 | |
104 /** | |
105 * @param {!WebInspector.SourceEdit} edit1 | |
106 * @param {!WebInspector.SourceEdit} edit2 | |
107 * @return {number} | |
108 */ | |
109 function sequentialOrder(edit1, edit2) | |
110 { | |
111 var range1 = edit1.oldRange.collapseToStart(); | |
112 var range2 = edit2.oldRange.collapseToStart(); | |
113 if (range1.equal(range2)) | |
114 return 0; | |
115 return range1.follows(range2) ? 1 : -1; | |
116 } | |
117 }, | |
118 }; | |
119 | |
120 /** | |
121 * @constructor | |
122 * @param {!WebInspector.SASSSupport.ASTDocument} document | |
123 */ | |
124 WebInspector.SASSSupport.Node = function(document) | |
125 { | |
126 this.document = document; | 121 this.document = document; |
127 }; | 122 } |
128 | 123 }; |
129 /** | 124 |
130 * @constructor | 125 /** |
131 * @extends {WebInspector.SASSSupport.Node} | 126 * @unrestricted |
132 * @param {!WebInspector.SASSSupport.ASTDocument} document | 127 */ |
133 * @param {string} text | 128 WebInspector.SASSSupport.TextNode = class extends WebInspector.SASSSupport.Node
{ |
134 * @param {!WebInspector.TextRange} range | 129 /** |
135 */ | 130 * @param {!WebInspector.SASSSupport.ASTDocument} document |
136 WebInspector.SASSSupport.TextNode = function(document, text, range) | 131 * @param {string} text |
137 { | 132 * @param {!WebInspector.TextRange} range |
138 WebInspector.SASSSupport.Node.call(this, document); | 133 */ |
| 134 constructor(document, text, range) { |
| 135 super(document); |
139 this.text = text; | 136 this.text = text; |
140 this.range = range; | 137 this.range = range; |
141 }; | 138 } |
142 | 139 |
143 WebInspector.SASSSupport.TextNode.prototype = { | 140 /** |
144 /** | 141 * @param {string} newText |
145 * @param {string} newText | 142 */ |
146 */ | 143 setText(newText) { |
147 setText: function(newText) | 144 if (this.text === newText) |
148 { | 145 return; |
149 if (this.text === newText) | 146 this.text = newText; |
150 return; | 147 this.document.edits.push(new WebInspector.SourceEdit(this.document.url, this
.range, newText)); |
151 this.text = newText; | 148 } |
152 this.document.edits.push(new WebInspector.SourceEdit(this.document.url,
this.range, newText)); | 149 |
153 }, | 150 /** |
154 | 151 * @param {!WebInspector.SASSSupport.ASTDocument} document |
155 /** | 152 * @return {!WebInspector.SASSSupport.TextNode} |
156 * @param {!WebInspector.SASSSupport.ASTDocument} document | 153 */ |
157 * @return {!WebInspector.SASSSupport.TextNode} | 154 clone(document) { |
158 */ | 155 return new WebInspector.SASSSupport.TextNode(document, this.text, this.range
.clone()); |
159 clone: function(document) | 156 } |
160 { | 157 |
161 return new WebInspector.SASSSupport.TextNode(document, this.text, this.r
ange.clone()); | 158 /** |
162 }, | 159 * @param {!WebInspector.SASSSupport.TextNode} other |
163 | 160 * @param {!Map<!WebInspector.SASSSupport.Node, !WebInspector.SASSSupport.Node
>=} outNodeMapping |
164 /** | 161 * @return {boolean} |
165 * @param {!WebInspector.SASSSupport.TextNode} other | 162 */ |
166 * @param {!Map<!WebInspector.SASSSupport.Node, !WebInspector.SASSSupport.No
de>=} outNodeMapping | 163 match(other, outNodeMapping) { |
167 * @return {boolean} | 164 if (this.text.trim() !== other.text.trim()) |
168 */ | 165 return false; |
169 match: function(other, outNodeMapping) | 166 if (outNodeMapping) |
170 { | 167 outNodeMapping.set(this, other); |
171 if (this.text.trim() !== other.text.trim()) | 168 return true; |
172 return false; | 169 } |
173 if (outNodeMapping) | 170 }; |
174 outNodeMapping.set(this, other); | 171 |
175 return true; | 172 /** |
176 }, | 173 * @unrestricted |
177 | 174 */ |
178 __proto__: WebInspector.SASSSupport.Node.prototype | 175 WebInspector.SASSSupport.Property = class extends WebInspector.SASSSupport.Node
{ |
179 }; | 176 /** |
180 | 177 * @param {!WebInspector.SASSSupport.ASTDocument} document |
181 /** | 178 * @param {!WebInspector.SASSSupport.TextNode} name |
182 * @constructor | 179 * @param {!WebInspector.SASSSupport.TextNode} value |
183 * @extends {WebInspector.SASSSupport.Node} | 180 * @param {!WebInspector.TextRange} range |
184 * @param {!WebInspector.SASSSupport.ASTDocument} document | 181 * @param {boolean} disabled |
185 * @param {!WebInspector.SASSSupport.TextNode} name | 182 */ |
186 * @param {!WebInspector.SASSSupport.TextNode} value | 183 constructor(document, name, value, range, disabled) { |
187 * @param {!WebInspector.TextRange} range | 184 super(document); |
188 * @param {boolean} disabled | |
189 */ | |
190 WebInspector.SASSSupport.Property = function(document, name, value, range, disab
led) | |
191 { | |
192 WebInspector.SASSSupport.Node.call(this, document); | |
193 this.name = name; | 185 this.name = name; |
194 this.value = value; | 186 this.value = value; |
195 this.range = range; | 187 this.range = range; |
196 this.name.parent = this; | 188 this.name.parent = this; |
197 this.value.parent = this; | 189 this.value.parent = this; |
198 this.disabled = disabled; | 190 this.disabled = disabled; |
199 }; | 191 } |
200 | 192 |
201 WebInspector.SASSSupport.Property.prototype = { | 193 /** |
202 /** | 194 * @param {!WebInspector.SASSSupport.ASTDocument} document |
203 * @param {!WebInspector.SASSSupport.ASTDocument} document | 195 * @return {!WebInspector.SASSSupport.Property} |
204 * @return {!WebInspector.SASSSupport.Property} | 196 */ |
205 */ | 197 clone(document) { |
206 clone: function(document) | 198 return new WebInspector.SASSSupport.Property( |
207 { | 199 document, this.name.clone(document), this.value.clone(document), this.ra
nge.clone(), this.disabled); |
208 return new WebInspector.SASSSupport.Property(document, this.name.clone(d
ocument), this.value.clone(document), this.range.clone(), this.disabled); | 200 } |
209 }, | 201 |
210 | 202 /** |
211 /** | 203 * @param {function(!WebInspector.SASSSupport.Node)} callback |
212 * @param {function(!WebInspector.SASSSupport.Node)} callback | 204 */ |
213 */ | 205 visit(callback) { |
214 visit: function(callback) | 206 callback(this); |
215 { | 207 callback(this.name); |
216 callback(this); | 208 callback(this.value); |
217 callback(this.name); | 209 } |
218 callback(this.value); | 210 |
219 }, | 211 /** |
220 | 212 * @param {!WebInspector.SASSSupport.Property} other |
221 /** | 213 * @param {!Map<!WebInspector.SASSSupport.Node, !WebInspector.SASSSupport.Node
>=} outNodeMapping |
222 * @param {!WebInspector.SASSSupport.Property} other | 214 * @return {boolean} |
223 * @param {!Map<!WebInspector.SASSSupport.Node, !WebInspector.SASSSupport.No
de>=} outNodeMapping | 215 */ |
224 * @return {boolean} | 216 match(other, outNodeMapping) { |
225 */ | 217 if (this.disabled !== other.disabled) |
226 match: function(other, outNodeMapping) | 218 return false; |
227 { | 219 if (outNodeMapping) |
228 if (this.disabled !== other.disabled) | 220 outNodeMapping.set(this, other); |
229 return false; | 221 return this.name.match(other.name, outNodeMapping) && this.value.match(other
.value, outNodeMapping); |
230 if (outNodeMapping) | 222 } |
231 outNodeMapping.set(this, other); | 223 |
232 return this.name.match(other.name, outNodeMapping) && this.value.match(o
ther.value, outNodeMapping); | 224 /** |
233 }, | 225 * @param {boolean} disabled |
234 | 226 */ |
235 /** | 227 setDisabled(disabled) { |
236 * @param {boolean} disabled | 228 if (this.disabled === disabled) |
237 */ | 229 return; |
238 setDisabled: function(disabled) | 230 this.disabled = disabled; |
239 { | 231 if (disabled) { |
240 if (this.disabled === disabled) | 232 var oldRange1 = WebInspector.TextRange.createFromLocation(this.range.start
Line, this.range.startColumn); |
241 return; | 233 var edit1 = new WebInspector.SourceEdit(this.document.url, oldRange1, '/*
'); |
242 this.disabled = disabled; | 234 var oldRange2 = WebInspector.TextRange.createFromLocation(this.range.endLi
ne, this.range.endColumn); |
243 if (disabled) { | 235 var edit2 = new WebInspector.SourceEdit(this.document.url, oldRange2, ' */
'); |
244 var oldRange1 = WebInspector.TextRange.createFromLocation(this.range
.startLine, this.range.startColumn); | 236 this.document.edits.push(edit1, edit2); |
245 var edit1 = new WebInspector.SourceEdit(this.document.url, oldRange1
, "/* "); | 237 return; |
246 var oldRange2 = WebInspector.TextRange.createFromLocation(this.range
.endLine, this.range.endColumn); | 238 } |
247 var edit2 = new WebInspector.SourceEdit(this.document.url, oldRange2
, " */"); | 239 var oldRange1 = new WebInspector.TextRange( |
248 this.document.edits.push(edit1, edit2); | 240 this.range.startLine, this.range.startColumn, this.range.startLine, this
.name.range.startColumn); |
249 return; | 241 var edit1 = new WebInspector.SourceEdit(this.document.url, oldRange1, ''); |
250 } | 242 |
251 var oldRange1 = new WebInspector.TextRange(this.range.startLine, this.ra
nge.startColumn, this.range.startLine, this.name.range.startColumn); | 243 var propertyText = this.document.text.extract(this.range); |
252 var edit1 = new WebInspector.SourceEdit(this.document.url, oldRange1, ""
); | 244 var endsWithSemicolon = propertyText.slice(0, -2).trim().endsWith(';'); |
253 | 245 var oldRange2 = new WebInspector.TextRange( |
254 var propertyText = this.document.text.extract(this.range); | 246 this.range.endLine, this.value.range.endColumn + (endsWithSemicolon ? 1
: 0), this.range.endLine, |
255 var endsWithSemicolon = propertyText.slice(0, -2).trim().endsWith(";"); | 247 this.range.endColumn); |
256 var oldRange2 = new WebInspector.TextRange(this.range.endLine, this.valu
e.range.endColumn + (endsWithSemicolon ? 1 : 0), this.range.endLine, this.range.
endColumn); | 248 var edit2 = new WebInspector.SourceEdit(this.document.url, oldRange2, ''); |
257 var edit2 = new WebInspector.SourceEdit(this.document.url, oldRange2, ""
); | 249 this.document.edits.push(edit1, edit2); |
258 this.document.edits.push(edit1, edit2); | 250 } |
259 }, | 251 |
260 | 252 remove() { |
261 remove: function() | 253 console.assert(this.parent); |
262 { | 254 var rule = this.parent; |
263 console.assert(this.parent); | 255 var index = rule.properties.indexOf(this); |
264 var rule = this.parent; | 256 rule.properties.splice(index, 1); |
265 var index = rule.properties.indexOf(this); | 257 this.parent = null; |
266 rule.properties.splice(index, 1); | 258 |
267 this.parent = null; | 259 var lineRange = new WebInspector.TextRange(this.range.startLine, 0, this.ran
ge.endLine + 1, 0); |
268 | 260 var oldRange; |
269 var lineRange = new WebInspector.TextRange(this.range.startLine, 0, this
.range.endLine + 1, 0); | 261 if (this.document.text.extract(lineRange).trim() === this.document.text.extr
act(this.range).trim()) |
270 var oldRange; | 262 oldRange = lineRange; |
271 if (this.document.text.extract(lineRange).trim() === this.document.text.
extract(this.range).trim()) | 263 else |
272 oldRange = lineRange; | 264 oldRange = this.range; |
273 else | 265 this.document.edits.push(new WebInspector.SourceEdit(this.document.url, oldR
ange, '')); |
274 oldRange = this.range; | 266 } |
275 this.document.edits.push(new WebInspector.SourceEdit(this.document.url,
oldRange, "")); | 267 }; |
276 }, | 268 |
277 | 269 /** |
278 __proto__: WebInspector.SASSSupport.Node.prototype | 270 * @unrestricted |
279 }; | 271 */ |
280 | 272 WebInspector.SASSSupport.Rule = class extends WebInspector.SASSSupport.Node { |
281 /** | 273 /** |
282 * @constructor | 274 * @param {!WebInspector.SASSSupport.ASTDocument} document |
283 * @extends {WebInspector.SASSSupport.Node} | 275 * @param {!Array<!WebInspector.SASSSupport.TextNode>} selectors |
284 * @param {!WebInspector.SASSSupport.ASTDocument} document | 276 * @param {!WebInspector.TextRange} styleRange |
285 * @param {!Array<!WebInspector.SASSSupport.TextNode>} selectors | 277 * @param {!Array<!WebInspector.SASSSupport.Property>} properties |
286 * @param {!WebInspector.TextRange} styleRange | 278 */ |
287 * @param {!Array<!WebInspector.SASSSupport.Property>} properties | 279 constructor(document, selectors, styleRange, properties) { |
288 */ | 280 super(document); |
289 WebInspector.SASSSupport.Rule = function(document, selectors, styleRange, proper
ties) | |
290 { | |
291 WebInspector.SASSSupport.Node.call(this, document); | |
292 this.selectors = selectors; | 281 this.selectors = selectors; |
293 this.properties = properties; | 282 this.properties = properties; |
294 this.styleRange = styleRange; | 283 this.styleRange = styleRange; |
295 | 284 |
296 var blockStartRange = styleRange.collapseToStart(); | 285 var blockStartRange = styleRange.collapseToStart(); |
297 blockStartRange.startColumn -= 1; | 286 blockStartRange.startColumn -= 1; |
298 this.blockStart = new WebInspector.SASSSupport.TextNode(document, this.docum
ent.text.extract(blockStartRange), blockStartRange); | 287 this.blockStart = |
| 288 new WebInspector.SASSSupport.TextNode(document, this.document.text.extra
ct(blockStartRange), blockStartRange); |
299 this.blockStart.parent = this; | 289 this.blockStart.parent = this; |
300 | 290 |
301 for (var i = 0; i < this.properties.length; ++i) | 291 for (var i = 0; i < this.properties.length; ++i) |
302 this.properties[i].parent = this; | 292 this.properties[i].parent = this; |
303 | 293 |
304 this._hasTrailingSemicolon = !this.properties.length || this.document.text.e
xtract(this.properties.peekLast().range).endsWith(";"); | 294 this._hasTrailingSemicolon = |
305 }; | 295 !this.properties.length || this.document.text.extract(this.properties.pe
ekLast().range).endsWith(';'); |
306 | 296 } |
307 WebInspector.SASSSupport.Rule.prototype = { | 297 |
308 /** | 298 /** |
309 * @param {!WebInspector.SASSSupport.ASTDocument} document | 299 * @param {!WebInspector.SASSSupport.ASTDocument} document |
310 * @return {!WebInspector.SASSSupport.Rule} | 300 * @return {!WebInspector.SASSSupport.Rule} |
311 */ | 301 */ |
312 clone: function(document) | 302 clone(document) { |
313 { | 303 var properties = []; |
314 var properties = []; | 304 for (var i = 0; i < this.properties.length; ++i) |
315 for (var i = 0; i < this.properties.length; ++i) | 305 properties.push(this.properties[i].clone(document)); |
316 properties.push(this.properties[i].clone(document)); | 306 var selectors = []; |
317 var selectors = []; | 307 for (var i = 0; i < this.selectors.length; ++i) |
318 for (var i = 0; i < this.selectors.length; ++i) | 308 selectors.push(this.selectors[i].clone(document)); |
319 selectors.push(this.selectors[i].clone(document)); | 309 return new WebInspector.SASSSupport.Rule(document, selectors, this.styleRang
e.clone(), properties); |
320 return new WebInspector.SASSSupport.Rule(document, selectors, this.style
Range.clone(), properties); | 310 } |
321 }, | 311 |
322 | 312 /** |
323 /** | 313 * @param {function(!WebInspector.SASSSupport.Node)} callback |
324 * @param {function(!WebInspector.SASSSupport.Node)} callback | 314 */ |
325 */ | 315 visit(callback) { |
326 visit: function(callback) | 316 callback(this); |
327 { | 317 for (var i = 0; i < this.selectors.length; ++i) |
328 callback(this); | 318 callback(this.selectors[i]); |
329 for (var i = 0; i < this.selectors.length; ++i) | 319 callback(this.blockStart); |
330 callback(this.selectors[i]); | 320 for (var i = 0; i < this.properties.length; ++i) |
331 callback(this.blockStart); | 321 this.properties[i].visit(callback); |
332 for (var i = 0; i < this.properties.length; ++i) | 322 } |
333 this.properties[i].visit(callback); | 323 |
334 }, | 324 /** |
335 | 325 * @param {!WebInspector.SASSSupport.Rule} other |
336 /** | 326 * @param {!Map<!WebInspector.SASSSupport.Node, !WebInspector.SASSSupport.Node
>=} outNodeMapping |
337 * @param {!WebInspector.SASSSupport.Rule} other | 327 * @return {boolean} |
338 * @param {!Map<!WebInspector.SASSSupport.Node, !WebInspector.SASSSupport.No
de>=} outNodeMapping | 328 */ |
339 * @return {boolean} | 329 match(other, outNodeMapping) { |
340 */ | 330 if (this.selectors.length !== other.selectors.length) |
341 match: function(other, outNodeMapping) | 331 return false; |
342 { | 332 if (this.properties.length !== other.properties.length) |
343 if (this.selectors.length !== other.selectors.length) | 333 return false; |
344 return false; | 334 if (outNodeMapping) |
345 if (this.properties.length !== other.properties.length) | 335 outNodeMapping.set(this, other); |
346 return false; | 336 var result = this.blockStart.match(other.blockStart, outNodeMapping); |
347 if (outNodeMapping) | 337 for (var i = 0; result && i < this.selectors.length; ++i) |
348 outNodeMapping.set(this, other); | 338 result = result && this.selectors[i].match(other.selectors[i], outNodeMapp
ing); |
349 var result = this.blockStart.match(other.blockStart, outNodeMapping); | 339 for (var i = 0; result && i < this.properties.length; ++i) |
350 for (var i = 0; result && i < this.selectors.length; ++i) | 340 result = result && this.properties[i].match(other.properties[i], outNodeMa
pping); |
351 result = result && this.selectors[i].match(other.selectors[i], outNo
deMapping); | 341 return result; |
352 for (var i = 0; result && i < this.properties.length; ++i) | 342 } |
353 result = result && this.properties[i].match(other.properties[i], out
NodeMapping); | 343 |
354 return result; | 344 _addTrailingSemicolon() { |
355 }, | 345 if (this._hasTrailingSemicolon || !this.properties) |
356 | 346 return; |
357 _addTrailingSemicolon: function() | 347 this._hasTrailingSemicolon = true; |
358 { | 348 this.document.edits.push( |
359 if (this._hasTrailingSemicolon || !this.properties) | 349 new WebInspector.SourceEdit(this.document.url, this.properties.peekLast(
).range.collapseToEnd(), ';')); |
360 return; | 350 } |
361 this._hasTrailingSemicolon = true; | 351 |
362 this.document.edits.push(new WebInspector.SourceEdit(this.document.url,
this.properties.peekLast().range.collapseToEnd(), ";")); | 352 /** |
363 }, | 353 * @param {?WebInspector.SASSSupport.Property} anchorProperty |
364 | 354 * @param {!Array<string>} nameTexts |
365 /** | 355 * @param {!Array<string>} valueTexts |
366 * @param {?WebInspector.SASSSupport.Property} anchorProperty | 356 * @param {!Array<boolean>} disabledStates |
367 * @param {!Array<string>} nameTexts | 357 * @return {!Array<!WebInspector.SASSSupport.Property>} |
368 * @param {!Array<string>} valueTexts | 358 */ |
369 * @param {!Array<boolean>} disabledStates | 359 insertProperties(anchorProperty, nameTexts, valueTexts, disabledStates) { |
370 * @return {!Array<!WebInspector.SASSSupport.Property>} | 360 console.assert( |
371 */ | 361 nameTexts.length === valueTexts.length && valueTexts.length === disabled
States.length, |
372 insertProperties: function(anchorProperty, nameTexts, valueTexts, disabledSt
ates) | 362 'Input array should be of the same size.'); |
373 { | 363 |
374 console.assert(nameTexts.length === valueTexts.length && valueTexts.leng
th === disabledStates.length, "Input array should be of the same size."); | 364 this._addTrailingSemicolon(); |
375 | 365 var newProperties = []; |
376 this._addTrailingSemicolon(); | 366 var index = anchorProperty ? this.properties.indexOf(anchorProperty) : -1; |
377 var newProperties = []; | 367 for (var i = 0; i < nameTexts.length; ++i) { |
378 var index = anchorProperty ? this.properties.indexOf(anchorProperty) : -
1; | 368 var nameText = nameTexts[i]; |
379 for (var i = 0; i < nameTexts.length; ++i) { | 369 var valueText = valueTexts[i]; |
380 var nameText = nameTexts[i]; | 370 var disabled = disabledStates[i]; |
381 var valueText = valueTexts[i]; | 371 this.document.edits.push(this._insertPropertyEdit(anchorProperty, nameText
, valueText, disabled)); |
382 var disabled = disabledStates[i]; | 372 |
383 this.document.edits.push(this._insertPropertyEdit(anchorProperty, na
meText, valueText, disabled)); | 373 var name = new WebInspector.SASSSupport.TextNode( |
384 | 374 this.document, nameText, WebInspector.TextRange.createFromLocation(0,
0)); |
385 var name = new WebInspector.SASSSupport.TextNode(this.document, name
Text, WebInspector.TextRange.createFromLocation(0, 0)); | 375 var value = new WebInspector.SASSSupport.TextNode( |
386 var value = new WebInspector.SASSSupport.TextNode(this.document, val
ueText, WebInspector.TextRange.createFromLocation(0, 0)); | 376 this.document, valueText, WebInspector.TextRange.createFromLocation(0,
0)); |
387 var newProperty = new WebInspector.SASSSupport.Property(this.documen
t, name, value, WebInspector.TextRange.createFromLocation(0, 0), disabled); | 377 var newProperty = new WebInspector.SASSSupport.Property( |
388 | 378 this.document, name, value, WebInspector.TextRange.createFromLocation(
0, 0), disabled); |
389 this.properties.splice(index + i + 1, 0, newProperty); | 379 |
390 newProperty.parent = this; | 380 this.properties.splice(index + i + 1, 0, newProperty); |
391 newProperties.push(newProperty); | 381 newProperty.parent = this; |
392 } | 382 newProperties.push(newProperty); |
393 return newProperties; | 383 } |
394 }, | 384 return newProperties; |
395 | 385 } |
396 /** | 386 |
397 * @param {?WebInspector.SASSSupport.Property} anchorProperty | 387 /** |
398 * @param {string} nameText | 388 * @param {?WebInspector.SASSSupport.Property} anchorProperty |
399 * @param {string} valueText | 389 * @param {string} nameText |
400 * @param {boolean} disabled | 390 * @param {string} valueText |
401 * @return {!WebInspector.SourceEdit} | 391 * @param {boolean} disabled |
402 */ | 392 * @return {!WebInspector.SourceEdit} |
403 _insertPropertyEdit: function(anchorProperty, nameText, valueText, disabled) | 393 */ |
404 { | 394 _insertPropertyEdit(anchorProperty, nameText, valueText, disabled) { |
405 var anchorRange = anchorProperty ? anchorProperty.range : this.blockStar
t.range; | 395 var anchorRange = anchorProperty ? anchorProperty.range : this.blockStart.ra
nge; |
406 var indent = this._computePropertyIndent(); | 396 var indent = this._computePropertyIndent(); |
407 var leftComment = disabled ? "/* " : ""; | 397 var leftComment = disabled ? '/* ' : ''; |
408 var rightComment = disabled ? " */" : ""; | 398 var rightComment = disabled ? ' */' : ''; |
409 var newText = String.sprintf("\n%s%s%s: %s;%s", indent, leftComment, nam
eText, valueText, rightComment); | 399 var newText = String.sprintf('\n%s%s%s: %s;%s', indent, leftComment, nameTex
t, valueText, rightComment); |
410 return new WebInspector.SourceEdit(this.document.url, anchorRange.collap
seToEnd(), newText); | 400 return new WebInspector.SourceEdit(this.document.url, anchorRange.collapseTo
End(), newText); |
411 }, | 401 } |
412 | 402 |
413 /** | 403 /** |
414 * @return {string} | 404 * @return {string} |
415 */ | 405 */ |
416 _computePropertyIndent: function() | 406 _computePropertyIndent() { |
417 { | 407 var indentProperty = this.properties.find(property => !property.range.isEmpt
y()); |
418 var indentProperty = this.properties.find(property => !property.range.is
Empty()); | 408 var result = ''; |
419 var result = ""; | 409 if (indentProperty) { |
420 if (indentProperty) { | 410 result = this.document.text.extract(new WebInspector.TextRange( |
421 result = this.document.text.extract(new WebInspector.TextRange(inden
tProperty.range.startLine, 0, indentProperty.range.startLine, indentProperty.ran
ge.startColumn)); | 411 indentProperty.range.startLine, 0, indentProperty.range.startLine, ind
entProperty.range.startColumn)); |
422 } else { | 412 } else { |
423 var lineNumber = this.blockStart.range.startLine; | 413 var lineNumber = this.blockStart.range.startLine; |
424 var columnNumber = this.blockStart.range.startColumn; | 414 var columnNumber = this.blockStart.range.startColumn; |
425 var baseLine = this.document.text.extract(new WebInspector.TextRange
(lineNumber, 0, lineNumber, columnNumber)); | 415 var baseLine = this.document.text.extract(new WebInspector.TextRange(lineN
umber, 0, lineNumber, columnNumber)); |
426 result = WebInspector.TextUtils.lineIndent(baseLine) + WebInspector.
moduleSetting("textEditorIndent").get(); | 416 result = WebInspector.TextUtils.lineIndent(baseLine) + WebInspector.module
Setting('textEditorIndent').get(); |
427 } | 417 } |
428 return result.isWhitespace() ? result : ""; | 418 return result.isWhitespace() ? result : ''; |
429 }, | 419 } |
430 | 420 }; |
431 __proto__: WebInspector.SASSSupport.Node.prototype | 421 |
432 }; | 422 /** |
433 | 423 * @unrestricted |
434 /** | 424 */ |
435 * @constructor | 425 WebInspector.SASSSupport.AST = class extends WebInspector.SASSSupport.Node { |
436 * @extends {WebInspector.SASSSupport.Node} | 426 /** |
437 * @param {!WebInspector.SASSSupport.ASTDocument} document | 427 * @param {!WebInspector.SASSSupport.ASTDocument} document |
438 * @param {!Array<!WebInspector.SASSSupport.Rule>} rules | 428 * @param {!Array<!WebInspector.SASSSupport.Rule>} rules |
439 */ | 429 */ |
440 WebInspector.SASSSupport.AST = function(document, rules) | 430 constructor(document, rules) { |
441 { | 431 super(document); |
442 WebInspector.SASSSupport.Node.call(this, document); | |
443 this.rules = rules; | 432 this.rules = rules; |
444 for (var i = 0; i < rules.length; ++i) | 433 for (var i = 0; i < rules.length; ++i) |
445 rules[i].parent = this; | 434 rules[i].parent = this; |
446 }; | 435 } |
447 | 436 |
448 WebInspector.SASSSupport.AST.prototype = { | 437 /** |
| 438 * @return {!WebInspector.SASSSupport.AST} |
| 439 */ |
| 440 clone() { |
| 441 var document = this.document.clone(); |
| 442 var rules = []; |
| 443 for (var i = 0; i < this.rules.length; ++i) |
| 444 rules.push(this.rules[i].clone(document)); |
| 445 return new WebInspector.SASSSupport.AST(document, rules); |
| 446 } |
| 447 |
| 448 /** |
| 449 * @param {!WebInspector.SASSSupport.AST} other |
| 450 * @param {!Map<!WebInspector.SASSSupport.Node, !WebInspector.SASSSupport.Node
>=} outNodeMapping |
| 451 * @return {boolean} |
| 452 */ |
| 453 match(other, outNodeMapping) { |
| 454 if (other.document.url !== this.document.url) |
| 455 return false; |
| 456 if (other.rules.length !== this.rules.length) |
| 457 return false; |
| 458 if (outNodeMapping) |
| 459 outNodeMapping.set(this, other); |
| 460 var result = true; |
| 461 for (var i = 0; result && i < this.rules.length; ++i) |
| 462 result = result && this.rules[i].match(other.rules[i], outNodeMapping); |
| 463 return result; |
| 464 } |
| 465 |
| 466 /** |
| 467 * @param {function(!WebInspector.SASSSupport.Node)} callback |
| 468 */ |
| 469 visit(callback) { |
| 470 callback(this); |
| 471 for (var i = 0; i < this.rules.length; ++i) |
| 472 this.rules[i].visit(callback); |
| 473 } |
| 474 |
| 475 /** |
| 476 * @param {number} lineNumber |
| 477 * @param {number} columnNumber |
| 478 * @return {?WebInspector.SASSSupport.TextNode} |
| 479 */ |
| 480 findNodeForPosition(lineNumber, columnNumber) { |
| 481 this._ensureNodePositionsIndex(); |
| 482 var index = this._sortedTextNodes.lowerBound({lineNumber: lineNumber, column
Number: columnNumber}, nodeComparator); |
| 483 var node = this._sortedTextNodes[index]; |
| 484 if (!node) |
| 485 return null; |
| 486 return node.range.containsLocation(lineNumber, columnNumber) ? node : null; |
| 487 |
449 /** | 488 /** |
450 * @return {!WebInspector.SASSSupport.AST} | 489 * @param {!{lineNumber: number, columnNumber: number}} position |
| 490 * @param {!WebInspector.SASSSupport.TextNode} textNode |
| 491 * @return {number} |
451 */ | 492 */ |
452 clone: function() | 493 function nodeComparator(position, textNode) { |
453 { | 494 return textNode.range.compareToPosition(position.lineNumber, position.colu
mnNumber); |
454 var document = this.document.clone(); | 495 } |
455 var rules = []; | 496 } |
456 for (var i = 0; i < this.rules.length; ++i) | 497 |
457 rules.push(this.rules[i].clone(document)); | 498 _ensureNodePositionsIndex() { |
458 return new WebInspector.SASSSupport.AST(document, rules); | 499 if (this._sortedTextNodes) |
459 }, | 500 return; |
| 501 this._sortedTextNodes = []; |
| 502 this.visit(onNode.bind(this)); |
| 503 this._sortedTextNodes.sort(nodeComparator); |
460 | 504 |
461 /** | 505 /** |
462 * @param {!WebInspector.SASSSupport.AST} other | 506 * @param {!WebInspector.SASSSupport.Node} node |
463 * @param {!Map<!WebInspector.SASSSupport.Node, !WebInspector.SASSSupport.No
de>=} outNodeMapping | 507 * @this {WebInspector.SASSSupport.AST} |
464 * @return {boolean} | |
465 */ | 508 */ |
466 match: function(other, outNodeMapping) | 509 function onNode(node) { |
467 { | 510 if (!(node instanceof WebInspector.SASSSupport.TextNode)) |
468 if (other.document.url !== this.document.url) | 511 return; |
469 return false; | 512 this._sortedTextNodes.push(node); |
470 if (other.rules.length !== this.rules.length) | 513 } |
471 return false; | |
472 if (outNodeMapping) | |
473 outNodeMapping.set(this, other); | |
474 var result = true; | |
475 for (var i = 0; result && i < this.rules.length; ++i) | |
476 result = result && this.rules[i].match(other.rules[i], outNodeMappin
g); | |
477 return result; | |
478 }, | |
479 | 514 |
480 /** | 515 /** |
481 * @param {function(!WebInspector.SASSSupport.Node)} callback | 516 * @param {!WebInspector.SASSSupport.TextNode} text1 |
| 517 * @param {!WebInspector.SASSSupport.TextNode} text2 |
| 518 * @return {number} |
482 */ | 519 */ |
483 visit: function(callback) | 520 function nodeComparator(text1, text2) { |
484 { | 521 return WebInspector.TextRange.comparator(text1.range, text2.range); |
485 callback(this); | 522 } |
486 for (var i = 0; i < this.rules.length; ++i) | 523 } |
487 this.rules[i].visit(callback); | |
488 }, | |
489 | |
490 /** | |
491 * @param {number} lineNumber | |
492 * @param {number} columnNumber | |
493 * @return {?WebInspector.SASSSupport.TextNode} | |
494 */ | |
495 findNodeForPosition: function(lineNumber, columnNumber) | |
496 { | |
497 this._ensureNodePositionsIndex(); | |
498 var index = this._sortedTextNodes.lowerBound({lineNumber: lineNumber, co
lumnNumber: columnNumber}, nodeComparator); | |
499 var node = this._sortedTextNodes[index]; | |
500 if (!node) | |
501 return null; | |
502 return node.range.containsLocation(lineNumber, columnNumber) ? node : nu
ll; | |
503 | |
504 /** | |
505 * @param {!{lineNumber: number, columnNumber: number}} position | |
506 * @param {!WebInspector.SASSSupport.TextNode} textNode | |
507 * @return {number} | |
508 */ | |
509 function nodeComparator(position, textNode) | |
510 { | |
511 return textNode.range.compareToPosition(position.lineNumber, positio
n.columnNumber); | |
512 } | |
513 }, | |
514 | |
515 _ensureNodePositionsIndex: function() | |
516 { | |
517 if (this._sortedTextNodes) | |
518 return; | |
519 this._sortedTextNodes = []; | |
520 this.visit(onNode.bind(this)); | |
521 this._sortedTextNodes.sort(nodeComparator); | |
522 | |
523 /** | |
524 * @param {!WebInspector.SASSSupport.Node} node | |
525 * @this {WebInspector.SASSSupport.AST} | |
526 */ | |
527 function onNode(node) | |
528 { | |
529 if (!(node instanceof WebInspector.SASSSupport.TextNode)) | |
530 return; | |
531 this._sortedTextNodes.push(node); | |
532 } | |
533 | |
534 /** | |
535 * @param {!WebInspector.SASSSupport.TextNode} text1 | |
536 * @param {!WebInspector.SASSSupport.TextNode} text2 | |
537 * @return {number} | |
538 */ | |
539 function nodeComparator(text1, text2) | |
540 { | |
541 return WebInspector.TextRange.comparator(text1.range, text2.range); | |
542 } | |
543 }, | |
544 | |
545 __proto__: WebInspector.SASSSupport.Node.prototype | |
546 }; | 524 }; |
547 | 525 |
548 /** @enum {string} */ | 526 /** @enum {string} */ |
549 WebInspector.SASSSupport.PropertyChangeType = { | 527 WebInspector.SASSSupport.PropertyChangeType = { |
550 PropertyAdded: "PropertyAdded", | 528 PropertyAdded: 'PropertyAdded', |
551 PropertyRemoved: "PropertyRemoved", | 529 PropertyRemoved: 'PropertyRemoved', |
552 PropertyToggled: "PropertyToggled", | 530 PropertyToggled: 'PropertyToggled', |
553 ValueChanged: "ValueChanged", | 531 ValueChanged: 'ValueChanged', |
554 NameChanged: "NameChanged" | 532 NameChanged: 'NameChanged' |
555 }; | 533 }; |
556 | 534 |
557 /** | 535 /** |
558 * @constructor | 536 * @unrestricted |
559 * @param {!WebInspector.SASSSupport.PropertyChangeType} type | 537 */ |
560 * @param {!WebInspector.SASSSupport.Rule} oldRule | 538 WebInspector.SASSSupport.PropertyChange = class { |
561 * @param {!WebInspector.SASSSupport.Rule} newRule | 539 /** |
562 * @param {number} oldPropertyIndex | 540 * @param {!WebInspector.SASSSupport.PropertyChangeType} type |
563 * @param {number} newPropertyIndex | 541 * @param {!WebInspector.SASSSupport.Rule} oldRule |
564 */ | 542 * @param {!WebInspector.SASSSupport.Rule} newRule |
565 WebInspector.SASSSupport.PropertyChange = function(type, oldRule, newRule, oldPr
opertyIndex, newPropertyIndex) | 543 * @param {number} oldPropertyIndex |
566 { | 544 * @param {number} newPropertyIndex |
| 545 */ |
| 546 constructor(type, oldRule, newRule, oldPropertyIndex, newPropertyIndex) { |
567 this.type = type; | 547 this.type = type; |
568 this.oldRule = oldRule; | 548 this.oldRule = oldRule; |
569 this.newRule = newRule; | 549 this.newRule = newRule; |
570 this.oldPropertyIndex = oldPropertyIndex; | 550 this.oldPropertyIndex = oldPropertyIndex; |
571 this.newPropertyIndex = newPropertyIndex; | 551 this.newPropertyIndex = newPropertyIndex; |
572 }; | 552 } |
573 | 553 |
574 WebInspector.SASSSupport.PropertyChange.prototype = { | 554 /** |
575 /** | 555 * @return {?WebInspector.SASSSupport.Property} |
576 * @return {?WebInspector.SASSSupport.Property} | 556 */ |
577 */ | 557 oldProperty() { |
578 oldProperty: function() | 558 return this.oldRule.properties[this.oldPropertyIndex] || null; |
579 { | 559 } |
580 return this.oldRule.properties[this.oldPropertyIndex] || null; | 560 |
581 }, | 561 /** |
582 | 562 * @return {?WebInspector.SASSSupport.Property} |
583 /** | 563 */ |
584 * @return {?WebInspector.SASSSupport.Property} | 564 newProperty() { |
585 */ | 565 return this.newRule.properties[this.newPropertyIndex] || null; |
586 newProperty: function() | 566 } |
587 { | 567 }; |
588 return this.newRule.properties[this.newPropertyIndex] || null; | 568 |
589 } | 569 /** |
590 }; | 570 * @unrestricted |
591 | 571 */ |
592 /** | 572 WebInspector.SASSSupport.ASTDiff = class { |
593 * @constructor | 573 /** |
594 * @param {string} url | 574 * @param {string} url |
595 * @param {!WebInspector.SASSSupport.AST} oldAST | 575 * @param {!WebInspector.SASSSupport.AST} oldAST |
596 * @param {!WebInspector.SASSSupport.AST} newAST | 576 * @param {!WebInspector.SASSSupport.AST} newAST |
597 * @param {!Map<!WebInspector.SASSSupport.TextNode, !WebInspector.SASSSupport.Te
xtNode>} mapping | 577 * @param {!Map<!WebInspector.SASSSupport.TextNode, !WebInspector.SASSSupport.
TextNode>} mapping |
598 * @param {!Array<!WebInspector.SASSSupport.PropertyChange>} changes | 578 * @param {!Array<!WebInspector.SASSSupport.PropertyChange>} changes |
599 */ | 579 */ |
600 WebInspector.SASSSupport.ASTDiff = function(url, oldAST, newAST, mapping, change
s) | 580 constructor(url, oldAST, newAST, mapping, changes) { |
601 { | |
602 this.url = url; | 581 this.url = url; |
603 this.mapping = mapping; | 582 this.mapping = mapping; |
604 this.changes = changes; | 583 this.changes = changes; |
605 this.oldAST = oldAST; | 584 this.oldAST = oldAST; |
606 this.newAST = newAST; | 585 this.newAST = newAST; |
607 }; | 586 } |
608 | 587 }; |
609 /** | 588 |
| 589 /** |
610 * @param {!WebInspector.SASSSupport.AST} oldAST | 590 * @param {!WebInspector.SASSSupport.AST} oldAST |
611 * @param {!WebInspector.SASSSupport.AST} newAST | 591 * @param {!WebInspector.SASSSupport.AST} newAST |
612 * @return {!WebInspector.SASSSupport.ASTDiff} | 592 * @return {!WebInspector.SASSSupport.ASTDiff} |
613 */ | 593 */ |
614 WebInspector.SASSSupport.diffModels = function(oldAST, newAST) | 594 WebInspector.SASSSupport.diffModels = function(oldAST, newAST) { |
615 { | 595 console.assert(oldAST.rules.length === newAST.rules.length, 'Not implemented f
or rule diff.'); |
616 console.assert(oldAST.rules.length === newAST.rules.length, "Not implemented
for rule diff."); | 596 console.assert(oldAST.document.url === newAST.document.url, 'Diff makes sense
for models with the same url.'); |
617 console.assert(oldAST.document.url === newAST.document.url, "Diff makes sens
e for models with the same url."); | 597 var T = WebInspector.SASSSupport.PropertyChangeType; |
618 var T = WebInspector.SASSSupport.PropertyChangeType; | 598 var changes = []; |
619 var changes = []; | 599 /** @type {!Map<!WebInspector.SASSSupport.TextNode, !WebInspector.SASSSupport.
TextNode>} */ |
620 /** @type {!Map<!WebInspector.SASSSupport.TextNode, !WebInspector.SASSSuppor
t.TextNode>} */ | 600 var mapping = new Map(); |
621 var mapping = new Map(); | 601 for (var i = 0; i < oldAST.rules.length; ++i) { |
622 for (var i = 0; i < oldAST.rules.length; ++i) { | 602 var oldRule = oldAST.rules[i]; |
623 var oldRule = oldAST.rules[i]; | 603 var newRule = newAST.rules[i]; |
624 var newRule = newAST.rules[i]; | 604 computeRuleDiff(mapping, oldRule, newRule); |
625 computeRuleDiff(mapping, oldRule, newRule); | 605 } |
| 606 return new WebInspector.SASSSupport.ASTDiff(oldAST.document.url, oldAST, newAS
T, mapping, changes); |
| 607 |
| 608 /** |
| 609 * @param {!WebInspector.SASSSupport.PropertyChangeType} type |
| 610 * @param {!WebInspector.SASSSupport.Rule} oldRule |
| 611 * @param {!WebInspector.SASSSupport.Rule} newRule |
| 612 * @param {number} oldPropertyIndex |
| 613 * @param {number} newPropertyIndex |
| 614 */ |
| 615 function addChange(type, oldRule, newRule, oldPropertyIndex, newPropertyIndex)
{ |
| 616 changes.push( |
| 617 new WebInspector.SASSSupport.PropertyChange(type, oldRule, newRule, oldP
ropertyIndex, newPropertyIndex)); |
| 618 } |
| 619 |
| 620 /** |
| 621 * @param {!Map<!WebInspector.SASSSupport.TextNode, !WebInspector.SASSSupport.
TextNode>} mapping |
| 622 * @param {!WebInspector.SASSSupport.Rule} oldRule |
| 623 * @param {!WebInspector.SASSSupport.Rule} newRule |
| 624 */ |
| 625 function computeRuleDiff(mapping, oldRule, newRule) { |
| 626 var oldLines = []; |
| 627 for (var i = 0; i < oldRule.properties.length; ++i) |
| 628 oldLines.push(oldRule.properties[i].name.text.trim() + ':' + oldRule.prope
rties[i].value.text.trim()); |
| 629 var newLines = []; |
| 630 for (var i = 0; i < newRule.properties.length; ++i) |
| 631 newLines.push(newRule.properties[i].name.text.trim() + ':' + newRule.prope
rties[i].value.text.trim()); |
| 632 var diff = WebInspector.Diff.lineDiff(oldLines, newLines); |
| 633 diff = WebInspector.Diff.convertToEditDiff(diff); |
| 634 |
| 635 var p1 = 0, p2 = 0; |
| 636 for (var i = 0; i < diff.length; ++i) { |
| 637 var token = diff[i]; |
| 638 if (token[0] === WebInspector.Diff.Operation.Delete) { |
| 639 for (var j = 0; j < token[1]; ++j) |
| 640 addChange(T.PropertyRemoved, oldRule, newRule, p1++, p2); |
| 641 } else if (token[0] === WebInspector.Diff.Operation.Insert) { |
| 642 for (var j = 0; j < token[1]; ++j) |
| 643 addChange(T.PropertyAdded, oldRule, newRule, p1, p2++); |
| 644 } else { |
| 645 for (var j = 0; j < token[1]; ++j) |
| 646 computePropertyDiff(mapping, oldRule, newRule, p1++, p2++); |
| 647 } |
626 } | 648 } |
627 return new WebInspector.SASSSupport.ASTDiff(oldAST.document.url, oldAST, new
AST, mapping, changes); | 649 } |
628 | 650 |
629 /** | 651 /** |
630 * @param {!WebInspector.SASSSupport.PropertyChangeType} type | 652 * @param {!Map<!WebInspector.SASSSupport.TextNode, !WebInspector.SASSSupport.
TextNode>} mapping |
631 * @param {!WebInspector.SASSSupport.Rule} oldRule | 653 * @param {!WebInspector.SASSSupport.Rule} oldRule |
632 * @param {!WebInspector.SASSSupport.Rule} newRule | 654 * @param {!WebInspector.SASSSupport.Rule} newRule |
633 * @param {number} oldPropertyIndex | 655 * @param {number} oldPropertyIndex |
634 * @param {number} newPropertyIndex | 656 * @param {number} newPropertyIndex |
635 */ | 657 */ |
636 function addChange(type, oldRule, newRule, oldPropertyIndex, newPropertyInde
x) | 658 function computePropertyDiff(mapping, oldRule, newRule, oldPropertyIndex, newP
ropertyIndex) { |
637 { | 659 var oldProperty = oldRule.properties[oldPropertyIndex]; |
638 changes.push(new WebInspector.SASSSupport.PropertyChange(type, oldRule,
newRule, oldPropertyIndex, newPropertyIndex)); | 660 var newProperty = newRule.properties[newPropertyIndex]; |
639 } | 661 mapping.set(oldProperty.name, newProperty.name); |
640 | 662 mapping.set(oldProperty.value, newProperty.value); |
641 /** | 663 if (oldProperty.name.text.trim() !== newProperty.name.text.trim()) |
642 * @param {!Map<!WebInspector.SASSSupport.TextNode, !WebInspector.SASSSuppor
t.TextNode>} mapping | 664 addChange(T.NameChanged, oldRule, newRule, oldPropertyIndex, newPropertyIn
dex); |
643 * @param {!WebInspector.SASSSupport.Rule} oldRule | 665 if (oldProperty.value.text.trim() !== newProperty.value.text.trim()) |
644 * @param {!WebInspector.SASSSupport.Rule} newRule | 666 addChange(T.ValueChanged, oldRule, newRule, oldPropertyIndex, newPropertyI
ndex); |
645 */ | 667 if (oldProperty.disabled !== newProperty.disabled) |
646 function computeRuleDiff(mapping, oldRule, newRule) | 668 addChange(T.PropertyToggled, oldRule, newRule, oldPropertyIndex, newProper
tyIndex); |
647 { | 669 } |
648 var oldLines = []; | |
649 for (var i = 0; i < oldRule.properties.length; ++i) | |
650 oldLines.push(oldRule.properties[i].name.text.trim() + ":" + oldRule
.properties[i].value.text.trim()); | |
651 var newLines = []; | |
652 for (var i = 0; i < newRule.properties.length; ++i) | |
653 newLines.push(newRule.properties[i].name.text.trim() + ":" + newRule
.properties[i].value.text.trim()); | |
654 var diff = WebInspector.Diff.lineDiff(oldLines, newLines); | |
655 diff = WebInspector.Diff.convertToEditDiff(diff); | |
656 | |
657 var p1 = 0, p2 = 0; | |
658 for (var i = 0; i < diff.length; ++i) { | |
659 var token = diff[i]; | |
660 if (token[0] === WebInspector.Diff.Operation.Delete) { | |
661 for (var j = 0; j < token[1]; ++j) | |
662 addChange(T.PropertyRemoved, oldRule, newRule, p1++, p2); | |
663 } else if (token[0] === WebInspector.Diff.Operation.Insert) { | |
664 for (var j = 0; j < token[1]; ++j) | |
665 addChange(T.PropertyAdded, oldRule, newRule, p1, p2++); | |
666 } else { | |
667 for (var j = 0; j < token[1]; ++j) | |
668 computePropertyDiff(mapping, oldRule, newRule, p1++, p2++); | |
669 } | |
670 } | |
671 } | |
672 | |
673 /** | |
674 * @param {!Map<!WebInspector.SASSSupport.TextNode, !WebInspector.SASSSuppor
t.TextNode>} mapping | |
675 * @param {!WebInspector.SASSSupport.Rule} oldRule | |
676 * @param {!WebInspector.SASSSupport.Rule} newRule | |
677 * @param {number} oldPropertyIndex | |
678 * @param {number} newPropertyIndex | |
679 */ | |
680 function computePropertyDiff(mapping, oldRule, newRule, oldPropertyIndex, ne
wPropertyIndex) | |
681 { | |
682 var oldProperty = oldRule.properties[oldPropertyIndex]; | |
683 var newProperty = newRule.properties[newPropertyIndex]; | |
684 mapping.set(oldProperty.name, newProperty.name); | |
685 mapping.set(oldProperty.value, newProperty.value); | |
686 if (oldProperty.name.text.trim() !== newProperty.name.text.trim()) | |
687 addChange(T.NameChanged, oldRule, newRule, oldPropertyIndex, newProp
ertyIndex); | |
688 if (oldProperty.value.text.trim() !== newProperty.value.text.trim()) | |
689 addChange(T.ValueChanged, oldRule, newRule, oldPropertyIndex, newPro
pertyIndex); | |
690 if (oldProperty.disabled !== newProperty.disabled) | |
691 addChange(T.PropertyToggled, oldRule, newRule, oldPropertyIndex, new
PropertyIndex); | |
692 } | |
693 }; | 670 }; |
OLD | NEW |