Skip to content

Commit 0bc13a8

Browse files
fshcheglovCommit Queue
authored andcommitted
Change rename class member refactoring to allow renaming chained super formal parameters, and renaming field formal parameters to private.
Bug: #60803 Change-Id: I6eab2eaa6d724f7f2c544c6f2bf74e9e73ad31f3 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/442249 Reviewed-by: Brian Wilkerson <[email protected]> Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent a35946c commit 0bc13a8

File tree

4 files changed

+115
-29
lines changed

4 files changed

+115
-29
lines changed

pkg/analysis_server/lib/src/services/refactoring/legacy/rename_class_member.dart

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -103,21 +103,6 @@ class RenameClassMemberRefactoringImpl extends RenameRefactoringImpl {
103103
processor.addDeclarationEdit(renameElement.setter);
104104
} else {
105105
processor.addDeclarationEdit(renameElement);
106-
if (!newName.startsWith('_')) {
107-
var interfaceElement = renameElement.enclosingElement;
108-
if (interfaceElement is InterfaceElement) {
109-
for (var constructor in interfaceElement.constructors) {
110-
for (var parameter in constructor.formalParameters) {
111-
if (parameter is FieldFormalParameterElement &&
112-
parameter.field == renameElement) {
113-
await searchEngine
114-
.searchReferences(parameter)
115-
.then(processor.addReferenceEdits);
116-
}
117-
}
118-
}
119-
}
120-
}
121106
}
122107
}
123108
await _updateReferences();
@@ -201,6 +186,10 @@ class RenameClassMemberRefactoringImpl extends RenameRefactoringImpl {
201186
continue;
202187
}
203188

189+
if (element is FormalParameterElement) {
190+
continue;
191+
}
192+
204193
if (unshadowed.contains(reference.element) &&
205194
reference.element is ExecutableElement) {
206195
await _addThisEdit(reference, newName);
@@ -537,6 +526,30 @@ class _RenameClassMemberValidator extends _BaseClassMemberValidator {
537526
} else {
538527
elements = {element};
539528
}
529+
530+
if (element is FieldElement) {
531+
var interfaceElement = element.enclosingElement;
532+
if (interfaceElement is InterfaceElement &&
533+
interfaceElement is! ExtensionTypeElement) {
534+
var formalParameters =
535+
interfaceElement.constructors
536+
.expand((constructor) => constructor.formalParameters)
537+
.whereType<FieldFormalParameterElement>()
538+
.where((formalParameter) => formalParameter.field == element)
539+
.cast<FormalParameterElement>()
540+
.toList();
541+
542+
// The language doesn't allow private named formal parameters.
543+
if (name.startsWith('_')) {
544+
formalParameters.removeWhere((formalParameter) {
545+
return formalParameter.isNamed;
546+
});
547+
}
548+
549+
await addNamedSuperFormalParameters(searchEngine, formalParameters);
550+
elements.addAll(formalParameters);
551+
}
552+
}
540553
}
541554

542555
/// Fills [references] with all references to [elements].

pkg/analysis_server/lib/src/services/refactoring/legacy/rename_parameter.dart

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -133,17 +133,7 @@ class RenameParameterRefactoringImpl extends RenameRefactoringImpl {
133133
var element = this.element;
134134
if (element.isNamed) {
135135
elements = await getHierarchyNamedParameters(searchEngine, element);
136-
137-
// Iteratively collect superFormalParameter(s) of subclasses.
138-
for (var i = 0; i < elements.length; i++) {
139-
var element = elements[i];
140-
var references = await searchEngine.searchReferences(element);
141-
elements.addAll(
142-
references
143-
.map((match) => match.element)
144-
.whereType<analyzer.SuperFormalParameterElement>(),
145-
);
146-
}
136+
await addNamedSuperFormalParameters(searchEngine, elements);
147137
} else if (element.isPositional) {
148138
elements = await getHierarchyPositionalParameters(searchEngine, element);
149139
}

pkg/analysis_server/lib/src/services/search/hierarchy.dart

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,25 @@ import 'package:analysis_server/src/services/search/search_engine.dart';
77
import 'package:analyzer/dart/element/element.dart';
88
import 'package:analyzer/src/util/performance/operation_performance.dart';
99

10+
/// Expand [formalParameters] to include all chains of super formals.
11+
Future<void> addNamedSuperFormalParameters(
12+
SearchEngine searchEngine,
13+
List<FormalParameterElement> formalParameters,
14+
) async {
15+
// Indexed-based loop to allow modification while iterating.
16+
for (var i = 0; i < formalParameters.length; i++) {
17+
var formalParameter = formalParameters[i];
18+
if (formalParameter.isNamed) {
19+
var references = await searchEngine.searchReferences(formalParameter);
20+
formalParameters.addAll(
21+
references
22+
.map((match) => match.element)
23+
.whereType<SuperFormalParameterElement>(),
24+
);
25+
}
26+
}
27+
}
28+
1029
/// Returns direct children of [parent].
1130
List<Element> getChildren(Element parent, [String? name]) {
1231
var children = <Element>[];
@@ -153,9 +172,7 @@ getHierarchyMembersAndParameters(
153172
subClasses.add(superClass);
154173
}
155174
if (member2.isPrivate) {
156-
subClasses.removeWhere(
157-
(subClass) => subClass.library != member2.library,
158-
);
175+
subClasses.removeWhere((subClass) => subClass.library != member2.library);
159176
}
160177
for (var subClass in subClasses) {
161178
var subClassMembers = getChildren(subClass, name);

pkg/analysis_server/test/services/refactoring/legacy/rename_class_member_test.dart

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,72 @@ void f() {
786786
''');
787787
}
788788

789+
Future<void>
790+
test_createChange_FieldElement_fieldFormalParameter_named_superChain() async {
791+
await indexTestUnit('''
792+
class A {
793+
final int tes^t;
794+
A({required this.test});
795+
}
796+
797+
class B extends A {
798+
B({required super.test});
799+
}
800+
801+
class C extends B {
802+
C({required super.test});
803+
}
804+
''');
805+
806+
createRenameRefactoring();
807+
expect(refactoring.refactoringName, 'Rename Field');
808+
expect(refactoring.elementKindName, 'field');
809+
refactoring.newName = 'newName';
810+
811+
return assertSuccessfulRefactoring('''
812+
class A {
813+
final int newName;
814+
A({required this.newName});
815+
}
816+
817+
class B extends A {
818+
B({required super.newName});
819+
}
820+
821+
class C extends B {
822+
C({required super.newName});
823+
}
824+
''');
825+
}
826+
827+
Future<void>
828+
test_createChange_FieldElement_fieldFormalParameter_positional_toPrivate() async {
829+
await indexTestUnit('''
830+
class A {
831+
int te^st;
832+
int foo;
833+
A(this.test): assert(test != 0), foo = test {
834+
test;
835+
}
836+
}
837+
''');
838+
// configure refactoring
839+
createRenameRefactoring();
840+
expect(refactoring.refactoringName, 'Rename Field');
841+
expect(refactoring.oldName, 'test');
842+
refactoring.newName = '_test';
843+
// validate change
844+
return assertSuccessfulRefactoring('''
845+
class A {
846+
int _test;
847+
int foo;
848+
A(this._test): assert(_test != 0), foo = _test {
849+
_test;
850+
}
851+
}
852+
''');
853+
}
854+
789855
Future<void> test_createChange_FieldElement_invocation() async {
790856
await indexTestUnit('''
791857
typedef F(a);

0 commit comments

Comments
 (0)