diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart index 2fb02e119b4..eaad3c10afe 100644 --- a/pkg/analyzer/test/generated/constant_test.dart +++ b/pkg/analyzer/test/generated/constant_test.dart @@ -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", context: ''' -void foo(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)", context: ''' -const b = true; -void foo(String a, T b) {} -void bar(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", context: ''' -void foo(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)", context: ''' -const b = true; -void foo(T a) {} -void bar(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", context: ''' -void foo(T a) {} -'''); - expect(result.isValid, isFalse); - } - - test_functionReference_explicitTypeArgs_tooFew() async { - var result = await _getExpressionValue("foo", context: ''' -void foo(T a) {} -'''); - expect(result.isValid, isFalse); - } - - test_functionReference_explicitTypeArgs_tooMany() async { - var result = await _getExpressionValue("foo", context: ''' -void foo(T a) {} -'''); - expect(result.isValid, isFalse); - } - - test_functionReference_uninstantiated_identifier() async { - var result = await _getExpressionValue("foo", context: ''' -void foo(T a) {} -'''); - expect(result.isValid, isTrue); - DartObject value = result.value!; - assertType(value.type, 'void Function(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 a) {} -void bar(T a) {} -'''); - expect(result.isValid, isTrue); - DartObject value = result.value!; - assertType(value.type, 'void Function(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 a) {} await _assertValueBool(false, "2 >= 3"); } - test_identical_functionReference_explicitTypeArgs_differentElements() async { - var result = - await _getExpressionValue("identical(foo, bar)", context: ''' -void foo(T a) {} -void bar(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, foo)", - context: ''' -void foo(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, foo)", context: ''' -void foo(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, foo)", context: ''' -void foo(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("?"); diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart index 69b54977fe1..7b42573864e 100644 --- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart +++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart @@ -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.new, C.new); ); } + test_identical_functionReference_explicitTypeArgs_differentElements() async { + await resolveTestCode(''' +void foo(T a) {} +void bar(T a) {} +const g = identical(foo, bar); +'''); + expect( + _evaluateConstant('g'), + _boolValue(false), + ); + } + + test_identical_functionReference_explicitTypeArgs_differentTypeArgs() async { + await resolveTestCode(''' +void foo(T a) {} +const g = identical(foo, foo); +'''); + expect( + _evaluateConstant('g'), + _boolValue(false), + ); + } + + test_identical_functionReference_explicitTypeArgs_onlyOneHasTypeArgs() async { + await resolveTestCode(''' +void foo(T a) {} +const g = identical(foo, foo); +'''); + expect( + _evaluateConstant('g'), + _boolValue(false), + ); + } + + test_identical_functionReference_explicitTypeArgs_sameElement() async { + await resolveTestCode(''' +void foo(T a) {} +const g = identical(foo, foo); +'''); + expect( + _evaluateConstant('g'), + _boolValue(true), + ); + } + + test_identical_functionReference_uninstantiated_sameElement() async { + await resolveTestCode(''' +void foo(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 a) {} +void bar(T a) {} +const g = (b ? foo : bar); +'''); + 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(String a, T b) {} +void bar(T a, String b) {} +const g = (b ? foo : bar); +'''); + 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 a) {} +const g = f; +'''); + 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 a) {} +const g = f; +'''); + 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 a) {} +const g = foo; +'''); + 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 a, U b) {} +const g = foo; +'''); + 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 a) {} +const g = foo; +'''); + 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 a) {} + +class C { + void m() { + static const g = f; + } +} +'''); + 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 a) {} +void bar(T a) {} +const g = b ? foo : bar; +'''); + var result = _evaluateConstant('g'); + assertType(result.type, 'void Function(T)'); + assertElement(result.toFunctionValue(), findElement.topFunction('foo')); + _assertTypeArguments(result, null); + } + + test_visitFunctionReference_uninstantiated_functionName() async { + await resolveTestCode(''' +void f(T a) {} +const g = f; +'''); + var result = _evaluateConstant('g'); + assertType(result.type, 'void Function(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? 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? errorCodes, @@ -1334,6 +1526,21 @@ class ConstantVisitorTestSupport extends PubPackageResolutionTest { )!; } + DartObjectImpl? _evaluateConstantLocal( + String name, { + List? errorCodes, + Map declaredVariables = const {}, + Map? lexicalEnvironment, + }) { + var expression = findNode.variableDeclaration(name).initializer!; + return _evaluateExpression( + expression, + errorCodes: errorCodes, + declaredVariables: declaredVariables, + lexicalEnvironment: lexicalEnvironment, + ); + } + DartObjectImpl? _evaluateConstantOrNull( String name, { List? errorCodes, @@ -1341,7 +1548,20 @@ class ConstantVisitorTestSupport extends PubPackageResolutionTest { Map? lexicalEnvironment, }) { var expression = findNode.topVariableDeclarationByName(name).initializer!; + return _evaluateExpression( + expression, + errorCodes: errorCodes, + declaredVariables: declaredVariables, + lexicalEnvironment: lexicalEnvironment, + ); + } + DartObjectImpl? _evaluateExpression( + Expression expression, { + List? errorCodes, + Map declaredVariables = const {}, + Map? 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),