Augment. Report INVOCATION_OF_NON_FUNCTION_EXPRESSION for AugmentedInvocation.

Change-Id: I927eeff270e8eb34e0d325707bdeae79178c3142
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/365500
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Konstantin Shcheglov 2024-05-06 18:51:06 +00:00
parent f2d8cd15c9
commit 6dac032753
3 changed files with 224 additions and 0 deletions

View file

@ -1905,6 +1905,39 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
var enclosingAugmentation = _enclosingAugmentation;
var augmentationTarget = enclosingAugmentation?.augmentationTarget;
// Rewrite invocation of a function-typed getter.
if (augmentationTarget is PropertyAccessorElementImpl) {
if (augmentationTarget.returnType case FunctionType functionType) {
var augmentedExpression = AugmentedExpressionImpl(
augmentedKeyword: node.augmentedKeyword,
);
augmentedExpression.element = augmentationTarget;
augmentedExpression.staticType = functionType;
var rewrite = FunctionExpressionInvocationImpl(
function: augmentedExpression,
typeArguments: node.typeArguments,
argumentList: node.arguments,
);
replaceExpression(node, rewrite);
flowAnalysis.transferTestData(node, rewrite);
_resolveRewrittenFunctionExpressionInvocation(
rewrite, whyNotPromotedList,
contextType: contextType);
} else {
node.element = augmentationTarget;
node.staticType = InvalidTypeImpl.instance;
errorReporter.atToken(
node.augmentedKeyword,
CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION,
);
for (var argument in node.arguments.arguments) {
argument.resolveExpression(this, InvalidTypeImpl.instance);
}
}
return;
}
FunctionType? rawType;
if (augmentationTarget is ExecutableElementImpl) {
node.element = augmentationTarget;

View file

@ -64,6 +64,8 @@ class FindNode {
ExportDirective get singleExportDirective => _single();
ExpressionStatement get singleExpressionStatement => _single();
ExtendsClause get singleExtendsClause => _single();
ExtensionDeclaration get singleExtensionDeclaration => _single();

View file

@ -87,6 +87,49 @@ AugmentedInvocation
''');
}
test_class_getter_functionTyped() async {
newFile('$testPackageLibPath/a.dart', r'''
import augment 'test.dart';
class A {
int Function(int a) get foo => throw 0;
}
''');
await assertNoErrorsInCode('''
augment library 'a.dart';
augment class A {
augment int Function(int a) get foo {
augmented(42);
throw 0;
}
}
''');
var node = findNode.expressionStatement('augmented(');
assertResolvedNodeText(node, r'''
ExpressionStatement
expression: FunctionExpressionInvocation
function: AugmentedExpression
augmentedKeyword: augmented
element: self::@class::A::@getter::foo
staticType: int Function(int)
argumentList: ArgumentList
leftParenthesis: (
arguments
IntegerLiteral
literal: 42
parameter: root::@parameter::a
staticType: int
rightParenthesis: )
staticElement: <null>
staticInvokeType: int Function(int)
staticType: int
semicolon: ;
''');
}
test_class_method() async {
newFile('$testPackageLibPath/a.dart', r'''
import augment 'test.dart';
@ -448,6 +491,152 @@ AugmentedInvocation
rightParenthesis: )
element: self::@function::foo
staticType: dynamic
''');
}
test_topLevel_getter_functionTyped() async {
newFile('$testPackageLibPath/a.dart', r'''
import augment 'test.dart';
int Function(int a) get foo => throw 0;
''');
await assertNoErrorsInCode('''
augment library 'a.dart';
augment int Function(int a) get foo {
augmented(42);
throw 0;
}
''');
var node = findNode.expressionStatement('augmented(');
assertResolvedNodeText(node, r'''
ExpressionStatement
expression: FunctionExpressionInvocation
function: AugmentedExpression
augmentedKeyword: augmented
element: self::@getter::foo
staticType: int Function(int)
argumentList: ArgumentList
leftParenthesis: (
arguments
IntegerLiteral
literal: 42
parameter: root::@parameter::a
staticType: int
rightParenthesis: )
staticElement: <null>
staticInvokeType: int Function(int)
staticType: int
semicolon: ;
''');
}
test_topLevel_getter_notFunctionTyped() async {
newFile('$testPackageLibPath/a.dart', r'''
import augment 'test.dart';
int get foo => 0;
''');
await assertErrorsInCode('''
augment library 'a.dart';
augment int get foo {
augmented();
return 0;
}
''', [
error(CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION, 51, 9),
]);
var node = findNode.expressionStatement('augmented(');
assertResolvedNodeText(node, r'''
ExpressionStatement
expression: AugmentedInvocation
augmentedKeyword: augmented
arguments: ArgumentList
leftParenthesis: (
rightParenthesis: )
element: self::@getter::foo
staticType: InvalidType
semicolon: ;
''');
}
test_topLevel_getter_notFunctionTyped_variableClosure() async {
newFile('$testPackageLibPath/a.dart', r'''
import augment 'test.dart';
int get foo => 0;
''');
await assertErrorsInCode('''
augment library 'a.dart';
augment int get foo {
var v = () {
augmented();
};
return 0;
}
''', [
error(WarningCode.UNUSED_LOCAL_VARIABLE, 55, 1),
error(CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION, 68, 9),
]);
var node = findNode.expressionStatement('augmented(');
assertResolvedNodeText(node, r'''
ExpressionStatement
expression: AugmentedInvocation
augmentedKeyword: augmented
arguments: ArgumentList
leftParenthesis: (
rightParenthesis: )
element: self::@getter::foo
staticType: InvalidType
semicolon: ;
''');
}
test_topLevel_setter() async {
newFile('$testPackageLibPath/a.dart', r'''
import augment 'test.dart';
set foo(int _) {}
''');
await assertErrorsInCode('''
augment library 'a.dart';
augment set foo(int _) {
augmented(0, 1);
}
''', [
error(CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION, 54, 9),
]);
var node = findNode.expressionStatement('augmented(');
assertResolvedNodeText(node, r'''
ExpressionStatement
expression: AugmentedInvocation
augmentedKeyword: augmented
arguments: ArgumentList
leftParenthesis: (
arguments
IntegerLiteral
literal: 0
parameter: <null>
staticType: int
IntegerLiteral
literal: 1
parameter: <null>
staticType: int
rightParenthesis: )
element: self::@setter::foo
staticType: InvalidType
semicolon: ;
''');
}
}