OLD | NEW |
---|---|
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library services.src.refactoring.extract_local; | 5 library services.src.refactoring.extract_local; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 | 8 |
9 import 'package:analysis_server/src/protocol.dart' hide Element; | 9 import 'package:analysis_server/src/protocol.dart' hide Element; |
10 import 'package:analysis_server/src/services/correction/name_suggestion.dart'; | 10 import 'package:analysis_server/src/services/correction/name_suggestion.dart'; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
122 String declarationSource = '$keyword $name = '; | 122 String declarationSource = '$keyword $name = '; |
123 SourceEdit edit = | 123 SourceEdit edit = |
124 new SourceEdit(singleExpression.offset, 0, declarationSource); | 124 new SourceEdit(singleExpression.offset, 0, declarationSource); |
125 change.addEdit(file, edit); | 125 change.addEdit(file, edit); |
126 return new Future.value(change); | 126 return new Future.value(change); |
127 } | 127 } |
128 // add variable declaration | 128 // add variable declaration |
129 { | 129 { |
130 String declarationSource; | 130 String declarationSource; |
131 if (stringLiteralPart != null) { | 131 if (stringLiteralPart != null) { |
132 declarationSource = "var ${name} = '${stringLiteralPart}';"; | 132 declarationSource = "var $name = '$stringLiteralPart';"; |
133 } else { | 133 } else { |
134 String keyword = _declarationKeyword; | 134 String keyword = _declarationKeyword; |
135 String initializerSource = utils.getRangeText(selectionRange); | 135 String initializerSource = utils.getRangeText(selectionRange); |
136 declarationSource = "${keyword} ${name} = ${initializerSource};"; | 136 declarationSource = "$keyword $name = $initializerSource;"; |
137 } | 137 } |
138 String eol = utils.endOfLine; | |
138 // prepare location for declaration | 139 // prepare location for declaration |
139 Statement targetStatement = _findTargetStatement(occurrences); | 140 Statement targetStatement; |
Paul Berry
2014/09/15 14:45:23
This code is confusing because of the implicit con
scheglov
2014/09/15 15:28:12
Done.
| |
140 String prefix = utils.getNodePrefix(targetStatement); | 141 ExpressionFunctionBody targetBody; |
142 { | |
143 List<AstNode> nodes = _findNodes(occurrences); | |
144 AstNode commonParent = getNearestCommonAncestor(nodes); | |
145 if (commonParent is Block) { | |
146 List<AstNode> firstParents = getParents(nodes[0]); | |
147 int commonIndex = firstParents.indexOf(commonParent); | |
148 targetStatement = firstParents[commonIndex + 1]; | |
149 } else { | |
150 targetBody = _getEnclosingExpressionBody(commonParent); | |
151 if (targetBody == null) { | |
152 targetStatement = | |
153 commonParent.getAncestor((node) => node is Statement); | |
154 } | |
155 } | |
156 } | |
141 // insert variable declaration | 157 // insert variable declaration |
142 String eol = utils.endOfLine; | 158 if (targetStatement != null) { |
143 SourceEdit edit = new SourceEdit( | 159 String prefix = utils.getNodePrefix(targetStatement); |
144 targetStatement.offset, | 160 SourceEdit edit = |
145 0, | 161 new SourceEdit(targetStatement.offset, 0, declarationSource + eol + prefix); |
146 '${declarationSource}${eol}${prefix}'); | 162 change.addEdit(file, edit); |
147 change.addEdit(file, edit); | 163 } |
164 if (targetBody != null) { | |
165 String prefix = utils.getNodePrefix(targetBody.parent); | |
166 String indent = utils.getIndent(1); | |
167 String declStatement = prefix + indent + declarationSource + eol; | |
168 String exprStatement = prefix + indent + 'return '; | |
169 Expression expr = targetBody.expression; | |
170 change.addEdit( | |
171 file, | |
172 new SourceEdit( | |
173 targetBody.offset, | |
174 expr.offset - targetBody.offset, | |
175 '{' + eol + declStatement + exprStatement)); | |
176 change.addEdit( | |
177 file, | |
178 new SourceEdit(expr.end, 0, ';' + eol + prefix + '}')); | |
179 } | |
148 } | 180 } |
149 // prepare replacement | 181 // prepare replacement |
150 String occurrenceReplacement = name; | 182 String occurrenceReplacement = name; |
151 if (stringLiteralPart != null) { | 183 if (stringLiteralPart != null) { |
152 occurrenceReplacement = "\${$name}"; | 184 occurrenceReplacement = "\${$name}"; |
153 } | 185 } |
154 // replace occurrences with variable reference | 186 // replace occurrences with variable reference |
155 for (SourceRange range in occurrences) { | 187 for (SourceRange range in occurrences) { |
156 SourceEdit edit = new SourceEdit.range(range, occurrenceReplacement); | 188 SourceEdit edit = new SourceEdit.range(range, occurrenceReplacement); |
157 change.addEdit(file, edit); | 189 change.addEdit(file, edit); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
234 List<AstNode> _findNodes(List<SourceRange> ranges) { | 266 List<AstNode> _findNodes(List<SourceRange> ranges) { |
235 List<AstNode> nodes = <AstNode>[]; | 267 List<AstNode> nodes = <AstNode>[]; |
236 for (SourceRange range in ranges) { | 268 for (SourceRange range in ranges) { |
237 AstNode node = new NodeLocator.con1(range.offset).searchWithin(unit); | 269 AstNode node = new NodeLocator.con1(range.offset).searchWithin(unit); |
238 nodes.add(node); | 270 nodes.add(node); |
239 } | 271 } |
240 return nodes; | 272 return nodes; |
241 } | 273 } |
242 | 274 |
243 /** | 275 /** |
244 * Returns the [Statement] such that variable declaration added before it is | 276 * Returns the [ExpressionFunctionBody] that encloses [node], or `null` |
245 * visible at all given occurrences. | 277 * if [node] is not enclosed with an [ExpressionFunctionBody]. |
246 */ | 278 */ |
247 Statement _findTargetStatement(List<SourceRange> occurrences) { | 279 ExpressionFunctionBody _getEnclosingExpressionBody(AstNode node) { |
248 List<AstNode> nodes = _findNodes(occurrences); | 280 while (node != null) { |
249 List<AstNode> firstParents = getParents(nodes[0]); | 281 if (node is Statement) { |
250 AstNode commonParent = getNearestCommonAncestor(nodes); | 282 return null; |
251 if (commonParent is Block) { | 283 } |
252 int commonIndex = firstParents.indexOf(commonParent); | 284 if (node is ExpressionFunctionBody) { |
253 return firstParents[commonIndex + 1] as Statement; | 285 return node; |
254 } else { | 286 } |
255 return commonParent.getAncestor((node) => node is Statement); | 287 node = node.parent; |
256 } | 288 } |
289 return null; | |
257 } | 290 } |
258 | 291 |
259 /** | 292 /** |
260 * Checks if it is OK to extract the node with the given [SourceRange]. | 293 * Checks if it is OK to extract the node with the given [SourceRange]. |
261 */ | 294 */ |
262 bool _isExtractable(SourceRange range) { | 295 bool _isExtractable(SourceRange range) { |
263 _ExtractExpressionAnalyzer analyzer = new _ExtractExpressionAnalyzer(range); | 296 _ExtractExpressionAnalyzer analyzer = new _ExtractExpressionAnalyzer(range); |
264 utils.unit.accept(analyzer); | 297 utils.unit.accept(analyzer); |
265 return analyzer.status.isOK; | 298 return analyzer.status.isOK; |
266 } | 299 } |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
528 Token startToken = nodeTokens[startTokenIndex]; | 561 Token startToken = nodeTokens[startTokenIndex]; |
529 Token endToken = nodeTokens[endTokenIndex]; | 562 Token endToken = nodeTokens[endTokenIndex]; |
530 // add occurrence range | 563 // add occurrence range |
531 int occuStart = nodeOffset + startToken.offset; | 564 int occuStart = nodeOffset + startToken.offset; |
532 int occuEnd = nodeOffset + endToken.end; | 565 int occuEnd = nodeOffset + endToken.end; |
533 SourceRange occuRange = rangeStartEnd(occuStart, occuEnd); | 566 SourceRange occuRange = rangeStartEnd(occuStart, occuEnd); |
534 _addOccurrence(occuRange); | 567 _addOccurrence(occuRange); |
535 } | 568 } |
536 } | 569 } |
537 } | 570 } |
OLD | NEW |