Skip to content

Commit 4bb644c

Browse files
scheglovCommit Queue
authored andcommitted
Augment. Parse enum constant augmentations, allow just ';' before methods.
I was unable to update the parser to avoid requirement for ';' at all. Ideally we should be able to parse: ``` enum E { void foo() } ``` Change-Id: I7edba99454b965407c3fb402642933b3d8d6bb7c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/363106 Reviewed-by: Johnni Winther <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent 55f2754 commit 4bb644c

File tree

48 files changed

+279
-116
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+279
-116
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -769,8 +769,8 @@ class ForwardingListener implements Listener {
769769
}
770770

771771
@override
772-
void handleEnumElement(Token beginToken) {
773-
listener?.handleEnumElement(beginToken);
772+
void handleEnumElement(Token beginToken, Token? augmentToken) {
773+
listener?.handleEnumElement(beginToken, augmentToken);
774774
}
775775

776776
@override

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ class Listener implements UnescapeErrorListener {
403403
/// Handle the enum element. Substructures:
404404
/// - Metadata
405405
/// - Enum value (identifier)
406-
void handleEnumElement(Token beginToken) {
406+
void handleEnumElement(Token beginToken, Token? augmentToken) {
407407
logEvent("EnumElement");
408408
}
409409

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

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -338,9 +338,15 @@ class Parser {
338338
/// [parsePrimaryPattern] and [parsePattern].
339339
bool isLastPatternAllowedInsideUnaryPattern = false;
340340

341-
Parser(this.listener,
342-
{this.useImplicitCreationExpression = true, this.allowPatterns = false})
343-
: assert(listener != null); // ignore:unnecessary_null_comparison
341+
/// Indicates whether the macros feature is enabled.
342+
final bool enableFeatureMacros;
343+
344+
Parser(
345+
this.listener, {
346+
this.useImplicitCreationExpression = true,
347+
this.allowPatterns = false,
348+
this.enableFeatureMacros = false,
349+
}) : assert(listener != null); // ignore:unnecessary_null_comparison
344350

345351
/// Executes [callback]; however if `this` is the `TestParser` (from
346352
/// `pkg/front_end/test/parser_test_parser.dart`) then no output is printed
@@ -2368,7 +2374,7 @@ class Parser {
23682374
Token next = token.next!;
23692375
if (optional('}', next) || optional(';', next)) {
23702376
token = next;
2371-
if (elementCount == 0) {
2377+
if (elementCount == 0 && !enableFeatureMacros) {
23722378
reportRecoverableError(token, codes.messageEnumDeclarationEmpty);
23732379
}
23742380
break;
@@ -2566,6 +2572,13 @@ class Parser {
25662572
Token parseEnumElement(Token token) {
25672573
Token beginToken = token;
25682574
token = parseMetadataStar(token);
2575+
2576+
Token? augmentToken;
2577+
if (optional('augment', token.next!)) {
2578+
augmentToken = token.next!;
2579+
token = token.next!;
2580+
}
2581+
25692582
token = ensureIdentifier(token, IdentifierContext.enumValueDeclaration);
25702583
bool hasTypeArgumentsOrDot = false;
25712584
{
@@ -2600,7 +2613,7 @@ class Parser {
26002613
} else {
26012614
listener.handleNoArguments(token);
26022615
}
2603-
listener.handleEnumElement(beginToken);
2616+
listener.handleEnumElement(beginToken, augmentToken);
26042617
return token;
26052618
}
26062619

pkg/analysis_server/test/src/services/correction/fix/add_enum_constant_test.dart

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'package:analysis_server/src/services/correction/fix.dart';
6-
import 'package:analyzer/src/error/codes.dart';
76
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
87
import 'package:test_reflective_loader/test_reflective_loader.dart';
98

@@ -174,10 +173,7 @@ enum E {ONE}
174173
void f() {
175174
E.ONE;
176175
}
177-
''',
178-
errorFilter: (e) =>
179-
e.errorCode == CompileTimeErrorCode.UNDEFINED_ENUM_CONSTANT,
180-
matchFixMessage: "Add enum constant 'ONE'");
176+
''');
181177
}
182178

183179
Future<void> test_unnamed() async {

pkg/analyzer/lib/src/dart/ast/ast.dart

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5509,6 +5509,10 @@ abstract final class EnumConstantDeclaration implements Declaration {
55095509
/// doesn't provide any explicit arguments.
55105510
EnumConstantArguments? get arguments;
55115511

5512+
/// The `augment` keyword, or `null` if the keyword was absent.
5513+
@experimental
5514+
Token? get augmentKeyword;
5515+
55125516
/// The constructor that is invoked by this enum constant, or `null` if the
55135517
/// AST structure hasn't been resolved, or if the constructor couldn't be
55145518
/// resolved.
@@ -5523,6 +5527,9 @@ abstract final class EnumConstantDeclaration implements Declaration {
55235527

55245528
final class EnumConstantDeclarationImpl extends DeclarationImpl
55255529
implements EnumConstantDeclaration {
5530+
@override
5531+
final Token? augmentKeyword;
5532+
55265533
@override
55275534
final Token name;
55285535

@@ -5542,6 +5549,7 @@ final class EnumConstantDeclarationImpl extends DeclarationImpl
55425549
EnumConstantDeclarationImpl({
55435550
required super.comment,
55445551
required super.metadata,
5552+
required this.augmentKeyword,
55455553
required this.name,
55465554
required this.arguments,
55475555
}) {
@@ -5552,10 +5560,11 @@ final class EnumConstantDeclarationImpl extends DeclarationImpl
55525560
Token get endToken => arguments?.endToken ?? name;
55535561

55545562
@override
5555-
Token get firstTokenAfterCommentAndMetadata => name;
5563+
Token get firstTokenAfterCommentAndMetadata => augmentKeyword ?? name;
55565564

55575565
@override
55585566
ChildEntities get _childEntities => super._childEntities
5567+
..addToken('augmentKeyword', augmentKeyword)
55595568
..addToken('name', name)
55605569
..addNode('arguments', arguments);
55615570

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4062,7 +4062,7 @@ class AstBuilder extends StackListener {
40624062
}
40634063

40644064
@override
4065-
void handleEnumElement(Token beginToken) {
4065+
void handleEnumElement(Token beginToken, Token? augmentToken) {
40664066
debugEvent("EnumElement");
40674067
var tmpArguments = pop() as MethodInvocationImpl?;
40684068
var tmpConstructor = pop() as ConstructorNameImpl?;
@@ -4103,6 +4103,7 @@ class AstBuilder extends StackListener {
41034103
constant = EnumConstantDeclarationImpl(
41044104
comment: constant.documentationComment,
41054105
metadata: constant.metadata,
4106+
augmentKeyword: augmentToken,
41064107
name: constant.name,
41074108
arguments: EnumConstantArgumentsImpl(
41084109
typeArguments: typeArguments,
@@ -4449,6 +4450,7 @@ class AstBuilder extends StackListener {
44494450
EnumConstantDeclarationImpl(
44504451
comment: comment,
44514452
metadata: metadata,
4453+
augmentKeyword: null,
44524454
name: token,
44534455
arguments: null,
44544456
),

pkg/analyzer/lib/src/generated/parser.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,11 @@ class Parser {
3838
featureSet,
3939
lineInfo,
4040
) {
41-
fastaParser = fasta.Parser(astBuilder,
42-
allowPatterns: featureSet.isEnabled(Feature.patterns));
41+
fastaParser = fasta.Parser(
42+
astBuilder,
43+
allowPatterns: featureSet.isEnabled(Feature.patterns),
44+
enableFeatureMacros: featureSet.isEnabled(Feature.macros),
45+
);
4346
astBuilder.parser = fastaParser;
4447
astBuilder.allowNativeClause = allowNativeClause;
4548
}

pkg/analyzer/test/generated/parser_fasta_listener.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,9 +1399,9 @@ class ForwardingTestListener extends ForwardingListener {
13991399
}
14001400

14011401
@override
1402-
void handleEnumElement(Token beginToken) {
1402+
void handleEnumElement(Token beginToken, Token? augmentToken) {
14031403
expectIn('Enum');
1404-
super.handleEnumElement(beginToken);
1404+
super.handleEnumElement(beginToken, augmentToken);
14051405
}
14061406

14071407
@override

pkg/analyzer/test/generated/parser_test_base.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,8 +395,11 @@ class FastaParserTestCase
395395
ErrorReporter errorReporter = ErrorReporter(listener, source);
396396
AstBuilder astBuilder = AstBuilder(errorReporter, source.uri, true,
397397
featureSet!, LineInfo.fromContent(content));
398-
fasta.Parser parser = fasta.Parser(astBuilder,
399-
allowPatterns: featureSet!.isEnabled(Feature.patterns));
398+
fasta.Parser parser = fasta.Parser(
399+
astBuilder,
400+
allowPatterns: featureSet!.isEnabled(Feature.patterns),
401+
enableFeatureMacros: featureSet!.isEnabled(Feature.macros),
402+
);
400403
astBuilder.parser = parser;
401404
astBuilder.allowNativeClause = allowNativeClause;
402405
parser.parseUnit(_fastaTokens);

pkg/analyzer/test/src/dart/parser/enum_test.dart

Lines changed: 136 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,37 @@ main() {
1414

1515
@reflectiveTest
1616
class EnumDeclarationParserTest extends ParserDiagnosticsTest {
17-
test_augment() {
17+
test_augment_constant_add() {
1818
var parseResult = parseStringWithErrors(r'''
1919
augment library 'a.dart';
2020
21-
augment enum E {bar}
21+
augment enum E {
22+
v
23+
}
24+
''');
25+
parseResult.assertNoErrors();
26+
27+
var node = parseResult.findNode.singleEnumDeclaration;
28+
assertParsedNodeText(node, r'''
29+
EnumDeclaration
30+
augmentKeyword: augment
31+
enumKeyword: enum
32+
name: E
33+
leftBracket: {
34+
constants
35+
EnumConstantDeclaration
36+
name: v
37+
rightBracket: }
38+
''');
39+
}
40+
41+
test_augment_constant_augment_withConstructor() {
42+
var parseResult = parseStringWithErrors(r'''
43+
augment library 'a.dart';
44+
45+
augment enum E {
46+
augment v.foo()
47+
}
2248
''');
2349
parseResult.assertNoErrors();
2450

@@ -31,7 +57,114 @@ EnumDeclaration
3157
leftBracket: {
3258
constants
3359
EnumConstantDeclaration
34-
name: bar
60+
augmentKeyword: augment
61+
name: v
62+
arguments: EnumConstantArguments
63+
constructorSelector: ConstructorSelector
64+
period: .
65+
name: SimpleIdentifier
66+
token: foo
67+
argumentList: ArgumentList
68+
leftParenthesis: (
69+
rightParenthesis: )
70+
rightBracket: }
71+
''');
72+
}
73+
74+
test_augment_noConstants_semicolon_method() {
75+
var parseResult = parseStringWithErrors(r'''
76+
augment library 'a.dart';
77+
78+
augment enum E {;
79+
void foo() {}
80+
}
81+
''');
82+
parseResult.assertNoErrors();
83+
84+
var node = parseResult.findNode.singleEnumDeclaration;
85+
assertParsedNodeText(node, r'''
86+
EnumDeclaration
87+
augmentKeyword: augment
88+
enumKeyword: enum
89+
name: E
90+
leftBracket: {
91+
semicolon: ;
92+
members
93+
MethodDeclaration
94+
returnType: NamedType
95+
name: void
96+
name: foo
97+
parameters: FormalParameterList
98+
leftParenthesis: (
99+
rightParenthesis: )
100+
body: BlockFunctionBody
101+
block: Block
102+
leftBracket: {
103+
rightBracket: }
104+
rightBracket: }
105+
''');
106+
}
107+
108+
test_declaration_empty() {
109+
var parseResult = parseStringWithErrors(r'''
110+
enum E {}
111+
''');
112+
parseResult.assertNoErrors();
113+
114+
var node = parseResult.findNode.singleEnumDeclaration;
115+
assertParsedNodeText(node, r'''
116+
EnumDeclaration
117+
enumKeyword: enum
118+
name: E
119+
leftBracket: {
120+
rightBracket: }
121+
''');
122+
}
123+
124+
test_declaration_noConstants_semicolon() {
125+
var parseResult = parseStringWithErrors(r'''
126+
enum E {;}
127+
''');
128+
parseResult.assertNoErrors();
129+
130+
var node = parseResult.findNode.singleEnumDeclaration;
131+
assertParsedNodeText(node, r'''
132+
EnumDeclaration
133+
enumKeyword: enum
134+
name: E
135+
leftBracket: {
136+
semicolon: ;
137+
rightBracket: }
138+
''');
139+
}
140+
141+
test_declaration_noConstants_semicolon_method() {
142+
var parseResult = parseStringWithErrors(r'''
143+
enum E {;
144+
void foo() {}
145+
}
146+
''');
147+
parseResult.assertNoErrors();
148+
149+
var node = parseResult.findNode.singleEnumDeclaration;
150+
assertParsedNodeText(node, r'''
151+
EnumDeclaration
152+
enumKeyword: enum
153+
name: E
154+
leftBracket: {
155+
semicolon: ;
156+
members
157+
MethodDeclaration
158+
returnType: NamedType
159+
name: void
160+
name: foo
161+
parameters: FormalParameterList
162+
leftParenthesis: (
163+
rightParenthesis: )
164+
body: BlockFunctionBody
165+
block: Block
166+
leftBracket: {
167+
rightBracket: }
35168
rightBracket: }
36169
''');
37170
}

0 commit comments

Comments
 (0)