Skip to content

libSyntax: support declaration modifiers, like static, private, etc. #13221

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 4, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2282,16 +2282,27 @@ Parser::parseDecl(ParseDeclOptions Flags,
StaticLoc = Tok.getLoc();
StaticSpelling = StaticSpellingKind::KeywordStatic;
}
SyntaxParsingContext ModContext(SyntaxContext, SyntaxKind::DeclModifier);
consumeToken(tok::kw_static);
// Static modifier doesn't have more details.
SyntaxParsingContext DetailContext(SyntaxContext, SyntaxKind::TokenList);
continue;
}
// 'class' is a modifier on func, but is also a top-level decl.
case tok::kw_class: {
SourceLoc ClassLoc = consumeToken(tok::kw_class);

SourceLoc ClassLoc;
bool AsModifier;
{
BacktrackingScope Scope(*this);
ClassLoc = consumeToken(tok::kw_class);
AsModifier = isStartOfDecl();
}
// If 'class' is a modifier on another decl kind, like var or func,
// then treat it as a modifier.
if (isStartOfDecl()) {
if (AsModifier) {
SyntaxParsingContext ModContext(SyntaxContext, SyntaxKind::DeclModifier);
consumeToken(tok::kw_class);
SyntaxParsingContext DetailContext(SyntaxContext, SyntaxKind::TokenList);
if (StaticLoc.isValid()) {
diagnose(Tok, diag::decl_already_static,
StaticSpellingKind::KeywordClass)
Expand All @@ -2303,6 +2314,7 @@ Parser::parseDecl(ParseDeclOptions Flags,
continue;
}

consumeToken(tok::kw_class);
// Otherwise this is the start of a class declaration.
DeclResult = parseDeclClass(ClassLoc, Flags, Attributes);
break;
Expand All @@ -2312,6 +2324,7 @@ Parser::parseDecl(ParseDeclOptions Flags,
case tok::kw_fileprivate:
case tok::kw_internal:
case tok::kw_public: {
SyntaxParsingContext ModContext(SyntaxContext, SyntaxKind::DeclModifier);
// We still model these specifiers as attributes.
parseNewDeclAttribute(Attributes, /*AtLoc=*/{}, DAK_AccessControl);
continue;
Expand Down Expand Up @@ -2356,6 +2369,7 @@ Parser::parseDecl(ParseDeclOptions Flags,
Kind = DAK_Convenience;
}
if (Kind) {
SyntaxParsingContext ModContext(SyntaxContext, SyntaxKind::DeclModifier);
parseNewDeclAttribute(Attributes, SourceLoc(), *Kind);
continue;
}
Expand Down
8 changes: 4 additions & 4 deletions test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@ struct foo <MemberDeclBlock>{

struct foo <MemberDeclBlock>{<Attribute>
@available(*, unavailable)</Attribute>
struct foo <MemberDeclBlock>{}</MemberDeclBlock>
public class foo {<Attribute>
struct foo <MemberDeclBlock>{}</MemberDeclBlock><DeclModifier>
public </DeclModifier>class foo {<Attribute>
@available(*, unavailable)</Attribute><Attribute>
@objc(fooObjc)</Attribute>
private static func foo() <CodeBlock>{}</CodeBlock>
@objc(fooObjc)</Attribute><DeclModifier>
private </DeclModifier><DeclModifier>static </DeclModifier>func foo() <CodeBlock>{}</CodeBlock>
}
}</MemberDeclBlock>
24 changes: 12 additions & 12 deletions unittests/Syntax/DeclSyntaxTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ DeclModifierSyntax getCannedDeclModifier() {
auto LParen = SyntaxFactory::makeLeftParenToken({}, {});
auto Set = SyntaxFactory::makeIdentifier("set", {}, {});
auto RParen = SyntaxFactory::makeRightParenToken({}, {});
return SyntaxFactory::makeDeclModifier(Private, LParen, Set, RParen);
return SyntaxFactory::makeDeclModifier(Private,
SyntaxFactory::makeTokenList({ LParen, Set, RParen}));
}

TEST(DeclSyntaxTests, DeclModifierMakeAPIs) {
Expand All @@ -40,12 +41,13 @@ TEST(DeclSyntaxTests, DeclModifierGetAPIs) {
auto LParen = SyntaxFactory::makeLeftParenToken({}, {});
auto Set = SyntaxFactory::makeIdentifier("set", {}, {});
auto RParen = SyntaxFactory::makeRightParenToken({}, {});
auto Mod = SyntaxFactory::makeDeclModifier(Private, LParen, Set, RParen);
auto Mod = SyntaxFactory::makeDeclModifier(Private,
SyntaxFactory::makeTokenList({LParen, Set, RParen}));

ASSERT_EQ(Private.getRaw(), Mod.getName().getRaw());
ASSERT_EQ(LParen.getRaw(), Mod.getLeftParen()->getRaw());
ASSERT_EQ(Set.getRaw(), Mod.getArgument()->getRaw());
ASSERT_EQ(RParen.getRaw(), Mod.getRightParen()->getRaw());
ASSERT_EQ(LParen.getRaw(), Mod.getDetail()[0].getRaw());
ASSERT_EQ(Set.getRaw(), Mod.getDetail()[1].getRaw());
ASSERT_EQ(RParen.getRaw(), Mod.getDetail()[2].getRaw());
}

TEST(DeclSyntaxTests, DeclModifierWithAPIs) {
Expand All @@ -58,9 +60,7 @@ TEST(DeclSyntaxTests, DeclModifierWithAPIs) {
llvm::raw_svector_ostream OS(Scratch);
SyntaxFactory::makeBlankDeclModifier()
.withName(Private)
.withLeftParen(LParen)
.withArgument(Set)
.withRightParen(RParen)
.withDetail(SyntaxFactory::makeTokenList({LParen, Set, RParen}))
.print(OS);
ASSERT_EQ(OS.str().str(), "private(set)");
}
Expand Down Expand Up @@ -480,12 +480,12 @@ ModifierListSyntax getCannedModifiers() {
auto NoLParen = TokenSyntax::missingToken(tok::l_paren, "(");
auto NoArgument = TokenSyntax::missingToken(tok::identifier, "");
auto NoRParen = TokenSyntax::missingToken(tok::r_paren, ")");
auto Public = SyntaxFactory::makeDeclModifier(PublicID, NoLParen, NoArgument,
NoRParen);
auto Public = SyntaxFactory::makeDeclModifier(PublicID,
SyntaxFactory::makeTokenList({NoLParen, NoArgument, NoRParen}));

auto StaticKW = SyntaxFactory::makeStaticKeyword({}, Trivia::spaces(1));
auto Static = SyntaxFactory::makeDeclModifier(StaticKW, NoLParen, NoArgument,
NoRParen);
auto Static = SyntaxFactory::makeDeclModifier(StaticKW,
SyntaxFactory::makeTokenList({NoLParen, NoArgument, NoRParen}));

return SyntaxFactory::makeBlankModifierList()
.appending(Public)
Expand Down
10 changes: 1 addition & 9 deletions utils/gyb_syntax_support/DeclNodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,7 @@
'fileprivate', 'internal', 'public', 'open',
'mutating', 'nonmutating',
]),
Child('LeftParen', kind='LeftParenToken',
is_optional=True),
Child('Argument', kind='IdentifierToken',
is_optional=True,
text_choices=[
'unowned', 'safe', 'unsafe', 'set',
]),
Child('RightParen', kind='RightParenToken',
is_optional=True),
Child('Detail', kind='TokenList'),
]),

# type-inheritance-clause -> ':' type
Expand Down