blob: e376e33d9c2fafe1f004e78c7f40349f1f7efc73 [file] [log] [blame]
// Copyright (c) 2019, 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/dart/analysis/experiments.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../generated/test_support.dart';
import '../dart/resolution/driver_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(
NotInitializedPotentiallyNonNullableLocalVariableTest,
);
});
}
@reflectiveTest
class NotInitializedPotentiallyNonNullableLocalVariableTest
extends DriverResolutionTest {
@override
AnalysisOptionsImpl get analysisOptions =>
AnalysisOptionsImpl()..enabledExperiments = [EnableString.non_nullable];
test_assignment_leftExpression() async {
await assertErrorsInCode(r'''
void f() {
List<int> v;
v[0] = (v = [1, 2])[1];
v;
}
''', [
_notAssignedError(28, 1),
]);
}
test_assignment_leftLocal_compound() async {
await assertErrorsInCode(r'''
void f() {
int v;
v += 1;
v;
}
''', [
_notAssignedError(22, 1),
]);
}
test_assignment_leftLocal_compound_assignInRight() async {
await assertErrorsInCode(r'''
void f() {
int v;
v += (v = v);
}
''', [
_notAssignedError(22, 1),
_notAssignedError(32, 1),
]);
}
test_assignment_leftLocal_pure_eq() async {
await assertNoErrorsInCode(r'''
void f() {
int v;
v = 0;
v;
}
''');
}
test_assignment_leftLocal_pure_eq_self() async {
await assertErrorsInCode(r'''
void f() {
int v;
v = v;
}
''', [
_notAssignedError(26, 1),
]);
}
test_assignment_leftLocal_pure_questionEq() async {
await assertErrorsInCode(r'''
void f() {
int v;
v ??= 0;
}
''', [
_notAssignedError(22, 1),
error(HintCode.DEAD_CODE, 28, 1),
]);
}
test_assignment_leftLocal_pure_questionEq_self() async {
await assertErrorsInCode(r'''
void f() {
int v;
v ??= v;
}
''', [
_notAssignedError(22, 1),
error(HintCode.DEAD_CODE, 28, 1),
_notAssignedError(28, 1),
]);
}
test_basic() async {
await assertNoErrorsInCode('''
void f() {
int v;
v = 0;
v;
}
''');
}
test_binaryExpression_ifNull_left() async {
await assertErrorsInCode(r'''
void f() {
int v;
(v = 0) ?? 0;
v;
}
''', [error(HintCode.DEAD_CODE, 33, 1)]);
}
test_binaryExpression_ifNull_right() async {
await assertErrorsInCode(r'''
void f(int a) {
int v;
a ?? (v = 0);
v;
}
''', [
error(HintCode.DEAD_CODE, 32, 7),
_notAssignedError(43, 1),
]);
}
test_binaryExpression_logicalAnd_left() async {
await assertNoErrorsInCode(r'''
main(bool c) {
int v;
((v = 0) >= 0) && c;
v;
}
''');
}
test_binaryExpression_logicalAnd_right() async {
await assertErrorsInCode(r'''
main(bool c) {
int v;
c && ((v = 0) >= 0);
v;
}
''', [
_notAssignedError(49, 1),
]);
}
test_binaryExpression_logicalOr_left() async {
await assertNoErrorsInCode(r'''
main(bool c) {
int v;
((v = 0) >= 0) || c;
v;
}
''');
}
test_binaryExpression_logicalOr_right() async {
await assertErrorsInCode(r'''
main(bool c) {
int v;
c || ((v = 0) >= 0);
v;
}
''', [
_notAssignedError(49, 1),
]);
}
test_binaryExpression_plus_left() async {
await assertNoErrorsInCode(r'''
main() {
int v;
(v = 0) + 1;
v;
}
''');
}
test_binaryExpression_plus_right() async {
await assertNoErrorsInCode(r'''
main() {
int v;
1 + (v = 0);
v;
}
''');
}
test_conditional_both() async {
await assertNoErrorsInCode(r'''
f(bool b) {
int v;
b ? (v = 1) : (v = 2);
v;
}
''');
}
test_conditional_else() async {
await assertErrorsInCode(r'''
f(bool b) {
int v;
b ? 1 : (v = 2);
v;
}
''', [
_notAssignedError(42, 1),
]);
}
test_conditional_then() async {
await assertErrorsInCode(r'''
f(bool b) {
int v;
b ? (v = 1) : 2;
v;
}
''', [
_notAssignedError(42, 1),
]);
}
test_conditionalExpression_condition() async {
await assertNoErrorsInCode(r'''
main() {
int v;
(v = 0) >= 0 ? 1 : 2;
v;
}
''');
}
test_doWhile_break_afterAssignment() async {
await assertNoErrorsInCode(r'''
void f(bool b) {
int v;
do {
v = 0;
v;
if (b) break;
} while (b);
v;
}
''');
}
test_doWhile_break_beforeAssignment() async {
await assertErrorsInCode(r'''
void f(bool b) {
int v;
do {
if (b) break;
v = 0;
} while (b);
v;
}
''', [
_notAssignedError(79, 1),
]);
}
test_doWhile_breakOuterFromInner() async {
await assertErrorsInCode(r'''
void f(bool b) {
int v1, v2, v3;
L1: do {
do {
v1 = 0;
if (b) break L1;
v2 = 0;
v3 = 0;
} while (b);
v2;
} while (b);
v1;
v3;
}
''', [
_notAssignedError(168, 2),
]);
}
test_doWhile_condition() async {
await assertErrorsInCode(r'''
void f() {
int v1, v2;
do {
v1; // assigned in the condition, but not yet
} while ((v1 = 0) + (v2 = 0) >= 0);
v2;
}
''', [
_notAssignedError(36, 2),
]);
}
test_doWhile_condition_break() async {
await assertErrorsInCode(r'''
void f(bool b) {
int v;
do {
if (b) break;
} while ((v = 0) >= 0);
v;
}
''', [
_notAssignedError(79, 1),
]);
}
test_doWhile_condition_break_continue() async {
await assertErrorsInCode(r'''
void f(bool b1, b2) {
int v1, v2, v3, v4, v5, v6;
do {
v1 = 0; // visible outside, visible to the condition
if (b1) break;
v2 = 0; // not visible outside, visible to the condition
v3 = 0; // not visible outside, visible to the condition
if (b2) continue;
v4 = 0; // not visible
v5 = 0; // not visible
} while ((v6 = v1 + v2 + v4) == 0); // has break => v6 is not visible outside
v1;
v3;
v5;
v6;
}
''', [
_notAssignedError(360, 2),
_notAssignedError(421, 2),
_notAssignedError(427, 2),
_notAssignedError(433, 2),
]);
}
test_doWhile_condition_continue() async {
await assertErrorsInCode(r'''
void f(bool b) {
int v1, v2, v3, v4;
do {
v1 = 0; // visible outside, visible to the condition
if (b) continue;
v2 = 0; // not visible
v3 = 0; // not visible
} while ((v4 = v1 + v2) == 0); // no break => v4 visible outside
v1;
v3;
v4;
}
''', [
_notAssignedError(200, 2),
_notAssignedError(253, 2),
]);
}
test_doWhile_continue_beforeAssignment() async {
await assertErrorsInCode(r'''
void f(bool b) {
int v;
do {
if (b) continue;
v = 0;
} while (b);
v;
}
''', [
_notAssignedError(82, 1),
]);
}
test_doWhile_true_assignInBreak() async {
await assertNoErrorsInCode(r'''
void f(bool b) {
int v;
do {
if (b) {
v = 0;
break;
}
} while (true);
v;
}
''');
}
test_for_body() async {
await assertErrorsInCode(r'''
void f(bool b) {
int v;
for (; b;) {
v = 0;
}
v;
}
''', [
_notAssignedError(58, 1),
]);
}
test_for_break() async {
await assertErrorsInCode(r'''
void f(bool b) {
int v1, v2;
for (; b;) {
v1 = 0;
if (b) break;
v2 = 0;
}
v1;
v2;
}
''', [
_notAssignedError(94, 2),
_notAssignedError(100, 2),
]);
}
test_for_break_updaters() async {
await assertNoErrorsInCode(r'''
void f(bool b) {
int v1, v2;
for (; b; v1 + v2) {
v1 = 0;
if (b) break;
v2 = 0;
}
}
''');
}
test_for_condition() async {
await assertNoErrorsInCode(r'''
void f() {
int v;
for (; (v = 0) >= 0;) {
v;
}
v;
}
''');
}
test_for_continue() async {
await assertErrorsInCode(r'''
void f(bool b) {
int v1, v2;
for (; b;) {
v1 = 0;
if (b) continue;
v2 = 0;
}
v1;
v2;
}
''', [
_notAssignedError(97, 2),
_notAssignedError(103, 2),
]);
}
test_for_continue_updaters() async {
await assertErrorsInCode(r'''
void f(bool b) {
int v1, v2;
for (; b; v1 + v2) {
v1 = 0;
if (b) continue;
v2 = 0;
}
}
''', [
_notAssignedError(48, 2),
]);
}
test_for_initializer_expression() async {
await assertErrorsInCode(r'''
void f() {
int v;
for (v = 0;;) {
v;
}
v;
}
''', [
error(HintCode.DEAD_CODE, 51, 2),
]);
}
test_for_initializer_variable() async {
await assertErrorsInCode(r'''
void f() {
int v;
for (var t = (v = 0);;) {
v;
}
v;
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 31, 1),
error(HintCode.DEAD_CODE, 61, 2),
]);
}
test_for_updaters() async {
await assertErrorsInCode(r'''
void f(bool b) {
int v1, v2, v3, v4;
for (; b; v1 = 0, v2 = 0, v3 = 0, v4) {
v1;
}
v2;
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 31, 2),
_notAssignedError(75, 2),
_notAssignedError(85, 2),
_notAssignedError(95, 2),
]);
}
test_for_updaters_afterBody() async {
await assertNoErrorsInCode(r'''
void f(bool b) {
int v;
for (; b; v) {
v = 0;
}
}
''');
}
test_forEach() async {
await assertErrorsInCode(r'''
void f() {
List<int> v1;
int v2;
for (var _ in (v1 = [0, 1, 2])) {
v2 = 0;
}
v1;
v2;
}
''', [
_notAssignedError(97, 2),
]);
}
test_forEach_break() async {
await assertErrorsInCode(r'''
void f(bool b) {
int v1, v2;
for (var _ in [0, 1, 2]) {
v1 = 0;
if (b) break;
v2 = 0;
}
v1;
v2;
}
''', [
_notAssignedError(108, 2),
_notAssignedError(114, 2),
]);
}
test_forEach_continue() async {
await assertErrorsInCode(r'''
void f(bool b) {
int v1, v2;
for (var _ in [0, 1, 2]) {
v1 = 0;
if (b) continue;
v2 = 0;
}
v1;
v2;
}
''', [
_notAssignedError(111, 2),
_notAssignedError(117, 2),
]);
}
test_functionExpression_closure_read() async {
await assertErrorsInCode(r'''
void f() {
int v1, v2;
v1 = 0;
[0, 1, 2].forEach((t) {
v1;
v2;
});
}
''', [
_notAssignedError(75, 2),
]);
}
test_functionExpression_closure_write() async {
await assertErrorsInCode(r'''
void f() {
int v;
[0, 1, 2].forEach((t) {
v = t;
});
v;
}
''', [
_notAssignedError(67, 1),
]);
}
test_functionExpression_localFunction_local() async {
await assertErrorsInCode(r'''
void f() {
int v;
v = 0;
void f() {
int v; // 1
v;
}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
error(HintCode.UNUSED_ELEMENT, 38, 1),
_notAssignedError(64, 1),
]);
}
test_functionExpression_localFunction_local2() async {
await assertErrorsInCode(r'''
void f() {
int v1;
v1 = 0;
void f() {
int v2, v3;
v2 = 0;
v1;
v2;
v3;
}
}
''', [
error(HintCode.UNUSED_ELEMENT, 40, 1),
_notAssignedError(94, 2),
]);
}
test_functionExpression_localFunction_read() async {
await assertErrorsInCode(r'''
void f() {
int v1, v2;
v1 = 0;
void f() {
v1;
v2;
}
v2 = 0;
}
''', [
error(HintCode.UNUSED_ELEMENT, 44, 1),
_notAssignedError(62, 2),
]);
}
test_functionExpression_localFunction_write() async {
await assertErrorsInCode(r'''
void f() {
int v;
void f() {
v = 0;
}
v;
}
''', [
error(HintCode.UNUSED_ELEMENT, 28, 1),
_notAssignedError(52, 1),
]);
}
test_futureOr_questionArgument_none() async {
await assertNoErrorsInCode('''
import 'dart:async';
f() {
FutureOr<int?> v;
}
''');
}
test_hasInitializer() async {
await assertNoErrorsInCode('''
f() {
int v = 0;
v;
}
''');
}
test_if_condition() async {
await assertNoErrorsInCode(r'''
main() {
int v;
if ((v = 0) >= 0) {
v;
} else {
v;
}
v;
}
''');
}
test_if_condition_false() async {
await assertErrorsInCode(r'''
void f() {
int v;
if (false) {
// not assigned
} else {
v = 0;
}
v;
}
''', [
error(HintCode.DEAD_CODE, 33, 25),
]);
}
test_if_condition_logicalAnd() async {
await assertErrorsInCode(r'''
void f(bool b, int i) {
int v;
if (b && (v = i) > 0) {
v;
} else {
v;
}
v;
}
''', [
_notAssignedError(81, 1),
_notAssignedError(90, 1),
]);
}
test_if_condition_logicalOr() async {
await assertErrorsInCode(r'''
void f(bool b, int i) {
int v;
if (b || (v = i) > 0) {
v;
} else {
v;
}
v;
}
''', [
_notAssignedError(63, 1),
_notAssignedError(90, 1),
]);
}
test_if_condition_notFalse() async {
await assertNoErrorsInCode(r'''
void f() {
int v;
if (!false) {
v = 0;
}
v;
}
''');
}
test_if_condition_notTrue() async {
await assertNoErrorsInCode(r'''
void f() {
int v;
if (!true) {
// not assigned
} else {
v = 0;
}
v;
}
''');
}
test_if_condition_true() async {
await assertNoErrorsInCode(r'''
void f() {
int v;
if (true) {
v = 0;
}
v;
}
''');
}
test_if_then() async {
await assertErrorsInCode(r'''
main(bool c) {
int v;
if (c) {
v = 0;
}
v;
}
''', [
_notAssignedError(52, 1),
]);
}
test_if_thenElse_all() async {
await assertNoErrorsInCode(r'''
main(bool c) {
int v;
if (c) {
v = 0;
v;
} else {
v = 0;
v;
}
v;
}
''');
}
test_if_thenElse_else() async {
await assertErrorsInCode(r'''
main(bool c) {
int v;
if (c) {
// not assigned
} else {
v = 0;
}
v;
}
''', [
_notAssignedError(83, 1),
]);
}
test_if_thenElse_then() async {
await assertErrorsInCode(r'''
main(bool c) {
int v;
if (c) {
v = 0;
} else {
// not assigned
}
v;
}
''', [
_notAssignedError(83, 1),
]);
}
test_late() async {
await assertNoErrorsInCode('''
f() {
late int v;
v;
}
''');
}
test_noInitializer() async {
await assertErrorsInCode('''
f() {
int v;
v;
}
''', [
_notAssignedError(17, 1),
]);
}
test_noInitializer_typeParameter() async {
await assertErrorsInCode('''
f<T>() {
T v;
v;
}
''', [
_notAssignedError(18, 1),
]);
}
test_notUsed() async {
await assertNoErrorsInCode('''
void f() {
int v;
}
''');
}
test_nullable() async {
await assertNoErrorsInCode('''
f() {
int? v;
v;
}
''');
}
test_switch_case1_default() async {
await assertErrorsInCode(r'''
void f(int e) {
int v;
switch (e) {
case 1:
v = 0;
break;
case 2:
// not assigned
break;
default:
v = 0;
}
v;
}
''', [
_notAssignedError(157, 1),
]);
}
test_switch_case2_default() async {
await assertErrorsInCode(r'''
void f(int e) {
int v1, v2;
switch (e) {
case 1:
v1 = 0;
v2 = 0;
v1;
break;
default:
v1 = 0;
v1;
}
v1;
v2;
}
''', [
_notAssignedError(157, 2),
]);
}
test_switch_case_default_break() async {
await assertErrorsInCode(r'''
void f(bool b, int e) {
int v1, v2;
switch (e) {
case 1:
v1 = 0;
if (b) break;
v2 = 0;
break;
default:
v1 = 0;
if (b) break;
v2 = 0;
}
v1;
v2;
}
''', [
_notAssignedError(199, 2),
]);
}
test_switch_case_default_continue() async {
// We don't analyze to which `case` we go from `continue L`,
// but we don't have to. If all cases assign, then the variable is
// removed from the unassigned set in the `breakState`. And if there is a
// case when it is not assigned, then the variable will be left unassigned
// in the `breakState`.
await assertNoErrorsInCode(r'''
void f(int e) {
int v;
switch (e) {
L: case 1:
v = 0;
break;
case 2:
continue L;
break;
default:
v = 0;
}
v;
}
''');
}
test_switch_case_noDefault() async {
await assertErrorsInCode(r'''
void f(int e) {
int v;
switch (e) {
case 1:
v = 0;
break;
}
v;
}
''', [
_notAssignedError(84, 1),
]);
}
test_switch_expression() async {
await assertNoErrorsInCode(r'''
void f() {
int v;
switch (v = 0) {}
v;
}
''');
}
test_tryCatch_body() async {
await assertErrorsInCode(r'''
void f() {
int v;
try {
v = 0;
} catch (_) {
// not assigned
}
v;
}
''', [
_notAssignedError(81, 1),
]);
}
test_tryCatch_body_catch() async {
await assertNoErrorsInCode(r'''
void f() {
int v;
try {
g();
v = 0;
} catch (_) {
v = 0;
}
v;
}
void g() {}
''');
}
test_tryCatch_body_catchRethrow() async {
await assertNoErrorsInCode(r'''
void f() {
int v;
try {
v = 0;
} catch (_) {
rethrow;
}
v;
}
''');
}
test_tryCatch_catch() async {
await assertErrorsInCode(r'''
void f() {
int v;
try {
// not assigned
} catch (_) {
v = 0;
}
v;
}
''', [
_notAssignedError(81, 1),
]);
}
test_tryCatchFinally_body() async {
await assertErrorsInCode(r'''
void f() {
int v;
try {
v = 0;
} catch (_) {
// not assigned
} finally {
// not assigned
}
v;
}
''', [
_notAssignedError(115, 1),
]);
}
test_tryCatchFinally_catch() async {
await assertErrorsInCode(r'''
void f() {
int v;
try {
// not assigned
} catch (_) {
v = 0;
} finally {
// not assigned
}
v;
}
''', [
_notAssignedError(115, 1),
]);
}
test_tryCatchFinally_finally() async {
await assertNoErrorsInCode(r'''
void f() {
int v;
try {
// not assigned
} catch (_) {
// not assigned
} finally {
v = 0;
}
v;
}
''');
}
test_tryCatchFinally_useInFinally() async {
await assertErrorsInCode(r'''
f() {
int x;
try {
g(); // may throw an exception
x = 1;
} catch (_) {
x = 1;
} finally {
x; // BAD
}
}
void g() {}
''', [
_notAssignedError(114, 1),
]);
}
test_tryFinally_body() async {
await assertNoErrorsInCode(r'''
void f() {
int v;
try {
v = 0;
} finally {
// not assigned
}
v;
}
''');
}
test_tryFinally_finally() async {
await assertNoErrorsInCode(r'''
void f() {
int v;
try {
// not assigned
} finally {
v = 0;
}
v;
}
''');
}
test_type_dynamic() async {
await assertNoErrorsInCode('''
f() {
dynamic v;
}
''');
}
test_type_dynamicImplicit() async {
await assertNoErrorsInCode('''
f() {
var v;
}
''');
}
test_type_void() async {
await assertNoErrorsInCode('''
f() {
void v;
}
''');
}
test_while_condition() async {
await assertNoErrorsInCode(r'''
void f() {
int v;
while ((v = 0) >= 0) {
v;
}
v;
}
''');
}
test_while_condition_notTrue() async {
await assertErrorsInCode(r'''
void f(bool b) {
int v;
while (b) {
v = 0;
v;
}
v;
}
''', [
_notAssignedError(64, 1),
]);
}
test_while_true_break_afterAssignment() async {
await assertNoErrorsInCode(r'''
void f(bool b) {
int v1, v2;
while (true) {
v1 = 0;
v1;
if (b) break;
v2 = 0;
v1;
v2;
}
v1;
}
''');
}
test_while_true_break_beforeAssignment() async {
await assertErrorsInCode(r'''
void f(bool b) {
int v;
while (true) {
if (b) break;
v = 0;
v;
}
v;
}
''', [
_notAssignedError(85, 1),
]);
}
test_while_true_break_if() async {
await assertNoErrorsInCode(r'''
void f(bool b) {
int v;
while (true) {
if (b) {
v = 0;
break;
} else {
v = 0;
break;
}
v;
}
v;
}
''');
}
test_while_true_break_if2() async {
await assertNoErrorsInCode(r'''
void f(bool b) {
var v;
while (true) {
if (b) {
break;
} else {
v = 0;
}
v;
}
}
''');
}
test_while_true_break_if3() async {
await assertErrorsInCode(r'''
void f(bool b) {
int v1, v2;
while (true) {
if (b) {
v1 = 0;
v2 = 0;
if (b) break;
} else {
if (b) break;
v1 = 0;
v2 = 0;
}
v1;
}
v2;
}
''', [
_notAssignedError(190, 2),
]);
}
test_while_true_breakOuterFromInner() async {
await assertErrorsInCode(r'''
void f(bool b) {
int v1, v2, v3;
L1: while (true) {
L2: while (true) {
v1 = 0;
if (b) break L1;
v2 = 0;
v3 = 0;
if (b) break L2;
}
v2;
}
v1;
v3;
}
''', [
_notAssignedError(193, 2),
]);
}
test_while_true_continue() async {
await assertErrorsInCode(r'''
void f(bool b) {
int v;
while (true) {
if (b) continue;
v = 0;
}
v;
}
''', [
error(HintCode.DEAD_CODE, 81, 2),
error(
CompileTimeErrorCode
.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE,
81,
1),
]);
}
test_while_true_noBreak() async {
await assertErrorsInCode(r'''
void f() {
int v;
while (true) {
// No assignment, but no break.
// So, we don't exit the loop.
}
v;
}
''', [
error(HintCode.DEAD_CODE, 114, 2),
error(
CompileTimeErrorCode
.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE,
114,
1),
]);
}
ExpectedError _notAssignedError(int offset, int length) {
return error(
CompileTimeErrorCode
.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE,
offset,
length);
}
}