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:
Sam Rawlins 2021-09-24 05:39:59 +00:00 committed by commit-bot@chromium.org
parent e559b80f52
commit 5e0f4c24c5
2 changed files with 222 additions and 141 deletions

View file

@ -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("?");

View file

@ -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),