Skip to content

Commit 9dfac63

Browse files
committed
[Parse] Adjust skipBracedBlock()
- Stop using skipBracedBlock() in parseDeclPrecedenceGroup(), skipUntilDeclRBrace() is better at this context. - Disable 'SyntaxParsingContext' inside skipBracedBlock() - Removed unsound recovery logic in consumeAbstractFunctionBody(). This doesn't match with the parser bahavior in the delayed parsing. - Expose 'skipBracedBlock()' as a Parser instance method so it's usable from other files.
1 parent 3e1de28 commit 9dfac63

File tree

3 files changed

+29
-40
lines changed

3 files changed

+29
-40
lines changed

include/swift/Parse/Parser.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,10 @@ class Parser {
651651
/// plain Tok.is(T1) check).
652652
bool skipUntilTokenOrEndOfLine(tok T1);
653653

654+
/// Skip a braced block (e.g. function body). The current token must be '{'.
655+
/// Returns \c true if the parser hit the eof before finding matched '}'.
656+
bool skipBracedBlock();
657+
654658
/// If the parser is generating only a syntax tree, try loading the current
655659
/// node from a previously generated syntax tree.
656660
/// Returns \c true if the node has been loaded and inserted into the current

lib/Parse/ParseDecl.cpp

Lines changed: 17 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2800,21 +2800,11 @@ static void diagnoseOperatorFixityAttributes(Parser &P,
28002800
static unsigned skipUntilMatchingRBrace(Parser &P,
28012801
bool &HasPoundDirective,
28022802
bool &HasOperatorDeclarations,
2803-
bool &HasNestedClassDeclarations,
2804-
SyntaxParsingContext *&SyntaxContext) {
2803+
bool &HasNestedClassDeclarations) {
28052804
HasPoundDirective = false;
28062805
HasOperatorDeclarations = false;
28072806
HasNestedClassDeclarations = false;
28082807

2809-
bool isRootCtx = SyntaxContext->isRoot();
2810-
SyntaxParsingContext BlockItemListContext(SyntaxContext,
2811-
SyntaxKind::CodeBlockItemList);
2812-
if (isRootCtx) {
2813-
BlockItemListContext.setTransparent();
2814-
}
2815-
SyntaxParsingContext BlockItemContext(SyntaxContext,
2816-
SyntaxKind::CodeBlockItem);
2817-
SyntaxParsingContext BodyContext(SyntaxContext, SyntaxKind::TokenList);
28182808
unsigned OpenBraces = 1;
28192809

28202810
bool LastTokenWasFunc = false;
@@ -3998,8 +3988,7 @@ bool Parser::canDelayMemberDeclParsing(bool &HasOperatorDeclarations,
39983988
skipUntilMatchingRBrace(*this,
39993989
HasPoundDirective,
40003990
HasOperatorDeclarations,
4001-
HasNestedClassDeclarations,
4002-
SyntaxContext);
3991+
HasNestedClassDeclarations);
40033992
if (!HasPoundDirective)
40043993
BackTrack.cancelBacktrack();
40053994
return !BackTrack.willBacktrack();
@@ -4690,25 +4679,24 @@ static ParameterList *parseOptionalAccessorArgument(SourceLoc SpecifierLoc,
46904679
return ParameterList::create(P.Context, StartLoc, param, EndLoc);
46914680
}
46924681

4693-
static unsigned skipBracedBlock(Parser &P,
4694-
SyntaxParsingContext *&SyntaxContext) {
4695-
SyntaxParsingContext CodeBlockContext(SyntaxContext, SyntaxKind::CodeBlock);
4696-
P.consumeToken(tok::l_brace);
4682+
bool Parser::skipBracedBlock() {
4683+
SyntaxParsingContext disabled(SyntaxContext);
4684+
SyntaxContext->disable();
4685+
consumeToken(tok::l_brace);
46974686

46984687
// We don't care if a skipped function body contained any of these, so
46994688
// just ignore them.
47004689
bool HasPoundDirectives;
47014690
bool HasOperatorDeclarations;
47024691
bool HasNestedClassDeclarations;
47034692

4704-
unsigned OpenBraces = skipUntilMatchingRBrace(P,
4693+
unsigned OpenBraces = skipUntilMatchingRBrace(*this,
47054694
HasPoundDirectives,
47064695
HasOperatorDeclarations,
4707-
HasNestedClassDeclarations,
4708-
SyntaxContext);
4709-
if (P.consumeIf(tok::r_brace))
4696+
HasNestedClassDeclarations);
4697+
if (consumeIf(tok::r_brace))
47104698
OpenBraces--;
4711-
return OpenBraces;
4699+
return OpenBraces != 0;
47124700
}
47134701

47144702
/// Returns a descriptive name for the given accessor/addressor kind.
@@ -5578,20 +5566,8 @@ void Parser::consumeAbstractFunctionBody(AbstractFunctionDecl *AFD,
55785566
SourceRange BodyRange;
55795567
BodyRange.Start = Tok.getLoc();
55805568

5581-
// Consume the '{', and find the matching '}'.
5582-
unsigned OpenBraces = skipBracedBlock(*this, SyntaxContext);
5583-
if (OpenBraces != 0 && Tok.isNot(tok::code_complete)) {
5584-
assert(Tok.is(tok::eof));
5585-
// We hit EOF, and not every brace has a pair. Recover by searching
5586-
// for the next decl except variable decls and cutting off before
5587-
// that point.
5588-
backtrackToPosition(BeginParserPosition);
5589-
consumeToken(tok::l_brace);
5590-
while (Tok.is(tok::kw_var) || Tok.is(tok::kw_let) ||
5591-
(Tok.isNot(tok::eof) && !isStartOfDecl())) {
5592-
consumeToken();
5593-
}
5594-
}
5569+
// Advance the parser to the end of the block; '{' ... '}'.
5570+
skipBracedBlock();
55955571

55965572
BodyRange.End = PreviousLoc;
55975573

@@ -7033,12 +7009,13 @@ Parser::parseDeclPrecedenceGroup(ParseDeclOptions flags,
70337009
if (parseIdentifier(name, nameLoc, diag::expected_precedencegroup_name)) {
70347010
// If the identifier is missing or a keyword or something, try to
70357011
// skip the entire body.
7036-
if (consumeIf(tok::l_brace)) {
7012+
if (!Tok.isAtStartOfLine() && Tok.isNot(tok::eof) &&
7013+
peekToken().is(tok::l_brace))
7014+
consumeToken();
7015+
if (Tok.is(tok::l_brace)) {
7016+
consumeToken(tok::l_brace);
70377017
skipUntilDeclRBrace();
70387018
(void) consumeIf(tok::r_brace);
7039-
} else if (Tok.isNot(tok::eof) && peekToken().is(tok::l_brace)) {
7040-
consumeToken();
7041-
skipBracedBlock(*this, SyntaxContext);
70427019
}
70437020
return nullptr;
70447021
}

tools/swift-ide-test/swift-ide-test.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,10 @@ static int doTypeContextInfo(const CompilerInvocation &InitInvok,
745745
// they are somewhat heavy operations and are not needed for completions.
746746
Invocation.getFrontendOptions().IgnoreSwiftSourceInfo = true;
747747

748+
// Disable to build syntax tree because code-completion skips some portion of
749+
// source text. That breaks an invariant of syntax tree building.
750+
Invocation.getLangOptions().BuildSyntaxTree = false;
751+
748752
Invocation.setCodeCompletionPoint(CleanFile.get(), Offset);
749753

750754
// Create a CodeCompletionConsumer.
@@ -810,6 +814,10 @@ doConformingMethodList(const CompilerInvocation &InitInvok,
810814
// they are somewhat heavy operations and are not needed for completions.
811815
Invocation.getFrontendOptions().IgnoreSwiftSourceInfo = true;
812816

817+
// Disable to build syntax tree because code-completion skips some portion of
818+
// source text. That breaks an invariant of syntax tree building.
819+
Invocation.getLangOptions().BuildSyntaxTree = false;
820+
813821
Invocation.setCodeCompletionPoint(CleanFile.get(), Offset);
814822

815823
SmallVector<const char *, 4> typeNames;

0 commit comments

Comments
 (0)