mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 03:07:49 +00:00
Move function reference const tests to evaluation_test.dart
This change moves tests out of the older-style test file. In addition: * additional tests for uninstantiated function tearoff identity. * additional tests for using a type parameter as a type argument in a function tearoff in a const expression. Change-Id: I6c6a6db13144e02794a62d78337013b4a525549a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/214139 Commit-Queue: Samuel Rawlins <srawlins@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
parent
e559b80f52
commit
5e0f4c24c5
|
@ -28,7 +28,7 @@ class ConstantEvaluatorTest extends PubPackageResolutionTest {
|
|||
}
|
||||
expect(
|
||||
typeArguments.map(
|
||||
(arg) => arg.toTypeValue()!.getDisplayString(withNullability: false)),
|
||||
(arg) => arg.toTypeValue()!.getDisplayString(withNullability: true)),
|
||||
equals(typeArgumentNames),
|
||||
);
|
||||
}
|
||||
|
@ -226,100 +226,6 @@ class C {
|
|||
await _assertValueBool(false, "'a' == 'b'");
|
||||
}
|
||||
|
||||
test_functionReference_explicitTypeArgs_badBound() async {
|
||||
var result = await _getExpressionValue("foo<String>", context: '''
|
||||
void foo<T extends num>(T a) {}
|
||||
''');
|
||||
expect(result.isValid, isTrue);
|
||||
DartObject value = result.value!;
|
||||
assertType(value.type, 'void Function(String)');
|
||||
assertElement(value.toFunctionValue(), findElement.topFunction('foo'));
|
||||
assertTypeArguments(value, ['String']);
|
||||
}
|
||||
|
||||
test_functionReference_explicitTypeArgs_differentElements() async {
|
||||
var result = await _getExpressionValue("(b ? foo : bar)<int>", context: '''
|
||||
const b = true;
|
||||
void foo<T>(String a, T b) {}
|
||||
void bar<T>(T a, String b) {}
|
||||
''');
|
||||
expect(result.isValid, isTrue);
|
||||
DartObject value = result.value!;
|
||||
assertType(value.type, 'void Function(String, int)');
|
||||
assertElement(value.toFunctionValue(), findElement.topFunction('foo'));
|
||||
assertTypeArguments(value, ['int']);
|
||||
}
|
||||
|
||||
test_functionReference_explicitTypeArgs_identifier() async {
|
||||
// TODO(srawlins): Add test where the type argument is a type variable.
|
||||
var result = await _getExpressionValue("foo<int>", context: '''
|
||||
void foo<T>(T a) {}
|
||||
''');
|
||||
expect(result.isValid, isTrue);
|
||||
var value = result.value!;
|
||||
assertType(value.type, 'void Function(int)');
|
||||
assertElement(value.toFunctionValue(), findElement.topFunction('foo'));
|
||||
assertTypeArguments(value, ['int']);
|
||||
}
|
||||
|
||||
test_functionReference_explicitTypeArgs_nonIdentifier() async {
|
||||
var result = await _getExpressionValue("(b ? foo : bar)<int>", context: '''
|
||||
const b = true;
|
||||
void foo<T>(T a) {}
|
||||
void bar<T>(T a) {}
|
||||
''');
|
||||
expect(result.isValid, isTrue);
|
||||
var value = result.value!;
|
||||
assertType(value.type, 'void Function(int)');
|
||||
assertElement(value.toFunctionValue(), findElement.topFunction('foo'));
|
||||
assertTypeArguments(value, ['int']);
|
||||
}
|
||||
|
||||
test_functionReference_explicitTypeArgs_notAType() async {
|
||||
var result = await _getExpressionValue("foo<true>", context: '''
|
||||
void foo<T>(T a) {}
|
||||
''');
|
||||
expect(result.isValid, isFalse);
|
||||
}
|
||||
|
||||
test_functionReference_explicitTypeArgs_tooFew() async {
|
||||
var result = await _getExpressionValue("foo<int>", context: '''
|
||||
void foo<T, U>(T a) {}
|
||||
''');
|
||||
expect(result.isValid, isFalse);
|
||||
}
|
||||
|
||||
test_functionReference_explicitTypeArgs_tooMany() async {
|
||||
var result = await _getExpressionValue("foo<int, int>", context: '''
|
||||
void foo<T>(T a) {}
|
||||
''');
|
||||
expect(result.isValid, isFalse);
|
||||
}
|
||||
|
||||
test_functionReference_uninstantiated_identifier() async {
|
||||
var result = await _getExpressionValue("foo", context: '''
|
||||
void foo<T>(T a) {}
|
||||
''');
|
||||
expect(result.isValid, isTrue);
|
||||
DartObject value = result.value!;
|
||||
assertType(value.type, 'void Function<T>(T)');
|
||||
assertElement(value.toFunctionValue(), findElement.topFunction('foo'));
|
||||
assertTypeArguments(value, null);
|
||||
}
|
||||
|
||||
test_functionReference_uninstantiated_nonIdentifier() async {
|
||||
var result = await _getExpressionValue("b ? foo : bar", context: '''
|
||||
const b = true;
|
||||
void foo<T>(T a) {}
|
||||
void bar<T>(T a) {}
|
||||
''');
|
||||
expect(result.isValid, isTrue);
|
||||
DartObject value = result.value!;
|
||||
assertType(value.type, 'void Function<T>(T)');
|
||||
assertElement(value.toFunctionValue(), findElement.topFunction('foo'));
|
||||
assertTypeArguments(value, null);
|
||||
}
|
||||
|
||||
test_greaterThan_int_int() async {
|
||||
await _assertValueBool(false, "2 > 3");
|
||||
}
|
||||
|
@ -328,51 +234,6 @@ void bar<T>(T a) {}
|
|||
await _assertValueBool(false, "2 >= 3");
|
||||
}
|
||||
|
||||
test_identical_functionReference_explicitTypeArgs_differentElements() async {
|
||||
var result =
|
||||
await _getExpressionValue("identical(foo<int>, bar<int>)", context: '''
|
||||
void foo<T>(T a) {}
|
||||
void bar<T>(T a) {}
|
||||
''');
|
||||
expect(result.isValid, isTrue);
|
||||
DartObject value = result.value!;
|
||||
assertType(value.type, 'bool');
|
||||
expect(value.toBoolValue(), false);
|
||||
}
|
||||
|
||||
test_identical_functionReference_explicitTypeArgs_differentTypeArgs() async {
|
||||
var result = await _getExpressionValue("identical(foo<int>, foo<String>)",
|
||||
context: '''
|
||||
void foo<T>(T a) {}
|
||||
''');
|
||||
expect(result.isValid, isTrue);
|
||||
DartObject value = result.value!;
|
||||
assertType(value.type, 'bool');
|
||||
expect(value.toBoolValue(), false);
|
||||
}
|
||||
|
||||
test_identical_functionReference_explicitTypeArgs_sameElement() async {
|
||||
var result =
|
||||
await _getExpressionValue("identical(foo<int>, foo<int>)", context: '''
|
||||
void foo<T>(T a) {}
|
||||
''');
|
||||
expect(result.isValid, isTrue);
|
||||
DartObject value = result.value!;
|
||||
assertType(value.type, 'bool');
|
||||
expect(value.toBoolValue(), true);
|
||||
}
|
||||
|
||||
test_identical_functionReference_onlyOneHasTypeArgs() async {
|
||||
var result =
|
||||
await _getExpressionValue("identical(foo<int>, foo)", context: '''
|
||||
void foo<T>(T a) {}
|
||||
''');
|
||||
expect(result.isValid, isTrue);
|
||||
DartObject value = result.value!;
|
||||
assertType(value.type, 'bool');
|
||||
expect(value.toBoolValue(), false);
|
||||
}
|
||||
|
||||
@failingTest
|
||||
test_identifier_class() async {
|
||||
var result = await _getExpressionValue("?");
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// 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';
|
||||
|
@ -120,6 +121,62 @@ const a = identical(C<int>.new, C.new);
|
|||
);
|
||||
}
|
||||
|
||||
test_identical_functionReference_explicitTypeArgs_differentElements() async {
|
||||
await resolveTestCode('''
|
||||
void foo<T>(T a) {}
|
||||
void bar<T>(T a) {}
|
||||
const g = identical(foo<int>, bar<int>);
|
||||
''');
|
||||
expect(
|
||||
_evaluateConstant('g'),
|
||||
_boolValue(false),
|
||||
);
|
||||
}
|
||||
|
||||
test_identical_functionReference_explicitTypeArgs_differentTypeArgs() async {
|
||||
await resolveTestCode('''
|
||||
void foo<T>(T a) {}
|
||||
const g = identical(foo<int>, foo<String>);
|
||||
''');
|
||||
expect(
|
||||
_evaluateConstant('g'),
|
||||
_boolValue(false),
|
||||
);
|
||||
}
|
||||
|
||||
test_identical_functionReference_explicitTypeArgs_onlyOneHasTypeArgs() async {
|
||||
await resolveTestCode('''
|
||||
void foo<T>(T a) {}
|
||||
const g = identical(foo<int>, foo);
|
||||
''');
|
||||
expect(
|
||||
_evaluateConstant('g'),
|
||||
_boolValue(false),
|
||||
);
|
||||
}
|
||||
|
||||
test_identical_functionReference_explicitTypeArgs_sameElement() async {
|
||||
await resolveTestCode('''
|
||||
void foo<T>(T a) {}
|
||||
const g = identical(foo<int>, foo<int>);
|
||||
''');
|
||||
expect(
|
||||
_evaluateConstant('g'),
|
||||
_boolValue(true),
|
||||
);
|
||||
}
|
||||
|
||||
test_identical_functionReference_uninstantiated_sameElement() async {
|
||||
await resolveTestCode('''
|
||||
void foo<T>(T a) {}
|
||||
const g = identical(foo, foo);
|
||||
''');
|
||||
expect(
|
||||
_evaluateConstant('g'),
|
||||
_boolValue(true),
|
||||
);
|
||||
}
|
||||
|
||||
test_visitAsExpression_potentialConstType() async {
|
||||
await assertNoErrorsInCode('''
|
||||
const num three = 3;
|
||||
|
@ -223,6 +280,128 @@ const c = 0xFF >>> 0;
|
|||
expect(result.toIntValue(), 0xFF);
|
||||
}
|
||||
|
||||
test_visitFunctionReference_explicitTypeArgs_complexExpression() async {
|
||||
await resolveTestCode('''
|
||||
const b = true;
|
||||
void foo<T>(T a) {}
|
||||
void bar<T>(T a) {}
|
||||
const g = (b ? foo : bar)<int>;
|
||||
''');
|
||||
var result = _evaluateConstant('g');
|
||||
assertType(result.type, 'void Function(int)');
|
||||
assertElement(result.toFunctionValue(), findElement.topFunction('foo'));
|
||||
_assertTypeArguments(result, ['int']);
|
||||
}
|
||||
|
||||
test_visitFunctionReference_explicitTypeArgs_complexExpression_differentTypes() async {
|
||||
await resolveTestCode('''
|
||||
const b = true;
|
||||
void foo<T>(String a, T b) {}
|
||||
void bar<T>(T a, String b) {}
|
||||
const g = (b ? foo : bar)<int>;
|
||||
''');
|
||||
var result = _evaluateConstant('g');
|
||||
assertType(result.type, 'void Function(String, int)');
|
||||
assertElement(result.toFunctionValue(), findElement.topFunction('foo'));
|
||||
_assertTypeArguments(result, ['int']);
|
||||
}
|
||||
|
||||
test_visitFunctionReference_explicitTypeArgs_functionName_constantType() async {
|
||||
await resolveTestCode('''
|
||||
void f<T>(T a) {}
|
||||
const g = f<int>;
|
||||
''');
|
||||
var result = _evaluateConstant('g');
|
||||
assertType(result.type, 'void Function(int)');
|
||||
assertElement(result.toFunctionValue(), findElement.topFunction('f'));
|
||||
_assertTypeArguments(result, ['int']);
|
||||
}
|
||||
|
||||
test_visitFunctionReference_explicitTypeArgs_functionName_notMatchingBound() async {
|
||||
await resolveTestCode('''
|
||||
void f<T extends num>(T a) {}
|
||||
const g = f<String>;
|
||||
''');
|
||||
var result = _evaluateConstant('g');
|
||||
assertType(result.type, 'void Function(String)');
|
||||
assertElement(result.toFunctionValue(), findElement.topFunction('f'));
|
||||
_assertTypeArguments(result, ['String']);
|
||||
}
|
||||
|
||||
test_visitFunctionReference_functionName_explicitTypeArgs_notType() async {
|
||||
await resolveTestCode('''
|
||||
void foo<T>(T a) {}
|
||||
const g = foo<true>;
|
||||
''');
|
||||
var result = _evaluateConstantOrNull('g', errorCodes: [
|
||||
CompileTimeErrorCode.CONST_EVAL_TYPE_NUM,
|
||||
CompileTimeErrorCode.INVALID_CONSTANT,
|
||||
]);
|
||||
expect(result, isNull);
|
||||
}
|
||||
|
||||
test_visitFunctionReference_functionName_explicitTypeArgs_tooFew() async {
|
||||
await resolveTestCode('''
|
||||
void foo<T, U>(T a, U b) {}
|
||||
const g = foo<int>;
|
||||
''');
|
||||
var result = _evaluateConstantOrNull('g');
|
||||
// The wrong number of arguments is reported elsewhere. Here, the result is
|
||||
// simply `null`.
|
||||
expect(result, isNull);
|
||||
}
|
||||
|
||||
test_visitFunctionReference_functionName_explicitTypeArgs_tooMany() async {
|
||||
await resolveTestCode('''
|
||||
void foo<T>(T a) {}
|
||||
const g = foo<int, String>;
|
||||
''');
|
||||
var result = _evaluateConstantOrNull('g');
|
||||
// The wrong number of arguments is reported elsewhere. Here, the result is
|
||||
// simply `null`.
|
||||
expect(result, isNull);
|
||||
}
|
||||
|
||||
test_visitFunctionReference_functionName_explicitTypeArgs_typeParameter() async {
|
||||
await resolveTestCode('''
|
||||
void f<T>(T a) {}
|
||||
|
||||
class C<U> {
|
||||
void m() {
|
||||
static const g = f<U>;
|
||||
}
|
||||
}
|
||||
''');
|
||||
var result = _evaluateConstantLocal('g')!;
|
||||
assertType(result.type, 'void Function(U)');
|
||||
assertElement(result.toFunctionValue(), findElement.topFunction('f'));
|
||||
_assertTypeArguments(result, ['U']);
|
||||
}
|
||||
|
||||
test_visitFunctionReference_uninstantiated_complexExpression() async {
|
||||
await resolveTestCode('''
|
||||
const b = true;
|
||||
void foo<T>(T a) {}
|
||||
void bar<T>(T a) {}
|
||||
const g = b ? foo : bar;
|
||||
''');
|
||||
var result = _evaluateConstant('g');
|
||||
assertType(result.type, 'void Function<T>(T)');
|
||||
assertElement(result.toFunctionValue(), findElement.topFunction('foo'));
|
||||
_assertTypeArguments(result, null);
|
||||
}
|
||||
|
||||
test_visitFunctionReference_uninstantiated_functionName() async {
|
||||
await resolveTestCode('''
|
||||
void f<T>(T a) {}
|
||||
const g = f;
|
||||
''');
|
||||
var result = _evaluateConstant('g');
|
||||
assertType(result.type, 'void Function<T>(T)');
|
||||
assertElement(result.toFunctionValue(), findElement.topFunction('f'));
|
||||
_assertTypeArguments(result, null);
|
||||
}
|
||||
|
||||
test_visitSimpleIdentifier_className() async {
|
||||
await resolveTestCode('''
|
||||
const a = C;
|
||||
|
@ -1320,6 +1499,19 @@ const b = 3;''');
|
|||
}
|
||||
|
||||
class ConstantVisitorTestSupport extends PubPackageResolutionTest {
|
||||
void _assertTypeArguments(DartObject value, List<String>? typeArgumentNames) {
|
||||
var typeArguments = (value as DartObjectImpl).typeArguments;
|
||||
if (typeArguments == null) {
|
||||
expect(typeArguments, typeArgumentNames);
|
||||
return;
|
||||
}
|
||||
expect(
|
||||
typeArguments.map(
|
||||
(arg) => arg.toTypeValue()!.getDisplayString(withNullability: true)),
|
||||
equals(typeArgumentNames),
|
||||
);
|
||||
}
|
||||
|
||||
DartObjectImpl _evaluateConstant(
|
||||
String name, {
|
||||
List<ErrorCode>? errorCodes,
|
||||
|
@ -1334,6 +1526,21 @@ class ConstantVisitorTestSupport extends PubPackageResolutionTest {
|
|||
)!;
|
||||
}
|
||||
|
||||
DartObjectImpl? _evaluateConstantLocal(
|
||||
String name, {
|
||||
List<ErrorCode>? errorCodes,
|
||||
Map<String, String> declaredVariables = const {},
|
||||
Map<String, DartObjectImpl>? lexicalEnvironment,
|
||||
}) {
|
||||
var expression = findNode.variableDeclaration(name).initializer!;
|
||||
return _evaluateExpression(
|
||||
expression,
|
||||
errorCodes: errorCodes,
|
||||
declaredVariables: declaredVariables,
|
||||
lexicalEnvironment: lexicalEnvironment,
|
||||
);
|
||||
}
|
||||
|
||||
DartObjectImpl? _evaluateConstantOrNull(
|
||||
String name, {
|
||||
List<ErrorCode>? errorCodes,
|
||||
|
@ -1341,7 +1548,20 @@ class ConstantVisitorTestSupport extends PubPackageResolutionTest {
|
|||
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();
|
||||
|
@ -1351,7 +1571,7 @@ class ConstantVisitorTestSupport extends PubPackageResolutionTest {
|
|||
isNonNullableByDefault: false,
|
||||
);
|
||||
|
||||
DartObjectImpl? result = expression.accept(
|
||||
var result = expression.accept(
|
||||
ConstantVisitor(
|
||||
ConstantEvaluationEngine(
|
||||
declaredVariables: DeclaredVariables.fromMap(declaredVariables),
|
||||
|
|
Loading…
Reference in a new issue