blob: 071c51e7d04ba6b409d7079261ce36752ebb3d36 [file] [log] [blame]
// Copyright (c) 2016, 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/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/constant.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../../generated/test_support.dart';
import '../resolution/context_collection_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ConstantVisitorTest);
defineReflectiveTests(ConstantVisitorWithoutNullSafetyTest);
defineReflectiveTests(InstanceCreationEvaluatorTest);
defineReflectiveTests(InstanceCreationEvaluatorWithoutNullSafetyTest);
});
}
@reflectiveTest
class ConstantVisitorTest extends ConstantVisitorTestSupport
with ConstantVisitorTestCases {
test_declaration_staticError_notAssignable() async {
await assertErrorsInCode('''
const int x = 'foo';
''', [
error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 14, 5),
]);
}
test_equalEqual_double_object() async {
await assertNoErrorsInCode('''
const v = 1.2 == Object();
''');
final result = _topLevelVar('v');
assertDartObjectText(result, '''
bool false
variable: self::@variable::v
''');
}
test_equalEqual_int_int_false() async {
await assertNoErrorsInCode('''
const v = 1 == 2;
''');
final result = _topLevelVar('v');
assertDartObjectText(result, '''
bool false
variable: self::@variable::v
''');
}
test_equalEqual_int_int_true() async {
await assertNoErrorsInCode('''
const v = 1 == 1;
''');
final result = _topLevelVar('v');
assertDartObjectText(result, '''
bool true
variable: self::@variable::v
''');
}
test_equalEqual_int_null() async {
await assertNoErrorsInCode('''
const int? a = 1;
const v = a == null;
''');
final result = _topLevelVar('v');
assertDartObjectText(result, '''
bool false
variable: self::@variable::v
''');
}
test_equalEqual_int_object() async {
await assertNoErrorsInCode('''
const v = 1 == Object();
''');
final result = _topLevelVar('v');
assertDartObjectText(result, '''
bool false
variable: self::@variable::v
''');
}
test_equalEqual_int_userClass() async {
await assertNoErrorsInCode('''
class A {
const A();
}
const v = 1 == A();
''');
final result = _topLevelVar('v');
assertDartObjectText(result, '''
bool false
variable: self::@variable::v
''');
}
test_equalEqual_null_object() async {
await assertNoErrorsInCode('''
const Object? a = null;
const v = a == Object();
''');
final result = _topLevelVar('v');
assertDartObjectText(result, '''
bool false
variable: self::@variable::v
''');
}
test_equalEqual_string_object() async {
await assertNoErrorsInCode('''
const v = 'foo' == Object();
''');
final result = _topLevelVar('v');
assertDartObjectText(result, '''
bool false
variable: self::@variable::v
''');
}
test_equalEqual_userClass_hasEqEq() async {
await assertErrorsInCode('''
class A {
const A();
bool operator ==(other) => false;
}
const v = A() == 0;
''', [
error(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING, 72, 8),
]);
final result = _topLevelVar('v');
_assertNull(result);
}
test_equalEqual_userClass_hasHashCode() async {
await assertErrorsInCode('''
class A {
const A();
int get hashCode => 0;
}
const v = A() == 0;
''', [
error(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING, 61, 8),
]);
final result = _topLevelVar('v');
_assertNull(result);
}
test_equalEqual_userClass_hasPrimitiveEquality_false() async {
await assertNoErrorsInCode('''
class A {
final int f;
const A(this.f);
}
const v = A(0) == 0;
''');
final result = _topLevelVar('v');
assertDartObjectText(result, '''
bool false
variable: self::@variable::v
''');
}
test_equalEqual_userClass_hasPrimitiveEquality_language219() async {
await assertErrorsInCode('''
// @dart = 2.19
class A {
const A();
}
const v = A() == 0;
''', [
error(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING, 52, 8),
]);
final result = _topLevelVar('v');
_assertNull(result);
}
test_equalEqual_userClass_hasPrimitiveEquality_true() async {
await assertNoErrorsInCode('''
class A {
final int f;
const A(this.f);
}
const v = A(0) == A(0);
''');
final result = _topLevelVar('v');
assertDartObjectText(result, '''
bool true
variable: self::@variable::v
''');
}
test_hasPrimitiveEquality_bool() async {
await assertNoErrorsInCode('''
const v = true;
''');
_assertHasPrimitiveEqualityTrue('v');
}
test_hasPrimitiveEquality_class_hasEqEq() async {
await assertNoErrorsInCode('''
const v = const A();
class A {
const A();
bool operator ==(other) => false;
}
''');
_assertHasPrimitiveEqualityFalse('v');
}
test_hasPrimitiveEquality_class_hasEqEq_language219() async {
await assertNoErrorsInCode('''
// @dart = 2.19
const v = const A();
class A {
const A();
bool operator ==(other) => false;
}
''');
_assertHasPrimitiveEqualityFalse('v');
}
test_hasPrimitiveEquality_class_hasHashCode() async {
await assertNoErrorsInCode('''
const v = const A();
class A {
const A();
int get hashCode => 0;
}
''');
_assertHasPrimitiveEqualityFalse('v');
}
test_hasPrimitiveEquality_class_hasHashCode_language219() async {
await assertNoErrorsInCode('''
// @dart = 2.19
const v = const A();
class A {
const A();
int get hashCode => 0;
}
''');
_assertHasPrimitiveEqualityTrue('v');
}
test_hasPrimitiveEquality_class_hasNone() async {
await assertNoErrorsInCode('''
const v = const A();
class A {
const A();
}
''');
_assertHasPrimitiveEqualityTrue('v');
}
test_hasPrimitiveEquality_double() async {
await assertNoErrorsInCode('''
const v = 1.2;
''');
_assertHasPrimitiveEqualityFalse('v');
}
test_hasPrimitiveEquality_functionReference_staticMethod() async {
await assertNoErrorsInCode('''
const v = A.foo;
class A {
static void foo() {}
}
''');
_assertHasPrimitiveEqualityTrue('v');
}
test_hasPrimitiveEquality_functionReference_topLevelFunction() async {
await assertNoErrorsInCode('''
const v = foo;
void foo() {}
''');
_assertHasPrimitiveEqualityTrue('v');
}
test_hasPrimitiveEquality_int() async {
await assertNoErrorsInCode('''
const v = 0;
''');
_assertHasPrimitiveEqualityTrue('v');
}
test_hasPrimitiveEquality_list() async {
await assertNoErrorsInCode('''
const v = const [0];
''');
_assertHasPrimitiveEqualityTrue('v');
}
test_hasPrimitiveEquality_map() async {
await assertNoErrorsInCode('''
const v = const <int, String>{0: ''};
''');
_assertHasPrimitiveEqualityTrue('v');
}
test_hasPrimitiveEquality_null() async {
await assertNoErrorsInCode('''
const v = null;
''');
_assertHasPrimitiveEqualityTrue('v');
}
test_hasPrimitiveEquality_record_named_false() async {
await assertNoErrorsInCode('''
const v = (f1: true, f2: 1.2);
''');
_assertHasPrimitiveEqualityFalse('v');
}
test_hasPrimitiveEquality_record_named_true() async {
await assertNoErrorsInCode('''
const v = (f1: true, f2: 0);
''');
_assertHasPrimitiveEqualityTrue('v');
}
test_hasPrimitiveEquality_record_positional_false() async {
await assertNoErrorsInCode('''
const v = (true, 1.2);
''');
_assertHasPrimitiveEqualityFalse('v');
}
test_hasPrimitiveEquality_record_positional_true() async {
await assertNoErrorsInCode('''
const v = (true, 0);
''');
_assertHasPrimitiveEqualityTrue('v');
}
test_hasPrimitiveEquality_set() async {
await assertNoErrorsInCode('''
const v = const {0};
''');
_assertHasPrimitiveEqualityTrue('v');
}
test_hasPrimitiveEquality_symbol() async {
await assertNoErrorsInCode('''
const v = #foo.bar;
''');
_assertHasPrimitiveEqualityTrue('v');
}
test_hasPrimitiveEquality_type() async {
await assertNoErrorsInCode('''
const v = int;
''');
_assertHasPrimitiveEqualityTrue('v');
}
test_identical_typeLiteral_explicitTypeArgs_differentTypeArgs() async {
await assertNoErrorsInCode('''
class C<T> {}
const c = identical(C<int>, C<String>);
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::c
''');
}
test_identical_typeLiteral_explicitTypeArgs_differentTypes() async {
await assertNoErrorsInCode('''
class C<T> {}
class D<T> {}
const c = identical(C<int>, D<int>);
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::c
''');
}
test_identical_typeLiteral_explicitTypeArgs_sameType() async {
await assertNoErrorsInCode('''
class C<T> {}
const c = identical(C<int>, C<int>);
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::c
''');
}
test_identical_typeLiteral_explicitTypeArgs_simpleTypeAlias() async {
await assertNoErrorsInCode('''
class C<T> {}
typedef TC = C<int>;
const c = identical(C<int>, TC);
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::c
''');
}
test_identical_typeLiteral_explicitTypeArgs_typeAlias() async {
await assertNoErrorsInCode('''
class C<T> {}
typedef TC<T> = C<T>;
const c = identical(C<int>, TC<int>);
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::c
''');
}
test_identical_typeLiteral_explicitTypeArgs_typeAlias_differentTypeArgs() async {
await assertNoErrorsInCode('''
class C<T> {}
typedef TC<T> = C<T>;
const c = identical(C<int>, TC<String>);
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::c
''');
}
test_identical_typeLiteral_explicitTypeArgs_typeAlias_implicitTypeArgs() async {
await assertNoErrorsInCode('''
class C<T> {}
typedef TC<T> = C<T>;
const c = identical(C<dynamic>, TC);
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::c
''');
}
test_identical_typeLiteral_explicitTypeArgs_typeAlias_implicitTypeArgs_bound() async {
await assertNoErrorsInCode('''
class C<T extends num> {}
typedef TC<T extends num> = C<T>;
const c = identical(C<num>, TC);
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::c
''');
}
test_identical_typeLiteral_simple_differentTypes() async {
await assertNoErrorsInCode('''
const c = identical(int, String);
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::c
''');
}
test_identical_typeLiteral_simple_sameType() async {
await assertNoErrorsInCode('''
const c = identical(int, int);
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::c
''');
}
/// https://github.com/dart-lang/sdk/issues/53029
/// Dependencies of map patterns should be considered.
test_mapPattern_dependencies() async {
newFile('$testPackageLibPath/a.dart', r'''
const a = 0;
''');
await assertNoErrorsInCode('''
import 'a.dart';
void f(Object? x) {
if (x case {a: _}) {}
}
''');
}
test_visitBinaryExpression_extensionMethod() async {
await assertErrorsInCode('''
extension on Object {
int operator +(Object other) => 0;
}
const Object v1 = 0;
const v2 = v1 + v1;
''', [
error(CompileTimeErrorCode.CONST_EVAL_EXTENSION_METHOD, 94, 7),
]);
final result = _topLevelVar('v2');
_assertNull(result);
}
test_visitBinaryExpression_gtGtGt_negative_fewerBits() async {
await assertNoErrorsInCode('''
const c = 0xFFFFFFFF >>> 8;
''');
final result = _topLevelVar('c');
dartObjectPrinterConfiguration.withHexIntegers = true;
assertDartObjectText(result, r'''
int 0xffffff
variable: self::@variable::c
''');
}
test_visitBinaryExpression_gtGtGt_negative_moreBits() async {
await assertNoErrorsInCode('''
const c = 0xFFFFFFFF >>> 33;
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
int 0
variable: self::@variable::c
''');
}
test_visitBinaryExpression_gtGtGt_negative_moreThan64Bits() async {
await assertNoErrorsInCode('''
const c = 0xFFFFFFFF >>> 65;
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
int 0
variable: self::@variable::c
''');
}
test_visitBinaryExpression_gtGtGt_negative_negativeBits() async {
await assertErrorsInCode('''
const c = 0xFFFFFFFF >>> -2;
''', [
error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 10, 17),
]);
final result = _topLevelVar('c');
_assertNull(result);
}
test_visitBinaryExpression_gtGtGt_negative_zeroBits() async {
await assertNoErrorsInCode('''
const c = 0xFFFFFFFF >>> 0;
''');
final result = _topLevelVar('c');
dartObjectPrinterConfiguration.withHexIntegers = true;
assertDartObjectText(result, r'''
int 0xffffffff
variable: self::@variable::c
''');
}
test_visitBinaryExpression_gtGtGt_positive_fewerBits() async {
await assertNoErrorsInCode('''
const c = 0xFF >>> 3;
''');
final result = _topLevelVar('c');
dartObjectPrinterConfiguration.withHexIntegers = true;
assertDartObjectText(result, r'''
int 0x1f
variable: self::@variable::c
''');
}
test_visitBinaryExpression_gtGtGt_positive_moreBits() async {
await assertNoErrorsInCode('''
const c = 0xFF >>> 9;
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
int 0
variable: self::@variable::c
''');
}
test_visitBinaryExpression_gtGtGt_positive_moreThan64Bits() async {
await assertNoErrorsInCode('''
const c = 0xFF >>> 65;
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
int 0
variable: self::@variable::c
''');
}
test_visitBinaryExpression_gtGtGt_positive_negativeBits() async {
await assertErrorsInCode('''
const c = 0xFF >>> -2;
''', [
error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 10, 11),
]);
final result = _topLevelVar('c');
_assertNull(result);
}
test_visitBinaryExpression_gtGtGt_positive_zeroBits() async {
await assertNoErrorsInCode('''
const c = 0xFF >>> 0;
''');
final result = _topLevelVar('c');
dartObjectPrinterConfiguration.withHexIntegers = true;
assertDartObjectText(result, r'''
int 0xff
variable: self::@variable::c
''');
}
test_visitBinaryExpression_questionQuestion_invalid_notNull() async {
await assertErrorsInCode('''
final x = 0;
const c = x ?? 1;
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 23,
1),
error(StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION, 28, 1),
]);
}
test_visitBinaryExpression_questionQuestion_notNull_invalid() async {
await assertErrorsInCode('''
final x = 1;
const c = 0 ?? x;
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 28,
1),
error(StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION, 28, 1),
]);
}
test_visitConditionalExpression_eager_invalid_int_int() async {
await assertErrorsInCode('''
const c = null ? 1 : 0;
''', [
error(CompileTimeErrorCode.NON_BOOL_CONDITION, 10, 4),
error(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL, 10, 4),
]);
}
test_visitConditionalExpression_instantiatedFunctionType_variable() async {
await assertNoErrorsInCode('''
void f<T>(T p, {T? q}) {}
const void Function<T>(T p) g = f;
const bool b = false;
const void Function(int p) h = b ? g : g;
''');
final result = _topLevelVar('h');
assertDartObjectText(result, '''
void Function(int, {int? q})
element: self::@function::f
typeArguments
int
variable: self::@variable::h
''');
}
test_visitConditionalExpression_unknownCondition() async {
await assertNoErrorsInCode('''
const bool kIsWeb = identical(0, 0.0);
const x = kIsWeb ? 0 : 1;
''');
final result = _topLevelVar('x');
assertDartObjectText(result, r'''
<unknown> int
variable: self::@variable::x
''');
}
test_visitConditionalExpression_unknownCondition_errorInConstructor() async {
await assertErrorsInCode(r'''
const bool kIsWeb = identical(0, 0.0);
var a = 2;
const x = A(kIsWeb ? 0 : a);
class A {
const A(int _);
}
''', [
error(CompileTimeErrorCode.INVALID_CONSTANT, 76, 1),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 76,
1),
]);
final result = _topLevelVar('x');
_assertNull(result);
}
test_visitConditionalExpression_unknownCondition_undefinedIdentifier() async {
await assertErrorsInCode(r'''
const bool kIsWeb = identical(0, 0.0);
const x = kIsWeb ? a : b;
''', [
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 58, 1),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 58,
1),
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 62, 1),
]);
final result = _topLevelVar('x');
_assertNull(result);
}
test_visitConstructorDeclaration_field_asExpression_nonConst() async {
await assertErrorsInCode(r'''
dynamic y = 2;
class A {
const A();
final x = y as num;
}
''', [
error(
CompileTimeErrorCode
.CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST,
27,
5),
]);
}
test_visitConstructorReference_identical_aliasIsNotGeneric() async {
await assertNoErrorsInCode('''
class C<T> {}
typedef MyC = C<int>;
const a = identical(MyC.new, C<int>.new);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_aliasIsNotProperRename_differentBound() async {
await assertNoErrorsInCode('''
class C<T> {}
typedef MyC<T extends num> = C<T>;
const a = identical(MyC.new, C.new);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_aliasIsNotProperRename_differentCount() async {
await assertNoErrorsInCode('''
class C<T, U> {}
typedef MyC<T> = C<T, int>;
const a = identical(MyC.new, C.new);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_aliasIsNotProperRename_differentCount2() async {
await assertNoErrorsInCode('''
class C<T, U> {}
typedef MyC<T> = C;
const a = identical(MyC.new, C.new);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_aliasIsNotProperRename_differentOrder() async {
await assertNoErrorsInCode('''
class C<T, U> {}
typedef MyC<T, U> = C<U, T>;
const a = identical(MyC.new, C.new);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_aliasIsNotProperRename_instantiated() async {
await assertNoErrorsInCode('''
class C<T> {}
typedef MyC<T extends num> = C<T>;
const a = identical(MyC<int>.new, C<int>.new);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_aliasIsNotProperRename_mixedInstantiations() async {
await assertNoErrorsInCode('''
class C<T> {}
typedef MyC<T extends num> = C<T>;
const a = identical(MyC<int>.new, (MyC.new)<int>);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_aliasIsProperRename_instantiated() async {
await assertNoErrorsInCode('''
class C<T> {}
typedef MyC<T> = C<T>;
const a = identical(MyC<int>.new, MyC<int>.new);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_aliasIsProperRename_mixedInstantiations() async {
await assertNoErrorsInCode('''
class C<T> {}
typedef MyC<T> = C<T>;
const a = identical(MyC<int>.new, (MyC.new)<int>);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_aliasIsProperRename_mutualSubtypes_dynamic() async {
await assertNoErrorsInCode('''
class C<T> {}
typedef MyC<T extends Object?> = C<T>;
const a = identical(MyC<int>.new, MyC<int>.new);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_aliasIsProperRename_mutualSubtypes_futureOr() async {
await assertNoErrorsInCode('''
import 'dart:async';
class C<T extends FutureOr<num>> {}
typedef MyC<T extends num> = C<T>;
const a = identical(MyC<int>.new, MyC<int>.new);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_aliasIsProperRename_uninstantiated() async {
await assertNoErrorsInCode('''
class C<T> {}
typedef MyC<T> = C<T>;
const a = identical(MyC.new, MyC.new);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_explicitTypeArgs_differentClasses() async {
await assertNoErrorsInCode('''
class C<T> {}
class D<T> {}
const a = identical(C<int>.new, D<int>.new);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_explicitTypeArgs_differentConstructors() async {
await assertNoErrorsInCode('''
class C<T> {
C();
C.named();
}
const a = identical(C<int>.new, C<int>.named);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_explicitTypeArgs_differentTypeArgs() async {
await assertNoErrorsInCode('''
class C<T> {}
const a = identical(C<int>.new, C<String>.new);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_explicitTypeArgs_sameElement() async {
await assertNoErrorsInCode('''
class C<T> {}
const a = identical(C<int>.new, C<int>.new);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_inferredTypeArgs_sameElement() async {
await assertNoErrorsInCode('''
class C<T> {}
const C<int> Function() c1 = C.new;
const c2 = C<int>.new;
const a = identical(c1, c2);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_notInstantiated_differentClasses() async {
await assertNoErrorsInCode('''
class C<T> {}
class D<T> {}
const a = identical(C.new, D.new);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_notInstantiated_differentConstructors() async {
await assertNoErrorsInCode('''
class C<T> {
C();
C.named();
}
const a = identical(C.new, C.named);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_notInstantiated_sameElement() async {
await assertNoErrorsInCode('''
class C<T> {}
const a = identical(C.new, C.new);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::a
''');
}
test_visitConstructorReference_identical_onlyOneHasTypeArgs() async {
await assertNoErrorsInCode('''
class C<T> {}
const a = identical(C<int>.new, C.new);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::a
''');
}
test_visitFunctionReference_defaultConstructorValue() async {
await assertErrorsInCode(r'''
void f<T>(T t) => t;
class C<T> {
final void Function(T) p;
const C({this.p = f});
}
''', [
error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 83, 1),
]);
}
test_visitFunctionReference_explicitTypeArgs_complexExpression() async {
await assertNoErrorsInCode(r'''
const b = true;
void foo<T>(T a) {}
void bar<T>(T a) {}
const g = (b ? foo : bar)<int>;
''');
final result = _topLevelVar('g');
assertDartObjectText(result, r'''
void Function(int)
element: self::@function::foo
typeArguments
int
variable: self::@variable::g
''');
}
test_visitFunctionReference_explicitTypeArgs_complexExpression_differentTypes() async {
await assertNoErrorsInCode(r'''
const b = true;
void foo<T>(String a, T b) {}
void bar<T>(T a, String b) {}
const g = (b ? foo : bar)<int>;
''');
final result = _topLevelVar('g');
assertDartObjectText(result, r'''
void Function(String, int)
element: self::@function::foo
typeArguments
int
variable: self::@variable::g
''');
}
test_visitFunctionReference_explicitTypeArgs_functionName_constantType() async {
await assertNoErrorsInCode(r'''
void f<T>(T a) {}
const g = f<int>;
''');
final result = _topLevelVar('g');
assertDartObjectText(result, r'''
void Function(int)
element: self::@function::f
typeArguments
int
variable: self::@variable::g
''');
}
test_visitFunctionReference_explicitTypeArgs_functionName_notMatchingBound() async {
await assertErrorsInCode(r'''
void f<T extends num>(T a) {}
const g = f<String>;
''', [
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 42, 6),
]);
final result = _topLevelVar('g');
assertDartObjectText(result, r'''
void Function(String)
element: self::@function::f
typeArguments
String
variable: self::@variable::g
''');
}
test_visitFunctionReference_explicitTypeArgs_functionName_notType() async {
await assertErrorsInCode(r'''
void foo<T>(T a) {}
const g = foo<true>;
''', [
error(CompileTimeErrorCode.CONST_EVAL_TYPE_NUM, 30, 8),
error(CompileTimeErrorCode.UNDEFINED_OPERATOR, 33, 1),
error(ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND, 38, 1),
error(ParserErrorCode.MISSING_IDENTIFIER, 39, 1),
]);
final result = _topLevelVar('g');
_assertNull(result);
}
test_visitFunctionReference_explicitTypeArgs_functionName_tooFew() async {
await assertErrorsInCode(r'''
void foo<T, U>(T a, U b) {}
const g = foo<int>;
''', [
error(
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 41, 5),
]);
final result = _topLevelVar('g');
_assertNull(result);
}
test_visitFunctionReference_explicitTypeArgs_functionName_tooMany() async {
await assertErrorsInCode(r'''
void foo<T>(T a) {}
const g = foo<int, String>;
''', [
error(
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 33, 13),
]);
final result = _topLevelVar('g');
_assertNull(result);
}
test_visitFunctionReference_explicitTypeArgs_functionName_typeParameter() async {
await assertErrorsInCode(r'''
void f<T>(T a) {}
class C<U> {
void m() {
const g = f<U>;
}
}
''', [
error(WarningCode.UNUSED_LOCAL_VARIABLE, 55, 1),
error(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF,
61, 1),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 61,
1),
]);
}
test_visitFunctionReference_explicitTypeArgs_identical_differentElements() async {
await assertNoErrorsInCode(r'''
void foo<T>(T a) {}
void bar<T>(T a) {}
const g = identical(foo<int>, bar<int>);
''');
final result = _topLevelVar('g');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::g
''');
}
test_visitFunctionReference_explicitTypeArgs_identical_differentTypeArgs() async {
await assertNoErrorsInCode(r'''
void foo<T>(T a) {}
const g = identical(foo<int>, foo<String>);
''');
final result = _topLevelVar('g');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::g
''');
}
test_visitFunctionReference_explicitTypeArgs_identical_onlyOneHasTypeArgs() async {
await assertNoErrorsInCode(r'''
void foo<T>(T a) {}
const g = identical(foo<int>, foo);
''');
final result = _topLevelVar('g');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::g
''');
}
test_visitFunctionReference_explicitTypeArgs_identical_sameElement() async {
await assertNoErrorsInCode(r'''
void foo<T>(T a) {}
const g = identical(foo<int>, foo<int>);
''');
final result = _topLevelVar('g');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::g
''');
}
test_visitFunctionReference_explicitTypeArgs_identical_sameElement_runtimeTypeEquality() async {
await assertNoErrorsInCode(r'''
import 'dart:async';
void foo<T>(T a) {}
const g = identical(foo<Object>, foo<FutureOr<Object>>);
''');
final result = _topLevelVar('g');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::g
''');
}
test_visitFunctionReference_identical_explicitTypeArgs_differentElements() async {
await assertNoErrorsInCode(r'''
void foo<T>(T a) {}
void bar<T>(T a) {}
const g = identical(foo<int>, bar<int>);
''');
final result = _topLevelVar('g');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::g
''');
}
test_visitFunctionReference_identical_explicitTypeArgs_differentTypeArgs() async {
await assertNoErrorsInCode(r'''
void foo<T>(T a) {}
const g = identical(foo<int>, foo<String>);
''');
final result = _topLevelVar('g');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::g
''');
}
test_visitFunctionReference_identical_explicitTypeArgs_onlyOneHasTypeArgs() async {
await assertNoErrorsInCode(r'''
void foo<T>(T a) {}
const g = identical(foo<int>, foo);
''');
final result = _topLevelVar('g');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::g
''');
}
test_visitFunctionReference_identical_explicitTypeArgs_sameElement() async {
await assertNoErrorsInCode(r'''
void foo<T>(T a) {}
const g = identical(foo<int>, foo<int>);
''');
final result = _topLevelVar('g');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::g
''');
}
test_visitFunctionReference_identical_explicitTypeArgs_sameElement_runtimeTypeEquality() async {
await assertNoErrorsInCode(r'''
import 'dart:async';
void foo<T>(T a) {}
const g = identical(foo<Object>, foo<FutureOr<Object>>);
''');
final result = _topLevelVar('g');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::g
''');
}
test_visitFunctionReference_identical_implicitTypeArgs_differentTypes() async {
await assertNoErrorsInCode(r'''
void foo<T>(T a) {}
const void Function(int) f = foo;
const void Function(String) g = foo;
const c = identical(f, g);
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::c
''');
}
test_visitFunctionReference_identical_implicitTypeArgs_sameTypes() async {
await assertNoErrorsInCode(r'''
void foo<T>(T a) {}
const void Function(int) f = foo;
const void Function(int) g = foo;
const c = identical(f, g);
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::c
''');
}
test_visitFunctionReference_identical_uninstantiated_sameElement() async {
await assertNoErrorsInCode(r'''
void foo<T>(T a) {}
const c = identical(foo, foo);
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::c
''');
}
test_visitFunctionReference_implicitTypeArgs_identical_differentTypes() async {
await assertNoErrorsInCode(r'''
void foo<T>(T a) {}
const void Function(int) f = foo;
const void Function(String) g = foo;
const c = identical(f, g);
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::c
''');
}
test_visitFunctionReference_implicitTypeArgs_identical_sameTypes() async {
await assertNoErrorsInCode(r'''
void foo<T>(T a) {}
const void Function(int) f = foo;
const void Function(int) g = foo;
const c = identical(f, g);
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::c
''');
}
test_visitFunctionReference_uninstantiated_complexExpression() async {
await assertNoErrorsInCode(r'''
const b = true;
void foo<T>(T a) {}
void bar<T>(T a) {}
const g = b ? foo : bar;
''');
final result = _topLevelVar('g');
assertDartObjectText(result, r'''
void Function<T>(T)
element: self::@function::foo
variable: self::@variable::g
''');
}
test_visitFunctionReference_uninstantiated_functionName() async {
await assertNoErrorsInCode(r'''
void f<T>(T a) {}
const g = f;
''');
final result = _topLevelVar('g');
assertDartObjectText(result, r'''
void Function<T>(T)
element: self::@function::f
variable: self::@variable::g
''');
}
test_visitFunctionReference_uninstantiated_identical_sameElement() async {
await assertNoErrorsInCode(r'''
void foo<T>(T a) {}
const c = identical(foo, foo);
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::c
''');
}
test_visitInterpolationExpression_list() async {
await assertErrorsInCode(r'''
const x = '${const [2]}';
''', [
error(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING, 11, 12),
]);
}
test_visitIsExpression_is_functionType_correctTypes() async {
await assertErrorsInCode('''
void foo(int a) {}
const c = foo is void Function(int);
''', [
error(WarningCode.UNNECESSARY_TYPE_CHECK_TRUE, 29, 25),
]);
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::c
''');
}
test_visitIsExpression_is_instanceOfSameClass() async {
await assertErrorsInCode('''
const a = const A();
const b = a is A;
class A {
const A();
}
''', [
error(WarningCode.UNNECESSARY_TYPE_CHECK_TRUE, 31, 6),
]);
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::b
''');
}
test_visitIsExpression_is_instanceOfSubclass() async {
await assertErrorsInCode('''
const a = const B();
const b = a is A;
class A {
const A();
}
class B extends A {
const B();
}
''', [
error(WarningCode.UNNECESSARY_TYPE_CHECK_TRUE, 31, 6),
]);
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::b
''');
}
test_visitIsExpression_is_null() async {
await assertNoErrorsInCode('''
const a = null;
const b = a is A;
class A {}
''');
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::b
''');
}
test_visitIsExpression_is_null_nullable() async {
await assertNoErrorsInCode('''
const a = null;
const b = a is A?;
class A {}
''');
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::b
''');
}
test_visitIsExpression_is_null_object() async {
await assertNoErrorsInCode('''
const a = null;
const b = a is Object;
''');
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::b
''');
}
test_visitIsExpression_isNot_instanceOfSameClass() async {
await assertErrorsInCode('''
const a = const A();
const b = a is! A;
class A {
const A();
}
''', [
error(WarningCode.UNNECESSARY_TYPE_CHECK_FALSE, 31, 7),
]);
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::b
''');
}
test_visitIsExpression_isNot_instanceOfSubclass() async {
await assertErrorsInCode('''
const a = const B();
const b = a is! A;
class A {
const A();
}
class B extends A {
const B();
}
''', [
error(WarningCode.UNNECESSARY_TYPE_CHECK_FALSE, 31, 7),
]);
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::b
''');
}
test_visitIsExpression_isNot_null() async {
await assertNoErrorsInCode('''
const a = null;
const b = a is! A;
class A {}
''');
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::b
''');
}
test_visitListLiteral_forElement() async {
await assertErrorsInCode(r'''
const x = [for (int i = 0; i < 3; i++) i];
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 10,
31),
error(CompileTimeErrorCode.CONST_EVAL_FOR_ELEMENT, 11, 29),
]);
final result = _topLevelVar('x');
_assertNull(result);
}
test_visitListLiteral_ifElement_nonBoolCondition() async {
await assertErrorsInCode(r'''
const dynamic c = 2;
const x = [1, if (c) 2 else 3, 4];
''', [
error(CompileTimeErrorCode.NON_BOOL_CONDITION, 39, 1),
]);
final result = _topLevelVar('x');
_assertNull(result);
}
test_visitListLiteral_ifElement_nonBoolCondition_static() async {
await assertErrorsInCode(r'''
const x = [1, if (1) 2 else 3, 4];
''', [
error(CompileTimeErrorCode.NON_BOOL_CONDITION, 18, 1),
]);
final result = _topLevelVar('x');
_assertNull(result);
}
test_visitListLiteral_spreadElement() async {
await assertErrorsInCode(r'''
const dynamic a = 5;
const x = <int>[...a];
''', [
error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET, 40, 1),
]);
final result = _topLevelVar('x');
_assertNull(result);
}
test_visitMethodInvocation_notIdentical() async {
await assertErrorsInCode(r'''
int f() {
return 3;
}
const a = f();
''', [
error(CompileTimeErrorCode.CONST_EVAL_METHOD_INVOCATION, 34, 3),
]);
}
test_visitNamedType_typeLiteral_typeParameter_nested() async {
await assertErrorsInCode(r'''
void f<T>(Object? x) {
if (x case const (T)) {}
}
''', [
error(CompileTimeErrorCode.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION,
43, 1),
]);
}
test_visitNamedType_typeLiteral_typeParameter_nested2() async {
await assertErrorsInCode(r'''
void f<T>(Object? x) {
if (x case const (List<T>)) {}
}
''', [
error(CompileTimeErrorCode.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION,
43, 7),
]);
}
test_visitPrefixedIdentifier_function() async {
await assertNoErrorsInCode('''
import '' as self;
void f(int a) {}
const g = self.f;
''');
final result = _topLevelVar('g');
assertDartObjectText(result, '''
void Function(int)
element: self::@function::f
variable: self::@variable::g
''');
}
test_visitPrefixedIdentifier_genericFunction_instantiated() async {
await assertNoErrorsInCode('''
import '' as self;
void f<T>(T a) {}
const void Function(int) g = self.f;
''');
final result = _topLevelVar('g');
assertDartObjectText(result, '''
void Function(int)
element: self::@function::f
typeArguments
int
variable: self::@variable::g
''');
}
test_visitPrefixedIdentifier_genericFunction_instantiatedNonIdentifier() async {
await assertNoErrorsInCode('''
void f<T>(T a) {}
const b = false;
const g1 = f;
const g2 = f;
const void Function(int) h = b ? g1 : g2;
''');
final result = _topLevelVar('h');
assertDartObjectText(result, '''
void Function(int)
element: self::@function::f
typeArguments
int
variable: self::@variable::h
''');
}
test_visitPrefixedIdentifier_genericFunction_instantiatedPrefixed() async {
await assertNoErrorsInCode('''
import '' as self;
void f<T>(T a) {}
const g = f;
const void Function(int) h = self.g;
''');
final result = _topLevelVar('h');
assertDartObjectText(result, '''
void Function(int)
element: self::@function::f
typeArguments
int
variable: self::@variable::h
''');
}
test_visitPrefixedIdentifier_genericVariable_uninstantiated() async {
await assertNoErrorsInCode('''
import '' as self;
void f<T>(T a) {}
const g = f;
const h = self.g;
''');
final result = _topLevelVar('h');
assertDartObjectText(result, '''
void Function<T>(T)
element: self::@function::f
variable: self::@variable::h
''');
}
test_visitPrefixExpression_extensionMethod() async {
await assertErrorsInCode('''
extension on Object {
int operator -() => 0;
}
const Object v1 = 1;
const v2 = -v1;
''', [
error(CompileTimeErrorCode.CONST_EVAL_EXTENSION_METHOD, 82, 3),
]);
final result = _topLevelVar('v2');
_assertNull(result);
}
test_visitPropertyAccess_genericFunction_instantiated() async {
await assertNoErrorsInCode('''
import '' as self;
class C {
static void f<T>(T a) {}
}
const void Function(int) g = self.C.f;
''');
final result = _topLevelVar('g');
assertDartObjectText(result, '''
void Function(int)
element: self::@class::C::@method::f
typeArguments
int
variable: self::@variable::g
''');
}
test_visitRecordLiteral_objectField_generic() async {
await assertNoErrorsInCode(r'''
class A<T> {
final (T, T) record;
const A(T a) : record = (a, a);
}
const a = A(42);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
A<int>
record: Record(int, int)
positionalFields
$1: int 42
$2: int 42
variable: self::@variable::a
''');
}
test_visitRecordLiteral_withoutEnvironment() async {
await assertNoErrorsInCode(r'''
const a = (1, 'b', c: false);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
Record(int, String, {bool c})
positionalFields
$1: int 1
$2: String b
namedFields
c: bool false
variable: self::@variable::a
''');
}
test_visitSetOrMapLiteral_map_forElement() async {
await assertErrorsInCode(r'''
const x = {1: null, for (final i in const []) i: null};
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 10,
44),
error(CompileTimeErrorCode.CONST_EVAL_FOR_ELEMENT, 20, 33),
]);
final result = _topLevelVar('x');
_assertNull(result);
}
test_visitSetOrMapLiteral_map_forElement_nested() async {
await assertErrorsInCode(r'''
const x = {1: null, if (true) for (final i in const []) i: null};
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 10,
54),
error(CompileTimeErrorCode.CONST_EVAL_FOR_ELEMENT, 30, 33),
]);
final result = _topLevelVar('x');
_assertNull(result);
}
test_visitSetOrMapLiteral_map_ifElement_nonBoolCondition() async {
await assertErrorsInCode(r'''
const dynamic nonBool = null;
const c = const {if (nonBool) 'a' : 1};
''', [
error(CompileTimeErrorCode.NON_BOOL_CONDITION, 51, 7),
]);
final result = _topLevelVar('c');
_assertNull(result);
}
test_visitSetOrMapLiteral_set_forElement() async {
await assertErrorsInCode(r'''
const Set set = {};
const x = {for (final i in set) i};
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 30,
24),
error(CompileTimeErrorCode.CONST_EVAL_FOR_ELEMENT, 31, 22),
]);
final result = _topLevelVar('x');
_assertNull(result);
}
test_visitSetOrMapLiteral_set_ifElement_nonBoolCondition() async {
await assertErrorsInCode(r'''
const dynamic nonBool = 'a';
const c = const {if (nonBool) 3};
''', [
error(CompileTimeErrorCode.NON_BOOL_CONDITION, 50, 7),
]);
final result = _topLevelVar('c');
_assertNull(result);
}
test_visitSimpleIdentifier_className() async {
await assertNoErrorsInCode('''
const a = C;
class C {}
''');
final result = _topLevelVar('a');
assertDartObjectText(result, '''
Type C*
variable: self::@variable::a
''');
}
test_visitSimpleIdentifier_function() async {
await assertNoErrorsInCode('''
void f(int a) {}
const g = f;
''');
final result = _topLevelVar('g');
assertDartObjectText(result, '''
void Function(int)
element: self::@function::f
variable: self::@variable::g
''');
}
test_visitSimpleIdentifier_genericFunction_instantiated() async {
await assertNoErrorsInCode('''
void f<T>(T a) {}
const void Function(int) g = f;
''');
final result = _topLevelVar('g');
assertDartObjectText(result, '''
void Function(int)
element: self::@function::f
typeArguments
int
variable: self::@variable::g
''');
}
test_visitSimpleIdentifier_genericFunction_nonGeneric() async {
await assertNoErrorsInCode('''
void f(int a) {}
const void Function(int) g = f;
''');
final result = _topLevelVar('g');
assertDartObjectText(result, '''
void Function(int)
element: self::@function::f
variable: self::@variable::g
''');
}
test_visitSimpleIdentifier_genericVariable_instantiated() async {
await assertNoErrorsInCode('''
void f<T>(T a) {}
const g = f;
const void Function(int) h = g;
''');
final result = _topLevelVar('h');
assertDartObjectText(result, '''
void Function(int)
element: self::@function::f
typeArguments
int
variable: self::@variable::h
''');
}
test_visitSimpleIdentifier_genericVariable_uninstantiated() async {
await assertNoErrorsInCode('''
void f<T>(T a) {}
const g = f;
const h = g;
''');
final result = _topLevelVar('h');
assertDartObjectText(result, '''
void Function<T>(T)
element: self::@function::f
variable: self::@variable::h
''');
}
test_visitSimpleIdentifier_instantiatedFunctionType_field() async {
await assertNoErrorsInCode('''
void f<T>(T a, {T? b}) {}
class C {
static const void Function<T>(T a) g = f;
static const void Function(int a) h = g;
}
''');
final result = _field('h');
assertDartObjectText(result, '''
void Function(int, {int? b})
element: self::@function::f
typeArguments
int
variable: self::@class::C::@field::h
''');
}
test_visitSimpleIdentifier_instantiatedFunctionType_parameter() async {
await assertNoErrorsInCode('''
void f<T>(T a, {T? b}) {}
class C {
const C(void Function<T>(T a) g) : h = g;
final void Function(int a) h;
}
const c = C(f);
''');
final result = _topLevelVar('c');
assertDartObjectText(result, '''
C
h: void Function(int, {int? b})
element: self::@function::f
typeArguments
int
variable: self::@variable::c
''');
}
test_visitSimpleIdentifier_instantiatedFunctionType_variable() async {
await assertNoErrorsInCode('''
void f<T>(T a, {T? b}) {}
const void Function<T>(T a) g = f;
const void Function(int a) h = g;
''');
final result = _topLevelVar('h');
assertDartObjectText(result, '''
void Function(int, {int? b})
element: self::@function::f
typeArguments
int
variable: self::@variable::h
''');
}
void _assertHasPrimitiveEqualityFalse(String name) {
final value = _evaluateConstant(name);
final featureSet = result.libraryElement.featureSet;
final has = value.hasPrimitiveEquality(featureSet);
expect(has, isFalse);
}
void _assertHasPrimitiveEqualityTrue(String name) {
final value = _evaluateConstant(name);
final featureSet = result.libraryElement.featureSet;
final has = value.hasPrimitiveEquality(featureSet);
expect(has, isTrue);
}
}
@reflectiveTest
mixin ConstantVisitorTestCases on ConstantVisitorTestSupport {
test_listLiteral_ifElement_false_withElse() async {
await resolveTestCode('''
const c = [1, if (1 < 0) 2 else 3, 4];
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.listType(typeProvider.intType));
expect(result.toListValue()!.map((e) => e.toIntValue()), [1, 3, 4]);
}
test_listLiteral_ifElement_false_withoutElse() async {
await resolveTestCode('''
const c = [1, if (1 < 0) 2, 3];
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.listType(typeProvider.intType));
expect(result.toListValue()!.map((e) => e.toIntValue()), [1, 3]);
}
test_listLiteral_ifElement_true_withElse() async {
await resolveTestCode('''
const c = [1, if (1 > 0) 2 else 3, 4];
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.listType(typeProvider.intType));
expect(result.toListValue()!.map((e) => e.toIntValue()), [1, 2, 4]);
}
test_listLiteral_ifElement_true_withoutElse() async {
await resolveTestCode('''
const c = [1, if (1 > 0) 2, 3];
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.listType(typeProvider.intType));
expect(result.toListValue()!.map((e) => e.toIntValue()), [1, 2, 3]);
}
test_listLiteral_nested() async {
await resolveTestCode('''
const c = [1, if (1 > 0) if (2 > 1) 2, 3];
''');
DartObjectImpl result = _evaluateConstant('c');
// The expected type ought to be `List<int>`, but type inference isn't yet
// implemented.
expect(result.type, typeProvider.listType(typeProvider.intType));
expect(result.toListValue()!.map((e) => e.toIntValue()), [1, 2, 3]);
}
test_listLiteral_spreadElement() async {
await resolveTestCode('''
const c = [1, ...[2, 3], 4];
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.listType(typeProvider.intType));
expect(result.toListValue()!.map((e) => e.toIntValue()), [1, 2, 3, 4]);
}
test_mapLiteral_ifElement_false_withElse() async {
await resolveTestCode('''
const c = {'a' : 1, if (1 < 0) 'b' : 2 else 'c' : 3, 'd' : 4};
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type,
typeProvider.mapType(typeProvider.stringType, typeProvider.intType));
Map<DartObject, DartObject> value = result.toMapValue()!;
expect(value.keys.map((e) => e.toStringValue()),
unorderedEquals(['a', 'c', 'd']));
expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 3, 4]));
}
test_mapLiteral_ifElement_false_withoutElse() async {
await resolveTestCode('''
const c = {'a' : 1, if (1 < 0) 'b' : 2, 'c' : 3};
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type,
typeProvider.mapType(typeProvider.stringType, typeProvider.intType));
Map<DartObject, DartObject> value = result.toMapValue()!;
expect(
value.keys.map((e) => e.toStringValue()), unorderedEquals(['a', 'c']));
expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 3]));
}
test_mapLiteral_ifElement_true_withElse() async {
await resolveTestCode('''
const c = {'a' : 1, if (1 > 0) 'b' : 2 else 'c' : 3, 'd' : 4};
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type,
typeProvider.mapType(typeProvider.stringType, typeProvider.intType));
Map<DartObject, DartObject> value = result.toMapValue()!;
expect(value.keys.map((e) => e.toStringValue()),
unorderedEquals(['a', 'b', 'd']));
expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 2, 4]));
}
test_mapLiteral_ifElement_true_withoutElse() async {
await resolveTestCode('''
const c = {'a' : 1, if (1 > 0) 'b' : 2, 'c' : 3};
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type,
typeProvider.mapType(typeProvider.stringType, typeProvider.intType));
Map<DartObject, DartObject> value = result.toMapValue()!;
expect(value.keys.map((e) => e.toStringValue()),
unorderedEquals(['a', 'b', 'c']));
expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 2, 3]));
}
@failingTest
test_mapLiteral_nested() async {
// Fails because we're not yet parsing nested elements.
await resolveTestCode('''
const c = {'a' : 1, if (1 > 0) if (2 > 1) {'b' : 2}, 'c' : 3};
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type,
typeProvider.mapType(typeProvider.intType, typeProvider.intType));
Map<DartObject, DartObject> value = result.toMapValue()!;
expect(value.keys.map((e) => e.toStringValue()),
unorderedEquals(['a', 'b', 'c']));
expect(value.values.map((e) => e.toIntValue()), unorderedEquals([1, 2, 3]));
}
test_mapLiteral_spreadElement() async {
await resolveTestCode('''
const c = {'a' : 1, ...{'b' : 2, 'c' : 3}, 'd' : 4};
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type,
typeProvider.mapType(typeProvider.stringType, typeProvider.intType));
Map<DartObject, DartObject> value = result.toMapValue()!;
expect(value.keys.map((e) => e.toStringValue()),
unorderedEquals(['a', 'b', 'c', 'd']));
expect(
value.values.map((e) => e.toIntValue()), unorderedEquals([1, 2, 3, 4]));
}
test_setLiteral_ifElement_false_withElse() async {
await resolveTestCode('''
const c = {1, if (1 < 0) 2 else 3, 4};
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.setType(typeProvider.intType));
expect(result.toSetValue()!.map((e) => e.toIntValue()), [1, 3, 4]);
}
test_setLiteral_ifElement_false_withoutElse() async {
await resolveTestCode('''
const c = {1, if (1 < 0) 2, 3};
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.setType(typeProvider.intType));
expect(result.toSetValue()!.map((e) => e.toIntValue()), [1, 3]);
}
test_setLiteral_ifElement_true_withElse() async {
await resolveTestCode('''
const c = {1, if (1 > 0) 2 else 3, 4};
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.setType(typeProvider.intType));
expect(result.toSetValue()!.map((e) => e.toIntValue()), [1, 2, 4]);
}
test_setLiteral_ifElement_true_withoutElse() async {
await resolveTestCode('''
const c = {1, if (1 > 0) 2, 3};
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.setType(typeProvider.intType));
expect(result.toSetValue()!.map((e) => e.toIntValue()), [1, 2, 3]);
}
test_setLiteral_nested() async {
await resolveTestCode('''
const c = {1, if (1 > 0) if (2 > 1) 2, 3};
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.setType(typeProvider.intType));
expect(result.toSetValue()!.map((e) => e.toIntValue()), [1, 2, 3]);
}
test_setLiteral_spreadElement() async {
await resolveTestCode('''
const c = {1, ...{2, 3}, 4};
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.setType(typeProvider.intType));
expect(result.toSetValue()!.map((e) => e.toIntValue()), [1, 2, 3, 4]);
}
test_typeParameter() async {
await assertErrorsInCode('''
class A<X> {
const A();
void m() {
const x = X;
}
}
''', [
error(WarningCode.UNUSED_LOCAL_VARIABLE, 49, 1),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 53,
1),
]);
final result = _localVar('x');
_assertNull(result);
}
test_visitAsExpression_instanceOfSameClass() async {
await resolveTestCode('''
const a = const A();
const b = a as A;
class A {
const A();
}
''');
DartObjectImpl resultA = _evaluateConstant('a');
DartObjectImpl resultB = _evaluateConstant('b');
expect(resultB, resultA);
}
test_visitAsExpression_instanceOfSubclass() async {
await resolveTestCode('''
const a = const B();
const b = a as A;
class A {
const A();
}
class B extends A {
const B();
}
''');
DartObjectImpl resultA = _evaluateConstant('a');
DartObjectImpl resultB = _evaluateConstant('b');
expect(resultB, resultA);
}
test_visitAsExpression_instanceOfSuperclass() async {
await assertErrorsInCode('''
const a = const A();
const b = a as B;
class A {
const A();
}
class B extends A {
const B();
}
''', [
error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 31, 6),
]);
var result = _topLevelVar('b');
_assertNull(result);
}
test_visitAsExpression_instanceOfUnrelatedClass() async {
await assertErrorsInCode('''
const a = const A();
const b = a as B;
class A {
const A();
}
class B {
const B();
}
''', [
error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 31, 6),
]);
var result = _topLevelVar('b');
_assertNull(result);
}
test_visitAsExpression_potentialConst() async {
await assertNoErrorsInCode('''
class A {
const A();
}
class MyClass {
final A a;
const MyClass(Object o) : a = o as A;
}
''');
}
test_visitBinaryExpression_and_bool_false_invalid() async {
await assertErrorsInCode('''
final a = false;
const c = false && a;
''', [
error(WarningCode.DEAD_CODE, 33, 4),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 36,
1),
]);
}
test_visitBinaryExpression_and_bool_invalid_false() async {
await assertErrorsInCode('''
final a = false;
const c = a && false;
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 27,
1),
]);
}
test_visitBinaryExpression_and_bool_invalid_true() async {
await assertErrorsInCode('''
final a = false;
const c = a && true;
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 27,
1),
]);
}
test_visitBinaryExpression_and_bool_known_known() async {
await resolveTestCode('''
const c = false & true;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.boolType);
}
test_visitBinaryExpression_and_bool_known_unknown() async {
await resolveTestCode('''
const b = bool.fromEnvironment('y');
const c = false & b;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.boolType);
}
test_visitBinaryExpression_and_bool_true_invalid() async {
await assertErrorsInCode('''
final a = false;
const c = true && a;
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 27,
9),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 35,
1),
]);
}
test_visitBinaryExpression_and_bool_unknown_known() async {
await resolveTestCode('''
const a = bool.fromEnvironment('x');
const c = a & true;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.boolType);
}
test_visitBinaryExpression_and_bool_unknown_unknown() async {
await resolveTestCode('''
const a = bool.fromEnvironment('x');
const b = bool.fromEnvironment('y');
const c = a & b;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.boolType);
}
test_visitBinaryExpression_and_int() async {
await resolveTestCode('''
const c = 3 & 5;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.intType);
}
test_visitBinaryExpression_and_mixed() async {
await assertErrorsInCode('''
const c = 3 & false;
''', [
error(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT, 10, 9),
error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 14, 5),
]);
}
test_visitBinaryExpression_or_bool_false_invalid() async {
await assertErrorsInCode('''
final a = false;
const c = false || a;
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 27,
10),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 36,
1),
]);
}
test_visitBinaryExpression_or_bool_invalid_false() async {
await assertErrorsInCode('''
final a = false;
const c = a || false;
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 27,
1),
]);
}
test_visitBinaryExpression_or_bool_invalid_true() async {
await assertErrorsInCode('''
final a = false;
const c = a || true;
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 27,
1),
]);
}
test_visitBinaryExpression_or_bool_known_known() async {
await resolveTestCode('''
const c = false | true;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.boolType);
}
test_visitBinaryExpression_or_bool_known_unknown() async {
await resolveTestCode('''
const b = bool.fromEnvironment('y');
const c = false | b;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.boolType);
}
test_visitBinaryExpression_or_bool_true_invalid() async {
await assertErrorsInCode('''
final a = false;
const c = true || a;
''', [
error(WarningCode.DEAD_CODE, 32, 4),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 35,
1),
]);
}
test_visitBinaryExpression_or_bool_unknown_known() async {
await resolveTestCode('''
const a = bool.fromEnvironment('x');
const c = a | true;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.boolType);
}
test_visitBinaryExpression_or_bool_unknown_unknown() async {
await resolveTestCode('''
const a = bool.fromEnvironment('x');
const b = bool.fromEnvironment('y');
const c = a | b;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.boolType);
}
test_visitBinaryExpression_or_int() async {
await resolveTestCode('''
const c = 3 | 5;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.intType);
}
test_visitBinaryExpression_or_mixed() async {
await assertErrorsInCode('''
const c = 3 | false;
''', [
error(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT, 10, 9),
error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 14, 5),
]);
}
test_visitBinaryExpression_questionQuestion_notNull_notNull() async {
await resolveTestCode('''
const c = 'a' ?? 'b';
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.stringType);
expect(result.toStringValue(), 'a');
}
test_visitBinaryExpression_questionQuestion_null_invalid() async {
await assertErrorsInCode('''
const c = null ?? new C();
class C {}
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 18,
7),
]);
}
test_visitBinaryExpression_questionQuestion_null_notNull() async {
await resolveTestCode('''
const c = null ?? 'b';
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.stringType);
expect(result.toStringValue(), 'b');
}
test_visitBinaryExpression_questionQuestion_null_null() async {
await resolveTestCode('''
const c = null ?? null;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.isNull, isTrue);
}
test_visitBinaryExpression_xor_bool_known_known() async {
await resolveTestCode('''
const c = false ^ true;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.boolType);
}
test_visitBinaryExpression_xor_bool_known_unknown() async {
await resolveTestCode('''
const b = bool.fromEnvironment('y');
const c = false ^ b;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.boolType);
}
test_visitBinaryExpression_xor_bool_unknown_known() async {
await resolveTestCode('''
const a = bool.fromEnvironment('x');
const c = a ^ true;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.boolType);
}
test_visitBinaryExpression_xor_bool_unknown_unknown() async {
await resolveTestCode('''
const a = bool.fromEnvironment('x');
const b = bool.fromEnvironment('y');
const c = a ^ b;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.boolType);
}
test_visitBinaryExpression_xor_int() async {
await resolveTestCode('''
const c = 3 ^ 5;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.intType);
}
test_visitBinaryExpression_xor_mixed() async {
await assertErrorsInCode('''
const c = 3 ^ false;
''', [
error(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT, 10, 9),
error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 14, 5),
]);
}
test_visitConditionalExpression_eager_false_int_int() async {
await assertErrorsInCode('''
const c = false ? 1 : 0;
''', [
error(WarningCode.DEAD_CODE, 18, 1),
]);
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
int 0
variable: self::@variable::c
''');
}
test_visitConditionalExpression_eager_true_int_int() async {
await assertErrorsInCode('''
const c = true ? 1 : 0;
''', [
error(WarningCode.DEAD_CODE, 21, 1),
]);
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
int 1
variable: self::@variable::c
''');
}
test_visitConditionalExpression_eager_true_int_invalid() async {
await assertErrorsInCode('''
const c = true ? 1 : x;
''', [
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 21, 1),
error(WarningCode.DEAD_CODE, 21, 1),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 21,
1),
]);
}
test_visitConditionalExpression_eager_true_invalid_int() async {
await assertErrorsInCode('''
const c = true ? x : 0;
''', [
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 17, 1),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 17,
1),
error(WarningCode.DEAD_CODE, 21, 1),
]);
}
test_visitConditionalExpression_lazy_false_int_int() async {
await assertErrorsInCode('''
const c = false ? 1 : 0;
''', [
error(WarningCode.DEAD_CODE, 18, 1),
]);
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
int 0
variable: self::@variable::c
''');
}
test_visitConditionalExpression_lazy_false_int_invalid() async {
await assertErrorsInCode('''
const c = false ? 1 : new C();
''', [
error(WarningCode.DEAD_CODE, 18, 1),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 22,
7),
error(CompileTimeErrorCode.NEW_WITH_NON_TYPE, 26, 1),
]);
}
test_visitConditionalExpression_lazy_false_invalid_int() async {
await assertErrorsInCode('''
const c = false ? new C() : 0;
''', [
error(WarningCode.DEAD_CODE, 18, 7),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 18,
7),
error(CompileTimeErrorCode.NEW_WITH_NON_TYPE, 22, 1),
]);
}
test_visitConditionalExpression_lazy_invalid_int_int() async {
await assertErrorsInCode('''
const c = 3 ? 1 : 0;
''', [
error(CompileTimeErrorCode.NON_BOOL_CONDITION, 10, 1),
error(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL, 10, 1),
]);
}
test_visitConditionalExpression_lazy_true_int_int() async {
await assertErrorsInCode('''
const c = true ? 1 : 0;
''', [
error(WarningCode.DEAD_CODE, 21, 1),
]);
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
int 1
variable: self::@variable::c
''');
}
test_visitConditionalExpression_lazy_true_int_invalid() async {
await assertErrorsInCode('''
const c = true ? 1: new C();
''', [
error(WarningCode.DEAD_CODE, 20, 7),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 20,
7),
error(CompileTimeErrorCode.NEW_WITH_NON_TYPE, 24, 1),
]);
}
test_visitConditionalExpression_lazy_true_invalid_int() async {
await assertErrorsInCode('''
const c = true ? new C() : 0;
class C {}
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 17,
7),
error(WarningCode.DEAD_CODE, 27, 1),
]);
}
test_visitConditionalExpression_lazy_unknown_int_invalid() async {
await assertErrorsInCode('''
const c = identical(0, 0.0) ? 1 : new Object();
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 34,
12),
]);
}
test_visitConditionalExpression_lazy_unknown_invalid_int() async {
await assertErrorsInCode('''
const c = identical(0, 0.0) ? 1 : new Object();
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 34,
12),
]);
}
test_visitIntegerLiteral() async {
await resolveTestCode('''
const double d = 3;
''');
DartObjectImpl result = _evaluateConstant('d');
expect(result.type, typeProvider.doubleType);
expect(result.toDoubleValue(), 3.0);
}
test_visitIsExpression_is_functionType_badTypes() async {
await assertNoErrorsInCode('''
void foo(int a) {}
const c = foo is void Function(String);
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::c
''');
}
test_visitIsExpression_is_functionType_nonFunction() async {
await assertNoErrorsInCode('''
const c = false is void Function();
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::c
''');
}
test_visitIsExpression_is_instanceOfSuperclass() async {
await assertNoErrorsInCode('''
const a = const A();
const b = a is B;
class A {
const A();
}
class B extends A {
const B();
}
''');
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::b
''');
}
test_visitIsExpression_is_instanceOfUnrelatedClass() async {
await assertNoErrorsInCode('''
const a = const A();
const b = a is B;
class A {
const A();
}
class B {
const B();
}
''');
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::b
''');
}
test_visitIsExpression_is_null_dynamic() async {
await assertErrorsInCode('''
const a = null;
const b = a is dynamic;
class A {}
''', [
error(WarningCode.UNNECESSARY_TYPE_CHECK_TRUE, 26, 12),
]);
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::b
''');
}
test_visitIsExpression_is_null_null() async {
await assertErrorsInCode('''
const a = null;
const b = a is Null;
class A {}
''', [
error(WarningCode.TYPE_CHECK_IS_NULL, 26, 9),
]);
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::b
''');
}
test_visitIsExpression_isNot_instanceOfSuperclass() async {
await assertNoErrorsInCode('''
const a = const A();
const b = a is! B;
class A {
const A();
}
class B extends A {
const B();
}
''');
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::b
''');
}
test_visitIsExpression_isNot_instanceOfUnrelatedClass() async {
await assertNoErrorsInCode('''
const a = const A();
const b = a is! B;
class A {
const A();
}
class B {
const B();
}
''');
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::b
''');
}
test_visitPropertyAccess_fromExtension() async {
await assertErrorsInCode('''
extension ExtObject on Object {
int get length => 4;
}
class B {
final l;
const B(Object o) : l = o.length;
}
const b = B('');
''', [
error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 128, 5),
]);
}
test_visitSimpleIdentifier_dynamic() async {
await resolveTestCode('''
const a = dynamic;
''');
DartObjectImpl result = _evaluateConstant('a');
expect(result.type, typeProvider.typeType);
expect(result.toTypeValue(), typeProvider.dynamicType);
}
test_visitSimpleIdentifier_inEnvironment() async {
await assertNoErrorsInCode(r'''
const a = b;
const b = 3;''');
var environment = <String, DartObjectImpl>{
'b': DartObjectImpl(typeSystem, typeProvider.intType, IntState(6)),
};
var result = _evaluateConstant('a', lexicalEnvironment: environment);
assertDartObjectText(result, r'''
int 6
''');
}
test_visitSimpleIdentifier_notInEnvironment() async {
await assertNoErrorsInCode(r'''
const a = b;
const b = 3;''');
var environment = <String, DartObjectImpl>{
'c': DartObjectImpl(typeSystem, typeProvider.intType, IntState(6)),
};
var result = _evaluateConstant('a', lexicalEnvironment: environment);
assertDartObjectText(result, r'''
int 3
variable: self::@variable::b
''');
}
test_visitSimpleIdentifier_withoutEnvironment() async {
await assertNoErrorsInCode(r'''
const a = b;
const b = 3;''');
final result = _topLevelVar('a');
assertDartObjectText(result, r'''
int 3
variable: self::@variable::a
''');
}
}
class ConstantVisitorTestSupport extends PubPackageResolutionTest {
void _assertNull(DartObjectImpl? result) {
expect(result, isNull);
}
DartObjectImpl _evaluateConstant(
String name, {
List<ErrorCode>? errorCodes,
Map<String, String> declaredVariables = const {},
Map<String, DartObjectImpl>? lexicalEnvironment,
}) {
var expression = findNode.topVariableDeclarationByName(name).initializer!;
return _evaluateExpression(
expression,
errorCodes: errorCodes,
declaredVariables: declaredVariables,
lexicalEnvironment: lexicalEnvironment,
)!;
}
DartObjectImpl? _evaluateExpression(
Expression expression, {
List<ErrorCode>? errorCodes,
Map<String, String> declaredVariables = const {},
Map<String, DartObjectImpl>? lexicalEnvironment,
}) {
var unit = this.result.unit;
var source = unit.declaredElement!.source;
var errorListener = GatheringErrorListener();
var errorReporter = ErrorReporter(
errorListener,
source,
isNonNullableByDefault: false,
);
// TODO(kallentu): Remove unwrapping of Constant.
var expressionConstant = expression.accept(
ConstantVisitor(
ConstantEvaluationEngine(
declaredVariables: DeclaredVariables.fromMap(declaredVariables),
isNonNullableByDefault:
unit.featureSet.isEnabled(Feature.non_nullable),
configuration: ConstantEvaluationConfiguration(),
),
this.result.libraryElement as LibraryElementImpl,
errorReporter,
lexicalEnvironment: lexicalEnvironment,
),
);
var result =
expressionConstant is DartObjectImpl ? expressionConstant : null;
if (errorCodes == null) {
errorListener.assertNoErrors();
} else {
errorListener.assertErrorsWithCodes(errorCodes);
}
return result;
}
DartObjectImpl? _evaluationResult(ConstVariableElement element) {
final evaluationResult = element.evaluationResult;
if (evaluationResult == null) {
fail('Not evaluated: ${element.name}');
}
return evaluationResult.value;
}
DartObjectImpl? _field(String variableName) {
final element = findElement.field(variableName) as ConstVariableElement;
return _evaluationResult(element);
}
DartObjectImpl? _localVar(String variableName) {
final element = findElement.localVar(variableName) as ConstVariableElement;
return _evaluationResult(element);
}
DartObjectImpl? _topLevelVar(String variableName) {
final element = findElement.topVar(variableName) as ConstVariableElement;
return _evaluationResult(element);
}
}
@reflectiveTest
class ConstantVisitorWithoutNullSafetyTest extends ConstantVisitorTestSupport
with ConstantVisitorTestCases, WithoutNullSafetyMixin {
test_visitAsExpression_null() async {
await resolveTestCode('''
const a = null;
const b = a as A;
class A {}
''');
DartObjectImpl result = _evaluateConstant('b');
expect(result.type, typeProvider.nullType);
}
test_visitBinaryExpression_questionQuestion_invalid_notNull() async {
await assertErrorsInCode('''
final x = 0;
const c = x ?? 1;
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 23,
1),
]);
}
test_visitBinaryExpression_questionQuestion_notNull_invalid() async {
await assertErrorsInCode('''
final x = 1;
const c = 0 ?? x;
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 28,
1),
]);
}
test_visitConditionalExpression_eager_invalid_int_int() async {
await assertErrorsInCode('''
const c = null ? 1 : 0;
''', [
error(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL, 10, 4),
]);
}
test_visitIsExpression_is_functionType_correctTypes() async {
await assertNoErrorsInCode('''
void foo(int a) {}
const c = foo is void Function(int);
''');
final result = _topLevelVar('c');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::c
''');
}
test_visitIsExpression_is_instanceOfSameClass() async {
await assertNoErrorsInCode(
'''
const a = const A();
const b = a is A;
class A {
const A();
}
''',
);
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::b
''');
}
test_visitIsExpression_is_instanceOfSubclass() async {
await assertNoErrorsInCode('''
const a = const B();
const b = a is A;
class A {
const A();
}
class B extends A {
const B();
}
''');
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::b
''');
}
test_visitIsExpression_is_null() async {
await assertNoErrorsInCode('''
const a = null;
const b = a is A;
class A {}
''');
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::b
''');
}
test_visitIsExpression_is_null_object() async {
await assertErrorsInCode('''
const a = null;
const b = a is Object;
''', [
error(WarningCode.UNNECESSARY_TYPE_CHECK_TRUE, 26, 11),
]);
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool true
variable: self::@variable::b
''');
}
test_visitIsExpression_isNot_instanceOfSameClass() async {
await assertNoErrorsInCode('''
const a = const A();
const b = a is! A;
class A {
const A();
}
''');
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::b
''');
}
test_visitIsExpression_isNot_instanceOfSubclass() async {
await assertNoErrorsInCode('''
const a = const B();
const b = a is! A;
class A {
const A();
}
class B extends A {
const B();
}
''');
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::b
''');
}
test_visitIsExpression_isNot_null() async {
await assertNoErrorsInCode('''
const a = null;
const b = a is! A;
class A {}
''');
final result = _topLevelVar('b');
assertDartObjectText(result, r'''
bool false
variable: self::@variable::b
''');
}
}
@reflectiveTest
class InstanceCreationEvaluatorTest extends ConstantVisitorTestSupport
with InstanceCreationEvaluatorTestCases {
test_assertInitializer_assertIsNot_false() async {
await assertErrorsInCode('''
class A {
const A() : assert(0 is! int);
}
const a = const A(null);
''', [
error(WarningCode.UNNECESSARY_TYPE_CHECK_FALSE, 31, 9),
error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 56, 13),
error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 64, 4),
]);
}
test_assertInitializer_assertIsNot_null_nullableType() async {
await assertErrorsInCode('''
class A<T> {
const A() : assert(null is! T);
}
const a = const A<int?>();
''', [
error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 60, 15),
]);
}
test_assertInitializer_assertIsNot_true() async {
await assertErrorsInCode('''
class A {
const A() : assert(0 is! String);
}
const a = const A(null);
''', [
error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 67, 4),
]);
final result = _topLevelVar('a');
assertDartObjectText(result, '''
A
variable: self::@variable::a
''');
}
test_assertInitializer_intInDoubleContext_assertIsDouble_true() async {
await assertErrorsInCode('''
class A {
const A(double x): assert(x is double);
}
const a = const A(0);
''', [
error(WarningCode.UNNECESSARY_TYPE_CHECK_TRUE, 38, 11),
]);
final result = _topLevelVar('a');
assertDartObjectText(result, '''
A
variable: self::@variable::a
''');
}
test_assertInitializer_intInDoubleContext_true() async {
await assertNoErrorsInCode('''
class A {
const A(double x): assert((x + 3) / 2 == 1.5);
}
const v = const A(0);
''');
var result = _topLevelVar('v');
assertDartObjectText(result, '''
A
variable: self::@variable::v
''');
}
test_assertInitializer_simple_true() async {
await assertErrorsInCode('''
class A {
const A(): assert(1 is int);
}
const a = const A();
''', [
error(WarningCode.UNNECESSARY_TYPE_CHECK_TRUE, 30, 8),
]);
final result = _topLevelVar('a');
assertDartObjectText(result, '''
A
variable: self::@variable::a
''');
}
test_assertInitializer_simpleInSuperInitializer_true() async {
await assertErrorsInCode('''
class A {
const A(): assert(1 is int);
}
class B extends A {
const B() : super();
}
const b = const B();
''', [
error(WarningCode.UNNECESSARY_TYPE_CHECK_TRUE, 30, 8),
]);
var result = _topLevelVar('b');
assertDartObjectText(result, '''
B
(super): A
variable: self::@variable::b
''');
}
test_assertInitializer_usingArgument_true() async {
await assertNoErrorsInCode('''
class A {
const A(int x): assert(x > 0);
}
const a = const A(1);
''');
final result = _topLevelVar('a');
assertDartObjectText(result, '''
A
variable: self::@variable::a
''');
}
test_fieldInitializer_functionReference_withTypeParameter() async {
await assertNoErrorsInCode('''
void g<U>(U a) {}
class A<T> {
final void Function(T) f;
const A(): f = g;
}
const a = const A<int>();
''');
final result = _topLevelVar('a');
assertDartObjectText(result, '''
A<int>
f: void Function(int)
element: self::@function::g
typeArguments
T
variable: self::@variable::a
''');
}
test_fieldInitializer_typeParameter() async {
await assertNoErrorsInCode('''
class A<T> {
final Object f;
const A(): f = T;
}
const a = const A<int>();
''');
final result = _topLevelVar('a');
assertDartObjectText(result, '''
A<int>
f: Type int
variable: self::@variable::a
''');
}
test_fieldInitializer_typeParameter_implicitTypeArgs() async {
await assertNoErrorsInCode('''
class A<T> {
final Object f;
const A(): f = T;
}
const a = const A();
''');
final result = _topLevelVar('a');
assertDartObjectText(result, '''
A<dynamic>
f: Type dynamic
variable: self::@variable::a
''');
}
test_fieldInitializer_typeParameter_typeAlias() async {
await assertNoErrorsInCode('''
class A<T, U> {
final Object f, g;
const A(): f = T, g = U;
}
typedef B<S> = A<int, S>;
const a = const B<String>();
''');
final result = _topLevelVar('a');
assertDartObjectText(result, '''
A<int, String>
f: Type int
g: Type String
variable: self::@variable::a
''');
}
test_fieldInitializer_typeParameter_withoutConstructorTearoffs() async {
await assertErrorsInCode('''
// @dart=2.12
class A<T> {
final Object f;
const A(): f = T;
}
const a = const A<int>();
''', [
error(CompileTimeErrorCode.INVALID_CONSTANT, 62, 1),
error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 77, 14),
]);
final result = _topLevelVar('a');
_assertNull(result);
}
test_fieldInitializer_visitAsExpression_potentialConstType() async {
await assertNoErrorsInCode('''
const num three = 3;
class C<T extends num> {
final T w;
const C() : w = three as T;
}
void main() {
const C<int>().w;
}
''');
}
test_issue49389() async {
await assertErrorsInCode('''
class Foo {
const Foo({required this.bar});
final Map<String, String> bar;
}
void main() {
final data = <String, String>{};
const Foo(bar: data);
}
''', [
error(CompileTimeErrorCode.INVALID_CONSTANT, 148, 4),
]);
}
test_redirectingConstructor_typeParameter() async {
await assertNoErrorsInCode('''
class A<T> {
final Object f;
const A(): this.named(T);
const A.named(Object t): f = t;
}
const a = const A<int>();
''');
final result = _topLevelVar('a');
assertDartObjectText(result, '''
A<int>
f: Type int
variable: self::@variable::a
''');
}
test_superInitializer_typeParameter() async {
await assertNoErrorsInCode('''
class A<T> {
final Object f;
const A(Object t): f = t;
}
class B<T> extends A<T> {
const B(): super(T);
}
const a = const B<int>();
''');
final result = _topLevelVar('a');
assertDartObjectText(result, '''
B<int>
(super): A<int>
f: Type int
variable: self::@variable::a
''');
}
test_superInitializer_typeParameter_superNonGeneric() async {
await assertNoErrorsInCode('''
class A {
final Object f;
const A(Object t): f = t;
}
class B<T> extends A {
const B(): super(T);
}
const a = const B<int>();
''');
final result = _topLevelVar('a');
assertDartObjectText(result, '''
B<int>
(super): A
f: Type int
variable: self::@variable::a
''');
}
}
@reflectiveTest
mixin InstanceCreationEvaluatorTestCases on ConstantVisitorTestSupport {
test_assertInitializer_indirect() async {
await assertErrorsInCode(r'''
class A {
const A(int i)
: assert(i == 1); // (2)
}
class B extends A {
const B(int i) : super(i);
}
main() {
print(const B(2)); // (1)
}
''', [
error(
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
124,
10,
contextMessages: [
ExpectedContextMessage(testFile.path, 84, 1,
text:
"The evaluated constructor 'A' is called by 'B' and 'B' is defined here."),
ExpectedContextMessage(testFile.path, 31, 14,
text:
"The exception is 'The assertion in this constant expression failed.' and occurs here."),
],
),
]);
}
test_assertInitializer_intInDoubleContext_false() async {
await assertErrorsInCode('''
class A {
const A(double x): assert((x + 3) / 2 == 1.5);
}
const a = const A(1);
''', [
error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 71, 10),
]);
}
test_assertInitializer_simple_false() async {
await assertErrorsInCode('''
class A {
const A(): assert(1 is String);
}
const a = const A();
''', [
error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 56, 9),
]);
}
test_assertInitializer_simpleInSuperInitializer_false() async {
await assertErrorsInCode('''
class A {
const A(): assert(1 is String);
}
class B extends A {
const B() : super();
}
const b = const B();
''', [
error(
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
101,
9,
contextMessages: [
ExpectedContextMessage(testFile.path, 74, 1,
text:
"The evaluated constructor 'A' is called by 'B' and 'B' is defined here."),
ExpectedContextMessage(testFile.path, 23, 19,
text:
"The exception is 'The assertion in this constant expression failed.' and occurs here."),
],
),
]);
}
test_assertInitializer_usingArgument_false() async {
await assertErrorsInCode('''
class A {
const A(int x): assert(x > 0);
}
const a = const A(0);
''', [
error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 55, 10),
]);
}
test_bool_fromEnvironment() async {
await assertNoErrorsInCode('''
const a = bool.fromEnvironment('a');
const b = bool.fromEnvironment('b', defaultValue: true);
''');
assertDartObjectText(_topLevelVar('a'), '''
bool false
variable: self::@variable::a
''');
assertDartObjectText(
_evaluateConstant('a', declaredVariables: {'a': 'true'}), '''
bool true
''');
final bResult = _evaluateConstant(
'b',
declaredVariables: {'b': 'bbb'},
lexicalEnvironment: {
'defaultValue':
DartObjectImpl(typeSystem, typeProvider.boolType, BoolState(true)),
},
);
assertDartObjectText(bResult, '''
bool true
''');
}
test_bool_hasEnvironment() async {
await assertNoErrorsInCode('''
const a = bool.hasEnvironment('a');
''');
assertDartObjectText(_topLevelVar('a'), '''
bool false
variable: self::@variable::a
''');
assertDartObjectText(
_evaluateConstant('a', declaredVariables: {'a': '42'}), '''
bool true
''');
}
test_field_deferred_issue48991() async {
newFile('$testPackageLibPath/a.dart', '''
class A {
const A();
}
const aa = A();
''');
await assertErrorsInCode('''
import 'a.dart' deferred as a;
class B {
const B(Object a);
}
main() {
print(const B(a.aa));
}
''', [
error(
CompileTimeErrorCode.CONST_CONSTRUCTOR_CONSTANT_FROM_DEFERRED_LIBRARY,
93,
2),
]);
}
test_field_imported_staticConst() async {
newFile('$testPackageLibPath/a.dart', '''
class A {
static const A instance = const A();
const A();
}
''');
await assertNoErrorsInCode('''
import 'a.dart';
class B {
final A v;
const B(this.v);
}
B f1() => const B(A.instance);
''');
}
test_int_fromEnvironment() async {
await assertNoErrorsInCode('''
const a = int.fromEnvironment('a');
const b = int.fromEnvironment('b', defaultValue: 42);
''');
assertDartObjectText(_topLevelVar('a'), '''
int 0
variable: self::@variable::a
''');
assertDartObjectText(
_evaluateConstant('a', declaredVariables: {'a': '5'}), '''
int 5
''');
final bResult = _evaluateConstant(
'b',
declaredVariables: {'b': 'bbb'},
lexicalEnvironment: {
'defaultValue':
DartObjectImpl(typeSystem, typeProvider.intType, IntState(42)),
},
);
assertDartObjectText(bResult, '''
int 42
''');
}
test_issue47351() async {
await assertErrorsInCode('''
class Foo {
final int bar;
const Foo(this.bar);
}
int bar = 2;
const a = const Foo(bar);
''', [
error(CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT, 88, 3),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 88,
3),
]);
}
test_issue47603() async {
await assertErrorsInCode('''
class C {
final void Function() c;
const C(this.c);
}
void main() {
const C(() {});
}
''', [
error(CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT, 83, 5),
]);
}
test_string_fromEnvironment() async {
await assertNoErrorsInCode('''
const a = String.fromEnvironment('a');
''');
assertDartObjectText(_topLevelVar('a'), '''
String <empty>
variable: self::@variable::a
''');
assertDartObjectText(
_evaluateConstant('a', declaredVariables: {'a': 'test'}), '''
String test
''');
}
}
@reflectiveTest
class InstanceCreationEvaluatorWithoutNullSafetyTest
extends ConstantVisitorTestSupport
with InstanceCreationEvaluatorTestCases, WithoutNullSafetyMixin {}