From d804fca4e82310366b59c09cb3ce33d32faafb1a Mon Sep 17 00:00:00 2001 From: Brian Wilkerson Date: Thu, 9 Apr 2026 06:42:00 -0700 Subject: [PATCH] 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 Reviewed-by: Samuel Rawlins --- .../refactoring/legacy/refactoring.dart | 21 +++- .../refactoring/legacy/rename_label.dart | 37 ++++++- .../refactoring/legacy/rename_local.dart | 98 ++++++++++++------- .../refactoring/legacy/rename_parameter.dart | 90 +++++++++++------ 4 files changed, 176 insertions(+), 70 deletions(-) diff --git a/pkg/analysis_server/lib/src/services/refactoring/legacy/refactoring.dart b/pkg/analysis_server/lib/src/services/refactoring/legacy/refactoring.dart index 9246b64e3d0..dc6c25406e8 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/legacy/refactoring.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/legacy/refactoring.dart @@ -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( diff --git a/pkg/analysis_server/lib/src/services/refactoring/legacy/rename_label.dart b/pkg/analysis_server/lib/src/services/refactoring/legacy/rename_label.dart index 12b657c1ae9..98e86cf3382 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/legacy/rename_label.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/legacy/rename_label.dart @@ -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 buildChange({required ChangeBuilder builder}) async { + var processor = RenameProcessor2( + workspace, + sessionHelper, + builder, + newName, + ); + return await processor.renameElement(element); + } + @override Future checkFinalConditions() { var result = RefactoringStatus(); @@ -35,9 +55,20 @@ class RenameLabelRefactoringImpl extends RenameRefactoringImpl { return result; } + @override + Future 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 fillChange() { - var processor = RenameProcessor(workspace, sessionHelper, change, newName); - return processor.renameElement(element); + throw UnsupportedError('This method should never be called.'); } } diff --git a/pkg/analysis_server/lib/src/services/refactoring/legacy/rename_local.dart b/pkg/analysis_server/lib/src/services/refactoring/legacy/rename_local.dart index 17abd95b950..bbcc7decf2b 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/legacy/rename_local.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/legacy/rename_local.dart @@ -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 { final RefactoringStatus result; @@ -123,11 +126,17 @@ class ConflictValidatorVisitor extends RecursiveAstVisitor { /// 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 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() + .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 checkFinalConditions() async { var result = RefactoringStatus(); @@ -168,40 +218,20 @@ class RenameLocalRefactoringImpl extends RenameRefactoringImpl { } @override - Future fillChange() async { - var processor = RenameProcessor(workspace, sessionHelper, change, newName); + Future 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() - .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 fillChange() { + throw UnsupportedError('This method should never be called.'); } } diff --git a/pkg/analysis_server/lib/src/services/refactoring/legacy/rename_parameter.dart b/pkg/analysis_server/lib/src/services/refactoring/legacy/rename_parameter.dart index e7e54a46503..86129b37244 100644 --- a/pkg/analysis_server/lib/src/services/refactoring/legacy/rename_parameter.dart +++ b/pkg/analysis_server/lib/src/services/refactoring/legacy/rename_parameter.dart @@ -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 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 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 checkFinalConditions() async { var result = RefactoringStatus(); @@ -91,36 +137,20 @@ class RenameParameterRefactoringImpl extends RenameRefactoringImpl { } @override - Future 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 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 fillChange() { + throw UnsupportedError('This method should never be called.'); } /// Fills [elements] with [Element]s to rename.