Convert more pieces of the rename refactor

This converts three more of the rename classes to use a ChangeBuilder.
There are still several more to come.

Change-Id: Ie03a356855a7ec1bbe602ab9ac824b10dc46834a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/494000
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
Brian Wilkerson
2026-04-09 06:42:00 -07:00
committed by Commit Queue
parent 85991680ac
commit d804fca4e8
4 changed files with 176 additions and 70 deletions
@@ -494,7 +494,12 @@ abstract class RenameRefactoring implements Refactoring {
);
}
if (element is LabelElement) {
return RenameLabelRefactoringImpl(workspace, sessionHelper, element);
return RenameLabelRefactoringImpl(
workspace,
sessionHelper,
resolvedUnit,
element,
);
}
if (element is LibraryElement) {
return RenameLibraryRefactoringImpl(workspace, sessionHelper, element);
@@ -511,10 +516,20 @@ abstract class RenameRefactoring implements Refactoring {
}
}
if (element is FormalParameterElement) {
return RenameParameterRefactoringImpl(workspace, sessionHelper, element);
return RenameParameterRefactoringImpl(
workspace,
sessionHelper,
resolvedUnit,
element,
);
}
if (element is LocalElement) {
return RenameLocalRefactoringImpl(workspace, sessionHelper, element);
return RenameLocalRefactoringImpl(
workspace,
sessionHelper,
resolvedUnit,
element,
);
}
if (element is TypeParameterElement) {
return RenameTypeParameterRefactoringImpl(
@@ -6,15 +6,25 @@ import 'package:analysis_server/src/services/correction/status.dart';
import 'package:analysis_server/src/services/refactoring/legacy/naming_conventions.dart';
import 'package:analysis_server/src/services/refactoring/legacy/refactoring.dart';
import 'package:analysis_server/src/services/refactoring/legacy/rename.dart';
import 'package:analysis_server_plugin/edit/correction_utils.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
/// A [Refactoring] for renaming [LabelElement]s.
class RenameLabelRefactoringImpl extends RenameRefactoringImpl {
final ResolvedUnitResult resolvedUnit;
final CorrectionUtils utils;
RenameLabelRefactoringImpl(
super.workspace,
super.sessionHelper,
this.resolvedUnit,
LabelElement super.element,
) : super();
) : utils = CorrectionUtils(resolvedUnit),
super();
@override
LabelElement get element => super.element as LabelElement;
@@ -22,6 +32,16 @@ class RenameLabelRefactoringImpl extends RenameRefactoringImpl {
@override
String get refactoringName => 'Rename Label';
Future<void> buildChange({required ChangeBuilder builder}) async {
var processor = RenameProcessor2(
workspace,
sessionHelper,
builder,
newName,
);
return await processor.renameElement(element);
}
@override
Future<RefactoringStatus> checkFinalConditions() {
var result = RefactoringStatus();
@@ -35,9 +55,20 @@ class RenameLabelRefactoringImpl extends RenameRefactoringImpl {
return result;
}
@override
Future<SourceChange> createChange({ChangeBuilder? builder}) async {
builder ??= ChangeBuilder(
session: resolvedUnit.session,
defaultEol: utils.endOfLine,
);
await buildChange(builder: builder);
var sourceChange = builder.sourceChange;
sourceChange.message = "$refactoringName '$oldName' to '$newName'";
return sourceChange;
}
@override
Future<void> fillChange() {
var processor = RenameProcessor(workspace, sessionHelper, change, newName);
return processor.renameElement(element);
throw UnsupportedError('This method should never be called.');
}
}
@@ -11,6 +11,8 @@ import 'package:analysis_server/src/services/refactoring/legacy/refactoring.dart
import 'package:analysis_server/src/services/refactoring/legacy/rename.dart';
import 'package:analysis_server/src/services/refactoring/legacy/visible_ranges_computer.dart';
import 'package:analysis_server/src/services/search/hierarchy.dart';
import 'package:analysis_server_plugin/edit/correction_utils.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
@@ -18,6 +20,7 @@ import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
class ConflictValidatorVisitor extends RecursiveAstVisitor<void> {
final RefactoringStatus result;
@@ -123,11 +126,17 @@ class ConflictValidatorVisitor extends RecursiveAstVisitor<void> {
/// A [Refactoring] for renaming [LocalElement]s (excluding
/// [FormalParameterElement]s).
class RenameLocalRefactoringImpl extends RenameRefactoringImpl {
final ResolvedUnitResult resolvedUnit;
final CorrectionUtils utils;
RenameLocalRefactoringImpl(
super.workspace,
super.sessionHelper,
this.resolvedUnit,
LocalElement super.element,
) : super();
) : utils = CorrectionUtils(resolvedUnit),
super();
@override
LocalElement get element => super.element as LocalElement;
@@ -140,6 +149,47 @@ class RenameLocalRefactoringImpl extends RenameRefactoringImpl {
return 'Rename Local Variable';
}
Future<void> buildChange({required ChangeBuilder builder}) async {
var processor = RenameProcessor2(
workspace,
sessionHelper,
builder,
newName,
);
var element = this.element;
if (element is PatternVariableElement) {
var rootVariable =
(element.firstFragment as PatternVariableFragmentImpl).rootVariable;
var declaredFragments = rootVariable is JoinPatternVariableFragmentImpl
? rootVariable.transitiveVariables
.whereType<BindPatternVariableFragmentImpl>()
.toList()
: [element.firstFragment];
for (var declaredFragment in declaredFragments) {
await processor.addDeclarationEdit(declaredFragment.element);
if (declaredFragment is BindPatternVariableFragmentImpl) {
// If a variable is used to resolve a named field with an implicit
// name, we need to make the field name explicit.
var fieldName = declaredFragment.node.fieldNameWithImplicitName;
if (fieldName != null) {
await processor.replace(
referenceElement: element,
offset: fieldName.colon.offset,
length: 0,
code: element.name!,
);
}
}
}
} else {
await processor.addDeclarationEdit(element);
}
var references = await searchEngine.searchReferences(element);
await processor.addReferenceEdits(references);
}
@override
Future<RefactoringStatus> checkFinalConditions() async {
var result = RefactoringStatus();
@@ -168,40 +218,20 @@ class RenameLocalRefactoringImpl extends RenameRefactoringImpl {
}
@override
Future<void> fillChange() async {
var processor = RenameProcessor(workspace, sessionHelper, change, newName);
Future<SourceChange> createChange({ChangeBuilder? builder}) async {
builder ??= ChangeBuilder(
session: resolvedUnit.session,
defaultEol: utils.endOfLine,
);
await buildChange(builder: builder);
var sourceChange = builder.sourceChange;
sourceChange.message = "$refactoringName '$oldName' to '$newName'";
return sourceChange;
}
var element = this.element;
if (element is PatternVariableElement) {
var rootVariable =
(element.firstFragment as PatternVariableFragmentImpl).rootVariable;
var declaredFragments = rootVariable is JoinPatternVariableFragmentImpl
? rootVariable.transitiveVariables
.whereType<BindPatternVariableFragmentImpl>()
.toList()
: [element.firstFragment];
for (var declaredFragment in declaredFragments) {
processor.addDeclarationEdit(declaredFragment.element);
if (declaredFragment is BindPatternVariableFragmentImpl) {
// If a variable is used to resolve a named field with an implicit
// name, we need to make the field name explicit.
var fieldName = declaredFragment.node.fieldNameWithImplicitName;
if (fieldName != null) {
processor.replace(
referenceElement: element,
offset: fieldName.colon.offset,
length: 0,
code: element.name!,
);
}
}
}
} else {
processor.addDeclarationEdit(element);
}
var references = await searchEngine.searchReferences(element);
processor.addReferenceEdits(references);
@override
Future<void> fillChange() {
throw UnsupportedError('This method should never be called.');
}
}
@@ -9,20 +9,29 @@ import 'package:analysis_server/src/services/refactoring/legacy/rename.dart';
import 'package:analysis_server/src/services/refactoring/legacy/rename_local.dart';
import 'package:analysis_server/src/services/refactoring/legacy/visible_ranges_computer.dart';
import 'package:analysis_server/src/services/search/hierarchy.dart';
import 'package:analysis_server_plugin/edit/correction_utils.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/element/element.dart' as analyzer;
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
/// A [Refactoring] for renaming [analyzer.FormalParameterElement]s.
class RenameParameterRefactoringImpl extends RenameRefactoringImpl {
final ResolvedUnitResult resolvedUnit;
final CorrectionUtils utils;
List<analyzer.FormalParameterElement> elements = [];
bool _renameAllPositionalOccurrences = false;
RenameParameterRefactoringImpl(
super.workspace,
super.sessionHelper,
this.resolvedUnit,
analyzer.FormalParameterElement super.element,
) : super();
) : utils = CorrectionUtils(resolvedUnit),
super();
@override
analyzer.FormalParameterElement get element =>
@@ -33,6 +42,43 @@ class RenameParameterRefactoringImpl extends RenameRefactoringImpl {
return 'Rename Parameter';
}
Future<void> buildChange({required ChangeBuilder builder}) async {
var processor = RenameProcessor2(
workspace,
sessionHelper,
builder,
newName,
);
for (var element in elements) {
if (element != this.element &&
element.isPositional &&
!_renameAllPositionalOccurrences) {
continue;
}
var fieldRenamed = false;
if (element is analyzer.FieldFormalParameterElement) {
var field = element.field;
if (field != null) {
await processor.renameElement(field);
fieldRenamed = true;
}
}
if (!fieldRenamed) {
await processor.addDeclarationEdit(element);
}
var references = await searchEngine.searchReferences(element);
// Named super formals are already in [elements].
// Positional super formals are not tied by name so shouldn't be renamed.
references.removeWhere(
(match) => match.element is analyzer.SuperFormalParameterElement,
);
await processor.addReferenceEdits(references);
}
}
@override
Future<RefactoringStatus> checkFinalConditions() async {
var result = RefactoringStatus();
@@ -91,36 +137,20 @@ class RenameParameterRefactoringImpl extends RenameRefactoringImpl {
}
@override
Future<void> fillChange() async {
var processor = RenameProcessor(workspace, sessionHelper, change, newName);
for (var element in elements) {
if (element != this.element &&
element.isPositional &&
!_renameAllPositionalOccurrences) {
continue;
}
var fieldRenamed = false;
if (element is analyzer.FieldFormalParameterElement) {
var field = element.field;
if (field != null) {
await processor.renameElement(field);
fieldRenamed = true;
}
}
Future<SourceChange> createChange({ChangeBuilder? builder}) async {
builder ??= ChangeBuilder(
session: resolvedUnit.session,
defaultEol: utils.endOfLine,
);
await buildChange(builder: builder);
var sourceChange = builder.sourceChange;
sourceChange.message = "$refactoringName '$oldName' to '$newName'";
return sourceChange;
}
if (!fieldRenamed) {
processor.addDeclarationEdit(element);
}
var references = await searchEngine.searchReferences(element);
// Named super formals are already in [elements].
// Positional super formals are not tied by name so shouldn't be renamed.
references.removeWhere(
(match) => match.element is analyzer.SuperFormalParameterElement,
);
processor.addReferenceEdits(references);
}
@override
Future<void> fillChange() {
throw UnsupportedError('This method should never be called.');
}
/// Fills [elements] with [Element]s to rename.