Skip to content

Commit 83c1e7b

Browse files
authored
Merge pull request #28433 from rintaro/ide-completion-secondpassend
[CodeCompletion] Stop using temporary Lexer in the second pass
2 parents 8cd3ddc + 6f201db commit 83c1e7b

File tree

5 files changed

+65
-81
lines changed

5 files changed

+65
-81
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
@@ -5740,6 +5740,7 @@ ParserResult<FuncDecl> Parser::parseDeclFunc(SourceLoc StaticLoc,
57405740
}
57415741
}
57425742

5743+
ParserStatus Status;
57435744
SourceLoc FuncLoc =
57445745
HasFuncKeyword ? consumeToken(tok::kw_func) : Tok.getLoc();
57455746

@@ -5796,27 +5797,25 @@ ParserResult<FuncDecl> Parser::parseDeclFunc(SourceLoc StaticLoc,
57965797
Optional<Scope> GenericsScope;
57975798
GenericsScope.emplace(this, ScopeKind::Generics);
57985799
GenericParamList *GenericParams;
5799-
bool SignatureHasCodeCompletion = false;
58005800
auto GenericParamResult = maybeParseGenericParams();
58015801
GenericParams = GenericParamResult.getPtrOrNull();
5802-
SignatureHasCodeCompletion |= GenericParamResult.hasCodeCompletion();
5803-
if (SignatureHasCodeCompletion && !CodeCompletion)
5804-
return makeParserCodeCompletionStatus();
5802+
if (GenericParamResult.hasCodeCompletion()) {
5803+
Status.setHasCodeCompletion();
5804+
if (!CodeCompletion)
5805+
return Status;
5806+
}
58055807

58065808
DefaultArgumentInfo DefaultArgs;
58075809
TypeRepr *FuncRetTy = nullptr;
58085810
DeclName FullName;
58095811
ParameterList *BodyParams;
58105812
SourceLoc throwsLoc;
58115813
bool rethrows;
5812-
ParserStatus SignatureStatus =
5813-
parseFunctionSignature(SimpleName, FullName, BodyParams, DefaultArgs,
5814-
throwsLoc, rethrows, FuncRetTy);
5815-
5816-
SignatureHasCodeCompletion |= SignatureStatus.hasCodeCompletion();
5817-
if (SignatureStatus.hasCodeCompletion() && !CodeCompletion) {
5814+
Status |= parseFunctionSignature(SimpleName, FullName, BodyParams,
5815+
DefaultArgs, throwsLoc, rethrows, FuncRetTy);
5816+
if (Status.hasCodeCompletion() && !CodeCompletion) {
58185817
// Trigger delayed parsing, no need to continue.
5819-
return SignatureStatus;
5818+
return Status;
58205819
}
58215820

58225821
diagnoseWhereClauseInGenericParamList(GenericParams);
@@ -5841,11 +5840,10 @@ ParserResult<FuncDecl> Parser::parseDeclFunc(SourceLoc StaticLoc,
58415840
if (Tok.is(tok::kw_where)) {
58425841
ContextChange CC(*this, FD);
58435842

5844-
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
5845-
SignatureHasCodeCompletion |= whereStatus.hasCodeCompletion();
5846-
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
5843+
Status |= parseFreestandingGenericWhereClause(GenericParams);
5844+
if (Status.hasCodeCompletion() && !CodeCompletion) {
58475845
// Trigger delayed parsing, no need to continue.
5848-
return whereStatus;
5846+
return Status;
58495847
}
58505848
}
58515849

@@ -5866,8 +5864,10 @@ ParserResult<FuncDecl> Parser::parseDeclFunc(SourceLoc StaticLoc,
58665864
FD->getAttrs() = Attributes;
58675865

58685866
// Pass the function signature to code completion.
5869-
if (SignatureHasCodeCompletion)
5867+
if (Status.hasCodeCompletion()) {
5868+
assert(CodeCompletion && "must be code completion second pass");
58705869
CodeCompletion->setParsedDecl(FD);
5870+
}
58715871

58725872
DefaultArgs.setFunctionContext(FD, FD->getParameters());
58735873
setLocalDiscriminator(FD);
@@ -5877,7 +5877,7 @@ ParserResult<FuncDecl> Parser::parseDeclFunc(SourceLoc StaticLoc,
58775877
diagnose(Tok, diag::protocol_method_with_body);
58785878
skipSingle();
58795879
}
5880-
} else {
5880+
} else if (!Status.hasCodeCompletion()) {
58815881
parseAbstractFunctionBody(FD);
58825882
}
58835883

@@ -6639,14 +6639,14 @@ Parser::parseDeclSubscript(SourceLoc StaticLoc,
66396639
Optional<Scope> GenericsScope;
66406640
GenericsScope.emplace(this, ScopeKind::Generics);
66416641
GenericParamList *GenericParams;
6642-
bool SignatureHasCodeCompletion = false;
66436642

66446643
auto Result = maybeParseGenericParams();
66456644
GenericParams = Result.getPtrOrNull();
6646-
SignatureHasCodeCompletion |= Result.hasCodeCompletion();
6647-
6648-
if (SignatureHasCodeCompletion && !CodeCompletion)
6649-
return makeParserCodeCompletionStatus();
6645+
if (Result.hasCodeCompletion()) {
6646+
Status.setHasCodeCompletion();
6647+
if (!CodeCompletion)
6648+
return Status;
6649+
}
66506650

66516651
// Parse the parameter list.
66526652
DefaultArgumentInfo DefaultArgs;
@@ -6655,10 +6655,8 @@ Parser::parseDeclSubscript(SourceLoc StaticLoc,
66556655
= parseSingleParameterClause(ParameterContextKind::Subscript,
66566656
&argumentNames, &DefaultArgs);
66576657
Status |= Indices;
6658-
6659-
SignatureHasCodeCompletion |= Indices.hasCodeCompletion();
6660-
if (SignatureHasCodeCompletion && !CodeCompletion)
6661-
return makeParserCodeCompletionStatus();
6658+
if (Status.hasCodeCompletion() && !CodeCompletion)
6659+
return Status;
66626660

66636661
SourceLoc ArrowLoc;
66646662
ParserResult<TypeRepr> ElementTy;
@@ -6682,10 +6680,9 @@ Parser::parseDeclSubscript(SourceLoc StaticLoc,
66826680
// type
66836681
ElementTy = parseDeclResultType(diag::expected_type_subscript);
66846682
Status |= ElementTy;
6685-
SignatureHasCodeCompletion |= ElementTy.hasCodeCompletion();
6686-
if (SignatureHasCodeCompletion && !CodeCompletion) {
6687-
return makeParserCodeCompletionStatus();
6688-
}
6683+
if (Status.hasCodeCompletion() && !CodeCompletion)
6684+
return Status;
6685+
66896686
if (ElementTy.isNull()) {
66906687
// Always set an element type.
66916688
ElementTy = makeParserResult(ElementTy, new (Context) ErrorTypeRepr());
@@ -6719,16 +6716,16 @@ Parser::parseDeclSubscript(SourceLoc StaticLoc,
67196716
if (Tok.is(tok::kw_where)) {
67206717
ContextChange CC(*this, Subscript);
67216718

6722-
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
6723-
SignatureHasCodeCompletion |= whereStatus.hasCodeCompletion();
6724-
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
6719+
Status |= parseFreestandingGenericWhereClause(GenericParams);
6720+
if (Status.hasCodeCompletion() && !CodeCompletion) {
67256721
// Trigger delayed parsing, no need to continue.
6726-
return whereStatus;
6722+
return Status;
67276723
}
67286724
}
67296725

67306726
// Pass the function signature to code completion.
6731-
if (SignatureHasCodeCompletion && CodeCompletion) {
6727+
if (Status.hasCodeCompletion()) {
6728+
assert(CodeCompletion && "must be code completion second pass");
67326729
CodeCompletion->setParsedDecl(Subscript);
67336730
}
67346731

@@ -6749,7 +6746,7 @@ Parser::parseDeclSubscript(SourceLoc StaticLoc,
67496746
}
67506747
Status.setIsParseError();
67516748
}
6752-
} else {
6749+
} else if (!Status.hasCodeCompletion()) {
67536750
Status |= parseGetSet(Flags, GenericParams, Indices.get(),
67546751
accessors, Subscript, StaticLoc);
67556752
}
@@ -6774,6 +6771,7 @@ Parser::parseDeclSubscript(SourceLoc StaticLoc,
67746771
ParserResult<ConstructorDecl>
67756772
Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
67766773
assert(Tok.is(tok::kw_init));
6774+
ParserStatus Status;
67776775
SourceLoc ConstructorLoc = consumeToken();
67786776
bool Failable = false, IUO = false;
67796777
SourceLoc FailabilityLoc;
@@ -6808,21 +6806,22 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
68086806
Scope S(this, ScopeKind::Generics);
68096807
auto GPResult = maybeParseGenericParams();
68106808
GenericParamList *GenericParams = GPResult.getPtrOrNull();
6811-
if (GPResult.hasCodeCompletion())
6812-
return makeParserCodeCompletionStatus();
6809+
if (GPResult.hasCodeCompletion()) {
6810+
Status.setHasCodeCompletion();
6811+
if (!CodeCompletion)
6812+
return Status;
6813+
}
68136814

68146815
// Parse the parameters.
68156816
DefaultArgumentInfo DefaultArgs;
68166817
llvm::SmallVector<Identifier, 4> namePieces;
6817-
bool SignatureHasCodeCompletion = false;
68186818
ParserResult<ParameterList> Params
68196819
= parseSingleParameterClause(ParameterContextKind::Initializer,
68206820
&namePieces, &DefaultArgs);
6821-
6822-
SignatureHasCodeCompletion |= Params.hasCodeCompletion();
6823-
if (Params.hasCodeCompletion() && !CodeCompletion) {
6821+
Status |= Params;
6822+
if (Status.hasCodeCompletion() && !CodeCompletion) {
68246823
// Trigger delayed parsing, no need to continue.
6825-
return makeParserCodeCompletionStatus();
6824+
return Status;
68266825
}
68276826

68286827
// Protocol initializer arguments may not have default values.
@@ -6854,11 +6853,10 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
68546853
if (Tok.is(tok::kw_where)) {
68556854
ContextChange(*this, CD);
68566855

6857-
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
6858-
SignatureHasCodeCompletion |= whereStatus.hasCodeCompletion();
6859-
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
6856+
Status |= parseFreestandingGenericWhereClause(GenericParams);
6857+
if (Status.hasCodeCompletion() && !CodeCompletion) {
68606858
// Trigger delayed parsing, no need to continue.
6861-
return whereStatus;
6859+
return Status;
68626860
}
68636861
}
68646862

@@ -6867,8 +6865,10 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
68676865
DefaultArgs.setFunctionContext(CD, CD->getParameters());
68686866

68696867
// Pass the function signature to code completion.
6870-
if (SignatureHasCodeCompletion)
6868+
if (Status.hasCodeCompletion()) {
6869+
assert(CodeCompletion && "must be code completion second pass");
68716870
CodeCompletion->setParsedDecl(CD);
6871+
}
68726872

68736873
if (ConstructorsNotAllowed || Params.isParseError()) {
68746874
// Tell the type checker not to touch this constructor.
@@ -6880,11 +6880,11 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
68806880
diagnose(Tok, diag::protocol_init_with_body);
68816881
skipSingle();
68826882
}
6883-
} else {
6883+
} else if(!Status.hasCodeCompletion()) {
68846884
parseAbstractFunctionBody(CD);
68856885
}
68866886

6887-
return makeParserResult(CD);
6887+
return makeParserResult(Status, CD);
68886888
}
68896889

68906890
ParserResult<DestructorDecl> Parser::

lib/Parse/Parser.cpp

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -143,24 +143,8 @@ void Parser::performCodeCompletionSecondPassImpl(
143143
// Disable libSyntax creation in the delayed parsing.
144144
SyntaxContext->disable();
145145

146-
auto BeginParserPosition = getParserPosition(info.BodyPos);
147-
auto EndLexerState = L->getStateForEndOfTokenLoc(info.BodyEnd);
148-
149-
// ParserPositionRAII needs a primed parser to restore to.
150-
if (Tok.is(tok::NUM_TOKENS))
151-
consumeTokenWithoutFeedingReceiver();
152-
153-
// Ensure that we restore the parser state at exit.
154-
ParserPositionRAII PPR(*this);
155-
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-
162-
// Rewind to the beginning of the top-level code.
163-
restoreParserPosition(BeginParserPosition);
146+
// Set the parser position to the start of the delayed decl or the body.
147+
restoreParserPosition(getParserPosition(info.BodyPos));
164148

165149
// Do not delay parsing in the second pass.
166150
llvm::SaveAndRestore<bool> DisableDelayedBody(DelayBodyParsing, false);

lib/Sema/TypeCheckStmt.cpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2126,15 +2126,11 @@ TypeCheckFunctionBodyUntilRequest::evaluate(Evaluator &evaluator,
21262126
builderType);
21272127
if (!body)
21282128
return true;
2129-
} else if (func->hasSingleExpressionBody()) {
2130-
auto resultTypeLoc = func->getBodyResultTypeLoc();
2131-
auto expr = func->getSingleExpressionBody();
2132-
2133-
if (resultTypeLoc.isNull() || resultTypeLoc.getType()->isVoid()) {
2134-
// The function returns void. We don't need an explicit return, no matter
2135-
// what the type of the expression is. Take the inserted return back out.
2136-
body->setFirstElement(expr);
2137-
}
2129+
} else if (func->hasSingleExpressionBody() &&
2130+
func->getResultInterfaceType()->isVoid()) {
2131+
// The function returns void. We don't need an explicit return, no matter
2132+
// what the type of the expression is. Take the inserted return back out.
2133+
body->setFirstElement(func->getSingleExpressionBody());
21382134
}
21392135
} else if (isa<ConstructorDecl>(AFD) &&
21402136
(body->empty() ||

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)