Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1016)

Side by Side Diff: pkg/analysis_server/lib/src/services/refactoring/extract_local.dart

Issue 568333003: Issue 18895. Convert an expression function body into the block function body when Extract Local. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/analysis_server/test/services/refactoring/extract_local_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analysis_server/test/services/refactoring/extract_local_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698