Skip to content

Commit c5a4af3

Browse files
authored
Merge pull request #33421 from rintaro/ast-func-oriignalsourcerange
[AST] Formalize getBodySourceRange() for fast completion
2 parents 4b8bbf7 + ee6c6f4 commit c5a4af3

File tree

5 files changed

+78
-16
lines changed

5 files changed

+78
-16
lines changed

include/swift/AST/Decl.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5935,13 +5935,14 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
59355935

59365936
/// Note that parsing for the body was delayed.
59375937
void setBodyDelayed(SourceRange bodyRange) {
5938-
assert(getBodyKind() == BodyKind::None ||
5939-
getBodyKind() == BodyKind::Skipped);
5938+
assert(getBodyKind() == BodyKind::None);
59405939
assert(bodyRange.isValid());
59415940
BodyRange = bodyRange;
59425941
setBodyKind(BodyKind::Unparsed);
59435942
}
59445943

5944+
void setBodyToBeReparsed(SourceRange bodyRange);
5945+
59455946
/// Provide the parsed body for the function.
59465947
void setBodyParsed(BraceStmt *S) {
59475948
setBody(S, BodyKind::Parsed);
@@ -6007,6 +6008,19 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
60076008
/// Retrieve the source range of the function body.
60086009
SourceRange getBodySourceRange() const;
60096010

6011+
/// Keep current \c getBodySourceRange() as the "original" body source range
6012+
/// iff the this method hasn't been called on this object. The current body
6013+
/// source range must be in the same buffer as the location of the declaration
6014+
/// itself.
6015+
void keepOriginalBodySourceRange();
6016+
6017+
/// Retrieve the source range of the *original* function body.
6018+
///
6019+
/// This may be different from \c getBodySourceRange() that returns the source
6020+
/// range of the *current* body. It happens when the body is parsed from other
6021+
/// source buffers for e.g. code-completion.
6022+
SourceRange getOriginalBodySourceRange() const;
6023+
60106024
/// Retrieve the source range of the function declaration name + patterns.
60116025
SourceRange getSignatureSourceRange() const;
60126026

lib/AST/ASTContext.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,10 @@ struct ASTContext::Implementation {
339339
/// LiteralExprs in fully-checked AST.
340340
llvm::DenseMap<const NominalTypeDecl *, ConcreteDeclRef> BuiltinInitWitness;
341341

342+
/// Mapping from the function decl to its original body's source range. This
343+
/// is populated if the body is reparsed from other source buffers.
344+
llvm::DenseMap<const AbstractFunctionDecl *, SourceRange> OriginalBodySourceRanges;
345+
342346
/// Structure that captures data that is segregated into different
343347
/// arenas.
344348
struct Arena {
@@ -4778,6 +4782,36 @@ void VarDecl::setOriginalWrappedProperty(VarDecl *originalProperty) {
47784782
ctx.getImpl().OriginalWrappedProperties[this] = originalProperty;
47794783
}
47804784

4785+
#ifndef NDEBUG
4786+
static bool isSourceLocInOrignalBuffer(const Decl *D, SourceLoc Loc) {
4787+
assert(Loc.isValid());
4788+
auto bufferID = D->getDeclContext()->getParentSourceFile()->getBufferID();
4789+
assert(bufferID.hasValue() && "Source buffer ID must be set");
4790+
auto &SM = D->getASTContext().SourceMgr;
4791+
return SM.getRangeForBuffer(*bufferID).contains(Loc);
4792+
}
4793+
#endif
4794+
4795+
void AbstractFunctionDecl::keepOriginalBodySourceRange() {
4796+
auto &impl = getASTContext().getImpl();
4797+
auto result =
4798+
impl.OriginalBodySourceRanges.insert({this, getBodySourceRange()});
4799+
assert((!result.second ||
4800+
isSourceLocInOrignalBuffer(this, result.first->getSecond().Start)) &&
4801+
"This function must be called before setting new body range");
4802+
(void)result;
4803+
}
4804+
4805+
SourceRange AbstractFunctionDecl::getOriginalBodySourceRange() const {
4806+
auto &impl = getASTContext().getImpl();
4807+
auto found = impl.OriginalBodySourceRanges.find(this);
4808+
if (found != impl.OriginalBodySourceRanges.end()) {
4809+
return found->getSecond();
4810+
} else {
4811+
return getBodySourceRange();
4812+
}
4813+
}
4814+
47814815
IndexSubset *
47824816
IndexSubset::get(ASTContext &ctx, const SmallBitVector &indices) {
47834817
auto &foldingSet = ctx.getImpl().IndexSubsets;

lib/AST/Decl.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6726,6 +6726,20 @@ void AbstractFunctionDecl::setBody(BraceStmt *S, BodyKind NewBodyKind) {
67266726
}
67276727
}
67286728

6729+
void AbstractFunctionDecl::setBodyToBeReparsed(SourceRange bodyRange) {
6730+
assert(bodyRange.isValid());
6731+
assert(getBodyKind() == BodyKind::Unparsed ||
6732+
getBodyKind() == BodyKind::Parsed ||
6733+
getBodyKind() == BodyKind::TypeChecked);
6734+
assert(getASTContext().SourceMgr.rangeContainsTokenLoc(
6735+
bodyRange, getASTContext().SourceMgr.getCodeCompletionLoc()) &&
6736+
"This function is only intended to be used for code completion");
6737+
6738+
keepOriginalBodySourceRange();
6739+
BodyRange = bodyRange;
6740+
setBodyKind(BodyKind::Unparsed);
6741+
}
6742+
67296743
SourceRange AbstractFunctionDecl::getBodySourceRange() const {
67306744
switch (getBodyKind()) {
67316745
case BodyKind::None:
@@ -7386,7 +7400,7 @@ SourceRange FuncDecl::getSourceRange() const {
73867400
getBodyKind() == BodyKind::Skipped)
73877401
return { StartLoc, BodyRange.End };
73887402

7389-
SourceLoc RBraceLoc = getBodySourceRange().End;
7403+
SourceLoc RBraceLoc = getOriginalBodySourceRange().End;
73907404
if (RBraceLoc.isValid()) {
73917405
return { StartLoc, RBraceLoc };
73927406
}
@@ -7507,7 +7521,7 @@ SourceRange ConstructorDecl::getSourceRange() const {
75077521
if (isImplicit())
75087522
return getConstructorLoc();
75097523

7510-
SourceLoc End = getBodySourceRange().End;
7524+
SourceLoc End = getOriginalBodySourceRange().End;
75117525
if (End.isInvalid())
75127526
End = getGenericTrailingWhereClauseSourceRange().End;
75137527
if (End.isInvalid())
@@ -7733,7 +7747,7 @@ ConstructorDecl::getDelegatingOrChainedInitKind(DiagnosticEngine *diags,
77337747
}
77347748

77357749
SourceRange DestructorDecl::getSourceRange() const {
7736-
SourceLoc End = getBodySourceRange().End;
7750+
SourceLoc End = getOriginalBodySourceRange().End;
77377751
if (End.isInvalid()) {
77387752
End = getDestructorLoc();
77397753
}

lib/IDE/CompletionInstance.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,9 +411,12 @@ bool CompletionInstance::performCachedOperationIfPossible(
411411
oldInfo.PrevOffset = newInfo.PrevOffset;
412412
oldState->restoreCodeCompletionDelayedDeclState(oldInfo);
413413

414+
auto newBufferStart = SM.getRangeForBuffer(newBufferID).getStart();
415+
SourceRange newBodyRange(newBufferStart.getAdvancedLoc(newInfo.StartOffset),
416+
newBufferStart.getAdvancedLoc(newInfo.EndOffset));
417+
414418
auto *AFD = cast<AbstractFunctionDecl>(DC);
415-
if (AFD->isBodySkipped())
416-
AFD->setBodyDelayed(AFD->getBodySourceRange());
419+
AFD->setBodyToBeReparsed(newBodyRange);
417420

418421
traceDC = AFD;
419422
break;

lib/Parse/ParseDecl.cpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6248,15 +6248,12 @@ void Parser::consumeAbstractFunctionBody(AbstractFunctionDecl *AFD,
62486248

62496249
AFD->setBodyDelayed(BodyRange);
62506250

6251-
if (isCodeCompletionFirstPass()) {
6252-
if (SourceMgr.rangeContainsCodeCompletionLoc(BodyRange)) {
6253-
State->setCodeCompletionDelayedDeclState(
6254-
SourceMgr, L->getBufferID(),
6255-
CodeCompletionDelayedDeclKind::FunctionBody,
6256-
PD_Default, AFD, BodyRange, BeginParserPosition.PreviousLoc);
6257-
} else {
6258-
AFD->setBodySkipped(BodyRange);
6259-
}
6251+
if (isCodeCompletionFirstPass() &&
6252+
SourceMgr.rangeContainsCodeCompletionLoc(BodyRange)) {
6253+
State->setCodeCompletionDelayedDeclState(
6254+
SourceMgr, L->getBufferID(),
6255+
CodeCompletionDelayedDeclKind::FunctionBody,
6256+
PD_Default, AFD, BodyRange, BeginParserPosition.PreviousLoc);
62606257
}
62616258
}
62626259

0 commit comments

Comments
 (0)