Skip to content

Commit 037ddc9

Browse files
committed
[CursorInfo] Re-use already built ASTs ahead of currently building ones
Resolves rdar://110344363.
1 parent 3676379 commit 037ddc9

File tree

2 files changed

+42
-9
lines changed

2 files changed

+42
-9
lines changed

test/SourceKit/CursorInfo/cursor_after_edit.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@
88
// RUN: %sourcekitd-test \
99
// RUN: -req=open -text-input %t/empty.swift %t/func.swift -- %t/func.swift == \
1010
// RUN: -req=edit -offset=0 -length=0 -replace="func foo() {}" -req-opts=enablesyntaxmap=0,enablesubstructure=0,enablediagnostics=0 %t/func.swift -- %t/func.swift == \
11-
// RUN: -req=cursor -offset=5 %t/func.swift -- %t/func.swift
11+
// RUN: -req=cursor -offset=5 %t/func.swift -- %t/func.swift == \
12+
// RUN: -req=edit -offset=0 -length=0 -replace="// some comment\n" -req-opts=enablesyntaxmap=0,enablesubstructure=0,enablediagnostics=0 %t/func.swift -- %t/func.swift == \
13+
// RUN: -req=cursor -offset=21 %t/func.swift -- %t/func.swift

tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,30 +1219,61 @@ bool ASTBuildOperation::addConsumer(SwiftASTConsumerRef Consumer) {
12191219
return true;
12201220
}
12211221

1222+
/// Returns a build operation that `Consumer` can use, in order of the
1223+
/// following:
1224+
/// 1. The latest finished build operation that either exactly matches, or
1225+
/// can be used with snapshots
1226+
/// 2. If none, the latest in-progress build operation with the same
1227+
/// conditions
1228+
/// 3. `nullptr` otherwise
12221229
ASTBuildOperationRef ASTProducer::getBuildOperationForConsumer(
12231230
SwiftASTConsumerRef Consumer,
12241231
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
12251232
SwiftASTManagerRef Mgr) {
1233+
ASTBuildOperationRef LatestUsableOp;
1234+
Statistic *StatCount = nullptr;
12261235
for (auto &BuildOp : llvm::reverse(BuildOperations)) {
1227-
if (BuildOp->isCancelled()) {
1236+
if (BuildOp->isCancelled())
1237+
continue;
1238+
1239+
// No point checking for a match, we already have one - we're just looking
1240+
// for a finished operation that can be used with the file contents of
1241+
// `BuildOp` at this point (which we will prefer over an incomplete
1242+
// operation, whether that exactly matches or not).
1243+
if (LatestUsableOp && !BuildOp->isFinished())
1244+
continue;
1245+
1246+
// Check for an exact match
1247+
if (BuildOp->matchesSourceState(FileSystem)) {
1248+
LatestUsableOp = BuildOp;
1249+
StatCount = &Mgr->Impl.Stats->numASTCacheHits;
1250+
if (BuildOp->isFinished())
1251+
break;
12281252
continue;
12291253
}
1254+
1255+
// Check for whether the operation can be used taking into account
1256+
// snapshots
12301257
std::vector<ImmutableTextSnapshotRef> Snapshots;
12311258
Snapshots.reserve(BuildOp->getFileContents().size());
12321259
for (auto &FileContent : BuildOp->getFileContents()) {
12331260
if (FileContent.Snapshot) {
12341261
Snapshots.push_back(FileContent.Snapshot);
12351262
}
12361263
}
1237-
if (BuildOp->matchesSourceState(FileSystem)) {
1238-
++Mgr->Impl.Stats->numASTCacheHits;
1239-
return BuildOp;
1240-
} else if (Consumer->canUseASTWithSnapshots(Snapshots)) {
1241-
++Mgr->Impl.Stats->numASTsUsedWithSnapshots;
1242-
return BuildOp;
1264+
1265+
if (Consumer->canUseASTWithSnapshots(Snapshots)) {
1266+
LatestUsableOp = BuildOp;
1267+
StatCount = &Mgr->Impl.Stats->numASTsUsedWithSnapshots;
1268+
if (BuildOp->isFinished())
1269+
break;
12431270
}
12441271
}
1245-
return nullptr;
1272+
1273+
if (StatCount) {
1274+
++(*StatCount);
1275+
}
1276+
return LatestUsableOp;
12461277
}
12471278

12481279
void ASTProducer::enqueueConsumer(

0 commit comments

Comments
 (0)