Skip to content

Commit 93cd0cd

Browse files
stereotype441commit-bot@chromium.org
authored andcommitted
Parser support for generic annotations.
This CL updates the parser so that it allows annotations of the form: `@` <constructorDesignation> <argumentPart> Where <argumentPart> can contain type arguments. Previously this was prohibited at parse time. Generic annotations are still prohibited in the current language version, but the error is now generated by the parser listener (BodyBuilder in the case of CFE, AstBuilder in the case of analyzer); this should open the door for future CLs to add support for generic annotations when the `generic-metadata` experimental flag is supplied. Bug: #44838 Change-Id: I90604f38bcb378fc798c5737e486fb26589d4d1e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/182668 Reviewed-by: Konstantin Shcheglov <[email protected]> Reviewed-by: Jens Johansen <[email protected]>
1 parent 3bf29dc commit 93cd0cd

File tree

9 files changed

+54
-9
lines changed

9 files changed

+54
-9
lines changed

pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6430,6 +6430,17 @@ const MessageCode messageMetadataTypeArguments = const MessageCode(
64306430
index: 91,
64316431
message: r"""An annotation (metadata) can't use type arguments.""");
64326432

6433+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
6434+
const Code<Null> codeMetadataTypeArgumentsUninstantiated =
6435+
messageMetadataTypeArgumentsUninstantiated;
6436+
6437+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
6438+
const MessageCode messageMetadataTypeArgumentsUninstantiated = const MessageCode(
6439+
"MetadataTypeArgumentsUninstantiated",
6440+
index: 114,
6441+
message:
6442+
r"""An annotation (metadata) with type arguments must be followed by an argument list.""");
6443+
64336444
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
64346445
const Template<Message Function(String name)> templateMethodNotFound =
64356446
const Template<Message Function(String name)>(

pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,16 +1055,18 @@ class Parser {
10551055
token = ensureIdentifier(atToken, IdentifierContext.metadataReference);
10561056
token =
10571057
parseQualifiedRestOpt(token, IdentifierContext.metadataContinuation);
1058-
if (optional("<", token.next!)) {
1059-
reportRecoverableError(token.next!, codes.messageMetadataTypeArguments);
1060-
}
1058+
bool hasTypeArguments = optional("<", token.next!);
10611059
token = computeTypeParamOrArg(token).parseArguments(token, this);
10621060
Token? period = null;
10631061
if (optional('.', token.next!)) {
10641062
period = token.next!;
10651063
token = ensureIdentifier(
10661064
period, IdentifierContext.metadataContinuationAfterTypeArguments);
10671065
}
1066+
if (hasTypeArguments && !optional("(", token.next!)) {
1067+
reportRecoverableError(
1068+
token, codes.messageMetadataTypeArgumentsUninstantiated);
1069+
}
10681070
token = parseArgumentsOpt(token);
10691071
listener.endMetadata(atToken, period, token.next!);
10701072
return token;

pkg/analyzer/lib/error/error.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,7 @@ const List<ErrorCode> errorCodeValues = [
624624
ParserErrorCode.ABSTRACT_TYPEDEF,
625625
ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT,
626626
ParserErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS,
627+
ParserErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS_UNINSTANTIATED,
627628
ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER,
628629
ParserErrorCode.BINARY_OPERATOR_WRITTEN_OUT,
629630
ParserErrorCode.BREAK_OUTSIDE_OF_LOOP,

pkg/analyzer/lib/src/dart/error/syntactic_errors.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ class ParserErrorCode extends ErrorCode {
6161
static const ParserErrorCode ANNOTATION_WITH_TYPE_ARGUMENTS =
6262
_ANNOTATION_WITH_TYPE_ARGUMENTS;
6363

64+
static const ParserErrorCode ANNOTATION_WITH_TYPE_ARGUMENTS_UNINSTANTIATED =
65+
_ANNOTATION_WITH_TYPE_ARGUMENTS_UNINSTANTIATED;
66+
6467
/**
6568
* 16.32 Identifier Reference: It is a compile-time error if any of the
6669
* identifiers async, await, or yield is used as an identifier in a function

pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ final fastaAnalyzerErrorCodes = <ErrorCode?>[
121121
_ANNOTATION_ON_TYPE_ARGUMENT,
122122
_BINARY_OPERATOR_WRITTEN_OUT,
123123
_EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD,
124+
_ANNOTATION_WITH_TYPE_ARGUMENTS_UNINSTANTIATED,
124125
];
125126

126127
const ParserErrorCode _ABSTRACT_CLASS_MEMBER = ParserErrorCode(
@@ -150,6 +151,10 @@ const ParserErrorCode _ANNOTATION_WITH_TYPE_ARGUMENTS = ParserErrorCode(
150151
'ANNOTATION_WITH_TYPE_ARGUMENTS',
151152
r"An annotation (metadata) can't use type arguments.");
152153

154+
const ParserErrorCode _ANNOTATION_WITH_TYPE_ARGUMENTS_UNINSTANTIATED =
155+
ParserErrorCode('ANNOTATION_WITH_TYPE_ARGUMENTS_UNINSTANTIATED',
156+
r"An annotation (metadata) with type arguments must be followed by an argument list.");
157+
153158
const ParserErrorCode _BINARY_OPERATOR_WRITTEN_OUT = ParserErrorCode(
154159
'BINARY_OPERATOR_WRITTEN_OUT',
155160
r"Binary operator '#string' is written as '#string2' instead of the written out word.",

pkg/analyzer/lib/src/fasta/ast_builder.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import 'package:_fe_analyzer_shared/src/messages/codes.dart'
2222
messageInvalidInitializer,
2323
messageInvalidSuperInInitializer,
2424
messageInvalidThisInInitializer,
25+
messageMetadataTypeArguments,
2526
messageMissingAssignableSelector,
2627
messageNativeClauseShouldBeAnnotation,
2728
messageOperatorWithTypeParameters,
@@ -1831,7 +1832,12 @@ class AstBuilder extends StackListener {
18311832
var invocation = pop() as MethodInvocation?;
18321833
var constructorName =
18331834
periodBeforeName != null ? pop() as SimpleIdentifier : null;
1834-
pop(); // Type arguments, not allowed.
1835+
var typeArguments = pop() as TypeArgumentList?;
1836+
if (typeArguments != null &&
1837+
!_featureSet.isEnabled(Feature.generic_metadata)) {
1838+
handleRecoverableError(messageMetadataTypeArguments,
1839+
typeArguments.beginToken, typeArguments.beginToken);
1840+
}
18351841
var name = pop() as Identifier;
18361842
push(ast.annotation(
18371843
atSign: atSign,

pkg/front_end/lib/src/fasta/kernel/body_builder.dart

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,8 @@ class BodyBuilder extends ScopeListener<JumpTarget>
630630
if (arguments != null) {
631631
push(arguments);
632632
_buildConstructorReferenceInvocation(
633-
beginToken.next, beginToken.offset, Constness.explicitConst);
633+
beginToken.next, beginToken.offset, Constness.explicitConst,
634+
inMetadata: true);
634635
push(popForValue());
635636
} else {
636637
pop(); // Name last identifier
@@ -4360,11 +4361,13 @@ class BodyBuilder extends ScopeListener<JumpTarget>
43604361
void endNewExpression(Token token) {
43614362
debugEvent("NewExpression");
43624363
_buildConstructorReferenceInvocation(
4363-
token.next, token.offset, Constness.explicitNew);
4364+
token.next, token.offset, Constness.explicitNew,
4365+
inMetadata: false);
43644366
}
43654367

43664368
void _buildConstructorReferenceInvocation(
4367-
Token nameToken, int offset, Constness constness) {
4369+
Token nameToken, int offset, Constness constness,
4370+
{bool inMetadata}) {
43684371
assert(checkState(nameToken, [
43694372
/*arguments*/ ValueKinds.Arguments,
43704373
/*constructor name identifier*/ ValueKinds.IdentifierOrNull,
@@ -4381,6 +4384,10 @@ class BodyBuilder extends ScopeListener<JumpTarget>
43814384
Token nameLastToken = nameLastIdentifier?.token ?? nameToken;
43824385
String name = pop();
43834386
List<UnresolvedType> typeArguments = pop();
4387+
if (inMetadata && typeArguments != null) {
4388+
handleRecoverableError(fasta.messageMetadataTypeArguments,
4389+
nameLastToken.next, nameLastToken.next);
4390+
}
43844391

43854392
Object type = pop();
43864393

@@ -4406,7 +4413,8 @@ class BodyBuilder extends ScopeListener<JumpTarget>
44064413
void endImplicitCreationExpression(Token token) {
44074414
debugEvent("ImplicitCreationExpression");
44084415
_buildConstructorReferenceInvocation(
4409-
token.next, token.offset, Constness.implicit);
4416+
token.next, token.offset, Constness.implicit,
4417+
inMetadata: false);
44104418
}
44114419

44124420
@override
@@ -4660,7 +4668,8 @@ class BodyBuilder extends ScopeListener<JumpTarget>
46604668
void endConstExpression(Token token) {
46614669
debugEvent("endConstExpression");
46624670
_buildConstructorReferenceInvocation(
4663-
token.next, token.offset, Constness.explicitConst);
4671+
token.next, token.offset, Constness.explicitConst,
4672+
inMetadata: false);
46644673
}
46654674

46664675
@override

pkg/front_end/messages.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,6 +1501,13 @@ MetadataTypeArguments:
15011501
template: "An annotation (metadata) can't use type arguments."
15021502
analyzerCode: ParserErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS
15031503

1504+
MetadataTypeArgumentsUninstantiated:
1505+
index: 114
1506+
template: "An annotation (metadata) with type arguments must be followed by an argument list."
1507+
analyzerCode: ParserErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS_UNINSTANTIATED
1508+
script:
1509+
- "@deprecated<int> class C {}"
1510+
15041511
ConstructorNotFound:
15051512
template: "Couldn't find constructor '#name'."
15061513
analyzerCode: CONSTRUCTOR_NOT_FOUND

pkg/front_end/test/spell_checking_list_code.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,6 +1268,7 @@ unification
12681268
unifier
12691269
unify
12701270
uninstantiable
1271+
uninstantiated
12711272
unions
12721273
uniqueness
12731274
unittest

0 commit comments

Comments
 (0)