| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 | 4 |
| 5 /** | 5 /** |
| 6 * @constructor | 6 * @constructor |
| 7 * @implements {WebInspector.FormatterWorkerContentParser} | 7 * @implements {FormatterWorker.FormatterWorkerContentParser} |
| 8 */ | 8 */ |
| 9 WebInspector.SCSSParser = function() | 9 Gonzales.SCSSParser = function() |
| 10 { | 10 { |
| 11 } | 11 } |
| 12 | 12 |
| 13 WebInspector.SCSSParser.prototype = { | 13 Gonzales.SCSSParser.prototype = { |
| 14 /** | 14 /** |
| 15 * @override | 15 * @override |
| 16 * @param {string} content | 16 * @param {string} content |
| 17 * @return {!Array<!WebInspector.SCSSParser.Rule>} | 17 * @return {!Array<!Gonzales.SCSSParser.Rule>} |
| 18 */ | 18 */ |
| 19 parse: function(content) | 19 parse: function(content) |
| 20 { | 20 { |
| 21 var ast = null; | 21 var ast = null; |
| 22 try { | 22 try { |
| 23 ast = gonzales.parse(content, {syntax: "scss"}); | 23 ast = gonzales.parse(content, {syntax: "scss"}); |
| 24 } catch (e) { | 24 } catch (e) { |
| 25 return []; | 25 return []; |
| 26 } | 26 } |
| 27 | 27 |
| 28 /** @type {!{properties: !Array<!Gonzales.Node>, node: !Gonzales.Node}}
*/ | 28 /** @type {!{properties: !Array<!Gonzales.Node>, node: !Gonzales.Node}}
*/ |
| 29 var rootBlock = { | 29 var rootBlock = { |
| 30 properties: [], | 30 properties: [], |
| 31 node: ast | 31 node: ast |
| 32 }; | 32 }; |
| 33 /** @type {!Array<!{properties: !Array<!Gonzales.Node>, node: !Gonzales.
Node}>} */ | 33 /** @type {!Array<!{properties: !Array<!Gonzales.Node>, node: !Gonzales.
Node}>} */ |
| 34 var blocks = [rootBlock]; | 34 var blocks = [rootBlock]; |
| 35 ast.selectors = []; | 35 ast.selectors = []; |
| 36 WebInspector.SCSSParser.extractNodes(ast, blocks, rootBlock); | 36 Gonzales.SCSSParser.extractNodes(ast, blocks, rootBlock); |
| 37 | 37 |
| 38 var rules = []; | 38 var rules = []; |
| 39 for (var block of blocks) | 39 for (var block of blocks) |
| 40 this._handleBlock(block, rules); | 40 this._handleBlock(block, rules); |
| 41 return rules; | 41 return rules; |
| 42 }, | 42 }, |
| 43 | 43 |
| 44 /** | 44 /** |
| 45 * @param {!{node: !Gonzales.Node, properties: !Array<!Gonzales.Node>}} bloc
k | 45 * @param {!{node: !Gonzales.Node, properties: !Array<!Gonzales.Node>}} bloc
k |
| 46 * @param {!Array<!WebInspector.SCSSParser.Rule>} output | 46 * @param {!Array<!Gonzales.SCSSParser.Rule>} output |
| 47 */ | 47 */ |
| 48 _handleBlock: function(block, output) | 48 _handleBlock: function(block, output) |
| 49 { | 49 { |
| 50 var selectors = block.node.selectors.map(WebInspector.SCSSParser.rangeFr
omNode); | 50 var selectors = block.node.selectors.map(Gonzales.SCSSParser.rangeFromNo
de); |
| 51 var properties = []; | 51 var properties = []; |
| 52 var styleRange = WebInspector.SCSSParser.rangeFromNode(block.node); | 52 var styleRange = Gonzales.SCSSParser.rangeFromNode(block.node); |
| 53 styleRange.startColumn += 1; | 53 styleRange.startColumn += 1; |
| 54 styleRange.endColumn -= 1; | 54 styleRange.endColumn -= 1; |
| 55 for (var node of block.properties) { | 55 for (var node of block.properties) { |
| 56 if (node.type === "declaration") | 56 if (node.type === "declaration") |
| 57 this._handleDeclaration(node, properties); | 57 this._handleDeclaration(node, properties); |
| 58 else if (node.type === "include") | 58 else if (node.type === "include") |
| 59 this._handleInclude(node, properties); | 59 this._handleInclude(node, properties); |
| 60 else if (node.type === "multilineComment" && node.start.line === nod
e.end.line) | 60 else if (node.type === "multilineComment" && node.start.line === nod
e.end.line) |
| 61 this._handleComment(node, properties); | 61 this._handleComment(node, properties); |
| 62 } | 62 } |
| 63 if (!selectors.length && !properties.length) | 63 if (!selectors.length && !properties.length) |
| 64 return; | 64 return; |
| 65 var rule = new WebInspector.SCSSParser.Rule(selectors, properties, style
Range); | 65 var rule = new Gonzales.SCSSParser.Rule(selectors, properties, styleRang
e); |
| 66 output.push(rule); | 66 output.push(rule); |
| 67 }, | 67 }, |
| 68 | 68 |
| 69 /** | 69 /** |
| 70 * @param {!Gonzales.Node} node | 70 * @param {!Gonzales.Node} node |
| 71 * @param {!Array<!WebInspector.SCSSParser.Property>} output | 71 * @param {!Array<!Gonzales.SCSSParser.Property>} output |
| 72 */ | 72 */ |
| 73 _handleDeclaration: function(node, output) | 73 _handleDeclaration: function(node, output) |
| 74 { | 74 { |
| 75 var propertyNode = node.content.find(node => node.type === "property"); | 75 var propertyNode = node.content.find(node => node.type === "property"); |
| 76 var valueNode = node.content.find(node => node.type === "value"); | 76 var valueNode = node.content.find(node => node.type === "value"); |
| 77 if (!propertyNode || !valueNode) | 77 if (!propertyNode || !valueNode) |
| 78 return; | 78 return; |
| 79 | 79 |
| 80 var nameRange = WebInspector.SCSSParser.rangeFromNode(propertyNode); | 80 var nameRange = Gonzales.SCSSParser.rangeFromNode(propertyNode); |
| 81 var valueRange = WebInspector.SCSSParser.rangeFromNode(valueNode); | 81 var valueRange = Gonzales.SCSSParser.rangeFromNode(valueNode); |
| 82 var range = /** @type {!WebInspector.TextRange} */(node.declarationRange
); | 82 var range = /** @type {!Common.TextRange} */(node.declarationRange); |
| 83 | 83 |
| 84 var property = new WebInspector.SCSSParser.Property(range, nameRange, va
lueRange, false); | 84 var property = new Gonzales.SCSSParser.Property(range, nameRange, valueR
ange, false); |
| 85 output.push(property); | 85 output.push(property); |
| 86 }, | 86 }, |
| 87 | 87 |
| 88 /** | 88 /** |
| 89 * @param {!Gonzales.Node} node | 89 * @param {!Gonzales.Node} node |
| 90 * @param {!Array<!WebInspector.SCSSParser.Property>} output | 90 * @param {!Array<!Gonzales.SCSSParser.Property>} output |
| 91 */ | 91 */ |
| 92 _handleInclude: function(node, output) | 92 _handleInclude: function(node, output) |
| 93 { | 93 { |
| 94 var mixinName = node.content.find(node => node.type === "ident"); | 94 var mixinName = node.content.find(node => node.type === "ident"); |
| 95 if (!mixinName) | 95 if (!mixinName) |
| 96 return; | 96 return; |
| 97 var nameRange = WebInspector.SCSSParser.rangeFromNode(mixinName); | 97 var nameRange = Gonzales.SCSSParser.rangeFromNode(mixinName); |
| 98 var mixinArguments = node.content.find(node => node.type === "arguments"
); | 98 var mixinArguments = node.content.find(node => node.type === "arguments"
); |
| 99 if (!mixinArguments) | 99 if (!mixinArguments) |
| 100 return; | 100 return; |
| 101 var parameters = mixinArguments.content.filter(node => node.type !== "de
limiter" && node.type !== "space"); | 101 var parameters = mixinArguments.content.filter(node => node.type !== "de
limiter" && node.type !== "space"); |
| 102 for (var parameter of parameters) { | 102 for (var parameter of parameters) { |
| 103 var range = WebInspector.SCSSParser.rangeFromNode(node); | 103 var range = Gonzales.SCSSParser.rangeFromNode(node); |
| 104 var valueRange = WebInspector.SCSSParser.rangeFromNode(parameter); | 104 var valueRange = Gonzales.SCSSParser.rangeFromNode(parameter); |
| 105 var property = new WebInspector.SCSSParser.Property(range, nameRange
, valueRange, false); | 105 var property = new Gonzales.SCSSParser.Property(range, nameRange, va
lueRange, false); |
| 106 output.push(property); | 106 output.push(property); |
| 107 } | 107 } |
| 108 }, | 108 }, |
| 109 | 109 |
| 110 /** | 110 /** |
| 111 * @param {!Gonzales.Node} node | 111 * @param {!Gonzales.Node} node |
| 112 * @param {!Array<!WebInspector.SCSSParser.Property>} output | 112 * @param {!Array<!Gonzales.SCSSParser.Property>} output |
| 113 */ | 113 */ |
| 114 _handleComment: function(node, output) | 114 _handleComment: function(node, output) |
| 115 { | 115 { |
| 116 if (node.start.line !== node.end.line) | 116 if (node.start.line !== node.end.line) |
| 117 return; | 117 return; |
| 118 var innerText = /** @type {string} */(node.content); | 118 var innerText = /** @type {string} */(node.content); |
| 119 var innerResult = this.parse(innerText); | 119 var innerResult = this.parse(innerText); |
| 120 if (innerResult.length !== 1 || innerResult[0].properties.length !== 1) | 120 if (innerResult.length !== 1 || innerResult[0].properties.length !== 1) |
| 121 return; | 121 return; |
| 122 var property = innerResult[0].properties[0]; | 122 var property = innerResult[0].properties[0]; |
| 123 var disabledProperty = property.rebaseInsideOneLineComment(node); | 123 var disabledProperty = property.rebaseInsideOneLineComment(node); |
| 124 output.push(disabledProperty); | 124 output.push(disabledProperty); |
| 125 }, | 125 }, |
| 126 } | 126 } |
| 127 | 127 |
| 128 /** | 128 /** |
| 129 * @param {!Gonzales.Node} node | 129 * @param {!Gonzales.Node} node |
| 130 * @return {!WebInspector.TextRange} | 130 * @return {!Common.TextRange} |
| 131 */ | 131 */ |
| 132 WebInspector.SCSSParser.rangeFromNode = function(node) | 132 Gonzales.SCSSParser.rangeFromNode = function(node) |
| 133 { | 133 { |
| 134 return new WebInspector.TextRange(node.start.line - 1, node.start.column - 1
, node.end.line - 1, node.end.column); | 134 return new Common.TextRange(node.start.line - 1, node.start.column - 1, node
.end.line - 1, node.end.column); |
| 135 } | 135 } |
| 136 | 136 |
| 137 /** | 137 /** |
| 138 * @constructor | 138 * @constructor |
| 139 * @param {!WebInspector.TextRange} range | 139 * @param {!Common.TextRange} range |
| 140 * @param {!WebInspector.TextRange} nameRange | 140 * @param {!Common.TextRange} nameRange |
| 141 * @param {!WebInspector.TextRange} valueRange | 141 * @param {!Common.TextRange} valueRange |
| 142 * @param {boolean} disabled | 142 * @param {boolean} disabled |
| 143 */ | 143 */ |
| 144 WebInspector.SCSSParser.Property = function(range, nameRange, valueRange, disabl
ed) | 144 Gonzales.SCSSParser.Property = function(range, nameRange, valueRange, disabled) |
| 145 { | 145 { |
| 146 this.range = range; | 146 this.range = range; |
| 147 this.name = nameRange; | 147 this.name = nameRange; |
| 148 this.value = valueRange; | 148 this.value = valueRange; |
| 149 this.disabled = disabled; | 149 this.disabled = disabled; |
| 150 } | 150 } |
| 151 | 151 |
| 152 WebInspector.SCSSParser.Property.prototype = { | 152 Gonzales.SCSSParser.Property.prototype = { |
| 153 /** | 153 /** |
| 154 * @param {!Gonzales.Node} commentNode | 154 * @param {!Gonzales.Node} commentNode |
| 155 * @return {!WebInspector.SCSSParser.Property} | 155 * @return {!Gonzales.SCSSParser.Property} |
| 156 */ | 156 */ |
| 157 rebaseInsideOneLineComment: function(commentNode) | 157 rebaseInsideOneLineComment: function(commentNode) |
| 158 { | 158 { |
| 159 var lineOffset = commentNode.start.line - 1; | 159 var lineOffset = commentNode.start.line - 1; |
| 160 // Account for the "/*". | 160 // Account for the "/*". |
| 161 var columnOffset = commentNode.start.column - 1 + 2; | 161 var columnOffset = commentNode.start.column - 1 + 2; |
| 162 var range = WebInspector.SCSSParser.rangeFromNode(commentNode); | 162 var range = Gonzales.SCSSParser.rangeFromNode(commentNode); |
| 163 var name = rebaseRange(this.name, lineOffset, columnOffset); | 163 var name = rebaseRange(this.name, lineOffset, columnOffset); |
| 164 var value = rebaseRange(this.value, lineOffset, columnOffset); | 164 var value = rebaseRange(this.value, lineOffset, columnOffset); |
| 165 return new WebInspector.SCSSParser.Property(range, name, value, true); | 165 return new Gonzales.SCSSParser.Property(range, name, value, true); |
| 166 | 166 |
| 167 /** | 167 /** |
| 168 * @param {!WebInspector.TextRange} range | 168 * @param {!Common.TextRange} range |
| 169 * @param {number} lineOffset | 169 * @param {number} lineOffset |
| 170 * @param {number} columnOffset | 170 * @param {number} columnOffset |
| 171 * @return {!WebInspector.TextRange} | 171 * @return {!Common.TextRange} |
| 172 */ | 172 */ |
| 173 function rebaseRange(range, lineOffset, columnOffset) | 173 function rebaseRange(range, lineOffset, columnOffset) |
| 174 { | 174 { |
| 175 return new WebInspector.TextRange(range.startLine + lineOffset, rang
e.startColumn + columnOffset, range.endLine + lineOffset, range.endColumn + colu
mnOffset); | 175 return new Common.TextRange(range.startLine + lineOffset, range.star
tColumn + columnOffset, range.endLine + lineOffset, range.endColumn + columnOffs
et); |
| 176 } | 176 } |
| 177 } | 177 } |
| 178 } | 178 } |
| 179 | 179 |
| 180 /** | 180 /** |
| 181 * @constructor | 181 * @constructor |
| 182 * @param {!Array<!WebInspector.TextRange>} selectors | 182 * @param {!Array<!Common.TextRange>} selectors |
| 183 * @param {!Array<!WebInspector.SCSSParser.Property>} properties | 183 * @param {!Array<!Gonzales.SCSSParser.Property>} properties |
| 184 * @param {!WebInspector.TextRange} styleRange | 184 * @param {!Common.TextRange} styleRange |
| 185 */ | 185 */ |
| 186 WebInspector.SCSSParser.Rule = function(selectors, properties, styleRange) | 186 Gonzales.SCSSParser.Rule = function(selectors, properties, styleRange) |
| 187 { | 187 { |
| 188 this.selectors = selectors; | 188 this.selectors = selectors; |
| 189 this.properties = properties; | 189 this.properties = properties; |
| 190 this.styleRange = styleRange; | 190 this.styleRange = styleRange; |
| 191 } | 191 } |
| 192 | 192 |
| 193 /** | 193 /** |
| 194 * @param {!Gonzales.Node} node | 194 * @param {!Gonzales.Node} node |
| 195 * @param {!Array<{node: !Gonzales.Node, properties: !Array<!Gonzales.Node>}>} b
locks | 195 * @param {!Array<{node: !Gonzales.Node, properties: !Array<!Gonzales.Node>}>} b
locks |
| 196 * @param {!{node: !Gonzales.Node, properties: !Array<!Gonzales.Node>}} lastBloc
k | 196 * @param {!{node: !Gonzales.Node, properties: !Array<!Gonzales.Node>}} lastBloc
k |
| 197 */ | 197 */ |
| 198 WebInspector.SCSSParser.extractNodes = function(node, blocks, lastBlock) | 198 Gonzales.SCSSParser.extractNodes = function(node, blocks, lastBlock) |
| 199 { | 199 { |
| 200 if (!Array.isArray(node.content)) | 200 if (!Array.isArray(node.content)) |
| 201 return; | 201 return; |
| 202 if (node.type === "block") { | 202 if (node.type === "block") { |
| 203 lastBlock = { | 203 lastBlock = { |
| 204 node: node, | 204 node: node, |
| 205 properties: [] | 205 properties: [] |
| 206 }; | 206 }; |
| 207 blocks.push(lastBlock); | 207 blocks.push(lastBlock); |
| 208 } | 208 } |
| 209 var lastDeclaration = null; | 209 var lastDeclaration = null; |
| 210 var selectors = []; | 210 var selectors = []; |
| 211 for (var i = 0; i < node.content.length; ++i) { | 211 for (var i = 0; i < node.content.length; ++i) { |
| 212 var child = node.content[i]; | 212 var child = node.content[i]; |
| 213 if (child.type === "declarationDelimiter" && lastDeclaration) { | 213 if (child.type === "declarationDelimiter" && lastDeclaration) { |
| 214 lastDeclaration.declarationRange.endLine = child.end.line - 1; | 214 lastDeclaration.declarationRange.endLine = child.end.line - 1; |
| 215 lastDeclaration.declarationRange.endColumn = child.end.column; | 215 lastDeclaration.declarationRange.endColumn = child.end.column; |
| 216 lastDeclaration = null; | 216 lastDeclaration = null; |
| 217 } else if (child.type === "selector") { | 217 } else if (child.type === "selector") { |
| 218 selectors.push(child); | 218 selectors.push(child); |
| 219 } else if (child.type === "block") { | 219 } else if (child.type === "block") { |
| 220 child.selectors = selectors; | 220 child.selectors = selectors; |
| 221 selectors = []; | 221 selectors = []; |
| 222 } | 222 } |
| 223 if (child.type === "include" || child.type === "declaration" || child.ty
pe === "multilineComment") | 223 if (child.type === "include" || child.type === "declaration" || child.ty
pe === "multilineComment") |
| 224 lastBlock.properties.push(child); | 224 lastBlock.properties.push(child); |
| 225 if (child.type === "declaration") { | 225 if (child.type === "declaration") { |
| 226 lastDeclaration = child; | 226 lastDeclaration = child; |
| 227 lastDeclaration.declarationRange = WebInspector.TextRange.createFrom
Location(child.start.line - 1, child.start.column - 1); | 227 lastDeclaration.declarationRange = Common.TextRange.createFromLocati
on(child.start.line - 1, child.start.column - 1); |
| 228 } | 228 } |
| 229 WebInspector.SCSSParser.extractNodes(child, blocks, lastBlock); | 229 Gonzales.SCSSParser.extractNodes(child, blocks, lastBlock); |
| 230 } | 230 } |
| 231 if (lastDeclaration) { | 231 if (lastDeclaration) { |
| 232 lastDeclaration.declarationRange.endLine = node.end.line - 1; | 232 lastDeclaration.declarationRange.endLine = node.end.line - 1; |
| 233 lastDeclaration.declarationRange.endColumn = node.end.column - 1; | 233 lastDeclaration.declarationRange.endColumn = node.end.column - 1; |
| 234 } | 234 } |
| 235 } | 235 } |
| OLD | NEW |