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

Side by Side Diff: pkg/analysis_services/lib/src/refactoring/rename_unit_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_unit_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/search_engine.dart';
13 import 'package:analysis_services/src/correction/util.dart';
14 import 'package:analysis_services/src/refactoring/naming_conventions.dart';
15 import 'package:analysis_services/src/refactoring/rename.dart';
16 import 'package:analyzer/src/generated/element.dart';
17 import 'package:analyzer/src/generated/java_core.dart';
18 import 'package:analysis_services/search/element_visitors.dart';
19
20
21 /**
22 * A [Refactoring] for renaming compilation unit member [Element]s.
23 */
24 class RenameUnitMemberRefactoringImpl extends RenameRefactoringImpl {
25 RenameUnitMemberRefactoringImpl(SearchEngine searchEngine, Element element)
26 : super(searchEngine, element);
27
28 @override
29 String get refactoringName {
30 if (element is FunctionElement) {
31 return "Rename Top-Level Function";
32 }
33 if (element is FunctionTypeAliasElement) {
34 return "Rename Function Type Alias";
35 }
36 if (element is TopLevelVariableElement) {
37 return "Rename Top-Level Variable";
38 }
39 return "Rename Class";
40 }
41
42 @override
43 Future<RefactoringStatus> checkFinalConditions() {
44 return new RenameUnitMemberValidator(
45 searchEngine,
46 element,
47 element.kind,
48 newName,
49 true).validate();
50 }
51
52 @override
53 RefactoringStatus checkNewName() {
54 RefactoringStatus result = super.checkNewName();
55 if (element is TopLevelVariableElement) {
56 TopLevelVariableElement variable = element as TopLevelVariableElement;
57 if (variable.isConst) {
58 result.addStatus(validateConstantName(newName));
59 } else {
60 result.addStatus(validateVariableName(newName));
61 }
62 }
63 if (element is FunctionElement) {
64 result.addStatus(validateFunctionName(newName));
65 }
66 if (element is FunctionTypeAliasElement) {
67 result.addStatus(validateFunctionTypeAliasName(newName));
68 }
69 if (element is ClassElement) {
70 result.addStatus(validateClassName(newName));
71 }
72 return result;
73 }
74
75 @override
76 Future<Change> createChange() {
77 Change change = new Change(refactoringName);
78 // prepare elements
79 List<Element> elements = [];
80 if (element is PropertyInducingElement && element.isSynthetic) {
81 PropertyInducingElement property = element as PropertyInducingElement;
82 PropertyAccessorElement getter = property.getter;
83 PropertyAccessorElement setter = property.setter;
84 if (getter != null) {
85 elements.add(getter);
86 }
87 if (setter != null) {
88 elements.add(setter);
89 }
90 } else {
91 elements.add(element);
92 }
93 // update each element
94 return Future.forEach(elements, (Element element) {
95 // update declaration
96 addDeclarationEdit(change, element);
97 // schedule updating references
98 return searchEngine.searchReferences(element).then((refMatches) {
99 List<SourceReference> references = getSourceReferences(refMatches);
100 for (SourceReference reference in references) {
101 addReferenceEdit(change, reference);
102 }
103 });
104 }).then((_) {
105 return change;
106 });
107 }
108 }
109
110
111 /**
112 * Helper to check if renaming or creating [Element] with given name will cause any problems.
113 */
114 class RenameUnitMemberValidator {
115 final SearchEngine searchEngine;
116 final Element element;
117 final ElementKind elementKind;
118 final String newName;
119 final bool forRename;
120
121 final RefactoringStatus result = new RefactoringStatus();
122
123 RenameUnitMemberValidator(this.searchEngine, this.element, this.elementKind,
124 this.newName, this.forRename);
125
126 Future<RefactoringStatus> validate() {
127 _validateWillConflict();
128 List<Future> futures = <Future>[];
129 if (forRename) {
130 futures.add(_validateWillBeShadowed());
131 }
132 futures.add(_validateWillShadow());
133 return Future.wait(futures).then((_) {
134 return result;
135 });
136 }
137
138 /**
139 * Returns `true` if [element] is visible at the given [SearchMatch].
140 */
141 bool _isVisibleAt(Element element, SearchMatch at) {
142 LibraryElement library = at.element.library;
143 // may be the same library
144 if (element.library == library) {
145 return true;
146 }
147 // check imports
148 for (ImportElement importElement in library.imports) {
149 // ignore if imported with prefix
150 if (importElement.prefix != null) {
151 continue;
152 }
153 // check imported elements
154 if (getImportNamespace(importElement).containsValue(element)) {
155 return true;
156 }
157 }
158 // no, it is not visible
159 return false;
160 }
161
162 /**
163 * Validates if any usage of [element] renamed to [newName] will be shadowed.
164 */
165 Future _validateWillBeShadowed() {
166 return searchEngine.searchReferences(element).then((references) {
167 for (SearchMatch reference in references) {
168 Element refElement = reference.element;
169 ClassElement refClass =
170 refElement.getAncestor((e) => e is ClassElement);
171 if (refClass != null) {
172 visitChildren(refClass, (shadow) {
173 if (hasDisplayName(shadow, newName)) {
174 String message =
175 format(
176 "Reference to renamed {0} will be shadowed by {1} '{2}'.",
177 getElementKindName(element),
178 getElementKindName(shadow),
179 getElementQualifiedName(shadow));
180 result.addError(
181 message,
182 new RefactoringStatusContext.forElement(shadow));
183 }
184 });
185 }
186 }
187 });
188 }
189
190 /**
191 * Validates if [element] renamed to [newName] will conflict with another
192 * top-level [Element] in the same library.
193 */
194 void _validateWillConflict() {
195 LibraryElement library = element.getAncestor((e) => e is LibraryElement);
196 visitLibraryTopLevelElements(library, (element) {
197 if (hasDisplayName(element, newName)) {
198 String message =
199 format(
200 "Library already declares {0} with name '{1}'.",
201 getElementKindName(element),
202 newName);
203 result.addError(
204 message,
205 new RefactoringStatusContext.forElement(element));
206 }
207 });
208 }
209
210 /**
211 * Validates if renamed [element] will shadow any [Element] named [newName].
212 */
213 Future _validateWillShadow() {
214 return searchEngine.searchMemberDeclarations(newName).then((declarations) {
215 return Future.forEach(declarations, (SearchMatch declaration) {
216 Element member = declaration.element;
217 ClassElement declaringClass = member.enclosingElement;
218 return searchEngine.searchReferences(member).then((memberReferences) {
219 for (SearchMatch memberReference in memberReferences) {
220 Element refElement = memberReference.element;
221 // cannot be shadowed if qualified
222 if (memberReference.isQualified) {
223 continue;
224 }
225 // cannot be shadowed if declared in the same class as reference
226 ClassElement refClass =
227 refElement.getAncestor((e) => e is ClassElement);
228 if (refClass == declaringClass) {
229 continue;
230 }
231 // ignore if not visitble
232 if (!_isVisibleAt(element, memberReference)) {
233 continue;
234 }
235 // OK, reference will be shadowed be the element being renamed
236 String message =
237 format(
238 forRename ?
239 "Renamed {0} will shadow {1} '{2}'." :
240 "Created {0} will shadow {1} '{2}'.",
241 getElementKindName(element),
242 getElementKindName(member),
243 getElementQualifiedName(member));
244 result.addError(
245 message,
246 new RefactoringStatusContext.forMatch(memberReference));
247 }
248 });
249 });
250 });
251 }
252 }
OLDNEW
« no previous file with comments | « pkg/analysis_services/lib/src/refactoring/rename_local.dart ('k') | pkg/analysis_services/lib/src/search/search_engine.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698