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

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: 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
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 // TODO
Brian Wilkerson 2015/04/03 21:00:41 Remove or expand (explain what needs to be done).
369 if (_isParameterNameConflictWithBody(parameter)) {
360 result.addError(format( 370 result.addError(format(
361 "'{0}' is already used as a name in the selected code", 371 "'{0}' is already used as a name in the selected code",
362 parameter.name)); 372 parameter.name));
363 return result; 373 return result;
364 } 374 }
375 // List<SourceRange> usedRanges = _usedNames[parameter.name];
376 // if (_usedNames.contains(parameter.name)) {
377 // result.addError(format(
378 // "'{0}' is already used as a name in the selected code",
379 // parameter.name));
380 // return result;
381 // }
365 } 382 }
366 return result; 383 return result;
367 } 384 }
368 385
369 /** 386 /**
370 * Checks if created method will shadow or will be shadowed by other elements. 387 * Checks if created method will shadow or will be shadowed by other elements.
371 */ 388 */
372 Future<RefactoringStatus> _checkPossibleConflicts() async { 389 Future<RefactoringStatus> _checkPossibleConflicts() async {
373 RefactoringStatus result = new RefactoringStatus(); 390 RefactoringStatus result = new RefactoringStatus();
374 AstNode parent = _parentMember.parent; 391 AstNode parent = _parentMember.parent;
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
621 638
622 /** 639 /**
623 * Checks if it is OK to extract the node with the given [SourceRange]. 640 * Checks if it is OK to extract the node with the given [SourceRange].
624 */ 641 */
625 bool _isExtractable(SourceRange range) { 642 bool _isExtractable(SourceRange range) {
626 _ExtractMethodAnalyzer analyzer = new _ExtractMethodAnalyzer(unit, range); 643 _ExtractMethodAnalyzer analyzer = new _ExtractMethodAnalyzer(unit, range);
627 utils.unit.accept(analyzer); 644 utils.unit.accept(analyzer);
628 return analyzer.status.isOK; 645 return analyzer.status.isOK;
629 } 646 }
630 647
648 bool _isParameterNameConflictWithBody(RefactoringMethodParameter parameter) {
649 String id = parameter.id;
650 String name = parameter.name;
651 // TODO
Brian Wilkerson 2015/04/03 21:00:41 ditto
652 List<SourceRange> parameterRanges = _parameterReferencesMap[id];
653 List<SourceRange> otherRanges = _localNames[name];
654 for (SourceRange parameterRange in parameterRanges) {
655 if (otherRanges != null) {
656 for (SourceRange otherRange in otherRanges) {
657 if (parameterRange.intersects(otherRange)) {
658 return true;
659 }
660 }
661 }
662 }
663 if (_unqualifiedNames.contains(name)) {
664 return true;
665 }
666 return false;
667 }
668
631 /** 669 /**
632 * Checks if [element] is referenced after [selectionRange]. 670 * Checks if [element] is referenced after [selectionRange].
633 */ 671 */
634 bool _isUsedAfterSelection(VariableElement element) { 672 bool _isUsedAfterSelection(VariableElement element) {
635 var visitor = new _IsUsedAfterSelectionVisitor(this, element); 673 var visitor = new _IsUsedAfterSelectionVisitor(this, element);
636 _parentMember.accept(visitor); 674 _parentMember.accept(visitor);
637 return visitor.result; 675 return visitor.result;
638 } 676 }
639 677
640 /** 678 /**
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
966 // next statement 1004 // next statement
967 if (found) { 1005 if (found) {
968 beginStatementIndex += selectionCount; 1006 beginStatementIndex += selectionCount;
969 } else { 1007 } else {
970 beginStatementIndex++; 1008 beginStatementIndex++;
971 } 1009 }
972 } 1010 }
973 } 1011 }
974 } 1012 }
975 1013
976 class _InitializeParametersVisitor extends GeneralizingAstVisitor<Object> { 1014 class _InitializeParametersVisitor extends GeneralizingAstVisitor {
977 final ExtractMethodRefactoringImpl ref; 1015 final ExtractMethodRefactoringImpl ref;
978 final List<VariableElement> assignedUsedVariables; 1016 final List<VariableElement> assignedUsedVariables;
979 1017
980 _InitializeParametersVisitor(this.ref, this.assignedUsedVariables); 1018 _InitializeParametersVisitor(this.ref, this.assignedUsedVariables);
981 1019
982 @override 1020 @override
983 Object visitSimpleIdentifier(SimpleIdentifier node) { 1021 void visitSimpleIdentifier(SimpleIdentifier node) {
984 SourceRange nodeRange = rangeNode(node); 1022 SourceRange nodeRange = rangeNode(node);
985 if (ref.selectionRange.covers(nodeRange)) { 1023 if (!ref.selectionRange.covers(nodeRange)) {
986 // analyze local variable 1024 return;
987 VariableElement variableElement = 1025 }
988 getLocalOrParameterVariableElement(node); 1026 String name = node.name;
989 if (variableElement != null) { 1027 // analyze local variable
990 // name of the named expression 1028 VariableElement variableElement = getLocalOrParameterVariableElement(node);
991 if (isNamedExpressionName(node)) { 1029 if (variableElement != null) {
992 return null; 1030 // name of the named expression
1031 if (isNamedExpressionName(node)) {
1032 return;
1033 }
1034 // if declared outside, add parameter
1035 if (!ref._isDeclaredInSelection(variableElement)) {
1036 // add parameter
1037 RefactoringMethodParameter parameter = ref._parametersMap[name];
1038 if (parameter == null) {
1039 DartType parameterType = node.bestType;
1040 String parameterTypeCode = ref._getTypeCode(parameterType);
1041 parameter = new RefactoringMethodParameter(
1042 RefactoringMethodParameterKind.REQUIRED, parameterTypeCode, name,
1043 id: name);
1044 ref._parameters.add(parameter);
1045 ref._parametersMap[name] = parameter;
993 } 1046 }
994 // if declared outside, add parameter 1047 // add reference to parameter
995 if (!ref._isDeclaredInSelection(variableElement)) { 1048 ref._addParameterReference(name, nodeRange);
996 String variableName = variableElement.displayName; 1049 }
997 // add parameter 1050 // remember, if assigned and used after selection
998 RefactoringMethodParameter parameter = 1051 if (isLeftHandOfAssignment(node) &&
999 ref._parametersMap[variableName]; 1052 ref._isUsedAfterSelection(variableElement)) {
1000 if (parameter == null) { 1053 if (!assignedUsedVariables.contains(variableElement)) {
1001 DartType parameterType = node.bestType; 1054 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 } 1055 }
1019 } 1056 }
1020 // remember declaration names 1057 }
1058 // remember information for conflicts checking
1059 if (variableElement is LocalElement) {
1060 // declared local elements
1061 LocalElement localElement = variableElement as LocalElement;
1021 if (node.inDeclarationContext()) { 1062 if (node.inDeclarationContext()) {
1022 ref._usedNames.add(node.name); 1063 ref._localNames.putIfAbsent(name, () => <SourceRange>[]);
1064 ref._localNames[name].add(localElement.visibleRange);
1065 }
1066 } else {
1067 // unqualified non-local names
1068 if (!node.isQualified) {
1069 ref._unqualifiedNames.add(name);
1023 } 1070 }
1024 } 1071 }
1025 return null;
1026 } 1072 }
1027 } 1073 }
1028 1074
1029 class _IsUsedAfterSelectionVisitor extends GeneralizingAstVisitor { 1075 class _IsUsedAfterSelectionVisitor extends GeneralizingAstVisitor {
1030 final ExtractMethodRefactoringImpl ref; 1076 final ExtractMethodRefactoringImpl ref;
1031 final VariableElement element; 1077 final VariableElement element;
1032 bool result = false; 1078 bool result = false;
1033 1079
1034 _IsUsedAfterSelectionVisitor(this.ref, this.element); 1080 _IsUsedAfterSelectionVisitor(this.ref, this.element);
1035 1081
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1107 return false; 1153 return false;
1108 } 1154 }
1109 for (int i = 0; i < parameterTypes.length; i++) { 1155 for (int i = 0; i < parameterTypes.length; i++) {
1110 if (other.parameterTypes[i] != parameterTypes[i]) { 1156 if (other.parameterTypes[i] != parameterTypes[i]) {
1111 return false; 1157 return false;
1112 } 1158 }
1113 } 1159 }
1114 return true; 1160 return true;
1115 } 1161 }
1116 } 1162 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698