Chromium Code Reviews| 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 |