2017-05-16 17:38:59 +08:00
|
|
|
//===--- ClangdLSPServer.cpp - LSP server ------------------------*- C++-*-===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2017-05-16 17:38:59 +08:00
|
|
|
//
|
2018-08-15 00:03:32 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2017-05-16 17:38:59 +08:00
|
|
|
|
|
|
|
#include "ClangdLSPServer.h"
|
2019-10-15 22:20:52 +08:00
|
|
|
#include "Context.h"
|
2018-03-12 23:28:22 +08:00
|
|
|
#include "Diagnostics.h"
|
2019-09-09 20:28:44 +08:00
|
|
|
#include "DraftStore.h"
|
2019-05-29 18:01:00 +08:00
|
|
|
#include "FormattedString.h"
|
2019-06-26 15:45:27 +08:00
|
|
|
#include "GlobalCompilationDatabase.h"
|
[clangd] Interfaces for writing code tweaks
Summary:
The code tweaks are an implementation of mini-refactorings exposed
via the LSP code actions. They run in two stages:
- Stage 1. Decides whether the action is available to the user and
collects all the information required to finish the action.
Should be cheap, since this will run over all the actions known to
clangd on each textDocument/codeAction request from the client.
- Stage 2. Uses information from stage 1 to produce the actual edits
that the code action should perform. This stage can be expensive and
will only run if the user chooses to perform the specified action in
the UI.
One unfortunate consequence of this change is increased latency of
processing the textDocument/codeAction requests, which now wait for an
AST. However, we cannot avoid this with what we have available in the LSP
today.
Reviewers: kadircet, ioeric, hokein, sammccall
Reviewed By: sammccall
Subscribers: mgrang, mgorny, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D56267
llvm-svn: 352494
2019-01-29 22:17:36 +08:00
|
|
|
#include "Protocol.h"
|
2019-07-04 15:53:12 +08:00
|
|
|
#include "SemanticHighlighting.h"
|
2017-12-19 20:23:48 +08:00
|
|
|
#include "SourceCode.h"
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
#include "Trace.h"
|
2018-01-29 23:37:46 +08:00
|
|
|
#include "URI.h"
|
2019-06-18 21:37:54 +08:00
|
|
|
#include "refactor/Tweak.h"
|
2020-03-03 19:25:46 +08:00
|
|
|
#include "clang/Basic/Version.h"
|
[clangd] Interfaces for writing code tweaks
Summary:
The code tweaks are an implementation of mini-refactorings exposed
via the LSP code actions. They run in two stages:
- Stage 1. Decides whether the action is available to the user and
collects all the information required to finish the action.
Should be cheap, since this will run over all the actions known to
clangd on each textDocument/codeAction request from the client.
- Stage 2. Uses information from stage 1 to produce the actual edits
that the code action should perform. This stage can be expensive and
will only run if the user chooses to perform the specified action in
the UI.
One unfortunate consequence of this change is increased latency of
processing the textDocument/codeAction requests, which now wait for an
AST. However, we cannot avoid this with what we have available in the LSP
today.
Reviewers: kadircet, ioeric, hokein, sammccall
Reviewed By: sammccall
Subscribers: mgrang, mgorny, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D56267
llvm-svn: 352494
2019-01-29 22:17:36 +08:00
|
|
|
#include "clang/Tooling/Core/Replacement.h"
|
2019-06-26 15:45:27 +08:00
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
2019-03-28 01:47:49 +08:00
|
|
|
#include "llvm/ADT/Optional.h"
|
2018-08-24 21:09:41 +08:00
|
|
|
#include "llvm/ADT/ScopeExit.h"
|
2019-09-09 20:28:44 +08:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
2019-09-24 21:38:33 +08:00
|
|
|
#include "llvm/ADT/iterator_range.h"
|
2018-03-16 22:30:42 +08:00
|
|
|
#include "llvm/Support/Errc.h"
|
[clangd] Interfaces for writing code tweaks
Summary:
The code tweaks are an implementation of mini-refactorings exposed
via the LSP code actions. They run in two stages:
- Stage 1. Decides whether the action is available to the user and
collects all the information required to finish the action.
Should be cheap, since this will run over all the actions known to
clangd on each textDocument/codeAction request from the client.
- Stage 2. Uses information from stage 1 to produce the actual edits
that the code action should perform. This stage can be expensive and
will only run if the user chooses to perform the specified action in
the UI.
One unfortunate consequence of this change is increased latency of
processing the textDocument/codeAction requests, which now wait for an
AST. However, we cannot avoid this with what we have available in the LSP
today.
Reviewers: kadircet, ioeric, hokein, sammccall
Reviewed By: sammccall
Subscribers: mgrang, mgorny, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D56267
llvm-svn: 352494
2019-01-29 22:17:36 +08:00
|
|
|
#include "llvm/Support/Error.h"
|
[clangd] Handle clangd.applyFix server-side
Summary:
When the user selects a fix-it (or any code action with commands), it is
possible to let the client forward the selected command to the server.
When the clangd.applyFix command is handled on the server, it can send a
workspace/applyEdit request to the client. This has the advantage that
the client doesn't explicitly have to know how to handle
clangd.applyFix. Therefore, the code to handle clangd.applyFix in the VS
Code extension (and any other Clangd client) is not required anymore.
Reviewers: ilya-biryukov, sammccall, Nebiroth, hokein
Reviewed By: hokein
Subscribers: ioeric, hokein, rwols, puremourning, bkramer, ilya-biryukov
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D39276
llvm-svn: 317322
2017-11-03 21:39:15 +08:00
|
|
|
#include "llvm/Support/FormatVariadic.h"
|
2019-09-24 21:38:33 +08:00
|
|
|
#include "llvm/Support/JSON.h"
|
2018-02-01 00:26:27 +08:00
|
|
|
#include "llvm/Support/Path.h"
|
2019-09-09 20:28:44 +08:00
|
|
|
#include "llvm/Support/SHA1.h"
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
#include "llvm/Support/ScopedPrinter.h"
|
2019-09-09 20:28:44 +08:00
|
|
|
#include <cstddef>
|
2019-09-24 21:38:33 +08:00
|
|
|
#include <memory>
|
[clangd] Show background index status using LSP 3.15 work-done progress notifications
Summary:
It simply shows the completed/total items on the background queue, e.g.
indexing: 233/1000
The denominator is reset to zero every time the queue goes idle.
The protocol is fairly complicated here (requires creating a remote "progress"
resource before sending updates). We implement the full protocol, but I've added
an extension allowing it to be skipped to reduce the burden on clients - in
particular the lit test takes this shortcut.
The addition of background index progress to DiagnosticConsumer seems ridiculous
at first glance, but I believe that interface is trending in the direction of
"ClangdServer callbacks" anyway. It's due for a rename, but otherwise actually
fits.
Reviewers: kadircet, usaxena95
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D73218
2020-01-23 02:41:45 +08:00
|
|
|
#include <mutex>
|
2019-09-09 20:28:44 +08:00
|
|
|
#include <string>
|
2019-09-24 21:38:33 +08:00
|
|
|
#include <vector>
|
[clangd] Handle clangd.applyFix server-side
Summary:
When the user selects a fix-it (or any code action with commands), it is
possible to let the client forward the selected command to the server.
When the clangd.applyFix command is handled on the server, it can send a
workspace/applyEdit request to the client. This has the advantage that
the client doesn't explicitly have to know how to handle
clangd.applyFix. Therefore, the code to handle clangd.applyFix in the VS
Code extension (and any other Clangd client) is not required anymore.
Reviewers: ilya-biryukov, sammccall, Nebiroth, hokein
Reviewed By: hokein
Subscribers: ioeric, hokein, rwols, puremourning, bkramer, ilya-biryukov
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D39276
llvm-svn: 317322
2017-11-03 21:39:15 +08:00
|
|
|
|
2018-10-20 23:30:37 +08:00
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
2017-05-16 22:40:30 +08:00
|
|
|
namespace {
|
[clangd] Track document versions, include them with diags, enhance logs
Summary:
This ties to an LSP feature (diagnostic versioning) but really a lot
of the value is in being able to log what's happening with file versions
and queues more descriptively and clearly.
As such it's fairly invasive, for a logging patch :-\
Key decisions:
- at the LSP layer, we don't reqire the client to provide versions (LSP
makes it mandatory but we never enforced it). If not provided,
versions start at 0 and increment. DraftStore handles this.
- don't propagate magically using contexts, but rather manually:
addDocument -> ParseInputs -> (ParsedAST, Preamble, various callbacks)
Context-propagation would hide the versions from ClangdServer, which
would make producing good log messages hard
- within ClangdServer, treat versions as opaque and unordered.
std::string is a convenient type for this, and allows richer versions
for embedders. They're "mandatory" but "null" is a reasonable default.
Subscribers: ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75582
2020-03-04 07:33:29 +08:00
|
|
|
|
|
|
|
// LSP defines file versions as numbers that increase.
|
|
|
|
// ClangdServer treats them as opaque and therefore uses strings instead.
|
|
|
|
std::string encodeVersion(int64_t LSPVersion) {
|
|
|
|
return llvm::to_string(LSPVersion);
|
|
|
|
}
|
|
|
|
llvm::Optional<int64_t> decodeVersion(llvm::StringRef Encoded) {
|
|
|
|
int64_t Result;
|
|
|
|
if (llvm::to_integer(Encoded, Result, 10))
|
|
|
|
return Result;
|
|
|
|
else if (!Encoded.empty()) // Empty can be e.g. diagnostics on close.
|
|
|
|
elog("unexpected non-numeric version {0}", Encoded);
|
|
|
|
return llvm::None;
|
|
|
|
}
|
|
|
|
|
[clangd] Interfaces for writing code tweaks
Summary:
The code tweaks are an implementation of mini-refactorings exposed
via the LSP code actions. They run in two stages:
- Stage 1. Decides whether the action is available to the user and
collects all the information required to finish the action.
Should be cheap, since this will run over all the actions known to
clangd on each textDocument/codeAction request from the client.
- Stage 2. Uses information from stage 1 to produce the actual edits
that the code action should perform. This stage can be expensive and
will only run if the user chooses to perform the specified action in
the UI.
One unfortunate consequence of this change is increased latency of
processing the textDocument/codeAction requests, which now wait for an
AST. However, we cannot avoid this with what we have available in the LSP
today.
Reviewers: kadircet, ioeric, hokein, sammccall
Reviewed By: sammccall
Subscribers: mgrang, mgorny, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D56267
llvm-svn: 352494
2019-01-29 22:17:36 +08:00
|
|
|
/// Transforms a tweak into a code action that would apply it if executed.
|
|
|
|
/// EXPECTS: T.prepare() was called and returned true.
|
|
|
|
CodeAction toCodeAction(const ClangdServer::TweakRef &T, const URIForFile &File,
|
|
|
|
Range Selection) {
|
|
|
|
CodeAction CA;
|
|
|
|
CA.title = T.Title;
|
2019-06-18 21:37:54 +08:00
|
|
|
switch (T.Intent) {
|
|
|
|
case Tweak::Refactor:
|
2020-01-29 03:23:46 +08:00
|
|
|
CA.kind = std::string(CodeAction::REFACTOR_KIND);
|
2019-06-18 21:37:54 +08:00
|
|
|
break;
|
|
|
|
case Tweak::Info:
|
2020-01-29 03:23:46 +08:00
|
|
|
CA.kind = std::string(CodeAction::INFO_KIND);
|
2019-06-18 21:37:54 +08:00
|
|
|
break;
|
|
|
|
}
|
[clangd] Interfaces for writing code tweaks
Summary:
The code tweaks are an implementation of mini-refactorings exposed
via the LSP code actions. They run in two stages:
- Stage 1. Decides whether the action is available to the user and
collects all the information required to finish the action.
Should be cheap, since this will run over all the actions known to
clangd on each textDocument/codeAction request from the client.
- Stage 2. Uses information from stage 1 to produce the actual edits
that the code action should perform. This stage can be expensive and
will only run if the user chooses to perform the specified action in
the UI.
One unfortunate consequence of this change is increased latency of
processing the textDocument/codeAction requests, which now wait for an
AST. However, we cannot avoid this with what we have available in the LSP
today.
Reviewers: kadircet, ioeric, hokein, sammccall
Reviewed By: sammccall
Subscribers: mgrang, mgorny, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D56267
llvm-svn: 352494
2019-01-29 22:17:36 +08:00
|
|
|
// This tweak may have an expensive second stage, we only run it if the user
|
|
|
|
// actually chooses it in the UI. We reply with a command that would run the
|
|
|
|
// corresponding tweak.
|
|
|
|
// FIXME: for some tweaks, computing the edits is cheap and we could send them
|
|
|
|
// directly.
|
|
|
|
CA.command.emplace();
|
|
|
|
CA.command->title = T.Title;
|
2020-01-29 03:23:46 +08:00
|
|
|
CA.command->command = std::string(Command::CLANGD_APPLY_TWEAK);
|
[clangd] Interfaces for writing code tweaks
Summary:
The code tweaks are an implementation of mini-refactorings exposed
via the LSP code actions. They run in two stages:
- Stage 1. Decides whether the action is available to the user and
collects all the information required to finish the action.
Should be cheap, since this will run over all the actions known to
clangd on each textDocument/codeAction request from the client.
- Stage 2. Uses information from stage 1 to produce the actual edits
that the code action should perform. This stage can be expensive and
will only run if the user chooses to perform the specified action in
the UI.
One unfortunate consequence of this change is increased latency of
processing the textDocument/codeAction requests, which now wait for an
AST. However, we cannot avoid this with what we have available in the LSP
today.
Reviewers: kadircet, ioeric, hokein, sammccall
Reviewed By: sammccall
Subscribers: mgrang, mgorny, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D56267
llvm-svn: 352494
2019-01-29 22:17:36 +08:00
|
|
|
CA.command->tweakArgs.emplace();
|
|
|
|
CA.command->tweakArgs->file = File;
|
|
|
|
CA.command->tweakArgs->tweakID = T.ID;
|
|
|
|
CA.command->tweakArgs->selection = Selection;
|
|
|
|
return CA;
|
2019-02-03 22:08:30 +08:00
|
|
|
}
|
[clangd] Interfaces for writing code tweaks
Summary:
The code tweaks are an implementation of mini-refactorings exposed
via the LSP code actions. They run in two stages:
- Stage 1. Decides whether the action is available to the user and
collects all the information required to finish the action.
Should be cheap, since this will run over all the actions known to
clangd on each textDocument/codeAction request from the client.
- Stage 2. Uses information from stage 1 to produce the actual edits
that the code action should perform. This stage can be expensive and
will only run if the user chooses to perform the specified action in
the UI.
One unfortunate consequence of this change is increased latency of
processing the textDocument/codeAction requests, which now wait for an
AST. However, we cannot avoid this with what we have available in the LSP
today.
Reviewers: kadircet, ioeric, hokein, sammccall
Reviewed By: sammccall
Subscribers: mgrang, mgorny, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D56267
llvm-svn: 352494
2019-01-29 22:17:36 +08:00
|
|
|
|
2018-11-23 23:21:19 +08:00
|
|
|
void adjustSymbolKinds(llvm::MutableArrayRef<DocumentSymbol> Syms,
|
|
|
|
SymbolKindBitset Kinds) {
|
|
|
|
for (auto &S : Syms) {
|
|
|
|
S.kind = adjustKindToCapability(S.kind, Kinds);
|
|
|
|
adjustSymbolKinds(S.children, Kinds);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[clangd] Implementation of workspace/symbol request
Summary:
This is a basic implementation of the "workspace/symbol" request which is
used to find symbols by a string query. Since this is similar to code completion
in terms of result, this implementation reuses the "fuzzyFind" in order to get
matches. For now, the scoring algorithm is the same as code completion and
improvements could be done in the future.
The index model doesn't contain quite enough symbols for this to cover
common symbols like methods, enum class enumerators, functions in unamed
namespaces, etc. The index model will be augmented separately to achieve this.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: jkorous, hokein, simark, sammccall, klimek, mgorny, ilya-biryukov, mgrang, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44882
llvm-svn: 330637
2018-04-24 04:00:52 +08:00
|
|
|
SymbolKindBitset defaultSymbolKinds() {
|
|
|
|
SymbolKindBitset Defaults;
|
|
|
|
for (size_t I = SymbolKindMin; I <= static_cast<size_t>(SymbolKind::Array);
|
|
|
|
++I)
|
|
|
|
Defaults.set(I);
|
|
|
|
return Defaults;
|
|
|
|
}
|
|
|
|
|
2018-09-28 01:13:07 +08:00
|
|
|
CompletionItemKindBitset defaultCompletionItemKinds() {
|
|
|
|
CompletionItemKindBitset Defaults;
|
|
|
|
for (size_t I = CompletionItemKindMin;
|
|
|
|
I <= static_cast<size_t>(CompletionItemKind::Reference); ++I)
|
|
|
|
Defaults.set(I);
|
|
|
|
return Defaults;
|
|
|
|
}
|
|
|
|
|
2019-07-04 20:27:21 +08:00
|
|
|
// Build a lookup table (HighlightingKind => {TextMate Scopes}), which is sent
|
|
|
|
// to the LSP client.
|
|
|
|
std::vector<std::vector<std::string>> buildHighlightScopeLookupTable() {
|
|
|
|
std::vector<std::vector<std::string>> LookupTable;
|
|
|
|
// HighlightingKind is using as the index.
|
2019-09-09 16:57:17 +08:00
|
|
|
for (int KindValue = 0; KindValue <= (int)HighlightingKind::LastKind;
|
2019-07-04 20:27:21 +08:00
|
|
|
++KindValue)
|
2020-01-29 03:23:46 +08:00
|
|
|
LookupTable.push_back(
|
|
|
|
{std::string(toTextMateScope((HighlightingKind)(KindValue)))});
|
2019-07-04 20:27:21 +08:00
|
|
|
return LookupTable;
|
|
|
|
}
|
|
|
|
|
2019-10-23 20:40:20 +08:00
|
|
|
// Makes sure edits in \p FE are applicable to latest file contents reported by
|
2019-09-09 20:28:44 +08:00
|
|
|
// editor. If not generates an error message containing information about files
|
|
|
|
// that needs to be saved.
|
2019-10-23 20:40:20 +08:00
|
|
|
llvm::Error validateEdits(const DraftStore &DraftMgr, const FileEdits &FE) {
|
2019-09-09 20:28:44 +08:00
|
|
|
size_t InvalidFileCount = 0;
|
|
|
|
llvm::StringRef LastInvalidFile;
|
2019-10-23 20:40:20 +08:00
|
|
|
for (const auto &It : FE) {
|
2019-09-09 20:28:44 +08:00
|
|
|
if (auto Draft = DraftMgr.getDraft(It.first())) {
|
|
|
|
// If the file is open in user's editor, make sure the version we
|
|
|
|
// saw and current version are compatible as this is the text that
|
|
|
|
// will be replaced by editors.
|
2020-03-03 22:57:39 +08:00
|
|
|
if (!It.second.canApplyTo(Draft->Contents)) {
|
2019-09-09 20:28:44 +08:00
|
|
|
++InvalidFileCount;
|
|
|
|
LastInvalidFile = It.first();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!InvalidFileCount)
|
|
|
|
return llvm::Error::success();
|
|
|
|
if (InvalidFileCount == 1)
|
|
|
|
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
|
|
|
"File must be saved first: " +
|
|
|
|
LastInvalidFile);
|
|
|
|
return llvm::createStringError(
|
|
|
|
llvm::inconvertibleErrorCode(),
|
|
|
|
"Files must be saved first: " + LastInvalidFile + " (and " +
|
|
|
|
llvm::to_string(InvalidFileCount - 1) + " others)");
|
|
|
|
}
|
|
|
|
|
2017-05-16 22:40:30 +08:00
|
|
|
} // namespace
|
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
// MessageHandler dispatches incoming LSP messages.
|
|
|
|
// It handles cross-cutting concerns:
|
|
|
|
// - serializes/deserializes protocol objects to JSON
|
|
|
|
// - logging of inbound messages
|
|
|
|
// - cancellation handling
|
|
|
|
// - basic call tracing
|
[clangd] Enforce rules around "initialize" request, and create ClangdServer lazily.
Summary:
LSP is a slightly awkward map to C++ object lifetimes: the initialize request
is part of the protocol and provides information that doesn't change over the
lifetime of the server.
Until now, we handled this by initializing ClangdServer and ClangdLSPServer
right away, and making anything that can be set in the "initialize" request
mutable.
With this patch, we create ClangdLSPServer immediately, but defer creating
ClangdServer until "initialize". This opens the door to passing the relevant
initialize params in the constructor and storing them immutably.
(That change isn't actually done in this patch).
To make this safe, we have the MessageDispatcher enforce that the "initialize"
method is called before any other (as required by LSP). That way each method
handler can assume Server is initialized, as today.
As usual, while implementing this I found places where our test cases violated
the protocol.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53398
llvm-svn: 344741
2018-10-18 22:41:50 +08:00
|
|
|
// MessageHandler ensures that initialize() is called before any other handler.
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
class ClangdLSPServer::MessageHandler : public Transport::MessageHandler {
|
|
|
|
public:
|
|
|
|
MessageHandler(ClangdLSPServer &Server) : Server(Server) {}
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
bool onNotify(llvm::StringRef Method, llvm::json::Value Params) override {
|
2019-03-28 01:47:49 +08:00
|
|
|
WithContext HandlerContext(handlerContext());
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
log("<-- {0}", Method);
|
|
|
|
if (Method == "exit")
|
|
|
|
return false;
|
[clangd] Enforce rules around "initialize" request, and create ClangdServer lazily.
Summary:
LSP is a slightly awkward map to C++ object lifetimes: the initialize request
is part of the protocol and provides information that doesn't change over the
lifetime of the server.
Until now, we handled this by initializing ClangdServer and ClangdLSPServer
right away, and making anything that can be set in the "initialize" request
mutable.
With this patch, we create ClangdLSPServer immediately, but defer creating
ClangdServer until "initialize". This opens the door to passing the relevant
initialize params in the constructor and storing them immutably.
(That change isn't actually done in this patch).
To make this safe, we have the MessageDispatcher enforce that the "initialize"
method is called before any other (as required by LSP). That way each method
handler can assume Server is initialized, as today.
As usual, while implementing this I found places where our test cases violated
the protocol.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53398
llvm-svn: 344741
2018-10-18 22:41:50 +08:00
|
|
|
if (!Server.Server)
|
|
|
|
elog("Notification {0} before initialization", Method);
|
|
|
|
else if (Method == "$/cancelRequest")
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
onCancel(std::move(Params));
|
|
|
|
else if (auto Handler = Notifications.lookup(Method))
|
|
|
|
Handler(std::move(Params));
|
|
|
|
else
|
|
|
|
log("unhandled notification {0}", Method);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
bool onCall(llvm::StringRef Method, llvm::json::Value Params,
|
|
|
|
llvm::json::Value ID) override {
|
2019-03-28 01:47:49 +08:00
|
|
|
WithContext HandlerContext(handlerContext());
|
[clangd] Ensure that we reply to each call exactly once. NFC (I think!)
Summary:
In debug builds, getting this wrong will trigger asserts.
In production builds, it will send an error reply if none was sent,
and drop redundant replies. (And log).
No tests because this is always a programming error.
(We did have some cases of this, but I fixed them with the new dispatcher).
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53399
llvm-svn: 345144
2018-10-24 22:26:26 +08:00
|
|
|
// Calls can be canceled by the client. Add cancellation context.
|
|
|
|
WithContext WithCancel(cancelableRequestContext(ID));
|
|
|
|
trace::Span Tracer(Method);
|
|
|
|
SPAN_ATTACH(Tracer, "Params", Params);
|
|
|
|
ReplyOnce Reply(ID, Method, &Server, Tracer.Args);
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
log("<-- {0}({1})", Method, ID);
|
[clangd] Enforce rules around "initialize" request, and create ClangdServer lazily.
Summary:
LSP is a slightly awkward map to C++ object lifetimes: the initialize request
is part of the protocol and provides information that doesn't change over the
lifetime of the server.
Until now, we handled this by initializing ClangdServer and ClangdLSPServer
right away, and making anything that can be set in the "initialize" request
mutable.
With this patch, we create ClangdLSPServer immediately, but defer creating
ClangdServer until "initialize". This opens the door to passing the relevant
initialize params in the constructor and storing them immutably.
(That change isn't actually done in this patch).
To make this safe, we have the MessageDispatcher enforce that the "initialize"
method is called before any other (as required by LSP). That way each method
handler can assume Server is initialized, as today.
As usual, while implementing this I found places where our test cases violated
the protocol.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53398
llvm-svn: 344741
2018-10-18 22:41:50 +08:00
|
|
|
if (!Server.Server && Method != "initialize") {
|
|
|
|
elog("Call {0} before initialization.", Method);
|
2019-01-07 23:45:19 +08:00
|
|
|
Reply(llvm::make_error<LSPError>("server not initialized",
|
|
|
|
ErrorCode::ServerNotInitialized));
|
[clangd] Enforce rules around "initialize" request, and create ClangdServer lazily.
Summary:
LSP is a slightly awkward map to C++ object lifetimes: the initialize request
is part of the protocol and provides information that doesn't change over the
lifetime of the server.
Until now, we handled this by initializing ClangdServer and ClangdLSPServer
right away, and making anything that can be set in the "initialize" request
mutable.
With this patch, we create ClangdLSPServer immediately, but defer creating
ClangdServer until "initialize". This opens the door to passing the relevant
initialize params in the constructor and storing them immutably.
(That change isn't actually done in this patch).
To make this safe, we have the MessageDispatcher enforce that the "initialize"
method is called before any other (as required by LSP). That way each method
handler can assume Server is initialized, as today.
As usual, while implementing this I found places where our test cases violated
the protocol.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53398
llvm-svn: 344741
2018-10-18 22:41:50 +08:00
|
|
|
} else if (auto Handler = Calls.lookup(Method))
|
[clangd] Ensure that we reply to each call exactly once. NFC (I think!)
Summary:
In debug builds, getting this wrong will trigger asserts.
In production builds, it will send an error reply if none was sent,
and drop redundant replies. (And log).
No tests because this is always a programming error.
(We did have some cases of this, but I fixed them with the new dispatcher).
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53399
llvm-svn: 345144
2018-10-24 22:26:26 +08:00
|
|
|
Handler(std::move(Params), std::move(Reply));
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
else
|
2019-01-07 23:45:19 +08:00
|
|
|
Reply(llvm::make_error<LSPError>("method not found",
|
|
|
|
ErrorCode::MethodNotFound));
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
bool onReply(llvm::json::Value ID,
|
|
|
|
llvm::Expected<llvm::json::Value> Result) override {
|
2019-03-28 01:47:49 +08:00
|
|
|
WithContext HandlerContext(handlerContext());
|
2019-08-05 20:48:09 +08:00
|
|
|
|
|
|
|
Callback<llvm::json::Value> ReplyHandler = nullptr;
|
|
|
|
if (auto IntID = ID.getAsInteger()) {
|
|
|
|
std::lock_guard<std::mutex> Mutex(CallMutex);
|
|
|
|
// Find a corresponding callback for the request ID;
|
|
|
|
for (size_t Index = 0; Index < ReplyCallbacks.size(); ++Index) {
|
|
|
|
if (ReplyCallbacks[Index].first == *IntID) {
|
|
|
|
ReplyHandler = std::move(ReplyCallbacks[Index].second);
|
|
|
|
ReplyCallbacks.erase(ReplyCallbacks.begin() +
|
|
|
|
Index); // remove the entry
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ReplyHandler) {
|
|
|
|
// No callback being found, use a default log callback.
|
|
|
|
ReplyHandler = [&ID](llvm::Expected<llvm::json::Value> Result) {
|
|
|
|
elog("received a reply with ID {0}, but there was no such call", ID);
|
|
|
|
if (!Result)
|
|
|
|
llvm::consumeError(Result.takeError());
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// Log and run the reply handler.
|
|
|
|
if (Result) {
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
log("<-- reply({0})", ID);
|
2019-08-05 20:48:09 +08:00
|
|
|
ReplyHandler(std::move(Result));
|
|
|
|
} else {
|
|
|
|
auto Err = Result.takeError();
|
|
|
|
log("<-- reply({0}) error: {1}", ID, Err);
|
|
|
|
ReplyHandler(std::move(Err));
|
|
|
|
}
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bind an LSP method name to a call.
|
[clangd] Ensure that we reply to each call exactly once. NFC (I think!)
Summary:
In debug builds, getting this wrong will trigger asserts.
In production builds, it will send an error reply if none was sent,
and drop redundant replies. (And log).
No tests because this is always a programming error.
(We did have some cases of this, but I fixed them with the new dispatcher).
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53399
llvm-svn: 345144
2018-10-24 22:26:26 +08:00
|
|
|
template <typename Param, typename Result>
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
void bind(const char *Method,
|
[clangd] Ensure that we reply to each call exactly once. NFC (I think!)
Summary:
In debug builds, getting this wrong will trigger asserts.
In production builds, it will send an error reply if none was sent,
and drop redundant replies. (And log).
No tests because this is always a programming error.
(We did have some cases of this, but I fixed them with the new dispatcher).
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53399
llvm-svn: 345144
2018-10-24 22:26:26 +08:00
|
|
|
void (ClangdLSPServer::*Handler)(const Param &, Callback<Result>)) {
|
2019-01-07 23:45:19 +08:00
|
|
|
Calls[Method] = [Method, Handler, this](llvm::json::Value RawParams,
|
[clangd] Ensure that we reply to each call exactly once. NFC (I think!)
Summary:
In debug builds, getting this wrong will trigger asserts.
In production builds, it will send an error reply if none was sent,
and drop redundant replies. (And log).
No tests because this is always a programming error.
(We did have some cases of this, but I fixed them with the new dispatcher).
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53399
llvm-svn: 345144
2018-10-24 22:26:26 +08:00
|
|
|
ReplyOnce Reply) {
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
Param P;
|
[clangd] Ensure that we reply to each call exactly once. NFC (I think!)
Summary:
In debug builds, getting this wrong will trigger asserts.
In production builds, it will send an error reply if none was sent,
and drop redundant replies. (And log).
No tests because this is always a programming error.
(We did have some cases of this, but I fixed them with the new dispatcher).
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53399
llvm-svn: 345144
2018-10-24 22:26:26 +08:00
|
|
|
if (fromJSON(RawParams, P)) {
|
|
|
|
(Server.*Handler)(P, std::move(Reply));
|
|
|
|
} else {
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
elog("Failed to decode {0} request.", Method);
|
2019-01-07 23:45:19 +08:00
|
|
|
Reply(llvm::make_error<LSPError>("failed to decode request",
|
|
|
|
ErrorCode::InvalidRequest));
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-08-05 20:48:09 +08:00
|
|
|
// Bind a reply callback to a request. The callback will be invoked when
|
|
|
|
// clangd receives the reply from the LSP client.
|
|
|
|
// Return a call id of the request.
|
|
|
|
llvm::json::Value bindReply(Callback<llvm::json::Value> Reply) {
|
|
|
|
llvm::Optional<std::pair<int, Callback<llvm::json::Value>>> OldestCB;
|
|
|
|
int ID;
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> Mutex(CallMutex);
|
|
|
|
ID = NextCallID++;
|
|
|
|
ReplyCallbacks.emplace_back(ID, std::move(Reply));
|
|
|
|
|
|
|
|
// If the queue overflows, we assume that the client didn't reply the
|
|
|
|
// oldest request, and run the corresponding callback which replies an
|
|
|
|
// error to the client.
|
|
|
|
if (ReplyCallbacks.size() > MaxReplayCallbacks) {
|
|
|
|
elog("more than {0} outstanding LSP calls, forgetting about {1}",
|
|
|
|
MaxReplayCallbacks, ReplyCallbacks.front().first);
|
|
|
|
OldestCB = std::move(ReplyCallbacks.front());
|
|
|
|
ReplyCallbacks.pop_front();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (OldestCB)
|
|
|
|
OldestCB->second(llvm::createStringError(
|
|
|
|
llvm::inconvertibleErrorCode(),
|
|
|
|
llvm::formatv("failed to receive a client reply for request ({0})",
|
|
|
|
OldestCB->first)));
|
|
|
|
return ID;
|
|
|
|
}
|
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
// Bind an LSP method name to a notification.
|
|
|
|
template <typename Param>
|
|
|
|
void bind(const char *Method,
|
|
|
|
void (ClangdLSPServer::*Handler)(const Param &)) {
|
2019-01-07 23:45:19 +08:00
|
|
|
Notifications[Method] = [Method, Handler,
|
|
|
|
this](llvm::json::Value RawParams) {
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
Param P;
|
|
|
|
if (!fromJSON(RawParams, P)) {
|
|
|
|
elog("Failed to decode {0} request.", Method);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
trace::Span Tracer(Method);
|
|
|
|
SPAN_ATTACH(Tracer, "Params", RawParams);
|
|
|
|
(Server.*Handler)(P);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
[clangd] Ensure that we reply to each call exactly once. NFC (I think!)
Summary:
In debug builds, getting this wrong will trigger asserts.
In production builds, it will send an error reply if none was sent,
and drop redundant replies. (And log).
No tests because this is always a programming error.
(We did have some cases of this, but I fixed them with the new dispatcher).
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53399
llvm-svn: 345144
2018-10-24 22:26:26 +08:00
|
|
|
// Function object to reply to an LSP call.
|
|
|
|
// Each instance must be called exactly once, otherwise:
|
|
|
|
// - the bug is logged, and (in debug mode) an assert will fire
|
|
|
|
// - if there was no reply, an error reply is sent
|
|
|
|
// - if there were multiple replies, only the first is sent
|
|
|
|
class ReplyOnce {
|
|
|
|
std::atomic<bool> Replied = {false};
|
2018-10-24 23:18:40 +08:00
|
|
|
std::chrono::steady_clock::time_point Start;
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::json::Value ID;
|
[clangd] Ensure that we reply to each call exactly once. NFC (I think!)
Summary:
In debug builds, getting this wrong will trigger asserts.
In production builds, it will send an error reply if none was sent,
and drop redundant replies. (And log).
No tests because this is always a programming error.
(We did have some cases of this, but I fixed them with the new dispatcher).
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53399
llvm-svn: 345144
2018-10-24 22:26:26 +08:00
|
|
|
std::string Method;
|
|
|
|
ClangdLSPServer *Server; // Null when moved-from.
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::json::Object *TraceArgs;
|
[clangd] Ensure that we reply to each call exactly once. NFC (I think!)
Summary:
In debug builds, getting this wrong will trigger asserts.
In production builds, it will send an error reply if none was sent,
and drop redundant replies. (And log).
No tests because this is always a programming error.
(We did have some cases of this, but I fixed them with the new dispatcher).
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53399
llvm-svn: 345144
2018-10-24 22:26:26 +08:00
|
|
|
|
|
|
|
public:
|
2019-01-07 23:45:19 +08:00
|
|
|
ReplyOnce(const llvm::json::Value &ID, llvm::StringRef Method,
|
|
|
|
ClangdLSPServer *Server, llvm::json::Object *TraceArgs)
|
2018-10-24 23:18:40 +08:00
|
|
|
: Start(std::chrono::steady_clock::now()), ID(ID), Method(Method),
|
|
|
|
Server(Server), TraceArgs(TraceArgs) {
|
[clangd] Ensure that we reply to each call exactly once. NFC (I think!)
Summary:
In debug builds, getting this wrong will trigger asserts.
In production builds, it will send an error reply if none was sent,
and drop redundant replies. (And log).
No tests because this is always a programming error.
(We did have some cases of this, but I fixed them with the new dispatcher).
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53399
llvm-svn: 345144
2018-10-24 22:26:26 +08:00
|
|
|
assert(Server);
|
|
|
|
}
|
|
|
|
ReplyOnce(ReplyOnce &&Other)
|
2018-10-24 23:18:40 +08:00
|
|
|
: Replied(Other.Replied.load()), Start(Other.Start),
|
|
|
|
ID(std::move(Other.ID)), Method(std::move(Other.Method)),
|
|
|
|
Server(Other.Server), TraceArgs(Other.TraceArgs) {
|
[clangd] Ensure that we reply to each call exactly once. NFC (I think!)
Summary:
In debug builds, getting this wrong will trigger asserts.
In production builds, it will send an error reply if none was sent,
and drop redundant replies. (And log).
No tests because this is always a programming error.
(We did have some cases of this, but I fixed them with the new dispatcher).
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53399
llvm-svn: 345144
2018-10-24 22:26:26 +08:00
|
|
|
Other.Server = nullptr;
|
|
|
|
}
|
2019-01-03 21:28:05 +08:00
|
|
|
ReplyOnce &operator=(ReplyOnce &&) = delete;
|
[clangd] Ensure that we reply to each call exactly once. NFC (I think!)
Summary:
In debug builds, getting this wrong will trigger asserts.
In production builds, it will send an error reply if none was sent,
and drop redundant replies. (And log).
No tests because this is always a programming error.
(We did have some cases of this, but I fixed them with the new dispatcher).
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53399
llvm-svn: 345144
2018-10-24 22:26:26 +08:00
|
|
|
ReplyOnce(const ReplyOnce &) = delete;
|
2019-01-03 21:28:05 +08:00
|
|
|
ReplyOnce &operator=(const ReplyOnce &) = delete;
|
[clangd] Ensure that we reply to each call exactly once. NFC (I think!)
Summary:
In debug builds, getting this wrong will trigger asserts.
In production builds, it will send an error reply if none was sent,
and drop redundant replies. (And log).
No tests because this is always a programming error.
(We did have some cases of this, but I fixed them with the new dispatcher).
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53399
llvm-svn: 345144
2018-10-24 22:26:26 +08:00
|
|
|
|
|
|
|
~ReplyOnce() {
|
2019-08-05 20:48:09 +08:00
|
|
|
// There's one legitimate reason to never reply to a request: clangd's
|
|
|
|
// request handler send a call to the client (e.g. applyEdit) and the
|
|
|
|
// client never replied. In this case, the ReplyOnce is owned by
|
|
|
|
// ClangdLSPServer's reply callback table and is destroyed along with the
|
|
|
|
// server. We don't attempt to send a reply in this case, there's little
|
|
|
|
// to be gained from doing so.
|
|
|
|
if (Server && !Server->IsBeingDestroyed && !Replied) {
|
[clangd] Ensure that we reply to each call exactly once. NFC (I think!)
Summary:
In debug builds, getting this wrong will trigger asserts.
In production builds, it will send an error reply if none was sent,
and drop redundant replies. (And log).
No tests because this is always a programming error.
(We did have some cases of this, but I fixed them with the new dispatcher).
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53399
llvm-svn: 345144
2018-10-24 22:26:26 +08:00
|
|
|
elog("No reply to message {0}({1})", Method, ID);
|
|
|
|
assert(false && "must reply to all calls!");
|
2019-01-07 23:45:19 +08:00
|
|
|
(*this)(llvm::make_error<LSPError>("server failed to reply",
|
|
|
|
ErrorCode::InternalError));
|
[clangd] Ensure that we reply to each call exactly once. NFC (I think!)
Summary:
In debug builds, getting this wrong will trigger asserts.
In production builds, it will send an error reply if none was sent,
and drop redundant replies. (And log).
No tests because this is always a programming error.
(We did have some cases of this, but I fixed them with the new dispatcher).
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53399
llvm-svn: 345144
2018-10-24 22:26:26 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
void operator()(llvm::Expected<llvm::json::Value> Reply) {
|
[clangd] Ensure that we reply to each call exactly once. NFC (I think!)
Summary:
In debug builds, getting this wrong will trigger asserts.
In production builds, it will send an error reply if none was sent,
and drop redundant replies. (And log).
No tests because this is always a programming error.
(We did have some cases of this, but I fixed them with the new dispatcher).
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53399
llvm-svn: 345144
2018-10-24 22:26:26 +08:00
|
|
|
assert(Server && "moved-from!");
|
|
|
|
if (Replied.exchange(true)) {
|
|
|
|
elog("Replied twice to message {0}({1})", Method, ID);
|
|
|
|
assert(false && "must reply to each call only once!");
|
|
|
|
return;
|
|
|
|
}
|
2018-10-24 23:18:40 +08:00
|
|
|
auto Duration = std::chrono::steady_clock::now() - Start;
|
|
|
|
if (Reply) {
|
|
|
|
log("--> reply:{0}({1}) {2:ms}", Method, ID, Duration);
|
|
|
|
if (TraceArgs)
|
[clangd] Ensure that we reply to each call exactly once. NFC (I think!)
Summary:
In debug builds, getting this wrong will trigger asserts.
In production builds, it will send an error reply if none was sent,
and drop redundant replies. (And log).
No tests because this is always a programming error.
(We did have some cases of this, but I fixed them with the new dispatcher).
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53399
llvm-svn: 345144
2018-10-24 22:26:26 +08:00
|
|
|
(*TraceArgs)["Reply"] = *Reply;
|
2018-10-24 23:18:40 +08:00
|
|
|
std::lock_guard<std::mutex> Lock(Server->TranspWriter);
|
|
|
|
Server->Transp.reply(std::move(ID), std::move(Reply));
|
|
|
|
} else {
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Error Err = Reply.takeError();
|
2018-10-24 23:18:40 +08:00
|
|
|
log("--> reply:{0}({1}) {2:ms}, error: {3}", Method, ID, Duration, Err);
|
|
|
|
if (TraceArgs)
|
2019-01-07 23:45:19 +08:00
|
|
|
(*TraceArgs)["Error"] = llvm::to_string(Err);
|
2018-10-24 23:18:40 +08:00
|
|
|
std::lock_guard<std::mutex> Lock(Server->TranspWriter);
|
|
|
|
Server->Transp.reply(std::move(ID), std::move(Err));
|
[clangd] Ensure that we reply to each call exactly once. NFC (I think!)
Summary:
In debug builds, getting this wrong will trigger asserts.
In production builds, it will send an error reply if none was sent,
and drop redundant replies. (And log).
No tests because this is always a programming error.
(We did have some cases of this, but I fixed them with the new dispatcher).
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53399
llvm-svn: 345144
2018-10-24 22:26:26 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::StringMap<std::function<void(llvm::json::Value)>> Notifications;
|
|
|
|
llvm::StringMap<std::function<void(llvm::json::Value, ReplyOnce)>> Calls;
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
|
|
|
|
// Method calls may be cancelled by ID, so keep track of their state.
|
|
|
|
// This needs a mutex: handlers may finish on a different thread, and that's
|
|
|
|
// when we clean up entries in the map.
|
|
|
|
mutable std::mutex RequestCancelersMutex;
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::StringMap<std::pair<Canceler, /*Cookie*/ unsigned>> RequestCancelers;
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
unsigned NextRequestCookie = 0; // To disambiguate reused IDs, see below.
|
2019-01-07 23:45:19 +08:00
|
|
|
void onCancel(const llvm::json::Value &Params) {
|
|
|
|
const llvm::json::Value *ID = nullptr;
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
if (auto *O = Params.getAsObject())
|
|
|
|
ID = O->get("id");
|
|
|
|
if (!ID) {
|
|
|
|
elog("Bad cancellation request: {0}", Params);
|
|
|
|
return;
|
|
|
|
}
|
2019-01-07 23:45:19 +08:00
|
|
|
auto StrID = llvm::to_string(*ID);
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
std::lock_guard<std::mutex> Lock(RequestCancelersMutex);
|
|
|
|
auto It = RequestCancelers.find(StrID);
|
|
|
|
if (It != RequestCancelers.end())
|
|
|
|
It->second.first(); // Invoke the canceler.
|
|
|
|
}
|
2019-03-28 01:47:49 +08:00
|
|
|
|
|
|
|
Context handlerContext() const {
|
|
|
|
return Context::current().derive(
|
|
|
|
kCurrentOffsetEncoding,
|
|
|
|
Server.NegotiatedOffsetEncoding.getValueOr(OffsetEncoding::UTF16));
|
|
|
|
}
|
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
// We run cancelable requests in a context that does two things:
|
|
|
|
// - allows cancellation using RequestCancelers[ID]
|
|
|
|
// - cleans up the entry in RequestCancelers when it's no longer needed
|
|
|
|
// If a client reuses an ID, the last wins and the first cannot be canceled.
|
2019-01-07 23:45:19 +08:00
|
|
|
Context cancelableRequestContext(const llvm::json::Value &ID) {
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
auto Task = cancelableTask();
|
2019-01-07 23:45:19 +08:00
|
|
|
auto StrID = llvm::to_string(ID); // JSON-serialize ID for map key.
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
auto Cookie = NextRequestCookie++; // No lock, only called on main thread.
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> Lock(RequestCancelersMutex);
|
|
|
|
RequestCancelers[StrID] = {std::move(Task.second), Cookie};
|
|
|
|
}
|
|
|
|
// When the request ends, we can clean up the entry we just added.
|
|
|
|
// The cookie lets us check that it hasn't been overwritten due to ID
|
|
|
|
// reuse.
|
2019-01-07 23:45:19 +08:00
|
|
|
return Task.first.derive(llvm::make_scope_exit([this, StrID, Cookie] {
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
std::lock_guard<std::mutex> Lock(RequestCancelersMutex);
|
|
|
|
auto It = RequestCancelers.find(StrID);
|
|
|
|
if (It != RequestCancelers.end() && It->second.second == Cookie)
|
|
|
|
RequestCancelers.erase(It);
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
2019-10-09 21:59:31 +08:00
|
|
|
// The maximum number of callbacks held in clangd.
|
|
|
|
//
|
|
|
|
// We bound the maximum size to the pending map to prevent memory leakage
|
|
|
|
// for cases where LSP clients don't reply for the request.
|
|
|
|
// This has to go after RequestCancellers and RequestCancellersMutex since it
|
|
|
|
// can contain a callback that has a cancelable context.
|
|
|
|
static constexpr int MaxReplayCallbacks = 100;
|
|
|
|
mutable std::mutex CallMutex;
|
|
|
|
int NextCallID = 0; /* GUARDED_BY(CallMutex) */
|
|
|
|
std::deque<std::pair</*RequestID*/ int,
|
|
|
|
/*ReplyHandler*/ Callback<llvm::json::Value>>>
|
|
|
|
ReplyCallbacks; /* GUARDED_BY(CallMutex) */
|
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
ClangdLSPServer &Server;
|
|
|
|
};
|
2019-08-05 20:48:09 +08:00
|
|
|
constexpr int ClangdLSPServer::MessageHandler::MaxReplayCallbacks;
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
|
|
|
|
// call(), notify(), and reply() wrap the Transport, adding logging and locking.
|
2019-08-05 20:48:09 +08:00
|
|
|
void ClangdLSPServer::callRaw(StringRef Method, llvm::json::Value Params,
|
|
|
|
Callback<llvm::json::Value> CB) {
|
|
|
|
auto ID = MsgHandler->bindReply(std::move(CB));
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
log("--> {0}({1})", Method, ID);
|
|
|
|
std::lock_guard<std::mutex> Lock(TranspWriter);
|
|
|
|
Transp.call(Method, std::move(Params), ID);
|
|
|
|
}
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
void ClangdLSPServer::notify(llvm::StringRef Method, llvm::json::Value Params) {
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
log("--> {0}", Method);
|
|
|
|
std::lock_guard<std::mutex> Lock(TranspWriter);
|
|
|
|
Transp.notify(Method, std::move(Params));
|
|
|
|
}
|
|
|
|
|
2020-03-24 09:24:47 +08:00
|
|
|
static std::vector<llvm::StringRef> semanticTokenTypes() {
|
|
|
|
std::vector<llvm::StringRef> Types;
|
|
|
|
for (unsigned I = 0; I <= static_cast<unsigned>(HighlightingKind::LastKind);
|
|
|
|
++I)
|
|
|
|
Types.push_back(toSemanticTokenType(static_cast<HighlightingKind>(I)));
|
|
|
|
return Types;
|
|
|
|
}
|
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
void ClangdLSPServer::onInitialize(const InitializeParams &Params,
|
2019-01-07 23:45:19 +08:00
|
|
|
Callback<llvm::json::Value> Reply) {
|
2019-03-28 01:47:49 +08:00
|
|
|
// Determine character encoding first as it affects constructed ClangdServer.
|
|
|
|
if (Params.capabilities.offsetEncoding && !NegotiatedOffsetEncoding) {
|
|
|
|
NegotiatedOffsetEncoding = OffsetEncoding::UTF16; // fallback
|
|
|
|
for (OffsetEncoding Supported : *Params.capabilities.offsetEncoding)
|
|
|
|
if (Supported != OffsetEncoding::UnsupportedEncoding) {
|
|
|
|
NegotiatedOffsetEncoding = Supported;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-24 07:31:14 +08:00
|
|
|
ClangdServerOpts.TheiaSemanticHighlighting =
|
|
|
|
Params.capabilities.TheiaSemanticHighlighting;
|
2018-10-19 23:42:23 +08:00
|
|
|
if (Params.rootUri && *Params.rootUri)
|
2020-01-29 03:23:46 +08:00
|
|
|
ClangdServerOpts.WorkspaceRoot = std::string(Params.rootUri->file());
|
2018-10-19 23:42:23 +08:00
|
|
|
else if (Params.rootPath && !Params.rootPath->empty())
|
|
|
|
ClangdServerOpts.WorkspaceRoot = *Params.rootPath;
|
[clangd] Enforce rules around "initialize" request, and create ClangdServer lazily.
Summary:
LSP is a slightly awkward map to C++ object lifetimes: the initialize request
is part of the protocol and provides information that doesn't change over the
lifetime of the server.
Until now, we handled this by initializing ClangdServer and ClangdLSPServer
right away, and making anything that can be set in the "initialize" request
mutable.
With this patch, we create ClangdLSPServer immediately, but defer creating
ClangdServer until "initialize". This opens the door to passing the relevant
initialize params in the constructor and storing them immutably.
(That change isn't actually done in this patch).
To make this safe, we have the MessageDispatcher enforce that the "initialize"
method is called before any other (as required by LSP). That way each method
handler can assume Server is initialized, as today.
As usual, while implementing this I found places where our test cases violated
the protocol.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53398
llvm-svn: 344741
2018-10-18 22:41:50 +08:00
|
|
|
if (Server)
|
2019-01-07 23:45:19 +08:00
|
|
|
return Reply(llvm::make_error<LSPError>("server already initialized",
|
|
|
|
ErrorCode::InvalidRequest));
|
2018-10-25 12:22:52 +08:00
|
|
|
if (const auto &Dir = Params.initializationOptions.compilationDatabasePath)
|
|
|
|
CompileCommandsDir = Dir;
|
2019-06-26 15:45:27 +08:00
|
|
|
if (UseDirBasedCDB) {
|
2019-08-15 07:52:23 +08:00
|
|
|
BaseCDB = std::make_unique<DirectoryBasedGlobalCompilationDatabase>(
|
2018-11-02 21:09:36 +08:00
|
|
|
CompileCommandsDir);
|
2019-06-26 15:45:27 +08:00
|
|
|
BaseCDB = getQueryDriverDatabase(
|
|
|
|
llvm::makeArrayRef(ClangdServerOpts.QueryDriverGlobs),
|
|
|
|
std::move(BaseCDB));
|
|
|
|
}
|
[clangd] (take 2) Try harder to find a plausible `clang` as argv0, particularly on Mac.
Summary:
This was originally committed in 88bccded8fa169481fa367debf5ec615640635a1,
and reverted in 93f77617abba512d2861e2fc50ce385883f587b6.
This version is now much more testable: the "detect toolchain properties" part
is still not tested but also not active in tests.
All the command manipulation based on the detected properties is
directly tested, and also not active in other tests.
Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178
Reviewers: kbobyrev, ilya-biryukov
Subscribers: mgorny, ormris, cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71029
2019-11-30 02:37:48 +08:00
|
|
|
auto Mangler = CommandMangler::detect();
|
|
|
|
if (ClangdServerOpts.ResourceDir)
|
|
|
|
Mangler.ResourceDir = *ClangdServerOpts.ResourceDir;
|
2019-01-22 17:10:20 +08:00
|
|
|
CDB.emplace(BaseCDB.get(), Params.initializationOptions.fallbackFlags,
|
[clangd] (take 2) Try harder to find a plausible `clang` as argv0, particularly on Mac.
Summary:
This was originally committed in 88bccded8fa169481fa367debf5ec615640635a1,
and reverted in 93f77617abba512d2861e2fc50ce385883f587b6.
This version is now much more testable: the "detect toolchain properties" part
is still not tested but also not active in tests.
All the command manipulation based on the detected properties is
directly tested, and also not active in other tests.
Fixes https://github.com/clangd/clangd/issues/211
Fixes https://github.com/clangd/clangd/issues/178
Reviewers: kbobyrev, ilya-biryukov
Subscribers: mgorny, ormris, cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71029
2019-11-30 02:37:48 +08:00
|
|
|
tooling::ArgumentsAdjuster(Mangler));
|
2019-10-15 22:20:52 +08:00
|
|
|
{
|
|
|
|
// Switch caller's context with LSPServer's background context. Since we
|
|
|
|
// rather want to propagate information from LSPServer's context into the
|
|
|
|
// Server, CDB, etc.
|
|
|
|
WithContext MainContext(BackgroundContext.clone());
|
|
|
|
llvm::Optional<WithContextValue> WithOffsetEncoding;
|
|
|
|
if (NegotiatedOffsetEncoding)
|
|
|
|
WithOffsetEncoding.emplace(kCurrentOffsetEncoding,
|
|
|
|
*NegotiatedOffsetEncoding);
|
2020-01-24 21:08:56 +08:00
|
|
|
Server.emplace(*CDB, FSProvider, ClangdServerOpts,
|
|
|
|
static_cast<ClangdServer::Callbacks *>(this));
|
2019-10-15 22:20:52 +08:00
|
|
|
}
|
2018-10-25 12:22:52 +08:00
|
|
|
applyConfiguration(Params.initializationOptions.ConfigSettings);
|
2018-08-01 19:28:49 +08:00
|
|
|
|
2018-10-17 15:33:42 +08:00
|
|
|
CCOpts.EnableSnippets = Params.capabilities.CompletionSnippets;
|
2019-06-18 19:57:26 +08:00
|
|
|
CCOpts.IncludeFixIts = Params.capabilities.CompletionFixes;
|
2019-07-09 01:27:15 +08:00
|
|
|
if (!CCOpts.BundleOverloads.hasValue())
|
|
|
|
CCOpts.BundleOverloads = Params.capabilities.HasSignatureHelp;
|
2018-10-17 15:33:42 +08:00
|
|
|
DiagOpts.EmbedFixesInDiagnostics = Params.capabilities.DiagnosticFixes;
|
|
|
|
DiagOpts.SendDiagnosticCategory = Params.capabilities.DiagnosticCategory;
|
2019-04-18 23:17:07 +08:00
|
|
|
DiagOpts.EmitRelatedLocations =
|
|
|
|
Params.capabilities.DiagnosticRelatedInformation;
|
2018-10-17 15:33:42 +08:00
|
|
|
if (Params.capabilities.WorkspaceSymbolKinds)
|
|
|
|
SupportedSymbolKinds |= *Params.capabilities.WorkspaceSymbolKinds;
|
|
|
|
if (Params.capabilities.CompletionItemKinds)
|
|
|
|
SupportedCompletionItemKinds |= *Params.capabilities.CompletionItemKinds;
|
|
|
|
SupportsCodeAction = Params.capabilities.CodeActionStructure;
|
2018-11-23 23:21:19 +08:00
|
|
|
SupportsHierarchicalDocumentSymbol =
|
|
|
|
Params.capabilities.HierarchicalDocumentSymbol;
|
2018-12-20 23:39:12 +08:00
|
|
|
SupportFileStatus = Params.initializationOptions.FileStatus;
|
2019-05-29 18:01:00 +08:00
|
|
|
HoverContentFormat = Params.capabilities.HoverContentFormat;
|
2019-06-04 17:36:59 +08:00
|
|
|
SupportsOffsetsInSignatureHelp = Params.capabilities.OffsetsInSignatureHelp;
|
[clangd] Show background index status using LSP 3.15 work-done progress notifications
Summary:
It simply shows the completed/total items on the background queue, e.g.
indexing: 233/1000
The denominator is reset to zero every time the queue goes idle.
The protocol is fairly complicated here (requires creating a remote "progress"
resource before sending updates). We implement the full protocol, but I've added
an extension allowing it to be skipped to reduce the burden on clients - in
particular the lit test takes this shortcut.
The addition of background index progress to DiagnosticConsumer seems ridiculous
at first glance, but I believe that interface is trending in the direction of
"ClangdServer callbacks" anyway. It's due for a rename, but otherwise actually
fits.
Reviewers: kadircet, usaxena95
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D73218
2020-01-23 02:41:45 +08:00
|
|
|
if (Params.capabilities.WorkDoneProgress)
|
|
|
|
BackgroundIndexProgressState = BackgroundIndexProgress::Empty;
|
|
|
|
BackgroundIndexSkipCreate = Params.capabilities.ImplicitProgressCreation;
|
2019-07-24 15:49:23 +08:00
|
|
|
|
|
|
|
// Per LSP, renameProvider can be either boolean or RenameOptions.
|
|
|
|
// RenameOptions will be specified if the client states it supports prepare.
|
|
|
|
llvm::json::Value RenameProvider =
|
|
|
|
llvm::json::Object{{"prepareProvider", true}};
|
|
|
|
if (!Params.capabilities.RenamePrepareSupport) // Only boolean allowed per LSP
|
|
|
|
RenameProvider = true;
|
|
|
|
|
2019-08-22 22:53:45 +08:00
|
|
|
// Per LSP, codeActionProvide can be either boolean or CodeActionOptions.
|
|
|
|
// CodeActionOptions is only valid if the client supports action literal
|
|
|
|
// via textDocument.codeAction.codeActionLiteralSupport.
|
|
|
|
llvm::json::Value CodeActionProvider = true;
|
|
|
|
if (Params.capabilities.CodeActionStructure)
|
|
|
|
CodeActionProvider = llvm::json::Object{
|
|
|
|
{"codeActionKinds",
|
|
|
|
{CodeAction::QUICKFIX_KIND, CodeAction::REFACTOR_KIND,
|
|
|
|
CodeAction::INFO_KIND}}};
|
|
|
|
|
2019-03-28 01:47:49 +08:00
|
|
|
llvm::json::Object Result{
|
2020-03-03 19:25:46 +08:00
|
|
|
{{"serverInfo",
|
|
|
|
llvm::json::Object{{"name", "clangd"},
|
|
|
|
{"version", getClangToolFullVersion("clangd")}}},
|
|
|
|
{"capabilities",
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::json::Object{
|
[clangd] Support incremental document syncing
Summary:
This patch adds support for incremental document syncing, as described
in the LSP spec. The protocol specifies ranges in terms of Position (a
line and a character), and our drafts are stored as plain strings. So I
see two things that may not be super efficient for very large files:
- Converting a Position to an offset (the positionToOffset function)
requires searching for end of lines until we reach the desired line.
- When we update a range, we construct a new string, which implies
copying the whole document.
However, for the typical size of a C++ document and the frequency of
update (at which a user types), it may not be an issue. This patch aims
at getting the basic feature in, and we can always improve it later if
we find it's too slow.
Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
Reviewers: malaperle, ilya-biryukov
Reviewed By: ilya-biryukov
Subscribers: MaskRay, klimek, mgorny, ilya-biryukov, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D44272
llvm-svn: 328500
2018-03-26 22:41:40 +08:00
|
|
|
{"textDocumentSync", (int)TextDocumentSyncKind::Incremental},
|
2017-11-07 23:49:35 +08:00
|
|
|
{"documentFormattingProvider", true},
|
|
|
|
{"documentRangeFormattingProvider", true},
|
|
|
|
{"documentOnTypeFormattingProvider",
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::json::Object{
|
[clangd] Revamp textDocument/onTypeFormatting.
Summary:
The existing implementation (which triggers on }) is fairly simple and
has flaws:
- doesn't trigger frequently/regularly enough (particularly in editors that type the }
for you)
- often reformats too much code around the edit
- has jarring cases that I don't have clear ideas for fixing
This implementation is designed to trigger on newline, which feels to me more
intuitive than } or ;.
It does have allow for reformatting after other characters - it has a
basic behavior and a model for adding specialized behavior for
particular characters. But at least initially I'd stick to advertising
\n in the capabilities.
This also handles comment splitting: when you insert a line break inside
a line comment, it will make the new line into an aligned line comment.
Working on tests, but want people to patch it in and try it - it's hard to
see if "feel" is right purely by looking at a test.
Reviewers: ilya-biryukov, hokein
Subscribers: mgorny, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60605
llvm-svn: 362939
2019-06-10 22:26:21 +08:00
|
|
|
{"firstTriggerCharacter", "\n"},
|
2017-11-07 23:49:35 +08:00
|
|
|
{"moreTriggerCharacter", {}},
|
|
|
|
}},
|
2019-08-22 22:53:45 +08:00
|
|
|
{"codeActionProvider", std::move(CodeActionProvider)},
|
2017-11-07 23:49:35 +08:00
|
|
|
{"completionProvider",
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::json::Object{
|
2020-02-19 00:55:12 +08:00
|
|
|
{"allCommitCharacters", " \t()[]{}<>:;,+-/*%^&#?.=\"'|"},
|
2017-11-07 23:49:35 +08:00
|
|
|
{"resolveProvider", false},
|
2019-01-03 21:37:12 +08:00
|
|
|
// We do extra checks for '>' and ':' in completion to only
|
|
|
|
// trigger on '->' and '::'.
|
2017-11-07 23:49:35 +08:00
|
|
|
{"triggerCharacters", {".", ">", ":"}},
|
|
|
|
}},
|
2020-03-24 09:24:47 +08:00
|
|
|
{"semanticTokensProvider",
|
|
|
|
llvm::json::Object{
|
|
|
|
{"documentProvider", true},
|
|
|
|
{"rangeProvider", false},
|
|
|
|
{"legend",
|
|
|
|
llvm::json::Object{{"tokenTypes", semanticTokenTypes()},
|
|
|
|
{"tokenModifiers", llvm::json::Array()}}},
|
|
|
|
}},
|
2017-11-07 23:49:35 +08:00
|
|
|
{"signatureHelpProvider",
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::json::Object{
|
2017-11-07 23:49:35 +08:00
|
|
|
{"triggerCharacters", {"(", ","}},
|
|
|
|
}},
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
{"declarationProvider", true},
|
2017-11-07 23:49:35 +08:00
|
|
|
{"definitionProvider", true},
|
[clangd] Document highlights for clangd
Summary: Implementation of Document Highlights Request as described in
LSP.
Contributed by William Enright (nebiroth).
Reviewers: malaperle, krasimir, bkramer, ilya-biryukov
Reviewed By: malaperle
Subscribers: mgrang, sammccall, klimek, ioeric, rwols, cfe-commits, arphaman, ilya-biryukov
Differential Revision: https://reviews.llvm.org/D38425
llvm-svn: 320474
2017-12-12 20:27:47 +08:00
|
|
|
{"documentHighlightProvider", true},
|
2019-12-17 02:08:51 +08:00
|
|
|
{"documentLinkProvider",
|
|
|
|
llvm::json::Object{
|
|
|
|
{"resolveProvider", false},
|
|
|
|
}},
|
[clangd] Implement textDocument/hover
Summary: Implemention of textDocument/hover as described in LSP definition.
This patch adds a basic Hover implementation. When hovering a variable,
function, method or namespace, clangd will return a text containing the
declaration's scope, as well as the declaration of the hovered entity.
For example, for a variable:
Declared in class Foo::Bar
int hello = 2
For macros, the macro definition is returned.
This patch doesn't include:
- markdown support (the client I use doesn't support it yet)
- range support (optional in the Hover response)
- comments associated to variables/functions/classes
They are kept as future work to keep this patch simpler.
I added tests in XRefsTests.cpp. hover.test contains one simple
smoketest to make sure the feature works from a black box perspective.
Reviewers: malaperle, krasimir, bkramer, ilya-biryukov
Subscribers: sammccall, mgrang, klimek, rwols, ilya-biryukov, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D35894
Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
Signed-off-by: William Enright <william.enright@polymtl.ca>
llvm-svn: 325395
2018-02-17 05:38:15 +08:00
|
|
|
{"hoverProvider", true},
|
2019-07-24 15:49:23 +08:00
|
|
|
{"renameProvider", std::move(RenameProvider)},
|
2019-09-24 21:38:33 +08:00
|
|
|
{"selectionRangeProvider", true},
|
2018-07-06 03:35:01 +08:00
|
|
|
{"documentSymbolProvider", true},
|
[clangd] Implementation of workspace/symbol request
Summary:
This is a basic implementation of the "workspace/symbol" request which is
used to find symbols by a string query. Since this is similar to code completion
in terms of result, this implementation reuses the "fuzzyFind" in order to get
matches. For now, the scoring algorithm is the same as code completion and
improvements could be done in the future.
The index model doesn't contain quite enough symbols for this to cover
common symbols like methods, enum class enumerators, functions in unamed
namespaces, etc. The index model will be augmented separately to achieve this.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: jkorous, hokein, simark, sammccall, klimek, mgorny, ilya-biryukov, mgrang, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44882
llvm-svn: 330637
2018-04-24 04:00:52 +08:00
|
|
|
{"workspaceSymbolProvider", true},
|
2018-09-05 19:53:07 +08:00
|
|
|
{"referencesProvider", true},
|
2017-11-07 23:49:35 +08:00
|
|
|
{"executeCommandProvider",
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::json::Object{
|
[clangd] Interfaces for writing code tweaks
Summary:
The code tweaks are an implementation of mini-refactorings exposed
via the LSP code actions. They run in two stages:
- Stage 1. Decides whether the action is available to the user and
collects all the information required to finish the action.
Should be cheap, since this will run over all the actions known to
clangd on each textDocument/codeAction request from the client.
- Stage 2. Uses information from stage 1 to produce the actual edits
that the code action should perform. This stage can be expensive and
will only run if the user chooses to perform the specified action in
the UI.
One unfortunate consequence of this change is increased latency of
processing the textDocument/codeAction requests, which now wait for an
AST. However, we cannot avoid this with what we have available in the LSP
today.
Reviewers: kadircet, ioeric, hokein, sammccall
Reviewed By: sammccall
Subscribers: mgrang, mgorny, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D56267
llvm-svn: 352494
2019-01-29 22:17:36 +08:00
|
|
|
{"commands",
|
|
|
|
{ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND,
|
|
|
|
ExecuteCommandParams::CLANGD_APPLY_TWEAK}},
|
2017-11-07 23:49:35 +08:00
|
|
|
}},
|
[clangd] Add support for type hierarchy (super types only for now)
Summary:
Patch by Nathan Ridge(@nridge)!
This is an LSP extension proposed here:
https://github.com/Microsoft/vscode-languageserver-node/pull/426
An example client implementation can be found here:
https://github.com/theia-ide/theia/pull/3802
Reviewers: kadircet, sammccall
Reviewed By: kadircet
Subscribers: jdoerfert, sammccall, cfe-commits, mgorny, dschaefer, simark, ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, kadircet
Tags: #clang
Differential Revision: https://reviews.llvm.org/D56370
llvm-svn: 356445
2019-03-19 17:27:04 +08:00
|
|
|
{"typeHierarchyProvider", true},
|
2019-03-28 01:47:49 +08:00
|
|
|
}}}};
|
|
|
|
if (NegotiatedOffsetEncoding)
|
|
|
|
Result["offsetEncoding"] = *NegotiatedOffsetEncoding;
|
2020-03-24 07:31:14 +08:00
|
|
|
if (Params.capabilities.TheiaSemanticHighlighting)
|
2019-07-04 15:53:12 +08:00
|
|
|
Result.getObject("capabilities")
|
|
|
|
->insert(
|
|
|
|
{"semanticHighlighting",
|
2019-07-04 20:27:21 +08:00
|
|
|
llvm::json::Object{{"scopes", buildHighlightScopeLookupTable()}}});
|
2019-03-28 01:47:49 +08:00
|
|
|
Reply(std::move(Result));
|
2017-05-16 22:40:30 +08:00
|
|
|
}
|
|
|
|
|
2020-03-03 19:12:14 +08:00
|
|
|
void ClangdLSPServer::onInitialized(const InitializedParams &Params) {}
|
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
void ClangdLSPServer::onShutdown(const ShutdownParams &Params,
|
|
|
|
Callback<std::nullptr_t> Reply) {
|
2017-10-25 16:45:41 +08:00
|
|
|
// Do essentially nothing, just say we're ready to exit.
|
|
|
|
ShutdownRequestReceived = true;
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
Reply(nullptr);
|
2017-10-12 21:29:58 +08:00
|
|
|
}
|
2017-05-16 22:40:30 +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
|
|
|
// sync is a clangd extension: it blocks until all background work completes.
|
|
|
|
// It blocks the calling thread, so no messages are processed until it returns!
|
|
|
|
void ClangdLSPServer::onSync(const NoParams &Params,
|
|
|
|
Callback<std::nullptr_t> Reply) {
|
|
|
|
if (Server->blockUntilIdleForTest(/*TimeoutSeconds=*/60))
|
|
|
|
Reply(nullptr);
|
|
|
|
else
|
2019-01-07 23:45:19 +08:00
|
|
|
Reply(llvm::createStringError(llvm::inconvertibleErrorCode(),
|
|
|
|
"Not idle after a minute"));
|
[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
|
|
|
}
|
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
void ClangdLSPServer::onDocumentDidOpen(
|
|
|
|
const DidOpenTextDocumentParams &Params) {
|
2018-03-16 22:30:42 +08:00
|
|
|
PathRef File = Params.textDocument.uri.file();
|
2018-06-13 17:20:41 +08:00
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
const std::string &Contents = Params.textDocument.text;
|
2018-03-16 22:30:42 +08:00
|
|
|
|
[clangd] Track document versions, include them with diags, enhance logs
Summary:
This ties to an LSP feature (diagnostic versioning) but really a lot
of the value is in being able to log what's happening with file versions
and queues more descriptively and clearly.
As such it's fairly invasive, for a logging patch :-\
Key decisions:
- at the LSP layer, we don't reqire the client to provide versions (LSP
makes it mandatory but we never enforced it). If not provided,
versions start at 0 and increment. DraftStore handles this.
- don't propagate magically using contexts, but rather manually:
addDocument -> ParseInputs -> (ParsedAST, Preamble, various callbacks)
Context-propagation would hide the versions from ClangdServer, which
would make producing good log messages hard
- within ClangdServer, treat versions as opaque and unordered.
std::string is a convenient type for this, and allows richer versions
for embedders. They're "mandatory" but "null" is a reasonable default.
Subscribers: ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75582
2020-03-04 07:33:29 +08:00
|
|
|
auto Version = DraftMgr.addDraft(File, Params.textDocument.version, Contents);
|
|
|
|
Server->addDocument(File, Contents, encodeVersion(Version),
|
|
|
|
WantDiagnostics::Yes);
|
2017-05-16 22:40:30 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
void ClangdLSPServer::onDocumentDidChange(
|
|
|
|
const DidChangeTextDocumentParams &Params) {
|
2018-02-23 02:40:39 +08:00
|
|
|
auto WantDiags = WantDiagnostics::Auto;
|
|
|
|
if (Params.wantDiagnostics.hasValue())
|
|
|
|
WantDiags = Params.wantDiagnostics.getValue() ? WantDiagnostics::Yes
|
|
|
|
: WantDiagnostics::No;
|
2018-03-16 22:30:42 +08:00
|
|
|
|
|
|
|
PathRef File = Params.textDocument.uri.file();
|
2020-03-03 22:57:39 +08:00
|
|
|
llvm::Expected<DraftStore::Draft> Draft = DraftMgr.updateDraft(
|
|
|
|
File, Params.textDocument.version, Params.contentChanges);
|
|
|
|
if (!Draft) {
|
[clangd] Support incremental document syncing
Summary:
This patch adds support for incremental document syncing, as described
in the LSP spec. The protocol specifies ranges in terms of Position (a
line and a character), and our drafts are stored as plain strings. So I
see two things that may not be super efficient for very large files:
- Converting a Position to an offset (the positionToOffset function)
requires searching for end of lines until we reach the desired line.
- When we update a range, we construct a new string, which implies
copying the whole document.
However, for the typical size of a C++ document and the frequency of
update (at which a user types), it may not be an issue. This patch aims
at getting the basic feature in, and we can always improve it later if
we find it's too slow.
Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
Reviewers: malaperle, ilya-biryukov
Reviewed By: ilya-biryukov
Subscribers: MaskRay, klimek, mgorny, ilya-biryukov, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D44272
llvm-svn: 328500
2018-03-26 22:41:40 +08:00
|
|
|
// If this fails, we are most likely going to be not in sync anymore with
|
|
|
|
// the client. It is better to remove the draft and let further operations
|
|
|
|
// fail rather than giving wrong results.
|
|
|
|
DraftMgr.removeDraft(File);
|
2018-09-26 13:48:29 +08:00
|
|
|
Server->removeDocument(File);
|
2020-03-03 22:57:39 +08:00
|
|
|
elog("Failed to update {0}: {1}", File, Draft.takeError());
|
[clangd] Support incremental document syncing
Summary:
This patch adds support for incremental document syncing, as described
in the LSP spec. The protocol specifies ranges in terms of Position (a
line and a character), and our drafts are stored as plain strings. So I
see two things that may not be super efficient for very large files:
- Converting a Position to an offset (the positionToOffset function)
requires searching for end of lines until we reach the desired line.
- When we update a range, we construct a new string, which implies
copying the whole document.
However, for the typical size of a C++ document and the frequency of
update (at which a user types), it may not be an issue. This patch aims
at getting the basic feature in, and we can always improve it later if
we find it's too slow.
Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
Reviewers: malaperle, ilya-biryukov
Reviewed By: ilya-biryukov
Subscribers: MaskRay, klimek, mgorny, ilya-biryukov, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D44272
llvm-svn: 328500
2018-03-26 22:41:40 +08:00
|
|
|
return;
|
|
|
|
}
|
2018-03-16 22:30:42 +08:00
|
|
|
|
[clangd] Track document versions, include them with diags, enhance logs
Summary:
This ties to an LSP feature (diagnostic versioning) but really a lot
of the value is in being able to log what's happening with file versions
and queues more descriptively and clearly.
As such it's fairly invasive, for a logging patch :-\
Key decisions:
- at the LSP layer, we don't reqire the client to provide versions (LSP
makes it mandatory but we never enforced it). If not provided,
versions start at 0 and increment. DraftStore handles this.
- don't propagate magically using contexts, but rather manually:
addDocument -> ParseInputs -> (ParsedAST, Preamble, various callbacks)
Context-propagation would hide the versions from ClangdServer, which
would make producing good log messages hard
- within ClangdServer, treat versions as opaque and unordered.
std::string is a convenient type for this, and allows richer versions
for embedders. They're "mandatory" but "null" is a reasonable default.
Subscribers: ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75582
2020-03-04 07:33:29 +08:00
|
|
|
Server->addDocument(File, Draft->Contents, encodeVersion(Draft->Version),
|
|
|
|
WantDiags, Params.forceRebuild);
|
2017-05-16 22:40:30 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
void ClangdLSPServer::onFileEvent(const DidChangeWatchedFilesParams &Params) {
|
2018-09-26 13:48:29 +08:00
|
|
|
Server->onFileEvent(Params);
|
2017-10-03 02:00:37 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
void ClangdLSPServer::onCommand(const ExecuteCommandParams &Params,
|
2019-01-07 23:45:19 +08:00
|
|
|
Callback<llvm::json::Value> Reply) {
|
2019-08-16 20:46:41 +08:00
|
|
|
auto ApplyEdit = [this](WorkspaceEdit WE, std::string SuccessMessage,
|
|
|
|
decltype(Reply) Reply) {
|
2018-02-16 22:15:55 +08:00
|
|
|
ApplyWorkspaceEditParams Edit;
|
|
|
|
Edit.edit = std::move(WE);
|
2019-08-16 20:46:41 +08:00
|
|
|
call<ApplyWorkspaceEditResponse>(
|
|
|
|
"workspace/applyEdit", std::move(Edit),
|
|
|
|
[Reply = std::move(Reply), SuccessMessage = std::move(SuccessMessage)](
|
|
|
|
llvm::Expected<ApplyWorkspaceEditResponse> Response) mutable {
|
|
|
|
if (!Response)
|
|
|
|
return Reply(Response.takeError());
|
|
|
|
if (!Response->applied) {
|
|
|
|
std::string Reason = Response->failureReason
|
|
|
|
? *Response->failureReason
|
|
|
|
: "unknown reason";
|
|
|
|
return Reply(llvm::createStringError(
|
|
|
|
llvm::inconvertibleErrorCode(),
|
|
|
|
("edits were not applied: " + Reason).c_str()));
|
|
|
|
}
|
|
|
|
return Reply(SuccessMessage);
|
|
|
|
});
|
2018-02-16 22:15:55 +08:00
|
|
|
};
|
2019-08-16 20:46:41 +08:00
|
|
|
|
[clangd] Handle clangd.applyFix server-side
Summary:
When the user selects a fix-it (or any code action with commands), it is
possible to let the client forward the selected command to the server.
When the clangd.applyFix command is handled on the server, it can send a
workspace/applyEdit request to the client. This has the advantage that
the client doesn't explicitly have to know how to handle
clangd.applyFix. Therefore, the code to handle clangd.applyFix in the VS
Code extension (and any other Clangd client) is not required anymore.
Reviewers: ilya-biryukov, sammccall, Nebiroth, hokein
Reviewed By: hokein
Subscribers: ioeric, hokein, rwols, puremourning, bkramer, ilya-biryukov
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D39276
llvm-svn: 317322
2017-11-03 21:39:15 +08:00
|
|
|
if (Params.command == ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND &&
|
|
|
|
Params.workspaceEdit) {
|
|
|
|
// The flow for "apply-fix" :
|
|
|
|
// 1. We publish a diagnostic, including fixits
|
|
|
|
// 2. The user clicks on the diagnostic, the editor asks us for code actions
|
|
|
|
// 3. We send code actions, with the fixit embedded as context
|
|
|
|
// 4. The user selects the fixit, the editor asks us to apply it
|
|
|
|
// 5. We unwrap the changes and send them back to the editor
|
2019-08-05 20:48:09 +08:00
|
|
|
// 6. The editor applies the changes (applyEdit), and sends us a reply
|
|
|
|
// 7. We unwrap the reply and send a reply to the editor.
|
2019-08-16 20:46:41 +08:00
|
|
|
ApplyEdit(*Params.workspaceEdit, "Fix applied.", std::move(Reply));
|
[clangd] Interfaces for writing code tweaks
Summary:
The code tweaks are an implementation of mini-refactorings exposed
via the LSP code actions. They run in two stages:
- Stage 1. Decides whether the action is available to the user and
collects all the information required to finish the action.
Should be cheap, since this will run over all the actions known to
clangd on each textDocument/codeAction request from the client.
- Stage 2. Uses information from stage 1 to produce the actual edits
that the code action should perform. This stage can be expensive and
will only run if the user chooses to perform the specified action in
the UI.
One unfortunate consequence of this change is increased latency of
processing the textDocument/codeAction requests, which now wait for an
AST. However, we cannot avoid this with what we have available in the LSP
today.
Reviewers: kadircet, ioeric, hokein, sammccall
Reviewed By: sammccall
Subscribers: mgrang, mgorny, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D56267
llvm-svn: 352494
2019-01-29 22:17:36 +08:00
|
|
|
} else if (Params.command == ExecuteCommandParams::CLANGD_APPLY_TWEAK &&
|
|
|
|
Params.tweakArgs) {
|
|
|
|
auto Code = DraftMgr.getDraft(Params.tweakArgs->file.file());
|
|
|
|
if (!Code)
|
|
|
|
return Reply(llvm::createStringError(
|
|
|
|
llvm::inconvertibleErrorCode(),
|
|
|
|
"trying to apply a code action for a non-added file"));
|
|
|
|
|
2019-08-16 20:46:41 +08:00
|
|
|
auto Action = [this, ApplyEdit, Reply = std::move(Reply),
|
|
|
|
File = Params.tweakArgs->file, Code = std::move(*Code)](
|
2019-08-15 22:16:06 +08:00
|
|
|
llvm::Expected<Tweak::Effect> R) mutable {
|
[clangd] Interfaces for writing code tweaks
Summary:
The code tweaks are an implementation of mini-refactorings exposed
via the LSP code actions. They run in two stages:
- Stage 1. Decides whether the action is available to the user and
collects all the information required to finish the action.
Should be cheap, since this will run over all the actions known to
clangd on each textDocument/codeAction request from the client.
- Stage 2. Uses information from stage 1 to produce the actual edits
that the code action should perform. This stage can be expensive and
will only run if the user chooses to perform the specified action in
the UI.
One unfortunate consequence of this change is increased latency of
processing the textDocument/codeAction requests, which now wait for an
AST. However, we cannot avoid this with what we have available in the LSP
today.
Reviewers: kadircet, ioeric, hokein, sammccall
Reviewed By: sammccall
Subscribers: mgrang, mgorny, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D56267
llvm-svn: 352494
2019-01-29 22:17:36 +08:00
|
|
|
if (!R)
|
|
|
|
return Reply(R.takeError());
|
|
|
|
|
2019-09-09 20:28:44 +08:00
|
|
|
assert(R->ShowMessage ||
|
|
|
|
(!R->ApplyEdits.empty() && "tweak has no effect"));
|
2019-08-16 20:46:41 +08:00
|
|
|
|
2019-06-18 21:37:54 +08:00
|
|
|
if (R->ShowMessage) {
|
|
|
|
ShowMessageParams Msg;
|
|
|
|
Msg.message = *R->ShowMessage;
|
|
|
|
Msg.type = MessageType::Info;
|
|
|
|
notify("window/showMessage", Msg);
|
|
|
|
}
|
2019-08-16 20:46:41 +08:00
|
|
|
// When no edit is specified, make sure we Reply().
|
2019-09-09 20:28:44 +08:00
|
|
|
if (R->ApplyEdits.empty())
|
|
|
|
return Reply("Tweak applied.");
|
|
|
|
|
2019-10-23 20:40:20 +08:00
|
|
|
if (auto Err = validateEdits(DraftMgr, R->ApplyEdits))
|
2019-09-09 20:28:44 +08:00
|
|
|
return Reply(std::move(Err));
|
|
|
|
|
|
|
|
WorkspaceEdit WE;
|
|
|
|
WE.changes.emplace();
|
|
|
|
for (const auto &It : R->ApplyEdits) {
|
2019-10-02 17:12:01 +08:00
|
|
|
(*WE.changes)[URI::createFile(It.first()).toString()] =
|
2019-09-09 20:28:44 +08:00
|
|
|
It.second.asTextEdits();
|
|
|
|
}
|
|
|
|
// ApplyEdit will take care of calling Reply().
|
|
|
|
return ApplyEdit(std::move(WE), "Tweak applied.", std::move(Reply));
|
[clangd] Interfaces for writing code tweaks
Summary:
The code tweaks are an implementation of mini-refactorings exposed
via the LSP code actions. They run in two stages:
- Stage 1. Decides whether the action is available to the user and
collects all the information required to finish the action.
Should be cheap, since this will run over all the actions known to
clangd on each textDocument/codeAction request from the client.
- Stage 2. Uses information from stage 1 to produce the actual edits
that the code action should perform. This stage can be expensive and
will only run if the user chooses to perform the specified action in
the UI.
One unfortunate consequence of this change is increased latency of
processing the textDocument/codeAction requests, which now wait for an
AST. However, we cannot avoid this with what we have available in the LSP
today.
Reviewers: kadircet, ioeric, hokein, sammccall
Reviewed By: sammccall
Subscribers: mgrang, mgorny, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D56267
llvm-svn: 352494
2019-01-29 22:17:36 +08:00
|
|
|
};
|
|
|
|
Server->applyTweak(Params.tweakArgs->file.file(),
|
|
|
|
Params.tweakArgs->selection, Params.tweakArgs->tweakID,
|
2019-08-15 22:16:06 +08:00
|
|
|
std::move(Action));
|
[clangd] Handle clangd.applyFix server-side
Summary:
When the user selects a fix-it (or any code action with commands), it is
possible to let the client forward the selected command to the server.
When the clangd.applyFix command is handled on the server, it can send a
workspace/applyEdit request to the client. This has the advantage that
the client doesn't explicitly have to know how to handle
clangd.applyFix. Therefore, the code to handle clangd.applyFix in the VS
Code extension (and any other Clangd client) is not required anymore.
Reviewers: ilya-biryukov, sammccall, Nebiroth, hokein
Reviewed By: hokein
Subscribers: ioeric, hokein, rwols, puremourning, bkramer, ilya-biryukov
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D39276
llvm-svn: 317322
2017-11-03 21:39:15 +08:00
|
|
|
} 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.
|
2019-01-07 23:45:19 +08:00
|
|
|
Reply(llvm::make_error<LSPError>(
|
|
|
|
llvm::formatv("Unsupported command \"{0}\".", Params.command).str(),
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
ErrorCode::InvalidParams));
|
[clangd] Handle clangd.applyFix server-side
Summary:
When the user selects a fix-it (or any code action with commands), it is
possible to let the client forward the selected command to the server.
When the clangd.applyFix command is handled on the server, it can send a
workspace/applyEdit request to the client. This has the advantage that
the client doesn't explicitly have to know how to handle
clangd.applyFix. Therefore, the code to handle clangd.applyFix in the VS
Code extension (and any other Clangd client) is not required anymore.
Reviewers: ilya-biryukov, sammccall, Nebiroth, hokein
Reviewed By: hokein
Subscribers: ioeric, hokein, rwols, puremourning, bkramer, ilya-biryukov
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D39276
llvm-svn: 317322
2017-11-03 21:39:15 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
void ClangdLSPServer::onWorkspaceSymbol(
|
|
|
|
const WorkspaceSymbolParams &Params,
|
|
|
|
Callback<std::vector<SymbolInformation>> Reply) {
|
2018-09-26 13:48:29 +08:00
|
|
|
Server->workspaceSymbols(
|
[clangd] Implementation of workspace/symbol request
Summary:
This is a basic implementation of the "workspace/symbol" request which is
used to find symbols by a string query. Since this is similar to code completion
in terms of result, this implementation reuses the "fuzzyFind" in order to get
matches. For now, the scoring algorithm is the same as code completion and
improvements could be done in the future.
The index model doesn't contain quite enough symbols for this to cover
common symbols like methods, enum class enumerators, functions in unamed
namespaces, etc. The index model will be augmented separately to achieve this.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: jkorous, hokein, simark, sammccall, klimek, mgorny, ilya-biryukov, mgrang, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44882
llvm-svn: 330637
2018-04-24 04:00:52 +08:00
|
|
|
Params.query, CCOpts.Limit,
|
2019-08-15 22:16:06 +08:00
|
|
|
[Reply = std::move(Reply),
|
|
|
|
this](llvm::Expected<std::vector<SymbolInformation>> Items) mutable {
|
|
|
|
if (!Items)
|
|
|
|
return Reply(Items.takeError());
|
|
|
|
for (auto &Sym : *Items)
|
|
|
|
Sym.kind = adjustKindToCapability(Sym.kind, SupportedSymbolKinds);
|
|
|
|
|
|
|
|
Reply(std::move(*Items));
|
|
|
|
});
|
[clangd] Implementation of workspace/symbol request
Summary:
This is a basic implementation of the "workspace/symbol" request which is
used to find symbols by a string query. Since this is similar to code completion
in terms of result, this implementation reuses the "fuzzyFind" in order to get
matches. For now, the scoring algorithm is the same as code completion and
improvements could be done in the future.
The index model doesn't contain quite enough symbols for this to cover
common symbols like methods, enum class enumerators, functions in unamed
namespaces, etc. The index model will be augmented separately to achieve this.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: jkorous, hokein, simark, sammccall, klimek, mgorny, ilya-biryukov, mgrang, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44882
llvm-svn: 330637
2018-04-24 04:00:52 +08:00
|
|
|
}
|
|
|
|
|
2019-07-24 15:49:23 +08:00
|
|
|
void ClangdLSPServer::onPrepareRename(const TextDocumentPositionParams &Params,
|
|
|
|
Callback<llvm::Optional<Range>> Reply) {
|
|
|
|
Server->prepareRename(Params.textDocument.uri.file(), Params.position,
|
2020-02-19 22:37:36 +08:00
|
|
|
RenameOpts, std::move(Reply));
|
2019-07-24 15:49:23 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
void ClangdLSPServer::onRename(const RenameParams &Params,
|
|
|
|
Callback<WorkspaceEdit> Reply) {
|
2020-01-29 03:23:46 +08:00
|
|
|
Path File = std::string(Params.textDocument.uri.file());
|
2020-03-03 22:57:39 +08:00
|
|
|
if (!DraftMgr.getDraft(File))
|
2019-01-07 23:45:19 +08:00
|
|
|
return Reply(llvm::make_error<LSPError>(
|
|
|
|
"onRename called for non-added file", ErrorCode::InvalidParams));
|
2019-10-23 20:40:20 +08:00
|
|
|
Server->rename(
|
2020-02-19 22:37:36 +08:00
|
|
|
File, Params.position, Params.newName, RenameOpts,
|
2019-10-23 20:40:20 +08:00
|
|
|
[File, Params, Reply = std::move(Reply),
|
|
|
|
this](llvm::Expected<FileEdits> Edits) mutable {
|
|
|
|
if (!Edits)
|
|
|
|
return Reply(Edits.takeError());
|
|
|
|
if (auto Err = validateEdits(DraftMgr, *Edits))
|
|
|
|
return Reply(std::move(Err));
|
|
|
|
WorkspaceEdit Result;
|
|
|
|
Result.changes.emplace();
|
|
|
|
for (const auto &Rep : *Edits) {
|
|
|
|
(*Result.changes)[URI::createFile(Rep.first()).toString()] =
|
|
|
|
Rep.second.asTextEdits();
|
|
|
|
}
|
|
|
|
Reply(Result);
|
|
|
|
});
|
2017-11-09 19:30:04 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
void ClangdLSPServer::onDocumentDidClose(
|
|
|
|
const DidCloseTextDocumentParams &Params) {
|
2018-03-16 22:30:42 +08:00
|
|
|
PathRef File = Params.textDocument.uri.file();
|
|
|
|
DraftMgr.removeDraft(File);
|
2018-09-26 13:48:29 +08:00
|
|
|
Server->removeDocument(File);
|
2019-03-25 18:15:11 +08:00
|
|
|
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> Lock(FixItsMutex);
|
|
|
|
FixItsMap.erase(File);
|
|
|
|
}
|
2019-08-01 16:08:44 +08:00
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> HLock(HighlightingsMutex);
|
|
|
|
FileToHighlightings.erase(File);
|
|
|
|
}
|
2019-03-25 18:15:11 +08:00
|
|
|
// clangd will not send updates for this file anymore, so we empty out the
|
|
|
|
// list of diagnostics shown on the client (e.g. in the "Problems" pane of
|
|
|
|
// VSCode). Note that this cannot race with actual diagnostics responses
|
|
|
|
// because removeDocument() guarantees no diagnostic callbacks will be
|
|
|
|
// executed after it returns.
|
2020-03-03 19:44:40 +08:00
|
|
|
PublishDiagnosticsParams Notification;
|
|
|
|
Notification.uri = URIForFile::canonicalize(File, /*TUPath=*/File);
|
|
|
|
publishDiagnostics(Notification);
|
2017-05-16 22:40:30 +08:00
|
|
|
}
|
|
|
|
|
2017-09-30 18:08:52 +08:00
|
|
|
void ClangdLSPServer::onDocumentOnTypeFormatting(
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
const DocumentOnTypeFormattingParams &Params,
|
|
|
|
Callback<std::vector<TextEdit>> Reply) {
|
2018-02-16 20:20:47 +08:00
|
|
|
auto File = Params.textDocument.uri.file();
|
2018-03-16 22:30:42 +08:00
|
|
|
auto Code = DraftMgr.getDraft(File);
|
2018-01-17 20:30:24 +08:00
|
|
|
if (!Code)
|
2019-01-07 23:45:19 +08:00
|
|
|
return Reply(llvm::make_error<LSPError>(
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
"onDocumentOnTypeFormatting called for non-added file",
|
|
|
|
ErrorCode::InvalidParams));
|
2018-01-17 20:30:24 +08:00
|
|
|
|
2020-03-03 22:57:39 +08:00
|
|
|
Reply(Server->formatOnType(Code->Contents, File, Params.position, Params.ch));
|
2017-05-16 22:40:30 +08:00
|
|
|
}
|
|
|
|
|
2017-09-30 18:08:52 +08:00
|
|
|
void ClangdLSPServer::onDocumentRangeFormatting(
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
const DocumentRangeFormattingParams &Params,
|
|
|
|
Callback<std::vector<TextEdit>> Reply) {
|
2018-02-16 20:20:47 +08:00
|
|
|
auto File = Params.textDocument.uri.file();
|
2018-03-16 22:30:42 +08:00
|
|
|
auto Code = DraftMgr.getDraft(File);
|
2018-01-17 20:30:24 +08:00
|
|
|
if (!Code)
|
2019-01-07 23:45:19 +08:00
|
|
|
return Reply(llvm::make_error<LSPError>(
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
"onDocumentRangeFormatting called for non-added file",
|
|
|
|
ErrorCode::InvalidParams));
|
2018-01-17 20:30:24 +08:00
|
|
|
|
2020-03-03 22:57:39 +08:00
|
|
|
auto ReplacementsOrError =
|
|
|
|
Server->formatRange(Code->Contents, File, Params.range);
|
2017-12-13 04:25:06 +08:00
|
|
|
if (ReplacementsOrError)
|
2020-03-03 22:57:39 +08:00
|
|
|
Reply(replacementsToEdits(Code->Contents, ReplacementsOrError.get()));
|
2017-12-13 04:25:06 +08:00
|
|
|
else
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
Reply(ReplacementsOrError.takeError());
|
2017-05-16 22:40:30 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
void ClangdLSPServer::onDocumentFormatting(
|
|
|
|
const DocumentFormattingParams &Params,
|
|
|
|
Callback<std::vector<TextEdit>> Reply) {
|
2018-02-16 20:20:47 +08:00
|
|
|
auto File = Params.textDocument.uri.file();
|
2018-03-16 22:30:42 +08:00
|
|
|
auto Code = DraftMgr.getDraft(File);
|
2018-01-17 20:30:24 +08:00
|
|
|
if (!Code)
|
2019-01-07 23:45:19 +08:00
|
|
|
return Reply(llvm::make_error<LSPError>(
|
|
|
|
"onDocumentFormatting called for non-added file",
|
|
|
|
ErrorCode::InvalidParams));
|
2018-01-17 20:30:24 +08:00
|
|
|
|
2020-03-03 22:57:39 +08:00
|
|
|
auto ReplacementsOrError = Server->formatFile(Code->Contents, File);
|
2017-12-13 04:25:06 +08:00
|
|
|
if (ReplacementsOrError)
|
2020-03-03 22:57:39 +08:00
|
|
|
Reply(replacementsToEdits(Code->Contents, ReplacementsOrError.get()));
|
2017-12-13 04:25:06 +08:00
|
|
|
else
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
Reply(ReplacementsOrError.takeError());
|
2017-05-16 22:40:30 +08:00
|
|
|
}
|
|
|
|
|
2018-11-23 23:21:19 +08:00
|
|
|
/// The functions constructs a flattened view of the DocumentSymbol hierarchy.
|
|
|
|
/// Used by the clients that do not support the hierarchical view.
|
|
|
|
static std::vector<SymbolInformation>
|
|
|
|
flattenSymbolHierarchy(llvm::ArrayRef<DocumentSymbol> Symbols,
|
|
|
|
const URIForFile &FileURI) {
|
|
|
|
|
|
|
|
std::vector<SymbolInformation> Results;
|
2019-01-07 23:45:19 +08:00
|
|
|
std::function<void(const DocumentSymbol &, llvm::StringRef)> Process =
|
|
|
|
[&](const DocumentSymbol &S, llvm::Optional<llvm::StringRef> ParentName) {
|
2018-11-23 23:21:19 +08:00
|
|
|
SymbolInformation SI;
|
2020-01-29 03:23:46 +08:00
|
|
|
SI.containerName = std::string(ParentName ? "" : *ParentName);
|
2018-11-23 23:21:19 +08:00
|
|
|
SI.name = S.name;
|
|
|
|
SI.kind = S.kind;
|
|
|
|
SI.location.range = S.range;
|
|
|
|
SI.location.uri = FileURI;
|
|
|
|
|
|
|
|
Results.push_back(std::move(SI));
|
|
|
|
std::string FullName =
|
|
|
|
!ParentName ? S.name : (ParentName->str() + "::" + S.name);
|
|
|
|
for (auto &C : S.children)
|
|
|
|
Process(C, /*ParentName=*/FullName);
|
|
|
|
};
|
|
|
|
for (auto &S : Symbols)
|
|
|
|
Process(S, /*ParentName=*/"");
|
|
|
|
return Results;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClangdLSPServer::onDocumentSymbol(const DocumentSymbolParams &Params,
|
2019-01-07 23:45:19 +08:00
|
|
|
Callback<llvm::json::Value> Reply) {
|
2018-11-23 23:21:19 +08:00
|
|
|
URIForFile FileURI = Params.textDocument.uri;
|
2018-09-26 13:48:29 +08:00
|
|
|
Server->documentSymbols(
|
2018-07-06 03:35:01 +08:00
|
|
|
Params.textDocument.uri.file(),
|
2019-08-15 22:16:06 +08:00
|
|
|
[this, FileURI, Reply = std::move(Reply)](
|
|
|
|
llvm::Expected<std::vector<DocumentSymbol>> Items) mutable {
|
|
|
|
if (!Items)
|
|
|
|
return Reply(Items.takeError());
|
|
|
|
adjustSymbolKinds(*Items, SupportedSymbolKinds);
|
|
|
|
if (SupportsHierarchicalDocumentSymbol)
|
|
|
|
return Reply(std::move(*Items));
|
|
|
|
else
|
|
|
|
return Reply(flattenSymbolHierarchy(*Items, FileURI));
|
|
|
|
});
|
2018-07-06 03:35:01 +08:00
|
|
|
}
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
static llvm::Optional<Command> asCommand(const CodeAction &Action) {
|
2018-10-17 00:29:41 +08:00
|
|
|
Command Cmd;
|
|
|
|
if (Action.command && Action.edit)
|
2018-10-20 23:30:37 +08:00
|
|
|
return None; // Not representable. (We never emit these anyway).
|
2018-10-17 00:29:41 +08:00
|
|
|
if (Action.command) {
|
|
|
|
Cmd = *Action.command;
|
|
|
|
} else if (Action.edit) {
|
2020-01-29 03:23:46 +08:00
|
|
|
Cmd.command = std::string(Command::CLANGD_APPLY_FIX_COMMAND);
|
2018-10-17 00:29:41 +08:00
|
|
|
Cmd.workspaceEdit = *Action.edit;
|
|
|
|
} else {
|
2018-10-20 23:30:37 +08:00
|
|
|
return None;
|
2018-10-17 00:29:41 +08:00
|
|
|
}
|
|
|
|
Cmd.title = Action.title;
|
|
|
|
if (Action.kind && *Action.kind == CodeAction::QUICKFIX_KIND)
|
|
|
|
Cmd.title = "Apply fix: " + Cmd.title;
|
|
|
|
return Cmd;
|
|
|
|
}
|
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
void ClangdLSPServer::onCodeAction(const CodeActionParams &Params,
|
2019-01-07 23:45:19 +08:00
|
|
|
Callback<llvm::json::Value> Reply) {
|
[clangd] Interfaces for writing code tweaks
Summary:
The code tweaks are an implementation of mini-refactorings exposed
via the LSP code actions. They run in two stages:
- Stage 1. Decides whether the action is available to the user and
collects all the information required to finish the action.
Should be cheap, since this will run over all the actions known to
clangd on each textDocument/codeAction request from the client.
- Stage 2. Uses information from stage 1 to produce the actual edits
that the code action should perform. This stage can be expensive and
will only run if the user chooses to perform the specified action in
the UI.
One unfortunate consequence of this change is increased latency of
processing the textDocument/codeAction requests, which now wait for an
AST. However, we cannot avoid this with what we have available in the LSP
today.
Reviewers: kadircet, ioeric, hokein, sammccall
Reviewed By: sammccall
Subscribers: mgrang, mgorny, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D56267
llvm-svn: 352494
2019-01-29 22:17:36 +08:00
|
|
|
URIForFile File = Params.textDocument.uri;
|
|
|
|
auto Code = DraftMgr.getDraft(File.file());
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
if (!Code)
|
2019-01-07 23:45:19 +08:00
|
|
|
return Reply(llvm::make_error<LSPError>(
|
|
|
|
"onCodeAction called for non-added file", ErrorCode::InvalidParams));
|
2018-10-17 00:29:41 +08:00
|
|
|
// We provide a code action for Fixes on the specified diagnostics.
|
[clangd] Interfaces for writing code tweaks
Summary:
The code tweaks are an implementation of mini-refactorings exposed
via the LSP code actions. They run in two stages:
- Stage 1. Decides whether the action is available to the user and
collects all the information required to finish the action.
Should be cheap, since this will run over all the actions known to
clangd on each textDocument/codeAction request from the client.
- Stage 2. Uses information from stage 1 to produce the actual edits
that the code action should perform. This stage can be expensive and
will only run if the user chooses to perform the specified action in
the UI.
One unfortunate consequence of this change is increased latency of
processing the textDocument/codeAction requests, which now wait for an
AST. However, we cannot avoid this with what we have available in the LSP
today.
Reviewers: kadircet, ioeric, hokein, sammccall
Reviewed By: sammccall
Subscribers: mgrang, mgorny, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D56267
llvm-svn: 352494
2019-01-29 22:17:36 +08:00
|
|
|
std::vector<CodeAction> FixIts;
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
for (const Diagnostic &D : Params.context.diagnostics) {
|
[clangd] Interfaces for writing code tweaks
Summary:
The code tweaks are an implementation of mini-refactorings exposed
via the LSP code actions. They run in two stages:
- Stage 1. Decides whether the action is available to the user and
collects all the information required to finish the action.
Should be cheap, since this will run over all the actions known to
clangd on each textDocument/codeAction request from the client.
- Stage 2. Uses information from stage 1 to produce the actual edits
that the code action should perform. This stage can be expensive and
will only run if the user chooses to perform the specified action in
the UI.
One unfortunate consequence of this change is increased latency of
processing the textDocument/codeAction requests, which now wait for an
AST. However, we cannot avoid this with what we have available in the LSP
today.
Reviewers: kadircet, ioeric, hokein, sammccall
Reviewed By: sammccall
Subscribers: mgrang, mgorny, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D56267
llvm-svn: 352494
2019-01-29 22:17:36 +08:00
|
|
|
for (auto &F : getFixes(File.file(), D)) {
|
|
|
|
FixIts.push_back(toCodeAction(F, Params.textDocument.uri));
|
|
|
|
FixIts.back().diagnostics = {D};
|
Adds a json::Expr type to represent intermediate JSON expressions.
Summary:
This form can be created with a nice clang-format-friendly literal syntax,
and gets escaping right. It knows how to call unparse() on our Protocol types.
All the places where we pass around JSON internally now use this type.
Object properties are sorted (stored as std::map) and so serialization is
canonicalized, with optional prettyprinting (triggered by a -pretty flag).
This makes the lit tests much nicer to read and somewhat nicer to debug.
(Unfortunately the completion tests use CHECK-DAG, which only has
line-granularity, so pretty-printing is disabled there. In future we
could make completion ordering deterministic, or switch to unittests).
Compared to the current approach, it has some efficiencies like avoiding copies
of string literals used as object keys, but is probably slower overall.
I think the code/test quality benefits are worth it.
This patch doesn't attempt to do anything about JSON *parsing*.
It takes direction from the proposal in this doc[1], but is limited in scope
and visibility, for now.
I am of half a mind just to use Expr as the target of a parser, and maybe do a
little string deduplication, but not bother with clever memory allocation.
That would be simple, and fast enough for clangd...
[1] https://docs.google.com/document/d/1OEF9IauWwNuSigZzvvbjc1cVS1uGHRyGTXaoy3DjqM4/edit
+cc d0k so he can tell me not to use std::map.
Reviewers: ioeric, malaperle
Subscribers: bkramer, ilya-biryukov, mgorny, klimek
Differential Revision: https://reviews.llvm.org/D39435
llvm-svn: 317486
2017-11-06 23:40:30 +08:00
|
|
|
}
|
2017-05-16 22:40:30 +08:00
|
|
|
}
|
2018-10-17 00:29:41 +08:00
|
|
|
|
[clangd] Interfaces for writing code tweaks
Summary:
The code tweaks are an implementation of mini-refactorings exposed
via the LSP code actions. They run in two stages:
- Stage 1. Decides whether the action is available to the user and
collects all the information required to finish the action.
Should be cheap, since this will run over all the actions known to
clangd on each textDocument/codeAction request from the client.
- Stage 2. Uses information from stage 1 to produce the actual edits
that the code action should perform. This stage can be expensive and
will only run if the user chooses to perform the specified action in
the UI.
One unfortunate consequence of this change is increased latency of
processing the textDocument/codeAction requests, which now wait for an
AST. However, we cannot avoid this with what we have available in the LSP
today.
Reviewers: kadircet, ioeric, hokein, sammccall
Reviewed By: sammccall
Subscribers: mgrang, mgorny, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D56267
llvm-svn: 352494
2019-01-29 22:17:36 +08:00
|
|
|
// Now enumerate the semantic code actions.
|
|
|
|
auto ConsumeActions =
|
2019-08-15 22:16:06 +08:00
|
|
|
[Reply = std::move(Reply), File, Code = std::move(*Code),
|
|
|
|
Selection = Params.range, FixIts = std::move(FixIts), this](
|
|
|
|
llvm::Expected<std::vector<ClangdServer::TweakRef>> Tweaks) mutable {
|
2019-01-30 22:24:17 +08:00
|
|
|
if (!Tweaks)
|
|
|
|
return Reply(Tweaks.takeError());
|
[clangd] Interfaces for writing code tweaks
Summary:
The code tweaks are an implementation of mini-refactorings exposed
via the LSP code actions. They run in two stages:
- Stage 1. Decides whether the action is available to the user and
collects all the information required to finish the action.
Should be cheap, since this will run over all the actions known to
clangd on each textDocument/codeAction request from the client.
- Stage 2. Uses information from stage 1 to produce the actual edits
that the code action should perform. This stage can be expensive and
will only run if the user chooses to perform the specified action in
the UI.
One unfortunate consequence of this change is increased latency of
processing the textDocument/codeAction requests, which now wait for an
AST. However, we cannot avoid this with what we have available in the LSP
today.
Reviewers: kadircet, ioeric, hokein, sammccall
Reviewed By: sammccall
Subscribers: mgrang, mgorny, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D56267
llvm-svn: 352494
2019-01-29 22:17:36 +08:00
|
|
|
|
|
|
|
std::vector<CodeAction> Actions = std::move(FixIts);
|
|
|
|
Actions.reserve(Actions.size() + Tweaks->size());
|
|
|
|
for (const auto &T : *Tweaks)
|
|
|
|
Actions.push_back(toCodeAction(T, File, Selection));
|
|
|
|
|
|
|
|
if (SupportsCodeAction)
|
|
|
|
return Reply(llvm::json::Array(Actions));
|
|
|
|
std::vector<Command> Commands;
|
|
|
|
for (const auto &Action : Actions) {
|
|
|
|
if (auto Command = asCommand(Action))
|
|
|
|
Commands.push_back(std::move(*Command));
|
|
|
|
}
|
|
|
|
return Reply(llvm::json::Array(Commands));
|
|
|
|
};
|
|
|
|
|
2019-08-15 22:16:06 +08:00
|
|
|
Server->enumerateTweaks(File.file(), Params.range, std::move(ConsumeActions));
|
2017-05-16 22:40:30 +08:00
|
|
|
}
|
|
|
|
|
2019-01-03 21:37:12 +08:00
|
|
|
void ClangdLSPServer::onCompletion(const CompletionParams &Params,
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
Callback<CompletionList> Reply) {
|
2019-06-08 00:24:38 +08:00
|
|
|
if (!shouldRunCompletion(Params)) {
|
|
|
|
// Clients sometimes auto-trigger completions in undesired places (e.g.
|
|
|
|
// 'a >^ '), we return empty results in those cases.
|
|
|
|
vlog("ignored auto-triggered completion, preceding char did not match");
|
|
|
|
return Reply(CompletionList());
|
|
|
|
}
|
2019-01-07 23:45:19 +08:00
|
|
|
Server->codeComplete(Params.textDocument.uri.file(), Params.position, CCOpts,
|
2019-08-15 22:16:06 +08:00
|
|
|
[Reply = std::move(Reply),
|
|
|
|
this](llvm::Expected<CodeCompleteResult> List) mutable {
|
|
|
|
if (!List)
|
|
|
|
return Reply(List.takeError());
|
|
|
|
CompletionList LSPList;
|
|
|
|
LSPList.isIncomplete = List->HasMore;
|
|
|
|
for (const auto &R : List->Completions) {
|
|
|
|
CompletionItem C = R.render(CCOpts);
|
|
|
|
C.kind = adjustKindToCapability(
|
|
|
|
C.kind, SupportedCompletionItemKinds);
|
|
|
|
LSPList.items.push_back(std::move(C));
|
|
|
|
}
|
|
|
|
return Reply(std::move(LSPList));
|
|
|
|
});
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClangdLSPServer::onSignatureHelp(const TextDocumentPositionParams &Params,
|
|
|
|
Callback<SignatureHelp> Reply) {
|
2018-09-26 13:48:29 +08:00
|
|
|
Server->signatureHelp(Params.textDocument.uri.file(), Params.position,
|
2019-08-15 22:16:06 +08:00
|
|
|
[Reply = std::move(Reply), this](
|
|
|
|
llvm::Expected<SignatureHelp> Signature) mutable {
|
|
|
|
if (!Signature)
|
|
|
|
return Reply(Signature.takeError());
|
|
|
|
if (SupportsOffsetsInSignatureHelp)
|
|
|
|
return Reply(std::move(*Signature));
|
|
|
|
// Strip out the offsets from signature help for
|
|
|
|
// clients that only support string labels.
|
|
|
|
for (auto &SigInfo : Signature->signatures) {
|
|
|
|
for (auto &Param : SigInfo.parameters)
|
|
|
|
Param.labelOffsets.reset();
|
|
|
|
}
|
|
|
|
return Reply(std::move(*Signature));
|
|
|
|
});
|
2017-10-06 19:54:17 +08:00
|
|
|
}
|
|
|
|
|
2019-02-02 13:56:00 +08:00
|
|
|
// Go to definition has a toggle function: if def and decl are distinct, then
|
|
|
|
// the first press gives you the def, the second gives you the matching def.
|
|
|
|
// getToggle() returns the counterpart location that under the cursor.
|
|
|
|
//
|
|
|
|
// We return the toggled location alone (ignoring other symbols) to encourage
|
|
|
|
// editors to "bounce" quickly between locations, without showing a menu.
|
|
|
|
static Location *getToggle(const TextDocumentPositionParams &Point,
|
|
|
|
LocatedSymbol &Sym) {
|
|
|
|
// Toggle only makes sense with two distinct locations.
|
|
|
|
if (!Sym.Definition || *Sym.Definition == Sym.PreferredDeclaration)
|
|
|
|
return nullptr;
|
|
|
|
if (Sym.Definition->uri.file() == Point.textDocument.uri.file() &&
|
|
|
|
Sym.Definition->range.contains(Point.position))
|
|
|
|
return &Sym.PreferredDeclaration;
|
|
|
|
if (Sym.PreferredDeclaration.uri.file() == Point.textDocument.uri.file() &&
|
|
|
|
Sym.PreferredDeclaration.range.contains(Point.position))
|
|
|
|
return &*Sym.Definition;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
void ClangdLSPServer::onGoToDefinition(const TextDocumentPositionParams &Params,
|
|
|
|
Callback<std::vector<Location>> Reply) {
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
Server->locateSymbolAt(
|
|
|
|
Params.textDocument.uri.file(), Params.position,
|
2019-08-15 22:16:06 +08:00
|
|
|
[Params, Reply = std::move(Reply)](
|
|
|
|
llvm::Expected<std::vector<LocatedSymbol>> Symbols) mutable {
|
|
|
|
if (!Symbols)
|
|
|
|
return Reply(Symbols.takeError());
|
|
|
|
std::vector<Location> Defs;
|
|
|
|
for (auto &S : *Symbols) {
|
|
|
|
if (Location *Toggle = getToggle(Params, S))
|
|
|
|
return Reply(std::vector<Location>{std::move(*Toggle)});
|
|
|
|
Defs.push_back(S.Definition.getValueOr(S.PreferredDeclaration));
|
|
|
|
}
|
|
|
|
Reply(std::move(Defs));
|
|
|
|
});
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClangdLSPServer::onGoToDeclaration(
|
|
|
|
const TextDocumentPositionParams &Params,
|
|
|
|
Callback<std::vector<Location>> Reply) {
|
|
|
|
Server->locateSymbolAt(
|
|
|
|
Params.textDocument.uri.file(), Params.position,
|
2019-08-15 22:16:06 +08:00
|
|
|
[Params, Reply = std::move(Reply)](
|
|
|
|
llvm::Expected<std::vector<LocatedSymbol>> Symbols) mutable {
|
|
|
|
if (!Symbols)
|
|
|
|
return Reply(Symbols.takeError());
|
|
|
|
std::vector<Location> Decls;
|
|
|
|
for (auto &S : *Symbols) {
|
|
|
|
if (Location *Toggle = getToggle(Params, S))
|
|
|
|
return Reply(std::vector<Location>{std::move(*Toggle)});
|
|
|
|
Decls.push_back(std::move(S.PreferredDeclaration));
|
|
|
|
}
|
|
|
|
Reply(std::move(Decls));
|
|
|
|
});
|
2017-06-29 00:12:10 +08:00
|
|
|
}
|
|
|
|
|
2019-05-07 15:55:35 +08:00
|
|
|
void ClangdLSPServer::onSwitchSourceHeader(
|
|
|
|
const TextDocumentIdentifier &Params,
|
2019-05-07 16:30:32 +08:00
|
|
|
Callback<llvm::Optional<URIForFile>> Reply) {
|
2019-10-01 18:21:15 +08:00
|
|
|
Server->switchSourceHeader(
|
|
|
|
Params.uri.file(),
|
|
|
|
[Reply = std::move(Reply),
|
|
|
|
Params](llvm::Expected<llvm::Optional<clangd::Path>> Path) mutable {
|
|
|
|
if (!Path)
|
|
|
|
return Reply(Path.takeError());
|
|
|
|
if (*Path)
|
2019-10-07 19:37:25 +08:00
|
|
|
return Reply(URIForFile::canonicalize(**Path, Params.uri.file()));
|
2019-10-01 18:21:15 +08:00
|
|
|
return Reply(llvm::None);
|
|
|
|
});
|
2017-09-28 11:14:40 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
void ClangdLSPServer::onDocumentHighlight(
|
|
|
|
const TextDocumentPositionParams &Params,
|
|
|
|
Callback<std::vector<DocumentHighlight>> Reply) {
|
|
|
|
Server->findDocumentHighlights(Params.textDocument.uri.file(),
|
|
|
|
Params.position, std::move(Reply));
|
[clangd] Document highlights for clangd
Summary: Implementation of Document Highlights Request as described in
LSP.
Contributed by William Enright (nebiroth).
Reviewers: malaperle, krasimir, bkramer, ilya-biryukov
Reviewed By: malaperle
Subscribers: mgrang, sammccall, klimek, ioeric, rwols, cfe-commits, arphaman, ilya-biryukov
Differential Revision: https://reviews.llvm.org/D38425
llvm-svn: 320474
2017-12-12 20:27:47 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
void ClangdLSPServer::onHover(const TextDocumentPositionParams &Params,
|
2019-01-07 23:45:19 +08:00
|
|
|
Callback<llvm::Optional<Hover>> Reply) {
|
2018-09-26 13:48:29 +08:00
|
|
|
Server->findHover(Params.textDocument.uri.file(), Params.position,
|
2019-08-15 22:16:06 +08:00
|
|
|
[Reply = std::move(Reply), this](
|
|
|
|
llvm::Expected<llvm::Optional<HoverInfo>> H) mutable {
|
|
|
|
if (!H)
|
|
|
|
return Reply(H.takeError());
|
|
|
|
if (!*H)
|
|
|
|
return Reply(llvm::None);
|
|
|
|
|
|
|
|
Hover R;
|
|
|
|
R.contents.kind = HoverContentFormat;
|
|
|
|
R.range = (*H)->SymRange;
|
|
|
|
switch (HoverContentFormat) {
|
|
|
|
case MarkupKind::PlainText:
|
2019-12-10 17:28:37 +08:00
|
|
|
R.contents.value = (*H)->present().asPlainText();
|
2019-08-15 22:16:06 +08:00
|
|
|
return Reply(std::move(R));
|
|
|
|
case MarkupKind::Markdown:
|
2019-12-10 17:28:37 +08:00
|
|
|
R.contents.value = (*H)->present().asMarkdown();
|
2019-08-15 22:16:06 +08:00
|
|
|
return Reply(std::move(R));
|
|
|
|
};
|
|
|
|
llvm_unreachable("unhandled MarkupKind");
|
|
|
|
});
|
[clangd] Implement textDocument/hover
Summary: Implemention of textDocument/hover as described in LSP definition.
This patch adds a basic Hover implementation. When hovering a variable,
function, method or namespace, clangd will return a text containing the
declaration's scope, as well as the declaration of the hovered entity.
For example, for a variable:
Declared in class Foo::Bar
int hello = 2
For macros, the macro definition is returned.
This patch doesn't include:
- markdown support (the client I use doesn't support it yet)
- range support (optional in the Hover response)
- comments associated to variables/functions/classes
They are kept as future work to keep this patch simpler.
I added tests in XRefsTests.cpp. hover.test contains one simple
smoketest to make sure the feature works from a black box perspective.
Reviewers: malaperle, krasimir, bkramer, ilya-biryukov
Subscribers: sammccall, mgrang, klimek, rwols, ilya-biryukov, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D35894
Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
Signed-off-by: William Enright <william.enright@polymtl.ca>
llvm-svn: 325395
2018-02-17 05:38:15 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Add support for type hierarchy (super types only for now)
Summary:
Patch by Nathan Ridge(@nridge)!
This is an LSP extension proposed here:
https://github.com/Microsoft/vscode-languageserver-node/pull/426
An example client implementation can be found here:
https://github.com/theia-ide/theia/pull/3802
Reviewers: kadircet, sammccall
Reviewed By: kadircet
Subscribers: jdoerfert, sammccall, cfe-commits, mgorny, dschaefer, simark, ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, kadircet
Tags: #clang
Differential Revision: https://reviews.llvm.org/D56370
llvm-svn: 356445
2019-03-19 17:27:04 +08:00
|
|
|
void ClangdLSPServer::onTypeHierarchy(
|
|
|
|
const TypeHierarchyParams &Params,
|
|
|
|
Callback<Optional<TypeHierarchyItem>> Reply) {
|
|
|
|
Server->typeHierarchy(Params.textDocument.uri.file(), Params.position,
|
|
|
|
Params.resolve, Params.direction, std::move(Reply));
|
|
|
|
}
|
|
|
|
|
2019-07-13 11:24:48 +08:00
|
|
|
void ClangdLSPServer::onResolveTypeHierarchy(
|
|
|
|
const ResolveTypeHierarchyItemParams &Params,
|
|
|
|
Callback<Optional<TypeHierarchyItem>> Reply) {
|
|
|
|
Server->resolveTypeHierarchy(Params.item, Params.resolve, Params.direction,
|
|
|
|
std::move(Reply));
|
|
|
|
}
|
|
|
|
|
2018-08-01 19:28:49 +08:00
|
|
|
void ClangdLSPServer::applyConfiguration(
|
2018-10-25 12:22:52 +08:00
|
|
|
const ConfigurationSettings &Settings) {
|
2018-10-16 23:55:03 +08:00
|
|
|
// Per-file update to the compilation database.
|
2020-01-14 06:01:10 +08:00
|
|
|
llvm::StringSet<> ModifiedFiles;
|
2018-10-25 12:22:52 +08:00
|
|
|
for (auto &Entry : Settings.compilationDatabaseChanges) {
|
|
|
|
PathRef File = Entry.first;
|
2018-11-02 21:09:36 +08:00
|
|
|
auto Old = CDB->getCompileCommand(File);
|
|
|
|
auto New =
|
|
|
|
tooling::CompileCommand(std::move(Entry.second.workingDirectory), File,
|
|
|
|
std::move(Entry.second.compilationCommand),
|
|
|
|
/*Output=*/"");
|
2018-11-02 22:07:51 +08:00
|
|
|
if (Old != New) {
|
2018-11-02 21:09:36 +08:00
|
|
|
CDB->setCompileCommand(File, std::move(New));
|
2020-01-14 06:01:10 +08:00
|
|
|
ModifiedFiles.insert(File);
|
2018-11-02 22:07:51 +08:00
|
|
|
}
|
2018-08-02 01:39:29 +08:00
|
|
|
}
|
2020-01-14 06:01:10 +08:00
|
|
|
|
|
|
|
reparseOpenedFiles(ModifiedFiles);
|
[clangd] DidChangeConfiguration Notification
Summary:
Implementation of DidChangeConfiguration notification handling in
clangd. This currently only supports changing one setting: the path of
the compilation database to be used for the current project. In other
words, it is no longer necessary to restart clangd with a different
command line argument in order to change the compilation database.
Reviewers: malaperle, krasimir, bkramer, ilya-biryukov
Subscribers: jkorous-apple, ioeric, simark, klimek, ilya-biryukov, arphaman, rwols, cfe-commits
Differential Revision: https://reviews.llvm.org/D39571
Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
Signed-off-by: William Enright <william.enright@polymtl.ca>
llvm-svn: 325784
2018-02-22 22:00:39 +08:00
|
|
|
}
|
|
|
|
|
2020-03-24 07:31:14 +08:00
|
|
|
void ClangdLSPServer::publishTheiaSemanticHighlighting(
|
|
|
|
const TheiaSemanticHighlightingParams &Params) {
|
2019-07-04 15:53:12 +08:00
|
|
|
notify("textDocument/semanticHighlighting", Params);
|
|
|
|
}
|
|
|
|
|
2019-03-25 18:15:11 +08:00
|
|
|
void ClangdLSPServer::publishDiagnostics(
|
2020-03-03 19:44:40 +08:00
|
|
|
const PublishDiagnosticsParams &Params) {
|
|
|
|
notify("textDocument/publishDiagnostics", Params);
|
2019-03-25 18:15:11 +08:00
|
|
|
}
|
|
|
|
|
2018-08-01 19:28:49 +08:00
|
|
|
// FIXME: This function needs to be properly tested.
|
|
|
|
void ClangdLSPServer::onChangeConfiguration(
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
const DidChangeConfigurationParams &Params) {
|
2018-08-01 19:28:49 +08:00
|
|
|
applyConfiguration(Params.settings);
|
|
|
|
}
|
|
|
|
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
void ClangdLSPServer::onReference(const ReferenceParams &Params,
|
|
|
|
Callback<std::vector<Location>> Reply) {
|
2018-09-26 13:48:29 +08:00
|
|
|
Server->findReferences(Params.textDocument.uri.file(), Params.position,
|
2019-11-18 18:35:00 +08:00
|
|
|
CCOpts.Limit,
|
|
|
|
[Reply = std::move(Reply)](
|
|
|
|
llvm::Expected<ReferencesResult> Refs) mutable {
|
|
|
|
if (!Refs)
|
|
|
|
return Reply(Refs.takeError());
|
|
|
|
return Reply(std::move(Refs->References));
|
|
|
|
});
|
2018-09-05 19:53:07 +08:00
|
|
|
}
|
|
|
|
|
2018-11-28 00:40:46 +08:00
|
|
|
void ClangdLSPServer::onSymbolInfo(const TextDocumentPositionParams &Params,
|
|
|
|
Callback<std::vector<SymbolDetails>> Reply) {
|
|
|
|
Server->symbolInfo(Params.textDocument.uri.file(), Params.position,
|
|
|
|
std::move(Reply));
|
|
|
|
}
|
|
|
|
|
2019-09-24 21:38:33 +08:00
|
|
|
void ClangdLSPServer::onSelectionRange(
|
|
|
|
const SelectionRangeParams &Params,
|
|
|
|
Callback<std::vector<SelectionRange>> Reply) {
|
|
|
|
Server->semanticRanges(
|
2020-03-25 07:51:50 +08:00
|
|
|
Params.textDocument.uri.file(), Params.positions,
|
2019-09-24 21:38:33 +08:00
|
|
|
[Reply = std::move(Reply)](
|
2020-03-25 07:51:50 +08:00
|
|
|
llvm::Expected<std::vector<SelectionRange>> Ranges) mutable {
|
|
|
|
if (!Ranges)
|
2019-09-24 21:38:33 +08:00
|
|
|
return Reply(Ranges.takeError());
|
2020-03-25 07:51:50 +08:00
|
|
|
return Reply(std::move(*Ranges));
|
2019-09-24 21:38:33 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-12-17 02:08:51 +08:00
|
|
|
void ClangdLSPServer::onDocumentLink(
|
|
|
|
const DocumentLinkParams &Params,
|
|
|
|
Callback<std::vector<DocumentLink>> Reply) {
|
|
|
|
|
|
|
|
// TODO(forster): This currently resolves all targets eagerly. This is slow,
|
|
|
|
// because it blocks on the preamble/AST being built. We could respond to the
|
|
|
|
// request faster by using string matching or the lexer to find the includes
|
|
|
|
// and resolving the targets lazily.
|
|
|
|
Server->documentLinks(
|
|
|
|
Params.textDocument.uri.file(),
|
|
|
|
[Reply = std::move(Reply)](
|
|
|
|
llvm::Expected<std::vector<DocumentLink>> Links) mutable {
|
|
|
|
if (!Links) {
|
|
|
|
return Reply(Links.takeError());
|
|
|
|
}
|
|
|
|
return Reply(std::move(Links));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-03-24 09:24:47 +08:00
|
|
|
void ClangdLSPServer::onSemanticTokens(const SemanticTokensParams &Params,
|
|
|
|
Callback<SemanticTokens> CB) {
|
|
|
|
Server->semanticHighlights(
|
|
|
|
Params.textDocument.uri.file(),
|
|
|
|
[CB(std::move(CB))](
|
|
|
|
llvm::Expected<std::vector<HighlightingToken>> Toks) mutable {
|
|
|
|
if (!Toks)
|
|
|
|
return CB(Toks.takeError());
|
|
|
|
SemanticTokens Result;
|
|
|
|
Result.data = toSemanticTokens(*Toks);
|
|
|
|
CB(std::move(Result));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-03-28 01:47:49 +08:00
|
|
|
ClangdLSPServer::ClangdLSPServer(
|
|
|
|
class Transport &Transp, const FileSystemProvider &FSProvider,
|
|
|
|
const clangd::CodeCompleteOptions &CCOpts,
|
2020-02-19 22:37:36 +08:00
|
|
|
const clangd::RenameOptions &RenameOpts,
|
2019-03-28 01:47:49 +08:00
|
|
|
llvm::Optional<Path> CompileCommandsDir, bool UseDirBasedCDB,
|
|
|
|
llvm::Optional<OffsetEncoding> ForcedOffsetEncoding,
|
|
|
|
const ClangdServer::Options &Opts)
|
2019-10-15 22:20:52 +08:00
|
|
|
: BackgroundContext(Context::current().clone()), Transp(Transp),
|
|
|
|
MsgHandler(new MessageHandler(*this)), FSProvider(FSProvider),
|
2020-02-19 22:37:36 +08:00
|
|
|
CCOpts(CCOpts), RenameOpts(RenameOpts),
|
|
|
|
SupportedSymbolKinds(defaultSymbolKinds()),
|
2018-09-28 01:13:07 +08:00
|
|
|
SupportedCompletionItemKinds(defaultCompletionItemKinds()),
|
2018-11-02 21:09:36 +08:00
|
|
|
UseDirBasedCDB(UseDirBasedCDB),
|
2019-03-28 01:47:49 +08:00
|
|
|
CompileCommandsDir(std::move(CompileCommandsDir)), ClangdServerOpts(Opts),
|
|
|
|
NegotiatedOffsetEncoding(ForcedOffsetEncoding) {
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
// clang-format off
|
|
|
|
MsgHandler->bind("initialize", &ClangdLSPServer::onInitialize);
|
2020-03-03 19:12:14 +08:00
|
|
|
MsgHandler->bind("initialized", &ClangdLSPServer::onInitialized);
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
MsgHandler->bind("shutdown", &ClangdLSPServer::onShutdown);
|
[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
|
|
|
MsgHandler->bind("sync", &ClangdLSPServer::onSync);
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
MsgHandler->bind("textDocument/rangeFormatting", &ClangdLSPServer::onDocumentRangeFormatting);
|
|
|
|
MsgHandler->bind("textDocument/onTypeFormatting", &ClangdLSPServer::onDocumentOnTypeFormatting);
|
|
|
|
MsgHandler->bind("textDocument/formatting", &ClangdLSPServer::onDocumentFormatting);
|
|
|
|
MsgHandler->bind("textDocument/codeAction", &ClangdLSPServer::onCodeAction);
|
|
|
|
MsgHandler->bind("textDocument/completion", &ClangdLSPServer::onCompletion);
|
|
|
|
MsgHandler->bind("textDocument/signatureHelp", &ClangdLSPServer::onSignatureHelp);
|
|
|
|
MsgHandler->bind("textDocument/definition", &ClangdLSPServer::onGoToDefinition);
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
MsgHandler->bind("textDocument/declaration", &ClangdLSPServer::onGoToDeclaration);
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
MsgHandler->bind("textDocument/references", &ClangdLSPServer::onReference);
|
|
|
|
MsgHandler->bind("textDocument/switchSourceHeader", &ClangdLSPServer::onSwitchSourceHeader);
|
2019-07-24 15:49:23 +08:00
|
|
|
MsgHandler->bind("textDocument/prepareRename", &ClangdLSPServer::onPrepareRename);
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
MsgHandler->bind("textDocument/rename", &ClangdLSPServer::onRename);
|
|
|
|
MsgHandler->bind("textDocument/hover", &ClangdLSPServer::onHover);
|
|
|
|
MsgHandler->bind("textDocument/documentSymbol", &ClangdLSPServer::onDocumentSymbol);
|
|
|
|
MsgHandler->bind("workspace/executeCommand", &ClangdLSPServer::onCommand);
|
|
|
|
MsgHandler->bind("textDocument/documentHighlight", &ClangdLSPServer::onDocumentHighlight);
|
|
|
|
MsgHandler->bind("workspace/symbol", &ClangdLSPServer::onWorkspaceSymbol);
|
|
|
|
MsgHandler->bind("textDocument/didOpen", &ClangdLSPServer::onDocumentDidOpen);
|
|
|
|
MsgHandler->bind("textDocument/didClose", &ClangdLSPServer::onDocumentDidClose);
|
|
|
|
MsgHandler->bind("textDocument/didChange", &ClangdLSPServer::onDocumentDidChange);
|
|
|
|
MsgHandler->bind("workspace/didChangeWatchedFiles", &ClangdLSPServer::onFileEvent);
|
|
|
|
MsgHandler->bind("workspace/didChangeConfiguration", &ClangdLSPServer::onChangeConfiguration);
|
2018-11-28 00:40:46 +08:00
|
|
|
MsgHandler->bind("textDocument/symbolInfo", &ClangdLSPServer::onSymbolInfo);
|
[clangd] Add support for type hierarchy (super types only for now)
Summary:
Patch by Nathan Ridge(@nridge)!
This is an LSP extension proposed here:
https://github.com/Microsoft/vscode-languageserver-node/pull/426
An example client implementation can be found here:
https://github.com/theia-ide/theia/pull/3802
Reviewers: kadircet, sammccall
Reviewed By: kadircet
Subscribers: jdoerfert, sammccall, cfe-commits, mgorny, dschaefer, simark, ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, kadircet
Tags: #clang
Differential Revision: https://reviews.llvm.org/D56370
llvm-svn: 356445
2019-03-19 17:27:04 +08:00
|
|
|
MsgHandler->bind("textDocument/typeHierarchy", &ClangdLSPServer::onTypeHierarchy);
|
2019-07-13 11:24:48 +08:00
|
|
|
MsgHandler->bind("typeHierarchy/resolve", &ClangdLSPServer::onResolveTypeHierarchy);
|
2019-09-24 21:38:33 +08:00
|
|
|
MsgHandler->bind("textDocument/selectionRange", &ClangdLSPServer::onSelectionRange);
|
2019-12-17 02:08:51 +08:00
|
|
|
MsgHandler->bind("textDocument/documentLink", &ClangdLSPServer::onDocumentLink);
|
2020-03-24 09:24:47 +08:00
|
|
|
MsgHandler->bind("textDocument/semanticTokens", &ClangdLSPServer::onSemanticTokens);
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
// clang-format on
|
|
|
|
}
|
|
|
|
|
[clangd] abort if shutdown takes more than a minute.
Summary:
A certain class of bug (e.g. infloop on an AST worker thread) currently means
clangd never terminates, even if the editor shuts down the protocol and closes
our stdin, and the main thread recognizes that.
Instead, let's wait 60 seconds for threads to finish cleanly, and then crash
if they haven't.
(Obviously, we should still fix these bugs).
Reviewers: kadircet
Subscribers: MaskRay, jkorous, arphaman, jfb, usaxena95, cfe-commits, ilya-biryukov
Tags: #clang
Differential Revision: https://reviews.llvm.org/D69329
2019-10-23 17:11:18 +08:00
|
|
|
ClangdLSPServer::~ClangdLSPServer() { IsBeingDestroyed = true;
|
|
|
|
// Explicitly destroy ClangdServer first, blocking on threads it owns.
|
|
|
|
// This ensures they don't access any other members.
|
|
|
|
Server.reset();
|
|
|
|
}
|
2017-05-16 17:38:59 +08:00
|
|
|
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
bool ClangdLSPServer::run() {
|
2017-05-16 22:40:30 +08:00
|
|
|
// Run the Language Server loop.
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
bool CleanExit = true;
|
[clangd] Lay JSONRPCDispatcher to rest.
Summary:
Most of its functionality is moved into ClangdLSPServer.
The decoupling between JSONRPCDispatcher, ProtocolCallbacks, ClangdLSPServer
was never real, and only served to obfuscate.
Some previous implicit/magic stuff is now explicit:
- the return type of LSP method calls are now in the signature
- no more reply() that gets the ID using global context magic
- arg tracing no longer relies on RequestArgs::stash context magic either
This is mostly refactoring, but some deliberate fixes while here:
- LSP method params are now by const reference
- notifications and calls are now distinct namespaces.
(some tests had protocol errors and needed updating)
- we now reply to calls we failed to decode
- outgoing calls use distinct IDs
A few error codes and message IDs changed in unimportant ways (see tests).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53387
llvm-svn: 344737
2018-10-18 20:32:04 +08:00
|
|
|
if (auto Err = Transp.loop(*MsgHandler)) {
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
elog("Transport error: {0}", std::move(Err));
|
|
|
|
CleanExit = false;
|
|
|
|
}
|
2017-05-16 17:38:59 +08:00
|
|
|
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
return CleanExit && ShutdownRequestReceived;
|
2017-05-16 17:38:59 +08:00
|
|
|
}
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
std::vector<Fix> ClangdLSPServer::getFixes(llvm::StringRef File,
|
2018-03-12 23:28:22 +08:00
|
|
|
const clangd::Diagnostic &D) {
|
2017-05-16 17:38:59 +08:00
|
|
|
std::lock_guard<std::mutex> Lock(FixItsMutex);
|
|
|
|
auto DiagToFixItsIter = FixItsMap.find(File);
|
|
|
|
if (DiagToFixItsIter == FixItsMap.end())
|
|
|
|
return {};
|
|
|
|
|
|
|
|
const auto &DiagToFixItsMap = DiagToFixItsIter->second;
|
|
|
|
auto FixItsIter = DiagToFixItsMap.find(D);
|
|
|
|
if (FixItsIter == DiagToFixItsMap.end())
|
|
|
|
return {};
|
|
|
|
|
|
|
|
return FixItsIter->second;
|
|
|
|
}
|
|
|
|
|
2019-01-03 21:37:12 +08:00
|
|
|
bool ClangdLSPServer::shouldRunCompletion(
|
|
|
|
const CompletionParams &Params) const {
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::StringRef Trigger = Params.context.triggerCharacter;
|
2019-01-03 21:37:12 +08:00
|
|
|
if (Params.context.triggerKind != CompletionTriggerKind::TriggerCharacter ||
|
|
|
|
(Trigger != ">" && Trigger != ":"))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
auto Code = DraftMgr.getDraft(Params.textDocument.uri.file());
|
|
|
|
if (!Code)
|
|
|
|
return true; // completion code will log the error for untracked doc.
|
|
|
|
|
|
|
|
// A completion request is sent when the user types '>' or ':', but we only
|
|
|
|
// want to trigger on '->' and '::'. We check the preceeding character to make
|
|
|
|
// sure it matches what we expected.
|
|
|
|
// Running the lexer here would be more robust (e.g. we can detect comments
|
|
|
|
// and avoid triggering completion there), but we choose to err on the side
|
|
|
|
// of simplicity here.
|
2020-03-03 22:57:39 +08:00
|
|
|
auto Offset = positionToOffset(Code->Contents, Params.position,
|
2019-01-03 21:37:12 +08:00
|
|
|
/*AllowColumnsBeyondLineLength=*/false);
|
|
|
|
if (!Offset) {
|
|
|
|
vlog("could not convert position '{0}' to offset for file '{1}'",
|
|
|
|
Params.position, Params.textDocument.uri.file());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (*Offset < 2)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (Trigger == ">")
|
2020-03-03 22:57:39 +08:00
|
|
|
return Code->Contents[*Offset - 2] == '-'; // trigger only on '->'.
|
2019-01-03 21:37:12 +08:00
|
|
|
if (Trigger == ":")
|
2020-03-03 22:57:39 +08:00
|
|
|
return Code->Contents[*Offset - 2] == ':'; // trigger only on '::'.
|
2019-01-03 21:37:12 +08:00
|
|
|
assert(false && "unhandled trigger character");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-07-04 15:53:12 +08:00
|
|
|
void ClangdLSPServer::onHighlightingsReady(
|
[clangd] Track document versions, include them with diags, enhance logs
Summary:
This ties to an LSP feature (diagnostic versioning) but really a lot
of the value is in being able to log what's happening with file versions
and queues more descriptively and clearly.
As such it's fairly invasive, for a logging patch :-\
Key decisions:
- at the LSP layer, we don't reqire the client to provide versions (LSP
makes it mandatory but we never enforced it). If not provided,
versions start at 0 and increment. DraftStore handles this.
- don't propagate magically using contexts, but rather manually:
addDocument -> ParseInputs -> (ParsedAST, Preamble, various callbacks)
Context-propagation would hide the versions from ClangdServer, which
would make producing good log messages hard
- within ClangdServer, treat versions as opaque and unordered.
std::string is a convenient type for this, and allows richer versions
for embedders. They're "mandatory" but "null" is a reasonable default.
Subscribers: ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75582
2020-03-04 07:33:29 +08:00
|
|
|
PathRef File, llvm::StringRef Version,
|
|
|
|
std::vector<HighlightingToken> Highlightings) {
|
2019-08-01 16:08:44 +08:00
|
|
|
std::vector<HighlightingToken> Old;
|
|
|
|
std::vector<HighlightingToken> HighlightingsCopy = Highlightings;
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> Lock(HighlightingsMutex);
|
|
|
|
Old = std::move(FileToHighlightings[File]);
|
|
|
|
FileToHighlightings[File] = std::move(HighlightingsCopy);
|
|
|
|
}
|
|
|
|
// LSP allows us to send incremental edits of highlightings. Also need to diff
|
|
|
|
// to remove highlightings from tokens that should no longer have them.
|
2019-08-26 16:38:45 +08:00
|
|
|
std::vector<LineHighlightings> Diffed = diffHighlightings(Highlightings, Old);
|
2020-03-24 07:31:14 +08:00
|
|
|
TheiaSemanticHighlightingParams Notification;
|
[clangd] Track document versions, include them with diags, enhance logs
Summary:
This ties to an LSP feature (diagnostic versioning) but really a lot
of the value is in being able to log what's happening with file versions
and queues more descriptively and clearly.
As such it's fairly invasive, for a logging patch :-\
Key decisions:
- at the LSP layer, we don't reqire the client to provide versions (LSP
makes it mandatory but we never enforced it). If not provided,
versions start at 0 and increment. DraftStore handles this.
- don't propagate magically using contexts, but rather manually:
addDocument -> ParseInputs -> (ParsedAST, Preamble, various callbacks)
Context-propagation would hide the versions from ClangdServer, which
would make producing good log messages hard
- within ClangdServer, treat versions as opaque and unordered.
std::string is a convenient type for this, and allows richer versions
for embedders. They're "mandatory" but "null" is a reasonable default.
Subscribers: ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75582
2020-03-04 07:33:29 +08:00
|
|
|
Notification.TextDocument.uri =
|
|
|
|
URIForFile::canonicalize(File, /*TUPath=*/File);
|
|
|
|
Notification.TextDocument.version = decodeVersion(Version);
|
2020-03-24 07:31:14 +08:00
|
|
|
Notification.Lines = toTheiaSemanticHighlightingInformation(Diffed);
|
|
|
|
publishTheiaSemanticHighlighting(Notification);
|
2019-07-04 15:53:12 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Track document versions, include them with diags, enhance logs
Summary:
This ties to an LSP feature (diagnostic versioning) but really a lot
of the value is in being able to log what's happening with file versions
and queues more descriptively and clearly.
As such it's fairly invasive, for a logging patch :-\
Key decisions:
- at the LSP layer, we don't reqire the client to provide versions (LSP
makes it mandatory but we never enforced it). If not provided,
versions start at 0 and increment. DraftStore handles this.
- don't propagate magically using contexts, but rather manually:
addDocument -> ParseInputs -> (ParsedAST, Preamble, various callbacks)
Context-propagation would hide the versions from ClangdServer, which
would make producing good log messages hard
- within ClangdServer, treat versions as opaque and unordered.
std::string is a convenient type for this, and allows richer versions
for embedders. They're "mandatory" but "null" is a reasonable default.
Subscribers: ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75582
2020-03-04 07:33:29 +08:00
|
|
|
void ClangdLSPServer::onDiagnosticsReady(PathRef File, llvm::StringRef Version,
|
2018-03-13 07:22:35 +08:00
|
|
|
std::vector<Diag> Diagnostics) {
|
2020-03-03 19:44:40 +08:00
|
|
|
PublishDiagnosticsParams Notification;
|
[clangd] Track document versions, include them with diags, enhance logs
Summary:
This ties to an LSP feature (diagnostic versioning) but really a lot
of the value is in being able to log what's happening with file versions
and queues more descriptively and clearly.
As such it's fairly invasive, for a logging patch :-\
Key decisions:
- at the LSP layer, we don't reqire the client to provide versions (LSP
makes it mandatory but we never enforced it). If not provided,
versions start at 0 and increment. DraftStore handles this.
- don't propagate magically using contexts, but rather manually:
addDocument -> ParseInputs -> (ParsedAST, Preamble, various callbacks)
Context-propagation would hide the versions from ClangdServer, which
would make producing good log messages hard
- within ClangdServer, treat versions as opaque and unordered.
std::string is a convenient type for this, and allows richer versions
for embedders. They're "mandatory" but "null" is a reasonable default.
Subscribers: ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75582
2020-03-04 07:33:29 +08:00
|
|
|
Notification.version = decodeVersion(Version);
|
2020-03-03 19:44:40 +08:00
|
|
|
Notification.uri = URIForFile::canonicalize(File, /*TUPath=*/File);
|
2017-05-16 17:38:59 +08:00
|
|
|
DiagnosticToReplacementMap LocalFixIts; // Temporary storage
|
2018-03-13 07:22:35 +08:00
|
|
|
for (auto &Diag : Diagnostics) {
|
2020-03-03 19:44:40 +08:00
|
|
|
toLSPDiags(Diag, Notification.uri, DiagOpts,
|
2019-01-07 23:45:19 +08:00
|
|
|
[&](clangd::Diagnostic Diag, llvm::ArrayRef<Fix> Fixes) {
|
[clangd] Embed fixes as CodeAction, instead of clangd_fixes. Clean up serialization.
Summary:
CodeAction provides us with a standard way of representing fixes inline, so
use it, replacing our existing ad-hoc extension.
After this, it's easy to serialize diagnostics using the structured
toJSON/Protocol.h mechanism rather than assembling JSON ad-hoc.
Reviewers: hokein, arphaman
Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53391
llvm-svn: 345119
2018-10-24 15:59:38 +08:00
|
|
|
auto &FixItsForDiagnostic = LocalFixIts[Diag];
|
|
|
|
llvm::copy(Fixes, std::back_inserter(FixItsForDiagnostic));
|
2020-03-03 19:44:40 +08:00
|
|
|
Notification.diagnostics.push_back(std::move(Diag));
|
[clangd] Embed fixes as CodeAction, instead of clangd_fixes. Clean up serialization.
Summary:
CodeAction provides us with a standard way of representing fixes inline, so
use it, replacing our existing ad-hoc extension.
After this, it's easy to serialize diagnostics using the structured
toJSON/Protocol.h mechanism rather than assembling JSON ad-hoc.
Reviewers: hokein, arphaman
Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53391
llvm-svn: 345119
2018-10-24 15:59:38 +08:00
|
|
|
});
|
2017-05-16 17:38:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Cache FixIts
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> Lock(FixItsMutex);
|
|
|
|
FixItsMap[File] = LocalFixIts;
|
|
|
|
}
|
|
|
|
|
2019-03-25 18:15:11 +08:00
|
|
|
// Send a notification to the LSP client.
|
2020-03-03 19:44:40 +08:00
|
|
|
publishDiagnostics(Notification);
|
2017-05-16 17:38:59 +08:00
|
|
|
}
|
2018-03-16 22:30:42 +08:00
|
|
|
|
[clangd] Show background index status using LSP 3.15 work-done progress notifications
Summary:
It simply shows the completed/total items on the background queue, e.g.
indexing: 233/1000
The denominator is reset to zero every time the queue goes idle.
The protocol is fairly complicated here (requires creating a remote "progress"
resource before sending updates). We implement the full protocol, but I've added
an extension allowing it to be skipped to reduce the burden on clients - in
particular the lit test takes this shortcut.
The addition of background index progress to DiagnosticConsumer seems ridiculous
at first glance, but I believe that interface is trending in the direction of
"ClangdServer callbacks" anyway. It's due for a rename, but otherwise actually
fits.
Reviewers: kadircet, usaxena95
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D73218
2020-01-23 02:41:45 +08:00
|
|
|
void ClangdLSPServer::onBackgroundIndexProgress(
|
|
|
|
const BackgroundQueue::Stats &Stats) {
|
|
|
|
static const char ProgressToken[] = "backgroundIndexProgress";
|
|
|
|
std::lock_guard<std::mutex> Lock(BackgroundIndexProgressMutex);
|
|
|
|
|
|
|
|
auto NotifyProgress = [this](const BackgroundQueue::Stats &Stats) {
|
|
|
|
if (BackgroundIndexProgressState != BackgroundIndexProgress::Live) {
|
|
|
|
WorkDoneProgressBegin Begin;
|
|
|
|
Begin.percentage = true;
|
|
|
|
Begin.title = "indexing";
|
|
|
|
progress(ProgressToken, std::move(Begin));
|
|
|
|
BackgroundIndexProgressState = BackgroundIndexProgress::Live;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Stats.Completed < Stats.Enqueued) {
|
|
|
|
assert(Stats.Enqueued > Stats.LastIdle);
|
|
|
|
WorkDoneProgressReport Report;
|
|
|
|
Report.percentage = 100.0 * (Stats.Completed - Stats.LastIdle) /
|
|
|
|
(Stats.Enqueued - Stats.LastIdle);
|
|
|
|
Report.message =
|
|
|
|
llvm::formatv("{0}/{1}", Stats.Completed - Stats.LastIdle,
|
|
|
|
Stats.Enqueued - Stats.LastIdle);
|
|
|
|
progress(ProgressToken, std::move(Report));
|
|
|
|
} else {
|
|
|
|
assert(Stats.Completed == Stats.Enqueued);
|
|
|
|
progress(ProgressToken, WorkDoneProgressEnd());
|
|
|
|
BackgroundIndexProgressState = BackgroundIndexProgress::Empty;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
switch (BackgroundIndexProgressState) {
|
|
|
|
case BackgroundIndexProgress::Unsupported:
|
|
|
|
return;
|
|
|
|
case BackgroundIndexProgress::Creating:
|
|
|
|
// Cache this update for when the progress bar is available.
|
|
|
|
PendingBackgroundIndexProgress = Stats;
|
|
|
|
return;
|
|
|
|
case BackgroundIndexProgress::Empty: {
|
|
|
|
if (BackgroundIndexSkipCreate) {
|
|
|
|
NotifyProgress(Stats);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Cache this update for when the progress bar is available.
|
|
|
|
PendingBackgroundIndexProgress = Stats;
|
|
|
|
BackgroundIndexProgressState = BackgroundIndexProgress::Creating;
|
|
|
|
WorkDoneProgressCreateParams CreateRequest;
|
|
|
|
CreateRequest.token = ProgressToken;
|
|
|
|
call<std::nullptr_t>(
|
|
|
|
"window/workDoneProgress/create", CreateRequest,
|
|
|
|
[this, NotifyProgress](llvm::Expected<std::nullptr_t> E) {
|
|
|
|
std::lock_guard<std::mutex> Lock(BackgroundIndexProgressMutex);
|
|
|
|
if (E) {
|
|
|
|
NotifyProgress(this->PendingBackgroundIndexProgress);
|
|
|
|
} else {
|
|
|
|
elog("Failed to create background index progress bar: {0}",
|
|
|
|
E.takeError());
|
|
|
|
// give up forever rather than thrashing about
|
|
|
|
BackgroundIndexProgressState = BackgroundIndexProgress::Unsupported;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case BackgroundIndexProgress::Live:
|
|
|
|
NotifyProgress(Stats);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-20 23:39:12 +08:00
|
|
|
void ClangdLSPServer::onFileUpdated(PathRef File, const TUStatus &Status) {
|
|
|
|
if (!SupportFileStatus)
|
|
|
|
return;
|
|
|
|
// FIXME: we don't emit "BuildingFile" and `RunningAction`, as these
|
|
|
|
// two statuses are running faster in practice, which leads the UI constantly
|
|
|
|
// changing, and doesn't provide much value. We may want to emit status at a
|
|
|
|
// reasonable time interval (e.g. 0.5s).
|
|
|
|
if (Status.Action.S == TUAction::BuildingFile ||
|
|
|
|
Status.Action.S == TUAction::RunningAction)
|
|
|
|
return;
|
|
|
|
notify("textDocument/clangd.fileStatus", Status.render(File));
|
|
|
|
}
|
|
|
|
|
2020-01-14 06:01:10 +08:00
|
|
|
void ClangdLSPServer::reparseOpenedFiles(
|
|
|
|
const llvm::StringSet<> &ModifiedFiles) {
|
|
|
|
if (ModifiedFiles.empty())
|
|
|
|
return;
|
|
|
|
// Reparse only opened files that were modified.
|
2018-03-16 22:30:42 +08:00
|
|
|
for (const Path &FilePath : DraftMgr.getActiveFiles())
|
2020-01-14 06:01:10 +08:00
|
|
|
if (ModifiedFiles.find(FilePath) != ModifiedFiles.end())
|
[clangd] Track document versions, include them with diags, enhance logs
Summary:
This ties to an LSP feature (diagnostic versioning) but really a lot
of the value is in being able to log what's happening with file versions
and queues more descriptively and clearly.
As such it's fairly invasive, for a logging patch :-\
Key decisions:
- at the LSP layer, we don't reqire the client to provide versions (LSP
makes it mandatory but we never enforced it). If not provided,
versions start at 0 and increment. DraftStore handles this.
- don't propagate magically using contexts, but rather manually:
addDocument -> ParseInputs -> (ParsedAST, Preamble, various callbacks)
Context-propagation would hide the versions from ClangdServer, which
would make producing good log messages hard
- within ClangdServer, treat versions as opaque and unordered.
std::string is a convenient type for this, and allows richer versions
for embedders. They're "mandatory" but "null" is a reasonable default.
Subscribers: ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75582
2020-03-04 07:33:29 +08:00
|
|
|
if (auto Draft = DraftMgr.getDraft(FilePath)) // else disappeared in race?
|
|
|
|
Server->addDocument(FilePath, std::move(Draft->Contents),
|
|
|
|
encodeVersion(Draft->Version),
|
|
|
|
WantDiagnostics::Auto);
|
2018-03-16 22:30:42 +08:00
|
|
|
}
|
2018-08-02 01:39:29 +08:00
|
|
|
|
2018-10-20 23:30:37 +08:00
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|