blob: e4627807a81473c83f233ce5df7b9ff375eb6442 [file]
// Copyright (c) 2024, 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 '../dart/resolution/context_collection_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ConstAnnotationTest);
});
}
@reflectiveTest
class ConstAnnotationTest extends PubPackageResolutionTest {
@override
void setUp() {
super.setUp();
writeTestPackageConfigWithMeta();
}
test_binary_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void main() {
var b = B();
var c = C();
final r = b < c;
print(r);
}
abstract class A {
bool operator <(A other);
}
class B implements A {
@override
bool operator <(@mustBeConst A other) {
return A is C;
}
}
class C implements A {
@override
bool operator <(A other) {
return false;
}
}
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 111, 1),
]);
}
test_binary_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void main() {
const b = B();
const c = C();
final r = b < c;
print(r);
}
abstract class A {
const A();
bool operator <(A other);
}
class B implements A {
const B();
@override
bool operator <(@mustBeConst A other) {
return A is C;
}
}
class C implements A {
const C();
@override
bool operator <(A other) {
return false;
}
}
''');
}
test_const_named_optional_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
final v = 3;
int f() => g(value: v);
int g({@mustBeConst int? value}) => (value ?? 0) + 1;
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 78, 8),
]);
}
test_const_named_optional_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
const v = 3;
int f() => g(value: v);
int g({@mustBeConst int? value}) => (value ?? 0) + 1;
''');
}
test_const_named_required_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
const v = 3;
int f() => g(value: v);
int g({@mustBeConst required int value}) => value + 1;
''');
}
test_const_positional_optional_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
const v = 3;
int f() => g(v);
int g([@mustBeConst int? value]) => (value ?? 0) + 1;
''');
}
test_constant_positional_required_list_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
const v = [3,4];
int f() => g(v);
int g(@mustBeConst List<int> value) => value.length;
''');
}
test_constant_positional_required_map_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
const v = {'k1': 3, 'k2': 4};
int f() => g(v);
int g(@mustBeConst Map<String, int> value) => value.length;
''');
}
test_constant_positional_required_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
const v = 3;
int f() => g(v);
int g(@mustBeConst int value) => value + 1;
''');
}
test_function_expression_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void f(int x) {
var g = (@mustBeConst int i) {};
g(x);
}
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 106, 1),
]);
}
test_function_expression_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void f() {
var g = (@mustBeConst int i) {};
g(3);
}
''');
}
test_function_type_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void f(void g(@mustBeConst int i), int x) {
g(3);
}
''');
}
test_index_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void main() {
final a = A();
final b = A();
a[1] = b;
}
class A {
const A();
void operator []=(@mustBeConst int i, @mustBeConst A v) {}
}
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 108, 1),
]);
}
test_index_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void main() {
final a = A();
const b = A();
a[1] = b;
}
class A {
const A();
void operator []=(@mustBeConst int i, @mustBeConst A v) {}
}
''');
}
test_literal_constructor_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
final c = C(3);
class C {
final int i;
C(@mustBeConst this.i);
}
''');
}
test_literal_method_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
int f() => C().g(3);
class C {
int g([@mustBeConst int? value]) => (value ?? 0) + 1;
}
''');
}
test_literal_named_required_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
int f() => g(value: 3);
int g({@mustBeConst required int value}) => value + 1;
''');
}
test_local_function_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void f(int x) {
void g(@mustBeConst int i) {}
g(x);
}
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 103, 1),
]);
}
test_local_function_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void f() {
void g(@mustBeConst int i) {}
g(3);
}
''');
}
test_noarg_named_optional_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
int f() => g();
int g({@mustBeConst int? value}) => (value ?? 0) + 1;
''');
}
test_noarg_positional_optional_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
int f() => g();
int g([@mustBeConst int? value]) => (value ?? 0) + 1;
''');
}
test_non_specified_positional_required_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
int f(int value) => g(value);
int g(@mustBeConst int value) => value + 1;
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 73, 5),
]);
}
test_nonconst_constructor_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
final v = 3;
final c = C(v);
class C {
final int i;
C(@mustBeConst this.i);
}
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 77, 1),
]);
}
test_nonconst_method_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
final v = 3;
int f() => C().g(v);
class C {
int g([@mustBeConst int? value]) => (value ?? 0) + 1;
}
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 82, 1),
]);
}
test_nonconst_positional_optional_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
final v = 3;
int f() => g(v);
int g([@mustBeConst int? value]) => (value ?? 0) + 1;
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 78, 1),
]);
}
test_nonconst_value_positional_required_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
final v = 3;
int f() => g(v);
int g(@mustBeConst int value) => value + 1;
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 78, 1),
]);
}
test_setter_fails() async {
await assertErrorsInCode(
r'''
import 'package:meta/meta.dart' show mustBeConst;
void main() {
final v = 3;
A().i = v;
}
class A {
int? _i;
int? get i => _i;
set i(@mustBeConst int? value) {
_i = value;
}
}
''',
[error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 90, 1)],
);
}
test_setter_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void main() {
A().i = 3;
}
class A {
int? _i;
int? get i => _i;
set i(@mustBeConst int? value) {
_i = value;
}
}
''');
}
test_subclasses_dont_inherit() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
final v = 3;
final r = B().f(v);
abstract class A {
int f(@mustBeConst int i);
}
class B extends A {
@override
int f(int i) => i + 1;
}
''');
}
test_superclass_can_be_overriden_cast_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
final v = 3;
final r = (B() as A).f(v);
abstract class A {
int f(int i);
}
class B extends A {
@override
int f(@mustBeConst int i) => i + 1;
}
''');
}
test_superclass_can_be_overriden_no_cast_fails() async {
await assertErrorsInCode(
r'''
import 'package:meta/meta.dart' show mustBeConst;
final v = 3;
final r = B().f(v);
abstract class A {
int f(int i);
}
class B extends A {
@override
int f(@mustBeConst int i) => i + 1;
}
''',
[
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 81, 1),
],
);
}
// This seems to not be supported, as the `mustBeConst` is stripped from the
// metadata of the `staticParameterElement`.
// test_function_type_fails() async {
// await assertErrorsInCode(r'''
// import 'package:meta/meta.dart' show mustBeConst;
// void f(void g(@mustBeConst int i), int x) {
// g(x);
// }
// ''', [
// error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 103, 1),
// ]);
// }
test_typedef_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
typedef Td = void Function(@mustBeConst int);
void f(Td td) { td(3); }
''');
}
// This seems to not be supported, as the `mustBeConst` is stripped from the
// metadata of the `staticParameterElement`.
// test_typedef_fails() async {
// await assertErrorsInCode(r'''
// import 'package:meta/meta.dart' show mustBeConst;
// typedef Td = void Function(@mustBeConst int);
// void f(int x, Td td) { td(x); }
// ''', [
// error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 103, 1),
// ]);
// }
}