Skip to content

Commit 8fae089

Browse files
committed
[CodeCompletion] Don't use temporary Lexer in the second pass
Since we only call one parsing function (i.e. parseAbstructFunctionBody, parseDecl, or parseStmtOrExpr), the parser stops at the end of the node. It's not necessary to limit the Lexer to set an ArtificialEOF. To minimize the parsing range, modify the Parser to *not* parse the body if the completion happens in the signature.
1 parent ff34795 commit 8fae089

File tree

4 files changed

+58
-61
lines changed

4 files changed

+58
-61
lines changed

lib/IDE/ExprContextAnalysis.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,14 @@ void typeCheckContextImpl(DeclContext *DC, SourceLoc Loc) {
7474

7575
case DeclContextKind::AbstractFunctionDecl: {
7676
auto *AFD = cast<AbstractFunctionDecl>(DC);
77-
swift::typeCheckAbstractFunctionBodyUntil(AFD, Loc);
77+
auto &SM = DC->getASTContext().SourceMgr;
78+
auto bodyRange = AFD->getBodySourceRange();
79+
if (SM.rangeContainsTokenLoc(bodyRange, Loc)) {
80+
swift::typeCheckAbstractFunctionBodyUntil(AFD, Loc);
81+
} else {
82+
assert(bodyRange.isInvalid() && "The body should not be parsed if the "
83+
"completion happens in the signature");
84+
}
7885
break;
7986
}
8087

lib/Parse/ParseDecl.cpp

Lines changed: 50 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -5646,6 +5646,7 @@ ParserResult<FuncDecl> Parser::parseDeclFunc(SourceLoc StaticLoc,
56465646
}
56475647
}
56485648

5649+
ParserStatus Status;
56495650
SourceLoc FuncLoc =
56505651
HasFuncKeyword ? consumeToken(tok::kw_func) : Tok.getLoc();
56515652

