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();