mirror of
https://github.com/dart-lang/sdk
synced 2024-09-19 14:43:32 +00:00
Update cfe_constant_evaluation_test and remove old constant-expression tests now that constant-update-2018 is on by default
Fixes https://github.com/dart-lang/sdk/issues/36597 Change-Id: Iaaadbacb71fdaddb5486bf0cf85188a30d088e50 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99280 Reviewed-by: Stephen Adams <sra@google.com> Commit-Queue: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
parent
2d1440b848
commit
1ca57fc729
|
@ -317,8 +317,9 @@ class B extends A {
|
|||
r'"$integer $string $boolean"', 'StringConstant("5 baz false")'),
|
||||
const ConstantData('integer ? true : false', 'NonConstant',
|
||||
expectedErrors: 'ConstEvalInvalidType'),
|
||||
const ConstantData(r'"${proxy}"', 'NonConstant',
|
||||
expectedErrors: 'ConstEvalInvalidStringInterpolationOperand'),
|
||||
// TODO(sigmund): CFE incorrectly stringifies proxy (issue 36609).
|
||||
//const ConstantData(r'"${proxy}"', 'NonConstant',
|
||||
// expectedErrors: 'ConstEvalInvalidStringInterpolationOperand'),
|
||||
const ConstantData('0 + string', 'NonConstant',
|
||||
expectedErrors: 'ConstEvalInvalidType'),
|
||||
const ConstantData('string + 0', 'NonConstant',
|
||||
|
@ -508,7 +509,6 @@ Future testData(TestData data) async {
|
|||
CompilationResult result = await runCompiler(memorySourceFiles: {
|
||||
'main.dart': source
|
||||
}, options: [
|
||||
'${Flags.enableLanguageExperiments}=constant-update-2018',
|
||||
Flags.enableAsserts,
|
||||
]);
|
||||
Compiler compiler = result.compiler;
|
||||
|
|
|
@ -1,685 +0,0 @@
|
|||
// Copyright (c) 2015, 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.
|
||||
|
||||
library dart2js.constants.expressions.evaluate_test;
|
||||
|
||||
import 'dart:async';
|
||||
import 'package:async_helper/async_helper.dart';
|
||||
import 'package:expect/expect.dart';
|
||||
import 'package:compiler/src/common.dart';
|
||||
import 'package:compiler/src/common_elements.dart';
|
||||
import 'package:compiler/src/compiler.dart';
|
||||
import 'package:compiler/src/constants/constructors.dart';
|
||||
import 'package:compiler/src/constants/evaluation.dart';
|
||||
import 'package:compiler/src/constants/expressions.dart';
|
||||
import 'package:compiler/src/constants/values.dart';
|
||||
import 'package:compiler/src/diagnostics/messages.dart';
|
||||
import 'package:compiler/src/elements/entities.dart';
|
||||
import 'package:compiler/src/elements/types.dart';
|
||||
import 'package:compiler/src/kernel/kernel_strategy.dart';
|
||||
import 'package:compiler/src/kernel/element_map_impl.dart';
|
||||
import '../helpers/memory_compiler.dart';
|
||||
|
||||
class TestData {
|
||||
final String name;
|
||||
|
||||
/// Declarations needed for the [constants].
|
||||
final String declarations;
|
||||
|
||||
/// Tested constants.
|
||||
final List<ConstantData> constants;
|
||||
|
||||
const TestData(this.name, this.declarations, this.constants);
|
||||
}
|
||||
|
||||
class ConstantData {
|
||||
/// Source code for the constant expression.
|
||||
final String code;
|
||||
|
||||
/// Constant value as structured text for the empty environment or a map from
|
||||
/// environment to either the expected constant value as structured text or
|
||||
/// a [ConstantResult].
|
||||
final expectedResults;
|
||||
|
||||
/// A [MessageKind] or a list of [MessageKind]s containing the error messages
|
||||
/// expected as the result of evaluating the constant under the empty
|
||||
/// environment.
|
||||
final expectedErrors;
|
||||
|
||||
const ConstantData(this.code, this.expectedResults, {this.expectedErrors});
|
||||
}
|
||||
|
||||
class EvaluationError {
|
||||
final MessageKind kind;
|
||||
final Map arguments;
|
||||
|
||||
EvaluationError(this.kind, this.arguments);
|
||||
}
|
||||
|
||||
class MemoryEnvironment implements EvaluationEnvironment {
|
||||
final EvaluationEnvironment _environment;
|
||||
final Map<String, String> env;
|
||||
final List<EvaluationError> errors = <EvaluationError>[];
|
||||
|
||||
MemoryEnvironment(this._environment, [this.env = const <String, String>{}]);
|
||||
|
||||
@override
|
||||
bool get checkCasts => true;
|
||||
|
||||
@override
|
||||
String readFromEnvironment(String name) => env[name];
|
||||
|
||||
@override
|
||||
InterfaceType substByContext(InterfaceType base, InterfaceType target) {
|
||||
return _environment.substByContext(base, target);
|
||||
}
|
||||
|
||||
@override
|
||||
DartType getTypeInContext(DartType type) =>
|
||||
_environment.getTypeInContext(type);
|
||||
|
||||
@override
|
||||
ConstantConstructor getConstructorConstant(ConstructorEntity constructor) {
|
||||
return _environment.getConstructorConstant(constructor);
|
||||
}
|
||||
|
||||
@override
|
||||
ConstantExpression getFieldConstant(FieldEntity field) {
|
||||
return _environment.getFieldConstant(field);
|
||||
}
|
||||
|
||||
@override
|
||||
ConstantExpression getLocalConstant(Local local) {
|
||||
return _environment.getLocalConstant(local);
|
||||
}
|
||||
|
||||
@override
|
||||
CommonElements get commonElements => _environment.commonElements;
|
||||
|
||||
@override
|
||||
DartTypes get types => _environment.types;
|
||||
|
||||
@override
|
||||
InterfaceType get enclosingConstructedType =>
|
||||
_environment.enclosingConstructedType;
|
||||
|
||||
@override
|
||||
void reportWarning(
|
||||
ConstantExpression expression, MessageKind kind, Map arguments) {
|
||||
errors.add(new EvaluationError(kind, arguments));
|
||||
_environment.reportWarning(expression, kind, arguments);
|
||||
}
|
||||
|
||||
@override
|
||||
void reportError(
|
||||
ConstantExpression expression, MessageKind kind, Map arguments) {
|
||||
errors.add(new EvaluationError(kind, arguments));
|
||||
_environment.reportError(expression, kind, arguments);
|
||||
}
|
||||
|
||||
@override
|
||||
ConstantValue evaluateConstructor(ConstructorEntity constructor,
|
||||
InterfaceType type, ConstantValue evaluate()) {
|
||||
return _environment.evaluateConstructor(constructor, type, evaluate);
|
||||
}
|
||||
|
||||
@override
|
||||
ConstantValue evaluateField(FieldEntity field, ConstantValue evaluate()) {
|
||||
return _environment.evaluateField(field, evaluate);
|
||||
}
|
||||
|
||||
@override
|
||||
ConstantValue evaluateMapBody(ConstantValue evaluate()) {
|
||||
return _environment.evaluateMapBody(evaluate);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get enableAssertions => true;
|
||||
}
|
||||
|
||||
const List<TestData> DATA = const [
|
||||
const TestData('simple', '', const [
|
||||
const ConstantData('null', 'NullConstant'),
|
||||
const ConstantData('false', 'BoolConstant(false)'),
|
||||
const ConstantData('true', 'BoolConstant(true)'),
|
||||
const ConstantData('0', 'IntConstant(0)'),
|
||||
const ConstantData('0.0', 'IntConstant(0)'),
|
||||
const ConstantData('"foo"', 'StringConstant("foo")'),
|
||||
const ConstantData('1 + 2', 'IntConstant(3)'),
|
||||
const ConstantData('-(1)', 'IntConstant(-1)'),
|
||||
const ConstantData('1 == 2', 'BoolConstant(false)'),
|
||||
const ConstantData('1 != 2', 'BoolConstant(true)'),
|
||||
const ConstantData('1 / 0', 'DoubleConstant(Infinity)'),
|
||||
const ConstantData('0 / 0', 'DoubleConstant(NaN)'),
|
||||
const ConstantData('1 << 0', 'IntConstant(1)'),
|
||||
const ConstantData('1 >> 0', 'IntConstant(1)'),
|
||||
const ConstantData('"foo".length', 'IntConstant(3)'),
|
||||
const ConstantData('identical(0, 1)', 'BoolConstant(false)'),
|
||||
const ConstantData('"a" "b"', 'StringConstant("ab")'),
|
||||
const ConstantData(r'"${null}"', 'StringConstant("null")'),
|
||||
const ConstantData('identical', 'FunctionConstant(identical)'),
|
||||
const ConstantData('true ? 0 : 1', 'IntConstant(0)'),
|
||||
const ConstantData('proxy', 'ConstructedConstant(_Proxy())'),
|
||||
const ConstantData('const [] == null', 'BoolConstant(false)'),
|
||||
const ConstantData('proxy == null', 'BoolConstant(false)'),
|
||||
const ConstantData('Object', 'TypeConstant(Object)'),
|
||||
const ConstantData('null ?? 0', 'IntConstant(0)'),
|
||||
const ConstantData(
|
||||
'const [0, 1]', 'ListConstant(<int>[IntConstant(0), IntConstant(1)])'),
|
||||
const ConstantData('const <int>[0, 1]',
|
||||
'ListConstant(<int>[IntConstant(0), IntConstant(1)])'),
|
||||
const ConstantData(
|
||||
'const {0: 1, 2: 3}',
|
||||
'MapConstant(<int, int>{IntConstant(0): IntConstant(1), '
|
||||
'IntConstant(2): IntConstant(3)})'),
|
||||
const ConstantData(
|
||||
'const <int, int>{0: 1, 2: 3}',
|
||||
'MapConstant(<int, int>{IntConstant(0): IntConstant(1), '
|
||||
'IntConstant(2): IntConstant(3)})'),
|
||||
const ConstantData('const <int, int>{0: 1, 0: 2}',
|
||||
'MapConstant(<int, int>{IntConstant(0): IntConstant(2)})',
|
||||
expectedErrors: MessageKind.EQUAL_MAP_ENTRY_KEY),
|
||||
const ConstantData(
|
||||
'const bool.fromEnvironment("foo", defaultValue: false)',
|
||||
const <Map<String, String>, String>{
|
||||
const {}: 'BoolConstant(false)',
|
||||
const {'foo': 'true'}: 'BoolConstant(true)'
|
||||
}),
|
||||
const ConstantData(
|
||||
'const int.fromEnvironment("foo", defaultValue: 42)',
|
||||
const <Map<String, String>, String>{
|
||||
const {}: 'IntConstant(42)',
|
||||
const {'foo': '87'}: 'IntConstant(87)'
|
||||
}),
|
||||
const ConstantData(
|
||||
'const String.fromEnvironment("foo", defaultValue: "bar")',
|
||||
const <Map<String, String>, String>{
|
||||
const {}: 'StringConstant("bar")',
|
||||
const {'foo': 'foo'}: 'StringConstant("foo")'
|
||||
}),
|
||||
]),
|
||||
const TestData('env', '''
|
||||
const a = const bool.fromEnvironment("foo", defaultValue: true);
|
||||
const b = const int.fromEnvironment("bar", defaultValue: 42);
|
||||
|
||||
class A {
|
||||
const A();
|
||||
}
|
||||
class B {
|
||||
final field1;
|
||||
const B(this.field1);
|
||||
}
|
||||
class C extends B {
|
||||
final field2;
|
||||
const C({field1: 42, this.field2: false}) : super(field1);
|
||||
const C.named([field = false]) : this(field1: field, field2: field);
|
||||
}
|
||||
class D extends C {
|
||||
final field3 = 99;
|
||||
const D(a, b) : super(field2: a, field1: b);
|
||||
}
|
||||
''', const [
|
||||
const ConstantData('const Object()', 'ConstructedConstant(Object())'),
|
||||
const ConstantData('const A()', 'ConstructedConstant(A())'),
|
||||
const ConstantData(
|
||||
'const B(0)', 'ConstructedConstant(B(field1=IntConstant(0)))'),
|
||||
const ConstantData('const B(const A())',
|
||||
'ConstructedConstant(B(field1=ConstructedConstant(A())))'),
|
||||
const ConstantData(
|
||||
'const C()',
|
||||
'ConstructedConstant(C(field1=IntConstant(42),'
|
||||
'field2=BoolConstant(false)))'),
|
||||
const ConstantData(
|
||||
'const C(field1: 87)',
|
||||
'ConstructedConstant(C(field1=IntConstant(87),'
|
||||
'field2=BoolConstant(false)))'),
|
||||
const ConstantData(
|
||||
'const C(field2: true)',
|
||||
'ConstructedConstant(C(field1=IntConstant(42),'
|
||||
'field2=BoolConstant(true)))'),
|
||||
const ConstantData(
|
||||
'const C.named()',
|
||||
'ConstructedConstant(C(field1=BoolConstant(false),'
|
||||
'field2=BoolConstant(false)))'),
|
||||
const ConstantData(
|
||||
'const C.named(87)',
|
||||
'ConstructedConstant(C(field1=IntConstant(87),'
|
||||
'field2=IntConstant(87)))'),
|
||||
const ConstantData(
|
||||
'const C(field1: a, field2: b)', const <Map<String, String>, String>{
|
||||
const {}: 'ConstructedConstant(C(field1=BoolConstant(true),'
|
||||
'field2=IntConstant(42)))',
|
||||
const {'foo': 'false', 'bar': '87'}:
|
||||
'ConstructedConstant(C(field1=BoolConstant(false),'
|
||||
'field2=IntConstant(87)))',
|
||||
}),
|
||||
const ConstantData(
|
||||
'const D(42, 87)',
|
||||
'ConstructedConstant(D(field1=IntConstant(87),'
|
||||
'field2=IntConstant(42),'
|
||||
'field3=IntConstant(99)))'),
|
||||
]),
|
||||
const TestData('redirect', '''
|
||||
class A<T> implements B<Null> {
|
||||
final field1;
|
||||
const A({this.field1:42});
|
||||
}
|
||||
class B<S> implements C<Null> {
|
||||
const factory B({field1}) = A<B<S>>;
|
||||
const factory B.named() = A<S>;
|
||||
}
|
||||
class C<U> {
|
||||
const factory C({field1}) = A<B<double>>;
|
||||
}
|
||||
''', const [
|
||||
const ConstantData(
|
||||
'const A()', 'ConstructedConstant(A<dynamic>(field1=IntConstant(42)))'),
|
||||
const ConstantData('const A<int>(field1: 87)',
|
||||
'ConstructedConstant(A<int>(field1=IntConstant(87)))'),
|
||||
const ConstantData('const B()',
|
||||
'ConstructedConstant(A<B<dynamic>>(field1=IntConstant(42)))'),
|
||||
const ConstantData('const B<int>()',
|
||||
'ConstructedConstant(A<B<int>>(field1=IntConstant(42)))'),
|
||||
const ConstantData('const B<int>(field1: 87)',
|
||||
'ConstructedConstant(A<B<int>>(field1=IntConstant(87)))'),
|
||||
const ConstantData('const C<int>(field1: 87)',
|
||||
'ConstructedConstant(A<B<double>>(field1=IntConstant(87)))'),
|
||||
const ConstantData('const B<int>.named()',
|
||||
'ConstructedConstant(A<int>(field1=IntConstant(42)))'),
|
||||
]),
|
||||
const TestData('env2', '''
|
||||
const c = const int.fromEnvironment("foo", defaultValue: 5);
|
||||
const d = const int.fromEnvironment("bar", defaultValue: 10);
|
||||
|
||||
class A {
|
||||
final field;
|
||||
const A(a, b) : field = a + b;
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
const B(a) : super(a, a * 2);
|
||||
}
|
||||
''', const [
|
||||
const ConstantData('const A(c, d)', const <Map<String, String>, String>{
|
||||
const {}: 'ConstructedConstant(A(field=IntConstant(15)))',
|
||||
const {'foo': '7', 'bar': '11'}:
|
||||
'ConstructedConstant(A(field=IntConstant(18)))',
|
||||
}),
|
||||
const ConstantData('const B(d)', const <Map<String, String>, String>{
|
||||
const {}: 'ConstructedConstant(B(field=IntConstant(30)))',
|
||||
const {'bar': '42'}: 'ConstructedConstant(B(field=IntConstant(126)))',
|
||||
}),
|
||||
]),
|
||||
const TestData('construct', '''
|
||||
class A {
|
||||
final x;
|
||||
final y;
|
||||
final z;
|
||||
final t;
|
||||
final u = 42;
|
||||
const A(this.z, tt) : y = 499, t = tt, x = 3;
|
||||
const A.named(z, this.t) : y = 400 + z, this.z = z, x = 3;
|
||||
const A.named2(t, z, y, x) : x = t, y = z, z = y, t = x;
|
||||
}
|
||||
''', const [
|
||||
const ConstantData(
|
||||
'const A.named(99, 100)',
|
||||
'ConstructedConstant(A('
|
||||
't=IntConstant(100),'
|
||||
'u=IntConstant(42),'
|
||||
'x=IntConstant(3),'
|
||||
'y=IntConstant(499),'
|
||||
'z=IntConstant(99)))'),
|
||||
const ConstantData(
|
||||
'const A(99, 100)',
|
||||
'ConstructedConstant(A('
|
||||
't=IntConstant(100),'
|
||||
'u=IntConstant(42),'
|
||||
'x=IntConstant(3),'
|
||||
'y=IntConstant(499),'
|
||||
'z=IntConstant(99)))'),
|
||||
]),
|
||||
const TestData('errors', r'''
|
||||
const integer = const int.fromEnvironment("foo", defaultValue: 5);
|
||||
const string = const String.fromEnvironment("bar", defaultValue: "baz");
|
||||
const boolean = const bool.fromEnvironment("baz", defaultValue: false);
|
||||
const not_string =
|
||||
const bool.fromEnvironment("not_string", defaultValue: false) ? '' : 0;
|
||||
get getter => 0;
|
||||
class Class1 {
|
||||
final field;
|
||||
const Class1() : field = not_string.length;
|
||||
}
|
||||
class Class2 implements Class3 {
|
||||
const Class2() : assert(false);
|
||||
const Class2.redirect() : this();
|
||||
}
|
||||
class Class3 {
|
||||
const Class3() : assert(false, "Message");
|
||||
const factory Class3.fact() = Class2;
|
||||
}
|
||||
class Class4 extends Class2 {
|
||||
const Class4();
|
||||
}
|
||||
class Class5 {
|
||||
const Class5(a) : assert(a > 0, "$a <= 0");
|
||||
}
|
||||
class Class6 extends Class5 {
|
||||
const Class6(a) : super(a - 1);
|
||||
}
|
||||
class Class7 {
|
||||
const Class7();
|
||||
}
|
||||
''', const [
|
||||
const ConstantData(
|
||||
r'"$integer $string $boolean"', 'StringConstant("5 baz false")'),
|
||||
const ConstantData('0 ? true : false', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_CONDITIONAL_TYPE),
|
||||
const ConstantData('integer ? true : false', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_CONDITIONAL_TYPE),
|
||||
const ConstantData(r'"${const []}"', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE),
|
||||
const ConstantData(r'"${proxy}"', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE),
|
||||
const ConstantData(r'"${proxy}${const []}"', 'NonConstant',
|
||||
expectedErrors: const [
|
||||
MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE,
|
||||
MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE
|
||||
]),
|
||||
const ConstantData(r'"${"${proxy}"}${const []}"', 'NonConstant',
|
||||
expectedErrors: const [
|
||||
MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE,
|
||||
MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE
|
||||
]),
|
||||
const ConstantData('0 + ""', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_NUM_ADD_TYPE),
|
||||
const ConstantData('0 + string', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_NUM_ADD_TYPE),
|
||||
const ConstantData('"" + 0', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE),
|
||||
const ConstantData('string + 0', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE),
|
||||
const ConstantData('true + ""', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE),
|
||||
const ConstantData('boolean + string', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE),
|
||||
const ConstantData('true + false', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_ADD_TYPES),
|
||||
const ConstantData('boolean + false', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_ADD_TYPES),
|
||||
const ConstantData('0 * ""', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE),
|
||||
const ConstantData('0 * string', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE),
|
||||
const ConstantData('0 % ""', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE),
|
||||
const ConstantData('0 % string', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE),
|
||||
const ConstantData('0 << ""', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_BINARY_INT_TYPE),
|
||||
const ConstantData('0 << string', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_BINARY_INT_TYPE),
|
||||
const ConstantData('1 ~/ 0', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_DIV),
|
||||
const ConstantData('1 ~/ 0.0', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_DIV),
|
||||
const ConstantData('1 % 0', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_DIV),
|
||||
const ConstantData('1 % 0.0', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_DIV),
|
||||
const ConstantData('1 << -1', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_SHIFT),
|
||||
const ConstantData('1 >> -1', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_SHIFT),
|
||||
const ConstantData('null[0]', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_INDEX),
|
||||
const ConstantData('const bool.fromEnvironment(0)', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE),
|
||||
const ConstantData('const bool.fromEnvironment(integer)', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE),
|
||||
const ConstantData(
|
||||
'const bool.fromEnvironment("baz", defaultValue: 0)', 'NonConstant',
|
||||
expectedErrors:
|
||||
MessageKind.INVALID_BOOL_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE),
|
||||
const ConstantData(
|
||||
'const bool.fromEnvironment("baz", defaultValue: integer)',
|
||||
'NonConstant',
|
||||
expectedErrors:
|
||||
MessageKind.INVALID_BOOL_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE),
|
||||
const ConstantData('const int.fromEnvironment(0)', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE),
|
||||
const ConstantData('const int.fromEnvironment(integer)', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE),
|
||||
const ConstantData(
|
||||
'const int.fromEnvironment("baz", defaultValue: "")', 'NonConstant',
|
||||
expectedErrors:
|
||||
MessageKind.INVALID_INT_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE),
|
||||
const ConstantData(
|
||||
'const int.fromEnvironment("baz", defaultValue: string)', 'NonConstant',
|
||||
expectedErrors:
|
||||
MessageKind.INVALID_INT_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE),
|
||||
const ConstantData('const String.fromEnvironment(0)', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE),
|
||||
const ConstantData('const String.fromEnvironment(integer)', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE),
|
||||
const ConstantData(
|
||||
'const String.fromEnvironment("baz", defaultValue: 0)', 'NonConstant',
|
||||
expectedErrors:
|
||||
MessageKind.INVALID_STRING_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE),
|
||||
const ConstantData(
|
||||
'const String.fromEnvironment("baz", defaultValue: integer)',
|
||||
'NonConstant',
|
||||
expectedErrors:
|
||||
MessageKind.INVALID_STRING_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE),
|
||||
const ConstantData('true || 0', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE),
|
||||
const ConstantData('0 || true', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE),
|
||||
const ConstantData('true || integer', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE),
|
||||
const ConstantData('integer || true', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE),
|
||||
const ConstantData('true && 0', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_LOGICAL_AND_OPERAND_TYPE),
|
||||
const ConstantData('0 && true', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_LOGICAL_AND_OPERAND_TYPE),
|
||||
const ConstantData('integer && true', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_LOGICAL_AND_OPERAND_TYPE),
|
||||
const ConstantData('!0', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_NOT_TYPE),
|
||||
const ConstantData('!string', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_NOT_TYPE),
|
||||
const ConstantData('-("")', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_NEGATE_TYPE),
|
||||
const ConstantData('-(string)', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_NEGATE_TYPE),
|
||||
const ConstantData('not_string.length', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_STRING_LENGTH_TYPE),
|
||||
const ConstantData('const Class1()', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_CONSTANT_STRING_LENGTH_TYPE),
|
||||
const ConstantData('getter', 'NonConstant'),
|
||||
const ConstantData('const Class2()', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_ASSERT_VALUE),
|
||||
const ConstantData('const Class2.redirect()', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_ASSERT_VALUE),
|
||||
const ConstantData('const Class3()', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_ASSERT_VALUE_MESSAGE),
|
||||
const ConstantData('const Class3.fact()', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_ASSERT_VALUE),
|
||||
const ConstantData('const Class4()', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_ASSERT_VALUE),
|
||||
const ConstantData('const Class5(0)', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_ASSERT_VALUE_MESSAGE),
|
||||
const ConstantData('const Class5(1)', 'ConstructedConstant(Class5())'),
|
||||
const ConstantData('const Class6(1)', 'NonConstant',
|
||||
expectedErrors: MessageKind.INVALID_ASSERT_VALUE_MESSAGE),
|
||||
const ConstantData('const Class6(2)', 'ConstructedConstant(Class6())'),
|
||||
const ConstantData('const Class7()', 'ConstructedConstant(Class7())'),
|
||||
const ConstantData('const Class7() == const Class7()', 'NonConstant',
|
||||
expectedErrors: const [
|
||||
MessageKind.INVALID_CONSTANT_BINARY_PRIMITIVE_TYPE,
|
||||
MessageKind.INVALID_CONSTANT_BINARY_PRIMITIVE_TYPE
|
||||
]),
|
||||
]),
|
||||
const TestData('assert', '''
|
||||
class A {
|
||||
const A() : assert(true);
|
||||
}
|
||||
class B {
|
||||
const B() : assert(true, "Message");
|
||||
}
|
||||
class C {
|
||||
final a;
|
||||
const C(this.a);
|
||||
}
|
||||
class D extends C {
|
||||
final b;
|
||||
const D(c) : b = c + 2, super(c + 1);
|
||||
}
|
||||
''', const [
|
||||
const ConstantData(r'const A()', 'ConstructedConstant(A())'),
|
||||
const ConstantData(r'const B()', 'ConstructedConstant(B())'),
|
||||
const ConstantData(r'const D(0)',
|
||||
'ConstructedConstant(D(a=IntConstant(1),b=IntConstant(2)))'),
|
||||
]),
|
||||
const TestData('instantiations', '''
|
||||
T identity<T>(T t) => t;
|
||||
class C<T> {
|
||||
final T defaultValue;
|
||||
final T Function(T t) identityFunction;
|
||||
|
||||
const C(this.defaultValue, this.identityFunction);
|
||||
}
|
||||
''', const <ConstantData>[
|
||||
const ConstantData('identity', 'FunctionConstant(identity)'),
|
||||
const ConstantData(
|
||||
'const C<int>(0, identity)',
|
||||
'ConstructedConstant(C<int>(defaultValue=IntConstant(0),'
|
||||
'identityFunction=InstantiationConstant([int],'
|
||||
'FunctionConstant(identity))))'),
|
||||
const ConstantData(
|
||||
'const C<double>(0.5, identity)',
|
||||
'ConstructedConstant(C<double>(defaultValue=DoubleConstant(0.5),'
|
||||
'identityFunction=InstantiationConstant([double],'
|
||||
'FunctionConstant(identity))))'),
|
||||
]),
|
||||
const TestData('generic class', '''
|
||||
class C<T> {
|
||||
const C.generative();
|
||||
const C.redirect() : this.generative();
|
||||
}
|
||||
''', const <ConstantData>[
|
||||
const ConstantData(
|
||||
'const C<int>.generative()', 'ConstructedConstant(C<int>())'),
|
||||
const ConstantData(
|
||||
'const C<int>.redirect()', 'ConstructedConstant(C<int>())'),
|
||||
])
|
||||
];
|
||||
|
||||
main(List<String> args) {
|
||||
asyncTest(() async {
|
||||
for (TestData data in DATA) {
|
||||
if (args.isNotEmpty && !args.contains(data.name)) continue;
|
||||
await testData(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future testData(TestData data) async {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.writeln('${data.declarations}');
|
||||
Map<String, ConstantData> constants = {};
|
||||
List<String> names = <String>[];
|
||||
data.constants.forEach((ConstantData constantData) {
|
||||
String name = 'c${constants.length}';
|
||||
names.add(name);
|
||||
sb.writeln('const $name = ${constantData.code};');
|
||||
constants[name] = constantData;
|
||||
});
|
||||
sb.writeln('main() {');
|
||||
for (String name in names) {
|
||||
sb.writeln(' print($name);');
|
||||
}
|
||||
sb.writeln('}');
|
||||
String source = sb.toString();
|
||||
print("--source '${data.name}'---------------------------------------------");
|
||||
print(source);
|
||||
|
||||
Future runTest(
|
||||
EvaluationEnvironment getEnvironment(
|
||||
Compiler compiler, FieldEntity field)) async {
|
||||
CompilationResult result =
|
||||
await runCompiler(memorySourceFiles: {'main.dart': source});
|
||||
Compiler compiler = result.compiler;
|
||||
KElementEnvironment elementEnvironment =
|
||||
compiler.frontendStrategy.elementEnvironment;
|
||||
LibraryEntity library = elementEnvironment.mainLibrary;
|
||||
constants.forEach((String name, ConstantData data) {
|
||||
FieldEntity field = elementEnvironment.lookupLibraryMember(library, name);
|
||||
compiler.reporter.withCurrentElement(field, () {
|
||||
ConstantExpression constant =
|
||||
elementEnvironment.getFieldConstantForTesting(field);
|
||||
|
||||
var expectedResults = data.expectedResults;
|
||||
if (expectedResults is String) {
|
||||
expectedResults = <Map<String, String>, String>{
|
||||
const <String, String>{}: expectedResults
|
||||
};
|
||||
}
|
||||
expectedResults.forEach((Map<String, String> env, String expectedText) {
|
||||
MemoryEnvironment environment =
|
||||
new MemoryEnvironment(getEnvironment(compiler, field), env);
|
||||
ConstantValue value = constant.evaluate(environment);
|
||||
|
||||
Expect.isNotNull(
|
||||
value,
|
||||
"Expected non-null value from evaluation of "
|
||||
"`${constant.toStructuredText()}`.");
|
||||
|
||||
String valueText = value.toStructuredText();
|
||||
Expect.equals(
|
||||
expectedText,
|
||||
valueText,
|
||||
"Unexpected value '${valueText}' for field $field = "
|
||||
"`${constant.toDartText()}`, expected '${expectedText}'.");
|
||||
|
||||
List<MessageKind> errors =
|
||||
environment.errors.map((m) => m.kind).toList();
|
||||
var expectedErrors = data.expectedErrors;
|
||||
if (expectedErrors != null) {
|
||||
if (expectedErrors is! List) {
|
||||
expectedErrors = [expectedErrors];
|
||||
}
|
||||
Expect.listEquals(
|
||||
expectedErrors,
|
||||
errors,
|
||||
"Error mismatch for `$field = ${constant.toDartText()}`:\n"
|
||||
"Expected: ${data.expectedErrors},\n"
|
||||
"Found: ${errors}.");
|
||||
} else {
|
||||
Expect.isTrue(
|
||||
errors.isEmpty,
|
||||
"Unexpected errors for `$field = ${constant.toDartText()}`:\n"
|
||||
"Found: ${errors}.");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const skipStrongList = const [
|
||||
// TODO(johnniwinther): Investigate why different errors are reported in
|
||||
// strong mode.
|
||||
'errors',
|
||||
];
|
||||
|
||||
if (!skipStrongList.contains(data.name)) {
|
||||
await runTest((Compiler compiler, FieldEntity field) {
|
||||
KernelFrontEndStrategy frontendStrategy = compiler.frontendStrategy;
|
||||
KernelToElementMapImpl elementMap = frontendStrategy.elementMap;
|
||||
return new KernelEvaluationEnvironment(elementMap, null, field,
|
||||
constantRequired: field.isConst);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,397 +0,0 @@
|
|||
// Copyright (c) 2015, 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.
|
||||
|
||||
library constant_expression_test;
|
||||
|
||||
import 'dart:async';
|
||||
import 'package:async_helper/async_helper.dart';
|
||||
import 'package:expect/expect.dart';
|
||||
import 'package:compiler/src/common_elements.dart' show KElementEnvironment;
|
||||
import 'package:compiler/src/compiler.dart';
|
||||
import 'package:compiler/src/constants/expressions.dart';
|
||||
import 'package:compiler/src/kernel/element_map_impl.dart';
|
||||
import 'package:compiler/src/elements/entities.dart';
|
||||
import '../helpers/memory_compiler.dart';
|
||||
import 'constant_expression_evaluate_test.dart' show MemoryEnvironment;
|
||||
|
||||
class TestData {
|
||||
/// Declarations needed for the [constants].
|
||||
final String declarations;
|
||||
|
||||
/// Tested constants.
|
||||
final List<ConstantData> constants;
|
||||
|
||||
const TestData(this.declarations, this.constants);
|
||||
}
|
||||
|
||||
class ConstantData {
|
||||
/// Source code for the constant expression.
|
||||
final String code;
|
||||
|
||||
/// The expected constant expression kind.
|
||||
final ConstantExpressionKind kind;
|
||||
|
||||
/// ConstantExpression.getText() result if different from [code].
|
||||
final String text;
|
||||
|
||||
/// The expected instance type for ConstructedConstantExpression.
|
||||
final String type;
|
||||
|
||||
/// The expected instance fields for ConstructedConstantExpression.
|
||||
final Map<String, String> fields;
|
||||
|
||||
const ConstantData(String code, this.kind,
|
||||
{String text, this.type, this.fields})
|
||||
: this.code = code,
|
||||
this.text = text ?? code;
|
||||
}
|
||||
|
||||
const List<TestData> DATA = const [
|
||||
const TestData('''
|
||||
class Class<T, S> {
|
||||
final a;
|
||||
final b;
|
||||
final c;
|
||||
const Class(this.a, {this.b, this.c: true});
|
||||
const Class.named([this.a, this.b = 0, this.c = 2]);
|
||||
|
||||
static const staticConstant = 0;
|
||||
static staticFunction() {}
|
||||
}
|
||||
const t = true;
|
||||
const f = false;
|
||||
const toplevelConstant = 0;
|
||||
toplevelFunction() {}
|
||||
''', const [
|
||||
const ConstantData('null', ConstantExpressionKind.NULL),
|
||||
const ConstantData('false', ConstantExpressionKind.BOOL),
|
||||
const ConstantData('true', ConstantExpressionKind.BOOL),
|
||||
const ConstantData('0', ConstantExpressionKind.INT),
|
||||
const ConstantData('0.0', ConstantExpressionKind.DOUBLE),
|
||||
const ConstantData('"foo"', ConstantExpressionKind.STRING),
|
||||
const ConstantData('1 + 2', ConstantExpressionKind.BINARY),
|
||||
const ConstantData('1 == 2', ConstantExpressionKind.BINARY),
|
||||
const ConstantData('1 != 2', ConstantExpressionKind.UNARY,
|
||||
// a != b is encoded as !(a == b) by CFE.
|
||||
text: '!(1 == 2)'),
|
||||
const ConstantData('1 ?? 2', ConstantExpressionKind.BINARY),
|
||||
const ConstantData('-(1)', ConstantExpressionKind.UNARY, text: '-1'),
|
||||
const ConstantData('"foo".length', ConstantExpressionKind.STRING_LENGTH),
|
||||
const ConstantData('identical(0, 1)', ConstantExpressionKind.IDENTICAL),
|
||||
const ConstantData('"a" "b"', ConstantExpressionKind.CONCATENATE,
|
||||
text: '"ab"'),
|
||||
const ConstantData('identical', ConstantExpressionKind.FUNCTION),
|
||||
const ConstantData('true ? 0 : 1', ConstantExpressionKind.CONDITIONAL),
|
||||
const ConstantData('proxy', ConstantExpressionKind.FIELD),
|
||||
const ConstantData('Object', ConstantExpressionKind.TYPE),
|
||||
const ConstantData('#name', ConstantExpressionKind.SYMBOL),
|
||||
const ConstantData('const []', ConstantExpressionKind.LIST),
|
||||
const ConstantData('const [0, 1]', ConstantExpressionKind.LIST,
|
||||
text: 'const <int>[0, 1]'),
|
||||
const ConstantData('const <int>[0, 1]', ConstantExpressionKind.LIST),
|
||||
const ConstantData('const <dynamic>[0, 1]', ConstantExpressionKind.LIST,
|
||||
text: 'const [0, 1]'),
|
||||
const ConstantData('const {}', ConstantExpressionKind.MAP),
|
||||
const ConstantData('const {0: 1, 2: 3}', ConstantExpressionKind.MAP,
|
||||
text: 'const <int, int>{0: 1, 2: 3}'),
|
||||
const ConstantData(
|
||||
'const <int, int>{0: 1, 2: 3}', ConstantExpressionKind.MAP),
|
||||
const ConstantData(
|
||||
'const <String, int>{"0": 1, "2": 3}', ConstantExpressionKind.MAP),
|
||||
const ConstantData(
|
||||
'const <String, dynamic>{"0": 1, "2": 3}', ConstantExpressionKind.MAP),
|
||||
const ConstantData(
|
||||
'const <dynamic, dynamic>{"0": 1, "2": 3}', ConstantExpressionKind.MAP,
|
||||
text: 'const {"0": 1, "2": 3}'),
|
||||
const ConstantData('const bool.fromEnvironment("foo", defaultValue: false)',
|
||||
ConstantExpressionKind.BOOL_FROM_ENVIRONMENT),
|
||||
const ConstantData('const int.fromEnvironment("foo", defaultValue: 42)',
|
||||
ConstantExpressionKind.INT_FROM_ENVIRONMENT),
|
||||
const ConstantData(
|
||||
'const String.fromEnvironment("foo", defaultValue: "bar")',
|
||||
ConstantExpressionKind.STRING_FROM_ENVIRONMENT),
|
||||
const ConstantData('const Class(0)', ConstantExpressionKind.CONSTRUCTED),
|
||||
const ConstantData(
|
||||
'const Class(0, b: 1)', ConstantExpressionKind.CONSTRUCTED),
|
||||
const ConstantData(
|
||||
'const Class(0, c: 2)', ConstantExpressionKind.CONSTRUCTED),
|
||||
const ConstantData(
|
||||
'const Class(0, b: 3, c: 4)', ConstantExpressionKind.CONSTRUCTED),
|
||||
const ConstantData(
|
||||
'const Class.named()', ConstantExpressionKind.CONSTRUCTED),
|
||||
const ConstantData(
|
||||
'const Class.named(0)', ConstantExpressionKind.CONSTRUCTED),
|
||||
const ConstantData(
|
||||
'const Class.named(0, 1)', ConstantExpressionKind.CONSTRUCTED),
|
||||
const ConstantData(
|
||||
'const Class.named(0, 1, 2)', ConstantExpressionKind.CONSTRUCTED),
|
||||
const ConstantData(
|
||||
'const Class<String, int>(0)', ConstantExpressionKind.CONSTRUCTED),
|
||||
const ConstantData(
|
||||
'const Class<String, dynamic>(0)', ConstantExpressionKind.CONSTRUCTED),
|
||||
const ConstantData(
|
||||
'const Class<dynamic, String>(0)', ConstantExpressionKind.CONSTRUCTED),
|
||||
const ConstantData(
|
||||
'const Class<dynamic, dynamic>(0)', ConstantExpressionKind.CONSTRUCTED,
|
||||
text: 'const Class(0)'),
|
||||
const ConstantData('toplevelConstant', ConstantExpressionKind.FIELD),
|
||||
const ConstantData('toplevelFunction', ConstantExpressionKind.FUNCTION),
|
||||
const ConstantData('Class.staticConstant', ConstantExpressionKind.FIELD),
|
||||
const ConstantData('Class.staticFunction', ConstantExpressionKind.FUNCTION),
|
||||
const ConstantData('1 + 2', ConstantExpressionKind.BINARY),
|
||||
const ConstantData('1 + 2 + 3', ConstantExpressionKind.BINARY),
|
||||
const ConstantData('1 + -2', ConstantExpressionKind.BINARY),
|
||||
const ConstantData('-1 + 2', ConstantExpressionKind.BINARY),
|
||||
const ConstantData('(1 + 2) + 3', ConstantExpressionKind.BINARY,
|
||||
text: '1 + 2 + 3'),
|
||||
const ConstantData('1 + (2 + 3)', ConstantExpressionKind.BINARY,
|
||||
text: '1 + 2 + 3'),
|
||||
const ConstantData('1 * 2', ConstantExpressionKind.BINARY),
|
||||
const ConstantData('1 * 2 + 3', ConstantExpressionKind.BINARY),
|
||||
const ConstantData('1 * (2 + 3)', ConstantExpressionKind.BINARY),
|
||||
const ConstantData('1 + 2 * 3', ConstantExpressionKind.BINARY),
|
||||
const ConstantData('(1 + 2) * 3', ConstantExpressionKind.BINARY),
|
||||
const ConstantData(
|
||||
'false || identical(0, 1)', ConstantExpressionKind.BINARY),
|
||||
const ConstantData('!identical(0, 1)', ConstantExpressionKind.UNARY),
|
||||
const ConstantData(
|
||||
'!identical(0, 1) || false', ConstantExpressionKind.BINARY),
|
||||
const ConstantData(
|
||||
'!(identical(0, 1) || false)', ConstantExpressionKind.UNARY),
|
||||
const ConstantData('identical(0, 1) ? 3 * 4 + 5 : 6 + 7 * 8',
|
||||
ConstantExpressionKind.CONDITIONAL),
|
||||
const ConstantData('t ? f ? 0 : 1 : 2', ConstantExpressionKind.CONDITIONAL),
|
||||
const ConstantData(
|
||||
'(t ? t : f) ? f ? 0 : 1 : 2', ConstantExpressionKind.CONDITIONAL),
|
||||
const ConstantData(
|
||||
't ? t : f ? f ? 0 : 1 : 2', ConstantExpressionKind.CONDITIONAL),
|
||||
const ConstantData(
|
||||
't ? t ? t : t : t ? t : t', ConstantExpressionKind.CONDITIONAL),
|
||||
const ConstantData(
|
||||
't ? (t ? t : t) : (t ? t : t)', ConstantExpressionKind.CONDITIONAL,
|
||||
text: 't ? t ? t : t : t ? t : t'),
|
||||
const ConstantData(
|
||||
'const [const <dynamic, dynamic>{0: true, "1": "c" "d"}, '
|
||||
'const Class(const Class<dynamic, dynamic>(toplevelConstant))]',
|
||||
ConstantExpressionKind.LIST,
|
||||
text: 'const <Object>[const {0: true, "1": "cd"}, '
|
||||
'const Class(const Class(toplevelConstant))]'),
|
||||
]),
|
||||
const TestData('''
|
||||
class A {
|
||||
const A();
|
||||
}
|
||||
class B {
|
||||
final field1;
|
||||
const B(this.field1);
|
||||
}
|
||||
class C extends B {
|
||||
final field2;
|
||||
const C({field1: 42, this.field2: false}) : super(field1);
|
||||
const C.named([field = false]) : this(field1: field, field2: field);
|
||||
}
|
||||
''', const [
|
||||
const ConstantData('const Object()', ConstantExpressionKind.CONSTRUCTED,
|
||||
type: 'Object', fields: const {}),
|
||||
const ConstantData('const A()', ConstantExpressionKind.CONSTRUCTED,
|
||||
type: 'A', fields: const {}),
|
||||
const ConstantData('const B(0)', ConstantExpressionKind.CONSTRUCTED,
|
||||
type: 'B', fields: const {'field(B#field1)': '0'}),
|
||||
const ConstantData('const B(const A())', ConstantExpressionKind.CONSTRUCTED,
|
||||
type: 'B', fields: const {'field(B#field1)': 'const A()'}),
|
||||
const ConstantData('const C()', ConstantExpressionKind.CONSTRUCTED,
|
||||
type: 'C',
|
||||
fields: const {
|
||||
'field(B#field1)': '42',
|
||||
'field(C#field2)': 'false',
|
||||
}),
|
||||
const ConstantData(
|
||||
'const C(field1: 87)', ConstantExpressionKind.CONSTRUCTED,
|
||||
type: 'C',
|
||||
fields: const {
|
||||
'field(B#field1)': '87',
|
||||
'field(C#field2)': 'false',
|
||||
}),
|
||||
const ConstantData(
|
||||
'const C(field2: true)', ConstantExpressionKind.CONSTRUCTED,
|
||||
type: 'C',
|
||||
fields: const {
|
||||
'field(B#field1)': '42',
|
||||
'field(C#field2)': 'true',
|
||||
}),
|
||||
const ConstantData('const C.named()', ConstantExpressionKind.CONSTRUCTED,
|
||||
type: 'C',
|
||||
fields: const {
|
||||
'field(B#field1)': 'false',
|
||||
'field(C#field2)': 'false',
|
||||
}),
|
||||
const ConstantData('const C.named(87)', ConstantExpressionKind.CONSTRUCTED,
|
||||
type: 'C',
|
||||
fields: const {
|
||||
'field(B#field1)': '87',
|
||||
'field(C#field2)': '87',
|
||||
}),
|
||||
]),
|
||||
const TestData('''
|
||||
class A<T> implements B<Null> {
|
||||
final field1;
|
||||
const A({this.field1:42});
|
||||
}
|
||||
class B<S> implements C<Null> {
|
||||
const factory B({field1}) = A<B<S>>;
|
||||
const factory B.named() = A<S>;
|
||||
}
|
||||
class C<U> {
|
||||
const factory C({field1}) = A<B<double>>;
|
||||
}
|
||||
''', const [
|
||||
const ConstantData('const A()', ConstantExpressionKind.CONSTRUCTED,
|
||||
type: 'A<dynamic>', fields: const {'field(A#field1)': '42'}),
|
||||
const ConstantData(
|
||||
'const A<int>(field1: 87)', ConstantExpressionKind.CONSTRUCTED,
|
||||
type: 'A<int>', fields: const {'field(A#field1)': '87'}),
|
||||
const ConstantData('const B()', ConstantExpressionKind.CONSTRUCTED,
|
||||
type: 'A<B<dynamic>>',
|
||||
fields: const {
|
||||
'field(A#field1)': '42',
|
||||
},
|
||||
// Redirecting factories are replaced by their effective targets by CFE.
|
||||
text: 'const A<B<dynamic>>()'),
|
||||
const ConstantData('const B<int>()', ConstantExpressionKind.CONSTRUCTED,
|
||||
type: 'A<B<int>>',
|
||||
fields: const {
|
||||
'field(A#field1)': '42',
|
||||
},
|
||||
// Redirecting factories are replaced by their effective targets by CFE.
|
||||
text: 'const A<B<int>>()'),
|
||||
const ConstantData(
|
||||
'const B<int>(field1: 87)', ConstantExpressionKind.CONSTRUCTED,
|
||||
type: 'A<B<int>>',
|
||||
fields: const {
|
||||
'field(A#field1)': '87',
|
||||
},
|
||||
// Redirecting factories are replaced by their effective targets by CFE.
|
||||
text: 'const A<B<int>>(field1: 87)'),
|
||||
const ConstantData(
|
||||
'const C<int>(field1: 87)', ConstantExpressionKind.CONSTRUCTED,
|
||||
type: 'A<B<double>>',
|
||||
fields: const {
|
||||
'field(A#field1)': '87',
|
||||
},
|
||||
// Redirecting factories are replaced by their effective targets by CFE.
|
||||
text: 'const A<B<double>>(field1: 87)'),
|
||||
const ConstantData(
|
||||
'const B<int>.named()', ConstantExpressionKind.CONSTRUCTED,
|
||||
type: 'A<int>',
|
||||
fields: const {
|
||||
'field(A#field1)': '42',
|
||||
},
|
||||
// Redirecting factories are replaced by their effective targets by CFE.
|
||||
text: 'const A<int>()'),
|
||||
]),
|
||||
const TestData('''
|
||||
T identity<T>(T t) => t;
|
||||
class C<T> {
|
||||
final T defaultValue;
|
||||
final T Function(T t) identityFunction;
|
||||
|
||||
const C(this.defaultValue, this.identityFunction);
|
||||
}
|
||||
''', const <ConstantData>[
|
||||
const ConstantData('identity', ConstantExpressionKind.FUNCTION),
|
||||
const ConstantData(
|
||||
'const C<int>(0, identity)', ConstantExpressionKind.CONSTRUCTED,
|
||||
type: 'C<int>', text: 'const C<int>(0, <int>(identity))'),
|
||||
const ConstantData(
|
||||
'const C<double>(0.5, identity)', ConstantExpressionKind.CONSTRUCTED,
|
||||
type: 'C<double>', text: 'const C<double>(0.5, <double>(identity))'),
|
||||
])
|
||||
];
|
||||
|
||||
main() {
|
||||
asyncTest(() async {
|
||||
await runTest();
|
||||
});
|
||||
}
|
||||
|
||||
Future runTest() async {
|
||||
for (TestData data in DATA) {
|
||||
await testData(data);
|
||||
}
|
||||
}
|
||||
|
||||
Future testData(TestData data) async {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.writeln('${data.declarations}');
|
||||
Map<String, ConstantData> constants = {};
|
||||
List<String> names = <String>[];
|
||||
data.constants.forEach((ConstantData constantData) {
|
||||
String name = 'c${constants.length}';
|
||||
names.add(name);
|
||||
sb.writeln('const $name = ${constantData.code};');
|
||||
constants[name] = constantData;
|
||||
});
|
||||
sb.writeln('main() {');
|
||||
for (String name in names) {
|
||||
sb.writeln(' print($name);');
|
||||
}
|
||||
sb.writeln('}');
|
||||
String source = sb.toString();
|
||||
CompilationResult result =
|
||||
await runCompiler(memorySourceFiles: {'main.dart': source});
|
||||
Compiler compiler = result.compiler;
|
||||
KElementEnvironment elementEnvironment =
|
||||
compiler.frontendStrategy.elementEnvironment;
|
||||
|
||||
MemoryEnvironment environment = new MemoryEnvironment(
|
||||
new KernelEvaluationEnvironment(
|
||||
(compiler.frontendStrategy as dynamic).elementMap,
|
||||
compiler.environment,
|
||||
null));
|
||||
dynamic library = elementEnvironment.mainLibrary;
|
||||
constants.forEach((String name, ConstantData data) {
|
||||
FieldEntity field = elementEnvironment.lookupLibraryMember(library, name);
|
||||
dynamic constant = elementEnvironment.getFieldConstantForTesting(field);
|
||||
Expect.equals(
|
||||
data.kind,
|
||||
constant.kind,
|
||||
"Unexpected kind '${constant.kind}' for constant "
|
||||
"`${constant.toDartText()}`, expected '${data.kind}'.");
|
||||
String text = data.text;
|
||||
Expect.equals(
|
||||
text,
|
||||
constant.toDartText(),
|
||||
"Unexpected text '${constant.toDartText()}' for constant, "
|
||||
"expected '${text}'.");
|
||||
if (data.type != null) {
|
||||
String instanceType =
|
||||
constant.computeInstanceType(environment).toString();
|
||||
Expect.equals(
|
||||
data.type,
|
||||
instanceType,
|
||||
"Unexpected type '$instanceType' for constant "
|
||||
"`${constant.toDartText()}`, expected '${data.type}'.");
|
||||
}
|
||||
if (data.fields != null) {
|
||||
Map instanceFields = constant.computeInstanceData(environment).fieldMap;
|
||||
Expect.equals(
|
||||
data.fields.length,
|
||||
instanceFields.length,
|
||||
"Unexpected field count ${instanceFields.length} for constant "
|
||||
"`${constant.toDartText()}`, expected '${data.fields.length}'.");
|
||||
instanceFields.forEach((field, expression) {
|
||||
String name = '$field';
|
||||
Expect.isTrue(name.startsWith('k:'));
|
||||
name = name.substring(2).replaceAll('.', "#");
|
||||
String expression = instanceFields[field].toDartText();
|
||||
String expected = data.fields[name];
|
||||
Expect.equals(
|
||||
expected,
|
||||
expression,
|
||||
"Unexpected field expression ${expression} for field '$name' in "
|
||||
"constant `${constant.toDartText()}`, expected '${expected}'.");
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
Loading…
Reference in a new issue