@@ -5702,27 +5703,25 @@ ParserResult<FuncDecl> Parser::parseDeclFunc(SourceLoc StaticLoc,
57025703
Optional<Scope> GenericsScope;
57035704
GenericsScope.emplace(this, ScopeKind::Generics);
57045705
GenericParamList *GenericParams;
5705-
bool SignatureHasCodeCompletion = false;
57065706
auto GenericParamResult = maybeParseGenericParams();
57075707
GenericParams = GenericParamResult.getPtrOrNull();
5708-
SignatureHasCodeCompletion |= GenericParamResult.hasCodeCompletion();
5709-
if (SignatureHasCodeCompletion && !CodeCompletion)
5710-
return makeParserCodeCompletionStatus();
5708+
if (GenericParamResult.hasCodeCompletion()) {
5709+
Status.setHasCodeCompletion();
5710+
if (!CodeCompletion)
5711+
return Status;
5712+
}
57115713

57125714
DefaultArgumentInfo DefaultArgs;
57135715
TypeRepr *FuncRetTy = nullptr;
57145716
DeclName FullName;
57155717
ParameterList *BodyParams;
57165718
SourceLoc throwsLoc;
57175719
bool rethrows;
5718-
ParserStatus SignatureStatus =
5719-
parseFunctionSignature(SimpleName, FullName, BodyParams, DefaultArgs,
5720-
throwsLoc, rethrows, FuncRetTy);
5721-
5722-
SignatureHasCodeCompletion |= SignatureStatus.hasCodeCompletion();
5723-
if (SignatureStatus.hasCodeCompletion() && !CodeCompletion) {
5720+
Status |= parseFunctionSignature(SimpleName, FullName, BodyParams,
5721+
DefaultArgs, throwsLoc, rethrows, FuncRetTy);
5722+
if (Status.hasCodeCompletion() && !CodeCompletion) {
57245723
// Trigger delayed parsing, no need to continue.
5725-
return SignatureStatus;
5724+
return Status;
57265725
}
57275726

57285727
diagnoseWhereClauseInGenericParamList(GenericParams);
@@ -5747,11 +5746,10 @@ ParserResult<FuncDecl> Parser::parseDeclFunc(SourceLoc StaticLoc,
57475746
if (Tok.is(tok::kw_where)) {
57485747
ContextChange CC(*this, FD);
57495748

5750-
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
5751-
SignatureHasCodeCompletion |= whereStatus.hasCodeCompletion();
5752-
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
5749+
Status |= parseFreestandingGenericWhereClause(GenericParams);
5750+
if (Status.hasCodeCompletion() && !CodeCompletion) {
57535751
// Trigger delayed parsing, no need to continue.
5754-
return whereStatus;
5752+
return Status;
57555753
}
57565754
}
57575755

@@ -5772,8 +5770,10 @@ ParserResult<FuncDecl> Parser::parseDeclFunc(SourceLoc StaticLoc,
57725770
FD->getAttrs() = Attributes;
57735771

57745772
// Pass the function signature to code completion.
5775-
if (SignatureHasCodeCompletion)
5773+
if (Status.hasCodeCompletion()) {
5774+
assert(CodeCompletion && "must be code completion second pass");
57765775
CodeCompletion->setParsedDecl(FD);
5776+
}
57775777

57785778
DefaultArgs.setFunctionContext(FD, FD->getParameters());
57795779
setLocalDiscriminator(FD);
@@ -5783,7 +5783,7 @@ ParserResult<FuncDecl> Parser::parseDeclFunc(SourceLoc StaticLoc,
57835783
diagnose(Tok, diag::protocol_method_with_body);
57845784
skipSingle();
57855785
}
5786-
} else {
5786+
} else if (!Status.hasCodeCompletion()) {
57875787
parseAbstractFunctionBody(FD);
57885788
}
57895789

@@ -6545,14 +6545,14 @@ Parser::parseDeclSubscript(SourceLoc StaticLoc,
65456545
Optional<Scope> GenericsScope;
65466546
GenericsScope.emplace(this, ScopeKind::Generics);
65476547
GenericParamList *GenericParams;
6548-
bool SignatureHasCodeCompletion = false;
65496548

65506549
auto Result = maybeParseGenericParams();
65516550
GenericParams = Result.getPtrOrNull();
6552-
SignatureHasCodeCompletion |= Result.hasCodeCompletion();
6553-
6554-
if (SignatureHasCodeCompletion && !CodeCompletion)
6555-
return makeParserCodeCompletionStatus();
6551+
if (Result.hasCodeCompletion()) {
6552+
Status.setHasCodeCompletion();
6553+
if (!CodeCompletion)
6554+
return Status;
6555+
}
65566556

65576557
// Parse the parameter list.
65586558
DefaultArgumentInfo DefaultArgs;
@@ -6561,10 +6561,8 @@ Parser::parseDeclSubscript(SourceLoc StaticLoc,
65616561
= parseSingleParameterClause(ParameterContextKind::Subscript,
65626562
&argumentNames, &DefaultArgs);
65636563
Status |= Indices;
6564-
6565-
SignatureHasCodeCompletion |= Indices.hasCodeCompletion();
6566-
if (SignatureHasCodeCompletion && !CodeCompletion)
6567-
return makeParserCodeCompletionStatus();
6564+
if (Status.hasCodeCompletion() && !CodeCompletion)
6565+
return Status;
65686566

65696567
SourceLoc ArrowLoc;
65706568
ParserResult<TypeRepr> ElementTy;
@@ -6588,10 +6586,9 @@ Parser::parseDeclSubscript(SourceLoc StaticLoc,
65886586
// type
65896587
ElementTy = parseDeclResultType(diag::expected_type_subscript);
65906588
Status |= ElementTy;
6591-
SignatureHasCodeCompletion |= ElementTy.hasCodeCompletion();
6592-
if (SignatureHasCodeCompletion && !CodeCompletion) {
6593-
return makeParserCodeCompletionStatus();
6594-
}
6589+
if (Status.hasCodeCompletion() && !CodeCompletion)
6590+
return Status;
6591+
65956592
if (ElementTy.isNull()) {
65966593
// Always set an element type.
65976594
ElementTy = makeParserResult(ElementTy, new (Context) ErrorTypeRepr());
@@ -6625,16 +6622,16 @@ Parser::parseDeclSubscript(SourceLoc StaticLoc,
66256622
if (Tok.is(tok::kw_where)) {
66266623
ContextChange CC(*this, Subscript);
66276624

6628-
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
6629-
SignatureHasCodeCompletion |= whereStatus.hasCodeCompletion();
6630-
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
6625+
Status |= parseFreestandingGenericWhereClause(GenericParams);
6626+
if (Status.hasCodeCompletion() && !CodeCompletion) {
66316627
// Trigger delayed parsing, no need to continue.
6632-
return whereStatus;
6628+
return Status;
66336629
}
66346630
}
66356631

66366632
// Pass the function signature to code completion.
6637-
if (SignatureHasCodeCompletion && CodeCompletion) {
6633+
if (Status.hasCodeCompletion()) {
6634+
assert(CodeCompletion && "must be code completion second pass");
66386635
CodeCompletion->setParsedDecl(Subscript);
66396636
}
66406637

@@ -6655,7 +6652,7 @@ Parser::parseDeclSubscript(SourceLoc StaticLoc,
66556652
}
66566653
Status.setIsParseError();
66576654
}
6658-
} else {
6655+
} else if (!Status.hasCodeCompletion()) {
66596656
Status |= parseGetSet(Flags, GenericParams, Indices.get(),
66606657
accessors, Subscript, StaticLoc);
66616658
}
@@ -6680,6 +6677,7 @@ Parser::parseDeclSubscript(SourceLoc StaticLoc,
66806677
ParserResult<ConstructorDecl>
66816678
Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
66826679
assert(Tok.is(tok::kw_init));
6680+
ParserStatus Status;
66836681
SourceLoc ConstructorLoc = consumeToken();
66846682
bool Failable = false, IUO = false;
66856683
SourceLoc FailabilityLoc;
@@ -6714,21 +6712,22 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
67146712
Scope S(this, ScopeKind::Generics);
67156713
auto GPResult = maybeParseGenericParams();
67166714
GenericParamList *GenericParams = GPResult.getPtrOrNull();
6717-
if (GPResult.hasCodeCompletion())
6718-
return makeParserCodeCompletionStatus();
6715+
if (GPResult.hasCodeCompletion()) {
6716+
Status.setHasCodeCompletion();
6717+
if (!CodeCompletion)
6718+
return Status;
6719+
}
67196720

67206721
// Parse the parameters.
67216722
DefaultArgumentInfo DefaultArgs;
67226723
llvm::SmallVector<Identifier, 4> namePieces;
6723-
bool SignatureHasCodeCompletion = false;
67246724
ParserResult<ParameterList> Params
67256725
= parseSingleParameterClause(ParameterContextKind::Initializer,
67266726
&namePieces, &DefaultArgs);
6727-
6728-
SignatureHasCodeCompletion |= Params.hasCodeCompletion();
6729-
if (Params.hasCodeCompletion() && !CodeCompletion) {
6727+
Status |= Params;
6728+
if (Status.hasCodeCompletion() && !CodeCompletion) {
67306729
// Trigger delayed parsing, no need to continue.
6731-
return makeParserCodeCompletionStatus();
6730+
return Status;
67326731
}
67336732

67346733
// Protocol initializer arguments may not have default values.
@@ -6760,11 +6759,10 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
67606759
if (Tok.is(tok::kw_where)) {
67616760
ContextChange(*this, CD);
67626761

6763-
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
6764-
SignatureHasCodeCompletion |= whereStatus.hasCodeCompletion();
6765-
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
6762+
Status |= parseFreestandingGenericWhereClause(GenericParams);
6763+
if (Status.hasCodeCompletion() && !CodeCompletion) {
67666764
// Trigger delayed parsing, no need to continue.
6767-
return whereStatus;
6765+
return Status;
67686766
}
67696767
}
67706768

@@ -6773,8 +6771,10 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
67736771
DefaultArgs.setFunctionContext(CD, CD->getParameters());
67746772

67756773
// Pass the function signature to code completion.
6776-
if (SignatureHasCodeCompletion)
6774+
if (Status.hasCodeCompletion()) {
6775+
assert(CodeCompletion && "must be code completion second pass");
67776776
CodeCompletion->setParsedDecl(CD);
6777+
}
67786778

67796779
if (ConstructorsNotAllowed || Params.isParseError()) {
67806780
// Tell the type checker not to touch this constructor.
@@ -6786,11 +6786,11 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
67866786
diagnose(Tok, diag::protocol_init_with_body);
67876787
skipSingle();
67886788
}
6789-
} else {
6789+
} else if(!Status.hasCodeCompletion()) {
67906790
parseAbstractFunctionBody(CD);
67916791
}
67926792

6793-
return makeParserResult(CD);
6793+
return makeParserResult(Status, CD);
67946794
}
67956795

67966796
ParserResult<DestructorDecl> Parser::

lib/Parse/Parser.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ void Parser::performCodeCompletionSecondPassImpl(
144144
SyntaxContext->disable();
145145

146146
auto BeginParserPosition = getParserPosition(info.BodyPos);
147-
auto EndLexerState = L->getStateForEndOfTokenLoc(info.BodyEnd);
148147

149148
// ParserPositionRAII needs a primed parser to restore to.
150149
if (Tok.is(tok::NUM_TOKENS))
@@ -153,12 +152,6 @@ void Parser::performCodeCompletionSecondPassImpl(
153152
// Ensure that we restore the parser state at exit.
154153
ParserPositionRAII PPR(*this);
155154

156-
// Create a lexer that cannot go past the end state.
157-
Lexer LocalLex(*L, BeginParserPosition.LS, EndLexerState);
158-
159-
// Temporarily swap out the parser's current lexer with our new one.
160-
llvm::SaveAndRestore<Lexer *> T(L, &LocalLex);
161-
162155
// Rewind to the beginning of the top-level code.
163156
restoreParserPosition(BeginParserPosition);
164157

test/Parse/recovery.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -695,9 +695,6 @@ struct InitializerWithNameAndParam {
695695
struct InitializerWithLabels {
696696
init c d: Int {}
697697
// expected-error @-1 {{expected '(' for initializer parameters}}
698-
// expected-error @-2 {{expected declaration}}
699-
// expected-error @-3 {{consecutive declarations on a line must be separated by ';'}}
700-
// expected-note @-5 {{in declaration of 'InitializerWithLabels'}}
701698
}
702699

703700
// rdar://20337695

0 commit comments

Comments
 (0)