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

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

Issue 592123002: Move SourceReference, extract duplicate code. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 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; 5 library services.src.refactoring.rename;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:collection';
9 8
10 import 'package:analysis_server/src/protocol.dart' hide Element; 9 import 'package:analysis_server/src/protocol.dart' hide Element;
11 import 'package:analysis_server/src/services/correction/source_range.dart'; 10 import 'package:analysis_server/src/services/correction/source_range.dart';
12 import 'package:analysis_server/src/services/correction/status.dart'; 11 import 'package:analysis_server/src/services/correction/status.dart';
13 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; 12 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
14 import 'package:analysis_server/src/services/refactoring/refactoring_internal.da rt'; 13 import 'package:analysis_server/src/services/refactoring/refactoring_internal.da rt';
15 import 'package:analysis_server/src/services/search/search_engine.dart'; 14 import 'package:analysis_server/src/services/search/search_engine.dart';
16 import 'package:analyzer/src/generated/element.dart'; 15 import 'package:analyzer/src/generated/element.dart';
17 import 'package:analyzer/src/generated/engine.dart'; 16 import 'package:analyzer/src/generated/engine.dart';
18 import 'package:analyzer/src/generated/source.dart'; 17 import 'package:analyzer/src/generated/source.dart';
19 18
20 19
21 /** 20 /**
22 * Returns the [Edit] to replace the given [SearchMatch] reference.
23 */
24 SourceEdit createReferenceEdit(SourceReference reference, String newText,
25 {String id}) {
26 return new SourceEdit.range(reference.range, newText, id: id);
27 }
28
29
30 /**
31 * Returns the file containing declaration of the given [Element].
32 */
33 String getElementFile(Element element) {
34 return element.source.fullName;
35 }
36
37
38 /**
39 * When a [Source] (a file) is used in more than one context, [SearchEngine]
40 * will return separate [SearchMatch]s for each context. But in rename
41 * refactorings we want to update each [Source] only once.
42 */
43 List<SourceReference> getSourceReferences(List<SearchMatch> matches) {
44 var uniqueReferences = new HashMap<SourceReference, SourceReference>();
45 for (SearchMatch match in matches) {
46 Element element = match.element;
47 String file = getElementFile(element);
48 SourceRange range = match.sourceRange;
49 SourceReference newReference =
50 new SourceReference(file, range, element, match.isResolved, match.isQual ified);
51 SourceReference oldReference = uniqueReferences[newReference];
52 if (oldReference == null) {
53 uniqueReferences[newReference] = newReference;
54 oldReference = newReference;
55 }
56 }
57 return uniqueReferences.keys.toList();
58 }
59
60
61 /**
62 * Returns `true` if two given [Element]s are [LocalElement]s and have 21 * Returns `true` if two given [Element]s are [LocalElement]s and have
63 * intersecting with visibility ranges. 22 * intersecting with visibility ranges.
64 */ 23 */
65 bool haveIntersectingRanges(LocalElement localElement, Element element) { 24 bool haveIntersectingRanges(LocalElement localElement, Element element) {
66 if (element is! LocalElement) { 25 if (element is! LocalElement) {
67 return false; 26 return false;
68 } 27 }
69 LocalElement localElement2 = element as LocalElement; 28 LocalElement localElement2 = element as LocalElement;
70 Source localSource = localElement.source; 29 Source localSource = localElement.source;
71 Source localSource2 = localElement2.source; 30 Source localSource2 = localElement2.source;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 * An abstract implementation of [RenameRefactoring]. 108 * An abstract implementation of [RenameRefactoring].
150 */ 109 */
151 abstract class RenameRefactoringImpl extends RefactoringImpl implements 110 abstract class RenameRefactoringImpl extends RefactoringImpl implements
152 RenameRefactoring { 111 RenameRefactoring {
153 final SearchEngine searchEngine; 112 final SearchEngine searchEngine;
154 final Element element; 113 final Element element;
155 final AnalysisContext context; 114 final AnalysisContext context;
156 final String elementKindName; 115 final String elementKindName;
157 final String oldName; 116 final String oldName;
158 117
118 SourceChange change;
119
159 String newName; 120 String newName;
160 121
161 RenameRefactoringImpl(SearchEngine searchEngine, Element element) 122 RenameRefactoringImpl(SearchEngine searchEngine, Element element)
162 : searchEngine = searchEngine, 123 : searchEngine = searchEngine,
163 element = element, 124 element = element,
164 context = element.context, 125 context = element.context,
165 elementKindName = element.kind.displayName, 126 elementKindName = element.kind.displayName,
166 oldName = _getDisplayName(element); 127 oldName = _getDisplayName(element);
167 128
168 /** 129 /**
169 * Adds the "Update declaration" [Edit] to [change]. 130 * Adds a [SourceEdit] to update [element] name to [change].
170 */ 131 */
171 void addDeclarationEdit(SourceChange change, Element element) { 132 void addDeclarationEdit(Element element) {
172 if (element != null) { 133 if (element != null) {
173 SourceEdit edit = 134 SourceRange range = rangeElementName(element);
174 new SourceEdit.range(rangeElementName(element), newName); 135 SourceEdit edit = new SourceEdit.range(range, newName);
175 change.addElementEdit(element, edit); 136 change.addElementEdit(element, edit);
176 } 137 }
177 } 138 }
178 139
179 /** 140 /**
180 * Adds an "Update reference" [Edit] to [change]. 141 * Adds [SourceEdit]s to update [matches] to [change].
181 */ 142 */
182 void addReferenceEdit(SourceChange change, SourceReference reference) { 143 void addReferenceEdits(List<SearchMatch> matches) {
183 SourceEdit edit = createReferenceEdit(reference, newName); 144 List<SourceReference> references = getSourceReferences(matches);
184 change.addElementEdit(reference.element, edit); 145 for (SourceReference reference in references) {
146 reference.addEdit(change, newName);
147 }
185 } 148 }
186 149
187 @override 150 @override
188 Future<RefactoringStatus> checkInitialConditions() { 151 Future<RefactoringStatus> checkInitialConditions() {
189 var result = new RefactoringStatus(); 152 RefactoringStatus result = new RefactoringStatus();
190 return new Future.value(result); 153 return new Future.value(result);
191 } 154 }
192 155
193 @override 156 @override
194 RefactoringStatus checkNewName() { 157 RefactoringStatus checkNewName() {
195 RefactoringStatus result = new RefactoringStatus(); 158 RefactoringStatus result = new RefactoringStatus();
196 if (newName == oldName) { 159 if (newName == oldName) {
197 result.addFatalError( 160 result.addFatalError(
198 "The new name must be different than the current name."); 161 "The new name must be different than the current name.");
199 } 162 }
200 return result; 163 return result;
201 } 164 }
202 165
203 @override 166 @override
167 Future<SourceChange> createChange() {
168 change = new SourceChange(refactoringName);
169 return fillChange().then((_) => change);
170 }
171
172 /**
173 * Adds individual edits to [change].
174 */
175 Future fillChange();
176
177 @override
204 bool requiresPreview() { 178 bool requiresPreview() {
205 return false; 179 return false;
206 } 180 }
207 181
208 static String _getDisplayName(Element element) { 182 static String _getDisplayName(Element element) {
209 if (element is ImportElement) { 183 if (element is ImportElement) {
210 PrefixElement prefix = element.prefix; 184 PrefixElement prefix = element.prefix;
211 if (prefix != null) { 185 if (prefix != null) {
212 return prefix.displayName; 186 return prefix.displayName;
213 } 187 }
214 } 188 }
215 return element.displayName; 189 return element.displayName;
216 } 190 }
217 } 191 }
218
219
220 /**
221 * The [SourceRange] in some [Source].
222 */
223 class SourceReference {
224 final String file;
225 final SourceRange range;
226 final Element element;
227 final bool isResolved;
228 final bool isQualified;
229
230 SourceReference(this.file, this.range, this.element, this.isResolved,
231 this.isQualified);
232
233 @override
234 int get hashCode {
235 int hash = file.hashCode;
236 hash = ((hash << 16) & 0xFFFFFFFF) + range.hashCode;
237 return hash;
238 }
239
240 @override
241 bool operator ==(Object other) {
242 if (identical(other, this)) {
243 return true;
244 }
245 if (other is SourceReference) {
246 return other.file == file && other.range == range;
247 }
248 return false;
249 }
250
251 @override
252 String toString() => '${file}@${range}';
253 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698