[analysis_server] AddExplicitCast to handle type arguments

Bug #49896

Change-Id: Ib024d40c1291ecb219f235fabf3dcc2305a82368
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/263741
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Ahmed Ashour 2022-10-13 21:34:03 +00:00 committed by Commit Queue
parent 20bdf8d8c5
commit 8436076fe4
2 changed files with 69 additions and 7 deletions

View file

@ -10,6 +10,7 @@ import 'package:analyzer/dart/ast/precedence.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
@ -84,12 +85,16 @@ class AddExplicitCast extends CorrectionProducer {
toType.isDartCoreList) ||
(fromType.isDartCoreIterable || fromType.isDartCoreSet) &&
toType.isDartCoreSet)) {
final toType_final = toType;
if (target.isCastMethodInvocation) {
// TODO(brianwilkerson) Consider updating the type arguments to the
// `cast` invocation.
var typeArguments = (target as MethodInvocation).typeArguments;
if (typeArguments != null) {
await builder.addDartFileEdit(file, (builder) {
_replaceTypeArgument(builder, typeArguments, toType_final, 0);
});
}
return;
}
final toType_final = toType;
await builder.addDartFileEdit(file, (builder) {
if (needsParentheses) {
builder.addSimpleInsertion(target_final.offset, '(');
@ -106,12 +111,17 @@ class AddExplicitCast extends CorrectionProducer {
} else if (fromType.isDartCoreMap &&
toType is InterfaceType &&
toType.isDartCoreMap) {
final toType_final = toType;
if (target.isCastMethodInvocation) {
// TODO(brianwilkerson) Consider updating the type arguments to the
// `cast` invocation.
var typeArguments = (target as MethodInvocation).typeArguments;
if (typeArguments != null) {
await builder.addDartFileEdit(file, (builder) {
_replaceTypeArgument(builder, typeArguments, toType_final, 0);
_replaceTypeArgument(builder, typeArguments, toType_final, 1);
});
}
return;
}
final toType_final = toType;
await builder.addDartFileEdit(file, (builder) {
if (needsParentheses) {
builder.addSimpleInsertion(target_final.offset, '(');
@ -142,4 +152,14 @@ class AddExplicitCast extends CorrectionProducer {
});
}
}
/// Replace the type argument of [typeArguments] at the specified [index]
/// with the corresponding type argument of [toType].
void _replaceTypeArgument(DartFileEditBuilder builder,
TypeArgumentList typeArguments, InterfaceType toType, int index) {
var replacementRange = range.node(typeArguments.arguments[index]);
builder.addReplacement(replacementRange, (builder) {
builder.writeType(toType.typeArguments[index]);
});
}
}

View file

@ -105,7 +105,28 @@ class B {}
''');
}
Future<void> test_assignment_iterable_to_set() async {
Future<void> test_assignment_iterable_cast() async {
await resolveTestCode('''
f(Set<A> a) {
Set<B> b;
b = a.cast<A>();
print(b);
}
class A {}
class B {}
''');
await assertHasFix('''
f(Set<A> a) {
Set<B> b;
b = a.cast<B>();
print(b);
}
class A {}
class B {}
''');
}
Future<void> test_assignment_iterable_toSet() async {
await resolveTestCode('''
f(List<A> a) {
Set<B> b;
@ -212,6 +233,27 @@ class B {}
''');
}
Future<void> test_assignment_map_cast() async {
await resolveTestCode('''
f(Map<A, B> a) {
Map<B, A> b;
b = a.cast<A, B>();
print(b);
}
class A {}
class B {}
''');
await assertHasFix('''
f(Map<A, B> a) {
Map<B, A> b;
b = a.cast<B, A>();
print(b);
}
class A {}
class B {}
''');
}
Future<void> test_assignment_needsParens() async {
await resolveTestCode('''
f(A a) {