| 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 AstNode target_; |
| 140 String prefix = utils.getNodePrefix(targetStatement); | 141 { |
| 142 List<AstNode> nodes = _findNodes(occurrences); |
| 143 AstNode commonParent = getNearestCommonAncestor(nodes); |
| 144 if (commonParent is Block) { |
| 145 List<AstNode> firstParents = getParents(nodes[0]); |
| 146 int commonIndex = firstParents.indexOf(commonParent); |
| 147 target_ = firstParents[commonIndex + 1]; |
| 148 } else { |
| 149 target_ = _getEnclosingExpressionBody(commonParent); |
| 150 if (target_ == null) { |
| 151 target_ = commonParent.getAncestor((node) => node is Statement); |
| 152 } |
| 153 } |
| 154 } |
| 155 AstNode target = target_; |
| 141 // insert variable declaration | 156 // insert variable declaration |
| 142 String eol = utils.endOfLine; | 157 if (target is Statement) { |
| 143 SourceEdit edit = new SourceEdit( | 158 String prefix = utils.getNodePrefix(target); |
| 144 targetStatement.offset, | 159 SourceEdit edit = |
| 145 0, | 160 new SourceEdit(target.offset, 0, declarationSource + eol + prefix); |
| 146 '${declarationSource}${eol}${prefix}'); | 161 change.addEdit(file, edit); |
| 147 change.addEdit(file, edit); | 162 } else if (target is ExpressionFunctionBody) { |
| 163 String prefix = utils.getNodePrefix(target.parent); |
| 164 String indent = utils.getIndent(1); |
| 165 String declStatement = prefix + indent + declarationSource + eol; |
| 166 String exprStatement = prefix + indent + 'return '; |
| 167 Expression expr = target.expression; |
| 168 change.addEdit( |
| 169 file, |
| 170 new SourceEdit( |
| 171 target.offset, |
| 172 expr.offset - target.offset, |
| 173 '{' + eol + declStatement + exprStatement)); |
| 174 change.addEdit( |
| 175 file, |
| 176 new SourceEdit(expr.end, 0, ';' + eol + prefix + '}')); |
| 177 } |
| 148 } | 178 } |
| 149 // prepare replacement | 179 // prepare replacement |
| 150 String occurrenceReplacement = name; | 180 String occurrenceReplacement = name; |
| 151 if (stringLiteralPart != null) { | 181 if (stringLiteralPart != null) { |
| 152 occurrenceReplacement = "\${$name}"; | 182 occurrenceReplacement = "\${$name}"; |
| 153 } | 183 } |
| 154 // replace occurrences with variable reference | 184 // replace occurrences with variable reference |
| 155 for (SourceRange range in occurrences) { | 185 for (SourceRange range in occurrences) { |
| 156 SourceEdit edit = new SourceEdit.range(range, occurrenceReplacement); | 186 SourceEdit edit = new SourceEdit.range(range, occurrenceReplacement); |
| 157 change.addEdit(file, edit); | 187 change.addEdit(file, edit); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 List<AstNode> _findNodes(List<SourceRange> ranges) { | 264 List<AstNode> _findNodes(List<SourceRange> ranges) { |
| 235 List<AstNode> nodes = <AstNode>[]; | 265 List<AstNode> nodes = <AstNode>[]; |
| 236 for (SourceRange range in ranges) { | 266 for (SourceRange range in ranges) { |
| 237 AstNode node = new NodeLocator.con1(range.offset).searchWithin(unit); | 267 AstNode node = new NodeLocator.con1(range.offset).searchWithin(unit); |
| 238 nodes.add(node); | 268 nodes.add(node); |
| 239 } | 269 } |
| 240 return nodes; | 270 return nodes; |
| 241 } | 271 } |
| 242 | 272 |
| 243 /** | 273 /** |
| 244 * Returns the [Statement] such that variable declaration added before it is | 274 * Returns the [ExpressionFunctionBody] that encloses [node], or `null` |
| 245 * visible at all given occurrences. | 275 * if [node] is not enclosed with an [ExpressionFunctionBody]. |
| 246 */ | 276 */ |
| 247 Statement _findTargetStatement(List<SourceRange> occurrences) { | 277 ExpressionFunctionBody _getEnclosingExpressionBody(AstNode node) { |
| 248 List<AstNode> nodes = _findNodes(occurrences); | 278 while (node != null) { |
| 249 List<AstNode> firstParents = getParents(nodes[0]); | 279 if (node is Statement) { |
| 250 AstNode commonParent = getNearestCommonAncestor(nodes); | 280 return null; |
| 251 if (commonParent is Block) { | 281 } |
| 252 int commonIndex = firstParents.indexOf(commonParent); | 282 if (node is ExpressionFunctionBody) { |
| 253 return firstParents[commonIndex + 1] as Statement; | 283 return node; |
| 254 } else { | 284 } |
| 255 return commonParent.getAncestor((node) => node is Statement); | 285 node = node.parent; |
| 256 } | 286 } |
| 287 return null; |
| 257 } | 288 } |
| 258 | 289 |
| 259 /** | 290 /** |
| 260 * Checks if it is OK to extract the node with the given [SourceRange]. | 291 * Checks if it is OK to extract the node with the given [SourceRange]. |
| 261 */ | 292 */ |
| 262 bool _isExtractable(SourceRange range) { | 293 bool _isExtractable(SourceRange range) { |
| 263 _ExtractExpressionAnalyzer analyzer = new _ExtractExpressionAnalyzer(range); | 294 _ExtractExpressionAnalyzer analyzer = new _ExtractExpressionAnalyzer(range); |
| 264 utils.unit.accept(analyzer); | 295 utils.unit.accept(analyzer); |
| 265 return analyzer.status.isOK; | 296 return analyzer.status.isOK; |
| 266 } | 297 } |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 Token startToken = nodeTokens[startTokenIndex]; | 559 Token startToken = nodeTokens[startTokenIndex]; |
| 529 Token endToken = nodeTokens[endTokenIndex]; | 560 Token endToken = nodeTokens[endTokenIndex]; |
| 530 // add occurrence range | 561 // add occurrence range |
| 531 int occuStart = nodeOffset + startToken.offset; | 562 int occuStart = nodeOffset + startToken.offset; |
| 532 int occuEnd = nodeOffset + endToken.end; | 563 int occuEnd = nodeOffset + endToken.end; |
| 533 SourceRange occuRange = rangeStartEnd(occuStart, occuEnd); | 564 SourceRange occuRange = rangeStartEnd(occuStart, occuEnd); |
| 534 _addOccurrence(occuRange); | 565 _addOccurrence(occuRange); |
| 535 } | 566 } |
| 536 } | 567 } |
| 537 } | 568 } |
| OLD | NEW |