| 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}';
|
| }
|
|
|