blob: 430201e78ebe58d5634d0405bf8f6191f3d95af9 [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/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/element/element.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);
});
}
@reflectiveTest
class ConstantVisitorTest extends ConstantVisitorTestSupport
with ConstantVisitorTestCases {
test_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_visitBinaryExpression_gtGtGt_negative_fewerBits() async {
await resolveTestCode('''
const c = 0xFFFFFFFF >>> 8;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.intType);
expect(result.toIntValue(), 0xFFFFFF);
}
test_visitBinaryExpression_gtGtGt_negative_moreBits() async {
await resolveTestCode('''
const c = 0xFFFFFFFF >>> 33;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.intType);
expect(result.toIntValue(), 0);
}
test_visitBinaryExpression_gtGtGt_negative_moreThan64Bits() async {
await resolveTestCode('''
const c = 0xFFFFFFFF >>> 65;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.intType);
expect(result.toIntValue(), 0);
}
test_visitBinaryExpression_gtGtGt_negative_negativeBits() async {
await resolveTestCode('''
const c = 0xFFFFFFFF >>> -2;
''');
_evaluateConstantOrNull('c',
errorCodes: [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
}
test_visitBinaryExpression_gtGtGt_negative_zeroBits() async {
await resolveTestCode('''
const c = 0xFFFFFFFF >>> 0;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.intType);
expect(result.toIntValue(), 0xFFFFFFFF);
}
test_visitBinaryExpression_gtGtGt_positive_fewerBits() async {
await resolveTestCode('''
const c = 0xFF >>> 3;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.intType);
expect(result.toIntValue(), 0x1F);
}
test_visitBinaryExpression_gtGtGt_positive_moreBits() async {
await resolveTestCode('''
const c = 0xFF >>> 9;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.intType);
expect(result.toIntValue(), 0);
}
test_visitBinaryExpression_gtGtGt_positive_moreThan64Bits() async {
await resolveTestCode('''
const c = 0xFF >>> 65;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.intType);
expect(result.toIntValue(), 0);
}
test_visitBinaryExpression_gtGtGt_positive_negativeBits() async {
await resolveTestCode('''
const c = 0xFF >>> -2;
''');
_evaluateConstantOrNull('c',
errorCodes: [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
}
test_visitBinaryExpression_gtGtGt_positive_zeroBits() async {
await resolveTestCode('''
const c = 0xFF >>> 0;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.intType);
expect(result.toIntValue(), 0xFF);
}
test_visitSimpleIdentifier_className() async {
await resolveTestCode('''
const a = C;
class C {}
''');
DartObjectImpl result = _evaluateConstant('a');
expect(result.type, typeProvider.typeType);
assertType(result.toTypeValue(), 'C*');
}
}
@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_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 resolveTestCode('''
const a = const A();
const b = a as B;
class A {
const A();
}
class B extends A {
const B();
}
''');
var result = _evaluateConstantOrNull('b',
errorCodes: [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
expect(result, isNull);
}
test_visitAsExpression_instanceOfUnrelatedClass() async {
await resolveTestCode('''
const a = const A();
const b = a as B;
class A {
const A();
}
class B {
const B();
}
''');
var result = _evaluateConstantOrNull('b',
errorCodes: [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
expect(result, isNull);
}
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 resolveTestCode('''
final a = false;
const c = false && a;
''');
DartObjectImpl result = _evaluateConstant('c', errorCodes: [
CompileTimeErrorCode.INVALID_CONSTANT,
]);
_assertBoolValue(result, false);
}
test_visitBinaryExpression_and_bool_invalid_false() async {
await resolveTestCode('''
final a = false;
const c = a && false;
''');
var result = _evaluateConstantOrNull('c', errorCodes: [
CompileTimeErrorCode.INVALID_CONSTANT,
]);
expect(result, isNull);
}
test_visitBinaryExpression_and_bool_invalid_true() async {
await resolveTestCode('''
final a = false;
const c = a && true;
''');
var result = _evaluateConstantOrNull('c', errorCodes: [
CompileTimeErrorCode.INVALID_CONSTANT,
]);
expect(result, isNull);
}
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 resolveTestCode('''
final a = false;
const c = true && a;
''');
var result = _evaluateConstantOrNull('c', errorCodes: [
CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL,
CompileTimeErrorCode.INVALID_CONSTANT,
]);
expect(result, isNull);
}
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 resolveTestCode('''
const c = 3 & false;
''');
_evaluateConstantOrNull('c',
errorCodes: [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT]);
}
test_visitBinaryExpression_or_bool_false_invalid() async {
await resolveTestCode('''
final a = false;
const c = false || a;
''');
var result = _evaluateConstantOrNull('c', errorCodes: [
CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL,
CompileTimeErrorCode.INVALID_CONSTANT,
]);
expect(result, isNull);
}
test_visitBinaryExpression_or_bool_invalid_false() async {
await resolveTestCode('''
final a = false;
const c = a || false;
''');
var result = _evaluateConstantOrNull('c', errorCodes: [
CompileTimeErrorCode.INVALID_CONSTANT,
]);
expect(result, isNull);
}
test_visitBinaryExpression_or_bool_invalid_true() async {
await resolveTestCode('''
final a = false;
const c = a || true;
''');
var result = _evaluateConstantOrNull('c', errorCodes: [
CompileTimeErrorCode.INVALID_CONSTANT,
]);
expect(result, isNull);
}
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 resolveTestCode('''
final a = false;
const c = true || a;
''');
var result = _evaluateConstant('c', errorCodes: [
CompileTimeErrorCode.INVALID_CONSTANT,
]);
_assertBoolValue(result, true);
}
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 resolveTestCode('''
const c = 3 | false;
''');
_evaluateConstantOrNull('c',
errorCodes: [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT]);
}
test_visitBinaryExpression_questionQuestion_invalid_notNull() async {
await resolveTestCode('''
final x = 0;
const c = x ?? 1;
''');
var result = _evaluateConstantOrNull('c', errorCodes: [
CompileTimeErrorCode.INVALID_CONSTANT,
]);
expect(result, isNull);
}
test_visitBinaryExpression_questionQuestion_notNull_invalid() async {
await resolveTestCode('''
final x = 1;
const c = 0 ?? x;
''');
var result = _evaluateConstant('c', errorCodes: [
CompileTimeErrorCode.INVALID_CONSTANT,
]);
_assertIntValue(result, 0);
}
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 resolveTestCode('''
const c = null ?? new C();
class C {}
''');
_evaluateConstantOrNull('c',
errorCodes: [CompileTimeErrorCode.INVALID_CONSTANT]);
}
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 resolveTestCode('''
const c = 3 ^ false;
''');
_evaluateConstantOrNull('c',
errorCodes: [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT]);
}
test_visitConditionalExpression_eager_false_int_int() async {
await resolveTestCode('''
const c = false ? 1 : 0;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.intType);
expect(result.toIntValue(), 0);
}
test_visitConditionalExpression_eager_invalid_int_int() async {
await resolveTestCode('''
const c = null ? 1 : 0;
''');
var result = _evaluateConstantOrNull(
'c',
errorCodes: [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL],
);
expect(result, isNull);
}
test_visitConditionalExpression_eager_true_int_int() async {
await resolveTestCode('''
const c = true ? 1 : 0;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.intType);
expect(result.toIntValue(), 1);
}
test_visitConditionalExpression_eager_true_int_invalid() async {
await resolveTestCode('''
const c = true ? 1 : x;
''');
DartObjectImpl result = _evaluateConstant(
'c',
errorCodes: [CompileTimeErrorCode.INVALID_CONSTANT],
);
if (analysisOptions.experimentStatus.constant_update_2018) {
expect(result.toIntValue(), 1);
} else {
expect(result, isNull);
}
}
test_visitConditionalExpression_eager_true_invalid_int() async {
await resolveTestCode('''
const c = true ? x : 0;
''');
var result = _evaluateConstantOrNull(
'c',
errorCodes: [CompileTimeErrorCode.INVALID_CONSTANT],
);
expect(result, isNull);
}
test_visitConditionalExpression_lazy_false_int_int() async {
await resolveTestCode('''
const c = false ? 1 : 0;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.intType);
expect(result.toIntValue(), 0);
}
test_visitConditionalExpression_lazy_false_int_invalid() async {
await resolveTestCode('''
const c = false ? 1 : new C();
''');
_evaluateConstantOrNull('c',
errorCodes: [CompileTimeErrorCode.INVALID_CONSTANT]);
}
test_visitConditionalExpression_lazy_false_invalid_int() async {
await resolveTestCode('''
const c = false ? new C() : 0;
''');
DartObjectImpl result = _evaluateConstant('c',
errorCodes: [CompileTimeErrorCode.INVALID_CONSTANT]);
expect(result.type, typeProvider.intType);
expect(result.toIntValue(), 0);
}
test_visitConditionalExpression_lazy_invalid_int_int() async {
await resolveTestCode('''
const c = 3 ? 1 : 0;
''');
_evaluateConstantOrNull('c',
errorCodes: [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL]);
}
test_visitConditionalExpression_lazy_true_int_int() async {
await resolveTestCode('''
const c = true ? 1 : 0;
''');
DartObjectImpl result = _evaluateConstant('c');
expect(result.type, typeProvider.intType);
expect(result.toIntValue(), 1);
}
test_visitConditionalExpression_lazy_true_int_invalid() async {
await resolveTestCode('''
const c = true ? 1: new C();
''');
DartObjectImpl result = _evaluateConstant('c',
errorCodes: [CompileTimeErrorCode.INVALID_CONSTANT]);
expect(result.type, typeProvider.intType);
expect(result.toIntValue(), 1);
}
test_visitConditionalExpression_lazy_true_invalid_int() async {
await resolveTestCode('''
const c = true ? new C() : 0;
class C {}
''');
_evaluateConstantOrNull('c',
errorCodes: [CompileTimeErrorCode.INVALID_CONSTANT]);
}
test_visitInstanceCreationExpression_bool_fromEnvironment() async {
await resolveTestCode('''
const a = bool.fromEnvironment('a');
const b = bool.fromEnvironment('b', defaultValue: true);
''');
expect(
_evaluateConstant('a'),
_boolValue(false),
);
expect(
_evaluateConstant('a', declaredVariables: {'a': 'true'}),
_boolValue(true),
);
expect(
_evaluateConstant(
'b',
declaredVariables: {'b': 'bbb'},
lexicalEnvironment: {'defaultValue': _boolValue(true)},
),
_boolValue(true),
);
}
test_visitInstanceCreationExpression_bool_hasEnvironment() async {
await resolveTestCode('''
const a = bool.hasEnvironment('a');
''');
expect(
_evaluateConstant('a'),
_boolValue(false),
);
expect(
_evaluateConstant('a', declaredVariables: {'a': '42'}),
_boolValue(true),
);
}
test_visitInstanceCreationExpression_int_fromEnvironment() async {
await resolveTestCode('''
const a = int.fromEnvironment('a');
const b = int.fromEnvironment('b', defaultValue: 42);
''');
expect(
_evaluateConstant('a'),
_intValue(0),
);
expect(
_evaluateConstant('a', declaredVariables: {'a': '5'}),
_intValue(5),
);
expect(
_evaluateConstant(
'b',
declaredVariables: {'b': 'bbb'},
lexicalEnvironment: {'defaultValue': _intValue(42)},
),
_intValue(42),
);
}
test_visitInstanceCreationExpression_string_fromEnvironment() async {
await resolveTestCode('''
const a = String.fromEnvironment('a');
''');
expect(
_evaluateConstant('a'),
DartObjectImpl(
typeSystem,
typeProvider.stringType,
StringState(''),
),
);
expect(
_evaluateConstant('a', declaredVariables: {'a': 'test'}),
DartObjectImpl(
typeSystem,
typeProvider.stringType,
StringState('test'),
),
);
}
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_instanceOfSameClass() async {
await resolveTestCode('''
const a = const A();
const b = a is A;
class A {
const A();
}
''');
DartObjectImpl result = _evaluateConstant('b');
expect(result.type, typeProvider.boolType);
expect(result.toBoolValue(), true);
}
test_visitIsExpression_is_instanceOfSubclass() async {
await resolveTestCode('''
const a = const B();
const b = a is A;
class A {
const A();
}
class B extends A {
const B();
}
''');
DartObjectImpl result = _evaluateConstant('b');
expect(result.type, typeProvider.boolType);
expect(result.toBoolValue(), true);
}
test_visitIsExpression_is_instanceOfSuperclass() async {
await resolveTestCode('''
const a = const A();
const b = a is B;
class A {
const A();
}
class B extends A {
const B();
}
''');
DartObjectImpl result = _evaluateConstant('b');
expect(result.type, typeProvider.boolType);
expect(result.toBoolValue(), false);
}
test_visitIsExpression_is_instanceOfUnrelatedClass() async {
await resolveTestCode('''
const a = const A();
const b = a is B;
class A {
const A();
}
class B {
const B();
}
''');
DartObjectImpl result = _evaluateConstant('b');
expect(result.type, typeProvider.boolType);
expect(result.toBoolValue(), false);
}
test_visitIsExpression_is_null() async {
await resolveTestCode('''
const a = null;
const b = a is A;
class A {}
''');
DartObjectImpl result = _evaluateConstant('b');
expect(result.type, typeProvider.boolType);
expect(result.toBoolValue(), false);
}
test_visitIsExpression_is_null_dynamic() async {
await resolveTestCode('''
const a = null;
const b = a is dynamic;
class A {}
''');
DartObjectImpl result = _evaluateConstant('b');
expect(result.type, typeProvider.boolType);
expect(result.toBoolValue(), true);
}
test_visitIsExpression_is_null_null() async {
await resolveTestCode('''
const a = null;
const b = a is Null;
class A {}
''');
DartObjectImpl result = _evaluateConstant('b');
expect(result.type, typeProvider.boolType);
expect(result.toBoolValue(), true);
}
test_visitIsExpression_is_null_object() async {
await resolveTestCode('''
const a = null;
const b = a is Object;
class A {}
''');
DartObjectImpl result = _evaluateConstant('b');
expect(result.type, typeProvider.boolType);
expect(result.toBoolValue(), true);
}
test_visitIsExpression_isNot_instanceOfSameClass() async {
await resolveTestCode('''
const a = const A();
const b = a is! A;
class A {
const A();
}
''');
DartObjectImpl result = _evaluateConstant('b');
expect(result.type, typeProvider.boolType);
expect(result.toBoolValue(), false);
}
test_visitIsExpression_isNot_instanceOfSubclass() async {
await resolveTestCode('''
const a = const B();
const b = a is! A;
class A {
const A();
}
class B extends A {
const B();
}
''');
DartObjectImpl result = _evaluateConstant('b');
expect(result.type, typeProvider.boolType);
expect(result.toBoolValue(), false);
}
test_visitIsExpression_isNot_instanceOfSuperclass() async {
await resolveTestCode('''
const a = const A();
const b = a is! B;
class A {
const A();
}
class B extends A {
const B();
}
''');
DartObjectImpl result = _evaluateConstant('b');
expect(result.type, typeProvider.boolType);
expect(result.toBoolValue(), true);
}
test_visitIsExpression_isNot_instanceOfUnrelatedClass() async {
await resolveTestCode('''
const a = const A();
const b = a is! B;
class A {
const A();
}
class B {
const B();
}
''');
DartObjectImpl result = _evaluateConstant('b');
expect(result.type, typeProvider.boolType);
expect(result.toBoolValue(), true);
}
test_visitIsExpression_isNot_null() async {
await resolveTestCode('''
const a = null;
const b = a is! A;
class A {}
''');
DartObjectImpl result = _evaluateConstant('b');
expect(result.type, typeProvider.boolType);
expect(result.toBoolValue(), true);
}
test_visitPropertyAccess_fromExtension() async {
await resolveTestCode('''
extension ExtObject on Object {
int get length => 4;
}
class B {
final l;
const B(Object o) : l = o.length;
}
const b = B('');
''');
_evaluateConstant('b', errorCodes: [
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION
]);
}
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 resolveTestCode(r'''
const a = b;
const b = 3;''');
var environment = <String, DartObjectImpl>{
'b': DartObjectImpl(typeSystem, typeProvider.intType, IntState(6)),
};
var result = _evaluateConstant('a', lexicalEnvironment: environment);
expect(result.type, typeProvider.intType);
expect(result.toIntValue(), 6);
}
test_visitSimpleIdentifier_notInEnvironment() async {
await resolveTestCode(r'''
const a = b;
const b = 3;''');
var environment = <String, DartObjectImpl>{
'c': DartObjectImpl(typeSystem, typeProvider.intType, IntState(6)),
};
var result = _evaluateConstant('a', lexicalEnvironment: environment);
expect(result.type, typeProvider.intType);
expect(result.toIntValue(), 3);
}
test_visitSimpleIdentifier_withoutEnvironment() async {
await resolveTestCode(r'''
const a = b;
const b = 3;''');
var result = _evaluateConstant('a');
expect(result.type, typeProvider.intType);
expect(result.toIntValue(), 3);
}
void _assertBoolValue(DartObjectImpl result, bool value) {
expect(result.type, typeProvider.boolType);
expect(result.toBoolValue(), value);
}
void _assertIntValue(DartObjectImpl result, int value) {
expect(result.type, typeProvider.intType);
expect(result.toIntValue(), value);
}
DartObjectImpl _boolValue(bool value) {
if (identical(value, false)) {
return DartObjectImpl(
typeSystem,
typeProvider.boolType,
BoolState.FALSE_STATE,
);
} else if (identical(value, true)) {
return DartObjectImpl(
typeSystem,
typeProvider.boolType,
BoolState.TRUE_STATE,
);
}
fail("Invalid boolean value used in test");
}
DartObjectImpl _intValue(int value) {
return DartObjectImpl(
typeSystem,
typeProvider.intType,
IntState(value),
);
}
}
class ConstantVisitorTestSupport extends PubPackageResolutionTest {
DartObjectImpl _evaluateConstant(
String name, {
List<ErrorCode>? errorCodes,
Map<String, String> declaredVariables = const {},
Map<String, DartObjectImpl>? lexicalEnvironment,
}) {
return _evaluateConstantOrNull(
name,
errorCodes: errorCodes,
declaredVariables: declaredVariables,
lexicalEnvironment: lexicalEnvironment,
)!;
}
DartObjectImpl? _evaluateConstantOrNull(
String name, {
List<ErrorCode>? errorCodes,
Map<String, String> declaredVariables = const {},
Map<String, DartObjectImpl>? lexicalEnvironment,
}) {
var expression = findNode.topVariableDeclarationByName(name).initializer!;
var unit = this.result.unit;
if (unit == null) {
throw StateError('analysis result unit is null');
}
var source = unit.declaredElement!.source;
var errorListener = GatheringErrorListener();
var errorReporter = ErrorReporter(
errorListener,
source,
isNonNullableByDefault: false,
);
DartObjectImpl? result = expression.accept(
ConstantVisitor(
ConstantEvaluationEngine(
DeclaredVariables.fromMap(declaredVariables),
unit.featureSet.isEnabled(Feature.triple_shift),
),
this.result.libraryElement as LibraryElementImpl,
errorReporter,
lexicalEnvironment: lexicalEnvironment,
),
);
if (errorCodes == null) {
errorListener.assertNoErrors();
} else {
errorListener.assertErrorsWithCodes(errorCodes);
}
return result;
}
}
@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);
}
}