[analysis_server] In "Encapsulate Field", update references to renamed parameters in initializers
Fixes https://github.com/dart-lang/sdk/issues/63145 Change-Id: I6dd672e5ae189a023419d2c41157fa7cdc43e46b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/494141 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Keerti Parthasarathy <keertip@google.com> Commit-Queue: Keerti Parthasarathy <keertip@google.com>
This commit is contained in:
committed by
Commit Queue
parent
c075592ca1
commit
4b01d6b803
@@ -7,6 +7,7 @@ import 'package:analysis_server/src/utilities/extensions/ast.dart';
|
||||
import 'package:analysis_server_plugin/edit/dart/correction_producer.dart';
|
||||
import 'package:analyzer/dart/analysis/features.dart';
|
||||
import 'package:analyzer/dart/ast/token.dart';
|
||||
import 'package:analyzer/dart/ast/visitor.dart';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:analyzer/src/dart/ast/ast.dart';
|
||||
import 'package:analyzer/src/dart/ast/extensions.dart';
|
||||
@@ -305,6 +306,10 @@ class EncapsulateField extends ResolvedCorrectionProducer {
|
||||
required Token? separator,
|
||||
required NodeList<ConstructorInitializer>? initializers,
|
||||
}) {
|
||||
// If we rename a parameter, keep track of it so we can update any
|
||||
// references in initializers.
|
||||
FieldFormalParameterElement? renamedParameterElement;
|
||||
|
||||
// Update any field formal parameter that refers to the field.
|
||||
for (var parameter in parameters.parameters) {
|
||||
var identifier = parameter.name;
|
||||
@@ -340,6 +345,7 @@ class EncapsulateField extends ResolvedCorrectionProducer {
|
||||
} else {
|
||||
// Rename the parameter.
|
||||
builder.addSimpleReplacement(range.token(identifier), '_$name');
|
||||
renamedParameterElement = parameterElement;
|
||||
}
|
||||
|
||||
// Change `final` to `var` in declaring parameters.
|
||||
@@ -361,6 +367,17 @@ class EncapsulateField extends ResolvedCorrectionProducer {
|
||||
'_$name',
|
||||
);
|
||||
}
|
||||
|
||||
// Update any references to the renamed parameter in initializers.
|
||||
if (renamedParameterElement != null) {
|
||||
initializer.accept(
|
||||
_InitializerReferenceUpdater(
|
||||
builder,
|
||||
renamedParameterElement,
|
||||
'_$name',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -402,3 +419,23 @@ class EncapsulateField extends ResolvedCorrectionProducer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates references to [parameterElement] to use [newName].
|
||||
class _InitializerReferenceUpdater extends RecursiveAstVisitor<void> {
|
||||
final DartFileEditBuilder builder;
|
||||
final FieldFormalParameterElement parameterElement;
|
||||
final String newName;
|
||||
|
||||
_InitializerReferenceUpdater(
|
||||
this.builder,
|
||||
this.parameterElement,
|
||||
this.newName,
|
||||
);
|
||||
|
||||
@override
|
||||
void visitSimpleIdentifier(SimpleIdentifier node) {
|
||||
if (node.element == parameterElement) {
|
||||
builder.addSimpleReplacement(range.token(node.token), newName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,6 +335,73 @@ void f(A a) {
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_initializer_reference() async {
|
||||
await resolveTestCode('''
|
||||
class Foo {
|
||||
final int ^a;
|
||||
final int b;
|
||||
|
||||
Foo(this.a) : b = a + 1 {}
|
||||
}
|
||||
''');
|
||||
await assertHasAssist('''
|
||||
class Foo {
|
||||
int _a;
|
||||
|
||||
int get a => _a;
|
||||
final int b;
|
||||
|
||||
Foo(this._a) : b = _a + 1 {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_initializer_reference_noPrivateNamedParameters() async {
|
||||
await resolveTestCode('''
|
||||
// @dart=3.10
|
||||
|
||||
class Foo {
|
||||
final int ^a;
|
||||
final int b;
|
||||
|
||||
Foo({required this.a}) : b = a + 1 {}
|
||||
}
|
||||
''');
|
||||
await assertHasAssist('''
|
||||
// @dart=3.10
|
||||
|
||||
class Foo {
|
||||
int _a;
|
||||
|
||||
int get a => _a;
|
||||
final int b;
|
||||
|
||||
Foo({required int a}) : _a = a, b = a + 1 {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_initializer_reference_privateNamedParameters() async {
|
||||
await resolveTestCode('''
|
||||
class Foo {
|
||||
final int ^a;
|
||||
final int b;
|
||||
|
||||
Foo({required this.a}) : b = a + 1 {}
|
||||
}
|
||||
''');
|
||||
await assertHasAssist('''
|
||||
class Foo {
|
||||
int _a;
|
||||
|
||||
int get a => _a;
|
||||
final int b;
|
||||
|
||||
Foo({required this._a}) : b = _a + 1 {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_mixin_hasType() async {
|
||||
await resolveTestCode('''
|
||||
mixin M {
|
||||
|
||||
Reference in New Issue
Block a user