From facfb4d9aa87285d4ea6159f96040e3ec00c5ac0 Mon Sep 17 00:00:00 2001 From: Ahmed Ashour Date: Mon, 19 Sep 2022 16:28:33 +0000 Subject: [PATCH] [analysis_server] `AddExplicitCast` to handle `toSet` Bug: #49896 Change-Id: I8fdbe33c3e0c5af9f39324b7c537a85a55a918d1 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/259700 Commit-Queue: Brian Wilkerson Reviewed-by: Brian Wilkerson --- .../correction/dart/add_explicit_cast.dart | 14 ++++++------- .../lib/src/utilities/extensions/ast.dart | 12 ++++++++++- .../lib/src/utilities/extensions/element.dart | 19 ++++++++++++++--- .../fix/add_explicit_cast_test.dart | 21 +++++++++++++++++++ 4 files changed, 54 insertions(+), 12 deletions(-) diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_explicit_cast.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_explicit_cast.dart index 8f132a9238d..b82c8a7a0b2 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/add_explicit_cast.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/add_explicit_cast.dart @@ -49,8 +49,7 @@ class AddExplicitCast extends CorrectionProducer { // because it's nullable, in which case a cast won't fix the problem. return; } - // TODO(brianwilkerson) Handle `toSet` in a manner similar to the below. - if (target.isToListMethodInvocation) { + if (target.isToListMethodInvocation || target.isToSetMethodInvocation) { var targetTarget = (target as MethodInvocation).target; if (targetTarget != null) { var targetTargetType = targetTarget.typeOrThrow; @@ -71,12 +70,11 @@ class AddExplicitCast extends CorrectionProducer { final target_final = target; var needsParentheses = target.precedence < Precedence.postfix; - if (((fromType.isDartCoreIterable || fromType.isDartCoreList) && - toType is InterfaceType && - toType.isDartCoreList) || - (fromType.isDartCoreSet && - toType is InterfaceType && - toType.isDartCoreSet)) { + if (toType is InterfaceType && + (((fromType.isDartCoreIterable || fromType.isDartCoreList) && + toType.isDartCoreList) || + (fromType.isDartCoreIterable || fromType.isDartCoreSet) && + toType.isDartCoreSet)) { if (target.isCastMethodInvocation) { // TODO(brianwilkerson) Consider updating the type arguments to the // `cast` invocation. diff --git a/pkg/analysis_server/lib/src/utilities/extensions/ast.dart b/pkg/analysis_server/lib/src/utilities/extensions/ast.dart index 703779c0eba..97ce3990785 100644 --- a/pkg/analysis_server/lib/src/utilities/extensions/ast.dart +++ b/pkg/analysis_server/lib/src/utilities/extensions/ast.dart @@ -180,7 +180,7 @@ extension ExpressionExtensions on Expression { } /// Return `true` if this expression is an invocation of the method `toList` - /// from either `Iterable` or `List`. + /// from `Iterable`. bool get isToListMethodInvocation { if (this is MethodInvocation) { var element = (this as MethodInvocation).methodName.staticElement; @@ -188,6 +188,16 @@ extension ExpressionExtensions on Expression { } return false; } + + /// Return `true` if this expression is an invocation of the method `toSet` + /// from `Iterable`. + bool get isToSetMethodInvocation { + if (this is MethodInvocation) { + var element = (this as MethodInvocation).methodName.staticElement; + return element is MethodElement && element.isToSetMethod; + } + return false; + } } extension FunctionBodyExtensions on FunctionBody { diff --git a/pkg/analysis_server/lib/src/utilities/extensions/element.dart b/pkg/analysis_server/lib/src/utilities/extensions/element.dart index 1c69d598fc2..906f3b4b984 100644 --- a/pkg/analysis_server/lib/src/utilities/extensions/element.dart +++ b/pkg/analysis_server/lib/src/utilities/extensions/element.dart @@ -79,8 +79,8 @@ extension MethodElementExtensions on MethodElement { definingClass.isDartCoreSet; } - /// Return `true` if this element represents the method `toList` from either - /// `Iterable` or `List`. + /// Return `true` if this element represents the method `toList` from + /// `Iterable`. bool get isToListMethod { if (name != 'toList') { return false; @@ -89,6 +89,19 @@ extension MethodElementExtensions on MethodElement { if (definingClass is! ClassElement) { return false; } - return definingClass.isDartCoreIterable || definingClass.isDartCoreList; + return definingClass.isDartCoreIterable; + } + + /// Return `true` if this element represents the method `toSet` from + /// `Iterable`. + bool get isToSetMethod { + if (name != 'toSet') { + return false; + } + var definingClass = enclosingElement3; + if (definingClass is! ClassElement) { + return false; + } + return definingClass.isDartCoreIterable; } } diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_explicit_cast_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_explicit_cast_test.dart index bdcfb2ab27b..4e7f56a62d2 100644 --- a/pkg/analysis_server/test/src/services/correction/fix/add_explicit_cast_test.dart +++ b/pkg/analysis_server/test/src/services/correction/fix/add_explicit_cast_test.dart @@ -76,6 +76,27 @@ class B {} '''); } + Future test_assignment_iterable_to_set() async { + await resolveTestCode(''' +f(List a) { + Set b; + b = a.where((e) => e is B).toSet(); + print(b); +} +class A {} +class B {} +'''); + await assertHasFix(''' +f(List a) { + Set b; + b = a.where((e) => e is B).cast().toSet(); + print(b); +} +class A {} +class B {} +'''); + } + Future test_assignment_list() async { await resolveTestCode(''' f(List a) {