File tree Expand file tree Collapse file tree 4 files changed +114
-0
lines changed
analysis_server_plugin/lib/edit/dart
analysis_server/test/src/services/correction/fix
analyzer/lib/src/utilities/extensions Expand file tree Collapse file tree 4 files changed +114
-0
lines changed Original file line number Diff line number Diff line change @@ -726,6 +726,42 @@ void bar(int i) {
726726 await assert_returnType_bool ('while ( test() ) {}' );
727727 }
728728
729+ Future <void > test_returnType_closure_expression () async {
730+ await resolveTestCode ('''
731+ void f(List<int> list) {
732+ list.where((i) => myMethod(i));
733+ }
734+ ''' );
735+ await assertHasFix ('''
736+ void f(List<int> list) {
737+ list.where((i) => myMethod(i));
738+ }
739+
740+ bool myMethod(int i) {
741+ }
742+ ''' );
743+ }
744+
745+ Future <void > test_returnType_closure_return () async {
746+ await resolveTestCode ('''
747+ void f(List<int> list) {
748+ list.where((i) {
749+ return myMethod(i);
750+ });
751+ }
752+ ''' );
753+ await assertHasFix ('''
754+ void f(List<int> list) {
755+ list.where((i) {
756+ return myMethod(i);
757+ });
758+ }
759+
760+ bool myMethod(int i) {
761+ }
762+ ''' );
763+ }
764+
729765 Future <void > test_returnType_fromAssignment_eq () async {
730766 await resolveTestCode ('''
731767void f() {
Original file line number Diff line number Diff line change @@ -1253,6 +1253,48 @@ class E {}
12531253''' , target: '$testPackageLibPath /test2.dart' );
12541254 }
12551255
1256+ Future <void > test_returnType_closure_expression () async {
1257+ await resolveTestCode ('''
1258+ class A {
1259+ void m(List<A> list) {
1260+ list.where((a) => a.myMethod());
1261+ }
1262+ }
1263+ ''' );
1264+ await assertHasFix ('''
1265+ class A {
1266+ void m(List<A> list) {
1267+ list.where((a) => a.myMethod());
1268+ }
1269+
1270+ bool myMethod() {}
1271+ }
1272+ ''' );
1273+ }
1274+
1275+ Future <void > test_returnType_closure_return () async {
1276+ await resolveTestCode ('''
1277+ class A {
1278+ void m(List<A> list) {
1279+ list.where((a) {
1280+ return a.myMethod();
1281+ });
1282+ }
1283+ }
1284+ ''' );
1285+ await assertHasFix ('''
1286+ class A {
1287+ void m(List<A> list) {
1288+ list.where((a) {
1289+ return a.myMethod();
1290+ });
1291+ }
1292+
1293+ bool myMethod() {}
1294+ }
1295+ ''' );
1296+ }
1297+
12561298 Future <void > test_static () async {
12571299 await resolveTestCode ('''
12581300extension E on String {}
Original file line number Diff line number Diff line change @@ -511,11 +511,17 @@ abstract class ResolvedCorrectionProducer
511511 }
512512 // `=> myFunction();`.
513513 if (parent is ExpressionFunctionBody ) {
514+ if (_closureReturnType (expression) case var returnType? ) {
515+ return returnType;
516+ }
514517 var executable = expression.enclosingExecutableElement2;
515518 return executable? .returnType;
516519 }
517520 // `return myFunction();`.
518521 if (parent is ReturnStatement ) {
522+ if (_closureReturnType (expression) case var returnType? ) {
523+ return returnType;
524+ }
519525 var executable = expression.enclosingExecutableElement2;
520526 return executable? .returnType;
521527 }
@@ -639,6 +645,19 @@ abstract class ResolvedCorrectionProducer
639645
640646 bool isEnabled (Feature feature) =>
641647 libraryElement2.featureSet.isEnabled (feature);
648+
649+ /// Looks if the [expression] is directly inside a closure and returns the
650+ /// return type of the closure.
651+ DartType ? _closureReturnType (Expression expression) {
652+ if (expression.enclosingClosure
653+ case FunctionExpression (: var correspondingParameter, : var staticType)) {
654+ if (correspondingParameter? .type ?? staticType
655+ case FunctionType (: var returnType)) {
656+ return returnType;
657+ }
658+ }
659+ return null ;
660+ }
642661}
643662
644663final class StubCorrectionProducerContext implements CorrectionProducerContext {
Original file line number Diff line number Diff line change @@ -26,6 +26,23 @@ extension AstNodeExtension on AstNode {
2626 return result;
2727 }
2828
29+ /// The [FunctionExpression] that encloses this node directly or `null` if
30+ /// there is another enclosing executable element.
31+ FunctionExpression ? get enclosingClosure {
32+ for (var node in withParents) {
33+ switch (node) {
34+ case FunctionExpression (: var parent)
35+ when parent is ! FunctionDeclaration :
36+ return node;
37+ case FunctionDeclaration () ||
38+ ConstructorDeclaration () ||
39+ MethodDeclaration ():
40+ break ;
41+ }
42+ }
43+ return null ;
44+ }
45+
2946 /// The [ExecutableElement2] of the enclosing executable [AstNode] .
3047 ExecutableElement2 ? get enclosingExecutableElement2 {
3148 for (var node in withParents) {
You can’t perform that action at this time.
0 commit comments