| 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_method; | 5 library services.src.refactoring.extract_method; |
| 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/selection_analyzer.dart'
; | 11 import 'package:analysis_server/src/services/correction/selection_analyzer.dart'
; |
| 11 import 'package:analysis_server/src/services/correction/source_range.dart'; | 12 import 'package:analysis_server/src/services/correction/source_range.dart'; |
| 12 import 'package:analysis_server/src/services/correction/statement_analyzer.dart'
; | 13 import 'package:analysis_server/src/services/correction/statement_analyzer.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/util.dart'; | 15 import 'package:analysis_server/src/services/correction/util.dart'; |
| 15 import 'package:analysis_server/src/services/refactoring/naming_conventions.dart
'; | 16 import 'package:analysis_server/src/services/refactoring/naming_conventions.dart
'; |
| 16 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; | 17 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; |
| 17 import 'package:analysis_server/src/services/refactoring/refactoring_internal.da
rt'; | 18 import 'package:analysis_server/src/services/refactoring/refactoring_internal.da
rt'; |
| 18 import 'package:analysis_server/src/services/refactoring/rename_class_member.dar
t'; | 19 import 'package:analysis_server/src/services/refactoring/rename_class_member.dar
t'; |
| 19 import 'package:analysis_server/src/services/refactoring/rename_unit_member.dart
'; | 20 import 'package:analysis_server/src/services/refactoring/rename_unit_member.dart
'; |
| 21 import 'package:analysis_server/src/services/search/element_visitors.dart'; |
| 20 import 'package:analysis_server/src/services/search/search_engine.dart'; | 22 import 'package:analysis_server/src/services/search/search_engine.dart'; |
| 21 import 'package:analyzer/src/generated/ast.dart'; | 23 import 'package:analyzer/src/generated/ast.dart'; |
| 22 import 'package:analyzer/src/generated/element.dart'; | 24 import 'package:analyzer/src/generated/element.dart'; |
| 23 import 'package:analyzer/src/generated/java_core.dart'; | 25 import 'package:analyzer/src/generated/java_core.dart'; |
| 24 import 'package:analyzer/src/generated/scanner.dart'; | 26 import 'package:analyzer/src/generated/scanner.dart'; |
| 25 import 'package:analyzer/src/generated/source.dart'; | 27 import 'package:analyzer/src/generated/source.dart'; |
| 26 | 28 |
| 27 | 29 |
| 28 const String _TOKEN_SEPARATOR = '\uFFFF'; | 30 const String _TOKEN_SEPARATOR = '\uFFFF'; |
| 29 | 31 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 | 67 |
| 66 String returnType; | 68 String returnType; |
| 67 String name; | 69 String name; |
| 68 bool extractAll = true; | 70 bool extractAll = true; |
| 69 bool createGetter = false; | 71 bool createGetter = false; |
| 70 final List<String> names = <String>[]; | 72 final List<String> names = <String>[]; |
| 71 final List<int> offsets = <int>[]; | 73 final List<int> offsets = <int>[]; |
| 72 final List<int> lengths = <int>[]; | 74 final List<int> lengths = <int>[]; |
| 73 | 75 |
| 74 Set<String> _usedNames = new Set<String>(); | 76 Set<String> _usedNames = new Set<String>(); |
| 77 Set<String> _excludedNames = new Set<String>(); |
| 75 List<RefactoringMethodParameter> _parameters = <RefactoringMethodParameter>[]; | 78 List<RefactoringMethodParameter> _parameters = <RefactoringMethodParameter>[]; |
| 76 Map<String, RefactoringMethodParameter> _parametersMap = <String, | 79 Map<String, RefactoringMethodParameter> _parametersMap = <String, |
| 77 RefactoringMethodParameter>{}; | 80 RefactoringMethodParameter>{}; |
| 78 Map<String, List<SourceRange>> _parameterReferencesMap = <String, | 81 Map<String, List<SourceRange>> _parameterReferencesMap = <String, |
| 79 List<SourceRange>>{}; | 82 List<SourceRange>>{}; |
| 80 DartType _returnType; | 83 DartType _returnType; |
| 81 String _returnVariableName; | 84 String _returnVariableName; |
| 82 AstNode _parentMember; | 85 AstNode _parentMember; |
| 83 Expression _selectionExpression; | 86 Expression _selectionExpression; |
| 84 FunctionExpression _selectionFunctionExpression; | 87 FunctionExpression _selectionFunctionExpression; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 Future<RefactoringStatus> checkInitialConditions() { | 179 Future<RefactoringStatus> checkInitialConditions() { |
| 177 RefactoringStatus result = new RefactoringStatus(); | 180 RefactoringStatus result = new RefactoringStatus(); |
| 178 // selection | 181 // selection |
| 179 result.addStatus(_checkSelection()); | 182 result.addStatus(_checkSelection()); |
| 180 if (result.hasFatalError) { | 183 if (result.hasFatalError) { |
| 181 return new Future.value(result); | 184 return new Future.value(result); |
| 182 } | 185 } |
| 183 // prepare parts | 186 // prepare parts |
| 184 result.addStatus(_initializeParameters()); | 187 result.addStatus(_initializeParameters()); |
| 185 _initializeReturnType(); | 188 _initializeReturnType(); |
| 189 _initializeGetter(); |
| 190 // occurrences |
| 186 _initializeOccurrences(); | 191 _initializeOccurrences(); |
| 187 _initializeGetter(); | 192 _prepareOffsetsLengths(); |
| 193 // names |
| 194 _prepareExcludedNames(); |
| 195 _prepareNames(); |
| 188 // closure cannot have parameters | 196 // closure cannot have parameters |
| 189 if (_selectionFunctionExpression != null && !_parameters.isEmpty) { | 197 if (_selectionFunctionExpression != null && !_parameters.isEmpty) { |
| 190 String message = format( | 198 String message = format( |
| 191 'Cannot extract closure as method, it references {0} external variable
(s).', | 199 'Cannot extract closure as method, it references {0} external variable
(s).', |
| 192 _parameters.length); | 200 _parameters.length); |
| 193 RefactoringStatus result = new RefactoringStatus.fatal(message); | 201 RefactoringStatus result = new RefactoringStatus.fatal(message); |
| 194 return new Future.value(result); | 202 return new Future.value(result); |
| 195 } | 203 } |
| 196 return new Future.value(result); | 204 return new Future.value(result); |
| 197 } | 205 } |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 return new RefactoringStatus(); | 450 return new RefactoringStatus(); |
| 443 } | 451 } |
| 444 } | 452 } |
| 445 } | 453 } |
| 446 // invalid selection | 454 // invalid selection |
| 447 return new RefactoringStatus.fatal( | 455 return new RefactoringStatus.fatal( |
| 448 'Can only extract a single expression or a set of statements.'); | 456 'Can only extract a single expression or a set of statements.'); |
| 449 } | 457 } |
| 450 | 458 |
| 451 /** | 459 /** |
| 452 * @return the selected [DartExpression] source, with applying new parameter n
ames. | 460 * Returns the selected [Expression] source, with applying new parameter |
| 461 * names. |
| 453 */ | 462 */ |
| 454 String _getMethodBodySource() { | 463 String _getMethodBodySource() { |
| 455 String source = utils.getRangeText(selectionRange); | 464 String source = utils.getRangeText(selectionRange); |
| 456 // prepare operations to replace variables with parameters | 465 // prepare operations to replace variables with parameters |
| 457 List<SourceEdit> replaceEdits = []; | 466 List<SourceEdit> replaceEdits = []; |
| 458 for (RefactoringMethodParameter parameter in _parametersMap.values) { | 467 for (RefactoringMethodParameter parameter in _parametersMap.values) { |
| 459 List<SourceRange> ranges = _parameterReferencesMap[parameter.id]; | 468 List<SourceRange> ranges = _parameterReferencesMap[parameter.id]; |
| 460 if (ranges != null) { | 469 if (ranges != null) { |
| 461 for (SourceRange range in ranges) { | 470 for (SourceRange range in ranges) { |
| 462 replaceEdits.add( | 471 replaceEdits.add( |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 /** | 644 /** |
| 636 * Checks if [element] is referenced after [selectionRange]. | 645 * Checks if [element] is referenced after [selectionRange]. |
| 637 */ | 646 */ |
| 638 bool _isUsedAfterSelection(VariableElement element) { | 647 bool _isUsedAfterSelection(VariableElement element) { |
| 639 var visitor = new _IsUsedAfterSelectionVisitor(this, element); | 648 var visitor = new _IsUsedAfterSelectionVisitor(this, element); |
| 640 _parentMember.accept(visitor); | 649 _parentMember.accept(visitor); |
| 641 return visitor.result; | 650 return visitor.result; |
| 642 } | 651 } |
| 643 | 652 |
| 644 /** | 653 /** |
| 654 * Prepare names that are used in the enclosing function, so should not be |
| 655 * proposed as names of the extracted method. |
| 656 */ |
| 657 void _prepareExcludedNames() { |
| 658 _excludedNames.clear(); |
| 659 ExecutableElement enclosingExecutable = |
| 660 getEnclosingExecutableElement(_parentMember); |
| 661 if (enclosingExecutable != null) { |
| 662 visitChildren(enclosingExecutable, (Element element) { |
| 663 if (element is LocalElement) { |
| 664 SourceRange elementRange = element.visibleRange; |
| 665 if (elementRange != null) { |
| 666 _excludedNames.add(element.displayName); |
| 667 } |
| 668 } |
| 669 return true; |
| 670 }); |
| 671 } |
| 672 } |
| 673 |
| 674 void _prepareNames() { |
| 675 names.clear(); |
| 676 if (_selectionExpression != null) { |
| 677 names.addAll( |
| 678 getVariableNameSuggestionsForExpression( |
| 679 _selectionExpression.staticType, |
| 680 _selectionExpression, |
| 681 _excludedNames)); |
| 682 } |
| 683 } |
| 684 |
| 685 void _prepareOffsetsLengths() { |
| 686 offsets.clear(); |
| 687 lengths.clear(); |
| 688 for (_Occurrence occurrence in _occurrences) { |
| 689 offsets.add(occurrence.range.offset); |
| 690 lengths.add(occurrence.range.length); |
| 691 } |
| 692 } |
| 693 |
| 694 /** |
| 645 * Checks if [node] has a [MethodInvocation]. | 695 * Checks if [node] has a [MethodInvocation]. |
| 646 */ | 696 */ |
| 647 static bool _hasMethodInvocation(AstNode node) { | 697 static bool _hasMethodInvocation(AstNode node) { |
| 648 var visitor = new _HasMethodInvocationVisitor(); | 698 var visitor = new _HasMethodInvocationVisitor(); |
| 649 node.accept(visitor); | 699 node.accept(visitor); |
| 650 return visitor.result; | 700 return visitor.result; |
| 651 } | 701 } |
| 652 } | 702 } |
| 653 | 703 |
| 654 | 704 |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1048 | 1098 |
| 1049 /** | 1099 /** |
| 1050 * Generalized version of some source, in which references to the specific | 1100 * Generalized version of some source, in which references to the specific |
| 1051 * variables are replaced with pattern variables, with back mapping from the | 1101 * variables are replaced with pattern variables, with back mapping from the |
| 1052 * pattern to the original variable names. | 1102 * pattern to the original variable names. |
| 1053 */ | 1103 */ |
| 1054 class _SourcePattern { | 1104 class _SourcePattern { |
| 1055 String patternSource; | 1105 String patternSource; |
| 1056 Map<String, String> originalToPatternNames = {}; | 1106 Map<String, String> originalToPatternNames = {}; |
| 1057 } | 1107 } |
| OLD | NEW |