Migration: better handle a variable declaration statement with multiple variables.
This fix addresses the case where a variable declaration statement
declares multiple variables with different types; previously, we were
applying the type of the first variable to all the variables, leading
to possible crashes.
There are still some other issues with variable declaration statements
that declare multiple variables; I'll address them in follow-up CLs.
Bug: https://github.com/dart-lang/sdk/issues/47669
Change-Id: Iba82ef5ccc0b22382f30bf5a6ed391f4874f7443
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/220042
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
diff --git a/pkg/nnbd_migration/lib/src/node_builder.dart b/pkg/nnbd_migration/lib/src/node_builder.dart
index 653d36b..2dad8d1 100644
--- a/pkg/nnbd_migration/lib/src/node_builder.dart
+++ b/pkg/nnbd_migration/lib/src/node_builder.dart
@@ -660,7 +660,7 @@
DecoratedType? visitVariableDeclarationList(VariableDeclarationList node) {
node.metadata.accept(this);
var typeAnnotation = node.type;
- var type = _pushNullabilityNodeTarget(
+ var declaredType = _pushNullabilityNodeTarget(
NullabilityNodeTarget.element(
node.variables.first.declaredElement!, _getLineInfo),
() => typeAnnotation?.accept(this));
@@ -671,9 +671,11 @@
if (hint != null && hint.kind == HintCommentKind.lateFinal) {
_variables!.recordLateHint(source, node, hint);
}
+ var parent = node.parent;
for (var variable in node.variables) {
variable.metadata.accept(this);
var declaredElement = variable.declaredElement;
+ var type = declaredType;
if (type == null) {
var target =
NullabilityNodeTarget.element(declaredElement!, _getLineInfo);
@@ -683,11 +685,11 @@
}
_variables!.recordDecoratedElementType(declaredElement, type);
variable.initializer?.accept(this);
- }
- var parent = node.parent;
- if (parent is FieldDeclaration) {
- if (_hasAngularChildAnnotation(parent.metadata)) {
- _graph.makeNullable(type!.node!, AngularAnnotationOrigin(source, node));
+ if (parent is FieldDeclaration) {
+ if (_hasAngularChildAnnotation(parent.metadata)) {
+ _graph.makeNullable(
+ type.node!, AngularAnnotationOrigin(source, node));
+ }
}
}
return null;
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index de7d447..69a8936 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -8927,6 +8927,31 @@
await _checkSingleFileChanges(content, expected);
}
+ Future<void> test_var_with_different_types() async {
+ // Based on https://github.com/dart-lang/sdk/issues/47669
+ var content = '''
+class C<T> {
+ T m() => throw 'foo';
+}
+f(bool b, List<C<int>> cs) {
+ var x = !b,
+ y = cs.first,
+ z = y.m();
+}
+''';
+ var expected = '''
+class C<T> {
+ T m() => throw 'foo';
+}
+f(bool b, List<C<int>> cs) {
+ var x = !b,
+ y = cs.first,
+ z = y.m();
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
Future<void> test_weak_if_visit_weak_subexpression() async {
var content = '''
int f(int x, int/*?*/ y) {