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

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

Issue 477383002: Checks for shadowing in 'Rename Class Member' 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
« no previous file with comments | « no previous file | pkg/analysis_services/test/refactoring/rename_class_member_test.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.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_services/correction/change.dart'; 9 import 'package:analysis_services/correction/change.dart';
10 import 'package:analysis_services/correction/status.dart'; 10 import 'package:analysis_services/correction/status.dart';
11 import 'package:analysis_services/refactoring/refactoring.dart'; 11 import 'package:analysis_services/refactoring/refactoring.dart';
12 import 'package:analysis_services/search/hierarchy.dart'; 12 import 'package:analysis_services/search/hierarchy.dart';
13 import 'package:analysis_services/search/search_engine.dart'; 13 import 'package:analysis_services/search/search_engine.dart';
14 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/naming_conventions.dart';
15 import 'package:analysis_services/src/refactoring/rename.dart'; 16 import 'package:analysis_services/src/refactoring/rename.dart';
16 import 'package:analyzer/src/generated/element.dart'; 17 import 'package:analyzer/src/generated/element.dart';
18 import 'package:analyzer/src/generated/java_core.dart';
17 19
18 20
19 /** 21 /**
20 * A [Refactoring] for renaming class member [Element]s. 22 * A [Refactoring] for renaming class member [Element]s.
21 */ 23 */
22 class RenameClassMemberRefactoringImpl extends RenameRefactoringImpl { 24 class RenameClassMemberRefactoringImpl extends RenameRefactoringImpl {
23 _RenameClassMemberValidator _validator; 25 _RenameClassMemberValidator _validator;
24 26
25 RenameClassMemberRefactoringImpl(SearchEngine searchEngine, Element element) 27 RenameClassMemberRefactoringImpl(SearchEngine searchEngine, Element element)
26 : super(searchEngine, element); 28 : super(searchEngine, element);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 /** 125 /**
124 * Helper to check if renaming of an [Element] to the given name will cause any 126 * Helper to check if renaming of an [Element] to the given name will cause any
125 * problems. 127 * problems.
126 */ 128 */
127 class _RenameClassMemberValidator { 129 class _RenameClassMemberValidator {
128 final SearchEngine searchEngine; 130 final SearchEngine searchEngine;
129 final Element element; 131 final Element element;
130 final String oldName; 132 final String oldName;
131 final String newName; 133 final String newName;
132 134
133 // Set<ClassElement> _superClasses;
134 // Set<ClassElement> _subClasses;
135
136 Set<Element> elements = new Set(); 135 Set<Element> elements = new Set();
137 List<SearchMatch> references = []; 136 List<SearchMatch> references = [];
138 137
139 _RenameClassMemberValidator(this.searchEngine, Element element, this.newName) 138 _RenameClassMemberValidator(this.searchEngine, Element element, this.newName)
140 : element = element, 139 : element = element,
141 oldName = element.displayName; 140 oldName = element.displayName;
142 141
143 Future<RefactoringStatus> validate() { 142 Future<RefactoringStatus> validate() {
144 RefactoringStatus result = new RefactoringStatus(); 143 RefactoringStatus result = new RefactoringStatus();
145 ClassElement elementClass = element.enclosingElement; 144 ClassElement elementClass = element.enclosingElement;
146 return _prepareElements().then((_) { 145 // check if there is a member with "newName" in the same ClassElement
147 return Future.forEach(elements, (Element element) { 146 for (Element newNameMember in getChildren(elementClass, newName)) {
148 return searchEngine.searchReferences(element).then((references) { 147 result.addError(
149 this.references.addAll(references); 148 format(
150 }); 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;
151 }); 161 });
152 }).then((_) { 162 }).then((_) {
153 return new RefactoringStatus(); 163 // check shadowing in hierarchy
154 }); 164 return searchEngine.searchElementDeclarations(newName).then((decls) {
155 // _superClasses = getSuperClasses(elementClass); 165 for (SearchMatch decl in decls) {
156 // TODO(scheglov) validate 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);
157 } 211 }
158 212
159 /** 213 /**
160 * Fills [elements] with [Element]s to rename. 214 * Fills [elements] with [Element]s to rename.
161 */ 215 */
162 Future _prepareElements() { 216 Future _prepareElements() {
163 if (element is ClassMemberElement) { 217 if (element is ClassMemberElement) {
164 return getHierarchyMembers( 218 return getHierarchyMembers(
165 searchEngine, 219 searchEngine,
166 element).then((Set<Element> elements) { 220 element).then((Set<Element> elements) {
167 this.elements = elements; 221 this.elements = elements;
168 }); 222 });
169 } else { 223 } else {
170 elements = new Set.from([element]); 224 elements = new Set.from([element]);
171 return new Future.value(); 225 return new Future.value();
172 } 226 }
173 } 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 }
174 } 241 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analysis_services/test/refactoring/rename_class_member_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698