Skip to content

Commit 6c0af2a

Browse files
authored
[Syntax] Introduce CodeBlockItem (#14458)
CodeBlockItem represents Decl, Stmt or Expr that optionally followed by semi-colon. SourceFile syntax holds a list of CodeBlockItem.
1 parent af67204 commit 6c0af2a

File tree

14 files changed

+480
-519
lines changed

14 files changed

+480
-519
lines changed

lib/Parse/ParseDecl.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3905,7 +3905,8 @@ bool Parser::parseGetSetImpl(ParseDeclOptions Flags,
39053905
if (Flags.contains(PD_InProtocol) || isInSILMode()) {
39063906
if (Tok.is(tok::r_brace)) {
39073907
// Give syntax node an empty statement list.
3908-
SyntaxParsingContext StmtListContext(SyntaxContext, SyntaxKind::StmtList);
3908+
SyntaxParsingContext StmtListContext(SyntaxContext,
3909+
SyntaxKind::CodeBlockItemList);
39093910
}
39103911
while (Tok.isNot(tok::r_brace)) {
39113912
if (Tok.is(tok::eof))
@@ -3988,7 +3989,8 @@ bool Parser::parseGetSetImpl(ParseDeclOptions Flags,
39883989
// an implicit fallthrough off the end.
39893990
if (Tok.is(tok::r_brace)) {
39903991
// Give syntax node an empty statement list.
3991-
SyntaxParsingContext StmtListContext(SyntaxContext, SyntaxKind::StmtList);
3992+
SyntaxParsingContext StmtListContext(SyntaxContext,
3993+
SyntaxKind::CodeBlockItemList);
39923994
diagnose(Tok, diag::computed_property_no_accessors);
39933995
return true;
39943996
}

lib/Parse/ParseStmt.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ bool Parser::isStartOfStmt() {
8989

9090
ParserStatus Parser::parseExprOrStmt(ASTNode &Result) {
9191
if (Tok.is(tok::semi)) {
92+
SyntaxParsingContext ErrorCtxt(SyntaxContext, SyntaxContextKind::Stmt);
9293
diagnose(Tok, diag::illegal_semi_stmt)
9394
.fixItRemove(SourceRange(Tok.getLoc()));
9495
consumeToken();
@@ -112,6 +113,7 @@ ParserStatus Parser::parseExprOrStmt(ASTNode &Result) {
112113
if (Tok.is(tok::code_complete)) {
113114
if (CodeCompletion)
114115
CodeCompletion->completeStmtOrExpr();
116+
SyntaxParsingContext ErrorCtxt(SyntaxContext, SyntaxContextKind::Stmt);
115117
consumeToken(tok::code_complete);
116118
return makeParserCodeCompletionStatus();
117119
}
@@ -228,7 +230,8 @@ void Parser::consumeTopLevelDecl(ParserPosition BeginParserPosition,
228230
ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries,
229231
BraceItemListKind Kind,
230232
BraceItemListKind ConditionalBlockKind) {
231-
SyntaxParsingContext StmtListContext(SyntaxContext, SyntaxKind::StmtList);
233+
SyntaxParsingContext ItemListContext(SyntaxContext,
234+
SyntaxKind::CodeBlockItemList);
232235

233236
bool IsTopLevel = (Kind == BraceItemListKind::TopLevelCode) ||
234237
(Kind == BraceItemListKind::TopLevelLibrary);
@@ -264,9 +267,10 @@ ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries,
264267
(isConditionalBlock ||
265268
!isTerminatorForBraceItemListKind(Kind, Entries))) {
266269

267-
SyntaxParsingContext StmtContext(SyntaxContext, SyntaxContextKind::Stmt);
270+
SyntaxParsingContext NodeContext(SyntaxContext, SyntaxKind::CodeBlockItem);
268271

269272
if (Tok.is(tok::r_brace)) {
273+
SyntaxParsingContext ErrContext(SyntaxContext, SyntaxContextKind::Stmt);
270274
assert(IsTopLevel);
271275
diagnose(Tok, diag::extra_rbrace)
272276
.fixItRemove(Tok.getLoc());
@@ -275,8 +279,11 @@ ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries,
275279
}
276280

277281
// Eat invalid tokens instead of allowing them to produce downstream errors.
278-
if (consumeIf(tok::unknown))
282+
if (Tok.is(tok::unknown)) {
283+
SyntaxParsingContext ErrContext(SyntaxContext, SyntaxContextKind::Stmt);
284+
consumeToken();
279285
continue;
286+
}
280287

281288
bool NeedParseErrorRecovery = false;
282289
ASTNode Result;
@@ -411,6 +418,11 @@ ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries,
411418
}
412419

413420
if (NeedParseErrorRecovery) {
421+
SyntaxContext->createNodeInPlace(SyntaxKind::CodeBlockItem);
422+
SyntaxContext->setTransparent();
423+
424+
SyntaxParsingContext ItemCtxt(SyntaxContext, SyntaxKind::CodeBlockItem);
425+
SyntaxParsingContext StmtCtxt(SyntaxContext, SyntaxContextKind::Stmt);
414426
// If we had a parse error, skip to the start of the next stmt, decl or
415427
// '{'.
416428
//

lib/Parse/SyntaxParsingContext.cpp

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,10 @@ RC<RawSyntax> SyntaxParsingContext::bridgeAs(SyntaxContextKind Kind,
6868
if (Parts.size() == 1) {
6969
auto RawNode = Parts.front();
7070
switch (Kind) {
71-
case SyntaxContextKind::Stmt: {
72-
if (RawNode->isStmt())
73-
return RawNode;
74-
else if (RawNode->isDecl())
75-
return createSyntaxAs(SyntaxKind::DeclarationStmt, Parts);
76-
else if (RawNode->isExpr())
77-
return createSyntaxAs(SyntaxKind::ExpressionStmt, Parts);
78-
else
71+
case SyntaxContextKind::Stmt:
72+
if (!RawNode->isStmt())
7973
return makeUnknownSyntax(SyntaxKind::UnknownStmt, Parts);
8074
break;
81-
}
8275
case SyntaxContextKind::Decl:
8376
if (!RawNode->isDecl())
8477
return makeUnknownSyntax(SyntaxKind::UnknownDecl, Parts);
@@ -186,6 +179,7 @@ void SyntaxParsingContext::createNodeInPlace(SyntaxKind Kind) {
186179
createNodeInPlace(Kind, Pair.first);
187180
break;
188181
}
182+
case SyntaxKind::CodeBlockItem:
189183
case SyntaxKind::IdentifierExpr:
190184
case SyntaxKind::SpecializeExpr:
191185
case SyntaxKind::MemberAccessExpr:
@@ -255,8 +249,8 @@ void finalizeSourceFile(RootContextData &RootData,
255249

256250
if (SF.hasSyntaxRoot()) {
257251
auto SourceRaw = SF.getSyntaxRoot().getRaw();
258-
auto Decls = SourceRaw->getChild(SourceFileSyntax::Cursor::TopLevelDecls)
259-
->getLayout();
252+
auto Decls =
253+
SourceRaw->getChild(SourceFileSyntax::Cursor::Items)->getLayout();
260254
std::copy(Decls.begin(), Decls.end(), std::back_inserter(AllTopLevel));
261255
EOFToken = SourceRaw->getChild(SourceFileSyntax::Cursor::EOFToken);
262256
}
@@ -267,12 +261,13 @@ void finalizeSourceFile(RootContextData &RootData,
267261
}
268262

269263
for (auto RawNode : Parts) {
270-
if (RawNode->getKind() != SyntaxKind::StmtList)
264+
if (RawNode->getKind() != SyntaxKind::CodeBlockItemList)
271265
// FIXME: Skip toplevel garbage nodes for now. we shouldn't emit them in
272266
// the first place.
273267
continue;
274-
AllTopLevel.push_back(
275-
SyntaxFactory::createRaw(SyntaxKind::TopLevelCodeDecl, {RawNode}));
268+
269+
auto Items = RawNode->getLayout();
270+
std::copy(Items.begin(), Items.end(), std::back_inserter(AllTopLevel));
276271
}
277272

278273
if (!EOFToken)
@@ -281,8 +276,10 @@ void finalizeSourceFile(RootContextData &RootData,
281276
auto newRaw = SyntaxFactory::createRaw(
282277
SyntaxKind::SourceFile,
283278
{
284-
SyntaxFactory::createRaw(SyntaxKind::DeclList, AllTopLevel), EOFToken,
279+
SyntaxFactory::createRaw(SyntaxKind::CodeBlockItemList, AllTopLevel),
280+
EOFToken,
285281
});
282+
assert(newRaw);
286283
SF.setSyntaxRoot(make<SourceFileSyntax>(newRaw));
287284

288285
if (SF.getASTContext().LangOpts.VerifySyntaxTree) {

lib/Syntax/RawSyntax.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ static bool isTrivialSyntaxKind(SyntaxKind Kind) {
3030
return true;
3131
switch(Kind) {
3232
case SyntaxKind::SourceFile:
33-
case SyntaxKind::TopLevelCodeDecl:
33+
case SyntaxKind::CodeBlockItem:
3434
case SyntaxKind::ExpressionStmt:
3535
case SyntaxKind::DeclarationStmt:
3636
return true;
@@ -179,6 +179,8 @@ RawSyntax::accumulateAbsolutePosition(AbsolutePosition &Pos) const {
179179
Trailer.accumulateAbsolutePosition(Pos);
180180
} else {
181181
for (auto &Child : getLayout()) {
182+
if (!Child)
183+
continue;
182184
auto Result = Child->accumulateAbsolutePosition(Pos);
183185
if (!Ret && Result)
184186
Ret = Result;
@@ -254,6 +256,8 @@ void RawSyntax::dump(llvm::raw_ostream &OS, unsigned Indent) const {
254256
}
255257
} else {
256258
for (auto &Child : getLayout()) {
259+
if (!Child)
260+
continue;
257261
OS << "\n";
258262
Child->dump(OS, Indent + 1);
259263
}

test/SwiftSyntax/SyntaxChildren.swift

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,25 +28,21 @@ var SyntaxChildrenAPI = TestSuite("SyntaxChildrenAPI")
2828
SyntaxChildrenAPI.test("IterateWithAllPresent") {
2929
let returnStmt = SyntaxFactory.makeReturnStmt(
3030
returnKeyword: SyntaxFactory.makeReturnKeyword(),
31-
expression: SyntaxFactory.makeBlankUnknownExpr(),
32-
semicolon: SyntaxFactory.makeSemicolonToken())
31+
expression: SyntaxFactory.makeBlankUnknownExpr())
3332

3433
var iterator = returnStmt.children.makeIterator()
3534
expectNext(&iterator) { ($0 as? TokenSyntax)?.tokenKind == .returnKeyword }
3635
expectNext(&iterator) { $0 is ExprSyntax }
37-
expectNext(&iterator) { ($0 as? TokenSyntax)?.tokenKind == .semicolon }
3836
expectNextIsNil(&iterator)
3937
}
4038

4139
SyntaxChildrenAPI.test("IterateWithSomeMissing") {
4240
let returnStmt = SyntaxFactory.makeReturnStmt(
4341
returnKeyword: SyntaxFactory.makeReturnKeyword(),
44-
expression: nil,
45-
semicolon: SyntaxFactory.makeSemicolonToken())
42+
expression: nil)
4643

4744
var iterator = returnStmt.children.makeIterator()
4845
expectNext(&iterator) { ($0 as? TokenSyntax)?.tokenKind == .returnKeyword }
49-
expectNext(&iterator) { ($0 as? TokenSyntax)?.tokenKind == .semicolon }
5046
expectNextIsNil(&iterator)
5147
}
5248

0 commit comments

Comments
 (0)