diff --git a/clang-tools-extra/clangd/index/FileIndex.cpp b/clang-tools-extra/clangd/index/FileIndex.cpp --- a/clang-tools-extra/clangd/index/FileIndex.cpp +++ b/clang-tools-extra/clangd/index/FileIndex.cpp @@ -428,11 +428,17 @@ // We are using the key received from ShardedIndex, so it should always // exist. assert(IF); - PreambleSymbols.update( - Uri, std::make_unique(std::move(*IF->Symbols)), - std::make_unique(), - std::make_unique(std::move(*IF->Relations)), - /*CountReferences=*/false); + auto FilePath = URI::resolve(Uri, Path); + if (FilePath) { + PreambleSymbols.update( + *FilePath, std::make_unique(std::move(*IF->Symbols)), + std::make_unique(), + std::make_unique(std::move(*IF->Relations)), + /*CountReferences=*/false); + } else { + elog("Update preamble: could not resolve URI {0}: {1}", Uri, + FilePath.takeError()); + } } size_t IndexVersion = 0; auto NewIndex = diff --git a/clang-tools-extra/clangd/index/Merge.cpp b/clang-tools-extra/clangd/index/Merge.cpp --- a/clang-tools-extra/clangd/index/Merge.cpp +++ b/clang-tools-extra/clangd/index/Merge.cpp @@ -76,7 +76,11 @@ Dynamic->lookup(Req, [&](const Symbol &S) { B.insert(S); }); auto RemainingIDs = Req.IDs; + auto DynamicContainsFile = Dynamic->indexedFiles(); Static->lookup(Req, [&](const Symbol &S) { + if (DynamicContainsFile(S.Definition ? S.Definition.FileURI + : S.CanonicalDeclaration.FileURI)) + return; const Symbol *Sym = B.find(S.ID); RemainingIDs.erase(S.ID); if (!Sym) diff --git a/clang-tools-extra/clangd/unittests/IndexTests.cpp b/clang-tools-extra/clangd/unittests/IndexTests.cpp --- a/clang-tools-extra/clangd/unittests/IndexTests.cpp +++ b/clang-tools-extra/clangd/unittests/IndexTests.cpp @@ -290,6 +290,42 @@ EXPECT_THAT(lookup(M, {}), UnorderedElementsAre()); } +TEST(MergeIndexTest, LookupRemovedDefinition) { + FileIndex DynamicIndex; + FileIndex StaticIndex; + MergedIndex Merge(&DynamicIndex, &StaticIndex); + + const char *HeaderCode = "class Foo;"; + auto HeaderSymbols = TestTU::withHeaderCode(HeaderCode).headerSymbols(); + auto Foo = findSymbol(HeaderSymbols, "Foo"); + + // Build static index for test.cc with Foo definition + TestTU Test; + Test.HeaderCode = HeaderCode; + Test.Code = "class Foo {};"; + Test.Filename = "test.cc"; + auto AST = Test.build(); + StaticIndex.updateMain(testPath(Test.Filename), AST); + + // Remove Foo definition from test.cc, i.e. build dynamic index for test.cc + // without Foo definition. + Test.Code = "class Foo;"; + AST = Test.build(); + DynamicIndex.updateMain(testPath(Test.Filename), AST); + + // Merged index should not return the symbol definition if this definition + // location is inside a file from the dynamic index. + LookupRequest LookupReq; + LookupReq.IDs = {Foo.ID}; + std::vector Symbols; + Merge.lookup(LookupReq, [&](const Symbol &Sym) { Symbols.push_back(Sym); }); + ASSERT_EQ(Symbols.size(), 1u); + const auto &Sym = Symbols.front(); + EXPECT_FALSE(Sym.Definition); + EXPECT_EQ(std::string(Sym.CanonicalDeclaration.FileURI), + std::string("unittest:///TestTU.h")); +} + TEST(MergeIndexTest, FuzzyFind) { auto I = MemIndex::build(generateSymbols({"ns::A", "ns::B"}), RefSlab(), RelationSlab()),