blob: d789305b96930c0b3ecfb1cd624696a5b2f69a62 [file] [log] [blame]
// 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_binaryOperator_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void f(A a) {
var b = A();
a < b;
}
class A {
bool operator <(@mustBeConst A other) => false;
}
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 86, 1),
]);
}
test_binaryOperator_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void f(A a) {
const b = A();
a < b;
}
class A {
const A();
bool operator <(@mustBeConst A other) => false;
}
''');
}
test_constructor_constantLiteral_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
final c = C(3);
class C {
C(@mustBeConst int i);
}
''');
}
test_constructor_variable_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
final v = 3;
final c = C(v);
class C {
C(@mustBeConst int i);
}
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 77, 1),
]);
}
test_functionExpression_constantLiteral_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void f() {
var g = (@mustBeConst int i) {};
g(3);
}
''');
}
test_functionExpression_variable_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_functionType_constantLiteral_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void f(void g(@mustBeConst int i)) {
g(3);
}
''');
}
test_functionType_variable_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, 99, 1),
]);
}
test_indexExpression_constExpression_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void f(A a) {
const b = A();
a[1] = b;
}
class A {
const A();
void operator []=(@mustBeConst int i, @mustBeConst A v) {}
}
''');
}
test_indexExpression_nonConstant_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void f(A a) {
a[1] = A();
}
class A {
const A();
void operator []=(@mustBeConst int i, @mustBeConst A v) {}
}
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 74, 3),
]);
}
test_localFunction_constantLiteral_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void f() {
void g(@mustBeConst int i) {}
g(3);
}
''');
}
test_localFunction_variable_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_method_constantLiteral_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void f(C c) => c.g(3);
class C {
void g([@mustBeConst int? value]) {}
}
''');
}
test_method_variable_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
final v = 3;
void f(C c) => c.g(v);
class C {
void g([@mustBeConst int? value]) {}
}
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 84, 1),
]);
}
test_optionalNamed_constVariable_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
const v = 3;
void f() => g(value: v);
void g({@mustBeConst int? value}) {}
''');
}
test_optionalNamed_noArgument_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void f() => g();
void g({@mustBeConst int? value}) {}
''');
}
test_optionalNamed_variable_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
final v = 3;
void f() => g(value: v);
void g({@mustBeConst int? value}) {}
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 79, 8),
]);
}
test_optionalPositional_constVariable_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
const v = 3;
void f() => g(v);
void g([@mustBeConst int? value]) {}
''');
}
test_optionalPositional_noArgument_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void f() => g();
void g([@mustBeConst int? value]) {}
''');
}
test_optionalPositional_variable_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
final v = 3;
void f() => g(v);
void g([@mustBeConst int? value]) {}
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 79, 1),
]);
}
test_redirectingConstructor_variable_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
class A {
A(@mustBeConst int i);
A.named(int i) : this(i);
}
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 110, 1),
]);
}
test_redirectingFactoryConstructor_variable_succeeds() async {
// The call to `A.named(v)` is not considered a direct call to `A()`; while
// the parameters declared in `A.named` must "match" those in `A.new`, they
// are separate. For example, they can have separate annotations.
// TODO(srawlins): It still seems that to be consistent, we should report
// `A.named(int i)`.
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
class A {
A(@mustBeConst int i);
factory A.named(int i) = A;
}
final v = 3;
var a = A.named(v);
''');
}
test_requiredNamed_constantLiteral_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void f() => g(value: 3);
void g({@mustBeConst required int value}) {}
''');
}
test_requiredNamed_constVariable_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
const v = 3;
void f() => g(value: v);
void g({@mustBeConst required int value}) {}
''');
}
test_requiredPositional_constVariable_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
const v = 3;
void f() => g(v);
void g(@mustBeConst int value) {}
''');
}
test_requiredPositional_list_constVariable_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
const v = [3,4];
void f() => g(v);
void g(@mustBeConst List<int> value) {}
''');
}
test_requiredPositional_localVariable_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void f(int value) => g(value);
void g(@mustBeConst int value) {}
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 74, 5),
]);
}
test_requiredPositional_map_constVariable_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
const v = {'k1': 3, 'k2': 4};
void f() => g(v);
void g(@mustBeConst Map<String, int> value) {}
''');
}
test_requiredPositional_topLevelVariable_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
final v = 3;
void f() => g(v);
void g(@mustBeConst int value) {}
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 79, 1),
]);
}
test_setter_fails() async {
await assertErrorsInCode(
r'''
import 'package:meta/meta.dart' show mustBeConst;
void f() {
final v = 3;
i = v;
}
set i(@mustBeConst int? value) {}
''',
[error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 83, 1)],
);
}
test_setter_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
void f() {
i = 3;
}
set i(@mustBeConst int? value) {}
''');
}
test_subclassesDontInherit() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
final v = 3;
final r = B().f(v);
abstract class A {
void f(@mustBeConst int i);
}
class B extends A {
@override
void f(int i) {}
}
''');
}
test_superclassCanBeOverriden_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 {
void f(int i);
}
class B extends A {
@override
void f(@mustBeConst int i) {}
}
''');
}
test_superclassCanBeOverriden_noCast_fails() async {
await assertErrorsInCode(
r'''
import 'package:meta/meta.dart' show mustBeConst;
final v = 3;
final r = B().f(v);
abstract class A {
void f(int i);
}
class B extends A {
@override
void f(@mustBeConst int i) {}
}
''',
[
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 81, 1),
],
);
}
test_superConstructor_variable_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
class A {
A(@mustBeConst int i);
}
class B extends A {
B(int i) : super(i);
}
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 128, 1),
]);
}
test_superParameter_variable_succeeds() async {
// TODO(srawlins): It seems that to be consistent, we should `super.i`.
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
class A {
A(@mustBeConst int i);
}
class B extends A {
B(super.i);
}
''');
}
test_typedef_function_constantLiteral_succeeds() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
typedef Td = void Function(@mustBeConst int);
void f(Td td) {
td(3);
}
''');
}
test_typedef_function_variable_succeeds() async {
// An annotation on a parameter in a function type is not supported.
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
typedef Td = void Function(@mustBeConst int);
void f(int x, Td td) {
td(x);
}
''');
}
test_typedef_nonFunction_variable_fails() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart' show mustBeConst;
typedef T = C;
class C {
C(@mustBeConst int i);
}
void g(int x) => T(x);
''', [
error(WarningCode.NON_CONST_ARGUMENT_FOR_CONST_PARAMETER, 124, 1),
]);
}
}