summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang-tools-extra/clangd/CMakeLists.txt1
-rw-r--r--clang-tools-extra/clangd/ClangdLSPServer.cpp23
-rw-r--r--clang-tools-extra/clangd/ClangdLSPServer.h4
-rw-r--r--clang-tools-extra/clangd/ClangdServer.cpp28
-rw-r--r--clang-tools-extra/clangd/ClangdServer.h9
-rw-r--r--clang-tools-extra/clangd/CompileArgsCache.cpp44
-rw-r--r--clang-tools-extra/clangd/CompileArgsCache.h43
-rw-r--r--clang-tools-extra/clangd/GlobalCompilationDatabase.cpp33
-rw-r--r--clang-tools-extra/clangd/GlobalCompilationDatabase.h28
-rw-r--r--clang-tools-extra/unittests/clangd/ClangdTests.cpp28
-rw-r--r--clang-tools-extra/unittests/clangd/SyncAPI.cpp4
-rw-r--r--clang-tools-extra/unittests/clangd/SyncAPI.h3
12 files changed, 109 insertions, 139 deletions
diff --git a/clang-tools-extra/clangd/CMakeLists.txt b/clang-tools-extra/clangd/CMakeLists.txt
index 6ff7fc555d6..16d5c0f2285 100644
--- a/clang-tools-extra/clangd/CMakeLists.txt
+++ b/clang-tools-extra/clangd/CMakeLists.txt
@@ -14,7 +14,6 @@ add_clang_library(clangDaemon
ClangdUnit.cpp
CodeComplete.cpp
CodeCompletionStrings.cpp
- CompileArgsCache.cpp
Compiler.cpp
Context.cpp
Diagnostics.cpp
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp
index 3e0e4f6d497..7e708a29665 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -129,11 +129,13 @@ void ClangdLSPServer::onShutdown(ShutdownParams &Params) {
void ClangdLSPServer::onExit(ExitParams &Params) { IsDone = true; }
void ClangdLSPServer::onDocumentDidOpen(DidOpenTextDocumentParams &Params) {
- if (Params.metadata && !Params.metadata->extraFlags.empty())
- CDB.setExtraFlagsForFile(Params.textDocument.uri.file(),
- std::move(Params.metadata->extraFlags));
-
PathRef File = Params.textDocument.uri.file();
+ if (Params.metadata && !Params.metadata->extraFlags.empty()) {
+ NonCachedCDB.setExtraFlagsForFile(File,
+ std::move(Params.metadata->extraFlags));
+ CDB.invalidate(File);
+ }
+
std::string &Contents = Params.textDocument.text;
DraftMgr.addDraft(File, Contents);
@@ -155,6 +157,7 @@ void ClangdLSPServer::onDocumentDidChange(DidChangeTextDocumentParams &Params) {
// fail rather than giving wrong results.
DraftMgr.removeDraft(File);
Server.removeDocument(File);
+ CDB.invalidate(File);
log(llvm::toString(Contents.takeError()));
return;
}
@@ -383,7 +386,10 @@ void ClangdLSPServer::onChangeConfiguration(
// Compilation database change.
if (Settings.compilationDatabasePath.hasValue()) {
- CDB.setCompileCommandsDir(Settings.compilationDatabasePath.getValue());
+ NonCachedCDB.setCompileCommandsDir(
+ Settings.compilationDatabasePath.getValue());
+ CDB.clear();
+
reparseOpenedFiles();
}
}
@@ -392,8 +398,8 @@ ClangdLSPServer::ClangdLSPServer(JSONOutput &Out,
const clangd::CodeCompleteOptions &CCOpts,
llvm::Optional<Path> CompileCommandsDir,
const ClangdServer::Options &Opts)
- : Out(Out), CDB(std::move(CompileCommandsDir)), CCOpts(CCOpts),
- SupportedSymbolKinds(defaultSymbolKinds()),
+ : Out(Out), NonCachedCDB(std::move(CompileCommandsDir)), CDB(NonCachedCDB),
+ CCOpts(CCOpts), SupportedSymbolKinds(defaultSymbolKinds()),
Server(CDB, FSProvider, /*DiagConsumer=*/*this, Opts) {}
bool ClangdLSPServer::run(std::FILE *In, JSONStreamStyle InputStyle) {
@@ -471,6 +477,5 @@ void ClangdLSPServer::onDiagnosticsReady(PathRef File,
void ClangdLSPServer::reparseOpenedFiles() {
for (const Path &FilePath : DraftMgr.getActiveFiles())
Server.addDocument(FilePath, *DraftMgr.getDraft(FilePath),
- WantDiagnostics::Auto,
- /*SkipCache=*/true);
+ WantDiagnostics::Auto);
}
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.h b/clang-tools-extra/clangd/ClangdLSPServer.h
index 67beed1e3cf..0a3e6fc0a52 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.h
+++ b/clang-tools-extra/clangd/ClangdLSPServer.h
@@ -100,7 +100,9 @@ private:
// Various ClangdServer parameters go here. It's important they're created
// before ClangdServer.
- DirectoryBasedGlobalCompilationDatabase CDB;
+ DirectoryBasedGlobalCompilationDatabase NonCachedCDB;
+ CachingCompilationDb CDB;
+
RealFileSystemProvider FSProvider;
/// Options used for code completion
clangd::CodeCompleteOptions CCOpts;
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp
index 3eae2e8d445..c2b68f8a970 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -23,6 +23,7 @@
#include "clang/Tooling/Refactoring/Rename/RenamingAction.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/ScopeExit.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -83,9 +84,9 @@ ClangdServer::ClangdServer(GlobalCompilationDatabase &CDB,
FileSystemProvider &FSProvider,
DiagnosticsConsumer &DiagConsumer,
const Options &Opts)
- : CompileArgs(CDB, Opts.ResourceDir ? Opts.ResourceDir->str()
- : getStandardResourceDir()),
- DiagConsumer(DiagConsumer), FSProvider(FSProvider),
+ : CDB(CDB), DiagConsumer(DiagConsumer), FSProvider(FSProvider),
+ ResourceDir(Opts.ResourceDir ? Opts.ResourceDir->str()
+ : getStandardResourceDir()),
FileIdx(Opts.BuildDynamicSymbolIndex ? new FileIndex() : nullptr),
PCHs(std::make_shared<PCHContainerOperations>()),
// Pass a callback into `WorkScheduler` to extract symbols from a newly
@@ -120,13 +121,10 @@ void ClangdServer::setRootPath(PathRef RootPath) {
}
void ClangdServer::addDocument(PathRef File, StringRef Contents,
- WantDiagnostics WantDiags, bool SkipCache) {
- if (SkipCache)
- CompileArgs.invalidate(File);
-
+ WantDiagnostics WantDiags) {
DocVersion Version = ++InternalVersion[File];
- ParseInputs Inputs = {CompileArgs.getCompileCommand(File),
- FSProvider.getFileSystem(), Contents.str()};
+ ParseInputs Inputs = {getCompileCommand(File), FSProvider.getFileSystem(),
+ Contents.str()};
Path FileStr = File.str();
WorkScheduler.update(File, std::move(Inputs), WantDiags,
@@ -137,7 +135,6 @@ void ClangdServer::addDocument(PathRef File, StringRef Contents,
void ClangdServer::removeDocument(PathRef File) {
++InternalVersion[File];
- CompileArgs.invalidate(File);
WorkScheduler.remove(File);
}
@@ -430,6 +427,17 @@ void ClangdServer::consumeDiagnostics(PathRef File, DocVersion Version,
DiagConsumer.onDiagnosticsReady(File, std::move(Diags));
}
+tooling::CompileCommand ClangdServer::getCompileCommand(PathRef File) {
+ llvm::Optional<tooling::CompileCommand> C = CDB.getCompileCommand(File);
+ if (!C) // FIXME: Suppress diagnostics? Let the user know?
+ C = CDB.getFallbackCommand(File);
+
+ // Inject the resource dir.
+ // FIXME: Don't overwrite it if it's already there.
+ C->CommandLine.push_back("-resource-dir=" + ResourceDir);
+ return std::move(*C);
+}
+
void ClangdServer::onFileEvent(const DidChangeWatchedFilesParams &Params) {
// FIXME: Do nothing for now. This will be used for indexing and potentially
// invalidating other caches.
diff --git a/clang-tools-extra/clangd/ClangdServer.h b/clang-tools-extra/clangd/ClangdServer.h
index 4ccf58f4494..b6d5f160128 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -12,7 +12,6 @@
#include "ClangdUnit.h"
#include "CodeComplete.h"
-#include "CompileArgsCache.h"
#include "Function.h"
#include "GlobalCompilationDatabase.h"
#include "Protocol.h"
@@ -122,8 +121,7 @@ public:
/// When \p SkipCache is true, compile commands will always be requested from
/// compilation database even if they were cached in previous invocations.
void addDocument(PathRef File, StringRef Contents,
- WantDiagnostics WD = WantDiagnostics::Auto,
- bool SkipCache = false);
+ WantDiagnostics WD = WantDiagnostics::Auto);
/// Remove \p File from list of tracked files, schedule a request to free
/// resources associated with it.
@@ -216,13 +214,16 @@ private:
void consumeDiagnostics(PathRef File, DocVersion Version,
std::vector<Diag> Diags);
- CompileArgsCache CompileArgs;
+ tooling::CompileCommand getCompileCommand(PathRef File);
+
+ GlobalCompilationDatabase &CDB;
DiagnosticsConsumer &DiagConsumer;
FileSystemProvider &FSProvider;
/// Used to synchronize diagnostic responses for added and removed files.
llvm::StringMap<DocVersion> InternalVersion;
+ Path ResourceDir;
// The index used to look up symbols. This could be:
// - null (all index functionality is optional)
// - the dynamic index owned by ClangdServer (FileIdx)
diff --git a/clang-tools-extra/clangd/CompileArgsCache.cpp b/clang-tools-extra/clangd/CompileArgsCache.cpp
deleted file mode 100644
index 42167e56bc3..00000000000
--- a/clang-tools-extra/clangd/CompileArgsCache.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-//===--- CompileArgsCache.cpp --------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===---------------------------------------------------------------------===//
-
-#include "CompileArgsCache.h"
-
-namespace clang {
-namespace clangd {
-namespace {
-tooling::CompileCommand getCompileCommand(GlobalCompilationDatabase &CDB,
- PathRef File, PathRef ResourceDir) {
- llvm::Optional<tooling::CompileCommand> C = CDB.getCompileCommand(File);
- if (!C) // FIXME: Suppress diagnostics? Let the user know?
- C = CDB.getFallbackCommand(File);
-
- // Inject the resource dir.
- // FIXME: Don't overwrite it if it's already there.
- C->CommandLine.push_back("-resource-dir=" + ResourceDir.str());
- return std::move(*C);
-}
-} // namespace
-
-CompileArgsCache::CompileArgsCache(GlobalCompilationDatabase &CDB,
- Path ResourceDir)
- : CDB(CDB), ResourceDir(std::move(ResourceDir)) {}
-
-tooling::CompileCommand CompileArgsCache::getCompileCommand(PathRef File) {
- auto It = Cached.find(File);
- if (It == Cached.end()) {
- It = Cached.insert({File, clangd::getCompileCommand(CDB, File, ResourceDir)})
- .first;
- }
- return It->second;
-}
-
-void CompileArgsCache::invalidate(PathRef File) { Cached.erase(File); }
-
-} // namespace clangd
-} // namespace clang
diff --git a/clang-tools-extra/clangd/CompileArgsCache.h b/clang-tools-extra/clangd/CompileArgsCache.h
deleted file mode 100644
index 49d88758104..00000000000
--- a/clang-tools-extra/clangd/CompileArgsCache.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//===--- CompileArgsCache.h -------------------------------------*- C++-*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===---------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_COMPILEARGSCACHE_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_COMPILEARGSCACHE_H
-
-#include "GlobalCompilationDatabase.h"
-#include "Path.h"
-#include "clang/Tooling/CompilationDatabase.h"
-
-namespace clang {
-namespace clangd {
-
-/// A helper class used by ClangdServer to get compile commands from CDB.
-/// Also caches CompileCommands produced by compilation database on per-file
-/// basis. This avoids queries to CDB that can be much more expensive than a
-/// table lookup.
-class CompileArgsCache {
-public:
- CompileArgsCache(GlobalCompilationDatabase &CDB, Path ResourceDir);
-
- /// Gets compile command for \p File from cache or CDB if it's not in the
- /// cache.
- tooling::CompileCommand getCompileCommand(PathRef File);
-
- /// Removes a cache entry for \p File, if it's present in the cache.
- void invalidate(PathRef File);
-
-private:
- GlobalCompilationDatabase &CDB;
- const Path ResourceDir;
- llvm::StringMap<tooling::CompileCommand> Cached;
-};
-
-} // namespace clangd
-} // namespace clang
-#endif
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index ca223f6b344..a8ac58d3d4d 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -119,5 +119,38 @@ DirectoryBasedGlobalCompilationDatabase::getCDBForFile(PathRef File) const {
return nullptr;
}
+CachingCompilationDb::CachingCompilationDb(
+ const GlobalCompilationDatabase &InnerCDB)
+ : InnerCDB(InnerCDB) {}
+
+llvm::Optional<tooling::CompileCommand>
+CachingCompilationDb::getCompileCommand(PathRef File) const {
+ std::unique_lock<std::mutex> Lock(Mut);
+ auto It = Cached.find(File);
+ if (It != Cached.end())
+ return It->second;
+
+ Lock.unlock();
+ llvm::Optional<tooling::CompileCommand> Command =
+ InnerCDB.getCompileCommand(File);
+ Lock.lock();
+ return Cached.try_emplace(File, std::move(Command)).first->getValue();
+}
+
+tooling::CompileCommand
+CachingCompilationDb::getFallbackCommand(PathRef File) const {
+ return InnerCDB.getFallbackCommand(File);
+}
+
+void CachingCompilationDb::invalidate(PathRef File) {
+ std::unique_lock<std::mutex> Lock(Mut);
+ Cached.erase(File);
+}
+
+void CachingCompilationDb::clear() {
+ std::unique_lock<std::mutex> Lock(Mut);
+ Cached.clear();
+}
+
} // namespace clangd
} // namespace clang
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
index cf1e613fbf1..ab89a185b46 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
@@ -85,6 +85,34 @@ private:
/// is located.
llvm::Optional<Path> CompileCommandsDir;
};
+
+/// A wrapper around GlobalCompilationDatabase that caches the compile commands.
+/// Note that only results of getCompileCommand are cached.
+class CachingCompilationDb : public GlobalCompilationDatabase {
+public:
+ explicit CachingCompilationDb(const GlobalCompilationDatabase &InnerCDB);
+
+ /// Gets compile command for \p File from cache or CDB if it's not in the
+ /// cache.
+ llvm::Optional<tooling::CompileCommand>
+ getCompileCommand(PathRef File) const override;
+
+ /// Forwards to the inner CDB. Results of this function are not cached.
+ tooling::CompileCommand getFallbackCommand(PathRef File) const override;
+
+ /// Removes an entry for \p File if it's present in the cache.
+ void invalidate(PathRef File);
+
+ /// Removes all cached compile commands.
+ void clear();
+
+private:
+ const GlobalCompilationDatabase &InnerCDB;
+ mutable std::mutex Mut;
+ mutable llvm::StringMap<llvm::Optional<tooling::CompileCommand>>
+ Cached; /* GUARDED_BY(Mut) */
+};
+
} // namespace clangd
} // namespace clang
diff --git a/clang-tools-extra/unittests/clangd/ClangdTests.cpp b/clang-tools-extra/unittests/clangd/ClangdTests.cpp
index a91b65ff2b7..ae47b60a53e 100644
--- a/clang-tools-extra/unittests/clangd/ClangdTests.cpp
+++ b/clang-tools-extra/unittests/clangd/ClangdTests.cpp
@@ -390,16 +390,7 @@ struct bar { T x; };
// Now switch to C++ mode.
CDB.ExtraClangFlags = {"-xc++"};
- // By default addDocument does not check if CompileCommand has changed, so we
- // expect to see the errors.
- runAddDocument(Server, FooCpp, SourceContents1);
- EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
- runAddDocument(Server, FooCpp, SourceContents2);
- EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
- // Passing SkipCache=true will force addDocument to reparse the file with
- // proper flags.
- runAddDocument(Server, FooCpp, SourceContents2, WantDiagnostics::Auto,
- /*SkipCache=*/true);
+ runAddDocument(Server, FooCpp, SourceContents2, WantDiagnostics::Auto);
EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
// Subsequent addDocument calls should finish without errors too.
runAddDocument(Server, FooCpp, SourceContents1);
@@ -431,14 +422,7 @@ int main() { return 0; }
// Parse without the define, no errors should be produced.
CDB.ExtraClangFlags = {};
- // By default addDocument does not check if CompileCommand has changed, so we
- // expect to see the errors.
- runAddDocument(Server, FooCpp, SourceContents);
- EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
- // Passing SkipCache=true will force addDocument to reparse the file with
- // proper flags.
- runAddDocument(Server, FooCpp, SourceContents, WantDiagnostics::Auto,
- /*SkipCache=*/true);
+ runAddDocument(Server, FooCpp, SourceContents, WantDiagnostics::Auto);
ASSERT_TRUE(Server.blockUntilIdleForTest());
EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
// Subsequent addDocument call should finish without errors too.
@@ -500,10 +484,8 @@ int hello;
CDB.ExtraClangFlags.clear();
DiagConsumer.clear();
Server.removeDocument(BazCpp);
- Server.addDocument(FooCpp, FooSource.code(), WantDiagnostics::Auto,
- /*SkipCache=*/true);
- Server.addDocument(BarCpp, BarSource.code(), WantDiagnostics::Auto,
- /*SkipCache=*/true);
+ Server.addDocument(FooCpp, FooSource.code(), WantDiagnostics::Auto);
+ Server.addDocument(BarCpp, BarSource.code(), WantDiagnostics::Auto);
ASSERT_TRUE(Server.blockUntilIdleForTest());
EXPECT_THAT(DiagConsumer.filesWithDiags(),
@@ -708,7 +690,7 @@ int d;
Server.addDocument(FilePaths[FileIndex],
ShouldHaveErrors ? SourceContentsWithErrors
: SourceContentsWithoutErrors,
- WantDiagnostics::Auto, SkipCache);
+ WantDiagnostics::Auto);
UpdateStatsOnAddDocument(FileIndex, ShouldHaveErrors);
};
diff --git a/clang-tools-extra/unittests/clangd/SyncAPI.cpp b/clang-tools-extra/unittests/clangd/SyncAPI.cpp
index 0a1c5988e7c..aa2a044f231 100644
--- a/clang-tools-extra/unittests/clangd/SyncAPI.cpp
+++ b/clang-tools-extra/unittests/clangd/SyncAPI.cpp
@@ -12,8 +12,8 @@ namespace clang {
namespace clangd {
void runAddDocument(ClangdServer &Server, PathRef File, StringRef Contents,
- WantDiagnostics WantDiags, bool SkipCache) {
- Server.addDocument(File, Contents, WantDiags, SkipCache);
+ WantDiagnostics WantDiags) {
+ Server.addDocument(File, Contents, WantDiags);
if (!Server.blockUntilIdleForTest())
llvm_unreachable("not idle after addDocument");
}
diff --git a/clang-tools-extra/unittests/clangd/SyncAPI.h b/clang-tools-extra/unittests/clangd/SyncAPI.h
index d4d2ac8f901..0a140aa9db3 100644
--- a/clang-tools-extra/unittests/clangd/SyncAPI.h
+++ b/clang-tools-extra/unittests/clangd/SyncAPI.h
@@ -20,8 +20,7 @@ namespace clangd {
// Calls addDocument and then blockUntilIdleForTest.
void runAddDocument(ClangdServer &Server, PathRef File, StringRef Contents,
- WantDiagnostics WantDiags = WantDiagnostics::Auto,
- bool SkipCache = false);
+ WantDiagnostics WantDiags = WantDiagnostics::Auto);
llvm::Expected<CompletionList>
runCodeComplete(ClangdServer &Server, PathRef File, Position Pos,
OpenPOWER on IntegriCloud