ilya-biryukov updated this revision to Diff 126327.
ilya-biryukov added a comment.
Udpated the patch after changes in Context
Repository:
rCTE Clang Tools Extra
https://reviews.llvm.org/D40486
Files:
clangd/ClangdLSPServer.cpp
clangd/ClangdServer.cpp
clangd/ClangdServer.h
clangd/ClangdUnit.cpp
clangd/ClangdUnit.h
clangd/ClangdUnitStore.cpp
clangd/ClangdUnitStore.h
clangd/CodeComplete.cpp
clangd/CodeComplete.h
clangd/GlobalCompilationDatabase.cpp
clangd/GlobalCompilationDatabase.h
clangd/JSONRPCDispatcher.cpp
clangd/JSONRPCDispatcher.h
clangd/Logger.cpp
clangd/Logger.h
clangd/Protocol.h
clangd/ProtocolHandlers.cpp
clangd/ProtocolHandlers.h
clangd/tool/ClangdMain.cpp
unittests/clangd/ClangdTests.cpp
unittests/clangd/CodeCompleteTests.cpp
Index: unittests/clangd/CodeCompleteTests.cpp
===================================================================
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "ClangdServer.h"
#include "Compiler.h"
+#include "Context.h"
#include "Protocol.h"
#include "TestFS.h"
#include "gtest/gtest.h"
@@ -74,8 +75,7 @@
MockCompilationDatabase CDB;
ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
- /*StorePreamblesInMemory=*/true,
- EmptyLogger::getInstance());
+ /*StorePreamblesInMemory=*/true);
auto FooCpp = getVirtualTestFilePath("foo.cpp");
const auto SourceContents = R"cpp(
@@ -101,29 +101,33 @@
// No need to sync reparses here as there are no asserts on diagnostics (or
// other async operations).
- Server.addDocument(FooCpp, SourceContents);
+ Server.addDocument(FooCpp, SourceContents, buildCtx());
{
auto CodeCompletionResults1 =
- Server.codeComplete(FooCpp, CompletePos, CCOpts, None).get().Value;
+ Server.codeComplete(FooCpp, CompletePos, CCOpts, buildCtx(), None)
+ .get()
+ .first.Value;
EXPECT_TRUE(ContainsItem(CodeCompletionResults1, "aba"));
EXPECT_FALSE(ContainsItem(CodeCompletionResults1, "cbc"));
}
{
auto CodeCompletionResultsOverriden =
Server
- .codeComplete(FooCpp, CompletePos, CCOpts,
+ .codeComplete(FooCpp, CompletePos, CCOpts, buildCtx(),
StringRef(OverridenSourceContents))
.get()
- .Value;
+ .first.Value;
EXPECT_TRUE(ContainsItem(CodeCompletionResultsOverriden, "cbc"));
EXPECT_FALSE(ContainsItem(CodeCompletionResultsOverriden, "aba"));
}
{
auto CodeCompletionResults2 =
- Server.codeComplete(FooCpp, CompletePos, CCOpts, None).get().Value;
+ Server.codeComplete(FooCpp, CompletePos, CCOpts, buildCtx(), None)
+ .get()
+ .first.Value;
EXPECT_TRUE(ContainsItem(CodeCompletionResults2, "aba"));
EXPECT_FALSE(ContainsItem(CodeCompletionResults2, "cbc"));
}
@@ -135,8 +139,7 @@
CDB.ExtraClangFlags.push_back("-xc++");
IgnoreDiagnostics DiagConsumer;
ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
- /*StorePreamblesInMemory=*/true,
- EmptyLogger::getInstance());
+ /*StorePreamblesInMemory=*/true);
auto FooCpp = getVirtualTestFilePath("foo.cpp");
FS.Files[FooCpp] = "";
@@ -150,17 +153,17 @@
int main() { ClassWithMembers().{complete} }
)cpp",
"complete");
- Server.addDocument(FooCpp, Completion.Text);
+ Server.addDocument(FooCpp, Completion.Text, buildCtx());
clangd::CodeCompleteOptions Opts;
Opts.Limit = 2;
/// For after-dot completion we must always get consistent results.
auto Results = Server
.codeComplete(FooCpp, Completion.MarkerPos, Opts,
- StringRef(Completion.Text))
+ buildCtx(), StringRef(Completion.Text))
.get()
- .Value;
+ .first.Value;
EXPECT_TRUE(Results.isIncomplete);
EXPECT_EQ(Opts.Limit, Results.items.size());
@@ -175,8 +178,7 @@
CDB.ExtraClangFlags.push_back("-xc++");
IgnoreDiagnostics DiagConsumer;
ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
- /*StorePreamblesInMemory=*/true,
- EmptyLogger::getInstance());
+ /*StorePreamblesInMemory=*/true);
auto FooCpp = getVirtualTestFilePath("foo.cpp");
FS.Files[FooCpp] = "";
@@ -194,12 +196,13 @@
StringWithPos Completion = parseTextMarker(
formatv("{0} int main() { {1}{{complete}} }", Body, Query).str(),
"complete");
- Server.addDocument(FooCpp, Completion.Text);
+ Server.addDocument(FooCpp, Completion.Text, buildCtx());
return Server
.codeComplete(FooCpp, Completion.MarkerPos,
- clangd::CodeCompleteOptions(), StringRef(Completion.Text))
+ clangd::CodeCompleteOptions(), buildCtx(),
+ StringRef(Completion.Text))
.get()
- .Value;
+ .first.Value;
};
auto Foba = Complete("S().Foba");
@@ -291,23 +294,23 @@
auto TestWithOpts = [&](clangd::CodeCompleteOptions Opts) {
ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
- /*StorePreamblesInMemory=*/true,
- EmptyLogger::getInstance());
+ /*StorePreamblesInMemory=*/true);
// No need to sync reparses here as there are no asserts on diagnostics (or
// other async operations).
- Server.addDocument(FooCpp, GlobalCompletion.Text);
+ Server.addDocument(FooCpp, GlobalCompletion.Text, buildCtx());
StringRef MethodItemText = Opts.EnableSnippets ? "method()" : "method";
StringRef GlobalFuncItemText =
Opts.EnableSnippets ? "global_func()" : "global_func";
/// For after-dot completion we must always get consistent results.
{
- auto Results = Server
- .codeComplete(FooCpp, MemberCompletion.MarkerPos, Opts,
- StringRef(MemberCompletion.Text))
- .get()
- .Value;
+ auto Results =
+ Server
+ .codeComplete(FooCpp, MemberCompletion.MarkerPos, Opts,
+ buildCtx(), StringRef(MemberCompletion.Text))
+ .get()
+ .first.Value;
// Class members. The only items that must be present in after-dor
// completion.
@@ -339,11 +342,12 @@
}
// Global completion differs based on the Opts that were passed.
{
- auto Results = Server
- .codeComplete(FooCpp, GlobalCompletion.MarkerPos, Opts,
- StringRef(GlobalCompletion.Text))
- .get()
- .Value;
+ auto Results =
+ Server
+ .codeComplete(FooCpp, GlobalCompletion.MarkerPos, Opts,
+ buildCtx(), StringRef(GlobalCompletion.Text))
+ .get()
+ .first.Value;
// Class members. Should never be present in global completions.
EXPECT_FALSE(ContainsItem(Results, MethodItemText));
Index: unittests/clangd/ClangdTests.cpp
===================================================================
--- unittests/clangd/ClangdTests.cpp
+++ unittests/clangd/ClangdTests.cpp
@@ -9,7 +9,7 @@
#include "ClangdLSPServer.h"
#include "ClangdServer.h"
-#include "Logger.h"
+#include "Context.h"
#include "TestFS.h"
#include "clang/Config/config.h"
#include "llvm/ADT/SmallVector.h"
@@ -28,6 +28,7 @@
namespace clang {
namespace clangd {
+
namespace {
// Don't wait for async ops in clangd test more than that to avoid blocking
@@ -123,8 +124,7 @@
ErrorCheckingDiagConsumer DiagConsumer;
MockCompilationDatabase CDB;
ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
- /*StorePreamblesInMemory=*/true,
- EmptyLogger::getInstance());
+ /*StorePreamblesInMemory=*/true);
for (const auto &FileWithContents : ExtraFiles)
FS.Files[getVirtualTestFilePath(FileWithContents.first)] =
FileWithContents.second;
@@ -135,7 +135,8 @@
// Have to sync reparses because requests are processed on the calling
// thread.
- auto AddDocFuture = Server.addDocument(SourceFilename, SourceContents);
+ auto AddDocFuture =
+ Server.addDocument(SourceFilename, SourceContents, buildCtx());
auto Result = dumpASTWithoutMemoryLocs(Server, SourceFilename);
@@ -187,8 +188,7 @@
ErrorCheckingDiagConsumer DiagConsumer;
MockCompilationDatabase CDB;
ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
- /*StorePreamblesInMemory=*/true,
- EmptyLogger::getInstance());
+ /*StorePreamblesInMemory=*/true);
const auto SourceContents = R"cpp(
#include "foo.h"
@@ -203,21 +203,21 @@
FS.ExpectedFile = FooCpp;
// To sync reparses before checking for errors.
- std::future<void> ParseFuture;
+ std::future<Context> ParseFuture;
- ParseFuture = Server.addDocument(FooCpp, SourceContents);
+ ParseFuture = Server.addDocument(FooCpp, SourceContents, buildCtx());
auto DumpParse1 = dumpASTWithoutMemoryLocs(Server, FooCpp);
ASSERT_EQ(ParseFuture.wait_for(DefaultFutureTimeout),
std::future_status::ready);
EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
- ParseFuture = Server.addDocument(FooCpp, "");
+ ParseFuture = Server.addDocument(FooCpp, "", buildCtx());
auto DumpParseEmpty = dumpASTWithoutMemoryLocs(Server, FooCpp);
ASSERT_EQ(ParseFuture.wait_for(DefaultFutureTimeout),
std::future_status::ready);
EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
- ParseFuture = Server.addDocument(FooCpp, SourceContents);
+ ParseFuture = Server.addDocument(FooCpp, SourceContents, buildCtx());
auto DumpParse2 = dumpASTWithoutMemoryLocs(Server, FooCpp);
ASSERT_EQ(ParseFuture.wait_for(DefaultFutureTimeout),
std::future_status::ready);
@@ -233,8 +233,7 @@
MockCompilationDatabase CDB;
ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
- /*StorePreamblesInMemory=*/true,
- EmptyLogger::getInstance());
+ /*StorePreamblesInMemory=*/true);
const auto SourceContents = R"cpp(
#include "foo.h"
@@ -249,23 +248,23 @@
FS.ExpectedFile = FooCpp;
// To sync reparses before checking for errors.
- std::future<void> ParseFuture;
+ std::future<Context> ParseFuture;
- ParseFuture = Server.addDocument(FooCpp, SourceContents);
+ ParseFuture = Server.addDocument(FooCpp, SourceContents, buildCtx());
auto DumpParse1 = dumpASTWithoutMemoryLocs(Server, FooCpp);
ASSERT_EQ(ParseFuture.wait_for(DefaultFutureTimeout),
std::future_status::ready);
EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
FS.Files[FooH] = "";
- ParseFuture = Server.forceReparse(FooCpp);
+ ParseFuture = Server.forceReparse(FooCpp, buildCtx());
auto DumpParseDifferent = dumpASTWithoutMemoryLocs(Server, FooCpp);
ASSERT_EQ(ParseFuture.wait_for(DefaultFutureTimeout),
std::future_status::ready);
EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
FS.Files[FooH] = "int a;";
- ParseFuture = Server.forceReparse(FooCpp);
+ ParseFuture = Server.forceReparse(FooCpp, buildCtx());
auto DumpParse2 = dumpASTWithoutMemoryLocs(Server, FooCpp);
EXPECT_EQ(ParseFuture.wait_for(DefaultFutureTimeout),
std::future_status::ready);
@@ -282,8 +281,7 @@
// Run ClangdServer synchronously.
ClangdServer Server(CDB, DiagConsumer, FS,
/*AsyncThreadsCount=*/0,
- /*StorePreamblesInMemory=*/true,
- EmptyLogger::getInstance());
+ /*StorePreamblesInMemory=*/true);
auto FooCpp = getVirtualTestFilePath("foo.cpp");
const auto SourceContents = "int a;";
@@ -296,15 +294,19 @@
// No need to sync reparses, because requests are processed on the calling
// thread.
FS.Tag = "123";
- Server.addDocument(FooCpp, SourceContents);
- EXPECT_EQ(Server.codeComplete(FooCpp, Position{0, 0}, CCOpts).get().Tag,
+ Server.addDocument(FooCpp, SourceContents, buildCtx());
+ EXPECT_EQ(Server.codeComplete(FooCpp, Position{0, 0}, CCOpts, buildCtx())
+ .get()
+ .first.Tag,
FS.Tag);
EXPECT_EQ(DiagConsumer.lastVFSTag(), FS.Tag);
FS.Tag = "321";
- Server.addDocument(FooCpp, SourceContents);
+ Server.addDocument(FooCpp, SourceContents, buildCtx());
EXPECT_EQ(DiagConsumer.lastVFSTag(), FS.Tag);
- EXPECT_EQ(Server.codeComplete(FooCpp, Position{0, 0}, CCOpts).get().Tag,
+ EXPECT_EQ(Server.codeComplete(FooCpp, Position{0, 0}, CCOpts, buildCtx())
+ .get()
+ .first.Tag,
FS.Tag);
}
@@ -322,8 +324,7 @@
// Run ClangdServer synchronously.
ClangdServer Server(CDB, DiagConsumer, FS,
/*AsyncThreadsCount=*/0,
- /*StorePreamblesInMemory=*/true,
- EmptyLogger::getInstance());
+ /*StorePreamblesInMemory=*/true);
// Just a random gcc version string
SmallString<8> Version("4.9.3");
@@ -354,14 +355,14 @@
// No need to sync reparses, because requests are processed on the calling
// thread.
- Server.addDocument(FooCpp, SourceContents);
+ Server.addDocument(FooCpp, SourceContents, buildCtx());
EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
const auto SourceContentsWithError = R"cpp(
#include <string>
std::string x;
)cpp";
- Server.addDocument(FooCpp, SourceContentsWithError);
+ Server.addDocument(FooCpp, SourceContentsWithError, buildCtx());
EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
}
#endif // LLVM_ON_UNIX
@@ -372,11 +373,10 @@
MockCompilationDatabase CDB;
ClangdServer Server(CDB, DiagConsumer, FS,
/*AsyncThreadsCount=*/0,
- /*StorePreamblesInMemory=*/true,
- EmptyLogger::getInstance());
- // No need to sync reparses, because reparses are performed on the calling
- // thread to true.
+ /*StorePreamblesInMemory=*/true);
+ // No need to sync reparses, because reparses are performed on the calling
+ // thread.
auto FooCpp = getVirtualTestFilePath("foo.cpp");
const auto SourceContents1 = R"cpp(
template <class T>
@@ -392,26 +392,26 @@
// First parse files in C mode and check they produce errors.
CDB.ExtraClangFlags = {"-xc"};
- Server.addDocument(FooCpp, SourceContents1);
+ Server.addDocument(FooCpp, SourceContents1, buildCtx());
EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
- Server.addDocument(FooCpp, SourceContents2);
+ Server.addDocument(FooCpp, SourceContents2, buildCtx());
EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
// Now switch to C++ mode.
CDB.ExtraClangFlags = {"-xc++"};
// Currently, addDocument never checks if CompileCommand has changed, so we
// expect to see the errors.
- Server.addDocument(FooCpp, SourceContents1);
+ Server.addDocument(FooCpp, SourceContents1, buildCtx());
EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
- Server.addDocument(FooCpp, SourceContents2);
+ Server.addDocument(FooCpp, SourceContents2, buildCtx());
EXPECT_TRUE(DiagConsumer.hadErrorInLastDiags());
// But forceReparse should reparse the file with proper flags.
- Server.forceReparse(FooCpp);
+ Server.forceReparse(FooCpp, buildCtx());
EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
// Subsequent addDocument calls should finish without errors too.
- Server.addDocument(FooCpp, SourceContents1);
+ Server.addDocument(FooCpp, SourceContents1, buildCtx());
EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
- Server.addDocument(FooCpp, SourceContents2);
+ Server.addDocument(FooCpp, SourceContents2, buildCtx());
EXPECT_FALSE(DiagConsumer.hadErrorInLastDiags());
}
@@ -501,7 +501,7 @@
unsigned RequestsWithErrors = 0;
bool LastContentsHadErrors = false;
bool FileIsRemoved = true;
- std::future<void> LastRequestFuture;
+ std::future<Context> LastRequestFuture;
};
std::vector<RequestStats> ReqStats;
@@ -513,8 +513,7 @@
{
MockCompilationDatabase CDB;
ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
- /*StorePreamblesInMemory=*/true,
- EmptyLogger::getInstance());
+ /*StorePreamblesInMemory=*/true);
// Prepare some random distributions for the test.
std::random_device RandGen;
@@ -529,7 +528,7 @@
// Some helpers.
auto UpdateStatsOnAddDocument = [&](unsigned FileIndex, bool HadErrors,
- std::future<void> Future) {
+ std::future<Context> Future) {
auto &Stats = ReqStats[FileIndex];
if (HadErrors)
@@ -542,15 +541,15 @@
};
auto UpdateStatsOnRemoveDocument = [&](unsigned FileIndex,
- std::future<void> Future) {
+ std::future<Context> Future) {
auto &Stats = ReqStats[FileIndex];
Stats.FileIsRemoved = true;
Stats.LastRequestFuture = std::move(Future);
};
auto UpdateStatsOnForceReparse = [&](unsigned FileIndex,
- std::future<void> Future) {
+ std::future<Context> Future) {
auto &Stats = ReqStats[FileIndex];
Stats.LastRequestFuture = std::move(Future);
@@ -562,9 +561,11 @@
auto AddDocument = [&](unsigned FileIndex) {
bool ShouldHaveErrors = ShouldHaveErrorsDist(RandGen);
- auto Future = Server.addDocument(
- FilePaths[FileIndex], ShouldHaveErrors ? SourceContentsWithErrors
- : SourceContentsWithoutErrors);
+ auto Future =
+ Server.addDocument(FilePaths[FileIndex],
+ ShouldHaveErrors ? SourceContentsWithErrors
+ : SourceContentsWithoutErrors,
+ buildCtx());
UpdateStatsOnAddDocument(FileIndex, ShouldHaveErrors, std::move(Future));
};
@@ -580,7 +581,7 @@
if (ReqStats[FileIndex].FileIsRemoved)
AddDocument(FileIndex);
- auto Future = Server.forceReparse(FilePaths[FileIndex]);
+ auto Future = Server.forceReparse(FilePaths[FileIndex], buildCtx());
UpdateStatsOnForceReparse(FileIndex, std::move(Future));
};
@@ -590,7 +591,7 @@
if (ReqStats[FileIndex].FileIsRemoved)
AddDocument(FileIndex);
- auto Future = Server.removeDocument(FilePaths[FileIndex]);
+ auto Future = Server.removeDocument(FilePaths[FileIndex], buildCtx());
UpdateStatsOnRemoveDocument(FileIndex, std::move(Future));
};
@@ -609,7 +610,7 @@
// same file.
Server
.codeComplete(FilePaths[FileIndex], Pos,
- clangd::CodeCompleteOptions())
+ clangd::CodeCompleteOptions(), buildCtx())
.wait();
};
@@ -620,7 +621,8 @@
AddDocument(FileIndex);
Position Pos{LineDist(RandGen), ColumnDist(RandGen)};
- ASSERT_TRUE(!!Server.findDefinitions(FilePaths[FileIndex], Pos));
+ ASSERT_TRUE(!!Server.findDefinitions(FilePaths[FileIndex], Pos,
+ Context::empty()));
};
std::vector<std::function<void()>> AsyncRequests = {
@@ -676,8 +678,7 @@
MockCompilationDatabase CDB;
ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
- /*StorePreamblesInMemory=*/true,
- EmptyLogger::getInstance());
+ /*StorePreamblesInMemory=*/true);
auto SourceContents = R"cpp(
#include "foo.h"
@@ -802,12 +803,13 @@
std::move(StartSecondReparsePromise));
MockCompilationDatabase CDB;
- ClangdServer Server(CDB, DiagConsumer, FS, 4, /*StorePreamblesInMemory=*/true,
- EmptyLogger::getInstance());
- Server.addDocument(FooCpp, SourceContentsWithErrors);
+ ClangdServer Server(CDB, DiagConsumer, FS, 4,
+ /*StorePreamblesInMemory=*/true);
+ Server.addDocument(FooCpp, SourceContentsWithErrors, buildCtx());
StartSecondReparse.wait();
- auto Future = Server.addDocument(FooCpp, SourceContentsWithoutErrors);
+ auto Future =
+ Server.addDocument(FooCpp, SourceContentsWithoutErrors, buildCtx());
Future.wait();
}
Index: clangd/tool/ClangdMain.cpp
===================================================================
--- clangd/tool/ClangdMain.cpp
+++ clangd/tool/ClangdMain.cpp
@@ -134,6 +134,8 @@
InputMirrorStream ? InputMirrorStream.getPointer() : nullptr,
PrettyPrint);
+ clangd::LoggingSession LoggingSession(Out);
+
// If --compile-commands-dir arg was invoked, check value and override default
// path.
llvm::Optional<Path> CompileCommandsDirPath;
@@ -172,8 +174,7 @@
CCOpts.IncludeIneligibleResults = IncludeIneligibleResults;
// Initialize and run ClangdLSPServer.
ClangdLSPServer LSPServer(Out, WorkerThreadsCount, StorePreamblesInMemory,
- CCOpts, ResourceDirRef,
- CompileCommandsDirPath);
+ CCOpts, ResourceDirRef, CompileCommandsDirPath);
constexpr int NoShutdownRequestErrorCode = 1;
llvm::set_thread_name("clangd.main");
return LSPServer.run(std::cin) ? 0 : NoShutdownRequestErrorCode;
Index: clangd/ProtocolHandlers.h
===================================================================
--- clangd/ProtocolHandlers.h
+++ clangd/ProtocolHandlers.h
@@ -29,7 +29,7 @@
// The interface implemented by ClangLSPServer to handle incoming requests.
class ProtocolCallbacks {
public:
- using Ctx = RequestContext;
+ using Ctx = Context;
virtual ~ProtocolCallbacks() = default;
virtual void onInitialize(Ctx C, InitializeParams &Params) = 0;
Index: clangd/ProtocolHandlers.cpp
===================================================================
--- clangd/ProtocolHandlers.cpp
+++ clangd/ProtocolHandlers.cpp
@@ -25,17 +25,16 @@
struct HandlerRegisterer {
template <typename Param>
void operator()(StringRef Method,
- void (ProtocolCallbacks::*Handler)(RequestContext, Param)) {
+ void (ProtocolCallbacks::*Handler)(Context, Param)) {
// Capture pointers by value, as the lambda will outlive this object.
- auto *Out = this->Out;
auto *Callbacks = this->Callbacks;
Dispatcher.registerHandler(
- Method, [=](RequestContext C, const json::Expr &RawParams) {
+ Method, [=](Context C, const json::Expr &RawParams) {
typename std::remove_reference<Param>::type P;
if (fromJSON(RawParams, P)) {
(Callbacks->*Handler)(std::move(C), P);
} else {
- Out->log("Failed to decode " + Method + " request.");
+ log(C, "Failed to decode " + Method + " request.");
}
});
}
Index: clangd/Protocol.h
===================================================================
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -21,6 +21,7 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOCOL_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOCOL_H
+#include "Context.h"
#include "JSONExpr.h"
#include "llvm/ADT/Optional.h"
#include <string>
Index: clangd/Logger.h
===================================================================
--- clangd/Logger.h
+++ clangd/Logger.h
@@ -10,29 +10,35 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_LOGGER_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_LOGGER_H
+#include "Context.h"
#include "llvm/ADT/Twine.h"
namespace clang {
namespace clangd {
+/// Main logging function. Logs messages to a globalLogger().
+void log(const Context &Ctx, const llvm::Twine &Message);
+
/// Interface to allow custom logging in clangd.
class Logger {
public:
virtual ~Logger() = default;
/// Implementations of this method must be thread-safe.
- virtual void log(const llvm::Twine &Message) = 0;
+ virtual void log(const Context &Ctx, const llvm::Twine &Message) = 0;
};
-/// Logger implementation that ignores all messages.
-class EmptyLogger : public Logger {
+/// Only one LoggingSession can be active at a time.
+class LoggingSession {
public:
- static EmptyLogger &getInstance();
+ LoggingSession(clangd::Logger &Instance);
+ ~LoggingSession();
- void log(const llvm::Twine &Message) override;
+ LoggingSession(LoggingSession &&) = delete;
+ LoggingSession &operator=(LoggingSession &&) = delete;
-private:
- EmptyLogger() = default;
+ LoggingSession(LoggingSession const &) = delete;
+ LoggingSession &operator=(LoggingSession const &) = delete;
};
} // namespace clangd
Index: clangd/Logger.cpp
===================================================================
--- clangd/Logger.cpp
+++ clangd/Logger.cpp
@@ -9,11 +9,29 @@
#include "Logger.h"
-using namespace clang::clangd;
+namespace clang {
+namespace clangd {
-EmptyLogger &EmptyLogger::getInstance() {
- static EmptyLogger Logger;
- return Logger;
+namespace {
+class EmptyLogger : public Logger {
+public:
+ void log(const Context &Ctx, const llvm::Twine &Message) override {}
+};
+
+EmptyLogger Empty;
+Logger *GlobalLogger = &Empty;
+} // namespace
+
+LoggingSession::LoggingSession(clangd::Logger &Instance) {
+ assert(GlobalLogger == &Empty);
+ GlobalLogger = &Instance;
+}
+
+LoggingSession::~LoggingSession() { GlobalLogger = &Empty; }
+
+void log(const Context &Ctx, const llvm::Twine &Message) {
+ GlobalLogger->log(Ctx, Message);
}
-void EmptyLogger::log(const llvm::Twine &Message) {}
+} // namespace clangd
+} // namespace clang
Index: clangd/JSONRPCDispatcher.h
===================================================================
--- clangd/JSONRPCDispatcher.h
+++ clangd/JSONRPCDispatcher.h
@@ -10,6 +10,7 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSONRPCDISPATCHER_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSONRPCDISPATCHER_H
+#include "Context.h"
#include "JSONExpr.h"
#include "Logger.h"
#include "Protocol.h"
@@ -35,7 +36,7 @@
void writeMessage(const json::Expr &Result);
/// Write a line to the logging stream.
- void log(const Twine &Message) override;
+ void log(const Context &Ctx, const Twine &Message) override;
/// Mirror \p Message into InputMirror stream. Does nothing if InputMirror is
/// null.
@@ -53,38 +54,23 @@
std::mutex StreamMutex;
};
-/// Context object passed to handlers to allow replies.
-class RequestContext {
-public:
- RequestContext(JSONOutput &Out, StringRef Method,
- llvm::Optional<json::Expr> ID)
- : Out(Out), ID(std::move(ID)),
- Tracer(llvm::make_unique<trace::Span>(Method)) {
- if (this->ID)
- SPAN_ATTACH(tracer(), "ID", *this->ID);
- }
-
- /// Sends a successful reply.
- void reply(json::Expr &&Result);
- /// Sends an error response to the client, and logs it.
- void replyError(ErrorCode code, const llvm::StringRef &Message);
- /// Sends a request to the client.
- void call(llvm::StringRef Method, json::Expr &&Params);
-
- trace::Span &tracer() { return *Tracer; }
-
-private:
- JSONOutput &Out;
- llvm::Optional<json::Expr> ID;
- std::unique_ptr<trace::Span> Tracer;
-};
+/// Sends a successful reply. \p Ctx must either be the Context accepted by
+/// JSONRPCDispatcher::Handler or be derived from it.
+void reply(const Context &Ctx, json::Expr &&Result);
+/// Sends an error response to the client, and logs it. \p Ctx must either be
+/// the Context accepted by JSONRPCDispatcher::Handler or be derived from it.
+void replyError(const Context &Ctx, ErrorCode code,
+ const llvm::StringRef &Message);
+/// Sends a request to the client. \p Ctx must either be the Context accepted by
+/// JSONRPCDispatcher::Handler or be derived from it.
+void call(const Context &Ctx, llvm::StringRef Method, json::Expr &&Params);
/// Main JSONRPC entry point. This parses the JSONRPC "header" and calls the
/// registered Handler for the method received.
class JSONRPCDispatcher {
public:
// A handler responds to requests for a particular method name.
- using Handler = std::function<void(RequestContext, const json::Expr &)>;
+ using Handler = std::function<void(Context, const json::Expr &)>;
/// Create a new JSONRPCDispatcher. UnknownHandler is called when an unknown
/// method is received.
Index: clangd/JSONRPCDispatcher.cpp
===================================================================
--- clangd/JSONRPCDispatcher.cpp
+++ clangd/JSONRPCDispatcher.cpp
@@ -19,6 +19,12 @@
using namespace clang;
using namespace clangd;
+namespace {
+static Key<std::unique_ptr<trace::Span>> TracerKey;
+static Key<json::Expr> IDKey;
+static Key<JSONOutput *> OutKey;
+} // namespace
+
void JSONOutput::writeMessage(const json::Expr &Message) {
std::string S;
llvm::raw_string_ostream OS(S);
@@ -38,7 +44,8 @@
Outs.flush();
}
-void JSONOutput::log(const Twine &Message) {
+void JSONOutput::log(const Context &Ctx, const Twine &Message) {
+ // FIXME(ibiryukov): get rid of trace::log here.
trace::log(Message);
std::lock_guard<std::mutex> Guard(StreamMutex);
Logs << Message << '\n';
@@ -53,41 +60,44 @@
InputMirror->flush();
}
-void RequestContext::reply(json::Expr &&Result) {
+void clangd::reply(const Context &Ctx, json::Expr &&Result) {
+ auto ID = Ctx.get(IDKey);
if (!ID) {
- Out.log("Attempted to reply to a notification!");
+ log(Ctx, "Attempted to reply to a notification!");
return;
}
- SPAN_ATTACH(tracer(), "Reply", Result);
- Out.writeMessage(json::obj{
+
+ SPAN_ATTACH(*Ctx.getExisting(TracerKey), "Reply", Result);
+ Ctx.getExisting(OutKey)->writeMessage(json::obj{
{"jsonrpc", "2.0"},
{"id", *ID},
{"result", std::move(Result)},
});
}
-void RequestContext::replyError(ErrorCode code,
- const llvm::StringRef &Message) {
- Out.log("Error " + Twine(static_cast<int>(code)) + ": " + Message);
- SPAN_ATTACH(tracer(), "Error",
+void clangd::replyError(const Context &Ctx, ErrorCode code,
+ const llvm::StringRef &Message) {
+ log(Ctx, "Error " + Twine(static_cast<int>(code)) + ": " + Message);
+ SPAN_ATTACH(*Ctx.getExisting(TracerKey), "Error",
(json::obj{{"code", static_cast<int>(code)},
{"message", Message.str()}}));
- if (ID) {
- Out.writeMessage(json::obj{
+
+ if (auto ID = Ctx.get(IDKey)) {
+ Ctx.getExisting(OutKey)->writeMessage(json::obj{
{"jsonrpc", "2.0"},
{"id", *ID},
{"error",
json::obj{{"code", static_cast<int>(code)}, {"message", Message}}},
});
}
}
-void RequestContext::call(StringRef Method, json::Expr &&Params) {
+void clangd::call(const Context &Ctx, StringRef Method, json::Expr &&Params) {
// FIXME: Generate/Increment IDs for every request so that we can get proper
// replies once we need to.
- SPAN_ATTACH(tracer(), "Call",
+ SPAN_ATTACH(*Ctx.getExisting(TracerKey), "Call",
(json::obj{{"method", Method.str()}, {"params", Params}}));
- Out.writeMessage(json::obj{
+ Ctx.getExisting(OutKey)->writeMessage(json::obj{
{"jsonrpc", "2.0"},
{"id", 1},
{"method", Method},
@@ -120,8 +130,17 @@
auto I = Handlers.find(*Method);
auto &Handler = I != Handlers.end() ? I->second : UnknownHandler;
- RequestContext Ctx(Out, *Method, std::move(ID));
- SPAN_ATTACH(Ctx.tracer(), "Params", Params);
+
+ auto Tracer = llvm::make_unique<trace::Span>(*Method);
+ if (ID)
+ SPAN_ATTACH(*Tracer, "ID", *ID);
+ SPAN_ATTACH(*Tracer, "Params", Params);
+
+ auto Ctx = buildCtx()
+ .addOpt(IDKey, ID)
+ .add(OutKey, &Out)
+ .add(TracerKey, std::move(Tracer));
+
Handler(std::move(Ctx), std::move(Params));
return true;
}
@@ -164,9 +183,10 @@
// The end of headers is signified by an empty line.
if (LineRef.consume_front("Content-Length: ")) {
if (ContentLength != 0) {
- Out.log("Warning: Duplicate Content-Length header received. "
- "The previous value for this message (" +
- std::to_string(ContentLength) + ") was ignored.");
+ log(Context::empty(),
+ "Warning: Duplicate Content-Length header received. "
+ "The previous value for this message (" +
+ std::to_string(ContentLength) + ") was ignored.\n");
}
llvm::getAsUnsignedInteger(LineRef.trim(), 0, ContentLength);
@@ -185,8 +205,8 @@
// and we don't want to crash downstream because of it.
if (ContentLength > 1 << 30) { // 1024M
In.ignore(ContentLength);
- Out.log("Skipped overly large message of " + Twine(ContentLength) +
- " bytes.");
+ log(Context::empty(), "Skipped overly large message of " +
+ Twine(ContentLength) + " bytes.\n");
continue;
}
@@ -200,34 +220,37 @@
// If the stream is aborted before we read ContentLength bytes, In
// will have eofbit and failbit set.
if (!In) {
- Out.log("Input was aborted. Read only " +
- std::to_string(In.gcount()) + " bytes of expected " +
- std::to_string(ContentLength) + ".");
+ log(Context::empty(), "Input was aborted. Read only " +
+ std::to_string(In.gcount()) +
+ " bytes of expected " +
+ std::to_string(ContentLength) + ".\n");
break;
}
JSONRef = StringRef(JSON.data(), ContentLength);
}
if (auto Doc = json::parse(JSONRef)) {
// Log the formatted message.
- Out.log(llvm::formatv(Out.Pretty ? "<-- {0:2}" : "<-- {0}", *Doc));
+ log(Context::empty(),
+ llvm::formatv(Out.Pretty ? "<-- {0:2}\n" : "<-- {0}\n", *Doc));
// Finally, execute the action for this JSON message.
if (!Dispatcher.call(*Doc, Out))
- Out.log("JSON dispatch failed!");
+ log(Context::empty(), "JSON dispatch failed!\n");
} else {
// Parse error. Log the raw message.
- Out.log("<-- " + JSONRef);
- Out.log(llvm::Twine("JSON parse error: ") +
- llvm::toString(Doc.takeError()));
+ log(Context::empty(), "<-- " + JSONRef + "\n");
+ log(Context::empty(), llvm::Twine("JSON parse error: ") +
+ llvm::toString(Doc.takeError()) + "\n");
}
// If we're done, exit the loop.
if (IsDone)
break;
} else {
- Out.log("Warning: Missing Content-Length header, or message has zero "
- "length.");
+ log(Context::empty(),
+ "Warning: Missing Content-Length header, or message has zero "
+ "length.\n");
}
}
}
Index: clangd/GlobalCompilationDatabase.h
===================================================================
--- clangd/GlobalCompilationDatabase.h
+++ clangd/GlobalCompilationDatabase.h
@@ -51,7 +51,7 @@
: public GlobalCompilationDatabase {
public:
DirectoryBasedGlobalCompilationDatabase(
- clangd::Logger &Logger, llvm::Optional<Path> CompileCommandsDir);
+ llvm::Optional<Path> CompileCommandsDir);
/// Scans File's parents looking for compilation databases.
/// Any extra flags will be added.
@@ -77,8 +77,6 @@
/// Stores extra flags per file.
llvm::StringMap<std::vector<std::string>> ExtraFlagsForFile;
- /// Used for logging.
- clangd::Logger &Logger;
/// Used for command argument pointing to folder where compile_commands.json
/// is located.
llvm::Optional<Path> CompileCommandsDir;
Index: clangd/GlobalCompilationDatabase.cpp
===================================================================
--- clangd/GlobalCompilationDatabase.cpp
+++ clangd/GlobalCompilationDatabase.cpp
@@ -26,8 +26,8 @@
DirectoryBasedGlobalCompilationDatabase::
DirectoryBasedGlobalCompilationDatabase(
- clangd::Logger &Logger, llvm::Optional<Path> CompileCommandsDir)
- : Logger(Logger), CompileCommandsDir(std::move(CompileCommandsDir)) {}
+ llvm::Optional<Path> CompileCommandsDir)
+ : CompileCommandsDir(std::move(CompileCommandsDir)) {}
llvm::Optional<tooling::CompileCommand>
DirectoryBasedGlobalCompilationDatabase::getCompileCommand(PathRef File) const {
@@ -104,8 +104,9 @@
tooling::CompilationDatabase *ReturnValue =
tryLoadDatabaseFromPath(CompileCommandsDir.getValue());
if (ReturnValue == nullptr)
- Logger.log("Failed to find compilation database for " + Twine(File) +
- "in overriden directory " + CompileCommandsDir.getValue());
+ log(Context::empty(), "Failed to find compilation database for " +
+ Twine(File) + "in overriden directory " +
+ CompileCommandsDir.getValue());
return ReturnValue;
}
@@ -118,7 +119,8 @@
return CDB;
}
- Logger.log("Failed to find compilation database for " + Twine(File));
+ log(Context::empty(),
+ "Failed to find compilation database for " + Twine(File));
return nullptr;
}
Index: clangd/CodeComplete.h
===================================================================
--- clangd/CodeComplete.h
+++ clangd/CodeComplete.h
@@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETE_H
+#include "Context.h"
#include "Logger.h"
#include "Path.h"
#include "Protocol.h"
@@ -67,14 +68,14 @@
StringRef Contents, Position Pos,
IntrusiveRefCntPtr<vfs::FileSystem> VFS,
std::shared_ptr<PCHContainerOperations> PCHs,
- CodeCompleteOptions Opts, Logger &Logger);
+ CodeCompleteOptions Opts, const Context &Ctx);
/// Get signature help at a specified \p Pos in \p FileName.
SignatureHelp
signatureHelp(PathRef FileName, const tooling::CompileCommand &Command,
PrecompiledPreamble const *Preamble, StringRef Contents,
Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
- std::shared_ptr<PCHContainerOperations> PCHs, Logger &Logger);
+ std::shared_ptr<PCHContainerOperations> PCHs, const Context &Ctx);
} // namespace clangd
} // namespace clang
Index: clangd/CodeComplete.cpp
===================================================================
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -591,7 +591,7 @@
PrecompiledPreamble const *Preamble, StringRef Contents,
Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
std::shared_ptr<PCHContainerOperations> PCHs,
- Logger &Logger) {
+ const Context &Ctx) {
std::vector<const char *> ArgStrs;
for (const auto &S : Command.CommandLine)
ArgStrs.push_back(S.c_str());
@@ -634,12 +634,12 @@
SyntaxOnlyAction Action;
if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) {
- Logger.log("BeginSourceFile() failed when running codeComplete for " +
- FileName);
+ log(Ctx,
+ "BeginSourceFile() failed when running codeComplete for " + FileName);
return false;
}
if (!Action.Execute()) {
- Logger.log("Execute() failed when running codeComplete for " + FileName);
+ log(Ctx, "Execute() failed when running codeComplete for " + FileName);
return false;
}
@@ -666,7 +666,7 @@
StringRef Contents, Position Pos,
IntrusiveRefCntPtr<vfs::FileSystem> VFS,
std::shared_ptr<PCHContainerOperations> PCHs,
- CodeCompleteOptions Opts, Logger &Logger) {
+ CodeCompleteOptions Opts, const Context &Ctx) {
CompletionList Results;
std::unique_ptr<CodeCompleteConsumer> Consumer;
if (Opts.EnableSnippets) {
@@ -678,24 +678,26 @@
}
invokeCodeComplete(std::move(Consumer), Opts.getClangCompleteOpts(), FileName,
Command, Preamble, Contents, Pos, std::move(VFS),
- std::move(PCHs), Logger);
+ std::move(PCHs), Ctx);
return Results;
}
-SignatureHelp
-signatureHelp(PathRef FileName, const tooling::CompileCommand &Command,
- PrecompiledPreamble const *Preamble, StringRef Contents,
- Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
- std::shared_ptr<PCHContainerOperations> PCHs, Logger &Logger) {
+SignatureHelp signatureHelp(PathRef FileName,
+ const tooling::CompileCommand &Command,
+ PrecompiledPreamble const *Preamble,
+ StringRef Contents, Position Pos,
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+ std::shared_ptr<PCHContainerOperations> PCHs,
+ const Context &Ctx) {
SignatureHelp Result;
clang::CodeCompleteOptions Options;
Options.IncludeGlobals = false;
Options.IncludeMacros = false;
Options.IncludeCodePatterns = false;
Options.IncludeBriefComments = true;
invokeCodeComplete(llvm::make_unique<SignatureHelpCollector>(Options, Result),
Options, FileName, Command, Preamble, Contents, Pos,
- std::move(VFS), std::move(PCHs), Logger);
+ std::move(VFS), std::move(PCHs), Ctx);
return Result;
}
Index: clangd/ClangdUnitStore.h
===================================================================
--- clangd/ClangdUnitStore.h
+++ clangd/ClangdUnitStore.h
@@ -14,6 +14,7 @@
#include "ClangdUnit.h"
#include "GlobalCompilationDatabase.h"
+#include "Logger.h"
#include "Path.h"
#include "clang/Tooling/CompilationDatabase.h"
@@ -28,8 +29,7 @@
std::shared_ptr<CppFile>
getOrCreateFile(PathRef File, PathRef ResourceDir,
GlobalCompilationDatabase &CDB, bool StorePreamblesInMemory,
- std::shared_ptr<PCHContainerOperations> PCHs,
- clangd::Logger &Logger) {
+ std::shared_ptr<PCHContainerOperations> PCHs) {
std::lock_guard<std::mutex> Lock(Mutex);
auto It = OpenedFiles.find(File);
@@ -39,7 +39,7 @@
It = OpenedFiles
.try_emplace(File, CppFile::Create(File, std::move(Command),
StorePreamblesInMemory,
- std::move(PCHs), Logger))
+ std::move(PCHs)))
.first;
}
return It->second;
@@ -61,8 +61,8 @@
/// will be returned in RecreateResult.RemovedFile.
RecreateResult recreateFileIfCompileCommandChanged(
PathRef File, PathRef ResourceDir, GlobalCompilationDatabase &CDB,
- bool StorePreamblesInMemory, std::shared_ptr<PCHContainerOperations> PCHs,
- clangd::Logger &Logger);
+ bool StorePreamblesInMemory,
+ std::shared_ptr<PCHContainerOperations> PCHs);
std::shared_ptr<CppFile> getFile(PathRef File) {
std::lock_guard<std::mutex> Lock(Mutex);
Index: clangd/ClangdUnitStore.cpp
===================================================================
--- clangd/ClangdUnitStore.cpp
+++ clangd/ClangdUnitStore.cpp
@@ -29,8 +29,7 @@
CppFileCollection::RecreateResult
CppFileCollection::recreateFileIfCompileCommandChanged(
PathRef File, PathRef ResourceDir, GlobalCompilationDatabase &CDB,
- bool StorePreamblesInMemory, std::shared_ptr<PCHContainerOperations> PCHs,
- clangd::Logger &Logger) {
+ bool StorePreamblesInMemory, std::shared_ptr<PCHContainerOperations> PCHs) {
auto NewCommand = getCompileCommand(CDB, File, ResourceDir);
std::lock_guard<std::mutex> Lock(Mutex);
@@ -42,14 +41,13 @@
It = OpenedFiles
.try_emplace(File, CppFile::Create(File, std::move(NewCommand),
StorePreamblesInMemory,
- std::move(PCHs), Logger))
+ std::move(PCHs)))
.first;
} else if (!compileCommandsAreEqual(It->second->getCompileCommand(),
NewCommand)) {
Result.RemovedFile = std::move(It->second);
- It->second =
- CppFile::Create(File, std::move(NewCommand), StorePreamblesInMemory,
- std::move(PCHs), Logger);
+ It->second = CppFile::Create(File, std::move(NewCommand),
+ StorePreamblesInMemory, std::move(PCHs));
}
Result.FileInCollection = It->second;
return Result;
Index: clangd/ClangdUnit.h
===================================================================
--- clangd/ClangdUnit.h
+++ clangd/ClangdUnit.h
@@ -10,6 +10,7 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNIT_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNIT_H
+#include "Context.h"
#include "Function.h"
#include "Path.h"
#include "Protocol.h"
@@ -40,8 +41,6 @@
namespace clangd {
-class Logger;
-
/// A diagnostic with its FixIts.
struct DiagWithFixIts {
clangd::Diagnostic Diag;
@@ -69,7 +68,7 @@
std::shared_ptr<const PreambleData> Preamble,
std::unique_ptr<llvm::MemoryBuffer> Buffer,
std::shared_ptr<PCHContainerOperations> PCHs,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS, clangd::Logger &Logger);
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS, const Context &Ctx);
ParsedAST(ParsedAST &&Other);
ParsedAST &operator=(ParsedAST &&Other);
@@ -146,12 +145,12 @@
static std::shared_ptr<CppFile>
Create(PathRef FileName, tooling::CompileCommand Command,
bool StorePreamblesInMemory,
- std::shared_ptr<PCHContainerOperations> PCHs, clangd::Logger &Logger);
+ std::shared_ptr<PCHContainerOperations> PCHs);
private:
CppFile(PathRef FileName, tooling::CompileCommand Command,
bool StorePreamblesInMemory,
- std::shared_ptr<PCHContainerOperations> PCHs, clangd::Logger &Logger);
+ std::shared_ptr<PCHContainerOperations> PCHs);
public:
CppFile(CppFile const &) = delete;
@@ -173,7 +172,8 @@
/// requested in parallel (effectively cancelling this rebuild) before
/// diagnostics were produced.
llvm::Optional<std::vector<DiagWithFixIts>>
- rebuild(StringRef NewContents, IntrusiveRefCntPtr<vfs::FileSystem> VFS);
+ rebuild(StringRef NewContents, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+ const Context &Ctx);
/// Schedule a rebuild and return a deferred computation that will finish the
/// rebuild, that can be called on a different thread.
@@ -189,7 +189,7 @@
/// The future to finish rebuild returns a list of diagnostics built during
/// reparse, or None, if another deferRebuild was called before this
/// rebuild was finished.
- UniqueFunction<llvm::Optional<std::vector<DiagWithFixIts>>()>
+ UniqueFunction<llvm::Optional<std::vector<DiagWithFixIts>>(const Context &)>
deferRebuild(StringRef NewContents, IntrusiveRefCntPtr<vfs::FileSystem> VFS);
/// Returns a future to get the most fresh PreambleData for a file. The
@@ -252,18 +252,22 @@
std::shared_ptr<const PreambleData> LatestAvailablePreamble;
/// Utility class, required by clang.
std::shared_ptr<PCHContainerOperations> PCHs;
- /// Used for logging various messages.
- clangd::Logger &Logger;
};
+/// Get signature help at a specified \p Pos in \p FileName.
+SignatureHelp
+signatureHelp(PathRef FileName, const tooling::CompileCommand &Command,
+ PrecompiledPreamble const *Preamble, StringRef Contents,
+ Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+ std::shared_ptr<PCHContainerOperations> PCHs, const Context &Ctx);
/// Get the beginning SourceLocation at a specified \p Pos.
SourceLocation getBeginningOfIdentifier(ParsedAST &Unit, const Position &Pos,
const FileEntry *FE);
/// Get definition of symbol at a specified \p Pos.
std::vector<Location> findDefinitions(ParsedAST &AST, Position Pos,
- clangd::Logger &Logger);
+ const Context &Ctx);
/// For testing/debugging purposes. Note that this method deserializes all
/// unserialized Decls, so use with care.
Index: clangd/ClangdUnit.cpp
===================================================================
--- clangd/ClangdUnit.cpp
+++ clangd/ClangdUnit.cpp
@@ -170,8 +170,7 @@
std::shared_ptr<const PreambleData> Preamble,
std::unique_ptr<llvm::MemoryBuffer> Buffer,
std::shared_ptr<PCHContainerOperations> PCHs,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS,
- clangd::Logger &Logger) {
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS, const Context &Ctx) {
std::vector<DiagWithFixIts> ASTDiags;
StoreDiagsConsumer UnitDiagsConsumer(/*ref*/ ASTDiags);
@@ -189,12 +188,12 @@
auto Action = llvm::make_unique<ClangdFrontendAction>();
const FrontendInputFile &MainInput = Clang->getFrontendOpts().Inputs[0];
if (!Action->BeginSourceFile(*Clang, MainInput)) {
- Logger.log("BeginSourceFile() failed when building AST for " +
- MainInput.getFile());
+ log(Ctx, "BeginSourceFile() failed when building AST for " +
+ MainInput.getFile());
return llvm::None;
}
if (!Action->Execute())
- Logger.log("Execute() failed when building AST for " + MainInput.getFile());
+ log(Ctx, "Execute() failed when building AST for " + MainInput.getFile());
// UnitDiagsConsumer is local, we can not store it in CompilerInstance that
// has a longer lifetime.
@@ -320,7 +319,7 @@
} // namespace
std::vector<Location> clangd::findDefinitions(ParsedAST &AST, Position Pos,
- clangd::Logger &Logger) {
+ const Context &Ctx) {
const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
const FileEntry *FE = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
if (!FE)
@@ -423,23 +422,20 @@
std::shared_ptr<CppFile>
CppFile::Create(PathRef FileName, tooling::CompileCommand Command,
bool StorePreamblesInMemory,
- std::shared_ptr<PCHContainerOperations> PCHs,
- clangd::Logger &Logger) {
- return std::shared_ptr<CppFile>(new CppFile(FileName, std::move(Command),
- StorePreamblesInMemory,
- std::move(PCHs), Logger));
+ std::shared_ptr<PCHContainerOperations> PCHs) {
+ return std::shared_ptr<CppFile>(new CppFile(
+ FileName, std::move(Command), StorePreamblesInMemory, std::move(PCHs)));
}
CppFile::CppFile(PathRef FileName, tooling::CompileCommand Command,
bool StorePreamblesInMemory,
- std::shared_ptr<PCHContainerOperations> PCHs,
- clangd::Logger &Logger)
+ std::shared_ptr<PCHContainerOperations> PCHs)
: FileName(FileName), Command(std::move(Command)),
StorePreamblesInMemory(StorePreamblesInMemory), RebuildCounter(0),
- RebuildInProgress(false), PCHs(std::move(PCHs)), Logger(Logger) {
- Logger.log("Opened file " + FileName + " with command [" +
- this->Command.Directory + "] " +
- llvm::join(this->Command.CommandLine, " "));
+ RebuildInProgress(false), PCHs(std::move(PCHs)) {
+ log(Context::empty(), "Opened file " + FileName + " with command [" +
+ this->Command.Directory + "] " +
+ llvm::join(this->Command.CommandLine, " "));
std::lock_guard<std::mutex> Lock(Mutex);
LatestAvailablePreamble = nullptr;
@@ -491,12 +487,12 @@
}
llvm::Optional<std::vector<DiagWithFixIts>>
-CppFile::rebuild(StringRef NewContents,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
- return deferRebuild(NewContents, std::move(VFS))();
+CppFile::rebuild(StringRef NewContents, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+ const Context &Ctx) {
+ return deferRebuild(NewContents, std::move(VFS))(Ctx);
}
-UniqueFunction<llvm::Optional<std::vector<DiagWithFixIts>>()>
+UniqueFunction<llvm::Optional<std::vector<DiagWithFixIts>>(const Context &)>
CppFile::deferRebuild(StringRef NewContents,
IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
std::shared_ptr<const PreambleData> OldPreamble;
@@ -533,9 +529,10 @@
// Don't let this CppFile die before rebuild is finished.
std::shared_ptr<CppFile> That = shared_from_this();
auto FinishRebuild = [OldPreamble, VFS, RequestRebuildCounter, PCHs,
- That](std::string NewContents) mutable // 'mutable' to
- // allow changing
- // OldPreamble.
+ That](std::string NewContents,
+ const Context &Ctx) mutable // 'mutable' to
+ // allow changing
+ // OldPreamble.
-> llvm::Optional<std::vector<DiagWithFixIts>> {
// Only one execution of this method is possible at a time.
// RebuildGuard will wait for any ongoing rebuilds to finish and will put us
@@ -631,9 +628,8 @@
{
trace::Span Tracer("Build");
SPAN_ATTACH(Tracer, "File", That->FileName);
- NewAST =
- ParsedAST::Build(std::move(CI), std::move(NewPreamble),
- std::move(ContentsBuffer), PCHs, VFS, That->Logger);
+ NewAST = ParsedAST::Build(std::move(CI), std::move(NewPreamble),
+ std::move(ContentsBuffer), PCHs, VFS, Ctx);
}
if (NewAST) {
Index: clangd/ClangdServer.h
===================================================================
--- clangd/ClangdServer.h
+++ clangd/ClangdServer.h
@@ -37,8 +37,6 @@
namespace clangd {
-class Logger;
-
/// Turn a [line, column] pair into an offset in Code.
size_t positionToOffset(StringRef Code, Position P);
@@ -205,13 +203,10 @@
///
/// \p StorePreamblesInMemory defines whether the Preambles generated by
/// clangd are stored in-memory or on disk.
- ///
- /// Various messages are logged using \p Logger.
ClangdServer(GlobalCompilationDatabase &CDB,
DiagnosticsConsumer &DiagConsumer,
FileSystemProvider &FSProvider, unsigned AsyncThreadsCount,
bool StorePreamblesInMemory,
- clangd::Logger &Logger,
llvm::Optional<StringRef> ResourceDir = llvm::None);
/// Set the root path of the workspace.
@@ -223,17 +218,18 @@
/// constructor will receive onDiagnosticsReady callback.
/// \return A future that will become ready when the rebuild (including
/// diagnostics) is finished.
- std::future<void> addDocument(PathRef File, StringRef Contents);
+ std::future<Context> addDocument(PathRef File, StringRef Contents,
+ Context Ctx);
/// Remove \p File from list of tracked files, schedule a request to free
/// resources associated with it.
/// \return A future that will become ready when the file is removed and all
/// associated resources are freed.
- std::future<void> removeDocument(PathRef File);
+ std::future<Context> removeDocument(PathRef File, Context Ctx);
/// Force \p File to be reparsed using the latest contents.
/// Will also check if CompileCommand, provided by GlobalCompilationDatabase
/// for \p File has changed. If it has, will remove currently stored Preamble
/// and AST and rebuild them from scratch.
- std::future<void> forceReparse(PathRef File);
+ std::future<Context> forceReparse(PathRef File, Context Ctx);
/// DEPRECATED. Please use a callback-based version, this API is deprecated
/// and will soon be removed.
@@ -252,19 +248,25 @@
/// This method should only be called for currently tracked files. However, it
/// is safe to call removeDocument for \p File after this method returns, even
/// while returned future is not yet ready.
- std::future<Tagged<CompletionList>>
+ ///
+ /// The callers are responsible for making sure \p Ctx stays alive until
+ /// std::future<> is ready (i.e. wait() or get() returns)
+ std::future<std::pair<Tagged<CompletionList>, Context>>
codeComplete(PathRef File, Position Pos,
- const clangd::CodeCompleteOptions &Opts,
+ const clangd::CodeCompleteOptions &Opts, Context Ctx,
llvm::Optional<StringRef> OverridenContents = llvm::None,
IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS = nullptr);
/// A version of `codeComplete` that runs \p Callback on the processing thread
/// when codeComplete results become available.
- void codeComplete(UniqueFunction<void(Tagged<CompletionList>)> Callback,
- PathRef File, Position Pos,
- const clangd::CodeCompleteOptions &Opts,
- llvm::Optional<StringRef> OverridenContents = llvm::None,
- IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS = nullptr);
+ /// The callers are responsible for making sure \p Ctx stays alive until \p
+ /// Callback is executed.
+ void
+ codeComplete(UniqueFunction<void(Tagged<CompletionList>, Context)> Callback,
+ PathRef File, Position Pos,
+ const clangd::CodeCompleteOptions &Opts, Context Ctx,
+ llvm::Optional<StringRef> OverridenContents = llvm::None,
+ IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS = nullptr);
/// Provide signature help for \p File at \p Pos. If \p OverridenContents is
/// not None, they will used only for signature help, i.e. no diagnostics
@@ -274,13 +276,13 @@
/// vfs::FileSystem used for signature help. This method should only be called
/// for currently tracked files.
llvm::Expected<Tagged<SignatureHelp>>
- signatureHelp(PathRef File, Position Pos,
+ signatureHelp(PathRef File, Position Pos, const Context &Ctx,
llvm::Optional<StringRef> OverridenContents = llvm::None,
IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS = nullptr);
/// Get definition of symbol at a specified \p Line and \p Column in \p File.
- llvm::Expected<Tagged<std::vector<Location>>> findDefinitions(PathRef File,
- Position Pos);
+ llvm::Expected<Tagged<std::vector<Location>>>
+ findDefinitions(PathRef File, Position Pos, const Context &Ctx);
/// Helper function that returns a path to the corresponding source file when
/// given a header file and vice versa.
@@ -295,7 +297,8 @@
/// Rename all occurrences of the symbol at the \p Pos in \p File to
/// \p NewName.
Expected<std::vector<tooling::Replacement>> rename(PathRef File, Position Pos,
- llvm::StringRef NewName);
+ llvm::StringRef NewName,
+ const Context &Ctx);
/// Gets current document contents for \p File. \p File must point to a
/// currently tracked file.
@@ -311,14 +314,13 @@
void onFileEvent(const DidChangeWatchedFilesParams &Params);
private:
- std::future<void>
- scheduleReparseAndDiags(PathRef File, VersionedDraft Contents,
- std::shared_ptr<CppFile> Resources,
- Tagged<IntrusiveRefCntPtr<vfs::FileSystem>> TaggedFS);
+ std::future<Context> scheduleReparseAndDiags(
+ PathRef File, VersionedDraft Contents, std::shared_ptr<CppFile> Resources,
+ Tagged<IntrusiveRefCntPtr<vfs::FileSystem>> TaggedFS, Context Ctx);
- std::future<void> scheduleCancelRebuild(std::shared_ptr<CppFile> Resources);
+ std::future<Context> scheduleCancelRebuild(std::shared_ptr<CppFile> Resources,
+ Context Ctx);
- clangd::Logger &Logger;
GlobalCompilationDatabase &CDB;
DiagnosticsConsumer &DiagConsumer;
FileSystemProvider &FSProvider;
Index: clangd/ClangdServer.cpp
===================================================================
--- clangd/ClangdServer.cpp
+++ clangd/ClangdServer.cpp
@@ -28,14 +28,16 @@
namespace {
-class FulfillPromiseGuard {
+class FulfillContextPromiseGuard {
public:
- FulfillPromiseGuard(std::promise<void> &Promise) : Promise(Promise) {}
+ FulfillContextPromiseGuard(std::promise<Context> &Promise, Context &Ctx)
+ : Promise(Promise), Ctx(Ctx) {}
- ~FulfillPromiseGuard() { Promise.set_value(); }
+ ~FulfillContextPromiseGuard() { Promise.set_value(std::move(Ctx)); }
private:
- std::promise<void> &Promise;
+ std::promise<Context> &Promise;
+ Context &Ctx;
};
std::vector<tooling::Replacement> formatCode(StringRef Code, StringRef Filename,
@@ -173,10 +175,9 @@
DiagnosticsConsumer &DiagConsumer,
FileSystemProvider &FSProvider,
unsigned AsyncThreadsCount,
- bool StorePreamblesInMemory, clangd::Logger &Logger,
+ bool StorePreamblesInMemory,
llvm::Optional<StringRef> ResourceDir)
- : Logger(Logger), CDB(CDB), DiagConsumer(DiagConsumer),
- FSProvider(FSProvider),
+ : CDB(CDB), DiagConsumer(DiagConsumer), FSProvider(FSProvider),
ResourceDir(ResourceDir ? ResourceDir->str() : getStandardResourceDir()),
PCHs(std::make_shared<PCHContainerOperations>()),
StorePreamblesInMemory(StorePreamblesInMemory),
@@ -189,65 +190,69 @@
this->RootPath = NewRootPath;
}
-std::future<void> ClangdServer::addDocument(PathRef File, StringRef Contents) {
+std::future<Context> ClangdServer::addDocument(PathRef File, StringRef Contents,
+ Context Ctx) {
DocVersion Version = DraftMgr.updateDraft(File, Contents);
auto TaggedFS = FSProvider.getTaggedFileSystem(File);
std::shared_ptr<CppFile> Resources = Units.getOrCreateFile(
- File, ResourceDir, CDB, StorePreamblesInMemory, PCHs, Logger);
+ File, ResourceDir, CDB, StorePreamblesInMemory, PCHs);
return scheduleReparseAndDiags(File, VersionedDraft{Version, Contents.str()},
- std::move(Resources), std::move(TaggedFS));
+ std::move(Resources), std::move(TaggedFS),
+ std::move(Ctx));
}
-std::future<void> ClangdServer::removeDocument(PathRef File) {
+std::future<Context> ClangdServer::removeDocument(PathRef File, Context Ctx) {
DraftMgr.removeDraft(File);
std::shared_ptr<CppFile> Resources = Units.removeIfPresent(File);
- return scheduleCancelRebuild(std::move(Resources));
+ return scheduleCancelRebuild(std::move(Resources), std::move(Ctx));
}
-std::future<void> ClangdServer::forceReparse(PathRef File) {
+std::future<Context> ClangdServer::forceReparse(PathRef File, Context Ctx) {
auto FileContents = DraftMgr.getDraft(File);
assert(FileContents.Draft &&
"forceReparse() was called for non-added document");
auto TaggedFS = FSProvider.getTaggedFileSystem(File);
auto Recreated = Units.recreateFileIfCompileCommandChanged(
- File, ResourceDir, CDB, StorePreamblesInMemory, PCHs, Logger);
+ File, ResourceDir, CDB, StorePreamblesInMemory, PCHs);
- // Note that std::future from this cleanup action is ignored.
- scheduleCancelRebuild(std::move(Recreated.RemovedFile));
+ // Note that std::future from this cleanup action.
+ // FIXME(ibiryukov): We use a global context here, should not fork the action
+ // instead.
+ scheduleCancelRebuild(std::move(Recreated.RemovedFile), buildCtx());
// Schedule a reparse.
return scheduleReparseAndDiags(File, std::move(FileContents),
std::move(Recreated.FileInCollection),
- std::move(TaggedFS));
+ std::move(TaggedFS), std::move(Ctx));
}
-std::future<Tagged<CompletionList>>
+std::future<std::pair<Tagged<CompletionList>, Context>>
ClangdServer::codeComplete(PathRef File, Position Pos,
- const clangd::CodeCompleteOptions &Opts,
+ const clangd::CodeCompleteOptions &Opts, Context Ctx,
llvm::Optional<StringRef> OverridenContents,
IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS) {
- using ResultType = Tagged<CompletionList>;
+ using ResultType = std::pair<Tagged<CompletionList>, Context>;
std::promise<ResultType> ResultPromise;
auto Callback = [](std::promise<ResultType> ResultPromise,
- ResultType Result) -> void {
- ResultPromise.set_value(std::move(Result));
+ Tagged<CompletionList> Result, Context Ctx) -> void {
+ ResultPromise.set_value({std::move(Result), std::move(Ctx)});
};
std::future<ResultType> ResultFuture = ResultPromise.get_future();
codeComplete(BindWithForward(Callback, std::move(ResultPromise)), File, Pos,
- Opts, OverridenContents, UsedFS);
+ Opts, std::move(Ctx), OverridenContents, UsedFS);
return ResultFuture;
}
void ClangdServer::codeComplete(
- UniqueFunction<void(Tagged<CompletionList>)> Callback, PathRef File,
- Position Pos, const clangd::CodeCompleteOptions &Opts,
- llvm::Optional<StringRef> OverridenContents,
+ UniqueFunction<void(Tagged<CompletionList>, Context)> Callback,
+ PathRef File, Position Pos, const clangd::CodeCompleteOptions &Opts,
+ Context Ctx, llvm::Optional<StringRef> OverridenContents,
IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS) {
- using CallbackType = UniqueFunction<void(Tagged<CompletionList>)>;
+ using CallbackType = UniqueFunction<void(Tagged<CompletionList>, Context)>;
std::string Contents;
if (OverridenContents) {
@@ -278,7 +283,7 @@
// A task that will be run asynchronously.
auto Task =
// 'mutable' to reassign Preamble variable.
- [=](CallbackType Callback) mutable {
+ [=](CallbackType Callback, Context Ctx) mutable {
if (!Preamble) {
// Maybe we built some preamble before processing this request.
Preamble = Resources->getPossiblyStalePreamble();
@@ -289,16 +294,18 @@
CompletionList Result = clangd::codeComplete(
File, Resources->getCompileCommand(),
Preamble ? &Preamble->Preamble : nullptr, Contents, Pos,
- TaggedFS.Value, PCHs, CodeCompleteOpts, Logger);
+ TaggedFS.Value, PCHs, CodeCompleteOpts, Ctx);
- Callback(make_tagged(std::move(Result), std::move(TaggedFS.Tag)));
+ Callback(make_tagged(std::move(Result), std::move(TaggedFS.Tag)),
+ std::move(Ctx));
};
- WorkScheduler.addToFront(std::move(Task), std::move(Callback));
+ WorkScheduler.addToFront(std::move(Task), std::move(Callback),
+ std::move(Ctx));
}
llvm::Expected<Tagged<SignatureHelp>>
-ClangdServer::signatureHelp(PathRef File, Position Pos,
+ClangdServer::signatureHelp(PathRef File, Position Pos, const Context &Ctx,
llvm::Optional<StringRef> OverridenContents,
IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS) {
std::string DraftStorage;
@@ -324,10 +331,10 @@
llvm::errc::invalid_argument);
auto Preamble = Resources->getPossiblyStalePreamble();
- auto Result = clangd::signatureHelp(File, Resources->getCompileCommand(),
- Preamble ? &Preamble->Preamble : nullptr,
- *OverridenContents, Pos, TaggedFS.Value,
- PCHs, Logger);
+ auto Result =
+ clangd::signatureHelp(File, Resources->getCompileCommand(),
+ Preamble ? &Preamble->Preamble : nullptr,
+ *OverridenContents, Pos, TaggedFS.Value, PCHs, Ctx);
return make_tagged(std::move(Result), TaggedFS.Tag);
}
@@ -361,7 +368,8 @@
}
Expected<std::vector<tooling::Replacement>>
-ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName) {
+ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
+ const Context &Ctx) {
std::string Code = getDocument(File);
std::shared_ptr<CppFile> Resources = Units.getFile(File);
RefactoringResultCollector ResultCollector;
@@ -432,7 +440,7 @@
}
llvm::Expected<Tagged<std::vector<Location>>>
-ClangdServer::findDefinitions(PathRef File, Position Pos) {
+ClangdServer::findDefinitions(PathRef File, Position Pos, const Context &Ctx) {
auto TaggedFS = FSProvider.getTaggedFileSystem(File);
std::shared_ptr<CppFile> Resources = Units.getFile(File);
@@ -442,10 +450,10 @@
llvm::errc::invalid_argument);
std::vector<Location> Result;
- Resources->getAST().get()->runUnderLock([Pos, &Result, this](ParsedAST *AST) {
+ Resources->getAST().get()->runUnderLock([Pos, &Result, &Ctx](ParsedAST *AST) {
if (!AST)
return;
- Result = clangd::findDefinitions(*AST, Pos, Logger);
+ Result = clangd::findDefinitions(*AST, Pos, Ctx);
});
return make_tagged(std::move(Result), TaggedFS.Tag);
}
@@ -509,32 +517,33 @@
return llvm::None;
}
-std::future<void> ClangdServer::scheduleReparseAndDiags(
+std::future<Context> ClangdServer::scheduleReparseAndDiags(
PathRef File, VersionedDraft Contents, std::shared_ptr<CppFile> Resources,
- Tagged<IntrusiveRefCntPtr<vfs::FileSystem>> TaggedFS) {
+ Tagged<IntrusiveRefCntPtr<vfs::FileSystem>> TaggedFS, Context Ctx) {
assert(Contents.Draft && "Draft must have contents");
- UniqueFunction<llvm::Optional<std::vector<DiagWithFixIts>>()>
+ UniqueFunction<llvm::Optional<std::vector<DiagWithFixIts>>(const Context &)>
DeferredRebuild =
Resources->deferRebuild(*Contents.Draft, TaggedFS.Value);
- std::promise<void> DonePromise;
- std::future<void> DoneFuture = DonePromise.get_future();
+ std::promise<Context> DonePromise;
+ std::future<Context> DoneFuture = DonePromise.get_future();
DocVersion Version = Contents.Version;
Path FileStr = File;
VFSTag Tag = TaggedFS.Tag;
auto ReparseAndPublishDiags =
[this, FileStr, Version,
- Tag](UniqueFunction<llvm::Optional<std::vector<DiagWithFixIts>>()>
+ Tag](UniqueFunction<llvm::Optional<std::vector<DiagWithFixIts>>(
+ const Context &)>
DeferredRebuild,
- std::promise<void> DonePromise) -> void {
- FulfillPromiseGuard Guard(DonePromise);
+ std::promise<Context> DonePromise, Context Ctx) -> void {
+ FulfillContextPromiseGuard Guard(DonePromise, Ctx);
auto CurrentVersion = DraftMgr.getVersion(FileStr);
if (CurrentVersion != Version)
return; // This request is outdated
- auto Diags = DeferredRebuild();
+ auto Diags = DeferredRebuild(Ctx);
if (!Diags)
return; // A new reparse was requested before this one completed.
@@ -555,28 +564,31 @@
};
WorkScheduler.addToFront(std::move(ReparseAndPublishDiags),
- std::move(DeferredRebuild), std::move(DonePromise));
+ std::move(DeferredRebuild), std::move(DonePromise),
+ std::move(Ctx));
return DoneFuture;
}
-std::future<void>
-ClangdServer::scheduleCancelRebuild(std::shared_ptr<CppFile> Resources) {
- std::promise<void> DonePromise;
- std::future<void> DoneFuture = DonePromise.get_future();
+std::future<Context>
+ClangdServer::scheduleCancelRebuild(std::shared_ptr<CppFile> Resources,
+ Context Ctx) {
+ std::promise<Context> DonePromise;
+ std::future<Context> DoneFuture = DonePromise.get_future();
if (!Resources) {
// No need to schedule any cleanup.
- DonePromise.set_value();
+ DonePromise.set_value(std::move(Ctx));
return DoneFuture;
}
UniqueFunction<void()> DeferredCancel = Resources->deferCancelRebuild();
- auto CancelReparses = [Resources](std::promise<void> DonePromise,
- UniqueFunction<void()> DeferredCancel) {
- FulfillPromiseGuard Guard(DonePromise);
+ auto CancelReparses = [Resources](std::promise<Context> DonePromise,
+ UniqueFunction<void()> DeferredCancel,
+ Context Ctx) {
+ FulfillContextPromiseGuard Guard(DonePromise, Ctx);
DeferredCancel();
};
WorkScheduler.addToFront(std::move(CancelReparses), std::move(DonePromise),
- std::move(DeferredCancel));
+ std::move(DeferredCancel), std::move(Ctx));
return DoneFuture;
}
Index: clangd/ClangdLSPServer.cpp
===================================================================
--- clangd/ClangdLSPServer.cpp
+++ clangd/ClangdLSPServer.cpp
@@ -35,7 +35,7 @@
} // namespace
void ClangdLSPServer::onInitialize(Ctx C, InitializeParams &Params) {
- C.reply(json::obj{
+ reply(C, json::obj{
{{"capabilities",
json::obj{
{"textDocumentSync", 1},
@@ -72,7 +72,7 @@
void ClangdLSPServer::onShutdown(Ctx C, ShutdownParams &Params) {
// Do essentially nothing, just say we're ready to exit.
ShutdownRequestReceived = true;
- C.reply(nullptr);
+ reply(C, nullptr);
}
void ClangdLSPServer::onExit(Ctx C, ExitParams &Params) { IsDone = true; }
@@ -82,17 +82,19 @@
if (Params.metadata && !Params.metadata->extraFlags.empty())
CDB.setExtraFlagsForFile(Params.textDocument.uri.file,
std::move(Params.metadata->extraFlags));
- Server.addDocument(Params.textDocument.uri.file, Params.textDocument.text);
+ Server.addDocument(Params.textDocument.uri.file, Params.textDocument.text,
+ std::move(C));
}
void ClangdLSPServer::onDocumentDidChange(Ctx C,
DidChangeTextDocumentParams &Params) {
if (Params.contentChanges.size() != 1)
- return C.replyError(ErrorCode::InvalidParams,
- "can only apply one change at a time");
+ return replyError(C, ErrorCode::InvalidParams,
+ "can only apply one change at a time");
// We only support full syncing right now.
Server.addDocument(Params.textDocument.uri.file,
- Params.contentChanges[0].text);
+ Params.contentChanges[0].text,
+ std::move(C));
}
void ClangdLSPServer::onFileEvent(Ctx C, DidChangeWatchedFilesParams &Params) {
@@ -113,62 +115,63 @@
ApplyWorkspaceEditParams ApplyEdit;
ApplyEdit.edit = *Params.workspaceEdit;
- C.reply("Fix applied.");
+ reply(C, "Fix applied.");
// We don't need the response so id == 1 is OK.
// Ideally, we would wait for the response and if there is no error, we
// would reply success/failure to the original RPC.
- C.call("workspace/applyEdit", ApplyEdit);
+ call(C, "workspace/applyEdit", ApplyEdit);
} else {
// We should not get here because ExecuteCommandParams would not have
// parsed in the first place and this handler should not be called. But if
// more commands are added, this will be here has a safe guard.
- C.replyError(
+ replyError(C,
ErrorCode::InvalidParams,
llvm::formatv("Unsupported command \"{0}\".", Params.command).str());
}
}
void ClangdLSPServer::onRename(Ctx C, RenameParams &Params) {
auto File = Params.textDocument.uri.file;
- auto Replacements = Server.rename(File, Params.position, Params.newName);
+ auto Replacements =
+ Server.rename(File, Params.position, Params.newName, C);
if (!Replacements) {
- C.replyError(ErrorCode::InternalError,
- llvm::toString(Replacements.takeError()));
+ replyError(C, ErrorCode::InternalError,
+ llvm::toString(Replacements.takeError()));
return;
}
std::string Code = Server.getDocument(File);
std::vector<TextEdit> Edits = replacementsToEdits(Code, *Replacements);
WorkspaceEdit WE;
WE.changes = {{Params.textDocument.uri.uri, Edits}};
- C.reply(WE);
+ reply(C, WE);
}
void ClangdLSPServer::onDocumentDidClose(Ctx C,
DidCloseTextDocumentParams &Params) {
- Server.removeDocument(Params.textDocument.uri.file);
+ Server.removeDocument(Params.textDocument.uri.file, std::move(C));
}
void ClangdLSPServer::onDocumentOnTypeFormatting(
Ctx C, DocumentOnTypeFormattingParams &Params) {
auto File = Params.textDocument.uri.file;
std::string Code = Server.getDocument(File);
- C.reply(json::ary(
+ reply(C, json::ary(
replacementsToEdits(Code, Server.formatOnType(File, Params.position))));
}
void ClangdLSPServer::onDocumentRangeFormatting(
Ctx C, DocumentRangeFormattingParams &Params) {
auto File = Params.textDocument.uri.file;
std::string Code = Server.getDocument(File);
- C.reply(json::ary(
+ reply(C, json::ary(
replacementsToEdits(Code, Server.formatRange(File, Params.range))));
}
void ClangdLSPServer::onDocumentFormatting(Ctx C,
DocumentFormattingParams &Params) {
auto File = Params.textDocument.uri.file;
std::string Code = Server.getDocument(File);
- C.reply(json::ary(replacementsToEdits(Code, Server.formatFile(File))));
+ reply(C, json::ary(replacementsToEdits(Code, Server.formatFile(File))));
}
void ClangdLSPServer::onCodeAction(Ctx C, CodeActionParams &Params) {
@@ -190,68 +193,67 @@
});
}
}
- C.reply(std::move(Commands));
+ reply(C, std::move(Commands));
}
void ClangdLSPServer::onCompletion(Ctx C, TextDocumentPositionParams &Params) {
- auto List =
- Server
- .codeComplete(
- Params.textDocument.uri.file,
- Position{Params.position.line, Params.position.character}, CCOpts)
- .get() // FIXME(ibiryukov): This could be made async if we
- // had an API that would allow to attach callbacks to
- // futures returned by ClangdServer.
- .Value;
- C.reply(List);
+ auto List = Server
+ .codeComplete(
+ Params.textDocument.uri.file,
+ Position{Params.position.line, Params.position.character},
+ CCOpts, C.derive())
+ .get() // FIXME(ibiryukov): This could be made async if we
+ // had an API that would allow to attach callbacks to
+ // futures returned by ClangdServer.
+ .first.Value;
+ reply(C, List);
}
void ClangdLSPServer::onSignatureHelp(Ctx C,
TextDocumentPositionParams &Params) {
auto SignatureHelp = Server.signatureHelp(
Params.textDocument.uri.file,
- Position{Params.position.line, Params.position.character});
+ Position{Params.position.line, Params.position.character}, C);
if (!SignatureHelp)
- return C.replyError(ErrorCode::InvalidParams,
- llvm::toString(SignatureHelp.takeError()));
- C.reply(SignatureHelp->Value);
+ return replyError(C, ErrorCode::InvalidParams,
+ llvm::toString(SignatureHelp.takeError()));
+ reply(C, SignatureHelp->Value);
}
void ClangdLSPServer::onGoToDefinition(Ctx C,
TextDocumentPositionParams &Params) {
auto Items = Server.findDefinitions(
Params.textDocument.uri.file,
- Position{Params.position.line, Params.position.character});
+ Position{Params.position.line, Params.position.character}, C);
if (!Items)
- return C.replyError(ErrorCode::InvalidParams,
- llvm::toString(Items.takeError()));
- C.reply(json::ary(Items->Value));
+ return replyError(C, ErrorCode::InvalidParams,
+ llvm::toString(Items.takeError()));
+ reply(C, json::ary(Items->Value));
}
void ClangdLSPServer::onSwitchSourceHeader(Ctx C,
TextDocumentIdentifier &Params) {
llvm::Optional<Path> Result = Server.switchSourceHeader(Params.uri.file);
std::string ResultUri;
- C.reply(Result ? URI::fromFile(*Result).uri : "");
+ reply(C, Result ? URI::fromFile(*Result).uri : "");
}
ClangdLSPServer::ClangdLSPServer(JSONOutput &Out, unsigned AsyncThreadsCount,
bool StorePreamblesInMemory,
const clangd::CodeCompleteOptions &CCOpts,
llvm::Optional<StringRef> ResourceDir,
llvm::Optional<Path> CompileCommandsDir)
- : Out(Out), CDB(/*Logger=*/Out, std::move(CompileCommandsDir)),
- CCOpts(CCOpts), Server(CDB, /*DiagConsumer=*/*this, FSProvider,
- AsyncThreadsCount, StorePreamblesInMemory,
- /*Logger=*/Out, ResourceDir) {}
+ : Out(Out), CDB(std::move(CompileCommandsDir)), CCOpts(CCOpts),
+ Server(CDB, /*DiagConsumer=*/*this, FSProvider, AsyncThreadsCount,
+ StorePreamblesInMemory, ResourceDir) {}
bool ClangdLSPServer::run(std::istream &In) {
assert(!IsDone && "Run was called before");
// Set up JSONRPCDispatcher.
JSONRPCDispatcher Dispatcher(
- [](RequestContext Ctx, const json::Expr &Params) {
- Ctx.replyError(ErrorCode::MethodNotFound, "method not found");
+ [](Context Ctx, const json::Expr &Params) {
+ replyError(Ctx, ErrorCode::MethodNotFound, "method not found");
});
registerCallbackHandlers(Dispatcher, Out, /*Callbacks=*/*this);
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits