Implement rename method for Cider
Change-Id: I48d65146b9a7f1687f9afc437aebae3aaa6f533b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/218785
Commit-Queue: Keerti Parthasarathy <keertip@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analysis_server/lib/src/cider/rename.dart b/pkg/analysis_server/lib/src/cider/rename.dart
index 6ff6528..0aa1a3f 100644
--- a/pkg/analysis_server/lib/src/cider/rename.dart
+++ b/pkg/analysis_server/lib/src/cider/rename.dart
@@ -14,17 +14,46 @@
class CanRenameResponse {
final LineInfo lineInfo;
final RenameRefactoringElement refactoringElement;
- final String oldName;
+ final FileResolver _fileResolver;
+ final String filePath;
- CanRenameResponse(this.lineInfo, this.refactoringElement, this.oldName);
+ CanRenameResponse(this.lineInfo, this.refactoringElement, this._fileResolver,
+ this.filePath);
+
+ String get oldName => refactoringElement.element.displayName;
+
+ CheckNameResponse? checkNewName(String name) {
+ var element = refactoringElement.element;
+ RefactoringStatus? status;
+ if (element is LocalVariableElement) {
+ status = validateVariableName(name);
+ } else if (element is ParameterElement) {
+ status = validateParameterName(name);
+ } else if (element is FunctionElement) {
+ status = validateFunctionName(name);
+ }
+ if (status == null) {
+ return null;
+ }
+ return CheckNameResponse(status, this);
+ }
}
class CheckNameResponse {
- final LineInfo lineInfo;
final RefactoringStatus status;
- final String oldName;
+ final CanRenameResponse canRename;
- CheckNameResponse(this.lineInfo, this.status, this.oldName);
+ CheckNameResponse(this.status, this.canRename);
+
+ LineInfo get lineInfo => canRename.lineInfo;
+
+ String get oldName => canRename.refactoringElement.element.displayName;
+
+ RenameResponse? computeRenameRanges() {
+ var matches = canRename._fileResolver.findReferences(
+ canRename.refactoringElement.offset, canRename.filePath);
+ return RenameResponse(matches, this);
+ }
}
class CiderRenameComputer {
@@ -56,11 +85,12 @@
}
var refactoring = RenameRefactoring.getElementToRename(node, element);
if (refactoring != null) {
- return CanRenameResponse(lineInfo, refactoring, element.displayName);
+ return CanRenameResponse(lineInfo, refactoring, _fileResolver, filePath);
}
return null;
}
+ @deprecated
CheckNameResponse? checkNewName(
String filePath, int line, int column, String name) {
var resolvedUnit = _fileResolver.resolve(path: filePath);
@@ -74,6 +104,10 @@
return null;
}
+ var refactoring = RenameRefactoring.getElementToRename(node, element);
+ if (refactoring == null) {
+ return null;
+ }
RefactoringStatus? status;
if (element is LocalVariableElement) {
status = validateVariableName(name);
@@ -85,7 +119,9 @@
if (status == null) {
return null;
}
- return CheckNameResponse(lineInfo, status, element.displayName);
+
+ return CheckNameResponse(status,
+ CanRenameResponse(lineInfo, refactoring, _fileResolver, filePath));
}
bool _canRenameElement(Element element) {
@@ -103,3 +139,10 @@
return false;
}
}
+
+class RenameResponse {
+ final List<CiderSearchMatch> matches;
+ final CheckNameResponse checkName;
+
+ RenameResponse(this.matches, this.checkName);
+}
diff --git a/pkg/analysis_server/test/src/cider/rename_test.dart b/pkg/analysis_server/test/src/cider/rename_test.dart
index 028aaea..1a70bf4 100644
--- a/pkg/analysis_server/test/src/cider/rename_test.dart
+++ b/pkg/analysis_server/test/src/cider/rename_test.dart
@@ -4,6 +4,7 @@
import 'package:analysis_server/src/cider/rename.dart';
import 'package:analyzer/source/line_info.dart';
+import 'package:analyzer/src/dart/micro/resolve_file.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -29,7 +30,6 @@
}
''');
- expect(refactor, isNotNull);
expect(refactor!.refactoringElement.element.name, 'bar');
expect(refactor.refactoringElement.offset, _correctionContext.offset);
}
@@ -40,7 +40,6 @@
}
''');
- expect(refactor, isNotNull);
expect(refactor!.refactoringElement.element.name, 'foo');
expect(refactor.refactoringElement.offset, _correctionContext.offset);
}
@@ -68,7 +67,6 @@
}
''');
- expect(refactor, isNotNull);
expect(refactor!.refactoringElement.element.name, 'a');
expect(refactor.refactoringElement.offset, _correctionContext.offset);
}
@@ -80,7 +78,6 @@
}
''');
- expect(refactor, isNotNull);
expect(refactor!.refactoringElement.element.name, 'foo');
expect(refactor.refactoringElement.offset, _correctionContext.offset);
}
@@ -112,9 +109,8 @@
int ^foo() => 2;
''', 'bar');
- expect(result, isNotNull);
- expect(result?.status.problems.length, 0);
- expect(result?.oldName, 'foo');
+ expect(result!.status.problems.length, 0);
+ expect(result.oldName, 'foo');
}
void test_checkName_local() {
@@ -124,9 +120,8 @@
}
''', 'bar');
- expect(result, isNotNull);
- expect(result?.status.problems.length, 0);
- expect(result?.oldName, 'a');
+ expect(result!.status.problems.length, 0);
+ expect(result.oldName, 'a');
}
void test_checkName_local_invalid() {
@@ -136,9 +131,8 @@
}
''', 'Aa');
- expect(result, isNotNull);
- expect(result?.status.problems.length, 1);
- expect(result?.oldName, 'a');
+ expect(result!.status.problems.length, 1);
+ expect(result.oldName, 'a');
}
void test_checkName_parameter() {
@@ -148,9 +142,57 @@
}
''', 'bar');
- expect(result, isNotNull);
- expect(result?.status.problems.length, 0);
- expect(result?.oldName, 'a');
+ expect(result!.status.problems.length, 0);
+ expect(result.oldName, 'a');
+ }
+
+ void test_rename_local() {
+ var result = _rename(r'''
+void foo() {
+ var ^a = 0; var b = a + 1;
+}
+''', 'bar');
+
+ expect(result!.matches.length, 1);
+ expect(
+ result.matches[0],
+ CiderSearchMatch('/workspace/dart/test/lib/test.dart',
+ [CharacterLocation(2, 7), CharacterLocation(2, 22)]));
+ }
+
+ void test_rename_method() {
+ var a = newFile('/workspace/dart/test/lib/a.dart', content: r'''
+void foo() {
+ a;
+}
+''');
+ fileResolver.resolve(path: a.path);
+
+ var result = _rename(r'''
+import 'a.dart';
+
+main() {
+^foo();
+}
+''', 'bar');
+
+ expect(result!.matches.length, 2);
+ expect(result.matches, [
+ CiderSearchMatch(
+ '/workspace/dart/test/lib/a.dart', [CharacterLocation(1, 6)]),
+ CiderSearchMatch(
+ '/workspace/dart/test/lib/test.dart', [CharacterLocation(4, 1)])
+ ]);
+ }
+
+ void test_rename_parameter() {
+ var result = _rename(r'''
+void foo(String ^a) {
+ var b = a + 1;
+}
+''', 'bar');
+ expect(result!.matches.length, 1);
+ expect(result.checkName.oldName, 'a');
}
CheckNameResponse? _checkName(String content, String newName) {
@@ -158,12 +200,13 @@
return CiderRenameComputer(
fileResolver,
- ).checkNewName(
- convertPath(testPath),
- _correctionContext.line,
- _correctionContext.character,
- newName,
- );
+ )
+ .canRename(
+ convertPath(testPath),
+ _correctionContext.line,
+ _correctionContext.character,
+ )
+ ?.checkNewName(newName);
}
CanRenameResponse? _compute(String content) {
@@ -178,6 +221,21 @@
);
}
+ RenameResponse? _rename(String content, newName) {
+ _updateFile(content);
+
+ return CiderRenameComputer(
+ fileResolver,
+ )
+ .canRename(
+ convertPath(testPath),
+ _correctionContext.line,
+ _correctionContext.character,
+ )
+ ?.checkNewName(newName)
+ ?.computeRenameRanges();
+ }
+
void _updateFile(String content) {
var offset = content.indexOf('^');
expect(offset, isPositive, reason: 'Expected to find ^');
diff --git a/pkg/analyzer/lib/source/line_info.dart b/pkg/analyzer/lib/source/line_info.dart
index 1867017..b552a35 100644
--- a/pkg/analyzer/lib/source/line_info.dart
+++ b/pkg/analyzer/lib/source/line_info.dart
@@ -17,6 +17,12 @@
CharacterLocation(this.lineNumber, this.columnNumber);
@override
+ bool operator ==(Object object) =>
+ object is CharacterLocation &&
+ lineNumber == object.lineNumber &&
+ columnNumber == object.columnNumber;
+
+ @override
String toString() => '$lineNumber:$columnNumber';
}
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 89c1fe0..b9fb939 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -9,6 +9,7 @@
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
import 'package:analyzer/src/context/packages.dart';
import 'package:analyzer/src/dart/analysis/context_root.dart';
@@ -46,19 +47,20 @@
class CiderSearchMatch {
final String path;
- final List<int> offsets;
+ final List<CharacterLocation?> startPositions;
- CiderSearchMatch(this.path, this.offsets);
+ CiderSearchMatch(this.path, this.startPositions);
@override
bool operator ==(Object object) =>
object is CiderSearchMatch &&
path == object.path &&
- const ListEquality<int>().equals(offsets, object.offsets);
+ const ListEquality<CharacterLocation?>()
+ .equals(startPositions, object.startPositions);
@override
String toString() {
- return '($path, $offsets)';
+ return '($path, $startPositions)';
}
}
@@ -202,7 +204,9 @@
resolved.unit.accept(collector);
var offsets = collector.offsets;
if (offsets.isNotEmpty) {
- references.add(CiderSearchMatch(filePath, offsets));
+ var lineInfo = resolved.unit.lineInfo;
+ references.add(CiderSearchMatch(filePath,
+ offsets.map((offset) => lineInfo?.getLocation(offset)).toList()));
}
});
}
diff --git a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
index 7a04577..52861ce 100644
--- a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
+++ b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:analyzer/src/dart/micro/cider_byte_store.dart';
import 'package:analyzer/src/dart/micro/library_graph.dart';
@@ -392,8 +393,8 @@
await resolveFile(bPath);
var result = fileResolver.findReferences(6, aPath);
var expected = <CiderSearchMatch>[
- CiderSearchMatch(aPath, [6]),
- CiderSearchMatch(bPath, [42])
+ CiderSearchMatch(bPath, [CharacterLocation(4, 11)]),
+ CiderSearchMatch(aPath, [CharacterLocation(1, 7)])
];
expect(result, unorderedEquals(expected));
}
@@ -413,7 +414,8 @@
await resolveFile(aPath);
var result = fileResolver.findReferences(16, aPath);
var expected = <CiderSearchMatch>[
- CiderSearchMatch(aPath, [16, 53])
+ CiderSearchMatch(
+ aPath, [CharacterLocation(2, 7), CharacterLocation(5, 5)])
];
expect(result, unorderedEquals(expected));
}
@@ -431,7 +433,8 @@
await resolveFile(aPath);
var result = fileResolver.findReferences(11, aPath);
var expected = <CiderSearchMatch>[
- CiderSearchMatch(aPath, [11, 28])
+ CiderSearchMatch(
+ aPath, [CharacterLocation(2, 3), CharacterLocation(5, 1)])
];
expect(result, unorderedEquals(expected));
}
@@ -456,8 +459,8 @@
await resolveFile(bPath);
var result = fileResolver.findReferences(20, aPath);
var expected = <CiderSearchMatch>[
- CiderSearchMatch(aPath, [20]),
- CiderSearchMatch(bPath, [56])
+ CiderSearchMatch(bPath, [CharacterLocation(5, 15)]),
+ CiderSearchMatch(aPath, [CharacterLocation(2, 11)])
];
expect(result, unorderedEquals(expected));
}
@@ -475,7 +478,8 @@
await resolveFile(aPath);
var result = fileResolver.findReferences(39, aPath);
var expected = <CiderSearchMatch>[
- CiderSearchMatch(aPath, [39, 62])
+ CiderSearchMatch(
+ aPath, [CharacterLocation(3, 9), CharacterLocation(4, 11)])
];
expect(result, unorderedEquals(expected));
}
@@ -507,8 +511,9 @@
await resolveFile(bPath);
var result = fileResolver.findReferences(17, aPath);
var expected = <CiderSearchMatch>[
- CiderSearchMatch(aPath, [17, 68]),
- CiderSearchMatch(bPath, [46])
+ CiderSearchMatch(bPath, [CharacterLocation(5, 5)]),
+ CiderSearchMatch(
+ aPath, [CharacterLocation(2, 8), CharacterLocation(7, 4)])
];
expect(result, unorderedEquals(expected));
}
@@ -533,8 +538,8 @@
await resolveFile(bPath);
var result = fileResolver.findReferences(21, aPath);
var expected = <CiderSearchMatch>[
- CiderSearchMatch(aPath, [21]),
- CiderSearchMatch(bPath, [46])
+ CiderSearchMatch(bPath, [CharacterLocation(5, 5)]),
+ CiderSearchMatch(aPath, [CharacterLocation(2, 12)])
];
expect(result, unorderedEquals(expected));
}
@@ -560,8 +565,8 @@
await resolveFile(bPath);
var result = fileResolver.findReferences(19, aPath);
var expected = <CiderSearchMatch>[
- CiderSearchMatch(aPath, [19]),
- CiderSearchMatch(bPath, [39])
+ CiderSearchMatch(bPath, [CharacterLocation(4, 13)]),
+ CiderSearchMatch(aPath, [CharacterLocation(3, 9)])
];
expect(result, unorderedEquals(expected));
}
@@ -587,8 +592,8 @@
await resolveFile(bPath);
var result = fileResolver.findReferences(20, aPath);
var expected = <CiderSearchMatch>[
- CiderSearchMatch(aPath, [20]),
- CiderSearchMatch(bPath, [29])
+ CiderSearchMatch(bPath, [CharacterLocation(4, 3)]),
+ CiderSearchMatch(aPath, [CharacterLocation(3, 10)])
];
expect(result, unorderedEquals(expected));
}
@@ -607,7 +612,8 @@
await resolveFile(aPath);
var result = fileResolver.findReferences(10, aPath);
var expected = <CiderSearchMatch>[
- CiderSearchMatch(aPath, [10, 43])
+ CiderSearchMatch(
+ aPath, [CharacterLocation(1, 11), CharacterLocation(4, 11)])
];
expect(result, unorderedEquals(expected));
}
@@ -624,12 +630,16 @@
await resolveFile(aPath);
var result = fileResolver.findReferences(10, aPath);
var expected = <CiderSearchMatch>[
- CiderSearchMatch(aPath, [10, 22, 40])
+ CiderSearchMatch(aPath, [
+ CharacterLocation(1, 11),
+ CharacterLocation(2, 8),
+ CharacterLocation(4, 12)
+ ])
];
expect(result.map((e) => e.path),
unorderedEquals(expected.map((e) => e.path)));
- expect(result.map((e) => e.offsets),
- unorderedEquals(expected.map((e) => e.offsets)));
+ expect(result.map((e) => e.startPositions),
+ unorderedEquals(expected.map((e) => e.startPositions)));
}
test_findReferences_typedef() async {
@@ -648,8 +658,8 @@
await resolveFile(bPath);
var result = fileResolver.findReferences(8, aPath);
var expected = <CiderSearchMatch>[
- CiderSearchMatch(aPath, [8]),
- CiderSearchMatch(bPath, [25])
+ CiderSearchMatch(bPath, [CharacterLocation(3, 8)]),
+ CiderSearchMatch(aPath, [CharacterLocation(1, 9)])
];
expect(result, unorderedEquals(expected));
}