2019-07-04 17:52:04 +08:00
|
|
|
#include "Headers.h"
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
#include "SyncAPI.h"
|
|
|
|
#include "TestFS.h"
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
#include "TestIndex.h"
|
2019-06-15 10:26:47 +08:00
|
|
|
#include "TestTU.h"
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
#include "index/Background.h"
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
#include "index/BackgroundRebuild.h"
|
2019-07-04 17:51:53 +08:00
|
|
|
#include "clang/Tooling/CompilationDatabase.h"
|
2018-11-16 17:03:56 +08:00
|
|
|
#include "llvm/Support/ScopedPrinter.h"
|
2018-12-18 23:39:33 +08:00
|
|
|
#include "llvm/Support/Threading.h"
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
#include "gmock/gmock.h"
|
|
|
|
#include "gtest/gtest.h"
|
2019-07-10 07:05:20 +08:00
|
|
|
#include <deque>
|
2018-12-18 23:39:33 +08:00
|
|
|
#include <thread>
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
|
2019-05-06 18:08:47 +08:00
|
|
|
using ::testing::_;
|
|
|
|
using ::testing::AllOf;
|
|
|
|
using ::testing::Contains;
|
|
|
|
using ::testing::ElementsAre;
|
|
|
|
using ::testing::Not;
|
|
|
|
using ::testing::UnorderedElementsAre;
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
|
|
|
|
|
|
|
MATCHER_P(Named, N, "") { return arg.Name == N; }
|
2018-11-14 19:55:45 +08:00
|
|
|
MATCHER(Declared, "") {
|
|
|
|
return !StringRef(arg.CanonicalDeclaration.FileURI).empty();
|
|
|
|
}
|
|
|
|
MATCHER(Defined, "") { return !StringRef(arg.Definition.FileURI).empty(); }
|
|
|
|
MATCHER_P(FileURI, F, "") { return StringRef(arg.Location.FileURI) == F; }
|
2019-05-06 18:08:47 +08:00
|
|
|
::testing::Matcher<const RefSlab &>
|
|
|
|
RefsAre(std::vector<::testing::Matcher<Ref>> Matchers) {
|
|
|
|
return ElementsAre(::testing::Pair(_, UnorderedElementsAreArray(Matchers)));
|
2018-11-06 18:55:21 +08:00
|
|
|
}
|
2018-12-04 19:31:57 +08:00
|
|
|
// URI cannot be empty since it references keys in the IncludeGraph.
|
|
|
|
MATCHER(EmptyIncludeNode, "") {
|
2019-07-04 17:52:04 +08:00
|
|
|
return arg.Flags == IncludeGraphNode::SourceFlag::None && !arg.URI.empty() &&
|
|
|
|
arg.Digest == FileDigest{{0}} && arg.DirectIncludes.empty();
|
2018-12-04 19:31:57 +08:00
|
|
|
}
|
2019-07-04 17:52:04 +08:00
|
|
|
|
|
|
|
MATCHER(HadErrors, "") {
|
|
|
|
return arg.Flags & IncludeGraphNode::SourceFlag::HadErrors;
|
|
|
|
}
|
|
|
|
|
2019-05-09 22:22:07 +08:00
|
|
|
MATCHER_P(NumReferences, N, "") { return arg.References == N; }
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
|
2018-11-16 17:03:56 +08:00
|
|
|
class MemoryShardStorage : public BackgroundIndexStorage {
|
|
|
|
mutable std::mutex StorageMu;
|
|
|
|
llvm::StringMap<std::string> &Storage;
|
|
|
|
size_t &CacheHits;
|
|
|
|
|
|
|
|
public:
|
|
|
|
MemoryShardStorage(llvm::StringMap<std::string> &Storage, size_t &CacheHits)
|
|
|
|
: Storage(Storage), CacheHits(CacheHits) {}
|
|
|
|
llvm::Error storeShard(llvm::StringRef ShardIdentifier,
|
|
|
|
IndexFileOut Shard) const override {
|
|
|
|
std::lock_guard<std::mutex> Lock(StorageMu);
|
2019-03-08 17:57:33 +08:00
|
|
|
AccessedPaths.insert(ShardIdentifier);
|
2018-11-16 17:03:56 +08:00
|
|
|
Storage[ShardIdentifier] = llvm::to_string(Shard);
|
|
|
|
return llvm::Error::success();
|
|
|
|
}
|
|
|
|
std::unique_ptr<IndexFileIn>
|
|
|
|
loadShard(llvm::StringRef ShardIdentifier) const override {
|
|
|
|
std::lock_guard<std::mutex> Lock(StorageMu);
|
2019-03-08 17:57:33 +08:00
|
|
|
AccessedPaths.insert(ShardIdentifier);
|
2018-11-16 17:03:56 +08:00
|
|
|
if (Storage.find(ShardIdentifier) == Storage.end()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
auto IndexFile = readIndexFile(Storage[ShardIdentifier]);
|
|
|
|
if (!IndexFile) {
|
|
|
|
ADD_FAILURE() << "Error while reading " << ShardIdentifier << ':'
|
|
|
|
<< IndexFile.takeError();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
CacheHits++;
|
2019-08-15 07:52:23 +08:00
|
|
|
return std::make_unique<IndexFileIn>(std::move(*IndexFile));
|
2018-11-16 17:03:56 +08:00
|
|
|
}
|
2019-03-08 17:57:33 +08:00
|
|
|
|
|
|
|
mutable llvm::StringSet<> AccessedPaths;
|
2018-11-16 17:03:56 +08:00
|
|
|
};
|
|
|
|
|
2018-11-27 20:09:13 +08:00
|
|
|
class BackgroundIndexTest : public ::testing::Test {
|
|
|
|
protected:
|
2019-07-11 21:34:38 +08:00
|
|
|
BackgroundIndexTest() { BackgroundQueue::preventThreadStarvationInTests(); }
|
2018-11-27 20:09:13 +08:00
|
|
|
};
|
|
|
|
|
2018-12-14 20:39:08 +08:00
|
|
|
TEST_F(BackgroundIndexTest, NoCrashOnErrorFile) {
|
|
|
|
MockFSProvider FS;
|
|
|
|
FS.Files[testPath("root/A.cc")] = "error file";
|
|
|
|
llvm::StringMap<std::string> Storage;
|
|
|
|
size_t CacheHits = 0;
|
|
|
|
MemoryShardStorage MSS(Storage, CacheHits);
|
|
|
|
OverlayCDB CDB(/*Base=*/nullptr);
|
2019-01-22 17:10:20 +08:00
|
|
|
BackgroundIndex Idx(Context::empty(), FS, CDB,
|
2018-12-14 20:39:08 +08:00
|
|
|
[&](llvm::StringRef) { return &MSS; });
|
|
|
|
|
|
|
|
tooling::CompileCommand Cmd;
|
|
|
|
Cmd.Filename = testPath("root/A.cc");
|
|
|
|
Cmd.Directory = testPath("root");
|
|
|
|
Cmd.CommandLine = {"clang++", "-DA=1", testPath("root/A.cc")};
|
|
|
|
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
|
|
|
|
|
|
|
|
ASSERT_TRUE(Idx.blockUntilIdleForTest());
|
|
|
|
}
|
|
|
|
|
2018-11-27 20:09:13 +08:00
|
|
|
TEST_F(BackgroundIndexTest, IndexTwoFiles) {
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
MockFSProvider FS;
|
|
|
|
// a.h yields different symbols when included by A.cc vs B.cc.
|
2018-11-06 18:55:21 +08:00
|
|
|
FS.Files[testPath("root/A.h")] = R"cpp(
|
|
|
|
void common();
|
|
|
|
void f_b();
|
|
|
|
#if A
|
|
|
|
class A_CC {};
|
|
|
|
#else
|
|
|
|
class B_CC{};
|
|
|
|
#endif
|
|
|
|
)cpp";
|
|
|
|
FS.Files[testPath("root/A.cc")] =
|
|
|
|
"#include \"A.h\"\nvoid g() { (void)common; }";
|
|
|
|
FS.Files[testPath("root/B.cc")] =
|
|
|
|
R"cpp(
|
|
|
|
#define A 0
|
|
|
|
#include "A.h"
|
|
|
|
void f_b() {
|
|
|
|
(void)common;
|
2019-05-09 22:22:07 +08:00
|
|
|
(void)common;
|
|
|
|
(void)common;
|
|
|
|
(void)common;
|
2018-11-06 18:55:21 +08:00
|
|
|
})cpp";
|
2018-11-16 17:03:56 +08:00
|
|
|
llvm::StringMap<std::string> Storage;
|
|
|
|
size_t CacheHits = 0;
|
|
|
|
MemoryShardStorage MSS(Storage, CacheHits);
|
[clangd] Auto-index watches global CDB for changes.
Summary:
Instead of receiving compilation commands, auto-index is triggered by just
filenames to reindex, and gets commands from the global comp DB internally.
This has advantages:
- more of the work can be done asynchronously (fetching compilation commands
upfront can be slow for large CDBs)
- we get access to the CDB which can be used to retrieve interpolated commands
for headers (useful in some cases where the original TU goes away)
- fits nicely with the filename-only change observation from r347297
The interface to GlobalCompilationDatabase gets extended: when retrieving a
compile command, the GCDB can optionally report the project the file belongs to.
This naturally fits together with getCompileCommand: it's hard to implement one
without the other. But because most callers don't care, I've ended up with an
awkward optional-out-param-in-virtual method pattern - maybe there's a better
one.
This is the main missing integration point between ClangdServer and
BackgroundIndex, after this we should be able to add an auto-index flag.
Reviewers: ioeric, kadircet
Subscribers: MaskRay, jkorous, arphaman, cfe-commits, ilya-biryukov
Differential Revision: https://reviews.llvm.org/D54865
llvm-svn: 347538
2018-11-26 17:51:50 +08:00
|
|
|
OverlayCDB CDB(/*Base=*/nullptr);
|
2019-01-22 17:10:20 +08:00
|
|
|
BackgroundIndex Idx(Context::empty(), FS, CDB,
|
2018-11-16 17:03:56 +08:00
|
|
|
[&](llvm::StringRef) { return &MSS; });
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
|
|
|
|
tooling::CompileCommand Cmd;
|
|
|
|
Cmd.Filename = testPath("root/A.cc");
|
|
|
|
Cmd.Directory = testPath("root");
|
2018-11-06 18:55:21 +08:00
|
|
|
Cmd.CommandLine = {"clang++", "-DA=1", testPath("root/A.cc")};
|
2018-12-04 19:31:57 +08:00
|
|
|
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
|
2018-11-06 18:55:21 +08:00
|
|
|
|
[clangd] Enable auto-index behind a flag.
Summary:
Ownership and configuration:
The auto-index (background index) is maintained by ClangdServer, like Dynamic.
(This means ClangdServer will be able to enqueue preamble indexing in future).
For now it's enabled by a simple boolean flag in ClangdServer::Options, but
we probably want to eventually allow injecting the storage strategy.
New 'sync' command:
In order to meaningfully test the integration (not just unit-test components)
we need a way for tests to ensure the asynchronous index reads/writes occur
before a certain point.
Because these tests and assertions are few, I think exposing an explicit "sync"
command for use in tests is simpler than allowing threading to be completely
disabled in the background index (as we do for TUScheduler).
Bugs:
I fixed a couple of trivial bugs I found while testing, but there's one I can't.
JSONCompilationDatabase::getAllFiles() may return relative paths, and currently
we trigger an assertion that assumes they are absolute.
There's no efficient way to resolve them (you have to retrieve the corresponding
command and then resolve against its directory property). In general I think
this behavior is broken and we should fix it in JSONCompilationDatabase and
require CompilationDatabase::getAllFiles() to be absolute.
Reviewers: kadircet
Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D54894
llvm-svn: 347567
2018-11-27 00:00:11 +08:00
|
|
|
ASSERT_TRUE(Idx.blockUntilIdleForTest());
|
2019-05-09 22:22:07 +08:00
|
|
|
EXPECT_THAT(runFuzzyFind(Idx, ""),
|
|
|
|
UnorderedElementsAre(AllOf(Named("common"), NumReferences(1U)),
|
|
|
|
AllOf(Named("A_CC"), NumReferences(0U)),
|
|
|
|
AllOf(Named("g"), NumReferences(0U)),
|
|
|
|
AllOf(Named("f_b"), Declared(),
|
|
|
|
Not(Defined()), NumReferences(0U))));
|
2018-11-06 18:55:21 +08:00
|
|
|
|
|
|
|
Cmd.Filename = testPath("root/B.cc");
|
|
|
|
Cmd.CommandLine = {"clang++", Cmd.Filename};
|
2019-05-09 22:22:07 +08:00
|
|
|
CDB.setCompileCommand(testPath("root/B.cc"), Cmd);
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
|
[clangd] Enable auto-index behind a flag.
Summary:
Ownership and configuration:
The auto-index (background index) is maintained by ClangdServer, like Dynamic.
(This means ClangdServer will be able to enqueue preamble indexing in future).
For now it's enabled by a simple boolean flag in ClangdServer::Options, but
we probably want to eventually allow injecting the storage strategy.
New 'sync' command:
In order to meaningfully test the integration (not just unit-test components)
we need a way for tests to ensure the asynchronous index reads/writes occur
before a certain point.
Because these tests and assertions are few, I think exposing an explicit "sync"
command for use in tests is simpler than allowing threading to be completely
disabled in the background index (as we do for TUScheduler).
Bugs:
I fixed a couple of trivial bugs I found while testing, but there's one I can't.
JSONCompilationDatabase::getAllFiles() may return relative paths, and currently
we trigger an assertion that assumes they are absolute.
There's no efficient way to resolve them (you have to retrieve the corresponding
command and then resolve against its directory property). In general I think
this behavior is broken and we should fix it in JSONCompilationDatabase and
require CompilationDatabase::getAllFiles() to be absolute.
Reviewers: kadircet
Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D54894
llvm-svn: 347567
2018-11-27 00:00:11 +08:00
|
|
|
ASSERT_TRUE(Idx.blockUntilIdleForTest());
|
2018-11-06 18:55:21 +08:00
|
|
|
// B_CC is dropped as we don't collect symbols from A.h in this compilation.
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
EXPECT_THAT(runFuzzyFind(Idx, ""),
|
2019-05-09 22:22:07 +08:00
|
|
|
UnorderedElementsAre(AllOf(Named("common"), NumReferences(5U)),
|
|
|
|
AllOf(Named("A_CC"), NumReferences(0U)),
|
|
|
|
AllOf(Named("g"), NumReferences(0U)),
|
|
|
|
AllOf(Named("f_b"), Declared(), Defined(),
|
|
|
|
NumReferences(1U))));
|
2018-11-06 18:55:21 +08:00
|
|
|
|
|
|
|
auto Syms = runFuzzyFind(Idx, "common");
|
|
|
|
EXPECT_THAT(Syms, UnorderedElementsAre(Named("common")));
|
|
|
|
auto Common = *Syms.begin();
|
|
|
|
EXPECT_THAT(getRefs(Idx, Common.ID),
|
|
|
|
RefsAre({FileURI("unittest:///root/A.h"),
|
|
|
|
FileURI("unittest:///root/A.cc"),
|
2019-05-09 22:22:07 +08:00
|
|
|
FileURI("unittest:///root/B.cc"),
|
|
|
|
FileURI("unittest:///root/B.cc"),
|
|
|
|
FileURI("unittest:///root/B.cc"),
|
2018-11-06 18:55:21 +08:00
|
|
|
FileURI("unittest:///root/B.cc")}));
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
}
|
|
|
|
|
2019-01-11 01:03:04 +08:00
|
|
|
TEST_F(BackgroundIndexTest, ShardStorageTest) {
|
2018-11-16 17:03:56 +08:00
|
|
|
MockFSProvider FS;
|
|
|
|
FS.Files[testPath("root/A.h")] = R"cpp(
|
|
|
|
void common();
|
|
|
|
void f_b();
|
|
|
|
class A_CC {};
|
|
|
|
)cpp";
|
2019-06-15 10:26:47 +08:00
|
|
|
std::string A_CC = "";
|
|
|
|
FS.Files[testPath("root/A.cc")] = R"cpp(
|
|
|
|
#include "A.h"
|
|
|
|
void g() { (void)common; }
|
|
|
|
class B_CC : public A_CC {};
|
|
|
|
)cpp";
|
2018-11-16 17:03:56 +08:00
|
|
|
|
|
|
|
llvm::StringMap<std::string> Storage;
|
|
|
|
size_t CacheHits = 0;
|
|
|
|
MemoryShardStorage MSS(Storage, CacheHits);
|
|
|
|
|
|
|
|
tooling::CompileCommand Cmd;
|
|
|
|
Cmd.Filename = testPath("root/A.cc");
|
|
|
|
Cmd.Directory = testPath("root");
|
|
|
|
Cmd.CommandLine = {"clang++", testPath("root/A.cc")};
|
|
|
|
// Check nothing is loaded from Storage, but A.cc and A.h has been stored.
|
|
|
|
{
|
[clangd] Auto-index watches global CDB for changes.
Summary:
Instead of receiving compilation commands, auto-index is triggered by just
filenames to reindex, and gets commands from the global comp DB internally.
This has advantages:
- more of the work can be done asynchronously (fetching compilation commands
upfront can be slow for large CDBs)
- we get access to the CDB which can be used to retrieve interpolated commands
for headers (useful in some cases where the original TU goes away)
- fits nicely with the filename-only change observation from r347297
The interface to GlobalCompilationDatabase gets extended: when retrieving a
compile command, the GCDB can optionally report the project the file belongs to.
This naturally fits together with getCompileCommand: it's hard to implement one
without the other. But because most callers don't care, I've ended up with an
awkward optional-out-param-in-virtual method pattern - maybe there's a better
one.
This is the main missing integration point between ClangdServer and
BackgroundIndex, after this we should be able to add an auto-index flag.
Reviewers: ioeric, kadircet
Subscribers: MaskRay, jkorous, arphaman, cfe-commits, ilya-biryukov
Differential Revision: https://reviews.llvm.org/D54865
llvm-svn: 347538
2018-11-26 17:51:50 +08:00
|
|
|
OverlayCDB CDB(/*Base=*/nullptr);
|
2019-01-22 17:10:20 +08:00
|
|
|
BackgroundIndex Idx(Context::empty(), FS, CDB,
|
2018-11-16 17:03:56 +08:00
|
|
|
[&](llvm::StringRef) { return &MSS; });
|
2018-12-04 19:31:57 +08:00
|
|
|
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
|
[clangd] Enable auto-index behind a flag.
Summary:
Ownership and configuration:
The auto-index (background index) is maintained by ClangdServer, like Dynamic.
(This means ClangdServer will be able to enqueue preamble indexing in future).
For now it's enabled by a simple boolean flag in ClangdServer::Options, but
we probably want to eventually allow injecting the storage strategy.
New 'sync' command:
In order to meaningfully test the integration (not just unit-test components)
we need a way for tests to ensure the asynchronous index reads/writes occur
before a certain point.
Because these tests and assertions are few, I think exposing an explicit "sync"
command for use in tests is simpler than allowing threading to be completely
disabled in the background index (as we do for TUScheduler).
Bugs:
I fixed a couple of trivial bugs I found while testing, but there's one I can't.
JSONCompilationDatabase::getAllFiles() may return relative paths, and currently
we trigger an assertion that assumes they are absolute.
There's no efficient way to resolve them (you have to retrieve the corresponding
command and then resolve against its directory property). In general I think
this behavior is broken and we should fix it in JSONCompilationDatabase and
require CompilationDatabase::getAllFiles() to be absolute.
Reviewers: kadircet
Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D54894
llvm-svn: 347567
2018-11-27 00:00:11 +08:00
|
|
|
ASSERT_TRUE(Idx.blockUntilIdleForTest());
|
2018-11-16 17:03:56 +08:00
|
|
|
}
|
|
|
|
EXPECT_EQ(CacheHits, 0U);
|
|
|
|
EXPECT_EQ(Storage.size(), 2U);
|
|
|
|
|
2019-01-11 01:03:04 +08:00
|
|
|
{
|
|
|
|
OverlayCDB CDB(/*Base=*/nullptr);
|
2019-01-22 17:10:20 +08:00
|
|
|
BackgroundIndex Idx(Context::empty(), FS, CDB,
|
2019-01-11 01:03:04 +08:00
|
|
|
[&](llvm::StringRef) { return &MSS; });
|
2019-07-19 18:18:52 +08:00
|
|
|
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
|
2019-01-11 01:03:04 +08:00
|
|
|
ASSERT_TRUE(Idx.blockUntilIdleForTest());
|
|
|
|
}
|
|
|
|
EXPECT_EQ(CacheHits, 2U); // Check both A.cc and A.h loaded from cache.
|
|
|
|
EXPECT_EQ(Storage.size(), 2U);
|
|
|
|
|
2018-11-16 17:03:56 +08:00
|
|
|
auto ShardHeader = MSS.loadShard(testPath("root/A.h"));
|
|
|
|
EXPECT_NE(ShardHeader, nullptr);
|
|
|
|
EXPECT_THAT(
|
|
|
|
*ShardHeader->Symbols,
|
|
|
|
UnorderedElementsAre(Named("common"), Named("A_CC"),
|
|
|
|
AllOf(Named("f_b"), Declared(), Not(Defined()))));
|
|
|
|
for (const auto &Ref : *ShardHeader->Refs)
|
|
|
|
EXPECT_THAT(Ref.second,
|
|
|
|
UnorderedElementsAre(FileURI("unittest:///root/A.h")));
|
|
|
|
|
|
|
|
auto ShardSource = MSS.loadShard(testPath("root/A.cc"));
|
|
|
|
EXPECT_NE(ShardSource, nullptr);
|
2019-06-15 10:26:47 +08:00
|
|
|
EXPECT_THAT(*ShardSource->Symbols,
|
|
|
|
UnorderedElementsAre(Named("g"), Named("B_CC")));
|
|
|
|
for (const auto &Ref : *ShardSource->Refs)
|
|
|
|
EXPECT_THAT(Ref.second,
|
|
|
|
UnorderedElementsAre(FileURI("unittest:///root/A.cc")));
|
|
|
|
|
|
|
|
// The BaseOf relationship between A_CC and B_CC is stored in the file
|
|
|
|
// containing the definition of the subject (A_CC)
|
|
|
|
SymbolID A = findSymbol(*ShardHeader->Symbols, "A_CC").ID;
|
|
|
|
SymbolID B = findSymbol(*ShardSource->Symbols, "B_CC").ID;
|
|
|
|
EXPECT_THAT(
|
|
|
|
*ShardHeader->Relations,
|
|
|
|
UnorderedElementsAre(Relation{A, index::SymbolRole::RelationBaseOf, B}));
|
|
|
|
// (and not in the file containing the definition of the object (B_CC)).
|
|
|
|
EXPECT_EQ(ShardSource->Relations->size(), 0u);
|
2018-11-16 17:03:56 +08:00
|
|
|
}
|
|
|
|
|
2018-12-04 19:31:57 +08:00
|
|
|
TEST_F(BackgroundIndexTest, DirectIncludesTest) {
|
|
|
|
MockFSProvider FS;
|
|
|
|
FS.Files[testPath("root/B.h")] = "";
|
|
|
|
FS.Files[testPath("root/A.h")] = R"cpp(
|
|
|
|
#include "B.h"
|
|
|
|
void common();
|
|
|
|
void f_b();
|
|
|
|
class A_CC {};
|
|
|
|
)cpp";
|
|
|
|
std::string A_CC = "#include \"A.h\"\nvoid g() { (void)common; }";
|
|
|
|
FS.Files[testPath("root/A.cc")] = A_CC;
|
|
|
|
|
|
|
|
llvm::StringMap<std::string> Storage;
|
|
|
|
size_t CacheHits = 0;
|
|
|
|
MemoryShardStorage MSS(Storage, CacheHits);
|
|
|
|
|
|
|
|
tooling::CompileCommand Cmd;
|
|
|
|
Cmd.Filename = testPath("root/A.cc");
|
|
|
|
Cmd.Directory = testPath("root");
|
|
|
|
Cmd.CommandLine = {"clang++", testPath("root/A.cc")};
|
|
|
|
{
|
|
|
|
OverlayCDB CDB(/*Base=*/nullptr);
|
2019-01-22 17:10:20 +08:00
|
|
|
BackgroundIndex Idx(Context::empty(), FS, CDB,
|
2018-12-04 19:31:57 +08:00
|
|
|
[&](llvm::StringRef) { return &MSS; });
|
|
|
|
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
|
|
|
|
ASSERT_TRUE(Idx.blockUntilIdleForTest());
|
|
|
|
}
|
|
|
|
|
|
|
|
auto ShardSource = MSS.loadShard(testPath("root/A.cc"));
|
|
|
|
EXPECT_TRUE(ShardSource->Sources);
|
|
|
|
EXPECT_EQ(ShardSource->Sources->size(), 2U); // A.cc, A.h
|
|
|
|
EXPECT_THAT(
|
|
|
|
ShardSource->Sources->lookup("unittest:///root/A.cc").DirectIncludes,
|
|
|
|
UnorderedElementsAre("unittest:///root/A.h"));
|
|
|
|
EXPECT_NE(ShardSource->Sources->lookup("unittest:///root/A.cc").Digest,
|
2018-12-05 19:29:27 +08:00
|
|
|
FileDigest{{0}});
|
2018-12-04 19:31:57 +08:00
|
|
|
EXPECT_THAT(ShardSource->Sources->lookup("unittest:///root/A.h"),
|
|
|
|
EmptyIncludeNode());
|
|
|
|
|
|
|
|
auto ShardHeader = MSS.loadShard(testPath("root/A.h"));
|
|
|
|
EXPECT_TRUE(ShardHeader->Sources);
|
|
|
|
EXPECT_EQ(ShardHeader->Sources->size(), 2U); // A.h, B.h
|
|
|
|
EXPECT_THAT(
|
|
|
|
ShardHeader->Sources->lookup("unittest:///root/A.h").DirectIncludes,
|
|
|
|
UnorderedElementsAre("unittest:///root/B.h"));
|
|
|
|
EXPECT_NE(ShardHeader->Sources->lookup("unittest:///root/A.h").Digest,
|
2018-12-05 19:29:27 +08:00
|
|
|
FileDigest{{0}});
|
2018-12-04 19:31:57 +08:00
|
|
|
EXPECT_THAT(ShardHeader->Sources->lookup("unittest:///root/B.h"),
|
|
|
|
EmptyIncludeNode());
|
|
|
|
}
|
|
|
|
|
2019-01-11 01:03:04 +08:00
|
|
|
TEST_F(BackgroundIndexTest, ShardStorageLoad) {
|
|
|
|
MockFSProvider FS;
|
|
|
|
FS.Files[testPath("root/A.h")] = R"cpp(
|
|
|
|
void common();
|
|
|
|
void f_b();
|
|
|
|
class A_CC {};
|
|
|
|
)cpp";
|
|
|
|
FS.Files[testPath("root/A.cc")] =
|
|
|
|
"#include \"A.h\"\nvoid g() { (void)common; }";
|
|
|
|
|
|
|
|
llvm::StringMap<std::string> Storage;
|
|
|
|
size_t CacheHits = 0;
|
|
|
|
MemoryShardStorage MSS(Storage, CacheHits);
|
|
|
|
|
|
|
|
tooling::CompileCommand Cmd;
|
|
|
|
Cmd.Filename = testPath("root/A.cc");
|
|
|
|
Cmd.Directory = testPath("root");
|
|
|
|
Cmd.CommandLine = {"clang++", testPath("root/A.cc")};
|
|
|
|
// Check nothing is loaded from Storage, but A.cc and A.h has been stored.
|
|
|
|
{
|
|
|
|
OverlayCDB CDB(/*Base=*/nullptr);
|
2019-01-22 17:10:20 +08:00
|
|
|
BackgroundIndex Idx(Context::empty(), FS, CDB,
|
2019-01-11 01:03:04 +08:00
|
|
|
[&](llvm::StringRef) { return &MSS; });
|
|
|
|
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
|
|
|
|
ASSERT_TRUE(Idx.blockUntilIdleForTest());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Change header.
|
|
|
|
FS.Files[testPath("root/A.h")] = R"cpp(
|
|
|
|
void common();
|
|
|
|
void f_b();
|
|
|
|
class A_CC {};
|
|
|
|
class A_CCnew {};
|
|
|
|
)cpp";
|
|
|
|
{
|
|
|
|
OverlayCDB CDB(/*Base=*/nullptr);
|
2019-01-22 17:10:20 +08:00
|
|
|
BackgroundIndex Idx(Context::empty(), FS, CDB,
|
2019-01-11 01:03:04 +08:00
|
|
|
[&](llvm::StringRef) { return &MSS; });
|
2019-07-19 18:18:52 +08:00
|
|
|
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
|
2019-01-11 01:03:04 +08:00
|
|
|
ASSERT_TRUE(Idx.blockUntilIdleForTest());
|
|
|
|
}
|
|
|
|
EXPECT_EQ(CacheHits, 2U); // Check both A.cc and A.h loaded from cache.
|
|
|
|
|
|
|
|
// Check if the new symbol has arrived.
|
|
|
|
auto ShardHeader = MSS.loadShard(testPath("root/A.h"));
|
|
|
|
EXPECT_NE(ShardHeader, nullptr);
|
|
|
|
EXPECT_THAT(*ShardHeader->Symbols, Contains(Named("A_CCnew")));
|
|
|
|
|
|
|
|
// Change source.
|
|
|
|
FS.Files[testPath("root/A.cc")] =
|
|
|
|
"#include \"A.h\"\nvoid g() { (void)common; }\nvoid f_b() {}";
|
|
|
|
{
|
|
|
|
CacheHits = 0;
|
|
|
|
OverlayCDB CDB(/*Base=*/nullptr);
|
2019-01-22 17:10:20 +08:00
|
|
|
BackgroundIndex Idx(Context::empty(), FS, CDB,
|
2019-01-11 01:03:04 +08:00
|
|
|
[&](llvm::StringRef) { return &MSS; });
|
2019-07-19 18:18:52 +08:00
|
|
|
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
|
2019-01-11 01:03:04 +08:00
|
|
|
ASSERT_TRUE(Idx.blockUntilIdleForTest());
|
|
|
|
}
|
|
|
|
EXPECT_EQ(CacheHits, 2U); // Check both A.cc and A.h loaded from cache.
|
|
|
|
|
|
|
|
// Check if the new symbol has arrived.
|
2019-01-15 17:03:33 +08:00
|
|
|
ShardHeader = MSS.loadShard(testPath("root/A.h"));
|
2019-01-11 01:03:04 +08:00
|
|
|
EXPECT_NE(ShardHeader, nullptr);
|
2019-01-15 17:03:33 +08:00
|
|
|
EXPECT_THAT(*ShardHeader->Symbols, Contains(Named("A_CCnew")));
|
|
|
|
auto ShardSource = MSS.loadShard(testPath("root/A.cc"));
|
|
|
|
EXPECT_NE(ShardSource, nullptr);
|
2019-01-11 01:03:04 +08:00
|
|
|
EXPECT_THAT(*ShardSource->Symbols,
|
|
|
|
Contains(AllOf(Named("f_b"), Declared(), Defined())));
|
|
|
|
}
|
|
|
|
|
2019-01-15 17:03:33 +08:00
|
|
|
TEST_F(BackgroundIndexTest, ShardStorageEmptyFile) {
|
|
|
|
MockFSProvider FS;
|
|
|
|
FS.Files[testPath("root/A.h")] = R"cpp(
|
|
|
|
void common();
|
|
|
|
void f_b();
|
|
|
|
class A_CC {};
|
|
|
|
)cpp";
|
|
|
|
FS.Files[testPath("root/B.h")] = R"cpp(
|
|
|
|
#include "A.h"
|
|
|
|
)cpp";
|
|
|
|
FS.Files[testPath("root/A.cc")] =
|
|
|
|
"#include \"B.h\"\nvoid g() { (void)common; }";
|
|
|
|
|
|
|
|
llvm::StringMap<std::string> Storage;
|
|
|
|
size_t CacheHits = 0;
|
|
|
|
MemoryShardStorage MSS(Storage, CacheHits);
|
|
|
|
|
|
|
|
tooling::CompileCommand Cmd;
|
|
|
|
Cmd.Filename = testPath("root/A.cc");
|
|
|
|
Cmd.Directory = testPath("root");
|
|
|
|
Cmd.CommandLine = {"clang++", testPath("root/A.cc")};
|
|
|
|
// Check that A.cc, A.h and B.h has been stored.
|
|
|
|
{
|
|
|
|
OverlayCDB CDB(/*Base=*/nullptr);
|
2019-01-22 17:10:20 +08:00
|
|
|
BackgroundIndex Idx(Context::empty(), FS, CDB,
|
2019-01-15 17:03:33 +08:00
|
|
|
[&](llvm::StringRef) { return &MSS; });
|
|
|
|
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
|
|
|
|
ASSERT_TRUE(Idx.blockUntilIdleForTest());
|
|
|
|
}
|
|
|
|
EXPECT_THAT(Storage.keys(),
|
|
|
|
UnorderedElementsAre(testPath("root/A.cc"), testPath("root/A.h"),
|
|
|
|
testPath("root/B.h")));
|
|
|
|
auto ShardHeader = MSS.loadShard(testPath("root/B.h"));
|
|
|
|
EXPECT_NE(ShardHeader, nullptr);
|
|
|
|
EXPECT_TRUE(ShardHeader->Symbols->empty());
|
|
|
|
|
|
|
|
// Check that A.cc, A.h and B.h has been loaded.
|
|
|
|
{
|
|
|
|
CacheHits = 0;
|
|
|
|
OverlayCDB CDB(/*Base=*/nullptr);
|
2019-01-22 17:10:20 +08:00
|
|
|
BackgroundIndex Idx(Context::empty(), FS, CDB,
|
2019-01-15 17:03:33 +08:00
|
|
|
[&](llvm::StringRef) { return &MSS; });
|
|
|
|
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
|
|
|
|
ASSERT_TRUE(Idx.blockUntilIdleForTest());
|
|
|
|
}
|
|
|
|
EXPECT_EQ(CacheHits, 3U);
|
|
|
|
|
|
|
|
// Update B.h to contain some symbols.
|
|
|
|
FS.Files[testPath("root/B.h")] = R"cpp(
|
|
|
|
#include "A.h"
|
|
|
|
void new_func();
|
|
|
|
)cpp";
|
|
|
|
// Check that B.h has been stored with new contents.
|
|
|
|
{
|
|
|
|
CacheHits = 0;
|
|
|
|
OverlayCDB CDB(/*Base=*/nullptr);
|
2019-01-22 17:10:20 +08:00
|
|
|
BackgroundIndex Idx(Context::empty(), FS, CDB,
|
2019-01-15 17:03:33 +08:00
|
|
|
[&](llvm::StringRef) { return &MSS; });
|
|
|
|
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
|
|
|
|
ASSERT_TRUE(Idx.blockUntilIdleForTest());
|
|
|
|
}
|
|
|
|
EXPECT_EQ(CacheHits, 3U);
|
|
|
|
ShardHeader = MSS.loadShard(testPath("root/B.h"));
|
|
|
|
EXPECT_NE(ShardHeader, nullptr);
|
|
|
|
EXPECT_THAT(*ShardHeader->Symbols,
|
|
|
|
Contains(AllOf(Named("new_func"), Declared(), Not(Defined()))));
|
|
|
|
}
|
|
|
|
|
2019-03-08 17:57:33 +08:00
|
|
|
TEST_F(BackgroundIndexTest, NoDotsInAbsPath) {
|
|
|
|
MockFSProvider FS;
|
|
|
|
llvm::StringMap<std::string> Storage;
|
|
|
|
size_t CacheHits = 0;
|
|
|
|
MemoryShardStorage MSS(Storage, CacheHits);
|
|
|
|
OverlayCDB CDB(/*Base=*/nullptr);
|
|
|
|
BackgroundIndex Idx(Context::empty(), FS, CDB,
|
|
|
|
[&](llvm::StringRef) { return &MSS; });
|
|
|
|
|
|
|
|
tooling::CompileCommand Cmd;
|
|
|
|
FS.Files[testPath("root/A.cc")] = "";
|
|
|
|
Cmd.Filename = "../A.cc";
|
|
|
|
Cmd.Directory = testPath("root/build");
|
|
|
|
Cmd.CommandLine = {"clang++", "../A.cc"};
|
|
|
|
CDB.setCompileCommand(testPath("root/build/../A.cc"), Cmd);
|
|
|
|
|
|
|
|
FS.Files[testPath("root/B.cc")] = "";
|
|
|
|
Cmd.Filename = "./B.cc";
|
|
|
|
Cmd.Directory = testPath("root");
|
|
|
|
Cmd.CommandLine = {"clang++", "./B.cc"};
|
|
|
|
CDB.setCompileCommand(testPath("root/./B.cc"), Cmd);
|
|
|
|
|
|
|
|
ASSERT_TRUE(Idx.blockUntilIdleForTest());
|
|
|
|
for (llvm::StringRef AbsPath : MSS.AccessedPaths.keys()) {
|
|
|
|
EXPECT_FALSE(AbsPath.contains("./")) << AbsPath;
|
|
|
|
EXPECT_FALSE(AbsPath.contains("../")) << AbsPath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-04 17:51:43 +08:00
|
|
|
TEST_F(BackgroundIndexTest, UncompilableFiles) {
|
|
|
|
MockFSProvider FS;
|
|
|
|
llvm::StringMap<std::string> Storage;
|
|
|
|
size_t CacheHits = 0;
|
|
|
|
MemoryShardStorage MSS(Storage, CacheHits);
|
|
|
|
OverlayCDB CDB(/*Base=*/nullptr);
|
|
|
|
BackgroundIndex Idx(Context::empty(), FS, CDB,
|
|
|
|
[&](llvm::StringRef) { return &MSS; });
|
|
|
|
|
|
|
|
tooling::CompileCommand Cmd;
|
|
|
|
FS.Files[testPath("A.h")] = "void foo();";
|
|
|
|
FS.Files[testPath("B.h")] = "#include \"C.h\"\nasdf;";
|
|
|
|
FS.Files[testPath("C.h")] = "";
|
|
|
|
FS.Files[testPath("A.cc")] = R"cpp(
|
|
|
|
#include "A.h"
|
|
|
|
#include "B.h"
|
|
|
|
#include "not_found_header.h"
|
|
|
|
|
|
|
|
void foo() {}
|
|
|
|
)cpp";
|
|
|
|
Cmd.Filename = "../A.cc";
|
|
|
|
Cmd.Directory = testPath("build");
|
|
|
|
Cmd.CommandLine = {"clang++", "../A.cc"};
|
|
|
|
CDB.setCompileCommand(testPath("build/../A.cc"), Cmd);
|
|
|
|
ASSERT_TRUE(Idx.blockUntilIdleForTest());
|
|
|
|
|
2019-07-04 17:52:12 +08:00
|
|
|
EXPECT_THAT(Storage.keys(), ElementsAre(testPath("A.cc"), testPath("A.h"),
|
|
|
|
testPath("B.h"), testPath("C.h")));
|
|
|
|
|
|
|
|
{
|
|
|
|
auto Shard = MSS.loadShard(testPath("A.cc"));
|
|
|
|
EXPECT_THAT(*Shard->Symbols, UnorderedElementsAre(Named("foo")));
|
|
|
|
EXPECT_THAT(Shard->Sources->keys(),
|
|
|
|
UnorderedElementsAre("unittest:///A.cc", "unittest:///A.h",
|
|
|
|
"unittest:///B.h"));
|
|
|
|
EXPECT_THAT(Shard->Sources->lookup("unittest:///A.cc"), HadErrors());
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
auto Shard = MSS.loadShard(testPath("A.h"));
|
|
|
|
EXPECT_THAT(*Shard->Symbols, UnorderedElementsAre(Named("foo")));
|
|
|
|
EXPECT_THAT(Shard->Sources->keys(),
|
|
|
|
UnorderedElementsAre("unittest:///A.h"));
|
|
|
|
EXPECT_THAT(Shard->Sources->lookup("unittest:///A.h"), HadErrors());
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
auto Shard = MSS.loadShard(testPath("B.h"));
|
|
|
|
EXPECT_THAT(*Shard->Symbols, UnorderedElementsAre(Named("asdf")));
|
|
|
|
EXPECT_THAT(Shard->Sources->keys(),
|
|
|
|
UnorderedElementsAre("unittest:///B.h", "unittest:///C.h"));
|
|
|
|
EXPECT_THAT(Shard->Sources->lookup("unittest:///B.h"), HadErrors());
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
auto Shard = MSS.loadShard(testPath("C.h"));
|
|
|
|
EXPECT_THAT(*Shard->Symbols, UnorderedElementsAre());
|
|
|
|
EXPECT_THAT(Shard->Sources->keys(),
|
|
|
|
UnorderedElementsAre("unittest:///C.h"));
|
|
|
|
EXPECT_THAT(Shard->Sources->lookup("unittest:///C.h"), HadErrors());
|
|
|
|
}
|
2019-07-04 17:51:43 +08:00
|
|
|
}
|
|
|
|
|
2019-07-04 17:51:53 +08:00
|
|
|
TEST_F(BackgroundIndexTest, CmdLineHash) {
|
|
|
|
MockFSProvider FS;
|
|
|
|
llvm::StringMap<std::string> Storage;
|
|
|
|
size_t CacheHits = 0;
|
|
|
|
MemoryShardStorage MSS(Storage, CacheHits);
|
|
|
|
OverlayCDB CDB(/*Base=*/nullptr, /*FallbackFlags=*/{},
|
|
|
|
/*ResourceDir=*/std::string(""));
|
|
|
|
BackgroundIndex Idx(Context::empty(), FS, CDB,
|
|
|
|
[&](llvm::StringRef) { return &MSS; });
|
|
|
|
|
|
|
|
tooling::CompileCommand Cmd;
|
|
|
|
FS.Files[testPath("A.cc")] = "#include \"A.h\"";
|
|
|
|
FS.Files[testPath("A.h")] = "";
|
|
|
|
Cmd.Filename = "../A.cc";
|
|
|
|
Cmd.Directory = testPath("build");
|
|
|
|
Cmd.CommandLine = {"clang++", "../A.cc", "-fsyntax-only"};
|
|
|
|
CDB.setCompileCommand(testPath("build/../A.cc"), Cmd);
|
|
|
|
ASSERT_TRUE(Idx.blockUntilIdleForTest());
|
|
|
|
|
|
|
|
EXPECT_THAT(Storage.keys(), ElementsAre(testPath("A.cc"), testPath("A.h")));
|
|
|
|
// Make sure we only store the Cmd for main file.
|
|
|
|
EXPECT_FALSE(MSS.loadShard(testPath("A.h"))->Cmd);
|
|
|
|
|
|
|
|
{
|
|
|
|
tooling::CompileCommand CmdStored = *MSS.loadShard(testPath("A.cc"))->Cmd;
|
|
|
|
EXPECT_EQ(CmdStored.CommandLine, Cmd.CommandLine);
|
|
|
|
EXPECT_EQ(CmdStored.Directory, Cmd.Directory);
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: Changing compile commands should be enough to invalidate the cache.
|
|
|
|
FS.Files[testPath("A.cc")] = " ";
|
|
|
|
Cmd.CommandLine = {"clang++", "../A.cc", "-Dfoo", "-fsyntax-only"};
|
|
|
|
CDB.setCompileCommand(testPath("build/../A.cc"), Cmd);
|
|
|
|
ASSERT_TRUE(Idx.blockUntilIdleForTest());
|
|
|
|
|
|
|
|
EXPECT_FALSE(MSS.loadShard(testPath("A.h"))->Cmd);
|
|
|
|
|
|
|
|
{
|
|
|
|
tooling::CompileCommand CmdStored = *MSS.loadShard(testPath("A.cc"))->Cmd;
|
|
|
|
EXPECT_EQ(CmdStored.CommandLine, Cmd.CommandLine);
|
|
|
|
EXPECT_EQ(CmdStored.Directory, Cmd.Directory);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
class BackgroundIndexRebuilderTest : public testing::Test {
|
|
|
|
protected:
|
|
|
|
BackgroundIndexRebuilderTest()
|
2019-08-15 07:52:23 +08:00
|
|
|
: Target(std::make_unique<MemIndex>()),
|
2019-07-16 18:17:06 +08:00
|
|
|
Rebuilder(&Target, &Source, /*Threads=*/10) {
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
// Prepare FileSymbols with TestSymbol in it, for checkRebuild.
|
|
|
|
TestSymbol.ID = SymbolID("foo");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Perform Action and determine whether it rebuilt the index or not.
|
|
|
|
bool checkRebuild(std::function<void()> Action) {
|
2019-07-10 07:05:20 +08:00
|
|
|
// Update name so we can tell if the index updates.
|
|
|
|
VersionStorage.push_back("Sym" + std::to_string(++VersionCounter));
|
|
|
|
TestSymbol.Name = VersionStorage.back();
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
SymbolSlab::Builder SB;
|
|
|
|
SB.insert(TestSymbol);
|
2019-08-15 07:52:23 +08:00
|
|
|
Source.update("", std::make_unique<SymbolSlab>(std::move(SB).build()),
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
nullptr, nullptr, false);
|
|
|
|
// Now maybe update the index.
|
|
|
|
Action();
|
2019-07-10 07:05:20 +08:00
|
|
|
// Now query the index to get the name count.
|
|
|
|
std::string ReadName;
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
LookupRequest Req;
|
|
|
|
Req.IDs.insert(TestSymbol.ID);
|
2019-07-10 07:05:20 +08:00
|
|
|
Target.lookup(Req, [&](const Symbol &S) { ReadName = S.Name; });
|
|
|
|
// The index was rebuild if the name is up to date.
|
|
|
|
return ReadName == VersionStorage.back();
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Symbol TestSymbol;
|
|
|
|
FileSymbols Source;
|
|
|
|
SwapIndex Target;
|
|
|
|
BackgroundIndexRebuilder Rebuilder;
|
2019-07-10 07:05:20 +08:00
|
|
|
|
|
|
|
unsigned VersionCounter = 0;
|
|
|
|
std::deque<std::string> VersionStorage;
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
TEST_F(BackgroundIndexRebuilderTest, IndexingTUs) {
|
2019-07-16 18:17:06 +08:00
|
|
|
for (unsigned I = 0; I < Rebuilder.TUsBeforeFirstBuild - 1; ++I)
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
EXPECT_FALSE(checkRebuild([&] { Rebuilder.indexedTU(); }));
|
|
|
|
EXPECT_TRUE(checkRebuild([&] { Rebuilder.indexedTU(); }));
|
2019-07-16 18:17:06 +08:00
|
|
|
for (unsigned I = 0; I < Rebuilder.TUsBeforeRebuild - 1; ++I)
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
EXPECT_FALSE(checkRebuild([&] { Rebuilder.indexedTU(); }));
|
|
|
|
EXPECT_TRUE(checkRebuild([&] { Rebuilder.indexedTU(); }));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(BackgroundIndexRebuilderTest, LoadingShards) {
|
|
|
|
Rebuilder.startLoading();
|
2019-07-19 18:18:52 +08:00
|
|
|
Rebuilder.loadedShard(10);
|
|
|
|
Rebuilder.loadedShard(20);
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
EXPECT_TRUE(checkRebuild([&] { Rebuilder.doneLoading(); }));
|
|
|
|
|
|
|
|
// No rebuild for no shards.
|
|
|
|
Rebuilder.startLoading();
|
|
|
|
EXPECT_FALSE(checkRebuild([&] { Rebuilder.doneLoading(); }));
|
|
|
|
|
|
|
|
// Loads can overlap.
|
|
|
|
Rebuilder.startLoading();
|
2019-07-19 18:18:52 +08:00
|
|
|
Rebuilder.loadedShard(1);
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
Rebuilder.startLoading();
|
2019-07-19 18:18:52 +08:00
|
|
|
Rebuilder.loadedShard(1);
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
EXPECT_FALSE(checkRebuild([&] { Rebuilder.doneLoading(); }));
|
2019-07-19 18:18:52 +08:00
|
|
|
Rebuilder.loadedShard(1);
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
EXPECT_TRUE(checkRebuild([&] { Rebuilder.doneLoading(); }));
|
|
|
|
|
|
|
|
// No rebuilding for indexed files while loading.
|
|
|
|
Rebuilder.startLoading();
|
2019-07-16 18:17:06 +08:00
|
|
|
for (unsigned I = 0; I < 3 * Rebuilder.TUsBeforeRebuild; ++I)
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
EXPECT_FALSE(checkRebuild([&] { Rebuilder.indexedTU(); }));
|
|
|
|
// But they get indexed when we're done, even if no shards were loaded.
|
|
|
|
EXPECT_TRUE(checkRebuild([&] { Rebuilder.doneLoading(); }));
|
|
|
|
}
|
|
|
|
|
2019-07-11 21:34:38 +08:00
|
|
|
TEST(BackgroundQueueTest, Priority) {
|
|
|
|
// Create high and low priority tasks.
|
|
|
|
// Once a bunch of high priority tasks have run, the queue is stopped.
|
|
|
|
// So the low priority tasks should never run.
|
|
|
|
BackgroundQueue Q;
|
|
|
|
std::atomic<unsigned> HiRan(0), LoRan(0);
|
|
|
|
BackgroundQueue::Task Lo([&] { ++LoRan; });
|
|
|
|
BackgroundQueue::Task Hi([&] {
|
|
|
|
if (++HiRan >= 10)
|
|
|
|
Q.stop();
|
|
|
|
});
|
|
|
|
Hi.QueuePri = 100;
|
|
|
|
|
|
|
|
// Enqueuing the low-priority ones first shouldn't make them run first.
|
|
|
|
Q.append(std::vector<BackgroundQueue::Task>(30, Lo));
|
|
|
|
for (unsigned I = 0; I < 30; ++I)
|
|
|
|
Q.push(Hi);
|
|
|
|
|
|
|
|
AsyncTaskRunner ThreadPool;
|
|
|
|
for (unsigned I = 0; I < 5; ++I)
|
|
|
|
ThreadPool.runAsync("worker", [&] { Q.work(); });
|
|
|
|
// We should test enqueue with active workers, but it's hard to avoid races.
|
|
|
|
// Just make sure we don't crash.
|
|
|
|
Q.push(Lo);
|
|
|
|
Q.append(std::vector<BackgroundQueue::Task>(2, Hi));
|
|
|
|
|
|
|
|
// After finishing, check the tasks that ran.
|
|
|
|
ThreadPool.wait();
|
|
|
|
EXPECT_GE(HiRan, 10u);
|
|
|
|
EXPECT_EQ(LoRan, 0u);
|
|
|
|
}
|
|
|
|
|
2019-07-12 18:18:42 +08:00
|
|
|
TEST(BackgroundQueueTest, Boost) {
|
|
|
|
std::string Sequence;
|
|
|
|
|
|
|
|
BackgroundQueue::Task A([&] { Sequence.push_back('A'); });
|
|
|
|
A.Tag = "A";
|
|
|
|
A.QueuePri = 1;
|
|
|
|
|
|
|
|
BackgroundQueue::Task B([&] { Sequence.push_back('B'); });
|
|
|
|
B.QueuePri = 2;
|
|
|
|
B.Tag = "B";
|
|
|
|
|
|
|
|
{
|
|
|
|
BackgroundQueue Q;
|
|
|
|
Q.append({A, B});
|
|
|
|
Q.work([&] { Q.stop(); });
|
|
|
|
EXPECT_EQ("BA", Sequence) << "priority order";
|
|
|
|
}
|
|
|
|
Sequence.clear();
|
|
|
|
{
|
|
|
|
BackgroundQueue Q;
|
|
|
|
Q.boost("A", 3);
|
|
|
|
Q.append({A, B});
|
|
|
|
Q.work([&] { Q.stop(); });
|
|
|
|
EXPECT_EQ("AB", Sequence) << "A was boosted before enqueueing";
|
|
|
|
}
|
|
|
|
Sequence.clear();
|
|
|
|
{
|
|
|
|
BackgroundQueue Q;
|
|
|
|
Q.append({A, B});
|
|
|
|
Q.boost("A", 3);
|
|
|
|
Q.work([&] { Q.stop(); });
|
|
|
|
EXPECT_EQ("AB", Sequence) << "A was boosted after enqueueing";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|