| 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 import 'dart:async'; | 5 import 'dart:async'; |
| 6 | 6 |
| 7 import 'package:analysis_server/src/protocol_server.dart' hide Element; | 7 import 'package:analysis_server/src/protocol_server.dart' hide Element; |
| 8 import 'package:analysis_server/src/services/correction/name_suggestion.dart'; | 8 import 'package:analysis_server/src/services/correction/name_suggestion.dart'; |
| 9 import 'package:analysis_server/src/services/correction/selection_analyzer.dart'
; | 9 import 'package:analysis_server/src/services/correction/selection_analyzer.dart'
; |
| 10 import 'package:analysis_server/src/services/correction/statement_analyzer.dart'
; | 10 import 'package:analysis_server/src/services/correction/statement_analyzer.dart'
; |
| 11 import 'package:analysis_server/src/services/correction/status.dart'; | 11 import 'package:analysis_server/src/services/correction/status.dart'; |
| 12 import 'package:analysis_server/src/services/correction/util.dart'; | 12 import 'package:analysis_server/src/services/correction/util.dart'; |
| 13 import 'package:analysis_server/src/services/refactoring/naming_conventions.dart
'; | 13 import 'package:analysis_server/src/services/refactoring/naming_conventions.dart
'; |
| 14 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; | 14 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; |
| 15 import 'package:analysis_server/src/services/refactoring/refactoring_internal.da
rt'; | 15 import 'package:analysis_server/src/services/refactoring/refactoring_internal.da
rt'; |
| 16 import 'package:analysis_server/src/services/refactoring/rename_class_member.dar
t'; | 16 import 'package:analysis_server/src/services/refactoring/rename_class_member.dar
t'; |
| 17 import 'package:analysis_server/src/services/refactoring/rename_unit_member.dart
'; | 17 import 'package:analysis_server/src/services/refactoring/rename_unit_member.dart
'; |
| 18 import 'package:analysis_server/src/services/search/search_engine.dart'; | 18 import 'package:analysis_server/src/services/search/search_engine.dart'; |
| 19 import 'package:analyzer/dart/analysis/session.dart'; |
| 19 import 'package:analyzer/dart/ast/ast.dart'; | 20 import 'package:analyzer/dart/ast/ast.dart'; |
| 20 import 'package:analyzer/dart/ast/standard_resolution_map.dart'; | 21 import 'package:analyzer/dart/ast/standard_resolution_map.dart'; |
| 21 import 'package:analyzer/dart/ast/token.dart'; | 22 import 'package:analyzer/dart/ast/token.dart'; |
| 22 import 'package:analyzer/dart/ast/visitor.dart'; | 23 import 'package:analyzer/dart/ast/visitor.dart'; |
| 23 import 'package:analyzer/dart/element/element.dart'; | 24 import 'package:analyzer/dart/element/element.dart'; |
| 24 import 'package:analyzer/dart/element/type.dart'; | 25 import 'package:analyzer/dart/element/type.dart'; |
| 25 import 'package:analyzer/src/dart/ast/utilities.dart'; | 26 import 'package:analyzer/src/dart/ast/utilities.dart'; |
| 26 import 'package:analyzer/src/dart/element/ast_provider.dart'; | 27 import 'package:analyzer/src/dart/element/ast_provider.dart'; |
| 27 import 'package:analyzer/src/generated/engine.dart'; | |
| 28 import 'package:analyzer/src/generated/java_core.dart'; | 28 import 'package:analyzer/src/generated/java_core.dart'; |
| 29 import 'package:analyzer/src/generated/resolver.dart' show ExitDetector; | 29 import 'package:analyzer/src/generated/resolver.dart' show ExitDetector; |
| 30 import 'package:analyzer/src/generated/source.dart'; | 30 import 'package:analyzer/src/generated/source.dart'; |
| 31 import 'package:analyzer/src/generated/type_system.dart'; |
| 31 import 'package:analyzer_plugin/utilities/range_factory.dart'; | 32 import 'package:analyzer_plugin/utilities/range_factory.dart'; |
| 32 | 33 |
| 33 const String _TOKEN_SEPARATOR = '\uFFFF'; | 34 const String _TOKEN_SEPARATOR = '\uFFFF'; |
| 34 | 35 |
| 35 Element _getLocalElement(SimpleIdentifier node) { | 36 Element _getLocalElement(SimpleIdentifier node) { |
| 36 Element element = node.staticElement; | 37 Element element = node.staticElement; |
| 37 if (element is LocalVariableElement || | 38 if (element is LocalVariableElement || |
| 38 element is ParameterElement || | 39 element is ParameterElement || |
| 39 element is FunctionElement && element.visibleRange != null) { | 40 element is FunctionElement && element.visibleRange != null) { |
| 40 return element; | 41 return element; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 69 implements ExtractMethodRefactoring { | 70 implements ExtractMethodRefactoring { |
| 70 static const ERROR_EXITS = | 71 static const ERROR_EXITS = |
| 71 'Selected statements contain a return statement, but not all possible ' | 72 'Selected statements contain a return statement, but not all possible ' |
| 72 'execution flows exit. Semantics may not be preserved.'; | 73 'execution flows exit. Semantics may not be preserved.'; |
| 73 | 74 |
| 74 final SearchEngine searchEngine; | 75 final SearchEngine searchEngine; |
| 75 final AstProvider astProvider; | 76 final AstProvider astProvider; |
| 76 final CompilationUnit unit; | 77 final CompilationUnit unit; |
| 77 final int selectionOffset; | 78 final int selectionOffset; |
| 78 final int selectionLength; | 79 final int selectionLength; |
| 79 AnalysisContext context; | 80 AnalysisSession session; |
| 80 CompilationUnitElement unitElement; | 81 CompilationUnitElement unitElement; |
| 81 LibraryElement libraryElement; | 82 LibraryElement libraryElement; |
| 82 SourceRange selectionRange; | 83 SourceRange selectionRange; |
| 83 CorrectionUtils utils; | 84 CorrectionUtils utils; |
| 84 Set<Source> librariesToImport = new Set<Source>(); | 85 Set<Source> librariesToImport = new Set<Source>(); |
| 85 | 86 |
| 86 String returnType = ''; | 87 String returnType = ''; |
| 87 String variableType; | 88 String variableType; |
| 88 String name; | 89 String name; |
| 89 bool extractAll = true; | 90 bool extractAll = true; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 116 Expression _selectionExpression; | 117 Expression _selectionExpression; |
| 117 FunctionExpression _selectionFunctionExpression; | 118 FunctionExpression _selectionFunctionExpression; |
| 118 List<Statement> _selectionStatements; | 119 List<Statement> _selectionStatements; |
| 119 List<_Occurrence> _occurrences = []; | 120 List<_Occurrence> _occurrences = []; |
| 120 bool _staticContext = false; | 121 bool _staticContext = false; |
| 121 | 122 |
| 122 ExtractMethodRefactoringImpl(this.searchEngine, this.astProvider, this.unit, | 123 ExtractMethodRefactoringImpl(this.searchEngine, this.astProvider, this.unit, |
| 123 this.selectionOffset, this.selectionLength) { | 124 this.selectionOffset, this.selectionLength) { |
| 124 unitElement = unit.element; | 125 unitElement = unit.element; |
| 125 libraryElement = unitElement.library; | 126 libraryElement = unitElement.library; |
| 126 context = libraryElement.context; | 127 session = astProvider.driver.currentSession; |
| 127 selectionRange = new SourceRange(selectionOffset, selectionLength); | 128 selectionRange = new SourceRange(selectionOffset, selectionLength); |
| 128 utils = new CorrectionUtils(unit); | 129 utils = new CorrectionUtils(unit); |
| 129 } | 130 } |
| 130 | 131 |
| 131 @override | 132 @override |
| 132 List<RefactoringMethodParameter> get parameters => _parameters; | 133 List<RefactoringMethodParameter> get parameters => _parameters; |
| 133 | 134 |
| 134 @override | 135 @override |
| 135 void set parameters(List<RefactoringMethodParameter> parameters) { | 136 void set parameters(List<RefactoringMethodParameter> parameters) { |
| 136 _parameters = parameters.toList(); | 137 _parameters = parameters.toList(); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 Future<RefactoringStatus> checkFinalConditions() async { | 189 Future<RefactoringStatus> checkFinalConditions() async { |
| 189 RefactoringStatus result = new RefactoringStatus(); | 190 RefactoringStatus result = new RefactoringStatus(); |
| 190 result.addStatus(validateMethodName(name)); | 191 result.addStatus(validateMethodName(name)); |
| 191 result.addStatus(_checkParameterNames()); | 192 result.addStatus(_checkParameterNames()); |
| 192 RefactoringStatus status = await _checkPossibleConflicts(); | 193 RefactoringStatus status = await _checkPossibleConflicts(); |
| 193 result.addStatus(status); | 194 result.addStatus(status); |
| 194 return result; | 195 return result; |
| 195 } | 196 } |
| 196 | 197 |
| 197 @override | 198 @override |
| 198 Future<RefactoringStatus> checkInitialConditions() { | 199 Future<RefactoringStatus> checkInitialConditions() async { |
| 199 RefactoringStatus result = new RefactoringStatus(); | 200 RefactoringStatus result = new RefactoringStatus(); |
| 200 // selection | 201 // selection |
| 201 result.addStatus(_checkSelection()); | 202 result.addStatus(_checkSelection()); |
| 202 if (result.hasFatalError) { | 203 if (result.hasFatalError) { |
| 203 return new Future.value(result); | 204 return result; |
| 204 } | 205 } |
| 205 // prepare parts | 206 // prepare parts |
| 206 result.addStatus(_initializeParameters()); | 207 result.addStatus(await _initializeParameters()); |
| 207 _initializeHasAwait(); | 208 _initializeHasAwait(); |
| 208 _initializeReturnType(); | 209 await _initializeReturnType(); |
| 209 // occurrences | 210 // occurrences |
| 210 _initializeOccurrences(); | 211 _initializeOccurrences(); |
| 211 _prepareOffsetsLengths(); | 212 _prepareOffsetsLengths(); |
| 212 // getter | 213 // getter |
| 213 canCreateGetter = _computeCanCreateGetter(); | 214 canCreateGetter = _computeCanCreateGetter(); |
| 214 createGetter = | 215 createGetter = |
| 215 canCreateGetter && _isExpressionForGetter(_selectionExpression); | 216 canCreateGetter && _isExpressionForGetter(_selectionExpression); |
| 216 // names | 217 // names |
| 217 _prepareExcludedNames(); | 218 _prepareExcludedNames(); |
| 218 _prepareNames(); | 219 _prepareNames(); |
| 219 // closure cannot have parameters | 220 // closure cannot have parameters |
| 220 if (_selectionFunctionExpression != null && !_parameters.isEmpty) { | 221 if (_selectionFunctionExpression != null && !_parameters.isEmpty) { |
| 221 String message = format( | 222 String message = format( |
| 222 'Cannot extract closure as method, it references {0} external variable
(s).', | 223 'Cannot extract closure as method, it references {0} external variable
(s).', |
| 223 _parameters.length); | 224 _parameters.length); |
| 224 RefactoringStatus result = new RefactoringStatus.fatal(message); | 225 return new RefactoringStatus.fatal(message); |
| 225 return new Future.value(result); | |
| 226 } | 226 } |
| 227 return new Future.value(result); | 227 return result; |
| 228 } | 228 } |
| 229 | 229 |
| 230 @override | 230 @override |
| 231 RefactoringStatus checkName() { | 231 RefactoringStatus checkName() { |
| 232 return validateMethodName(name); | 232 return validateMethodName(name); |
| 233 } | 233 } |
| 234 | 234 |
| 235 @override | 235 @override |
| 236 Future<SourceChange> createChange() async { | 236 Future<SourceChange> createChange() async { |
| 237 SourceChange change = new SourceChange(refactoringName); | 237 SourceChange change = new SourceChange(refactoringName); |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 660 AstNode enclosingMemberParent = _parentMember.parent; | 660 AstNode enclosingMemberParent = _parentMember.parent; |
| 661 // visit nodes which will able to access extracted method | 661 // visit nodes which will able to access extracted method |
| 662 enclosingMemberParent.accept(new _InitializeOccurrencesVisitor( | 662 enclosingMemberParent.accept(new _InitializeOccurrencesVisitor( |
| 663 this, selectionPattern, patternToSelectionName)); | 663 this, selectionPattern, patternToSelectionName)); |
| 664 } | 664 } |
| 665 | 665 |
| 666 /** | 666 /** |
| 667 * Prepares information about used variables, which should be turned into | 667 * Prepares information about used variables, which should be turned into |
| 668 * parameters. | 668 * parameters. |
| 669 */ | 669 */ |
| 670 RefactoringStatus _initializeParameters() { | 670 Future<RefactoringStatus> _initializeParameters() async { |
| 671 _parameters.clear(); | 671 _parameters.clear(); |
| 672 _parametersMap.clear(); | 672 _parametersMap.clear(); |
| 673 _parameterReferencesMap.clear(); | 673 _parameterReferencesMap.clear(); |
| 674 RefactoringStatus result = new RefactoringStatus(); | 674 RefactoringStatus result = new RefactoringStatus(); |
| 675 List<VariableElement> assignedUsedVariables = []; | 675 List<VariableElement> assignedUsedVariables = []; |
| 676 unit.accept(new _InitializeParametersVisitor(this, assignedUsedVariables)); | 676 unit.accept(new _InitializeParametersVisitor(this, assignedUsedVariables)); |
| 677 // single expression | 677 // single expression |
| 678 if (_selectionExpression != null) { | 678 if (_selectionExpression != null) { |
| 679 _returnType = _selectionExpression.bestType; | 679 _returnType = _selectionExpression.bestType; |
| 680 } | 680 } |
| 681 // verify that none or all execution flows end with a "return" | 681 // verify that none or all execution flows end with a "return" |
| 682 if (_selectionStatements != null) { | 682 if (_selectionStatements != null) { |
| 683 bool hasReturn = _selectionStatements.any(_mayEndWithReturnStatement); | 683 bool hasReturn = _selectionStatements.any(_mayEndWithReturnStatement); |
| 684 if (hasReturn && !ExitDetector.exits(_selectionStatements.last)) { | 684 if (hasReturn && !ExitDetector.exits(_selectionStatements.last)) { |
| 685 result.addError(ERROR_EXITS); | 685 result.addError(ERROR_EXITS); |
| 686 } | 686 } |
| 687 } | 687 } |
| 688 // maybe ends with "return" statement | 688 // maybe ends with "return" statement |
| 689 if (_selectionStatements != null) { | 689 if (_selectionStatements != null) { |
| 690 _ReturnTypeComputer returnTypeComputer = new _ReturnTypeComputer(context); | 690 _ReturnTypeComputer returnTypeComputer = |
| 691 new _ReturnTypeComputer(await session.typeSystem); |
| 691 _selectionStatements.forEach((statement) { | 692 _selectionStatements.forEach((statement) { |
| 692 statement.accept(returnTypeComputer); | 693 statement.accept(returnTypeComputer); |
| 693 }); | 694 }); |
| 694 _returnType = returnTypeComputer.returnType; | 695 _returnType = returnTypeComputer.returnType; |
| 695 } | 696 } |
| 696 // maybe single variable to return | 697 // maybe single variable to return |
| 697 if (assignedUsedVariables.length == 1) { | 698 if (assignedUsedVariables.length == 1) { |
| 698 // we cannot both return variable and have explicit return statement | 699 // we cannot both return variable and have explicit return statement |
| 699 if (_returnType != null) { | 700 if (_returnType != null) { |
| 700 result.addFatalError( | 701 result.addFatalError( |
| (...skipping 15 matching lines...) Expand all Loading... |
| 716 } | 717 } |
| 717 result.addFatalError(format( | 718 result.addFatalError(format( |
| 718 'Ambiguous return value: Selected block contains more than one ' | 719 'Ambiguous return value: Selected block contains more than one ' |
| 719 'assignment to local variables. Affected variables are:\n\n{0}', | 720 'assignment to local variables. Affected variables are:\n\n{0}', |
| 720 sb.toString().trim())); | 721 sb.toString().trim())); |
| 721 } | 722 } |
| 722 // done | 723 // done |
| 723 return result; | 724 return result; |
| 724 } | 725 } |
| 725 | 726 |
| 726 void _initializeReturnType() { | 727 Future<Null> _initializeReturnType() async { |
| 727 InterfaceType futureType = context.typeProvider.futureType; | 728 InterfaceType futureType = (await session.typeProvider).futureType; |
| 728 if (_selectionFunctionExpression != null) { | 729 if (_selectionFunctionExpression != null) { |
| 729 variableType = ''; | 730 variableType = ''; |
| 730 returnType = ''; | 731 returnType = ''; |
| 731 } else if (_returnType == null) { | 732 } else if (_returnType == null) { |
| 732 variableType = null; | 733 variableType = null; |
| 733 if (_hasAwait) { | 734 if (_hasAwait) { |
| 734 returnType = _getTypeCode(futureType); | 735 returnType = _getTypeCode(futureType); |
| 735 } else { | 736 } else { |
| 736 returnType = 'void'; | 737 returnType = 'void'; |
| 737 } | 738 } |
| (...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1255 class _Occurrence { | 1256 class _Occurrence { |
| 1256 final SourceRange range; | 1257 final SourceRange range; |
| 1257 final bool isSelection; | 1258 final bool isSelection; |
| 1258 | 1259 |
| 1259 Map<String, String> _parameterOldToOccurrenceName = <String, String>{}; | 1260 Map<String, String> _parameterOldToOccurrenceName = <String, String>{}; |
| 1260 | 1261 |
| 1261 _Occurrence(this.range, this.isSelection); | 1262 _Occurrence(this.range, this.isSelection); |
| 1262 } | 1263 } |
| 1263 | 1264 |
| 1264 class _ReturnTypeComputer extends RecursiveAstVisitor { | 1265 class _ReturnTypeComputer extends RecursiveAstVisitor { |
| 1265 final AnalysisContext context; | 1266 final TypeSystem typeSystem; |
| 1266 | 1267 |
| 1267 DartType returnType; | 1268 DartType returnType; |
| 1268 | 1269 |
| 1269 _ReturnTypeComputer(this.context); | 1270 _ReturnTypeComputer(this.typeSystem); |
| 1270 | 1271 |
| 1271 @override | 1272 @override |
| 1272 visitBlockFunctionBody(BlockFunctionBody node) {} | 1273 visitBlockFunctionBody(BlockFunctionBody node) {} |
| 1273 | 1274 |
| 1274 @override | 1275 @override |
| 1275 visitReturnStatement(ReturnStatement node) { | 1276 visitReturnStatement(ReturnStatement node) { |
| 1276 // prepare expression | 1277 // prepare expression |
| 1277 Expression expression = node.expression; | 1278 Expression expression = node.expression; |
| 1278 if (expression == null) { | 1279 if (expression == null) { |
| 1279 return; | 1280 return; |
| 1280 } | 1281 } |
| 1281 // prepare type | 1282 // prepare type |
| 1282 DartType type = expression.bestType; | 1283 DartType type = expression.bestType; |
| 1283 if (type.isBottom) { | 1284 if (type.isBottom) { |
| 1284 return; | 1285 return; |
| 1285 } | 1286 } |
| 1286 // combine types | 1287 // combine types |
| 1287 if (returnType == null) { | 1288 if (returnType == null) { |
| 1288 returnType = type; | 1289 returnType = type; |
| 1289 } else { | 1290 } else { |
| 1290 if (returnType is InterfaceType && type is InterfaceType) { | 1291 if (returnType is InterfaceType && type is InterfaceType) { |
| 1291 returnType = InterfaceType.getSmartLeastUpperBound(returnType, type); | 1292 returnType = InterfaceType.getSmartLeastUpperBound(returnType, type); |
| 1292 } else { | 1293 } else { |
| 1293 returnType = context.typeSystem.getLeastUpperBound(returnType, type); | 1294 returnType = typeSystem.getLeastUpperBound(returnType, type); |
| 1294 } | 1295 } |
| 1295 } | 1296 } |
| 1296 } | 1297 } |
| 1297 } | 1298 } |
| 1298 | 1299 |
| 1299 /** | 1300 /** |
| 1300 * Generalized version of some source, in which references to the specific | 1301 * Generalized version of some source, in which references to the specific |
| 1301 * variables are replaced with pattern variables, with back mapping from the | 1302 * variables are replaced with pattern variables, with back mapping from the |
| 1302 * pattern to the original variable names. | 1303 * pattern to the original variable names. |
| 1303 */ | 1304 */ |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1314 return false; | 1315 return false; |
| 1315 } | 1316 } |
| 1316 for (int i = 0; i < parameterTypes.length; i++) { | 1317 for (int i = 0; i < parameterTypes.length; i++) { |
| 1317 if (other.parameterTypes[i] != parameterTypes[i]) { | 1318 if (other.parameterTypes[i] != parameterTypes[i]) { |
| 1318 return false; | 1319 return false; |
| 1319 } | 1320 } |
| 1320 } | 1321 } |
| 1321 return true; | 1322 return true; |
| 1322 } | 1323 } |
| 1323 } | 1324 } |
| OLD | NEW |