Index: clang-tools-extra/trunk/clangd/index/Background.cpp =================================================================== --- clang-tools-extra/trunk/clangd/index/Background.cpp +++ clang-tools-extra/trunk/clangd/index/Background.cpp @@ -246,6 +246,7 @@ IndexFileOut Shard; Shard.Symbols = SS.get(); Shard.Refs = RS.get(); + Shard.Digest = &Hash; if (auto Error = IndexStorage->storeShard(Path, Shard)) elog("Failed to write background-index shard for file {0}: {1}", Path, std::move(Error)); Index: clang-tools-extra/trunk/clangd/index/Serialization.h =================================================================== --- clang-tools-extra/trunk/clangd/index/Serialization.h +++ clang-tools-extra/trunk/clangd/index/Serialization.h @@ -39,6 +39,8 @@ struct IndexFileIn { llvm::Optional Symbols; llvm::Optional Refs; + // Digest of the source file that generated the contents. + llvm::Optional> Digest; }; // Parse an index file. The input must be a RIFF or YAML file. llvm::Expected readIndexFile(llvm::StringRef); @@ -47,6 +49,8 @@ struct IndexFileOut { const SymbolSlab *Symbols = nullptr; const RefSlab *Refs = nullptr; + // Digest of the source file that generated the contents. + const std::array *Digest = nullptr; // TODO: Support serializing Dex posting lists. IndexFileFormat Format = IndexFileFormat::RIFF; Index: clang-tools-extra/trunk/clangd/index/Serialization.cpp =================================================================== --- clang-tools-extra/trunk/clangd/index/Serialization.cpp +++ clang-tools-extra/trunk/clangd/index/Serialization.cpp @@ -363,6 +363,13 @@ return Strings.takeError(); IndexFileIn Result; + if (Chunks.count("hash")) { + Reader Hash(Chunks.lookup("hash")); + llvm::StringRef Digest = Hash.consume(20); + Result.Digest.emplace(); + std::copy(Digest.bytes_begin(), Digest.bytes_end(), Result.Digest->begin()); + } + if (Chunks.count("symb")) { Reader SymbolReader(Chunks.lookup("symb")); SymbolSlab::Builder Symbols; @@ -399,6 +406,12 @@ } RIFF.Chunks.push_back({riff::fourCC("meta"), Meta}); + if (Data.Digest) { + llvm::StringRef Hash(reinterpret_cast(Data.Digest->data()), + Data.Digest->size()); + RIFF.Chunks.push_back({riff::fourCC("hash"), Hash}); + } + StringTableOut Strings; std::vector Symbols; for (const auto &Sym : *Data.Symbols) { Index: clang-tools-extra/trunk/unittests/clangd/BackgroundIndexTests.cpp =================================================================== --- clang-tools-extra/trunk/unittests/clangd/BackgroundIndexTests.cpp +++ clang-tools-extra/trunk/unittests/clangd/BackgroundIndexTests.cpp @@ -121,8 +121,10 @@ void f_b(); class A_CC {}; )cpp"; - FS.Files[testPath("root/A.cc")] = - "#include \"A.h\"\nvoid g() { (void)common; }"; + std::string A_CC = "#include \"A.h\"\nvoid g() { (void)common; }"; + FS.Files[testPath("root/A.cc")] = A_CC; + auto Digest = llvm::SHA1::hash( + {reinterpret_cast(A_CC.data()), A_CC.size()}); llvm::StringMap Storage; size_t CacheHits = 0; @@ -156,6 +158,7 @@ EXPECT_NE(ShardSource, nullptr); EXPECT_THAT(*ShardSource->Symbols, UnorderedElementsAre()); EXPECT_THAT(*ShardSource->Refs, RefsAre({FileURI("unittest:///root/A.cc")})); + EXPECT_EQ(*ShardSource->Digest, Digest); } } // namespace clangd Index: clang-tools-extra/trunk/unittests/clangd/SerializationTests.cpp =================================================================== --- clang-tools-extra/trunk/unittests/clangd/SerializationTests.cpp +++ clang-tools-extra/trunk/unittests/clangd/SerializationTests.cpp @@ -9,6 +9,7 @@ #include "index/Index.h" #include "index/Serialization.h" +#include "llvm/Support/SHA1.h" #include "llvm/Support/ScopedPrinter.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -172,6 +173,33 @@ UnorderedElementsAreArray(YAMLFromRefs(*In->Refs))); } +TEST(SerializationTest, HashTest) { + auto In = readIndexFile(YAML); + EXPECT_TRUE(bool(In)) << In.takeError(); + + std::string TestContent("TESTCONTENT"); + auto Digest = + llvm::SHA1::hash({reinterpret_cast(TestContent.data()), + TestContent.size()}); + // Write to binary format, and parse again. + IndexFileOut Out(*In); + Out.Format = IndexFileFormat::RIFF; + Out.Digest = &Digest; + std::string Serialized = to_string(Out); + + auto In2 = readIndexFile(Serialized); + ASSERT_TRUE(bool(In2)) << In.takeError(); + ASSERT_EQ(In2->Digest, Digest); + ASSERT_TRUE(In2->Symbols); + ASSERT_TRUE(In2->Refs); + + // Assert the YAML serializations match, for nice comparisons and diffs. + EXPECT_THAT(YAMLFromSymbols(*In2->Symbols), + UnorderedElementsAreArray(YAMLFromSymbols(*In->Symbols))); + EXPECT_THAT(YAMLFromRefs(*In2->Refs), + UnorderedElementsAreArray(YAMLFromRefs(*In->Refs))); +} + } // namespace } // namespace clangd } // namespace clang