linter: Move prefer_foreach tests

Change-Id: I0a6beae9d4983c8bef3445b569fc163c41f66faa
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/325361
Commit-Queue: Phil Quitslund <pquitslund@google.com>
Reviewed-by: Phil Quitslund <pquitslund@google.com>
Auto-Submit: Samuel Rawlins <srawlins@google.com>
diff --git a/pkg/linter/test/rules/all.dart b/pkg/linter/test/rules/all.dart
index 4773683..d8664d5 100644
--- a/pkg/linter/test/rules/all.dart
+++ b/pkg/linter/test/rules/all.dart
@@ -130,6 +130,7 @@
 import 'prefer_for_elements_to_map_fromIterable_test.dart'
 // ignore: library_prefixes
     as prefer_for_elements_to_map_fromIterable;
+import 'prefer_foreach_test.dart' as prefer_foreach;
 import 'prefer_function_declarations_over_variables_test.dart'
     as prefer_function_declarations_over_variables;
 import 'prefer_generic_function_type_aliases_test.dart'
@@ -327,6 +328,7 @@
   prefer_final_locals.main();
   prefer_final_parameters.main();
   prefer_for_elements_to_map_fromIterable.main();
+  prefer_foreach.main();
   prefer_function_declarations_over_variables.main();
   prefer_generic_function_type_aliases.main();
   prefer_if_elements_to_conditional_expressions.main();
diff --git a/pkg/linter/test/rules/prefer_foreach_test.dart b/pkg/linter/test/rules/prefer_foreach_test.dart
new file mode 100644
index 0000000..6d534ad
--- /dev/null
+++ b/pkg/linter/test/rules/prefer_foreach_test.dart
@@ -0,0 +1,131 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../rule_test_support.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    // TODO(srawlins): Add tests with non-block-bodies for the for loop. Add
+    // tests with multiple statements in the body.
+    defineReflectiveTests(PreferForeachTest);
+  });
+}
+
+@reflectiveTest
+class PreferForeachTest extends LintRuleTest {
+  @override
+  String get lintRule => 'prefer_foreach';
+
+  test_blockBody_singleStatement_functionCall() async {
+    await assertDiagnostics(r'''
+void f(List<int> list, void Function(int) fn) {
+  for (final a in list) {
+    fn(a);
+  }
+}
+''', [
+      lint(50, 38),
+    ]);
+  }
+
+  test_blockBody_singleStatement_functionTypedExpressionCall() async {
+    await assertDiagnostics(r'''
+void Function(int) fn() => (int a) {};
+
+void f(List<int> list) {
+  for (final a in list) {
+    fn()(a);
+  }
+}
+''', [
+      lint(67, 40),
+    ]);
+  }
+
+  test_blockBody_singleStatement_methodCall() async {
+    await assertDiagnostics(r'''
+class C {
+  void f(int o) {}
+
+  void foo(List<int> list) {
+    for (final a in list) {
+      f(a);
+    }
+  }
+}
+''', [
+      lint(63, 41),
+    ]);
+  }
+
+  test_blockBody_singleStatement_methodCall_explicitTarget() async {
+    await assertDiagnostics(r'''
+void f(D d, List<int> list) {
+  for (final a in list) {
+    d.f(a);
+  }
+}
+class D {
+  void f(int a) {}
+}
+''', [
+      lint(32, 39),
+    ]);
+  }
+
+  test_blockBody_singleStatement_methodCall_forVariableIsInTarget() async {
+    await assertNoDiagnostics(r'''
+void f(List<D> list) {
+  for (final d in list) {
+    list[list.indexOf(d)].f(d);
+  }
+}
+class D {
+  void f(D d) {}
+}
+''');
+  }
+
+  test_blockBody_singleStatement_methodCall_forVariableIsTarget() async {
+    await assertNoDiagnostics(r'''
+void f(List<D> list) {
+  for (final d in list) {
+    d.f(d);
+  }
+}
+class D {
+  void f(D d) {}
+}
+''');
+  }
+
+  test_blockBody_singleStatement_parenthesizedFunctionCall() async {
+    await assertDiagnostics(r'''
+void f(List<int> list, void Function(int) fn) {
+  for (final a in list) {
+    (fn(a));
+  }
+}
+''', [
+      lint(50, 40),
+    ]);
+  }
+
+  test_blockBody_singleStatement_staticMethodCall() async {
+    await assertDiagnostics(r'''
+void f(List<int> list) {
+  for (final a in list) {
+    C.f(a);
+  }
+}
+class C {
+  static void f(int a) {}
+}
+''', [
+      lint(27, 39),
+    ]);
+  }
+}
diff --git a/pkg/linter/test_data/rules/prefer_foreach.dart b/pkg/linter/test_data/rules/prefer_foreach.dart
deleted file mode 100644
index 3a628c3..0000000
--- a/pkg/linter/test_data/rules/prefer_foreach.dart
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// test w/ `dart test -N prefer_foreach`
-
-void f(Object o) {}
-
-void foo() {
-  final myList = [];
-  for (final a in myList) { // LINT
-    f(a);
-  }
-}
-
-void foo2() {
-  for (final a in []) { //LINT
-    (f(a));
-  }
-}
-
-Function func() => () {};
-
-void foo3() {
-  for (final a in <int>[1]) { //LINT
-    func()(a);
-  }
-}
-
-class WithMethods {
-  void f(Object o) {}
-
-  void foo() {
-    final myList = [];
-    for (final a in myList) { // LINT
-      f(a);
-    }
-  }
-}
-
-class WithThirdPartyMethods {
-  WithMethods x = WithMethods();
-
-  void foo() {
-    final myList = [];
-    for (final a in myList) { // LINT
-      x.f(a);
-    }
-  }
-}
-
-class WithElementInTarget {
-  List<WithMethods> myList = [];
-
-  void good() {
-    for (final x in myList) { // OK because x is the target
-      x.f(x);
-    }
-  }
-
-  void good2() {
-    for (final x in myList) { // OK because x is in the target
-      myList[myList.indexOf(x)].f(x);
-    }
-  }
-}
-
-class WithStaticMethods {
-  static void f(Object o) {}
-
-  void foo() {
-    final myList = [];
-    for (final a in myList) { // LINT
-      WithStaticMethods.f(a);
-    }
-  }
-}