Fix "Convert to a primary constructor" on generic classes.
It would incorrectly put the primary constructor parameter list before
the type's type parameter list, like:
```dart
// Before:
class C<T> {
C();
}
// After:
class C()<T> {
}
```
This fixes it to follow the type parameter list if there is one.
Change-Id: Ib49c7df7923e9feed11f87579fefc8300c56c4a6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/506760
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Auto-Submit: Bob Nystrom <rnystrom@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Bob Nystrom <rnystrom@google.com>
This commit is contained in:
committed by
dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent
9bd89a769d
commit
2cd3ec552c
+33
-40
@@ -68,13 +68,16 @@ class ConvertToPrimaryConstructor extends ResolvedCorrectionProducer {
|
||||
if (constructor.constKeyword != null && !containerData.isEnum) {
|
||||
builder.addSimpleInsertion(containerData.name.offset, 'const ');
|
||||
}
|
||||
builder.addInsertion(containerData.name.end, (builder) {
|
||||
if (constructor.name case var name?) {
|
||||
builder.write('.');
|
||||
builder.write(name.lexeme);
|
||||
}
|
||||
builder.write(_parameterText(constructor.parameters));
|
||||
});
|
||||
builder.addInsertion(
|
||||
containerData.typeParameters?.end ?? containerData.name.end,
|
||||
(builder) {
|
||||
if (constructor.name case var name?) {
|
||||
builder.write('.');
|
||||
builder.write(name.lexeme);
|
||||
}
|
||||
builder.write(_parameterText(constructor.parameters));
|
||||
},
|
||||
);
|
||||
|
||||
// Remove the constructor that was converted.
|
||||
//
|
||||
@@ -104,39 +107,24 @@ class ConvertToPrimaryConstructor extends ResolvedCorrectionProducer {
|
||||
/// Returns information about the declaration in which the [constructor] is
|
||||
/// declared.
|
||||
_ContainerData? _getContainerData(ConstructorDeclaration constructor) {
|
||||
Token name;
|
||||
bool hasPrimaryConstructor;
|
||||
int nonRedirectingGenerativeConstructorCount;
|
||||
bool isEnum = false;
|
||||
var parent = constructor.parent;
|
||||
switch (parent) {
|
||||
case BlockClassBody body:
|
||||
parent = body.parent;
|
||||
case BlockEnumBody body:
|
||||
parent = body.parent;
|
||||
}
|
||||
switch (parent) {
|
||||
case ClassDeclaration(:var namePart):
|
||||
name = namePart.typeName;
|
||||
hasPrimaryConstructor = namePart is PrimaryConstructorDeclaration;
|
||||
nonRedirectingGenerativeConstructorCount =
|
||||
_nonRedirectingGenerativeConstructorCount(parent.classMembers);
|
||||
case EnumDeclaration(:var namePart):
|
||||
name = namePart.typeName;
|
||||
hasPrimaryConstructor = namePart is PrimaryConstructorDeclaration;
|
||||
nonRedirectingGenerativeConstructorCount =
|
||||
_nonRedirectingGenerativeConstructorCount(parent.classMembers);
|
||||
isEnum = true;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
return _ContainerData(
|
||||
name: name,
|
||||
hasPrimaryConstructor: hasPrimaryConstructor,
|
||||
hasMultipleNonRedirectingGenerativeConstructors:
|
||||
nonRedirectingGenerativeConstructorCount > 1,
|
||||
isEnum: isEnum,
|
||||
);
|
||||
var parent = switch (constructor.parent) {
|
||||
BlockClassBody body => body.parent,
|
||||
BlockEnumBody body => body.parent,
|
||||
var parent => parent,
|
||||
};
|
||||
|
||||
return switch (parent) {
|
||||
ClassDeclaration(:var namePart) ||
|
||||
EnumDeclaration(:var namePart) => _ContainerData(
|
||||
name: namePart.typeName,
|
||||
typeParameters: namePart.typeParameters,
|
||||
hasPrimaryConstructor: namePart is PrimaryConstructorDeclaration,
|
||||
hasMultipleNonRedirectingGenerativeConstructors:
|
||||
_nonRedirectingGenerativeConstructorCount(parent.classMembers) > 1,
|
||||
isEnum: parent is EnumDeclaration,
|
||||
),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns the number of non-redirecting generative constructors in the list
|
||||
@@ -163,6 +151,10 @@ class _ContainerData {
|
||||
/// The name of the class or enum.
|
||||
Token name;
|
||||
|
||||
/// The type parameters on the class or enum or `null` if the type isn't
|
||||
/// generic.
|
||||
TypeParameterList? typeParameters;
|
||||
|
||||
/// Whether the class or enum already has a primary constructor.
|
||||
bool hasPrimaryConstructor;
|
||||
|
||||
@@ -175,6 +167,7 @@ class _ContainerData {
|
||||
|
||||
_ContainerData({
|
||||
required this.name,
|
||||
required this.typeParameters,
|
||||
required this.hasPrimaryConstructor,
|
||||
required this.hasMultipleNonRedirectingGenerativeConstructors,
|
||||
required this.isEnum,
|
||||
|
||||
+26
@@ -20,6 +20,18 @@ class ConvertToPrimaryConstructorClassTest extends AssistProcessorTest {
|
||||
@override
|
||||
AssistKind get kind => DartAssistKind.convertToPrimaryConstructor;
|
||||
|
||||
Future<void> test_genericClass() async {
|
||||
await resolveTestCode('''
|
||||
class C<T> {
|
||||
C^();
|
||||
}
|
||||
''');
|
||||
await assertHasAssist('''
|
||||
class C<T>() {
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_noParameters_noBody_named() async {
|
||||
await resolveTestCode('''
|
||||
class C {
|
||||
@@ -483,6 +495,20 @@ class ConvertToPrimaryConstructorEnumTest extends AssistProcessorTest {
|
||||
@override
|
||||
AssistKind get kind => DartAssistKind.convertToPrimaryConstructor;
|
||||
|
||||
Future<void> test_genericEnum() async {
|
||||
await resolveTestCode('''
|
||||
enum C<T> {
|
||||
a;
|
||||
C^();
|
||||
}
|
||||
''');
|
||||
await assertHasAssist('''
|
||||
enum C<T>() {
|
||||
a;
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_noParameters_noBody() async {
|
||||
await resolveTestCode('''
|
||||
enum E {
|
||||
|
||||
Reference in New Issue
Block a user