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

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

Issue 1053323002: Issue 22988. Improve checking for conflicts between parameters and local elements during extracting… (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Clean up. Created 5 years, 8 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/mock_sdk.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_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_server.dart' hide Element; 9 import 'package:analysis_server/src/protocol_server.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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 70
71 String returnType; 71 String returnType;
72 String name; 72 String name;
73 bool extractAll = true; 73 bool extractAll = true;
74 bool canCreateGetter = false; 74 bool canCreateGetter = false;
75 bool createGetter = false; 75 bool createGetter = false;
76 final List<String> names = <String>[]; 76 final List<String> names = <String>[];
77 final List<int> offsets = <int>[]; 77 final List<int> offsets = <int>[];
78 final List<int> lengths = <int>[]; 78 final List<int> lengths = <int>[];
79 79
80 Set<String> _usedNames = new Set<String>(); 80 /**
81 * The map of local names to their visibility ranges.
82 */
83 Map<String, List<SourceRange>> _localNames = <String, List<SourceRange>>{};
84
85 /**
86 * The set of names that are referenced without any qualifier.
87 */
88 Set<String> _unqualifiedNames = new Set<String>();
89
81 Set<String> _excludedNames = new Set<String>(); 90 Set<String> _excludedNames = new Set<String>();
82 List<RefactoringMethodParameter> _parameters = <RefactoringMethodParameter>[]; 91 List<RefactoringMethodParameter> _parameters = <RefactoringMethodParameter>[];
83 Map<String, RefactoringMethodParameter> _parametersMap = 92 Map<String, RefactoringMethodParameter> _parametersMap =
84 <String, RefactoringMethodParameter>{}; 93 <String, RefactoringMethodParameter>{};
85 Map<String, List<SourceRange>> _parameterReferencesMap = 94 Map<String, List<SourceRange>> _parameterReferencesMap =
86 <String, List<SourceRange>>{}; 95 <String, List<SourceRange>>{};
87 DartType _returnType; 96 DartType _returnType;
88 String _returnVariableName; 97 String _returnVariableName;
89 AstNode _parentMember; 98 AstNode _parentMember;
90 Expression _selectionExpression; 99 Expression _selectionExpression;
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 RefactoringStatus result = new RefactoringStatus(); 358 RefactoringStatus result = new RefactoringStatus();
350 for (RefactoringMethodParameter parameter in _parameters) { 359 for (RefactoringMethodParameter parameter in _parameters) {
351 result.addStatus(validateParameterName(parameter.name)); 360 result.addStatus(validateParameterName(parameter.name));
352 for (RefactoringMethodParameter other in _parameters) { 361 for (RefactoringMethodParameter other in _parameters) {
353 if (!identical(parameter, other) && other.name == parameter.name) { 362 if (!identical(parameter, other) && other.name == parameter.name) {
354 result.addError( 363 result.addError(
355 format("Parameter '{0}' already exists", parameter.name)); 364 format("Parameter '{0}' already exists", parameter.name));
356 return result; 365 return result;
357 } 366 }
358 } 367 }
359 if (_usedNames.contains(parameter.name)) { 368 if (_isParameterNameConflictWithBody(parameter)) {
360 result.addError(format( 369 result.addError(format(
361 "'{0}' is already used as a name in the selected code", 370 "'{0}' is already used as a name in the selected code",
362 parameter.name)); 371 parameter.name));
363 return result; 372 return result;
364 } 373 }
365 } 374 }
366 return result; 375 return result;
367 } 376 }
368 377
369 /** 378 /**
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
621 630
622 /** 631 /**
623 * Checks if it is OK to extract the node with the given [SourceRange]. 632 * Checks if it is OK to extract the node with the given [SourceRange].
624 */ 633 */
625 bool _isExtractable(SourceRange range) { 634 bool _isExtractable(SourceRange range) {
626 _ExtractMethodAnalyzer analyzer = new _ExtractMethodAnalyzer(unit, range); 635 _ExtractMethodAnalyzer analyzer = new _ExtractMethodAnalyzer(unit, range);
627 utils.unit.accept(analyzer); 636 utils.unit.accept(analyzer);
628 return analyzer.status.isOK; 637 return analyzer.status.isOK;
629 } 638 }
630 639
640 bool _isParameterNameConflictWithBody(RefactoringMethodParameter parameter) {
641 String id = parameter.id;
642 String name = parameter.name;
643 List<SourceRange> parameterRanges = _parameterReferencesMap[id];
644 List<SourceRange> otherRanges = _localNames[name];
645 for (SourceRange parameterRange in parameterRanges) {
646 if (otherRanges != null) {
647 for (SourceRange otherRange in otherRanges) {
648 if (parameterRange.intersects(otherRange)) {
649 return true;
650 }
651 }
652 }
653 }
654 if (_unqualifiedNames.contains(name)) {
655 return true;
656 }
657 return false;
658 }
659
631 /** 660 /**
632 * Checks if [element] is referenced after [selectionRange]. 661 * Checks if [element] is referenced after [selectionRange].
633 */ 662 */
634 bool _isUsedAfterSelection(VariableElement element) { 663 bool _isUsedAfterSelection(VariableElement element) {
635 var visitor = new _IsUsedAfterSelectionVisitor(this, element); 664 var visitor = new _IsUsedAfterSelectionVisitor(this, element);
636 _parentMember.accept(visitor); 665 _parentMember.accept(visitor);
637 return visitor.result; 666 return visitor.result;
638 } 667 }
639 668
640 /** 669 /**
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
966 // next statement 995 // next statement
967 if (found) { 996 if (found) {
968 beginStatementIndex += selectionCount; 997 beginStatementIndex += selectionCount;
969 } else { 998 } else {
970 beginStatementIndex++; 999 beginStatementIndex++;
971 } 1000 }
972 } 1001 }
973 } 1002 }
974 } 1003 }
975 1004
976 class _InitializeParametersVisitor extends GeneralizingAstVisitor<Object> { 1005 class _InitializeParametersVisitor extends GeneralizingAstVisitor {
977 final ExtractMethodRefactoringImpl ref; 1006 final ExtractMethodRefactoringImpl ref;
978 final List<VariableElement> assignedUsedVariables; 1007 final List<VariableElement> assignedUsedVariables;
979 1008
980 _InitializeParametersVisitor(this.ref, this.assignedUsedVariables); 1009 _InitializeParametersVisitor(this.ref, this.assignedUsedVariables);
981 1010
982 @override 1011 @override
983 Object visitSimpleIdentifier(SimpleIdentifier node) { 1012 void visitSimpleIdentifier(SimpleIdentifier node) {
984 SourceRange nodeRange = rangeNode(node); 1013 SourceRange nodeRange = rangeNode(node);
985 if (ref.selectionRange.covers(nodeRange)) { 1014 if (!ref.selectionRange.covers(nodeRange)) {
986 // analyze local variable 1015 return;
987 VariableElement variableElement = 1016 }
988 getLocalOrParameterVariableElement(node); 1017 String name = node.name;
989 if (variableElement != null) { 1018 // analyze local variable
990 // name of the named expression 1019 VariableElement variableElement = getLocalOrParameterVariableElement(node);
991 if (isNamedExpressionName(node)) { 1020 if (variableElement != null) {
992 return null; 1021 // name of the named expression
1022 if (isNamedExpressionName(node)) {
1023 return;
1024 }
1025 // if declared outside, add parameter
1026 if (!ref._isDeclaredInSelection(variableElement)) {
1027 // add parameter
1028 RefactoringMethodParameter parameter = ref._parametersMap[name];
1029 if (parameter == null) {
1030 DartType parameterType = node.bestType;
1031 String parameterTypeCode = ref._getTypeCode(parameterType);
1032 parameter = new RefactoringMethodParameter(
1033 RefactoringMethodParameterKind.REQUIRED, parameterTypeCode, name,
1034 id: name);
1035 ref._parameters.add(parameter);
1036 ref._parametersMap[name] = parameter;
993 } 1037 }
994 // if declared outside, add parameter 1038 // add reference to parameter
995 if (!ref._isDeclaredInSelection(variableElement)) { 1039 ref._addParameterReference(name, nodeRange);
996 String variableName = variableElement.displayName; 1040 }
997 // add parameter 1041 // remember, if assigned and used after selection
998 RefactoringMethodParameter parameter = 1042 if (isLeftHandOfAssignment(node) &&
999 ref._parametersMap[variableName]; 1043 ref._isUsedAfterSelection(variableElement)) {
1000 if (parameter == null) { 1044 if (!assignedUsedVariables.contains(variableElement)) {
1001 DartType parameterType = node.bestType; 1045 assignedUsedVariables.add(variableElement);
1002 String parameterTypeCode = ref._getTypeCode(parameterType);
1003 parameter = new RefactoringMethodParameter(
1004 RefactoringMethodParameterKind.REQUIRED, parameterTypeCode,
1005 variableName, id: variableName);
1006 ref._parameters.add(parameter);
1007 ref._parametersMap[variableName] = parameter;
1008 }
1009 // add reference to parameter
1010 ref._addParameterReference(variableName, nodeRange);
1011 }
1012 // remember, if assigned and used after selection
1013 if (isLeftHandOfAssignment(node) &&
1014 ref._isUsedAfterSelection(variableElement)) {
1015 if (!assignedUsedVariables.contains(variableElement)) {
1016 assignedUsedVariables.add(variableElement);
1017 }
1018 } 1046 }
1019 } 1047 }
1020 // remember declaration names 1048 }
1049 // remember information for conflicts checking
1050 if (variableElement is LocalElement) {
1051 // declared local elements
1052 LocalElement localElement = variableElement as LocalElement;
1021 if (node.inDeclarationContext()) { 1053 if (node.inDeclarationContext()) {
1022 ref._usedNames.add(node.name); 1054 ref._localNames.putIfAbsent(name, () => <SourceRange>[]);
1055 ref._localNames[name].add(localElement.visibleRange);
1056 }
1057 } else {
1058 // unqualified non-local names
1059 if (!node.isQualified) {
1060 ref._unqualifiedNames.add(name);
1023 } 1061 }
1024 } 1062 }
1025 return null;
1026 } 1063 }
1027 } 1064 }
1028 1065
1029 class _IsUsedAfterSelectionVisitor extends GeneralizingAstVisitor { 1066 class _IsUsedAfterSelectionVisitor extends GeneralizingAstVisitor {
1030 final ExtractMethodRefactoringImpl ref; 1067 final ExtractMethodRefactoringImpl ref;
1031 final VariableElement element; 1068 final VariableElement element;
1032 bool result = false; 1069 bool result = false;
1033 1070
1034 _IsUsedAfterSelectionVisitor(this.ref, this.element); 1071 _IsUsedAfterSelectionVisitor(this.ref, this.element);
1035 1072
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1107 return false; 1144 return false;
1108 } 1145 }
1109 for (int i = 0; i < parameterTypes.length; i++) { 1146 for (int i = 0; i < parameterTypes.length; i++) {
1110 if (other.parameterTypes[i] != parameterTypes[i]) { 1147 if (other.parameterTypes[i] != parameterTypes[i]) {
1111 return false; 1148 return false;
1112 } 1149 }
1113 } 1150 }
1114 return true; 1151 return true;
1115 } 1152 }
1116 } 1153 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analysis_server/test/mock_sdk.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698