blob: 447f8871aa56a5174e2b7499aaaf93c4cfda5965 [file] [log] [blame]
// Copyright (c) 2014, 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/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../src/dart/resolution/context_collection_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(StaticTypeWarningCodeTest);
defineReflectiveTests(StrongModeStaticTypeWarningCodeTest);
defineReflectiveTests(StaticTypeWarningCodeWithoutNullSafetyTest);
});
}
/// TODO(srawlins) Figure out what to do with the rest of these tests.
/// The names do not correspond to diagnostic codes, so it isn't clear what
/// they're testing.
@reflectiveTest
class StaticTypeWarningCodeTest extends PubPackageResolutionTest {
test_await_simple() async {
await assertErrorsInCode('''
Future<int> fi() => Future.value(0);
f() async {
String a = await fi(); // Warning: int not assignable to String
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 58, 1),
error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 62, 10),
]);
}
test_awaitForIn_declaredVariableRightType() async {
await assertErrorsInCode('''
f(Stream<int> stream) async {
await for (int i in stream) {}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 47, 1),
]);
}
test_awaitForIn_declaredVariableWrongType() async {
await assertErrorsInCode('''
f(Stream<String> stream) async {
await for (int i in stream) {}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 50, 1),
error(CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 55, 6),
]);
}
test_awaitForIn_downcast() async {
await assertErrorsInCode('''
f(Stream<num> stream) async {
await for (int i in stream) {}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 47, 1),
error(CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 52, 6),
]);
}
test_awaitForIn_dynamicVariable() async {
await assertErrorsInCode('''
f(Stream<int> stream) async {
await for (var i in stream) {}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 47, 1),
]);
}
test_awaitForIn_existingVariableRightType() async {
await assertErrorsInCode('''
f(Stream<int> stream) async {
late int i;
await for (i in stream) {}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 41, 1),
]);
}
test_awaitForIn_existingVariableWrongType() async {
await assertErrorsInCode('''
f(Stream<String> stream) async {
late int i;
await for (i in stream) {}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 44, 1),
error(CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 65, 6),
]);
}
test_awaitForIn_streamOfDynamic() async {
await assertErrorsInCode('''
f(Stream stream) async {
await for (int i in stream) {}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 42, 1),
]);
}
test_awaitForIn_upcast() async {
await assertErrorsInCode('''
f(Stream<int> stream) async {
await for (num i in stream) {}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 47, 1),
]);
}
test_forIn_declaredVariableRightType() async {
await assertErrorsInCode('''
f() {
for (int i in <int>[]) {}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
]);
}
test_forIn_declaredVariableWrongType() async {
await assertErrorsInCode('''
f() {
for (int i in <String>[]) {}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
error(CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 22, 10),
]);
}
test_forIn_dynamic() async {
await assertErrorsInCode('''
f() {
dynamic d; // Could be [].
for (var i in d) {}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 46, 1),
]);
}
test_forIn_dynamicIterable() async {
await assertErrorsInCode('''
f() {
dynamic iterable;
for (int i in iterable) {}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 37, 1),
]);
}
test_forIn_dynamicVariable() async {
await assertErrorsInCode('''
f() {
for (var i in <int>[]) {}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
]);
}
test_forIn_existingVariableRightType() async {
await assertErrorsInCode('''
f() {
int i;
for (i in <int>[]) {}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 12, 1),
]);
}
test_forIn_existingVariableWrongType() async {
await assertErrorsInCode('''
f() {
int i;
for (i in <String>[]) {}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 12, 1),
error(CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 27, 10),
]);
}
test_forIn_iterableOfDynamic() async {
await assertErrorsInCode('''
f() {
for (int i in []) {}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
]);
}
test_forIn_object() async {
await assertErrorsInCode('''
f(List o) { // Could be [].
for (var i in o) {}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 39, 1),
]);
}
test_forIn_typeBoundBad() async {
await assertErrorsInCode('''
class Foo<T extends Iterable<int>> {
void method(T iterable) {
for (String i in iterable) {}
}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 81, 1),
error(CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 86, 8),
]);
}
test_forIn_typeBoundGood() async {
await assertErrorsInCode('''
class Foo<T extends Iterable<int>> {
void method(T iterable) {
for (var i in iterable) {}
}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 78, 1),
]);
}
test_forIn_upcast() async {
await assertErrorsInCode('''
f() {
for (num i in <int>[]) {}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
]);
}
test_typePromotion_booleanAnd_useInRight_accessedInClosureRight_mutated() async {
await assertErrorsInCode(r'''
callMe(f()) { f(); }
f(Object p) {
(p is String) && callMe(() { p.length; });
p = 0;
}
''', [
error(CompileTimeErrorCode.UNDEFINED_GETTER, 68, 6),
]);
}
test_typePromotion_booleanAnd_useInRight_mutatedInLeft() async {
await assertErrorsInCode(r'''
f(Object p) {
((p is String) && ((p = 42) == 42)) && p.length != 0;
}
''', [
error(CompileTimeErrorCode.UNDEFINED_GETTER, 57, 6),
]);
}
test_typePromotion_booleanAnd_useInRight_mutatedInRight() async {
await assertErrorsInCode(r'''
f(Object p) {
(p is String) && (((p = 42) == 42) && p.length != 0);
}
''', [
error(CompileTimeErrorCode.UNDEFINED_GETTER, 56, 6),
]);
}
test_typePromotion_conditional_useInThen_accessedInClosure_hasAssignment_after() async {
await assertErrorsInCode(r'''
callMe(f()) { f(); }
g(Object p) {
p is String ? callMe(() { p.length; }) : 0;
p = 42;
}
''', [
error(CompileTimeErrorCode.UNDEFINED_GETTER, 65, 6),
]);
}
test_typePromotion_conditional_useInThen_accessedInClosure_hasAssignment_before() async {
await assertErrorsInCode(r'''
callMe(f()) { f(); }
g(Object p) {
p = 42;
p is String ? callMe(() { p.length; }) : 0;
}
''', [
error(CompileTimeErrorCode.UNDEFINED_GETTER, 75, 6),
]);
}
test_typePromotion_if_accessedInClosure_hasAssignment() async {
await assertErrorsInCode(r'''
callMe(f()) { f(); }
f(Object p) {
if (p is String) {
callMe(() {
p.length;
});
}
p = 0;
}
''', [
error(CompileTimeErrorCode.UNDEFINED_GETTER, 80, 6),
]);
}
test_typePromotion_if_extends_notMoreSpecific_dynamic() async {
await assertErrorsInCode(r'''
class V {}
class A<T> {}
class B<S> extends A<S> {
var b;
}
f(A<V> p) {
if (p is B) {
p.b;
}
}
''', [
error(CompileTimeErrorCode.UNDEFINED_GETTER, 97, 1),
]);
}
test_typePromotion_if_extends_notMoreSpecific_notMoreSpecificTypeArg() async {
await assertErrorsInCode(r'''
class V {}
class A<T> {}
class B<S> extends A<S> {
var b;
}
f(A<V> p) {
if (p is B<int>) {
p.b;
}
}
''', [
error(CompileTimeErrorCode.UNDEFINED_GETTER, 102, 1),
]);
}
test_typePromotion_if_hasAssignment_before() async {
await assertErrorsInCode(r'''
f(Object p) {
if (p is String) {
p = 0;
p.length;
}
}
''', [
error(CompileTimeErrorCode.UNDEFINED_GETTER, 52, 6),
]);
}
test_typePromotion_if_hasAssignment_inClosure_anonymous_before() async {
await assertErrorsInCode(r'''
f(Object p) {
() {p = 0;};
if (p is String) {
p.length;
}
}
''', [
error(CompileTimeErrorCode.UNDEFINED_GETTER, 56, 6),
]);
}
test_typePromotion_if_hasAssignment_inClosure_function_before() async {
await assertErrorsInCode(r'''
g(Object p) {
f() {p = 0;};
if (p is String) {
p.length;
}
}
''', [
error(HintCode.UNUSED_ELEMENT, 16, 1),
error(CompileTimeErrorCode.UNDEFINED_GETTER, 57, 6),
]);
}
test_typePromotion_if_implements_notMoreSpecific_dynamic() async {
await assertErrorsInCode(r'''
class V {}
class A<T> {}
class B<S> implements A<S> {
var b;
}
f(A<V> p) {
if (p is B) {
p.b;
}
}
''', [
error(CompileTimeErrorCode.UNDEFINED_GETTER, 100, 1),
]);
}
test_typePromotion_if_with_notMoreSpecific_dynamic() async {
await assertErrorsInCode(r'''
class V {}
class A<T> {}
class B<S> extends Object with A<S> {
var b;
}
f(A<V> p) {
if (p is B) {
p.b;
}
}
''', [
error(CompileTimeErrorCode.UNDEFINED_GETTER, 109, 1),
]);
}
test_wrongNumberOfTypeArguments() async {
await assertErrorsInCode(r'''
class A<E> {
late E element;
}
g(A<NoSuchType> a) {
a.element.anyGetterExistsInDynamic;
}
''', [
error(CompileTimeErrorCode.NON_TYPE_AS_TYPE_ARGUMENT, 37, 10),
]);
}
}
@reflectiveTest
class StaticTypeWarningCodeWithoutNullSafetyTest
extends PubPackageResolutionTest with WithoutNullSafetyMixin {
test_assert_message_suppresses_type_promotion() async {
// If a variable is assigned to inside the expression for an assert
// message, type promotion should be suppressed, just as it would be if the
// assignment occurred outside an assert statement. (Note that it is a
// dubious practice for the computation of an assert message to have side
// effects, since it is only evaluated if the assert fails).
await assertErrorsInCode('''
class C {
void foo() {}
}
f(Object x) {
if (x is C) {
x.foo();
assert(true, () { x = new C(); return 'msg'; }());
}
}
''', [
error(CompileTimeErrorCode.UNDEFINED_METHOD, 65, 3),
]);
}
test_await_flattened() async {
await assertErrorsInCode('''
Future<Future<int>> ffi() => null;
f() async {
Future<int> b = await ffi();
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 61, 1),
]);
}
test_bug21912() async {
await assertErrorsInCode('''
class A {}
class B extends A {}
typedef T Function2<S, T>(S z);
typedef B AToB(A x);
typedef A BToA(B x);
void main() {
{
Function2<Function2<A, B>, Function2<B, A>> t1;
Function2<AToB, BToA> t2;
Function2<Function2<int, double>, Function2<int, double>> left;
left = t1;
left = t2;
}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 271, 4),
error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 289, 2),
error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 304, 2),
]);
}
test_forIn_downcast() async {
await assertErrorsInCode('''
f() {
for (int i in <num>[]) {}
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
]);
}
test_typePromotion_conditional_useInThen_hasAssignment() async {
await assertErrorsInCode(r'''
f(Object p) {
p is String ? (p.length + (p = 42)) : 0;
}
''', [
error(CompileTimeErrorCode.UNDEFINED_GETTER, 33, 6),
]);
}
test_typePromotion_if_and_right_hasAssignment() async {
await assertErrorsInCode(r'''
f(Object p) {
if (p is String && (p = null) == null) {
p.length;
}
}
''', [
error(CompileTimeErrorCode.UNDEFINED_GETTER, 63, 6),
]);
}
test_typePromotion_if_hasAssignment_after() async {
await assertErrorsInCode(r'''
f(Object p) {
if (p is String) {
p.length;
p = 0;
}
}
''', [
error(CompileTimeErrorCode.UNDEFINED_GETTER, 41, 6),
]);
}
test_typePromotion_if_hasAssignment_inClosure_anonymous_after() async {
await assertErrorsInCode(r'''
f(Object p) {
if (p is String) {
p.length;
}
() {p = 0;};
}
''', [
error(CompileTimeErrorCode.UNDEFINED_GETTER, 41, 6),
]);
}
test_typePromotion_if_hasAssignment_inClosure_function_after() async {
await assertErrorsInCode(r'''
g(Object p) {
if (p is String) {
p.length;
}
f() {p = 0;};
}
''', [
error(CompileTimeErrorCode.UNDEFINED_GETTER, 41, 6),
error(HintCode.UNUSED_ELEMENT, 55, 1),
]);
}
}
@reflectiveTest
class StrongModeStaticTypeWarningCodeTest extends PubPackageResolutionTest {
test_legalAsyncGeneratorReturnType_function_supertypeOfStream() async {
await assertNoErrorsInCode('''
f() async* { yield 42; }
dynamic f2() async* { yield 42; }
Object f3() async* { yield 42; }
Stream f4() async* { yield 42; }
Stream<dynamic> f5() async* { yield 42; }
Stream<Object> f6() async* { yield 42; }
Stream<num> f7() async* { yield 42; }
Stream<int> f8() async* { yield 42; }
''');
}
test_legalAsyncReturnType_function_supertypeOfFuture() async {
await assertNoErrorsInCode('''
f() async { return 42; }
dynamic f2() async { return 42; }
Object f3() async { return 42; }
Future f4() async { return 42; }
Future<dynamic> f5() async { return 42; }
Future<Object> f6() async { return 42; }
Future<num> f7() async { return 42; }
Future<int> f8() async { return 42; }
''');
}
test_legalSyncGeneratorReturnType_function_supertypeOfIterable() async {
await assertNoErrorsInCode('''
f() sync* { yield 42; }
dynamic f2() sync* { yield 42; }
Object f3() sync* { yield 42; }
Iterable f4() sync* { yield 42; }
Iterable<dynamic> f5() sync* { yield 42; }
Iterable<Object> f6() sync* { yield 42; }
Iterable<num> f7() sync* { yield 42; }
Iterable<int> f8() sync* { yield 42; }
''');
}
}