Skip to content

Commit 1fbbc70

Browse files
authored
Merge pull request #66908 from bnbarham/cherry-reuse-cursor-ast
[5.9][CursorInfo] Re-use already built ASTs when possible
2 parents 517c487 + 40ebc9a commit 1fbbc70

File tree

7 files changed

+143
-67
lines changed

7 files changed

+143
-67
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: touch %t/empty.swift %t/func.swift
3+
4+
// Check that cursor info re-uses the underlying AST if it's able to based
5+
// off edit snapshots.
6+
7+
// RUN: %sourcekitd-test \
8+
// RUN: -shell -- echo '## State 1' == \
9+
// RUN: -req=open -text-input %t/empty.swift %t/func.swift -- %t/func.swift == \
10+
// RUN: -req=edit -offset=0 -length=0 -replace="func foo() {}" -req-opts=enablesyntaxmap=0,enablesubstructure=0,enablediagnostics=0,syntactic_only=1 %t/func.swift -- %t/func.swift == \
11+
// RUN: -req=cursor -offset=5 %t/func.swift -- %t/func.swift == \
12+
// RUN: -shell -- echo '## State 2' == \
13+
// RUN: -req=edit -offset=0 -length=0 -replace="/* some comment */ " -req-opts=enablesyntaxmap=0,enablesubstructure=0,enablediagnostics=0,syntactic_only=1 %t/func.swift -- %t/func.swift == \
14+
// RUN: -req=cursor -offset=24 %t/func.swift -- %t/func.swift | %FileCheck %s
15+
16+
// CHECK: ## State 1
17+
// CHECK: source.lang.swift.decl.function.free
18+
// CHECK: foo()
19+
// CHECK: DID REUSE AST CONTEXT: 0
20+
// CHECK: ## State 2
21+
// CHECK: source.lang.swift.decl.function.free
22+
// CHECK: foo()
23+
// CHECK: DID REUSE AST CONTEXT: 1

tools/SourceKit/include/SourceKit/Core/LangSupport.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1086,7 +1086,8 @@ class LangSupport {
10861086
Receiver) = 0;
10871087

10881088
virtual void
1089-
getNameInfo(StringRef Filename, unsigned Offset, NameTranslatingInfo &Input,
1089+
getNameInfo(StringRef PrimaryFilePath, StringRef InputBufferName,
1090+
unsigned Offset, NameTranslatingInfo &Input,
10901091
ArrayRef<const char *> Args,
10911092
SourceKitCancellationToken CancellationToken,
10921093
std::function<void(const RequestResult<NameTranslatingInfo> &)>

tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,30 +1240,61 @@ bool ASTBuildOperation::addConsumer(SwiftASTConsumerRef Consumer) {
12401240
return true;
12411241
}
12421242

1243+
/// Returns a build operation that `Consumer` can use, in order of the
1244+
/// following:
1245+
/// 1. The latest finished build operation that either exactly matches, or
1246+
/// can be used with snapshots
1247+
/// 2. If none, the latest in-progress build operation with the same
1248+
/// conditions
1249+
/// 3. `nullptr` otherwise
12431250
ASTBuildOperationRef ASTProducer::getBuildOperationForConsumer(
12441251
SwiftASTConsumerRef Consumer,
12451252
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
12461253
SwiftASTManagerRef Mgr) {
1254+
ASTBuildOperationRef LatestUsableOp;
1255+
Statistic *StatCount = nullptr;
12471256
for (auto &BuildOp : llvm::reverse(BuildOperations)) {
1248-
if (BuildOp->isCancelled()) {
1257+
if (BuildOp->isCancelled())
1258+
continue;
1259+
1260+
// No point checking for a match, we already have one - we're just looking
1261+
// for a finished operation that can be used with the file contents of
1262+
// `BuildOp` at this point (which we will prefer over an incomplete
1263+
// operation, whether that exactly matches or not).
1264+
if (LatestUsableOp && !BuildOp->isFinished())
1265+
continue;
1266+
1267+
// Check for an exact match
1268+
if (BuildOp->matchesSourceState(FileSystem)) {
1269+
LatestUsableOp = BuildOp;
1270+
StatCount = &Mgr->Impl.Stats->numASTCacheHits;
1271+
if (BuildOp->isFinished())
1272+
break;
12491273
continue;
12501274
}
1275+
1276+
// Check for whether the operation can be used taking into account
1277+
// snapshots
12511278
std::vector<ImmutableTextSnapshotRef> Snapshots;
12521279
Snapshots.reserve(BuildOp->getFileContents().size());
12531280
for (auto &FileContent : BuildOp->getFileContents()) {
12541281
if (FileContent.Snapshot) {
12551282
Snapshots.push_back(FileContent.Snapshot);
12561283
}
12571284
}
1258-
if (BuildOp->matchesSourceState(FileSystem)) {
1259-
++Mgr->Impl.Stats->numASTCacheHits;
1260-
return BuildOp;
1261-
} else if (Consumer->canUseASTWithSnapshots(Snapshots)) {
1262-
++Mgr->Impl.Stats->numASTsUsedWithSnapshots;
1263-
return BuildOp;
1285+
1286+
if (Consumer->canUseASTWithSnapshots(Snapshots)) {
1287+
LatestUsableOp = BuildOp;
1288+
StatCount = &Mgr->Impl.Stats->numASTsUsedWithSnapshots;
1289+
if (BuildOp->isFinished())
1290+
break;
12641291
}
12651292
}
1266-
return nullptr;
1293+
1294+
if (StatCount) {
1295+
++(*StatCount);
1296+
}
1297+
return LatestUsableOp;
12671298
}
12681299

12691300
void ASTProducer::enqueueConsumer(

tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,8 +660,9 @@ class SwiftLangSupport : public LangSupport {
660660
Receiver) override;
661661

662662
void getNameInfo(
663-
StringRef Filename, unsigned Offset, NameTranslatingInfo &Input,
664-
ArrayRef<const char *> Args, SourceKitCancellationToken CancellationToken,
663+
StringRef PrimaryFilePath, StringRef InputBufferName, unsigned Offset,
664+
NameTranslatingInfo &Input, ArrayRef<const char *> Args,
665+
SourceKitCancellationToken CancellationToken,
665666
std::function<void(const RequestResult<NameTranslatingInfo> &)> Receiver)
666667
override;
667668

0 commit comments

Comments
 (0)