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

Unified Diff: pkg/analysis_services/lib/src/refactoring/rename.dart

Issue 465733002: 'Rename Local Variable' refactoring implementation. (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 side-by-side diff with in-line comments
Download patch
Index: pkg/analysis_services/lib/src/refactoring/rename.dart
diff --git a/pkg/analysis_services/lib/src/refactoring/rename.dart b/pkg/analysis_services/lib/src/refactoring/rename.dart
index b637d48867655da8b9a56158b6ed3f93f5ec1cdd..fa60818940c0aaac1857c8b3842933b0fcd46ede 100644
--- a/pkg/analysis_services/lib/src/refactoring/rename.dart
+++ b/pkg/analysis_services/lib/src/refactoring/rename.dart
@@ -7,11 +7,14 @@
library services.src.refactoring.rename;
+import 'dart:async';
+import 'dart:collection';
+
+import 'package:analysis_services/correction/change.dart';
import 'package:analysis_services/correction/status.dart';
import 'package:analysis_services/refactoring/refactoring.dart';
import 'package:analysis_services/search/search_engine.dart';
import 'package:analysis_services/src/correction/source_range.dart';
-import 'package:analysis_services/src/generated/change.dart';
import 'package:analysis_services/src/refactoring/refactoring.dart';
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/engine.dart';
@@ -27,6 +30,37 @@ Edit createReferenceEdit(SourceReference reference, String newText) {
/**
+ * Returns the file containing declaration of the given [Element].
+ */
+String getElementFile(Element element) {
+ return element.source.fullName;
+}
+
+
+/**
+ * When a [Source] (a file) is used in more than one context, [SearchEngine]
+ * will return separate [SearchMatch]s for each context. But in rename
+ * refactorings we want to update each [Source] only once.
+ */
+List<SourceReference> getSourceReferences(List<SearchMatch> matches) {
+ var uniqueReferences = new HashMap<SourceReference, SourceReference>();
+ for (SearchMatch match in matches) {
+ Element element = match.element;
+ MatchKind kind = match.kind;
+ String file = getElementFile(element);
+ SourceRange range = match.sourceRange;
+ SourceReference newReference = new SourceReference(kind, file, range);
+ SourceReference oldReference = uniqueReferences[newReference];
+ if (oldReference == null) {
+ uniqueReferences[newReference] = newReference;
+ oldReference = newReference;
+ }
+ }
+ return uniqueReferences.keys.toList();
+}
+
+
+/**
* Returns `true` if two given [Element]s are [LocalElement]s and have
* intersecting with visibility ranges.
*/
@@ -47,6 +81,22 @@ bool haveIntersectingRanges(LocalElement localElement, Element element) {
/**
+ * Checks if [element] is defined in the library containing [source].
+ */
+bool isDefinedInLibrary(Element element, AnalysisContext context, Source source)
+ {
+ // should be the same AnalysisContext
+ if (!isInContext(element, context)) {
+ return false;
+ }
+ // private elements are visible only in their library
+ List<Source> librarySourcesOfSource = context.getLibrariesContaining(source);
+ Source librarySourceOfElement = element.library.source;
+ return librarySourcesOfSource.contains(librarySourceOfElement);
+}
+
+
+/**
* Checks if the given [Element] is in the given [AnalysisContext].
*/
bool isInContext(Element element, AnalysisContext context) {
@@ -62,18 +112,19 @@ bool isInContext(Element element, AnalysisContext context) {
/**
- * Checks if [element] is defined in the library containing [source].
+ * Checks if the given unqualified [SearchMatch] intersects with visibility
+ * range of [localElement].
*/
-bool isDefinedInLibrary(Element element, AnalysisContext context, Source source)
- {
- // should be the same AnalysisContext
- if (!isInContext(element, context)) {
+bool isReferenceInLocalRange(LocalElement localElement, SearchMatch reference) {
+ if (reference.isQualified) {
return false;
}
- // private elements are visible only in their library
- List<Source> librarySourcesOfSource = context.getLibrariesContaining(source);
- Source librarySourceOfElement = element.library.source;
- return librarySourcesOfSource.contains(librarySourceOfElement);
+ Source localSource = localElement.source;
+ Source referenceSource = reference.element.source;
+ SourceRange localRange = localElement.visibleRange;
+ SourceRange referenceRange = reference.sourceRange;
+ return referenceSource == localSource &&
+ referenceRange.intersects(localRange);
}
@@ -95,22 +146,6 @@ bool isVisibleInLibrary(Element element, AnalysisContext context, Source source)
}
-/**
- * Checks if the given unqualified [SearchMatch] intersects with visibility
- * range of [localElement].
- */
-bool isReferenceInLocalRange(LocalElement localElement, SearchMatch reference) {
- if (reference.isQualified) {
- return false;
- }
- Source localSource = localElement.source;
- Source referenceSource = reference.element.source;
- SourceRange localRange = localElement.visibleRange;
- SourceRange referenceRange = reference.sourceRange;
- return referenceSource == localSource &&
- referenceRange.intersects(localRange);
-}
-
/**
* An abstract implementation of [RenameRefactoring].
@@ -131,24 +166,26 @@ abstract class RenameRefactoringImpl extends RefactoringImpl implements
oldName = _getDisplayName(element);
/**
- * Adds the "Update declaration" [Edit] to [sourceChange].
+ * Adds the "Update declaration" [Edit] to [change].
*/
- void addDeclarationEdit(SourceChange sourceChange, Element element) {
+ void addDeclarationEdit(Change change, Element element) {
+ String file = getElementFile(element);
Edit edit = new Edit.range(rangeElementName(element), newName);
- sourceChange.addEdit(edit, "Update declaration");
+ change.addEdit(file, edit);
}
/**
- * Adds an "Update reference" [Edit] to [sourceChange].
+ * Adds an "Update reference" [Edit] to [change].
*/
- void addReferenceEdit(SourceChange sourceChange, SourceReference reference) {
+ void addReferenceEdit(Change change, SourceReference reference) {
Edit edit = createReferenceEdit(reference, newName);
- sourceChange.addEdit(edit, "Update reference");
+ change.addEdit(reference.file, edit);
}
@override
- RefactoringStatus checkInitialConditions() {
- return new RefactoringStatus();
+ Future<RefactoringStatus> checkInitialConditions() {
+ var result = new RefactoringStatus();
+ return new Future.value(result);
}
@override
@@ -161,6 +198,11 @@ abstract class RenameRefactoringImpl extends RefactoringImpl implements
return result;
}
+ @override
+ bool requiresPreview() {
+ return false;
+ }
+
static String _getDisplayName(Element element) {
if (element is ImportElement) {
PrefixElement prefix = element.prefix;
@@ -178,30 +220,29 @@ abstract class RenameRefactoringImpl extends RefactoringImpl implements
*/
class SourceReference {
final MatchKind kind;
- final Source source;
+ final String file;
final SourceRange range;
- SourceReference(this.kind, this.source, this.range);
+ SourceReference(this.kind, this.file, this.range);
@override
int get hashCode {
- int hash = source.hashCode;
+ int hash = file.hashCode;
hash = ((hash << 16) & 0xFFFFFFFF) + range.hashCode;
return hash;
}
@override
- bool operator ==(Object obj) {
- if (identical(obj, this)) {
+ bool operator ==(Object other) {
+ if (identical(other, this)) {
return true;
}
- if (obj is! SourceReference) {
- return false;
+ if (other is SourceReference) {
+ return other.file == file && other.range == range;
}
- SourceReference other = obj as SourceReference;
- return other.source == source && other.range == range;
+ return false;
}
@override
- String toString() => '${source}@${range}';
+ String toString() => '${file}@${range}';
}

Powered by Google App Engine
This is Rietveld 408576698