Skip to content

Commit 63ef99e

Browse files
authored
Merge pull request #28014 from rintaro/ide-completion-secondpass-rdar56819166
[CodeCompleiton] Avoid walking the whole module to find the delayed func
2 parents 1184492 + 4b01a97 commit 63ef99e

File tree

7 files changed

+51
-92
lines changed

7 files changed

+51
-92
lines changed

include/swift/Parse/Parser.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,14 +167,14 @@ class Parser {
167167
LocalContext *CurLocalContext = nullptr;
168168

169169
bool isDelayedParsingEnabled() const {
170-
return DelayBodyParsing || SourceMgr.getCodeCompletionLoc().isValid();
170+
return DelayBodyParsing || isCodeCompletionFirstPass();
171171
}
172172

173173
void setCodeCompletionCallbacks(CodeCompletionCallbacks *Callbacks) {
174174
CodeCompletion = Callbacks;
175175
}
176176

177-
bool isCodeCompletionFirstPass() {
177+
bool isCodeCompletionFirstPass() const {
178178
return L->isCodeCompletion() && !CodeCompletion;
179179
}
180180

@@ -1057,6 +1057,7 @@ class Parser {
10571057
bool HasFuncKeyword = true);
10581058
void parseAbstractFunctionBody(AbstractFunctionDecl *AFD);
10591059
BraceStmt *parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD);
1060+
void parseAbstractFunctionBodyDelayed();
10601061
ParserResult<ProtocolDecl> parseDeclProtocol(ParseDeclOptions Flags,
10611062
DeclAttributes &Attributes);
10621063

include/swift/Parse/PersistentParserState.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class PersistentParserState {
5656
enum class DelayedDeclKind {
5757
TopLevelCodeDecl,
5858
Decl,
59+
FunctionBody,
5960
};
6061

6162
class DelayedDeclState {

include/swift/Subsystems.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,9 @@ namespace swift {
132132
PersistentParserState *PersistentState = nullptr,
133133
bool DelayBodyParsing = true);
134134

135-
/// Finish the parsing by going over the nodes that were delayed
136-
/// during the first parsing pass.
137-
void performDelayedParsing(DeclContext *DC,
138-
PersistentParserState &PersistentState,
139-
CodeCompletionCallbacksFactory *Factory);
135+
/// Finish the code completion.
136+
void performCodeCompletionSecondPass(PersistentParserState &PersistentState,
137+
CodeCompletionCallbacksFactory &Factory);
140138

141139
/// Lex and return a vector of tokens for the given buffer.
142140
std::vector<Token> tokenize(const LangOptions &LangOpts,

lib/Frontend/Frontend.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -869,8 +869,8 @@ void CompilerInstance::parseAndCheckTypesUpTo(
869869
});
870870

871871
if (Invocation.isCodeCompletion()) {
872-
performDelayedParsing(MainModule, *PersistentState.get(),
873-
Invocation.getCodeCompletionFactory());
872+
performCodeCompletionSecondPass(*PersistentState.get(),
873+
*Invocation.getCodeCompletionFactory());
874874
}
875875
finishTypeChecking(TypeCheckOptions);
876876
}

lib/IDE/REPLCodeCompletion.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ doCodeCompletion(SourceFile &SF, StringRef EnteredCode, unsigned *BufferID,
215215
performTypeChecking(SF, PersistentState.getTopLevelContext(), None,
216216
OriginalDeclCount);
217217

218-
performDelayedParsing(&SF, PersistentState, CompletionCallbacksFactory);
218+
performCodeCompletionSecondPass(PersistentState, *CompletionCallbacksFactory);
219219

220220
// Now we are done with code completion. Remove the declarations we
221221
// temporarily inserted.

lib/Parse/ParseDecl.cpp

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5394,11 +5394,16 @@ void Parser::consumeAbstractFunctionBody(AbstractFunctionDecl *AFD,
53945394

53955395
BodyRange.End = PreviousLoc;
53965396

5397-
if (SourceMgr.getCodeCompletionLoc().isInvalid() ||
5398-
SourceMgr.rangeContainsCodeCompletionLoc(BodyRange)) {
5399-
AFD->setBodyDelayed(BodyRange);
5400-
} else {
5401-
AFD->setBodySkipped(BodyRange);
5397+
AFD->setBodyDelayed(BodyRange);
5398+
5399+
if (isCodeCompletionFirstPass()) {
5400+
if (SourceMgr.rangeContainsCodeCompletionLoc(BodyRange)) {
5401+
State->delayDecl(PersistentParserState::DelayedDeclKind::FunctionBody,
5402+
PD_Default, AFD, BodyRange,
5403+
BeginParserPosition.PreviousLoc);
5404+
} else {
5405+
AFD->setBodySkipped(BodyRange);
5406+
}
54025407
}
54035408
}
54045409

@@ -5710,6 +5715,20 @@ BraceStmt *Parser::parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD) {
57105715
return parseBraceItemList(diag::func_decl_without_brace).getPtrOrNull();
57115716
}
57125717

5718+
/// Parse a delayed function body from the 'PersistentParserState'.
5719+
void Parser::parseAbstractFunctionBodyDelayed() {
5720+
auto DelayedState = State->takeDelayedDeclState();
5721+
assert(DelayedState.get() && "should have delayed state");
5722+
auto CD = DelayedState->ParentContext->getAsDecl();
5723+
auto AFD = cast<AbstractFunctionDecl>(CD);
5724+
5725+
// Eagarly parse local decls or nested function bodies inside the body.
5726+
llvm::SaveAndRestore<bool> DisableDelayedBody(DelayBodyParsing, false);
5727+
5728+
auto body = parseAbstractFunctionBodyDelayed(AFD);
5729+
AFD->setBodyParsed(body);
5730+
}
5731+
57135732
/// Parse a 'enum' declaration, returning true (and doing no token
57145733
/// skipping) on error.
57155734
///

lib/Parse/Parser.cpp

Lines changed: 17 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -110,75 +110,24 @@ using namespace swift::syntax;
110110

111111
void SILParserTUStateBase::anchor() { }
112112

113-
namespace {
114-
/// A visitor that does delayed parsing of function bodies.
115-
class ParseDelayedFunctionBodies : public ASTWalker {
116-
PersistentParserState &ParserState;
117-
CodeCompletionCallbacksFactory *CodeCompletionFactory;
118-
119-
public:
120-
ParseDelayedFunctionBodies(PersistentParserState &ParserState,
121-
CodeCompletionCallbacksFactory *Factory)
122-
: ParserState(ParserState), CodeCompletionFactory(Factory) {}
123-
124-
bool walkToDeclPre(Decl *D) override {
125-
if (auto AFD = dyn_cast<AbstractFunctionDecl>(D)) {
126-
if (AFD->getBodyKind() != FuncDecl::BodyKind::Unparsed)
127-
return false;
128-
parseFunctionBody(AFD);
129-
return true;
130-
}
131-
return true;
132-
}
133-
134-
private:
135-
void parseFunctionBody(AbstractFunctionDecl *AFD) {
136-
// FIXME: This duplicates the evaluation of
137-
// ParseAbstractFunctionBodyRequest, but installs a code completion
138-
// factory.
139-
assert(AFD->getBodyKind() == FuncDecl::BodyKind::Unparsed);
140-
141-
SourceFile &SF = *AFD->getDeclContext()->getParentSourceFile();
142-
SourceManager &SourceMgr = SF.getASTContext().SourceMgr;
143-
unsigned BufferID = SourceMgr.findBufferContainingLoc(AFD->getLoc());
144-
Parser TheParser(BufferID, SF, nullptr, &ParserState, nullptr,
145-
/*DelayBodyParsing=*/false);
146-
TheParser.SyntaxContext->disable();
147-
std::unique_ptr<CodeCompletionCallbacks> CodeCompletion;
148-
if (CodeCompletionFactory) {
149-
CodeCompletion.reset(
150-
CodeCompletionFactory->createCodeCompletionCallbacks(TheParser));
151-
TheParser.setCodeCompletionCallbacks(CodeCompletion.get());
152-
}
153-
auto body = TheParser.parseAbstractFunctionBodyDelayed(AFD);
154-
AFD->setBodyParsed(body);
155-
156-
if (CodeCompletion)
157-
CodeCompletion->doneParsing();
158-
}
159-
};
160-
161-
static void parseDelayedDecl(
162-
PersistentParserState &ParserState,
163-
CodeCompletionCallbacksFactory *CodeCompletionFactory) {
113+
void swift::performCodeCompletionSecondPass(
114+
PersistentParserState &ParserState,
115+
CodeCompletionCallbacksFactory &Factory) {
116+
SharedTimer timer("CodeCompletionSecondPass");
164117
if (!ParserState.hasDelayedDecl())
165118
return;
166119

167-
SourceFile &SF = *ParserState.getDelayedDeclContext()->getParentSourceFile();
168-
SourceManager &SourceMgr = SF.getASTContext().SourceMgr;
169-
unsigned BufferID =
170-
SourceMgr.findBufferContainingLoc(ParserState.getDelayedDeclLoc());
120+
auto &SF = *ParserState.getDelayedDeclContext()->getParentSourceFile();
121+
auto &SM = SF.getASTContext().SourceMgr;
122+
auto BufferID = SM.findBufferContainingLoc(ParserState.getDelayedDeclLoc());
171123
Parser TheParser(BufferID, SF, nullptr, &ParserState, nullptr);
172124

173125
// Disable libSyntax creation in the delayed parsing.
174126
TheParser.SyntaxContext->disable();
175127

176-
std::unique_ptr<CodeCompletionCallbacks> CodeCompletion;
177-
if (CodeCompletionFactory) {
178-
CodeCompletion.reset(
179-
CodeCompletionFactory->createCodeCompletionCallbacks(TheParser));
180-
TheParser.setCodeCompletionCallbacks(CodeCompletion.get());
181-
}
128+
std::unique_ptr<CodeCompletionCallbacks> CodeCompletion(
129+
Factory.createCodeCompletionCallbacks(TheParser));
130+
TheParser.setCodeCompletionCallbacks(CodeCompletion.get());
182131

183132
switch (ParserState.getDelayedDeclKind()) {
184133
case PersistentParserState::DelayedDeclKind::TopLevelCodeDecl:
@@ -188,13 +137,16 @@ static void parseDelayedDecl(
188137
case PersistentParserState::DelayedDeclKind::Decl:
189138
TheParser.parseDeclDelayed();
190139
break;
140+
141+
case PersistentParserState::DelayedDeclKind::FunctionBody: {
142+
TheParser.parseAbstractFunctionBodyDelayed();
143+
break;
191144
}
145+
}
146+
assert(!ParserState.hasDelayedDecl());
192147

193-
if (CodeCompletion)
194-
CodeCompletion->doneParsing();
148+
CodeCompletion->doneParsing();
195149
}
196-
} // unnamed namespace
197-
198150

199151
swift::Parser::BacktrackingScope::~BacktrackingScope() {
200152
if (Backtrack) {
@@ -203,18 +155,6 @@ swift::Parser::BacktrackingScope::~BacktrackingScope() {
203155
}
204156
}
205157

206-
void swift::performDelayedParsing(
207-
DeclContext *DC, PersistentParserState &PersistentState,
208-
CodeCompletionCallbacksFactory *CodeCompletionFactory) {
209-
SharedTimer timer("Parsing");
210-
ParseDelayedFunctionBodies Walker(PersistentState,
211-
CodeCompletionFactory);
212-
DC->walkContext(Walker);
213-
214-
if (CodeCompletionFactory)
215-
parseDelayedDecl(PersistentState, CodeCompletionFactory);
216-
}
217-
218158
/// Tokenizes a string literal, taking into account string interpolation.
219159
static void getStringPartTokens(const Token &Tok, const LangOptions &LangOpts,
220160
const SourceManager &SM,

0 commit comments

Comments
 (0)