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

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

Issue 484733003: Import analysis_services.dart into analysis_server.dart. (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
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 library services.src.refactoring.rename_class_member;
6
7 import 'dart:async';
8
9 import 'package:analysis_services/correction/change.dart';
10 import 'package:analysis_services/correction/status.dart';
11 import 'package:analysis_services/refactoring/refactoring.dart';
12 import 'package:analysis_services/search/hierarchy.dart';
13 import 'package:analysis_services/search/search_engine.dart';
14 import 'package:analysis_services/src/correction/util.dart';
15 import 'package:analysis_services/src/refactoring/naming_conventions.dart';
16 import 'package:analysis_services/src/refactoring/rename.dart';
17 import 'package:analyzer/src/generated/element.dart';
18 import 'package:analyzer/src/generated/java_core.dart';
19
20
21 /**
22 * A [Refactoring] for renaming class member [Element]s.
23 */
24 class RenameClassMemberRefactoringImpl extends RenameRefactoringImpl {
25 _RenameClassMemberValidator _validator;
26
27 RenameClassMemberRefactoringImpl(SearchEngine searchEngine, Element element)
28 : super(searchEngine, element);
29
30 @override
31 String get refactoringName {
32 if (element is TypeParameterElement) {
33 return "Rename Type Parameter";
34 }
35 if (element is FieldElement) {
36 return "Rename Field";
37 }
38 return "Rename Method";
39 }
40
41 @override
42 Future<RefactoringStatus> checkFinalConditions() {
43 _validator = new _RenameClassMemberValidator(
44 searchEngine,
45 element,
46 newName);
47 return _validator.validate();
48 }
49
50 @override
51 Future<RefactoringStatus> checkInitialConditions() {
52 RefactoringStatus result = new RefactoringStatus();
53 if (element is MethodElement && (element as MethodElement).isOperator) {
54 result.addFatalError('Cannot rename operator.');
55 }
56 return new Future.value(result);
57 }
58
59 @override
60 RefactoringStatus checkNewName() {
61 RefactoringStatus result = super.checkNewName();
62 if (element is FieldElement) {
63 FieldElement fieldElement = element as FieldElement;
64 if (fieldElement.isStatic && fieldElement.isConst) {
65 result.addStatus(validateConstantName(newName));
66 } else {
67 result.addStatus(validateFieldName(newName));
68 }
69 }
70 if (element is MethodElement) {
71 result.addStatus(validateMethodName(newName));
72 }
73 return result;
74 }
75
76 @override
77 Future<Change> createChange() {
78 Change change = new Change(refactoringName);
79 // update declarations
80 for (Element renameElement in _validator.elements) {
81 if (renameElement.isSynthetic && renameElement is FieldElement) {
82 addDeclarationEdit(change, renameElement.getter);
83 addDeclarationEdit(change, renameElement.setter);
84 } else {
85 addDeclarationEdit(change, renameElement);
86 }
87 }
88 // update references
89 List<SourceReference> references =
90 getSourceReferences(_validator.references);
91 for (SourceReference reference in references) {
92 addReferenceEdit(change, reference);
93 }
94 // potential matches
95 return searchEngine.searchMemberReferences(oldName).then((nameMatches) {
96 List<SourceReference> nameRefs = getSourceReferences(nameMatches);
97 for (SourceReference reference in nameRefs) {
98 // ignore resolved reference, we have already updated it
99 if (reference.isResolved) {
100 continue;
101 }
102 // check the element being renamed is accessible
103 {
104 LibraryElement whereLibrary = reference.element.library;
105 if (!element.isAccessibleIn(whereLibrary)) {
106 continue;
107 }
108 }
109 // add edit
110 Edit edit = createReferenceEdit(reference, newName);
111 _markEditAsPotential(edit);
112 change.addEdit(reference.file, edit);
113 }
114 }).then((_) => change);
115 }
116
117 void _markEditAsPotential(Edit edit) {
118 String id = potentialEditIds.length.toString();
119 potentialEditIds.add(id);
120 edit.id = id;
121 }
122 }
123
124
125 /**
126 * Helper to check if renaming of an [Element] to the given name will cause any
127 * problems.
128 */
129 class _RenameClassMemberValidator {
130 final SearchEngine searchEngine;
131 final Element element;
132 final String oldName;
133 final String newName;
134
135 Set<Element> elements = new Set();
136 List<SearchMatch> references = [];
137
138 _RenameClassMemberValidator(this.searchEngine, Element element, this.newName)
139 : element = element,
140 oldName = element.displayName;
141
142 Future<RefactoringStatus> validate() {
143 RefactoringStatus result = new RefactoringStatus();
144 ClassElement elementClass = element.enclosingElement;
145 // check if there is a member with "newName" in the same ClassElement
146 for (Element newNameMember in getChildren(elementClass, newName)) {
147 result.addError(
148 format(
149 "Class '{0}' already declares {1} with name '{2}'.",
150 elementClass.displayName,
151 getElementKindName(newNameMember),
152 newName),
153 new RefactoringStatusContext.forElement(newNameMember));
154 }
155 // do chained computations
156 Set<ClassElement> superClasses = getSuperClasses(elementClass);
157 Set<ClassElement> subClasses;
158 return _prepareReferences().then((_) {
159 return getSubClasses(searchEngine, elementClass).then((_subs) {
160 subClasses = _subs;
161 });
162 }).then((_) {
163 // check shadowing in hierarchy
164 return searchEngine.searchElementDeclarations(newName).then((decls) {
165 for (SearchMatch decl in decls) {
166 Element nameElement = getSyntheticAccessorVariable(decl.element);
167 Element nameClass = nameElement.enclosingElement;
168 // renamed Element shadows member of superclass
169 if (superClasses.contains(nameClass)) {
170 result.addError(
171 format(
172 "Renamed {0} will shadow {1} '{2}'.",
173 getElementKindName(element),
174 getElementKindName(nameElement),
175 getElementQualifiedName(nameElement)),
176 new RefactoringStatusContext.forElement(nameElement));
177 }
178 // renamed Element is shadowed by member of subclass
179 if (subClasses.contains(nameClass)) {
180 result.addError(
181 format(
182 "Renamed {0} will be shadowed by {1} '{2}'.",
183 getElementKindName(element),
184 getElementKindName(nameElement),
185 getElementQualifiedName(nameElement)),
186 new RefactoringStatusContext.forElement(nameElement));
187 }
188 // renamed Element is shadowed by local
189 if (nameElement is LocalElement) {
190 LocalElement localElement = nameElement;
191 ClassElement enclosingClass =
192 nameElement.getAncestor((element) => element is ClassElement);
193 if (enclosingClass == elementClass ||
194 subClasses.contains(enclosingClass)) {
195 for (SearchMatch reference in references) {
196 if (isReferenceInLocalRange(localElement, reference)) {
197 result.addError(
198 format(
199 "Usage of renamed {0} will be shadowed by {1} '{2}'.",
200 getElementKindName(element),
201 getElementKindName(localElement),
202 localElement.displayName),
203 new RefactoringStatusContext.forMatch(reference));
204 }
205 }
206 }
207 }
208 }
209 });
210 }).then((_) => result);
211 }
212
213 /**
214 * Fills [elements] with [Element]s to rename.
215 */
216 Future _prepareElements() {
217 if (element is ClassMemberElement) {
218 return getHierarchyMembers(
219 searchEngine,
220 element).then((Set<Element> elements) {
221 this.elements = elements;
222 });
223 } else {
224 elements = new Set.from([element]);
225 return new Future.value();
226 }
227 }
228
229 /**
230 * Fills [references] with all references to [elements].
231 */
232 Future _prepareReferences() {
233 return _prepareElements().then((_) {
234 return Future.forEach(elements, (Element element) {
235 return searchEngine.searchReferences(element).then((references) {
236 this.references.addAll(references);
237 });
238 });
239 });
240 }
241 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698