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

Side by Side Diff: pkg/analysis_services/lib/src/refactoring/rename.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;
6
7 import 'dart:async';
8 import 'dart:collection';
9
10 import 'package:analysis_services/correction/change.dart';
11 import 'package:analysis_services/correction/status.dart';
12 import 'package:analysis_services/refactoring/refactoring.dart';
13 import 'package:analysis_services/search/search_engine.dart';
14 import 'package:analysis_services/src/correction/source_range.dart';
15 import 'package:analysis_services/src/refactoring/refactoring.dart';
16 import 'package:analyzer/src/generated/element.dart';
17 import 'package:analyzer/src/generated/engine.dart';
18 import 'package:analyzer/src/generated/source.dart';
19
20
21 /**
22 * Returns the [Edit] to replace the given [SearchMatch] reference.
23 */
24 Edit createReferenceEdit(SourceReference reference, String newText) {
25 return new Edit.range(reference.range, newText);
26 }
27
28
29 /**
30 * Returns the file containing declaration of the given [Element].
31 */
32 String getElementFile(Element element) {
33 return element.source.fullName;
34 }
35
36
37 /**
38 * When a [Source] (a file) is used in more than one context, [SearchEngine]
39 * will return separate [SearchMatch]s for each context. But in rename
40 * refactorings we want to update each [Source] only once.
41 */
42 List<SourceReference> getSourceReferences(List<SearchMatch> matches) {
43 var uniqueReferences = new HashMap<SourceReference, SourceReference>();
44 for (SearchMatch match in matches) {
45 Element element = match.element;
46 String file = getElementFile(element);
47 SourceRange range = match.sourceRange;
48 SourceReference newReference =
49 new SourceReference(file, range, element, match.isResolved, match.isQual ified);
50 SourceReference oldReference = uniqueReferences[newReference];
51 if (oldReference == null) {
52 uniqueReferences[newReference] = newReference;
53 oldReference = newReference;
54 }
55 }
56 return uniqueReferences.keys.toList();
57 }
58
59
60 /**
61 * Returns `true` if two given [Element]s are [LocalElement]s and have
62 * intersecting with visibility ranges.
63 */
64 bool haveIntersectingRanges(LocalElement localElement, Element element) {
65 if (element is! LocalElement) {
66 return false;
67 }
68 LocalElement localElement2 = element as LocalElement;
69 Source localSource = localElement.source;
70 Source localSource2 = localElement2.source;
71 SourceRange localRange = localElement.visibleRange;
72 SourceRange localRange2 = localElement2.visibleRange;
73 return localSource2 == localSource &&
74 localRange != null &&
75 localRange2 != null &&
76 localRange2.intersects(localRange);
77 }
78
79
80 /**
81 * Checks if [element] is defined in the library containing [source].
82 */
83 bool isDefinedInLibrary(Element element, AnalysisContext context, Source source)
84 {
85 // should be the same AnalysisContext
86 if (!isInContext(element, context)) {
87 return false;
88 }
89 // private elements are visible only in their library
90 List<Source> librarySourcesOfSource = context.getLibrariesContaining(source);
91 Source librarySourceOfElement = element.library.source;
92 return librarySourcesOfSource.contains(librarySourceOfElement);
93 }
94
95
96 /**
97 * Checks if the given [Element] is in the given [AnalysisContext].
98 */
99 bool isInContext(Element element, AnalysisContext context) {
100 AnalysisContext elementContext = element.context;
101 if (elementContext == context) {
102 return true;
103 }
104 if (context is InstrumentedAnalysisContextImpl) {
105 return elementContext == context.basis;
106 }
107 return false;
108 }
109
110
111 /**
112 * Checks if the given unqualified [SearchMatch] intersects with visibility
113 * range of [localElement].
114 */
115 bool isReferenceInLocalRange(LocalElement localElement, SearchMatch reference) {
116 if (reference.isQualified) {
117 return false;
118 }
119 Source localSource = localElement.source;
120 Source referenceSource = reference.element.source;
121 SourceRange localRange = localElement.visibleRange;
122 SourceRange referenceRange = reference.sourceRange;
123 return referenceSource == localSource &&
124 referenceRange.intersects(localRange);
125 }
126
127
128 /**
129 * Checks if [element] is visible in the library containing [source].
130 */
131 bool isVisibleInLibrary(Element element, AnalysisContext context, Source source)
132 {
133 // should be the same AnalysisContext
134 if (!isInContext(element, context)) {
135 return false;
136 }
137 // public elements are always visible
138 if (element.isPublic) {
139 return true;
140 }
141 // private elements are visible only in their library
142 return isDefinedInLibrary(element, context, source);
143 }
144
145
146
147 /**
148 * An abstract implementation of [RenameRefactoring].
149 */
150 abstract class RenameRefactoringImpl extends RefactoringImpl implements
151 RenameRefactoring {
152 final SearchEngine searchEngine;
153 final Element element;
154 final AnalysisContext context;
155 final String oldName;
156
157 String newName;
158
159 RenameRefactoringImpl(SearchEngine searchEngine, Element element)
160 : searchEngine = searchEngine,
161 element = element,
162 context = element.context,
163 oldName = _getDisplayName(element);
164
165 /**
166 * Adds the "Update declaration" [Edit] to [change].
167 */
168 void addDeclarationEdit(Change change, Element element) {
169 if (element != null) {
170 String file = getElementFile(element);
171 Edit edit = new Edit.range(rangeElementName(element), newName);
172 change.addEdit(file, edit);
173 }
174 }
175
176 /**
177 * Adds an "Update reference" [Edit] to [change].
178 */
179 void addReferenceEdit(Change change, SourceReference reference) {
180 Edit edit = createReferenceEdit(reference, newName);
181 change.addEdit(reference.file, edit);
182 }
183
184 @override
185 Future<RefactoringStatus> checkInitialConditions() {
186 var result = new RefactoringStatus();
187 return new Future.value(result);
188 }
189
190 @override
191 RefactoringStatus checkNewName() {
192 RefactoringStatus result = new RefactoringStatus();
193 if (newName == oldName) {
194 result.addFatalError(
195 "The new name must be different than the current name.");
196 }
197 return result;
198 }
199
200 @override
201 bool requiresPreview() {
202 return false;
203 }
204
205 static String _getDisplayName(Element element) {
206 if (element is ImportElement) {
207 PrefixElement prefix = element.prefix;
208 if (prefix != null) {
209 return prefix.displayName;
210 }
211 }
212 return element.displayName;
213 }
214 }
215
216
217 /**
218 * The [SourceRange] in some [Source].
219 */
220 class SourceReference {
221 final String file;
222 final SourceRange range;
223 final Element element;
224 final bool isResolved;
225 final bool isQualified;
226
227 SourceReference(this.file, this.range, this.element, this.isResolved,
228 this.isQualified);
229
230 @override
231 int get hashCode {
232 int hash = file.hashCode;
233 hash = ((hash << 16) & 0xFFFFFFFF) + range.hashCode;
234 return hash;
235 }
236
237 @override
238 bool operator ==(Object other) {
239 if (identical(other, this)) {
240 return true;
241 }
242 if (other is SourceReference) {
243 return other.file == file && other.range == range;
244 }
245 return false;
246 }
247
248 @override
249 String toString() => '${file}@${range}';
250 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698