Skip to content

Commit b20804e

Browse files
committed
libSyntax: support declaration modifiers, like static, private, etc.
Some declaration modifiers may have more details attached, like "private(set)". This patch represents the detail part "(set)" as a token list. Also, this patch fixes an issue where back tracking scope doesn't recover leading/trailing trivia information.
1 parent 6834894 commit b20804e

File tree

6 files changed

+43
-29
lines changed

6 files changed

+43
-29
lines changed

include/swift/Parse/Parser.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,11 +425,17 @@ class Parser {
425425
llvm::Optional<syntax::SyntaxParsingContext> SynContext;
426426
bool Backtrack = true;
427427

428+
// Keep track of the original trivia information.
429+
syntax::Trivia LeadingTrivia;
430+
syntax::Trivia TrailingTrivia;
431+
428432
public:
429433
BacktrackingScope(Parser &P)
430-
: P(P), PP(P.getParserPosition()), DT(P.Diags) {
434+
: P(P), PP(P.getParserPosition()), DT(P.Diags),
435+
LeadingTrivia(P.LeadingTrivia), TrailingTrivia(P.TrailingTrivia) {
431436
SynContext.emplace(P.SyntaxContext);
432437
SynContext->setDiscard();
438+
433439
}
434440

435441
~BacktrackingScope();

lib/Parse/ParseDecl.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2282,16 +2282,27 @@ Parser::parseDecl(ParseDeclOptions Flags,
22822282
StaticLoc = Tok.getLoc();
22832283
StaticSpelling = StaticSpellingKind::KeywordStatic;
22842284
}
2285+
SyntaxParsingContext ModContext(SyntaxContext, SyntaxKind::DeclModifier);
22852286
consumeToken(tok::kw_static);
2287+
// Static modifier doesn't have more details.
2288+
SyntaxParsingContext DetailContext(SyntaxContext, SyntaxKind::TokenList);
22862289
continue;
22872290
}
22882291
// 'class' is a modifier on func, but is also a top-level decl.
22892292
case tok::kw_class: {
2290-
SourceLoc ClassLoc = consumeToken(tok::kw_class);
2291-
2293+
SourceLoc ClassLoc;
2294+
bool AsModifier;
2295+
{
2296+
BacktrackingScope Scope(*this);
2297+
ClassLoc = consumeToken(tok::kw_class);
2298+
AsModifier = isStartOfDecl();
2299+
}
22922300
// If 'class' is a modifier on another decl kind, like var or func,
22932301
// then treat it as a modifier.
2294-
if (isStartOfDecl()) {
2302+
if (AsModifier) {
2303+
SyntaxParsingContext ModContext(SyntaxContext, SyntaxKind::DeclModifier);
2304+
consumeToken(tok::kw_class);
2305+
SyntaxParsingContext DetailContext(SyntaxContext, SyntaxKind::TokenList);
22952306
if (StaticLoc.isValid()) {
22962307
diagnose(Tok, diag::decl_already_static,
22972308
StaticSpellingKind::KeywordClass)
@@ -2303,6 +2314,7 @@ Parser::parseDecl(ParseDeclOptions Flags,
23032314
continue;
23042315
}
23052316

2317+
consumeToken(tok::kw_class);
23062318
// Otherwise this is the start of a class declaration.
23072319
DeclResult = parseDeclClass(ClassLoc, Flags, Attributes);
23082320
break;
@@ -2312,6 +2324,7 @@ Parser::parseDecl(ParseDeclOptions Flags,
23122324
case tok::kw_fileprivate:
23132325
case tok::kw_internal:
23142326
case tok::kw_public: {
2327+
SyntaxParsingContext ModContext(SyntaxContext, SyntaxKind::DeclModifier);
23152328
// We still model these specifiers as attributes.
23162329
parseNewDeclAttribute(Attributes, /*AtLoc=*/{}, DAK_AccessControl);
23172330
continue;
@@ -2356,6 +2369,7 @@ Parser::parseDecl(ParseDeclOptions Flags,
23562369
Kind = DAK_Convenience;
23572370
}
23582371
if (Kind) {
2372+
SyntaxParsingContext ModContext(SyntaxContext, SyntaxKind::DeclModifier);
23592373
parseNewDeclAttribute(Attributes, SourceLoc(), *Kind);
23602374
continue;
23612375
}

lib/Parse/Parser.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ swift::Parser::BacktrackingScope::~BacktrackingScope() {
134134
if (Backtrack) {
135135
P.backtrackToPosition(PP);
136136
DT.abort();
137+
P.LeadingTrivia = LeadingTrivia;
138+
P.TrailingTrivia = TrailingTrivia;
137139
}
138140
}
139141

test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,10 @@ struct foo <MemberDeclBlock>{
7777

7878
struct foo <MemberDeclBlock>{<Attribute>
7979
@available(*, unavailable)</Attribute>
80-
struct foo <MemberDeclBlock>{}</MemberDeclBlock>
81-
public class foo {<Attribute>
80+
struct foo <MemberDeclBlock>{}</MemberDeclBlock><DeclModifier>
81+
public </DeclModifier>class foo {<Attribute>
8282
@available(*, unavailable)</Attribute><Attribute>
83-
@objc(fooObjc)</Attribute>
84-
private static func foo() <CodeBlock>{}</CodeBlock>
83+
@objc(fooObjc)</Attribute><DeclModifier>
84+
private </DeclModifier><DeclModifier>static </DeclModifier>func foo() <CodeBlock>{}</CodeBlock>
8585
}
8686
}</MemberDeclBlock>

unittests/Syntax/DeclSyntaxTests.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ DeclModifierSyntax getCannedDeclModifier() {
1717
auto LParen = SyntaxFactory::makeLeftParenToken({}, {});
1818
auto Set = SyntaxFactory::makeIdentifier("set", {}, {});
1919
auto RParen = SyntaxFactory::makeRightParenToken({}, {});
20-
return SyntaxFactory::makeDeclModifier(Private, LParen, Set, RParen);
20+
return SyntaxFactory::makeDeclModifier(Private,
21+
SyntaxFactory::makeTokenList({ LParen, Set, RParen}));
2122
}
2223

2324
TEST(DeclSyntaxTests, DeclModifierMakeAPIs) {
@@ -40,12 +41,13 @@ TEST(DeclSyntaxTests, DeclModifierGetAPIs) {
4041
auto LParen = SyntaxFactory::makeLeftParenToken({}, {});
4142
auto Set = SyntaxFactory::makeIdentifier("set", {}, {});
4243
auto RParen = SyntaxFactory::makeRightParenToken({}, {});
43-
auto Mod = SyntaxFactory::makeDeclModifier(Private, LParen, Set, RParen);
44+
auto Mod = SyntaxFactory::makeDeclModifier(Private,
45+
SyntaxFactory::makeTokenList({LParen, Set, RParen}));
4446

4547
ASSERT_EQ(Private.getRaw(), Mod.getName().getRaw());
46-
ASSERT_EQ(LParen.getRaw(), Mod.getLeftParen()->getRaw());
47-
ASSERT_EQ(Set.getRaw(), Mod.getArgument()->getRaw());
48-
ASSERT_EQ(RParen.getRaw(), Mod.getRightParen()->getRaw());
48+
ASSERT_EQ(LParen.getRaw(), Mod.getDetail()[0].getRaw());
49+
ASSERT_EQ(Set.getRaw(), Mod.getDetail()[1].getRaw());
50+
ASSERT_EQ(RParen.getRaw(), Mod.getDetail()[2].getRaw());
4951
}
5052

5153
TEST(DeclSyntaxTests, DeclModifierWithAPIs) {
@@ -58,9 +60,7 @@ TEST(DeclSyntaxTests, DeclModifierWithAPIs) {
5860
llvm::raw_svector_ostream OS(Scratch);
5961
SyntaxFactory::makeBlankDeclModifier()
6062
.withName(Private)
61-
.withLeftParen(LParen)
62-
.withArgument(Set)
63-
.withRightParen(RParen)
63+
.withDetail(SyntaxFactory::makeTokenList({LParen, Set, RParen}))
6464
.print(OS);
6565
ASSERT_EQ(OS.str().str(), "private(set)");
6666
}
@@ -480,12 +480,12 @@ ModifierListSyntax getCannedModifiers() {
480480
auto NoLParen = TokenSyntax::missingToken(tok::l_paren, "(");
481481
auto NoArgument = TokenSyntax::missingToken(tok::identifier, "");
482482
auto NoRParen = TokenSyntax::missingToken(tok::r_paren, ")");
483-
auto Public = SyntaxFactory::makeDeclModifier(PublicID, NoLParen, NoArgument,
484-
NoRParen);
483+
auto Public = SyntaxFactory::makeDeclModifier(PublicID,
484+
SyntaxFactory::makeTokenList({NoLParen, NoArgument, NoRParen}));
485485

486486
auto StaticKW = SyntaxFactory::makeStaticKeyword({}, Trivia::spaces(1));
487-
auto Static = SyntaxFactory::makeDeclModifier(StaticKW, NoLParen, NoArgument,
488-
NoRParen);
487+
auto Static = SyntaxFactory::makeDeclModifier(StaticKW,
488+
SyntaxFactory::makeTokenList({NoLParen, NoArgument, NoRParen}));
489489

490490
return SyntaxFactory::makeBlankModifierList()
491491
.appending(Public)

utils/gyb_syntax_support/DeclNodes.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,7 @@
7878
'fileprivate', 'internal', 'public', 'open',
7979
'mutating', 'nonmutating',
8080
]),
81-
Child('LeftParen', kind='LeftParenToken',
82-
is_optional=True),
83-
Child('Argument', kind='IdentifierToken',
84-
is_optional=True,
85-
text_choices=[
86-
'unowned', 'safe', 'unsafe', 'set',
87-
]),
88-
Child('RightParen', kind='RightParenToken',
89-
is_optional=True),
81+
Child('Detail', kind='TokenList'),
9082
]),
9183

9284
# type-inheritance-clause -> ':' type

0 commit comments

Comments
 (0)