Move a few ForStatement tests.

Change-Id: I972f9162d456c1a62c6bf9a7b5e645a52a214ae7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/266444
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index 2dc19b0..80629df 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -4113,67 +4113,6 @@
 
 @reflectiveTest
 class StrongModeTypePropagationTest extends PubPackageResolutionTest {
-  test_foreachInference_dynamic_disabled() async {
-    await resolveTestCode(r'''
-main() {
-  var list = <int>[];
-  for (dynamic v in list) {
-    v; // marker
-  }
-}''');
-    assertTypeDynamic(findElement.localVar('v').type);
-    assertTypeDynamic(findNode.simple('v; // marker'));
-  }
-
-  test_foreachInference_reusedVar_disabled() async {
-    await resolveTestCode(r'''
-main() {
-  var list = <int>[];
-  var v;
-  for (v in list) {
-    v; // marker
-  }
-}''');
-    assertTypeDynamic(findNode.simple('v in'));
-    assertTypeDynamic(findNode.simple('v; // marker'));
-  }
-
-  test_foreachInference_var() async {
-    await resolveTestCode(r'''
-main() {
-  var list = <int>[];
-  for (var v in list) {
-    v; // marker
-  }
-}''');
-    assertType(findElement.localVar('v').type, 'int');
-    assertType(findNode.simple('v; // marker'), 'int');
-  }
-
-  test_foreachInference_var_iterable() async {
-    await resolveTestCode(r'''
-main() {
-  Iterable<int> list = <int>[];
-  for (var v in list) {
-    v; // marker
-  }
-}''');
-    assertType(findElement.localVar('v').type, 'int');
-    assertType(findNode.simple('v; // marker'), 'int');
-  }
-
-  test_foreachInference_var_stream() async {
-    await resolveTestCode(r'''
-main() async {
-  Stream<int> stream = null;
-  await for (var v in stream) {
-    v; // marker
-  }
-}''');
-    assertType(findElement.localVar('v').type, 'int');
-    assertType(findNode.simple('v; // marker'), 'int');
-  }
-
   test_inconsistentMethodInheritance_inferFunctionTypeFromTypedef() async {
     await assertNoErrorsInCode(r'''
 typedef bool F<E>(E argument);
diff --git a/pkg/analyzer/test/src/dart/resolution/for_statement_test.dart b/pkg/analyzer/test/src/dart/resolution/for_statement_test.dart
index 447418d..874a2d3 100644
--- a/pkg/analyzer/test/src/dart/resolution/for_statement_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/for_statement_test.dart
@@ -9,33 +9,61 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(ForEachStatementResolutionTest);
-    defineReflectiveTests(ForLoopStatementResolutionTest);
+    defineReflectiveTests(
+        ForStatement_ForEachPartsWithDeclaration_ResolutionTest);
+    defineReflectiveTests(
+        ForStatement_ForEachPartsWithIdentifier_ResolutionTest);
+    defineReflectiveTests(ForStatement_ForParts_ResolutionTest);
   });
 }
 
 /// TODO(scheglov) Move other for-in tests here.
 @reflectiveTest
-class ForEachStatementResolutionTest extends PubPackageResolutionTest {
-  test_forIn_variable() async {
-    var code = r'''
-T f<T>() => null;
-
-void test(Iterable<num> iter) {
-  for (var w in f()) {} // 1
-  for (var x in iter) {} // 2
-  for (num y in f()) {} // 3
+class ForStatement_ForEachPartsWithDeclaration_ResolutionTest
+    extends PubPackageResolutionTest {
+  test_iterable_contextType() async {
+    await assertNoErrorsInCode(r'''
+void f() {
+  // ignore:unused_local_variable
+  for (int v in g()) {}
 }
-''';
-    await resolveTestCode(code);
 
-    assertType(findElement.localVar('w').type, 'Object?');
-    assertType(findNode.methodInvocation('f()) {} // 1'), 'Iterable<Object?>');
+T g<T>() => throw 0;
+''');
 
-    assertType(findElement.localVar('x').type, 'num');
-
-    assertType(findElement.localVar('y').type, 'num');
-    assertType(findNode.methodInvocation('f()) {} // 3'), 'Iterable<num>');
+    var node = findNode.forStatement('for');
+    assertResolvedNodeText(node, r'''
+ForStatement
+  forKeyword: for
+  leftParenthesis: (
+  forLoopParts: ForEachPartsWithDeclaration
+    loopVariable: DeclaredIdentifier
+      type: NamedType
+        name: SimpleIdentifier
+          token: int
+          staticElement: dart:core::@class::int
+          staticType: null
+        type: int
+      name: v
+      declaredElement: v@56
+    inKeyword: in
+    iterable: MethodInvocation
+      methodName: SimpleIdentifier
+        token: g
+        staticElement: self::@function::g
+        staticType: T Function<T>()
+      argumentList: ArgumentList
+        leftParenthesis: (
+        rightParenthesis: )
+      staticInvokeType: Iterable<int> Function()
+      staticType: Iterable<int>
+      typeArgumentTypes
+        Iterable<int>
+  rightParenthesis: )
+  body: Block
+    leftBracket: {
+    rightBracket: }
+''');
   }
 
   test_iterable_missing() async {
@@ -49,8 +77,225 @@
       error(ParserErrorCode.MISSING_IDENTIFIER, 26, 1),
     ]);
 
-    assertType(findElement.localVar('v').type, 'dynamic');
-    assertType(findNode.simple('v;'), 'dynamic');
+    var node = findNode.forStatement('for');
+    assertResolvedNodeText(node, r'''
+ForStatement
+  forKeyword: for
+  leftParenthesis: (
+  forLoopParts: ForEachPartsWithDeclaration
+    loopVariable: DeclaredIdentifier
+      keyword: var
+      name: v
+      declaredElement: v@22
+    inKeyword: in
+    iterable: SimpleIdentifier
+      token: <empty> <synthetic>
+      staticElement: <null>
+      staticType: dynamic
+  rightParenthesis: )
+  body: Block
+    leftBracket: {
+    statements
+      ExpressionStatement
+        expression: SimpleIdentifier
+          token: v
+          staticElement: v@22
+          staticType: dynamic
+        semicolon: ;
+    rightBracket: }
+''');
+  }
+
+  test_loopVariable_dynamic() async {
+    await resolveTestCode(r'''
+void f(List<int> values) {
+  for (dynamic v in values) {
+    v;
+  }
+}''');
+    var node = findNode.forStatement('for');
+    assertResolvedNodeText(node, r'''
+ForStatement
+  forKeyword: for
+  leftParenthesis: (
+  forLoopParts: ForEachPartsWithDeclaration
+    loopVariable: DeclaredIdentifier
+      type: NamedType
+        name: SimpleIdentifier
+          token: dynamic
+          staticElement: dynamic@-1
+          staticType: null
+        type: dynamic
+      name: v
+      declaredElement: v@42
+    inKeyword: in
+    iterable: SimpleIdentifier
+      token: values
+      staticElement: self::@function::f::@parameter::values
+      staticType: List<int>
+  rightParenthesis: )
+  body: Block
+    leftBracket: {
+    statements
+      ExpressionStatement
+        expression: SimpleIdentifier
+          token: v
+          staticElement: v@42
+          staticType: dynamic
+        semicolon: ;
+    rightBracket: }
+''');
+  }
+
+  test_loopVariable_var_genericFunction() async {
+    await assertNoErrorsInCode(r'''
+void f() {
+  // ignore:unused_local_variable
+  for (var v in g()) {}
+}
+
+T g<T>() => throw 0;
+''');
+
+    var node = findNode.forStatement('for');
+    assertResolvedNodeText(node, r'''
+ForStatement
+  forKeyword: for
+  leftParenthesis: (
+  forLoopParts: ForEachPartsWithDeclaration
+    loopVariable: DeclaredIdentifier
+      keyword: var
+      name: v
+      declaredElement: v@56
+    inKeyword: in
+    iterable: MethodInvocation
+      methodName: SimpleIdentifier
+        token: g
+        staticElement: self::@function::g
+        staticType: T Function<T>()
+      argumentList: ArgumentList
+        leftParenthesis: (
+        rightParenthesis: )
+      staticInvokeType: Iterable<Object?> Function()
+      staticType: Iterable<Object?>
+      typeArgumentTypes
+        Iterable<Object?>
+  rightParenthesis: )
+  body: Block
+    leftBracket: {
+    rightBracket: }
+''');
+  }
+
+  test_loopVariable_var_iterable() async {
+    await resolveTestCode(r'''
+void f(Iterable<int> values) {
+  for (var v in values) {
+    v;
+  }
+}
+''');
+    var node = findNode.forStatement('for');
+    assertResolvedNodeText(node, r'''
+ForStatement
+  forKeyword: for
+  leftParenthesis: (
+  forLoopParts: ForEachPartsWithDeclaration
+    loopVariable: DeclaredIdentifier
+      keyword: var
+      name: v
+      declaredElement: v@42
+    inKeyword: in
+    iterable: SimpleIdentifier
+      token: values
+      staticElement: self::@function::f::@parameter::values
+      staticType: Iterable<int>
+  rightParenthesis: )
+  body: Block
+    leftBracket: {
+    statements
+      ExpressionStatement
+        expression: SimpleIdentifier
+          token: v
+          staticElement: v@42
+          staticType: int
+        semicolon: ;
+    rightBracket: }
+''');
+  }
+
+  test_loopVariable_var_list() async {
+    await resolveTestCode(r'''
+void f(List<int> values) {
+  for (var v in values) {
+    v;
+  }
+}
+''');
+    var node = findNode.forStatement('for');
+    assertResolvedNodeText(node, r'''
+ForStatement
+  forKeyword: for
+  leftParenthesis: (
+  forLoopParts: ForEachPartsWithDeclaration
+    loopVariable: DeclaredIdentifier
+      keyword: var
+      name: v
+      declaredElement: v@38
+    inKeyword: in
+    iterable: SimpleIdentifier
+      token: values
+      staticElement: self::@function::f::@parameter::values
+      staticType: List<int>
+  rightParenthesis: )
+  body: Block
+    leftBracket: {
+    statements
+      ExpressionStatement
+        expression: SimpleIdentifier
+          token: v
+          staticElement: v@38
+          staticType: int
+        semicolon: ;
+    rightBracket: }
+''');
+  }
+
+  test_loopVariable_var_stream() async {
+    await resolveTestCode(r'''
+void f(Stream<int> values) async {
+  await for (var v in values) {
+    v;
+  }
+}''');
+    var node = findNode.forStatement('for');
+    assertResolvedNodeText(node, r'''
+ForStatement
+  awaitKeyword: await
+  forKeyword: for
+  leftParenthesis: (
+  forLoopParts: ForEachPartsWithDeclaration
+    loopVariable: DeclaredIdentifier
+      keyword: var
+      name: v
+      declaredElement: v@52
+    inKeyword: in
+    iterable: SimpleIdentifier
+      token: values
+      staticElement: self::@function::f::@parameter::values
+      staticType: Stream<int>
+  rightParenthesis: )
+  body: Block
+    leftBracket: {
+    statements
+      ExpressionStatement
+        expression: SimpleIdentifier
+          token: v
+          staticElement: v@52
+          staticType: int
+        semicolon: ;
+    rightBracket: }
+''');
   }
 
   /// Test that the parameter `x` is in the scope of the iterable.
@@ -58,21 +303,50 @@
   test_scope() async {
     await assertNoErrorsInCode('''
 void f(List<List<int>> x) {
-  for (int x in x.first) {
-    x.isEven;
+  for (var x in x.first) {
+    x;
   }
 }
 ''');
-
-    assertElement(
-      findNode.simpleFormalParameter('x) {'),
-      findElement.parameter('x'),
-    );
-
-    assertElement(
-      findNode.simple('x.isEven'),
-      findElement.localVar('x'),
-    );
+    var node = findNode.forStatement('for');
+    assertResolvedNodeText(node, r'''
+ForStatement
+  forKeyword: for
+  leftParenthesis: (
+  forLoopParts: ForEachPartsWithDeclaration
+    loopVariable: DeclaredIdentifier
+      keyword: var
+      name: x
+      declaredElement: x@39
+    inKeyword: in
+    iterable: PrefixedIdentifier
+      prefix: SimpleIdentifier
+        token: x
+        staticElement: self::@function::f::@parameter::x
+        staticType: List<List<int>>
+      period: .
+      identifier: SimpleIdentifier
+        token: first
+        staticElement: PropertyAccessorMember
+          base: dart:core::@class::Iterable::@getter::first
+          substitution: {E: List<int>, E: List<int>}
+        staticType: List<int>
+      staticElement: PropertyAccessorMember
+        base: dart:core::@class::Iterable::@getter::first
+        substitution: {E: List<int>, E: List<int>}
+      staticType: List<int>
+  rightParenthesis: )
+  body: Block
+    leftBracket: {
+    statements
+      ExpressionStatement
+        expression: SimpleIdentifier
+          token: x
+          staticElement: x@39
+          staticType: int
+        semicolon: ;
+    rightBracket: }
+''');
   }
 
   test_type_genericFunctionType() async {
@@ -84,23 +358,51 @@
 }
 ''');
   }
+}
 
-  test_type_inferred() async {
-    await assertNoErrorsInCode(r'''
-void f(List<int> a) {
-  for (var v in a) {
+@reflectiveTest
+class ForStatement_ForEachPartsWithIdentifier_ResolutionTest
+    extends PubPackageResolutionTest {
+  test_identifier_dynamic() async {
+    await resolveTestCode(r'''
+void f(var v, List<int> values) {
+  for (v in values) {
     v;
   }
 }
 ''');
-
-    assertType(findElement.localVar('v').type, 'int');
-    assertType(findNode.simple('v;'), 'int');
+    var node = findNode.forStatement('for');
+    assertResolvedNodeText(node, r'''
+ForStatement
+  forKeyword: for
+  leftParenthesis: (
+  forLoopParts: ForEachPartsWithIdentifier
+    identifier: SimpleIdentifier
+      token: v
+      staticElement: self::@function::f::@parameter::v
+      staticType: dynamic
+    inKeyword: in
+    iterable: SimpleIdentifier
+      token: values
+      staticElement: self::@function::f::@parameter::values
+      staticType: List<int>
+  rightParenthesis: )
+  body: Block
+    leftBracket: {
+    statements
+      ExpressionStatement
+        expression: SimpleIdentifier
+          token: v
+          staticElement: self::@function::f::@parameter::v
+          staticType: dynamic
+        semicolon: ;
+    rightBracket: }
+''');
   }
 }
 
 @reflectiveTest
-class ForLoopStatementResolutionTest extends PubPackageResolutionTest {
+class ForStatement_ForParts_ResolutionTest extends PubPackageResolutionTest {
   test_condition_rewrite() async {
     await assertNoErrorsInCode(r'''
 f(bool Function() b) {