blob: 5d5698237298557af30e813d9d4ae026d8065a94 [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);
});
}
// 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_flattened() async {
await assertErrorsInCode(
'''
external Future<Future<int>> ffi();
f() async {
Future<int> b = await ffi();
}
''',
[error(WarningCode.UNUSED_LOCAL_VARIABLE, 62, 1)],
);
}
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(WarningCode.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(WarningCode.UNUSED_LOCAL_VARIABLE, 47, 1)],
);
}
test_awaitForIn_declaredVariableWrongType() async {
await assertErrorsInCode(
'''
f(Stream<String> stream) async {
await for (int i in stream) {}
}
''',
[
error(WarningCode.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(WarningCode.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(WarningCode.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(WarningCode.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(WarningCode.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(WarningCode.UNUSED_LOCAL_VARIABLE, 42, 1)],
);
}
test_awaitForIn_upcast() async {
await assertErrorsInCode(
'''
f(Stream<int> stream) async {
await for (num i in stream) {}
}
''',
[error(WarningCode.UNUSED_LOCAL_VARIABLE, 47, 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 f(
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(WarningCode.UNUSED_LOCAL_VARIABLE, 263, 4),
error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 281, 2),
error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 296, 2),
],
);
}
test_forIn_declaredVariableRightType() async {
await assertErrorsInCode(
'''
f() {
for (int i in <int>[]) {}
}
''',
[error(WarningCode.UNUSED_LOCAL_VARIABLE, 17, 1)],
);
}
test_forIn_declaredVariableWrongType() async {
await assertErrorsInCode(
'''
f() {
for (int i in <String>[]) {}
}
''',
[
error(WarningCode.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(WarningCode.UNUSED_LOCAL_VARIABLE, 46, 1)],
);
}
test_forIn_dynamicIterable() async {
await assertErrorsInCode(
'''
f() {
dynamic iterable;
for (int i in iterable) {}
}
''',
[error(WarningCode.UNUSED_LOCAL_VARIABLE, 37, 1)],
);
}
test_forIn_dynamicVariable() async {
await assertErrorsInCode(
'''
f() {
for (var i in <int>[]) {}
}
''',
[error(WarningCode.UNUSED_LOCAL_VARIABLE, 17, 1)],
);
}
test_forIn_existingVariableRightType() async {
await assertErrorsInCode(
'''
f() {
int i;
for (i in <int>[]) {}
}
''',
[error(WarningCode.UNUSED_LOCAL_VARIABLE, 12, 1)],
);
}
test_forIn_existingVariableWrongType() async {
await assertErrorsInCode(
'''
f() {
int i;
for (i in <String>[]) {}
}
''',
[
error(WarningCode.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(WarningCode.UNUSED_LOCAL_VARIABLE, 17, 1)],
);
}
test_forIn_object() async {
await assertErrorsInCode(
'''
f(List o) { // Could be [].
for (var i in o) {}
}
''',
[error(WarningCode.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(WarningCode.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(WarningCode.UNUSED_LOCAL_VARIABLE, 78, 1)],
);
}
test_forIn_upcast() async {
await assertErrorsInCode(
'''
f() {
for (num i in <int>[]) {}
}
''',
[error(WarningCode.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(WarningCode.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 {}
mixin 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 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; }
''');
}
}