[clangd] Only publish preamble after rebuilds

Don't invoke parsing callback for preamble if clangd is using a
previously built one.

Differential Revision: https://reviews.llvm.org/D112137
This commit is contained in:
Kadir Cetinkaya 2021-10-20 15:12:25 +02:00
parent 3efd2a0bec
commit c959da9ef3
No known key found for this signature in database
GPG Key ID: E39E36B8D2057ED6
2 changed files with 31 additions and 2 deletions

View File

@ -901,15 +901,17 @@ void ASTWorker::runWithAST(
void PreambleThread::build(Request Req) { void PreambleThread::build(Request Req) {
assert(Req.CI && "Got preamble request with null compiler invocation"); assert(Req.CI && "Got preamble request with null compiler invocation");
const ParseInputs &Inputs = Req.Inputs; const ParseInputs &Inputs = Req.Inputs;
bool ReusedPreamble = false;
Status.update([&](TUStatus &Status) { Status.update([&](TUStatus &Status) {
Status.PreambleActivity = PreambleAction::Building; Status.PreambleActivity = PreambleAction::Building;
}); });
auto _ = llvm::make_scope_exit([this, &Req] { auto _ = llvm::make_scope_exit([this, &Req, &ReusedPreamble] {
ASTPeer.updatePreamble(std::move(Req.CI), std::move(Req.Inputs), ASTPeer.updatePreamble(std::move(Req.CI), std::move(Req.Inputs),
LatestBuild, std::move(Req.CIDiags), LatestBuild, std::move(Req.CIDiags),
std::move(Req.WantDiags)); std::move(Req.WantDiags));
Callbacks.onPreamblePublished(FileName); if (!ReusedPreamble)
Callbacks.onPreamblePublished(FileName);
}); });
if (!LatestBuild || Inputs.ForceRebuild) { if (!LatestBuild || Inputs.ForceRebuild) {
@ -918,6 +920,7 @@ void PreambleThread::build(Request Req) {
} else if (isPreambleCompatible(*LatestBuild, Inputs, FileName, *Req.CI)) { } else if (isPreambleCompatible(*LatestBuild, Inputs, FileName, *Req.CI)) {
vlog("Reusing preamble version {0} for version {1} of {2}", vlog("Reusing preamble version {0} for version {1} of {2}",
LatestBuild->Version, Inputs.Version, FileName); LatestBuild->Version, Inputs.Version, FileName);
ReusedPreamble = true;
return; return;
} else { } else {
vlog("Rebuilding invalidated preamble for {0} version {1} (previous was " vlog("Rebuilding invalidated preamble for {0} version {1} (previous was "

View File

@ -1165,6 +1165,32 @@ TEST_F(TUSchedulerTests, AsyncPreambleThread) {
Ready.notify(); Ready.notify();
} }
TEST_F(TUSchedulerTests, OnlyPublishWhenPreambleIsBuilt) {
struct PreamblePublishCounter : public ParsingCallbacks {
PreamblePublishCounter(int &PreamblePublishCount)
: PreamblePublishCount(PreamblePublishCount) {}
void onPreamblePublished(PathRef File) override { ++PreamblePublishCount; }
int &PreamblePublishCount;
};
int PreamblePublishCount = 0;
TUScheduler S(CDB, optsForTest(),
std::make_unique<PreamblePublishCounter>(PreamblePublishCount));
Path File = testPath("foo.cpp");
S.update(File, getInputs(File, ""), WantDiagnostics::Auto);
S.blockUntilIdle(timeoutSeconds(10));
EXPECT_EQ(PreamblePublishCount, 1);
// Same contents, no publish.
S.update(File, getInputs(File, ""), WantDiagnostics::Auto);
S.blockUntilIdle(timeoutSeconds(10));
EXPECT_EQ(PreamblePublishCount, 1);
// New contents, should publish.
S.update(File, getInputs(File, "#define FOO"), WantDiagnostics::Auto);
S.blockUntilIdle(timeoutSeconds(10));
EXPECT_EQ(PreamblePublishCount, 2);
}
// If a header file is missing from the CDB (or inferred using heuristics), and // If a header file is missing from the CDB (or inferred using heuristics), and
// it's included by another open file, then we parse it using that files flags. // it's included by another open file, then we parse it using that files flags.
TEST_F(TUSchedulerTests, IncluderCache) { TEST_F(TUSchedulerTests, IncluderCache) {