Resolve ForElement(s) in separate scopes.

R=brianwilkerson@google.com, paulberry@google.com

Context: co19_2/LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A04_t01
Change-Id: I09e63e0821015993aa47736efd729411a9bd67e9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/96833
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 523b409..88fce5b 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -4325,7 +4325,7 @@
   }
 
   @override
-  void visitForElement(ForElement node) {
+  void visitForElementInScope(ForElement node) {
     ForLoopParts forLoopParts = node.forLoopParts;
     if (forLoopParts is ForParts) {
       if (forLoopParts is ForPartsWithDeclarations) {
@@ -5798,6 +5798,27 @@
   }
 
   @override
+  void visitForElement(ForElement node) {
+    Scope outerNameScope = nameScope;
+    try {
+      nameScope = new EnclosedScope(nameScope);
+      visitForElementInScope(node);
+    } finally {
+      nameScope = outerNameScope;
+    }
+  }
+
+  /// Visit the given [node] after it's scope has been created. This replaces
+  /// the normal call to the inherited visit method so that ResolverVisitor can
+  /// intervene when type propagation is enabled.
+  void visitForElementInScope(ForElement node) {
+    // TODO(brianwilkerson) Investigate the possibility of removing the
+    //  visit...InScope methods now that type propagation is no longer done.
+    node.forLoopParts?.accept(this);
+    node.body?.accept(this);
+  }
+
+  @override
   void visitFormalParameterList(FormalParameterList node) {
     super.visitFormalParameterList(node);
     // We finished resolving function signature, now include formal parameters
diff --git a/pkg/analyzer/test/src/dart/resolution/for_element_test.dart b/pkg/analyzer/test/src/dart/resolution/for_element_test.dart
new file mode 100644
index 0000000..3069acf
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/for_element_test.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2018, 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:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ForEachElementTest);
+    defineReflectiveTests(ForLoopElementTest);
+  });
+}
+
+@reflectiveTest
+class ForEachElementTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+  test_declaredIdentifierScope() async {
+    addTestFile(r'''
+main() {
+  <int>[for (var i in [1, 2, 3]) i]; // 1
+  <double>[for (var i in [1.1, 2.2, 3.3]) i]; // 2
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    assertElement(
+      findNode.simple('i]; // 1'),
+      findNode.simple('i in [1, 2').staticElement,
+    );
+    assertElement(
+      findNode.simple('i]; // 2'),
+      findNode.simple('i in [1.1').staticElement,
+    );
+  }
+}
+
+@reflectiveTest
+class ForLoopElementTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = ['control-flow-collections', 'spread-collections'];
+
+  test_declaredVariableScope() async {
+    addTestFile(r'''
+main() {
+  <int>[for (var i = 1; i < 10; i += 3) i]; // 1
+  <double>[for (var i = 1.1; i < 10; i += 5) i]; // 2
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    assertElement(
+      findNode.simple('i]; // 1'),
+      findNode.simple('i = 1;').staticElement,
+    );
+    assertElement(
+      findNode.simple('i]; // 2'),
+      findNode.simple('i = 1.1;').staticElement,
+    );
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart
index 71d5075..9701036 100644
--- a/pkg/analyzer/test/src/dart/resolution/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart
@@ -10,6 +10,7 @@
 import 'constant_test.dart' as constant_test;
 import 'enum_test.dart' as enum_test;
 import 'flow_analysis_test.dart' as flow_analysis_test;
+import 'for_element_test.dart' as for_element_test;
 import 'for_in_test.dart' as for_in_test;
 import 'generic_type_alias_test.dart' as generic_type_alias_test;
 import 'import_prefix_test.dart' as import_prefix_test;
@@ -34,6 +35,7 @@
     constant_test.main();
     enum_test.main();
     flow_analysis_test.main();
+    for_element_test.main();
     for_in_test.main();
     generic_type_alias_test.main();
     import_prefix_test.main();