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

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

Issue 628293004: Remove references to Engine classes from protocol.dart (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 2 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
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 import 'dart:collection';
8 9
9 import 'package:analysis_server/src/protocol.dart' hide Element; 10 import 'package:analysis_server/src/protocol_server.dart' hide Element;
10 import 'package:analysis_server/src/services/correction/name_suggestion.dart'; 11 import 'package:analysis_server/src/services/correction/name_suggestion.dart';
11 import 'package:analysis_server/src/services/correction/selection_analyzer.dart' ; 12 import 'package:analysis_server/src/services/correction/selection_analyzer.dart' ;
12 import 'package:analysis_server/src/services/correction/source_range.dart'; 13 import 'package:analysis_server/src/services/correction/source_range.dart';
13 import 'package:analysis_server/src/services/correction/status.dart'; 14 import 'package:analysis_server/src/services/correction/status.dart';
14 import 'package:analysis_server/src/services/correction/strings.dart'; 15 import 'package:analysis_server/src/services/correction/strings.dart';
15 import 'package:analysis_server/src/services/correction/util.dart'; 16 import 'package:analysis_server/src/services/correction/util.dart';
16 import 'package:analysis_server/src/services/refactoring/naming_conventions.dart '; 17 import 'package:analysis_server/src/services/refactoring/naming_conventions.dart ';
17 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; 18 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
18 import 'package:analysis_server/src/services/refactoring/refactoring_internal.da rt'; 19 import 'package:analysis_server/src/services/refactoring/refactoring_internal.da rt';
19 import 'package:analysis_server/src/services/search/element_visitors.dart'; 20 import 'package:analysis_server/src/services/search/element_visitors.dart';
20 import 'package:analyzer/src/generated/ast.dart'; 21 import 'package:analyzer/src/generated/ast.dart';
21 import 'package:analyzer/src/generated/element.dart'; 22 import 'package:analyzer/src/generated/element.dart';
22 import 'package:analyzer/src/generated/java_core.dart'; 23 import 'package:analyzer/src/generated/java_core.dart';
23 import 'package:analyzer/src/generated/scanner.dart'; 24 import 'package:analyzer/src/generated/scanner.dart';
24 import 'package:analyzer/src/generated/source.dart'; 25 import 'package:analyzer/src/generated/source.dart';
25 import 'dart:collection';
26 26
27 27
28 const String _TOKEN_SEPARATOR = "\uFFFF"; 28 const String _TOKEN_SEPARATOR = "\uFFFF";
29 29
30 30
31 /** 31 /**
32 * [ExtractLocalRefactoring] implementation. 32 * [ExtractLocalRefactoring] implementation.
33 */ 33 */
34 class ExtractLocalRefactoringImpl extends RefactoringImpl implements 34 class ExtractLocalRefactoringImpl extends RefactoringImpl implements
35 ExtractLocalRefactoring { 35 ExtractLocalRefactoring {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 } else { 118 } else {
119 occurrences = [selectionRange]; 119 occurrences = [selectionRange];
120 } 120 }
121 // If the whole expression of a statement is selected, like '1 + 2', 121 // If the whole expression of a statement is selected, like '1 + 2',
122 // then convert it into a variable declaration statement. 122 // then convert it into a variable declaration statement.
123 if (wholeStatementExpression && occurrences.length == 1) { 123 if (wholeStatementExpression && occurrences.length == 1) {
124 String keyword = _declarationKeyword; 124 String keyword = _declarationKeyword;
125 String declarationSource = '$keyword $name = '; 125 String declarationSource = '$keyword $name = ';
126 SourceEdit edit = 126 SourceEdit edit =
127 new SourceEdit(singleExpression.offset, 0, declarationSource); 127 new SourceEdit(singleExpression.offset, 0, declarationSource);
128 change.addElementEdit(unitElement, edit); 128 doSourceChange_addElementEdit(change, unitElement, edit);
129 return new Future.value(change); 129 return new Future.value(change);
130 } 130 }
131 // add variable declaration 131 // add variable declaration
132 { 132 {
133 String declarationSource; 133 String declarationSource;
134 if (stringLiteralPart != null) { 134 if (stringLiteralPart != null) {
135 declarationSource = "var $name = '$stringLiteralPart';"; 135 declarationSource = "var $name = '$stringLiteralPart';";
136 } else { 136 } else {
137 String keyword = _declarationKeyword; 137 String keyword = _declarationKeyword;
138 String initializerSource = utils.getRangeText(selectionRange); 138 String initializerSource = utils.getRangeText(selectionRange);
(...skipping 15 matching lines...) Expand all
154 target_ = commonParent.getAncestor((node) => node is Statement); 154 target_ = commonParent.getAncestor((node) => node is Statement);
155 } 155 }
156 } 156 }
157 } 157 }
158 AstNode target = target_; 158 AstNode target = target_;
159 // insert variable declaration 159 // insert variable declaration
160 if (target is Statement) { 160 if (target is Statement) {
161 String prefix = utils.getNodePrefix(target); 161 String prefix = utils.getNodePrefix(target);
162 SourceEdit edit = 162 SourceEdit edit =
163 new SourceEdit(target.offset, 0, declarationSource + eol + prefix); 163 new SourceEdit(target.offset, 0, declarationSource + eol + prefix);
164 change.addElementEdit(unitElement, edit); 164 doSourceChange_addElementEdit(change, unitElement, edit);
165 } else if (target is ExpressionFunctionBody) { 165 } else if (target is ExpressionFunctionBody) {
166 String prefix = utils.getNodePrefix(target.parent); 166 String prefix = utils.getNodePrefix(target.parent);
167 String indent = utils.getIndent(1); 167 String indent = utils.getIndent(1);
168 String declStatement = prefix + indent + declarationSource + eol; 168 String declStatement = prefix + indent + declarationSource + eol;
169 String exprStatement = prefix + indent + 'return '; 169 String exprStatement = prefix + indent + 'return ';
170 Expression expr = target.expression; 170 Expression expr = target.expression;
171 change.addElementEdit( 171 doSourceChange_addElementEdit(
172 change,
172 unitElement, 173 unitElement,
173 new SourceEdit( 174 new SourceEdit(
174 target.offset, 175 target.offset,
175 expr.offset - target.offset, 176 expr.offset - target.offset,
176 '{' + eol + declStatement + exprStatement)); 177 '{' + eol + declStatement + exprStatement));
177 change.addElementEdit( 178 doSourceChange_addElementEdit(
179 change,
178 unitElement, 180 unitElement,
179 new SourceEdit(expr.end, 0, ';' + eol + prefix + '}')); 181 new SourceEdit(expr.end, 0, ';' + eol + prefix + '}'));
180 } 182 }
181 } 183 }
182 // prepare replacement 184 // prepare replacement
183 String occurrenceReplacement = name; 185 String occurrenceReplacement = name;
184 if (stringLiteralPart != null) { 186 if (stringLiteralPart != null) {
185 occurrenceReplacement = "\${$name}"; 187 occurrenceReplacement = "\${$name}";
186 } 188 }
187 // replace occurrences with variable reference 189 // replace occurrences with variable reference
188 for (SourceRange range in occurrences) { 190 for (SourceRange range in occurrences) {
189 SourceEdit edit = new SourceEdit.range(range, occurrenceReplacement); 191 SourceEdit edit = newSourceEdit_range(range, occurrenceReplacement);
190 change.addElementEdit(unitElement, edit); 192 doSourceChange_addElementEdit(change, unitElement, edit);
191 } 193 }
192 // done 194 // done
193 return new Future.value(change); 195 return new Future.value(change);
194 } 196 }
195 197
196 @override 198 @override
197 bool requiresPreview() => false; 199 bool requiresPreview() => false;
198 200
199 /** 201 /**
200 * Checks if [selectionRange] selects [Expression] which can be extracted, and 202 * Checks if [selectionRange] selects [Expression] which can be extracted, and
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 singleExpression = null; 257 singleExpression = null;
256 return new RefactoringStatus(); 258 return new RefactoringStatus();
257 } 259 }
258 } 260 }
259 // invalid selection 261 // invalid selection
260 return new RefactoringStatus.fatal( 262 return new RefactoringStatus.fatal(
261 'Expression must be selected to activate this refactoring.'); 263 'Expression must be selected to activate this refactoring.');
262 } 264 }
263 265
264 /** 266 /**
267 * Return an unique identifier for the given [Element], or `null` if [element]
268 * is `null`.
269 */
270 int _encodeElement(Element element) {
271 if (element == null) {
272 return null;
273 }
274 int id = elementIds[element];
275 if (id == null) {
276 id = elementIds.length;
277 elementIds[element] = id;
278 }
279 return id;
280 }
281
282 /**
283 * Returns an [Element]-sensitive encoding of [tokens].
284 * Each [Token] with a [LocalVariableElement] has a suffix of the element id.
285 *
286 * So, we can distingush different local variables with the same name, if
287 * there are multiple variables with the same name are declared in the
288 * function we are searching occurrences in.
289 */
290 String _encodeExpressionTokens(Expression expr, List<Token> tokens) {
291 // no expression, i.e. a part of a string
292 if (expr == null) {
293 return tokens.join(_TOKEN_SEPARATOR);
294 }
295 // prepare Token -> LocalElement map
296 Map<Token, Element> map = new HashMap<Token, Element>(
297 equals: (Token a, Token b) => a.lexeme == b.lexeme,
298 hashCode: (Token t) => t.lexeme.hashCode);
299 expr.accept(new _TokenLocalElementVisitor(map));
300 // map and join tokens
301 return tokens.map((Token token) {
302 String tokenString = token.lexeme;
303 // append token's Element id
304 Element element = map[token];
305 if (element != null) {
306 int elementId = _encodeElement(element);
307 if (elementId != null) {
308 tokenString += '-$elementId';
309 }
310 }
311 // done
312 return tokenString;
313 }).join(_TOKEN_SEPARATOR);
314 }
315
316 /**
265 * Returns [AstNode]s at the offsets of the given [SourceRange]s. 317 * Returns [AstNode]s at the offsets of the given [SourceRange]s.
266 */ 318 */
267 List<AstNode> _findNodes(List<SourceRange> ranges) { 319 List<AstNode> _findNodes(List<SourceRange> ranges) {
268 List<AstNode> nodes = <AstNode>[]; 320 List<AstNode> nodes = <AstNode>[];
269 for (SourceRange range in ranges) { 321 for (SourceRange range in ranges) {
270 AstNode node = new NodeLocator.con1(range.offset).searchWithin(unit); 322 AstNode node = new NodeLocator.con1(range.offset).searchWithin(unit);
271 nodes.add(node); 323 nodes.add(node);
272 } 324 }
273 return nodes; 325 return nodes;
274 } 326 }
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 } 438 }
387 439
388 void _prepareOffsetsLengths() { 440 void _prepareOffsetsLengths() {
389 offsets.clear(); 441 offsets.clear();
390 lengths.clear(); 442 lengths.clear();
391 for (SourceRange occurrence in occurrences) { 443 for (SourceRange occurrence in occurrences) {
392 offsets.add(occurrence.offset); 444 offsets.add(occurrence.offset);
393 lengths.add(occurrence.length); 445 lengths.add(occurrence.length);
394 } 446 }
395 } 447 }
396
397 /**
398 * Return an unique identifier for the given [Element], or `null` if [element]
399 * is `null`.
400 */
401 int _encodeElement(Element element) {
402 if (element == null) {
403 return null;
404 }
405 int id = elementIds[element];
406 if (id == null) {
407 id = elementIds.length;
408 elementIds[element] = id;
409 }
410 return id;
411 }
412
413 /**
414 * Returns an [Element]-sensitive encoding of [tokens].
415 * Each [Token] with a [LocalVariableElement] has a suffix of the element id.
416 *
417 * So, we can distingush different local variables with the same name, if
418 * there are multiple variables with the same name are declared in the
419 * function we are searching occurrences in.
420 */
421 String _encodeExpressionTokens(Expression expr, List<Token> tokens) {
422 // no expression, i.e. a part of a string
423 if (expr == null) {
424 return tokens.join(_TOKEN_SEPARATOR);
425 }
426 // prepare Token -> LocalElement map
427 Map<Token, Element> map = new HashMap<Token, Element>(
428 equals: (Token a, Token b) => a.lexeme == b.lexeme,
429 hashCode: (Token t) => t.lexeme.hashCode);
430 expr.accept(new _TokenLocalElementVisitor(map));
431 // map and join tokens
432 return tokens.map((Token token) {
433 String tokenString = token.lexeme;
434 // append token's Element id
435 Element element = map[token];
436 if (element != null) {
437 int elementId = _encodeElement(element);
438 if (elementId != null) {
439 tokenString += '-$elementId';
440 }
441 }
442 // done
443 return tokenString;
444 }).join(_TOKEN_SEPARATOR);
445 }
446 }
447
448
449 class _TokenLocalElementVisitor extends RecursiveAstVisitor {
450 final Map<Token, Element> map;
451
452 _TokenLocalElementVisitor(this.map);
453
454 visitSimpleIdentifier(SimpleIdentifier node) {
455 Element element = node.staticElement;
456 if (element is LocalVariableElement) {
457 map[node.token] = element;
458 }
459 }
460 } 448 }
461 449
462 450
463 /** 451 /**
464 * [SelectionAnalyzer] for [ExtractLocalRefactoringImpl]. 452 * [SelectionAnalyzer] for [ExtractLocalRefactoringImpl].
465 */ 453 */
466 class _ExtractExpressionAnalyzer extends SelectionAnalyzer { 454 class _ExtractExpressionAnalyzer extends SelectionAnalyzer {
467 final RefactoringStatus status = new RefactoringStatus(); 455 final RefactoringStatus status = new RefactoringStatus();
468 456
469 _ExtractExpressionAnalyzer(SourceRange selection) : super(selection); 457 _ExtractExpressionAnalyzer(SourceRange selection) : super(selection);
470 458
471 /** 459 /**
472 * Records fatal error with given message. 460 * Records fatal error with given message.
473 */ 461 */
474 void invalidSelection(String message) { 462 void invalidSelection(String message) {
475 _invalidSelection(message, null); 463 _invalidSelection(message, null);
476 } 464 }
477 465
478 @override 466 @override
479 Object visitAssignmentExpression(AssignmentExpression node) { 467 Object visitAssignmentExpression(AssignmentExpression node) {
480 super.visitAssignmentExpression(node); 468 super.visitAssignmentExpression(node);
481 Expression lhs = node.leftHandSide; 469 Expression lhs = node.leftHandSide;
482 if (_isFirstSelectedNode(lhs)) { 470 if (_isFirstSelectedNode(lhs)) {
483 _invalidSelection( 471 _invalidSelection(
484 'Cannot extract the left-hand side of an assignment.', 472 'Cannot extract the left-hand side of an assignment.',
485 new Location.fromNode(lhs)); 473 newLocation_fromNode(lhs));
486 } 474 }
487 return null; 475 return null;
488 } 476 }
489 477
490 @override 478 @override
491 Object visitSimpleIdentifier(SimpleIdentifier node) { 479 Object visitSimpleIdentifier(SimpleIdentifier node) {
492 super.visitSimpleIdentifier(node); 480 super.visitSimpleIdentifier(node);
493 if (_isFirstSelectedNode(node)) { 481 if (_isFirstSelectedNode(node)) {
494 // name of declaration 482 // name of declaration
495 if (node.inDeclarationContext()) { 483 if (node.inDeclarationContext()) {
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 Token startToken = nodeTokens[startTokenIndex]; 616 Token startToken = nodeTokens[startTokenIndex];
629 Token endToken = nodeTokens[endTokenIndex]; 617 Token endToken = nodeTokens[endTokenIndex];
630 // add occurrence range 618 // add occurrence range
631 int occuStart = nodeOffset + startToken.offset; 619 int occuStart = nodeOffset + startToken.offset;
632 int occuEnd = nodeOffset + endToken.end; 620 int occuEnd = nodeOffset + endToken.end;
633 SourceRange occuRange = rangeStartEnd(occuStart, occuEnd); 621 SourceRange occuRange = rangeStartEnd(occuStart, occuEnd);
634 _addOccurrence(occuRange); 622 _addOccurrence(occuRange);
635 } 623 }
636 } 624 }
637 } 625 }
626
627
628 class _TokenLocalElementVisitor extends RecursiveAstVisitor {
629 final Map<Token, Element> map;
630
631 _TokenLocalElementVisitor(this.map);
632
633 visitSimpleIdentifier(SimpleIdentifier node) {
634 Element element = node.staticElement;
635 if (element is LocalVariableElement) {
636 map[node.token] = element;
637 }
638 }
639 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698