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

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

Issue 506753002: Parameters and validation for the 'Extract Method' refactoring. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 4 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.rename_class_member; 5 library services.src.refactoring.rename_class_member;
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, ElementKind;
10 import 'package:analysis_server/src/services/correction/status.dart'; 10 import 'package:analysis_server/src/services/correction/status.dart';
11 import 'package:analysis_server/src/services/correction/util.dart';
12 import 'package:analysis_server/src/services/refactoring/naming_conventions.dart ';
11 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; 13 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
14 import 'package:analysis_server/src/services/refactoring/rename.dart';
12 import 'package:analysis_server/src/services/search/hierarchy.dart'; 15 import 'package:analysis_server/src/services/search/hierarchy.dart';
13 import 'package:analysis_server/src/services/search/search_engine.dart'; 16 import 'package:analysis_server/src/services/search/search_engine.dart';
14 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/rename.dart';
17 import 'package:analyzer/src/generated/element.dart'; 17 import 'package:analyzer/src/generated/element.dart';
18 import 'package:analyzer/src/generated/java_core.dart'; 18 import 'package:analyzer/src/generated/java_core.dart';
19 19
20 20
21 /** 21 /**
22 * Checks if creating a method with the given [name] in [classElement] will
23 * cause any conflicts.
24 */
25 Future<RefactoringStatus> validateCreateMethod(SearchEngine searchEngine,
26 ClassElement classElement, String name) {
27 return new _ClassMemberValidator.forCreate(
28 searchEngine,
29 classElement,
30 name).validate();
31 }
32
33
34 /**
22 * A [Refactoring] for renaming class member [Element]s. 35 * A [Refactoring] for renaming class member [Element]s.
23 */ 36 */
24 class RenameClassMemberRefactoringImpl extends RenameRefactoringImpl { 37 class RenameClassMemberRefactoringImpl extends RenameRefactoringImpl {
25 _RenameClassMemberValidator _validator; 38 _ClassMemberValidator _validator;
26 39
27 RenameClassMemberRefactoringImpl(SearchEngine searchEngine, Element element) 40 RenameClassMemberRefactoringImpl(SearchEngine searchEngine, Element element)
28 : super(searchEngine, element); 41 : super(searchEngine, element);
29 42
30 @override 43 @override
31 String get refactoringName { 44 String get refactoringName {
32 if (element is TypeParameterElement) { 45 if (element is TypeParameterElement) {
33 return "Rename Type Parameter"; 46 return "Rename Type Parameter";
34 } 47 }
35 if (element is FieldElement) { 48 if (element is FieldElement) {
36 return "Rename Field"; 49 return "Rename Field";
37 } 50 }
38 return "Rename Method"; 51 return "Rename Method";
39 } 52 }
40 53
41 @override 54 @override
42 Future<RefactoringStatus> checkFinalConditions() { 55 Future<RefactoringStatus> checkFinalConditions() {
43 _validator = 56 _validator =
44 new _RenameClassMemberValidator(searchEngine, element, newName); 57 new _ClassMemberValidator.forRename(searchEngine, element, newName);
45 return _validator.validate(); 58 return _validator.validate();
46 } 59 }
47 60
48 @override 61 @override
49 Future<RefactoringStatus> checkInitialConditions() { 62 Future<RefactoringStatus> checkInitialConditions() {
50 RefactoringStatus result = new RefactoringStatus(); 63 RefactoringStatus result = new RefactoringStatus();
51 if (element is MethodElement && (element as MethodElement).isOperator) { 64 if (element is MethodElement && (element as MethodElement).isOperator) {
52 result.addFatalError('Cannot rename operator.'); 65 result.addFatalError('Cannot rename operator.');
53 } 66 }
54 return new Future.value(result); 67 return new Future.value(result);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 127
115 String _newPotentialId() { 128 String _newPotentialId() {
116 String id = potentialEditIds.length.toString(); 129 String id = potentialEditIds.length.toString();
117 potentialEditIds.add(id); 130 potentialEditIds.add(id);
118 return id; 131 return id;
119 } 132 }
120 } 133 }
121 134
122 135
123 /** 136 /**
124 * Helper to check if renaming of an [Element] to the given name will cause any 137 * Helper to check if the created or renamed [Element] will cause any conflicts.
125 * problems.
126 */ 138 */
127 class _RenameClassMemberValidator { 139 class _ClassMemberValidator {
128 final SearchEngine searchEngine; 140 final SearchEngine searchEngine;
129 final Element element; 141 final Element element;
130 final String oldName; 142 final ClassElement elementClass;
131 final String newName; 143 final ElementKind elementKind;
144 final String name;
145 final bool isRename;
132 146
133 Set<Element> elements = new Set(); 147 Set<Element> elements = new Set<Element>();
134 List<SearchMatch> references = []; 148 List<SearchMatch> references = <SearchMatch>[];
135 149
136 _RenameClassMemberValidator(this.searchEngine, Element element, this.newName) 150 _ClassMemberValidator.forCreate(this.searchEngine, this.elementClass,
137 : element = element, 151 this.name)
138 oldName = element.displayName; 152 : isRename = false,
153 element = null,
154 elementKind = ElementKind.METHOD;
155
156 _ClassMemberValidator.forRename(this.searchEngine, Element element, this.name)
157 : isRename = true,
158 element = element,
159 elementClass = element.enclosingElement,
160 elementKind = element.kind;
139 161
140 Future<RefactoringStatus> validate() { 162 Future<RefactoringStatus> validate() {
141 RefactoringStatus result = new RefactoringStatus(); 163 RefactoringStatus result = new RefactoringStatus();
142 ClassElement elementClass = element.enclosingElement;
143 // check if there is a member with "newName" in the same ClassElement 164 // check if there is a member with "newName" in the same ClassElement
144 for (Element newNameMember in getChildren(elementClass, newName)) { 165 for (Element newNameMember in getChildren(elementClass, name)) {
145 result.addError( 166 result.addError(
146 format( 167 format(
147 "Class '{0}' already declares {1} with name '{2}'.", 168 "Class '{0}' already declares {1} with name '{2}'.",
148 elementClass.displayName, 169 elementClass.displayName,
149 getElementKindName(newNameMember), 170 getElementKindName(newNameMember),
150 newName), 171 name),
151 new Location.fromElement(newNameMember)); 172 new Location.fromElement(newNameMember));
152 } 173 }
153 // do chained computations 174 // do chained computations
154 Set<ClassElement> superClasses = getSuperClasses(elementClass); 175 Set<ClassElement> superClasses = getSuperClasses(elementClass);
155 Set<ClassElement> subClasses; 176 Set<ClassElement> subClasses;
156 return _prepareReferences().then((_) { 177 return _prepareReferences().then((_) {
157 return getSubClasses(searchEngine, elementClass).then((_subs) { 178 return getSubClasses(searchEngine, elementClass).then((_subs) {
158 subClasses = _subs; 179 subClasses = _subs;
159 }); 180 });
160 }).then((_) { 181 }).then((_) {
161 // check shadowing in hierarchy 182 // check shadowing in hierarchy
162 return searchEngine.searchElementDeclarations(newName).then((decls) { 183 return searchEngine.searchElementDeclarations(name).then((decls) {
163 for (SearchMatch decl in decls) { 184 for (SearchMatch decl in decls) {
164 Element nameElement = getSyntheticAccessorVariable(decl.element); 185 Element nameElement = getSyntheticAccessorVariable(decl.element);
165 Element nameClass = nameElement.enclosingElement; 186 Element nameClass = nameElement.enclosingElement;
166 // renamed Element shadows member of superclass 187 // renamed Element shadows member of superclass
167 if (superClasses.contains(nameClass)) { 188 if (superClasses.contains(nameClass)) {
168 result.addError( 189 result.addError(
169 format( 190 format(
170 "Renamed {0} will shadow {1} '{2}'.", 191 isRename ?
171 getElementKindName(element), 192 "Renamed {0} will shadow {1} '{2}'." :
193 "Created {0} will shadow {1} '{2}'.",
194 elementKind.displayName,
172 getElementKindName(nameElement), 195 getElementKindName(nameElement),
173 getElementQualifiedName(nameElement)), 196 getElementQualifiedName(nameElement)),
174 new Location.fromElement(nameElement)); 197 new Location.fromElement(nameElement));
175 } 198 }
176 // renamed Element is shadowed by member of subclass 199 // renamed Element is shadowed by member of subclass
177 if (subClasses.contains(nameClass)) { 200 if (isRename && subClasses.contains(nameClass)) {
178 result.addError( 201 result.addError(
179 format( 202 format(
180 "Renamed {0} will be shadowed by {1} '{2}'.", 203 "Renamed {0} will be shadowed by {1} '{2}'.",
181 getElementKindName(element), 204 elementKind.displayName,
182 getElementKindName(nameElement), 205 getElementKindName(nameElement),
183 getElementQualifiedName(nameElement)), 206 getElementQualifiedName(nameElement)),
184 new Location.fromElement(nameElement)); 207 new Location.fromElement(nameElement));
185 } 208 }
186 // renamed Element is shadowed by local 209 // renamed Element is shadowed by local
187 if (nameElement is LocalElement) { 210 if (nameElement is LocalElement) {
188 LocalElement localElement = nameElement; 211 LocalElement localElement = nameElement;
189 ClassElement enclosingClass = 212 ClassElement enclosingClass =
190 nameElement.getAncestor((element) => element is ClassElement); 213 nameElement.getAncestor((element) => element is ClassElement);
191 if (enclosingClass == elementClass || 214 if (enclosingClass == elementClass ||
192 subClasses.contains(enclosingClass)) { 215 subClasses.contains(enclosingClass)) {
193 for (SearchMatch reference in references) { 216 for (SearchMatch reference in references) {
194 if (isReferenceInLocalRange(localElement, reference)) { 217 if (isReferenceInLocalRange(localElement, reference)) {
195 result.addError( 218 result.addError(
196 format( 219 format(
197 "Usage of renamed {0} will be shadowed by {1} '{2}'.", 220 "Usage of renamed {0} will be shadowed by {1} '{2}'.",
198 getElementKindName(element), 221 elementKind.displayName,
199 getElementKindName(localElement), 222 getElementKindName(localElement),
200 localElement.displayName), 223 localElement.displayName),
201 new Location.fromMatch(reference)); 224 new Location.fromMatch(reference));
202 } 225 }
203 } 226 }
204 } 227 }
205 } 228 }
206 } 229 }
207 }); 230 });
208 }).then((_) => result); 231 }).then((_) => result);
(...skipping 12 matching lines...) Expand all
221 } else { 244 } else {
222 elements = new Set.from([element]); 245 elements = new Set.from([element]);
223 return new Future.value(); 246 return new Future.value();
224 } 247 }
225 } 248 }
226 249
227 /** 250 /**
228 * Fills [references] with all references to [elements]. 251 * Fills [references] with all references to [elements].
229 */ 252 */
230 Future _prepareReferences() { 253 Future _prepareReferences() {
254 if (!isRename) {
255 return new Future.value();
256 }
231 return _prepareElements().then((_) { 257 return _prepareElements().then((_) {
232 return Future.forEach(elements, (Element element) { 258 return Future.forEach(elements, (Element element) {
233 return searchEngine.searchReferences(element).then((references) { 259 return searchEngine.searchReferences(element).then((references) {
234 this.references.addAll(references); 260 this.references.addAll(references);
235 }); 261 });
236 }); 262 });
237 }); 263 });
238 } 264 }
239 } 265 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698