Skip to content

Commit 90c0aa6

Browse files
FMorschelCommit Queue
authored andcommitted
[DAS] Fixes create method/function return type
Fixes: #60306 Change-Id: Iba6222bbb5d0b63ca94920cad6d6abfd571ed830 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/417780 Auto-Submit: Felipe Morschel <[email protected]> Commit-Queue: Samuel Rawlins <[email protected]> Reviewed-by: Konstantin Shcheglov <[email protected]> Reviewed-by: Samuel Rawlins <[email protected]>
1 parent ff75aeb commit 90c0aa6

File tree

4 files changed

+114
-0
lines changed

4 files changed

+114
-0
lines changed

pkg/analysis_server/test/src/services/correction/fix/create_function_test.dart

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff 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('''
731767
void f() {

pkg/analysis_server/test/src/services/correction/fix/create_method_test.dart

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff 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('''
12581300
extension E on String {}

pkg/analysis_server_plugin/lib/edit/dart/correction_producer.dart

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff 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

644663
final class StubCorrectionProducerContext implements CorrectionProducerContext {

pkg/analyzer/lib/src/utilities/extensions/ast.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff 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) {

0 commit comments

Comments
 (0)