2017-05-16 17:38:59 +08:00
|
|
|
//===--- ClangdServer.cpp - Main clangd server code --------------*- 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
|
|
|
//
|
|
|
|
//===-------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "ClangdServer.h"
|
2017-12-20 01:06:07 +08:00
|
|
|
#include "CodeComplete.h"
|
2020-07-03 05:09:25 +08:00
|
|
|
#include "Config.h"
|
2021-03-15 17:18:12 +08:00
|
|
|
#include "Diagnostics.h"
|
2020-10-17 02:03:48 +08:00
|
|
|
#include "DumpAST.h"
|
[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
|
|
|
#include "FindSymbols.h"
|
[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
|
|
|
#include "Format.h"
|
2019-09-25 18:30:22 +08:00
|
|
|
#include "HeaderSourceSwitch.h"
|
2021-02-22 15:55:13 +08:00
|
|
|
#include "InlayHints.h"
|
2019-09-04 17:46:06 +08:00
|
|
|
#include "ParsedAST.h"
|
2019-09-04 15:35:00 +08:00
|
|
|
#include "Preamble.h"
|
[clangd] Add fallback mode for code completion when compile command or preamble is not ready.
Summary:
When calling TUScehduler::runWithPreamble (e.g. in code compleiton), allow
entering a fallback mode when compile command or preamble is not ready, instead of
waiting. This allows clangd to perform naive code completion e.g. using identifiers
in the current file or symbols in the index.
This patch simply returns empty result for code completion in fallback mode. Identifier-based
plus more advanced index-based completion will be added in followup patches.
Reviewers: ilya-biryukov, sammccall
Reviewed By: sammccall
Subscribers: sammccall, javed.absar, MaskRay, jkorous, arphaman, kadircet, jdoerfert, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D59811
llvm-svn: 357916
2019-04-08 22:53:16 +08:00
|
|
|
#include "Protocol.h"
|
2019-07-19 21:51:01 +08:00
|
|
|
#include "SemanticHighlighting.h"
|
2019-09-17 18:28:05 +08:00
|
|
|
#include "SemanticSelection.h"
|
2017-12-19 20:23:48 +08:00
|
|
|
#include "SourceCode.h"
|
[clangd] Add fallback mode for code completion when compile command or preamble is not ready.
Summary:
When calling TUScehduler::runWithPreamble (e.g. in code compleiton), allow
entering a fallback mode when compile command or preamble is not ready, instead of
waiting. This allows clangd to perform naive code completion e.g. using identifiers
in the current file or symbols in the index.
This patch simply returns empty result for code completion in fallback mode. Identifier-based
plus more advanced index-based completion will be added in followup patches.
Reviewers: ilya-biryukov, sammccall
Reviewed By: sammccall
Subscribers: sammccall, javed.absar, MaskRay, jkorous, arphaman, kadircet, jdoerfert, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D59811
llvm-svn: 357916
2019-04-08 22:53:16 +08:00
|
|
|
#include "TUScheduler.h"
|
2019-05-29 18:01:00 +08:00
|
|
|
#include "XRefs.h"
|
2019-02-05 00:19:57 +08:00
|
|
|
#include "index/CanonicalIncludes.h"
|
2018-09-18 18:30:44 +08:00
|
|
|
#include "index/FileIndex.h"
|
2018-01-15 20:33:00 +08:00
|
|
|
#include "index/Merge.h"
|
2019-05-07 15:11:56 +08:00
|
|
|
#include "refactor/Rename.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 "refactor/Tweak.h"
|
2022-02-26 18:40:12 +08:00
|
|
|
#include "support/Cancellation.h"
|
[clangd] Move non-clang base pieces into separate support/ lib. NFCI
Summary:
This enforces layering, reduces a sprawling clangd/ directory, and makes life
easier for embedders.
Reviewers: kbobyrev
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D79014
2020-04-28 23:49:17 +08:00
|
|
|
#include "support/Logger.h"
|
2020-09-28 21:09:55 +08:00
|
|
|
#include "support/MemoryTree.h"
|
2020-06-17 17:53:32 +08:00
|
|
|
#include "support/ThreadsafeFS.h"
|
[clangd] Move non-clang base pieces into separate support/ lib. NFCI
Summary:
This enforces layering, reduces a sprawling clangd/ directory, and makes life
easier for embedders.
Reviewers: kbobyrev
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D79014
2020-04-28 23:49:17 +08:00
|
|
|
#include "support/Trace.h"
|
2017-05-16 22:40:30 +08:00
|
|
|
#include "clang/Format/Format.h"
|
2018-05-24 23:50:15 +08:00
|
|
|
#include "clang/Lex/Preprocessor.h"
|
2017-05-16 17:38:59 +08:00
|
|
|
#include "clang/Tooling/CompilationDatabase.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"
|
2017-05-16 22:40:30 +08:00
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
[clangd] Speculative code completion index request before Sema is run.
Summary:
For index-based code completion, send an asynchronous speculative index
request, based on the index request for the last code completion on the same
file and the filter text typed before the cursor, before sema code completion
is invoked. This can reduce the code completion latency (by roughly latency of
sema code completion) if the speculative request is the same as the one
generated for the ongoing code completion from sema. As a sequence of code
completions often have the same scopes and proximity paths etc, this should be
effective for a number of code completions.
Trace with speculative index request:{F6997544}
Reviewers: hokein, ilya-biryukov
Reviewed By: ilya-biryukov
Subscribers: javed.absar, jfb, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D50962
llvm-svn: 340604
2018-08-24 19:23:56 +08:00
|
|
|
#include "llvm/ADT/Optional.h"
|
2019-07-19 21:51:01 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2018-06-13 17:20:41 +08:00
|
|
|
#include "llvm/ADT/StringRef.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"
|
2017-09-27 23:31:17 +08:00
|
|
|
#include "llvm/Support/Path.h"
|
2017-05-23 21:42:59 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
clangd: use -j for background index pool
Summary:
clangd supports a -j option to limit the amount of threads to use for parsing
TUs. However, when using -background-index (the default in later versions of
clangd), the parallelism used by clangd defaults to the hardware_parallelisn,
i.e. number of physical cores.
On shared hardware environments, with large projects, this can significantly
affect performance with no way to tune it down.
This change makes the -j parameter apply equally to parsing and background
index. It's not perfect, because the total number of threads is 2x the -j value,
which may still be unexpected. But at least this change allows users to prevent
clangd using all CPU cores.
Reviewers: kadircet, sammccall
Reviewed By: sammccall
Subscribers: javed.absar, jfb, sammccall, ilya-biryukov, MaskRay, jkorous, arphaman, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66031
llvm-svn: 368498
2019-08-10 07:03:32 +08:00
|
|
|
#include <algorithm>
|
2020-07-14 16:45:06 +08:00
|
|
|
#include <chrono>
|
2017-05-23 21:42:59 +08:00
|
|
|
#include <future>
|
[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 <memory>
|
[clangd] Speculative code completion index request before Sema is run.
Summary:
For index-based code completion, send an asynchronous speculative index
request, based on the index request for the last code completion on the same
file and the filter text typed before the cursor, before sema code completion
is invoked. This can reduce the code completion latency (by roughly latency of
sema code completion) if the speculative request is the same as the one
generated for the ongoing code completion from sema. As a sequence of code
completions often have the same scopes and proximity paths etc, this should be
effective for a number of code completions.
Trace with speculative index request:{F6997544}
Reviewers: hokein, ilya-biryukov
Reviewed By: ilya-biryukov
Subscribers: javed.absar, jfb, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D50962
llvm-svn: 340604
2018-08-24 19:23:56 +08:00
|
|
|
#include <mutex>
|
[clangd] Move clang-tidy check modifications into ClangdServer
Summary:
This enables sharing the logic between standalone clangd and embedders
of it. The new approach should be same performance-wise, as it is only called
once per addDocument call.
This patch also introduces a blacklisting code path for disabling crashy or
high-noise tests, until we figure out a way to make them work with clangd-setup.
The biggest difference is the way we make use of preambles, hence those checks
can't see directives coming from the preamble section of the file. The second
thing is the fact that code might-not be compiling while clangd is trying to
build an AST, hence some checks might choke on those incomplete ASTs.
Reviewers: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, aaron.ballman, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83224
2020-07-06 21:44:16 +08:00
|
|
|
#include <string>
|
clangd: use -j for background index pool
Summary:
clangd supports a -j option to limit the amount of threads to use for parsing
TUs. However, when using -background-index (the default in later versions of
clangd), the parallelism used by clangd defaults to the hardware_parallelisn,
i.e. number of physical cores.
On shared hardware environments, with large projects, this can significantly
affect performance with no way to tune it down.
This change makes the -j parameter apply equally to parsing and background
index. It's not perfect, because the total number of threads is 2x the -j value,
which may still be unexpected. But at least this change allows users to prevent
clangd using all CPU cores.
Reviewers: kadircet, sammccall
Reviewed By: sammccall
Subscribers: javed.absar, jfb, sammccall, ilya-biryukov, MaskRay, jkorous, arphaman, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66031
llvm-svn: 368498
2019-08-10 07:03:32 +08:00
|
|
|
#include <type_traits>
|
2017-05-16 17:38:59 +08:00
|
|
|
|
2018-10-20 23:30:37 +08:00
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
2017-05-16 22:40:30 +08:00
|
|
|
namespace {
|
|
|
|
|
2018-11-23 01:27:08 +08:00
|
|
|
// Update the FileIndex with new ASTs and plumb the diagnostics responses.
|
|
|
|
struct UpdateIndexCallbacks : public ParsingCallbacks {
|
2020-01-24 21:08:56 +08:00
|
|
|
UpdateIndexCallbacks(FileIndex *FIndex,
|
2021-01-28 08:16:47 +08:00
|
|
|
ClangdServer::Callbacks *ServerCallbacks)
|
|
|
|
: FIndex(FIndex), ServerCallbacks(ServerCallbacks) {}
|
[clangd] Add callbacks on parsed AST in addition to parsed preambles
Summary:
Will be used for updating the dynamic index on updates to the open files.
Currently we collect only information coming from the preamble
AST. This has a bunch of limitations:
- Dynamic index misses important information from the body of the
file, e.g. locations of definitions.
- XRefs cannot be collected at all, since we can only obtain full
information for the current file (preamble is parsed with skipped
function bodies, therefore not reliable).
This patch only adds the new callback, actually updates to the index
will be done in a follow-up patch.
Reviewers: hokein
Reviewed By: hokein
Subscribers: kadircet, javed.absar, ioeric, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D50847
llvm-svn: 340401
2018-08-22 19:39:16 +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 onPreambleAST(PathRef Path, llvm::StringRef Version, ASTContext &Ctx,
|
2021-12-15 09:13:26 +08:00
|
|
|
Preprocessor &PP,
|
2019-02-05 00:19:57 +08:00
|
|
|
const CanonicalIncludes &CanonIncludes) override {
|
2018-11-23 01:27:08 +08:00
|
|
|
if (FIndex)
|
2021-12-15 09:13:26 +08:00
|
|
|
FIndex->updatePreamble(Path, Version, Ctx, PP, CanonIncludes);
|
2018-11-23 01:27:08 +08:00
|
|
|
}
|
2018-09-18 18:30:44 +08:00
|
|
|
|
2019-07-19 21:51:01 +08:00
|
|
|
void onMainAST(PathRef Path, ParsedAST &AST, PublishFn Publish) override {
|
2018-11-23 01:27:08 +08:00
|
|
|
if (FIndex)
|
2018-09-18 21:35:16 +08:00
|
|
|
FIndex->updateMain(Path, AST);
|
2019-07-19 21:51:01 +08:00
|
|
|
|
2021-03-15 17:18:12 +08:00
|
|
|
assert(AST.getDiagnostics().hasValue() &&
|
|
|
|
"We issue callback only with fresh preambles");
|
|
|
|
std::vector<Diag> Diagnostics = *AST.getDiagnostics();
|
2020-01-24 21:08:56 +08:00
|
|
|
if (ServerCallbacks)
|
|
|
|
Publish([&]() {
|
[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
|
|
|
ServerCallbacks->onDiagnosticsReady(Path, AST.version(),
|
|
|
|
std::move(Diagnostics));
|
2020-01-24 21:08:56 +08:00
|
|
|
});
|
2018-11-23 01:27:08 +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 onFailedAST(PathRef Path, llvm::StringRef Version,
|
|
|
|
std::vector<Diag> Diags, PublishFn Publish) override {
|
2020-01-24 21:08:56 +08:00
|
|
|
if (ServerCallbacks)
|
[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
|
|
|
Publish(
|
|
|
|
[&]() { ServerCallbacks->onDiagnosticsReady(Path, Version, Diags); });
|
[clangd] Surface errors from command-line parsing
Summary:
Those errors are exposed at the first character of a file,
for a lack of a better place.
Previously, all errors were stored inside the AST and report
accordingly. However, errors in command-line argument parsing could
result in failure to produce the AST, so we need an alternative ways to
report those errors.
We take the following approach in this patch:
- buildCompilerInvocation() now requires an explicit DiagnosticConsumer.
- TUScheduler and TestTU now collect the diagnostics produced when
parsing command line arguments.
If pasing of the AST failed, diagnostics are reported via a new
ParsingCallbacks::onFailedAST method.
If parsing of the AST succeeded, any errors produced during
command-line parsing are stored alongside the AST inside the
ParsedAST instance and reported as previously by calling the
ParsingCallbacks::onMainAST method;
- The client code that uses ClangdServer's DiagnosticConsumer
does not need to change, it will receive new diagnostics in the
onDiagnosticsReady() callback
Errors produced when parsing command-line arguments are collected using
the same StoreDiags class that is used to collect all other errors. They
are recognized by their location being invalid. IIUC, the location is
invalid as there is no source manager at this point, it is created at a
later stage.
Although technically we might also get diagnostics that mention the
command-line arguments FileID with after the source manager was created
(and they have valid source locations), we choose to not handle those
and they are dropped as not coming from the main file. AFAICT, those
diagnostics should always be notes, therefore it's safe to drop them
without loosing too much information.
Reviewers: kadircet
Reviewed By: kadircet
Subscribers: nridge, javed.absar, MaskRay, jkorous, arphaman, cfe-commits, gribozavr
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66759
llvm-svn: 370177
2019-08-28 17:24:55 +08:00
|
|
|
}
|
|
|
|
|
2018-12-06 17:41:04 +08:00
|
|
|
void onFileUpdated(PathRef File, const TUStatus &Status) override {
|
2020-01-24 21:08:56 +08:00
|
|
|
if (ServerCallbacks)
|
|
|
|
ServerCallbacks->onFileUpdated(File, Status);
|
2018-12-06 17:41:04 +08:00
|
|
|
}
|
|
|
|
|
2021-05-19 19:45:44 +08:00
|
|
|
void onPreamblePublished(PathRef File) override {
|
|
|
|
if (ServerCallbacks)
|
|
|
|
ServerCallbacks->onSemanticsMaybeChanged(File);
|
|
|
|
}
|
|
|
|
|
2018-11-23 01:27:08 +08:00
|
|
|
private:
|
|
|
|
FileIndex *FIndex;
|
2020-01-24 21:08:56 +08:00
|
|
|
ClangdServer::Callbacks *ServerCallbacks;
|
2018-11-23 01:27:08 +08:00
|
|
|
};
|
[clangd] Move clang-tidy check modifications into ClangdServer
Summary:
This enables sharing the logic between standalone clangd and embedders
of it. The new approach should be same performance-wise, as it is only called
once per addDocument call.
This patch also introduces a blacklisting code path for disabling crashy or
high-noise tests, until we figure out a way to make them work with clangd-setup.
The biggest difference is the way we make use of preambles, hence those checks
can't see directives coming from the preamble section of the file. The second
thing is the fact that code might-not be compiling while clangd is trying to
build an AST, hence some checks might choke on those incomplete ASTs.
Reviewers: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, aaron.ballman, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83224
2020-07-06 21:44:16 +08:00
|
|
|
|
2021-03-09 22:35:20 +08:00
|
|
|
class DraftStoreFS : public ThreadsafeFS {
|
|
|
|
public:
|
|
|
|
DraftStoreFS(const ThreadsafeFS &Base, const DraftStore &Drafts)
|
|
|
|
: Base(Base), DirtyFiles(Drafts) {}
|
|
|
|
|
|
|
|
private:
|
|
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> viewImpl() const override {
|
|
|
|
auto OFS = llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(
|
|
|
|
Base.view(llvm::None));
|
|
|
|
OFS->pushOverlay(DirtyFiles.asVFS());
|
|
|
|
return OFS;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ThreadsafeFS &Base;
|
|
|
|
const DraftStore &DirtyFiles;
|
|
|
|
};
|
|
|
|
|
2018-11-23 01:27:08 +08:00
|
|
|
} // namespace
|
[clangd] Add callbacks on parsed AST in addition to parsed preambles
Summary:
Will be used for updating the dynamic index on updates to the open files.
Currently we collect only information coming from the preamble
AST. This has a bunch of limitations:
- Dynamic index misses important information from the body of the
file, e.g. locations of definitions.
- XRefs cannot be collected at all, since we can only obtain full
information for the current file (preamble is parsed with skipped
function bodies, therefore not reliable).
This patch only adds the new callback, actually updates to the index
will be done in a follow-up patch.
Reviewers: hokein
Reviewed By: hokein
Subscribers: kadircet, javed.absar, ioeric, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D50847
llvm-svn: 340401
2018-08-22 19:39:16 +08:00
|
|
|
|
2018-03-06 01:28:54 +08:00
|
|
|
ClangdServer::Options ClangdServer::optsForTest() {
|
|
|
|
ClangdServer::Options Opts;
|
2020-02-04 22:41:39 +08:00
|
|
|
Opts.UpdateDebounce = DebouncePolicy::fixed(/*zero*/ {});
|
2018-03-06 01:28:54 +08:00
|
|
|
Opts.StorePreamblesInMemory = true;
|
|
|
|
Opts.AsyncThreadsCount = 4; // Consistent!
|
|
|
|
return Opts;
|
|
|
|
}
|
|
|
|
|
2020-02-03 18:18:13 +08:00
|
|
|
ClangdServer::Options::operator TUScheduler::Options() const {
|
|
|
|
TUScheduler::Options Opts;
|
|
|
|
Opts.AsyncThreadsCount = AsyncThreadsCount;
|
|
|
|
Opts.RetentionPolicy = RetentionPolicy;
|
|
|
|
Opts.StorePreamblesInMemory = StorePreamblesInMemory;
|
|
|
|
Opts.UpdateDebounce = UpdateDebounce;
|
2021-01-21 05:34:24 +08:00
|
|
|
Opts.ContextProvider = ContextProvider;
|
2020-02-03 18:18:13 +08:00
|
|
|
return Opts;
|
|
|
|
}
|
|
|
|
|
2018-10-10 15:46:15 +08:00
|
|
|
ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB,
|
2020-06-18 00:09:54 +08:00
|
|
|
const ThreadsafeFS &TFS, const Options &Opts,
|
2020-06-17 17:53:32 +08:00
|
|
|
Callbacks *Callbacks)
|
2021-03-04 23:21:01 +08:00
|
|
|
: FeatureModules(Opts.FeatureModules), CDB(CDB), TFS(TFS),
|
2021-01-28 07:42:16 +08:00
|
|
|
DynamicIdx(Opts.BuildDynamicSymbolIndex ? new FileIndex() : nullptr),
|
2020-11-26 02:35:34 +08:00
|
|
|
ClangTidyProvider(Opts.ClangTidyProvider),
|
2022-01-17 18:55:35 +08:00
|
|
|
UseDirtyHeaders(Opts.UseDirtyHeaders), WorkspaceRoot(Opts.WorkspaceRoot),
|
2021-03-11 20:43:59 +08:00
|
|
|
Transient(Opts.ImplicitCancellation ? TUScheduler::InvalidateOnUpdate
|
|
|
|
: TUScheduler::NoInvalidation),
|
2021-03-09 22:35:20 +08:00
|
|
|
DirtyFS(std::make_unique<DraftStoreFS>(TFS, DraftMgr)) {
|
2021-02-16 16:16:10 +08:00
|
|
|
// Pass a callback into `WorkScheduler` to extract symbols from a newly
|
|
|
|
// parsed file and rebuild the file index synchronously each time an AST
|
|
|
|
// is parsed.
|
|
|
|
WorkScheduler.emplace(
|
|
|
|
CDB, TUScheduler::Options(Opts),
|
|
|
|
std::make_unique<UpdateIndexCallbacks>(DynamicIdx.get(), Callbacks));
|
[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
|
|
|
// Adds an index to the stack, at higher priority than existing indexes.
|
|
|
|
auto AddIndex = [&](SymbolIndex *Idx) {
|
|
|
|
if (this->Index != nullptr) {
|
2019-08-15 07:52:23 +08:00
|
|
|
MergedIdx.push_back(std::make_unique<MergedIndex>(Idx, this->Index));
|
[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
|
|
|
this->Index = MergedIdx.back().get();
|
|
|
|
} else {
|
|
|
|
this->Index = Idx;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
if (Opts.StaticIndex)
|
|
|
|
AddIndex(Opts.StaticIndex);
|
|
|
|
if (Opts.BackgroundIndex) {
|
2020-08-14 00:01:47 +08:00
|
|
|
BackgroundIndex::Options BGOpts;
|
|
|
|
BGOpts.ThreadPoolSize = std::max(Opts.AsyncThreadsCount, 1u);
|
|
|
|
BGOpts.OnProgress = [Callbacks](BackgroundQueue::Stats S) {
|
|
|
|
if (Callbacks)
|
|
|
|
Callbacks->onBackgroundIndexProgress(S);
|
|
|
|
};
|
2021-01-21 05:34:24 +08:00
|
|
|
BGOpts.ContextProvider = Opts.ContextProvider;
|
2019-08-15 07:52:23 +08:00
|
|
|
BackgroundIdx = std::make_unique<BackgroundIndex>(
|
2020-08-14 00:01:47 +08:00
|
|
|
TFS, CDB,
|
2019-07-19 18:18:52 +08:00
|
|
|
BackgroundIndexStorage::createDiskBackedStorageFactory(
|
clangd: use -j for background index pool
Summary:
clangd supports a -j option to limit the amount of threads to use for parsing
TUs. However, when using -background-index (the default in later versions of
clangd), the parallelism used by clangd defaults to the hardware_parallelisn,
i.e. number of physical cores.
On shared hardware environments, with large projects, this can significantly
affect performance with no way to tune it down.
This change makes the -j parameter apply equally to parsing and background
index. It's not perfect, because the total number of threads is 2x the -j value,
which may still be unexpected. But at least this change allows users to prevent
clangd using all CPU cores.
Reviewers: kadircet, sammccall
Reviewed By: sammccall
Subscribers: javed.absar, jfb, sammccall, ilya-biryukov, MaskRay, jkorous, arphaman, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66031
llvm-svn: 368498
2019-08-10 07:03:32 +08:00
|
|
|
[&CDB](llvm::StringRef File) { return CDB.getProjectInfo(File); }),
|
2020-08-14 00:01:47 +08:00
|
|
|
std::move(BGOpts));
|
[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
|
|
|
AddIndex(BackgroundIdx.get());
|
|
|
|
}
|
|
|
|
if (DynamicIdx)
|
|
|
|
AddIndex(DynamicIdx.get());
|
2021-02-16 03:26:48 +08:00
|
|
|
|
2021-03-04 23:21:01 +08:00
|
|
|
if (Opts.FeatureModules) {
|
|
|
|
FeatureModule::Facilities F{
|
2021-02-16 16:16:10 +08:00
|
|
|
*this->WorkScheduler,
|
2021-02-16 03:26:48 +08:00
|
|
|
this->Index,
|
|
|
|
this->TFS,
|
|
|
|
};
|
2021-03-04 23:21:01 +08:00
|
|
|
for (auto &Mod : *Opts.FeatureModules)
|
2021-02-16 03:26:48 +08:00
|
|
|
Mod.initialize(F);
|
|
|
|
}
|
2018-01-15 20:33:00 +08:00
|
|
|
}
|
2017-05-16 17:38:59 +08:00
|
|
|
|
2021-02-16 16:16:10 +08:00
|
|
|
ClangdServer::~ClangdServer() {
|
|
|
|
// Destroying TUScheduler first shuts down request threads that might
|
|
|
|
// otherwise access members concurrently.
|
|
|
|
// (Nobody can be using TUScheduler because we're on the main thread).
|
|
|
|
WorkScheduler.reset();
|
2021-03-04 23:21:01 +08:00
|
|
|
// Now requests have stopped, we can shut down feature modules.
|
|
|
|
if (FeatureModules) {
|
|
|
|
for (auto &Mod : *FeatureModules)
|
2021-02-16 16:16:10 +08:00
|
|
|
Mod.stop();
|
2021-03-04 23:21:01 +08:00
|
|
|
for (auto &Mod : *FeatureModules)
|
2021-02-16 16:16:10 +08:00
|
|
|
Mod.blockUntilIdle(Deadline::infinity());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
void ClangdServer::addDocument(PathRef File, llvm::StringRef Contents,
|
[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
|
|
|
llvm::StringRef Version,
|
2020-02-04 04:14:49 +08:00
|
|
|
WantDiagnostics WantDiags, bool ForceRebuild) {
|
2021-03-02 07:16:33 +08:00
|
|
|
std::string ActualVersion = DraftMgr.addDraft(File, Version, Contents);
|
2019-01-28 22:01:55 +08:00
|
|
|
ParseOptions Opts;
|
[clangd] Add fallback mode for code completion when compile command or preamble is not ready.
Summary:
When calling TUScehduler::runWithPreamble (e.g. in code compleiton), allow
entering a fallback mode when compile command or preamble is not ready, instead of
waiting. This allows clangd to perform naive code completion e.g. using identifiers
in the current file or symbols in the index.
This patch simply returns empty result for code completion in fallback mode. Identifier-based
plus more advanced index-based completion will be added in followup patches.
Reviewers: ilya-biryukov, sammccall
Reviewed By: sammccall
Subscribers: sammccall, javed.absar, MaskRay, jkorous, arphaman, kadircet, jdoerfert, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D59811
llvm-svn: 357916
2019-04-08 22:53:16 +08:00
|
|
|
|
2019-04-15 20:32:28 +08:00
|
|
|
// Compile command is set asynchronously during update, as it can be slow.
|
2019-01-28 22:01:55 +08:00
|
|
|
ParseInputs Inputs;
|
2022-01-17 18:55:35 +08:00
|
|
|
Inputs.TFS = &getHeaderFS();
|
2020-01-29 03:23:46 +08:00
|
|
|
Inputs.Contents = std::string(Contents);
|
2021-03-02 07:16:33 +08:00
|
|
|
Inputs.Version = std::move(ActualVersion);
|
2020-02-04 04:14:49 +08:00
|
|
|
Inputs.ForceRebuild = ForceRebuild;
|
2019-01-28 22:01:55 +08:00
|
|
|
Inputs.Opts = std::move(Opts);
|
|
|
|
Inputs.Index = Index;
|
2020-11-26 02:35:34 +08:00
|
|
|
Inputs.ClangTidyProvider = ClangTidyProvider;
|
2021-03-12 21:23:45 +08:00
|
|
|
Inputs.FeatureModules = FeatureModules;
|
2021-02-16 16:16:10 +08:00
|
|
|
bool NewFile = WorkScheduler->update(File, Inputs, WantDiags);
|
2019-07-12 18:18:42 +08:00
|
|
|
// If we loaded Foo.h, we want to make sure Foo.cpp is indexed.
|
|
|
|
if (NewFile && BackgroundIdx)
|
|
|
|
BackgroundIdx->boostRelated(File);
|
2017-05-16 17:38:59 +08:00
|
|
|
}
|
|
|
|
|
2021-03-02 07:16:33 +08:00
|
|
|
void ClangdServer::reparseOpenFilesIfNeeded(
|
|
|
|
llvm::function_ref<bool(llvm::StringRef File)> Filter) {
|
|
|
|
// Reparse only opened files that were modified.
|
|
|
|
for (const Path &FilePath : DraftMgr.getActiveFiles())
|
|
|
|
if (Filter(FilePath))
|
|
|
|
if (auto Draft = DraftMgr.getDraft(FilePath)) // else disappeared in race?
|
2021-03-09 22:35:20 +08:00
|
|
|
addDocument(FilePath, *Draft->Contents, Draft->Version,
|
2021-03-02 07:16:33 +08:00
|
|
|
WantDiagnostics::Auto);
|
|
|
|
}
|
|
|
|
|
2021-03-09 22:35:20 +08:00
|
|
|
std::shared_ptr<const std::string> ClangdServer::getDraft(PathRef File) const {
|
2021-03-02 07:16:33 +08:00
|
|
|
auto Draft = DraftMgr.getDraft(File);
|
|
|
|
if (!Draft)
|
2021-03-09 22:35:20 +08:00
|
|
|
return nullptr;
|
2021-03-02 07:16:33 +08:00
|
|
|
return std::move(Draft->Contents);
|
|
|
|
}
|
|
|
|
|
2021-01-21 05:34:24 +08:00
|
|
|
std::function<Context(PathRef)>
|
|
|
|
ClangdServer::createConfiguredContextProvider(const config::Provider *Provider,
|
|
|
|
Callbacks *Publish) {
|
|
|
|
if (!Provider)
|
|
|
|
return [](llvm::StringRef) { return Context::current().clone(); };
|
|
|
|
|
|
|
|
struct Impl {
|
|
|
|
const config::Provider *Provider;
|
|
|
|
ClangdServer::Callbacks *Publish;
|
|
|
|
std::mutex PublishMu;
|
|
|
|
|
|
|
|
Impl(const config::Provider *Provider, ClangdServer::Callbacks *Publish)
|
|
|
|
: Provider(Provider), Publish(Publish) {}
|
|
|
|
|
|
|
|
Context operator()(llvm::StringRef File) {
|
|
|
|
config::Params Params;
|
|
|
|
// Don't reread config files excessively often.
|
|
|
|
// FIXME: when we see a config file change event, use the event timestamp?
|
|
|
|
Params.FreshTime =
|
|
|
|
std::chrono::steady_clock::now() - std::chrono::seconds(5);
|
|
|
|
llvm::SmallString<256> PosixPath;
|
|
|
|
if (!File.empty()) {
|
|
|
|
assert(llvm::sys::path::is_absolute(File));
|
|
|
|
llvm::sys::path::native(File, PosixPath, llvm::sys::path::Style::posix);
|
|
|
|
Params.Path = PosixPath.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::StringMap<std::vector<Diag>> ReportableDiagnostics;
|
|
|
|
Config C = Provider->getConfig(Params, [&](const llvm::SMDiagnostic &D) {
|
|
|
|
// Create the map entry even for note diagnostics we don't report.
|
|
|
|
// This means that when the file is parsed with no warnings, we
|
|
|
|
// publish an empty set of diagnostics, clearing any the client has.
|
|
|
|
handleDiagnostic(D, !Publish || D.getFilename().empty()
|
|
|
|
? nullptr
|
|
|
|
: &ReportableDiagnostics[D.getFilename()]);
|
|
|
|
});
|
|
|
|
// Blindly publish diagnostics for the (unopened) parsed config files.
|
|
|
|
// We must avoid reporting diagnostics for *the same file* concurrently.
|
|
|
|
// Source diags are published elsewhere, but those are different files.
|
|
|
|
if (!ReportableDiagnostics.empty()) {
|
|
|
|
std::lock_guard<std::mutex> Lock(PublishMu);
|
|
|
|
for (auto &Entry : ReportableDiagnostics)
|
|
|
|
Publish->onDiagnosticsReady(Entry.first(), /*Version=*/"",
|
|
|
|
std::move(Entry.second));
|
|
|
|
}
|
|
|
|
return Context::current().derive(Config::Key, std::move(C));
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleDiagnostic(const llvm::SMDiagnostic &D,
|
|
|
|
std::vector<Diag> *ClientDiagnostics) {
|
|
|
|
switch (D.getKind()) {
|
|
|
|
case llvm::SourceMgr::DK_Error:
|
|
|
|
elog("config error at {0}:{1}:{2}: {3}", D.getFilename(), D.getLineNo(),
|
|
|
|
D.getColumnNo(), D.getMessage());
|
|
|
|
break;
|
|
|
|
case llvm::SourceMgr::DK_Warning:
|
|
|
|
log("config warning at {0}:{1}:{2}: {3}", D.getFilename(),
|
|
|
|
D.getLineNo(), D.getColumnNo(), D.getMessage());
|
|
|
|
break;
|
|
|
|
case llvm::SourceMgr::DK_Note:
|
|
|
|
case llvm::SourceMgr::DK_Remark:
|
|
|
|
vlog("config note at {0}:{1}:{2}: {3}", D.getFilename(), D.getLineNo(),
|
|
|
|
D.getColumnNo(), D.getMessage());
|
|
|
|
ClientDiagnostics = nullptr; // Don't emit notes as LSP diagnostics.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (ClientDiagnostics)
|
|
|
|
ClientDiagnostics->push_back(toDiag(D, Diag::ClangdConfig));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Copyable wrapper.
|
|
|
|
return [I(std::make_shared<Impl>(Provider, Publish))](llvm::StringRef Path) {
|
|
|
|
return (*I)(Path);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-03-02 07:16:33 +08:00
|
|
|
void ClangdServer::removeDocument(PathRef File) {
|
|
|
|
DraftMgr.removeDraft(File);
|
|
|
|
WorkScheduler->remove(File);
|
|
|
|
}
|
2017-05-16 17:38:59 +08:00
|
|
|
|
2018-09-13 20:58:36 +08:00
|
|
|
void ClangdServer::codeComplete(PathRef File, Position Pos,
|
|
|
|
const clangd::CodeCompleteOptions &Opts,
|
|
|
|
Callback<CodeCompleteResult> CB) {
|
2017-12-05 18:42:57 +08:00
|
|
|
// Copy completion options for passing them to async task handler.
|
|
|
|
auto CodeCompleteOpts = Opts;
|
2018-01-15 20:33:00 +08:00
|
|
|
if (!CodeCompleteOpts.Index) // Respect overridden index.
|
|
|
|
CodeCompleteOpts.Index = Index;
|
2018-01-09 22:39:27 +08:00
|
|
|
|
2020-06-05 00:26:52 +08:00
|
|
|
auto Task = [Pos, CodeCompleteOpts, File = File.str(), CB = std::move(CB),
|
2019-08-15 22:16:06 +08:00
|
|
|
this](llvm::Expected<InputsAndPreamble> IP) mutable {
|
2018-03-16 22:30:42 +08:00
|
|
|
if (!IP)
|
|
|
|
return CB(IP.takeError());
|
2020-04-12 00:19:50 +08:00
|
|
|
if (auto Reason = isCancelled())
|
|
|
|
return CB(llvm::make_error<CancelledError>(Reason));
|
2018-03-16 22:30:42 +08:00
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Optional<SpeculativeFuzzyFind> SpecFuzzyFind;
|
2019-04-11 17:36:36 +08:00
|
|
|
if (!IP->Preamble) {
|
|
|
|
// No speculation in Fallback mode, as it's supposed to be much faster
|
|
|
|
// without compiling.
|
|
|
|
vlog("Build for file {0} is not ready. Enter fallback mode.", File);
|
2021-01-15 00:19:39 +08:00
|
|
|
} else if (CodeCompleteOpts.Index) {
|
|
|
|
SpecFuzzyFind.emplace();
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> Lock(CachedCompletionFuzzyFindRequestMutex);
|
|
|
|
SpecFuzzyFind->CachedReq = CachedCompletionFuzzyFindRequestByFile[File];
|
[clangd] Speculative code completion index request before Sema is run.
Summary:
For index-based code completion, send an asynchronous speculative index
request, based on the index request for the last code completion on the same
file and the filter text typed before the cursor, before sema code completion
is invoked. This can reduce the code completion latency (by roughly latency of
sema code completion) if the speculative request is the same as the one
generated for the ongoing code completion from sema. As a sequence of code
completions often have the same scopes and proximity paths etc, this should be
effective for a number of code completions.
Trace with speculative index request:{F6997544}
Reviewers: hokein, ilya-biryukov
Reviewed By: ilya-biryukov
Subscribers: javed.absar, jfb, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D50962
llvm-svn: 340604
2018-08-24 19:23:56 +08:00
|
|
|
}
|
|
|
|
}
|
2022-01-17 18:55:35 +08:00
|
|
|
ParseInputs ParseInput{IP->Command, &getHeaderFS(), IP->Contents.str()};
|
2022-01-17 17:35:29 +08:00
|
|
|
// FIXME: Add traling new line if there is none at eof, workaround a crash,
|
|
|
|
// see https://github.com/clangd/clangd/issues/332
|
|
|
|
if (!IP->Contents.endswith("\n"))
|
|
|
|
ParseInput.Contents.append("\n");
|
2020-06-03 16:34:05 +08:00
|
|
|
ParseInput.Index = Index;
|
|
|
|
|
2021-01-10 23:32:00 +08:00
|
|
|
CodeCompleteOpts.MainFileSignals = IP->Signals;
|
2021-03-05 20:57:04 +08:00
|
|
|
CodeCompleteOpts.AllScopes = Config::current().Completion.AllScopes;
|
2018-01-31 16:51:16 +08:00
|
|
|
// FIXME(ibiryukov): even if Preamble is non-null, we may want to check
|
|
|
|
// both the old and the new version in case only one of them matches.
|
2018-06-29 22:47:57 +08:00
|
|
|
CodeCompleteResult Result = clangd::codeComplete(
|
2020-06-03 16:34:05 +08:00
|
|
|
File, Pos, IP->Preamble, ParseInput, CodeCompleteOpts,
|
|
|
|
SpecFuzzyFind ? SpecFuzzyFind.getPointer() : nullptr);
|
[clangd] Speculative code completion index request before Sema is run.
Summary:
For index-based code completion, send an asynchronous speculative index
request, based on the index request for the last code completion on the same
file and the filter text typed before the cursor, before sema code completion
is invoked. This can reduce the code completion latency (by roughly latency of
sema code completion) if the speculative request is the same as the one
generated for the ongoing code completion from sema. As a sequence of code
completions often have the same scopes and proximity paths etc, this should be
effective for a number of code completions.
Trace with speculative index request:{F6997544}
Reviewers: hokein, ilya-biryukov
Reviewed By: ilya-biryukov
Subscribers: javed.absar, jfb, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D50962
llvm-svn: 340604
2018-08-24 19:23:56 +08:00
|
|
|
{
|
|
|
|
clang::clangd::trace::Span Tracer("Completion results callback");
|
|
|
|
CB(std::move(Result));
|
|
|
|
}
|
|
|
|
if (SpecFuzzyFind && SpecFuzzyFind->NewReq.hasValue()) {
|
|
|
|
std::lock_guard<std::mutex> Lock(CachedCompletionFuzzyFindRequestMutex);
|
|
|
|
CachedCompletionFuzzyFindRequestByFile[File] =
|
|
|
|
SpecFuzzyFind->NewReq.getValue();
|
|
|
|
}
|
|
|
|
// SpecFuzzyFind is only destroyed after speculative fuzzy find finishes.
|
|
|
|
// We don't want `codeComplete` to wait for the async call if it doesn't use
|
|
|
|
// the result (e.g. non-index completion, speculation fails), so that `CB`
|
|
|
|
// is called as soon as results are available.
|
2018-01-31 16:51:16 +08:00
|
|
|
};
|
|
|
|
|
2018-08-30 23:07:34 +08:00
|
|
|
// We use a potentially-stale preamble because latency is critical here.
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithPreamble(
|
2019-05-21 21:40:31 +08:00
|
|
|
"CodeComplete", File,
|
|
|
|
(Opts.RunParser == CodeCompleteOptions::AlwaysParse)
|
|
|
|
? TUScheduler::Stale
|
|
|
|
: TUScheduler::StaleOrAbsent,
|
2019-08-15 22:16:06 +08:00
|
|
|
std::move(Task));
|
2017-05-16 17:38:59 +08:00
|
|
|
}
|
2017-05-23 21:42:59 +08:00
|
|
|
|
2018-03-13 07:22:35 +08:00
|
|
|
void ClangdServer::signatureHelp(PathRef File, Position Pos,
|
2021-12-09 16:36:04 +08:00
|
|
|
MarkupKind DocumentationFormat,
|
2018-03-13 07:22:35 +08:00
|
|
|
Callback<SignatureHelp> CB) {
|
2017-10-06 19:54:17 +08:00
|
|
|
|
2020-06-05 00:26:52 +08:00
|
|
|
auto Action = [Pos, File = File.str(), CB = std::move(CB),
|
2021-12-09 16:36:04 +08:00
|
|
|
DocumentationFormat,
|
2019-08-15 22:16:06 +08:00
|
|
|
this](llvm::Expected<InputsAndPreamble> IP) mutable {
|
2018-01-31 16:51:16 +08:00
|
|
|
if (!IP)
|
2018-03-13 07:22:35 +08:00
|
|
|
return CB(IP.takeError());
|
2018-02-15 21:15:47 +08:00
|
|
|
|
2020-04-01 17:31:53 +08:00
|
|
|
const auto *PreambleData = IP->Preamble;
|
|
|
|
if (!PreambleData)
|
[clangd] Add error() function for creating formatv-style llvm::Errors. NFC
Summary:
This is considerably terser than the makeStringError and friends, and
avoids verbosity cliffs that discourage adding log information.
It follows the syntax used in log/elog/vlog/dlog that have been successful.
The main caveats are:
- it's strictly out-of-place in logger.h, though kind of fits thematically and
in implementation
- it claims the "error" identifier, which seems a bit too opinionated
to put higher up in llvm
I've updated some users of StringError mostly at random - there are lots
more mechanical changes but I'd like to get this reviewed before making
them all.
Reviewers: kbobyrev, hokein
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83419
2020-07-09 03:49:38 +08:00
|
|
|
return CB(error("Failed to parse includes"));
|
2020-04-01 17:31:53 +08:00
|
|
|
|
2022-01-17 18:55:35 +08:00
|
|
|
ParseInputs ParseInput{IP->Command, &getHeaderFS(), IP->Contents.str()};
|
2022-01-17 17:35:29 +08:00
|
|
|
// FIXME: Add traling new line if there is none at eof, workaround a crash,
|
|
|
|
// see https://github.com/clangd/clangd/issues/332
|
|
|
|
if (!IP->Contents.endswith("\n"))
|
|
|
|
ParseInput.Contents.append("\n");
|
2020-06-03 16:34:05 +08:00
|
|
|
ParseInput.Index = Index;
|
2021-12-09 16:36:04 +08:00
|
|
|
CB(clangd::signatureHelp(File, Pos, *PreambleData, ParseInput,
|
|
|
|
DocumentationFormat));
|
2018-01-31 16:51:16 +08:00
|
|
|
};
|
2018-02-15 21:15:47 +08:00
|
|
|
|
2020-04-02 16:53:23 +08:00
|
|
|
// Unlike code completion, we wait for a preamble here.
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithPreamble("SignatureHelp", File, TUScheduler::Stale,
|
|
|
|
std::move(Action));
|
2017-10-06 19:54:17 +08:00
|
|
|
}
|
|
|
|
|
2021-03-02 07:16:33 +08:00
|
|
|
void ClangdServer::formatFile(PathRef File, llvm::Optional<Range> Rng,
|
[clangd] Run formatting operations asynchronously.
Summary:
They don't need ASTs or anything, so they should still run immediately.
These were sync for historical reasons (they predate clangd having a pervasive
threading model). This worked ok as they were "cheap".
Aside for consistency, there are a couple of reasons to make them async:
- they do IO (finding .clang-format) so aren't trivially cheap
- having TUScheduler involved in running these tasks means we can use it as
an injection point for configuration.
(TUScheduler::run will need to learn about which file is being operated on,
but that's an easy change).
- adding the config system adds more potential IO, too
Reviewers: kbobyrev
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D82642
2020-06-26 18:57:29 +08:00
|
|
|
Callback<tooling::Replacements> CB) {
|
2021-03-02 07:16:33 +08:00
|
|
|
auto Code = getDraft(File);
|
|
|
|
if (!Code)
|
|
|
|
return CB(llvm::make_error<LSPError>("trying to format non-added document",
|
|
|
|
ErrorCode::InvalidParams));
|
|
|
|
tooling::Range RequestedRange;
|
|
|
|
if (Rng) {
|
|
|
|
llvm::Expected<size_t> Begin = positionToOffset(*Code, Rng->start);
|
|
|
|
if (!Begin)
|
|
|
|
return CB(Begin.takeError());
|
|
|
|
llvm::Expected<size_t> End = positionToOffset(*Code, Rng->end);
|
|
|
|
if (!End)
|
|
|
|
return CB(End.takeError());
|
|
|
|
RequestedRange = tooling::Range(*Begin, *End - *Begin);
|
|
|
|
} else {
|
|
|
|
RequestedRange = tooling::Range(0, Code->size());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call clang-format.
|
|
|
|
auto Action = [File = File.str(), Code = std::move(*Code),
|
|
|
|
Ranges = std::vector<tooling::Range>{RequestedRange},
|
|
|
|
CB = std::move(CB), this]() mutable {
|
|
|
|
format::FormatStyle Style = getFormatStyleForFile(File, Code, TFS);
|
|
|
|
tooling::Replacements IncludeReplaces =
|
|
|
|
format::sortIncludes(Style, Code, Ranges, File);
|
|
|
|
auto Changed = tooling::applyAllReplacements(Code, IncludeReplaces);
|
|
|
|
if (!Changed)
|
|
|
|
return CB(Changed.takeError());
|
|
|
|
|
|
|
|
CB(IncludeReplaces.merge(format::reformat(
|
|
|
|
Style, *Changed,
|
|
|
|
tooling::calculateRangesAfterReplacements(IncludeReplaces, Ranges),
|
|
|
|
File)));
|
|
|
|
};
|
|
|
|
WorkScheduler->runQuick("Format", File, std::move(Action));
|
2017-05-16 22:40:30 +08:00
|
|
|
}
|
|
|
|
|
2021-03-02 07:16:33 +08:00
|
|
|
void ClangdServer::formatOnType(PathRef File, Position Pos,
|
|
|
|
StringRef TriggerText,
|
[clangd] Run formatting operations asynchronously.
Summary:
They don't need ASTs or anything, so they should still run immediately.
These were sync for historical reasons (they predate clangd having a pervasive
threading model). This worked ok as they were "cheap".
Aside for consistency, there are a couple of reasons to make them async:
- they do IO (finding .clang-format) so aren't trivially cheap
- having TUScheduler involved in running these tasks means we can use it as
an injection point for configuration.
(TUScheduler::run will need to learn about which file is being operated on,
but that's an easy change).
- adding the config system adds more potential IO, too
Reviewers: kbobyrev
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D82642
2020-06-26 18:57:29 +08:00
|
|
|
Callback<std::vector<TextEdit>> CB) {
|
2021-03-02 07:16:33 +08:00
|
|
|
auto Code = getDraft(File);
|
|
|
|
if (!Code)
|
|
|
|
return CB(llvm::make_error<LSPError>("trying to format non-added document",
|
|
|
|
ErrorCode::InvalidParams));
|
|
|
|
llvm::Expected<size_t> CursorPos = positionToOffset(*Code, Pos);
|
Make positionToOffset return llvm::Expected<size_t>
Summary:
To implement incremental document syncing, we want to verify that the
ranges provided by the front-end are valid. Currently, positionToOffset
deals with invalid Positions by returning 0 or Code.size(), which are
two valid offsets. Instead, return an llvm:Expected<size_t> with an
error if the position is invalid.
According to the LSP, if the character value exceeds the number of
characters of the given line, it should default back to the end of the
line. It makes sense in some contexts to have this behavior, and does
not in other contexts. The AllowColumnsBeyondLineLength parameter
allows to decide what to do in that case, default back to the end of the
line, or return an error.
Reviewers: ilya-biryukov
Subscribers: klimek, ilya-biryukov, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D44673
llvm-svn: 328100
2018-03-21 22:36:46 +08:00
|
|
|
if (!CursorPos)
|
[clangd] Run formatting operations asynchronously.
Summary:
They don't need ASTs or anything, so they should still run immediately.
These were sync for historical reasons (they predate clangd having a pervasive
threading model). This worked ok as they were "cheap".
Aside for consistency, there are a couple of reasons to make them async:
- they do IO (finding .clang-format) so aren't trivially cheap
- having TUScheduler involved in running these tasks means we can use it as
an injection point for configuration.
(TUScheduler::run will need to learn about which file is being operated on,
but that's an easy change).
- adding the config system adds more potential IO, too
Reviewers: kbobyrev
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D82642
2020-06-26 18:57:29 +08:00
|
|
|
return CB(CursorPos.takeError());
|
2021-03-02 07:16:33 +08:00
|
|
|
auto Action = [File = File.str(), Code = std::move(*Code),
|
[clangd] Run formatting operations asynchronously.
Summary:
They don't need ASTs or anything, so they should still run immediately.
These were sync for historical reasons (they predate clangd having a pervasive
threading model). This worked ok as they were "cheap".
Aside for consistency, there are a couple of reasons to make them async:
- they do IO (finding .clang-format) so aren't trivially cheap
- having TUScheduler involved in running these tasks means we can use it as
an injection point for configuration.
(TUScheduler::run will need to learn about which file is being operated on,
but that's an easy change).
- adding the config system adds more potential IO, too
Reviewers: kbobyrev
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D82642
2020-06-26 18:57:29 +08:00
|
|
|
TriggerText = TriggerText.str(), CursorPos = *CursorPos,
|
|
|
|
CB = std::move(CB), this]() mutable {
|
|
|
|
auto Style = format::getStyle(format::DefaultFormatStyle, File,
|
|
|
|
format::DefaultFallbackStyle, Code,
|
|
|
|
TFS.view(/*CWD=*/llvm::None).get());
|
|
|
|
if (!Style)
|
|
|
|
return CB(Style.takeError());
|
|
|
|
|
|
|
|
std::vector<TextEdit> Result;
|
|
|
|
for (const tooling::Replacement &R :
|
|
|
|
formatIncremental(Code, CursorPos, TriggerText, *Style))
|
|
|
|
Result.push_back(replacementToEdit(Code, R));
|
|
|
|
return CB(Result);
|
|
|
|
};
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runQuick("FormatOnType", File, std::move(Action));
|
2017-05-16 22:40:30 +08:00
|
|
|
}
|
2017-05-16 17:38:59 +08:00
|
|
|
|
2019-07-24 15:49:23 +08:00
|
|
|
void ClangdServer::prepareRename(PathRef File, Position Pos,
|
2020-10-08 03:16:45 +08:00
|
|
|
llvm::Optional<std::string> NewName,
|
2020-02-19 22:37:36 +08:00
|
|
|
const RenameOptions &RenameOpts,
|
2020-10-02 22:01:25 +08:00
|
|
|
Callback<RenameResult> CB) {
|
2020-10-08 03:16:45 +08:00
|
|
|
auto Action = [Pos, File = File.str(), CB = std::move(CB),
|
2021-02-11 22:57:54 +08:00
|
|
|
NewName = std::move(NewName),
|
|
|
|
RenameOpts](llvm::Expected<InputsAndAST> InpAST) mutable {
|
2019-07-24 15:49:23 +08:00
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
2021-02-11 22:57:54 +08:00
|
|
|
// prepareRename is latency-sensitive: we don't query the index, as we
|
|
|
|
// only need main-file references
|
2021-03-10 21:41:27 +08:00
|
|
|
auto Results =
|
2021-03-22 18:18:18 +08:00
|
|
|
clangd::rename({Pos, NewName.getValueOr("__clangd_rename_placeholder"),
|
2021-03-10 21:41:27 +08:00
|
|
|
InpAST->AST, File, /*FS=*/nullptr,
|
|
|
|
/*Index=*/nullptr, RenameOpts});
|
2020-10-02 22:01:25 +08:00
|
|
|
if (!Results) {
|
2019-07-24 15:49:23 +08:00
|
|
|
// LSP says to return null on failure, but that will result in a generic
|
|
|
|
// failure message. If we send an LSP error response, clients can surface
|
|
|
|
// the message to users (VSCode does).
|
2020-10-02 22:01:25 +08:00
|
|
|
return CB(Results.takeError());
|
2019-07-24 15:49:23 +08:00
|
|
|
}
|
2020-10-02 22:01:25 +08:00
|
|
|
return CB(*Results);
|
2019-07-24 15:49:23 +08:00
|
|
|
};
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithAST("PrepareRename", File, std::move(Action));
|
2019-07-24 15:49:23 +08:00
|
|
|
}
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
|
2020-10-02 22:01:25 +08:00
|
|
|
const RenameOptions &Opts,
|
|
|
|
Callback<RenameResult> CB) {
|
2020-02-19 22:37:36 +08:00
|
|
|
auto Action = [File = File.str(), NewName = NewName.str(), Pos, Opts,
|
2021-03-10 21:41:27 +08:00
|
|
|
CB = std::move(CB),
|
2019-08-15 22:16:06 +08:00
|
|
|
this](llvm::Expected<InputsAndAST> InpAST) mutable {
|
2020-04-17 05:12:09 +08:00
|
|
|
// Tracks number of files edited per invocation.
|
|
|
|
static constexpr trace::Metric RenameFiles("rename_files",
|
|
|
|
trace::Metric::Distribution);
|
2018-01-31 16:51:16 +08:00
|
|
|
if (!InpAST)
|
2018-03-13 07:22:35 +08:00
|
|
|
return CB(InpAST.takeError());
|
2021-03-10 21:41:27 +08:00
|
|
|
auto R = clangd::rename({Pos, NewName, InpAST->AST, File,
|
|
|
|
DirtyFS->view(llvm::None), Index, Opts});
|
2020-10-02 22:01:25 +08:00
|
|
|
if (!R)
|
|
|
|
return CB(R.takeError());
|
2019-06-20 01:25:24 +08:00
|
|
|
|
2020-02-19 22:37:36 +08:00
|
|
|
if (Opts.WantFormat) {
|
2020-06-16 18:16:24 +08:00
|
|
|
auto Style = getFormatStyleForFile(File, InpAST->Inputs.Contents,
|
2020-06-18 00:09:54 +08:00
|
|
|
*InpAST->Inputs.TFS);
|
2019-10-23 20:40:20 +08:00
|
|
|
llvm::Error Err = llvm::Error::success();
|
2020-10-02 22:01:25 +08:00
|
|
|
for (auto &E : R->GlobalChanges)
|
2019-10-23 20:40:20 +08:00
|
|
|
Err =
|
|
|
|
llvm::joinErrors(reformatEdit(E.getValue(), Style), std::move(Err));
|
2019-06-20 01:25:24 +08:00
|
|
|
|
2019-10-23 20:40:20 +08:00
|
|
|
if (Err)
|
|
|
|
return CB(std::move(Err));
|
|
|
|
}
|
2020-10-02 22:01:25 +08:00
|
|
|
RenameFiles.record(R->GlobalChanges.size());
|
|
|
|
return CB(*R);
|
2018-01-31 16:51:16 +08:00
|
|
|
};
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithAST("Rename", File, std::move(Action));
|
2017-11-09 19:30:04 +08:00
|
|
|
}
|
|
|
|
|
2020-02-24 03:03:00 +08:00
|
|
|
// May generate several candidate selections, due to SelectionTree ambiguity.
|
|
|
|
// vector of pointers because GCC doesn't like non-copyable Selection.
|
|
|
|
static llvm::Expected<std::vector<std::unique_ptr<Tweak::Selection>>>
|
2021-04-21 00:13:44 +08:00
|
|
|
tweakSelection(const Range &Sel, const InputsAndAST &AST,
|
|
|
|
llvm::vfs::FileSystem *FS) {
|
2019-02-01 23:09:47 +08:00
|
|
|
auto Begin = positionToOffset(AST.Inputs.Contents, Sel.start);
|
|
|
|
if (!Begin)
|
|
|
|
return Begin.takeError();
|
|
|
|
auto End = positionToOffset(AST.Inputs.Contents, Sel.end);
|
|
|
|
if (!End)
|
|
|
|
return End.takeError();
|
2020-02-24 03:03:00 +08:00
|
|
|
std::vector<std::unique_ptr<Tweak::Selection>> Result;
|
|
|
|
SelectionTree::createEach(
|
|
|
|
AST.AST.getASTContext(), AST.AST.getTokens(), *Begin, *End,
|
|
|
|
[&](SelectionTree T) {
|
|
|
|
Result.push_back(std::make_unique<Tweak::Selection>(
|
2021-04-21 00:13:44 +08:00
|
|
|
AST.Inputs.Index, AST.AST, *Begin, *End, std::move(T), FS));
|
2020-02-24 03:03:00 +08:00
|
|
|
return false;
|
|
|
|
});
|
|
|
|
assert(!Result.empty() && "Expected at least one SelectionTree");
|
2020-02-24 04:11:58 +08:00
|
|
|
return std::move(Result);
|
2019-02-01 23:09:47 +08:00
|
|
|
}
|
|
|
|
|
2020-10-02 17:34:40 +08:00
|
|
|
void ClangdServer::enumerateTweaks(
|
|
|
|
PathRef File, Range Sel, llvm::unique_function<bool(const Tweak &)> Filter,
|
|
|
|
Callback<std::vector<TweakRef>> CB) {
|
2020-04-17 05:12:09 +08:00
|
|
|
// Tracks number of times a tweak has been offered.
|
|
|
|
static constexpr trace::Metric TweakAvailable(
|
|
|
|
"tweak_available", trace::Metric::Counter, "tweak_id");
|
2021-04-30 20:27:23 +08:00
|
|
|
auto Action = [Sel, CB = std::move(CB), Filter = std::move(Filter),
|
2021-03-12 19:27:19 +08:00
|
|
|
FeatureModules(this->FeatureModules)](
|
|
|
|
Expected<InputsAndAST> InpAST) 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 (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
2021-04-21 00:13:44 +08:00
|
|
|
auto Selections = tweakSelection(Sel, *InpAST, /*FS=*/nullptr);
|
2020-02-24 03:03:00 +08:00
|
|
|
if (!Selections)
|
|
|
|
return CB(Selections.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<TweakRef> Res;
|
2020-02-24 03:03:00 +08:00
|
|
|
// Don't allow a tweak to fire more than once across ambiguous selections.
|
|
|
|
llvm::DenseSet<llvm::StringRef> PreparedTweaks;
|
2020-10-02 17:34:40 +08:00
|
|
|
auto DeduplicatingFilter = [&](const Tweak &T) {
|
|
|
|
return Filter(T) && !PreparedTweaks.count(T.id());
|
2020-02-24 03:03:00 +08:00
|
|
|
};
|
|
|
|
for (const auto &Sel : *Selections) {
|
2021-03-12 19:27:19 +08:00
|
|
|
for (auto &T : prepareTweaks(*Sel, DeduplicatingFilter, FeatureModules)) {
|
2020-09-29 00:12:37 +08:00
|
|
|
Res.push_back({T->id(), T->title(), T->kind()});
|
2020-02-24 03:03:00 +08:00
|
|
|
PreparedTweaks.insert(T->id());
|
2020-04-17 05:12:09 +08:00
|
|
|
TweakAvailable.record(1, T->id());
|
2020-02-24 03:03:00 +08:00
|
|
|
}
|
|
|
|
}
|
2019-07-12 16:50:20 +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
|
|
|
CB(std::move(Res));
|
|
|
|
};
|
|
|
|
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithAST("EnumerateTweaks", File, std::move(Action),
|
2021-03-11 20:43:59 +08:00
|
|
|
Transient);
|
[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
|
|
|
}
|
|
|
|
|
2019-02-01 13:41:50 +08:00
|
|
|
void ClangdServer::applyTweak(PathRef File, Range Sel, StringRef TweakID,
|
2019-06-19 15:29:10 +08:00
|
|
|
Callback<Tweak::Effect> CB) {
|
2020-09-11 17:40:54 +08:00
|
|
|
// Tracks number of times a tweak has been attempted.
|
2020-04-17 05:12:09 +08:00
|
|
|
static constexpr trace::Metric TweakAttempt(
|
|
|
|
"tweak_attempt", trace::Metric::Counter, "tweak_id");
|
2020-09-11 17:40:54 +08:00
|
|
|
// Tracks number of times a tweak has failed to produce edits.
|
|
|
|
static constexpr trace::Metric TweakFailed(
|
|
|
|
"tweak_failed", trace::Metric::Counter, "tweak_id");
|
2020-04-17 05:12:09 +08:00
|
|
|
TweakAttempt.record(1, TweakID);
|
2020-06-16 18:16:24 +08:00
|
|
|
auto Action = [File = File.str(), Sel, TweakID = TweakID.str(),
|
|
|
|
CB = std::move(CB),
|
|
|
|
this](Expected<InputsAndAST> InpAST) mutable {
|
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
2021-04-21 00:13:44 +08:00
|
|
|
auto FS = DirtyFS->view(llvm::None);
|
|
|
|
auto Selections = tweakSelection(Sel, *InpAST, FS.get());
|
2020-06-16 18:16:24 +08:00
|
|
|
if (!Selections)
|
|
|
|
return CB(Selections.takeError());
|
|
|
|
llvm::Optional<llvm::Expected<Tweak::Effect>> Effect;
|
|
|
|
// Try each selection, take the first one that prepare()s.
|
|
|
|
// If they all fail, Effect will hold get the last error.
|
|
|
|
for (const auto &Selection : *Selections) {
|
2021-03-12 19:27:19 +08:00
|
|
|
auto T = prepareTweak(TweakID, *Selection, FeatureModules);
|
2020-06-16 18:16:24 +08:00
|
|
|
if (T) {
|
|
|
|
Effect = (*T)->apply(*Selection);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Effect = T.takeError();
|
|
|
|
}
|
|
|
|
assert(Effect.hasValue() && "Expected at least one selection");
|
2021-06-29 00:11:22 +08:00
|
|
|
if (*Effect && (*Effect)->FormatEdits) {
|
|
|
|
// Format tweaks that require it centrally here.
|
2020-06-16 18:16:24 +08:00
|
|
|
for (auto &It : (*Effect)->ApplyEdits) {
|
|
|
|
Edit &E = It.second;
|
|
|
|
format::FormatStyle Style =
|
2020-06-18 00:09:54 +08:00
|
|
|
getFormatStyleForFile(File, E.InitialCode, TFS);
|
2020-06-16 18:16:24 +08:00
|
|
|
if (llvm::Error Err = reformatEdit(E, Style))
|
|
|
|
elog("Failed to format {0}: {1}", It.first(), std::move(Err));
|
|
|
|
}
|
2020-09-11 17:40:54 +08:00
|
|
|
} else {
|
|
|
|
TweakFailed.record(1, TweakID);
|
2020-06-16 18:16:24 +08:00
|
|
|
}
|
|
|
|
return CB(std::move(*Effect));
|
|
|
|
};
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithAST("ApplyTweak", File, std::move(Action));
|
[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
|
|
|
}
|
|
|
|
|
[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 ClangdServer::locateSymbolAt(PathRef File, Position Pos,
|
|
|
|
Callback<std::vector<LocatedSymbol>> CB) {
|
2019-08-15 22:16:06 +08:00
|
|
|
auto Action = [Pos, CB = std::move(CB),
|
|
|
|
this](llvm::Expected<InputsAndAST> InpAST) mutable {
|
2018-01-31 16:51:16 +08:00
|
|
|
if (!InpAST)
|
2018-03-13 07:22:35 +08:00
|
|
|
return CB(InpAST.takeError());
|
[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
|
|
|
CB(clangd::locateSymbolAt(InpAST->AST, Pos, Index));
|
2018-01-31 16:51:16 +08:00
|
|
|
};
|
2018-02-15 21:15:47 +08:00
|
|
|
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithAST("Definitions", File, std::move(Action));
|
2017-06-29 00:12:10 +08:00
|
|
|
}
|
2017-08-14 16:17:24 +08:00
|
|
|
|
2019-10-01 18:21:15 +08:00
|
|
|
void ClangdServer::switchSourceHeader(
|
|
|
|
PathRef Path, Callback<llvm::Optional<clangd::Path>> CB) {
|
2019-12-16 17:33:56 +08:00
|
|
|
// We want to return the result as fast as possible, strategy is:
|
2019-10-01 18:21:15 +08:00
|
|
|
// 1) use the file-only heuristic, it requires some IO but it is much
|
|
|
|
// faster than building AST, but it only works when .h/.cc files are in
|
|
|
|
// the same directory.
|
|
|
|
// 2) if 1) fails, we use the AST&Index approach, it is slower but supports
|
|
|
|
// different code layout.
|
2021-01-07 10:40:20 +08:00
|
|
|
if (auto CorrespondingFile =
|
|
|
|
getCorrespondingHeaderOrSource(Path, TFS.view(llvm::None)))
|
2019-10-01 18:21:15 +08:00
|
|
|
return CB(std::move(CorrespondingFile));
|
2019-10-07 19:37:25 +08:00
|
|
|
auto Action = [Path = Path.str(), CB = std::move(CB),
|
2019-10-01 18:21:15 +08:00
|
|
|
this](llvm::Expected<InputsAndAST> InpAST) mutable {
|
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
|
|
|
CB(getCorrespondingHeaderOrSource(Path, InpAST->AST, Index));
|
|
|
|
};
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithAST("SwitchHeaderSource", Path, std::move(Action));
|
2017-09-28 11:14:40 +08:00
|
|
|
}
|
|
|
|
|
2018-02-15 21:15:47 +08:00
|
|
|
void ClangdServer::findDocumentHighlights(
|
2018-03-13 07:22:35 +08:00
|
|
|
PathRef File, Position Pos, Callback<std::vector<DocumentHighlight>> CB) {
|
2019-08-15 22:16:06 +08:00
|
|
|
auto Action =
|
|
|
|
[Pos, CB = std::move(CB)](llvm::Expected<InputsAndAST> InpAST) mutable {
|
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
|
|
|
CB(clangd::findDocumentHighlights(InpAST->AST, Pos));
|
|
|
|
};
|
|
|
|
|
2021-03-11 20:43:59 +08:00
|
|
|
WorkScheduler->runWithAST("Highlights", File, std::move(Action), Transient);
|
[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
|
|
|
}
|
|
|
|
|
2018-06-04 18:37:16 +08:00
|
|
|
void ClangdServer::findHover(PathRef File, Position Pos,
|
2019-05-28 18:29:58 +08:00
|
|
|
Callback<llvm::Optional<HoverInfo>> CB) {
|
2019-08-15 22:16:06 +08:00
|
|
|
auto Action = [File = File.str(), Pos, CB = std::move(CB),
|
|
|
|
this](llvm::Expected<InputsAndAST> InpAST) mutable {
|
[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
|
|
|
if (!InpAST)
|
2018-03-13 07:22:35 +08:00
|
|
|
return CB(InpAST.takeError());
|
2020-06-16 18:16:24 +08:00
|
|
|
format::FormatStyle Style = getFormatStyleForFile(
|
2020-06-18 00:09:54 +08:00
|
|
|
File, InpAST->Inputs.Contents, *InpAST->Inputs.TFS);
|
2019-07-10 01:59:50 +08:00
|
|
|
CB(clangd::getHover(InpAST->AST, Pos, std::move(Style), Index));
|
[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
|
|
|
};
|
|
|
|
|
2021-03-11 20:43:59 +08:00
|
|
|
WorkScheduler->runWithAST("Hover", File, std::move(Action), Transient);
|
[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] 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 ClangdServer::typeHierarchy(PathRef File, Position Pos, int Resolve,
|
|
|
|
TypeHierarchyDirection Direction,
|
|
|
|
Callback<Optional<TypeHierarchyItem>> CB) {
|
2019-08-15 22:16:06 +08:00
|
|
|
auto Action = [File = File.str(), Pos, Resolve, Direction, CB = std::move(CB),
|
|
|
|
this](Expected<InputsAndAST> InpAST) mutable {
|
[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
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
[clangd] Type hierarchy subtypes
Summary:
This builds on the relations support added in D59407, D62459, D62471,
and D62839 to implement type hierarchy subtypes.
Reviewers: kadircet
Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, mgrang, arphaman,
jdoerfert, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D58880
llvm-svn: 363506
2019-06-16 10:31:37 +08:00
|
|
|
CB(clangd::getTypeHierarchy(InpAST->AST, Pos, Resolve, Direction, Index,
|
2019-08-15 22:16:06 +08:00
|
|
|
File));
|
[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
|
|
|
};
|
|
|
|
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithAST("TypeHierarchy", File, std::move(Action));
|
[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
|
|
|
}
|
|
|
|
|
2019-07-13 11:24:48 +08:00
|
|
|
void ClangdServer::resolveTypeHierarchy(
|
|
|
|
TypeHierarchyItem Item, int Resolve, TypeHierarchyDirection Direction,
|
|
|
|
Callback<llvm::Optional<TypeHierarchyItem>> CB) {
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->run(
|
2020-11-23 10:47:07 +08:00
|
|
|
"Resolve Type Hierarchy", "", [=, CB = std::move(CB)]() mutable {
|
|
|
|
clangd::resolveTypeHierarchy(Item, Resolve, Direction, Index);
|
|
|
|
CB(Item);
|
|
|
|
});
|
2019-07-13 11:24:48 +08:00
|
|
|
}
|
|
|
|
|
2020-11-16 10:36:46 +08:00
|
|
|
void ClangdServer::prepareCallHierarchy(
|
|
|
|
PathRef File, Position Pos, Callback<std::vector<CallHierarchyItem>> CB) {
|
|
|
|
auto Action = [File = File.str(), Pos,
|
|
|
|
CB = std::move(CB)](Expected<InputsAndAST> InpAST) mutable {
|
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
|
|
|
CB(clangd::prepareCallHierarchy(InpAST->AST, Pos, File));
|
|
|
|
};
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithAST("CallHierarchy", File, std::move(Action));
|
2020-11-16 10:36:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClangdServer::incomingCalls(
|
|
|
|
const CallHierarchyItem &Item,
|
|
|
|
Callback<std::vector<CallHierarchyIncomingCall>> CB) {
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->run("Incoming Calls", "",
|
|
|
|
[CB = std::move(CB), Item, this]() mutable {
|
|
|
|
CB(clangd::incomingCalls(Item, Index));
|
|
|
|
});
|
2020-11-16 10:36:46 +08:00
|
|
|
}
|
|
|
|
|
2022-01-06 05:40:50 +08:00
|
|
|
void ClangdServer::inlayHints(PathRef File, llvm::Optional<Range> RestrictRange,
|
2021-02-22 15:55:13 +08:00
|
|
|
Callback<std::vector<InlayHint>> CB) {
|
2022-01-06 05:40:50 +08:00
|
|
|
auto Action = [RestrictRange(std::move(RestrictRange)),
|
|
|
|
CB = std::move(CB)](Expected<InputsAndAST> InpAST) mutable {
|
2021-02-22 15:55:13 +08:00
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
2022-01-06 05:40:50 +08:00
|
|
|
CB(clangd::inlayHints(InpAST->AST, std::move(RestrictRange)));
|
2021-02-22 15:55:13 +08:00
|
|
|
};
|
2022-01-20 21:11:15 +08:00
|
|
|
WorkScheduler->runWithAST("InlayHints", File, std::move(Action), Transient);
|
2021-02-22 15:55:13 +08:00
|
|
|
}
|
|
|
|
|
2017-10-03 02:00:37 +08:00
|
|
|
void ClangdServer::onFileEvent(const DidChangeWatchedFilesParams &Params) {
|
|
|
|
// FIXME: Do nothing for now. This will be used for indexing and potentially
|
|
|
|
// invalidating other caches.
|
|
|
|
}
|
2018-01-25 22:32:21 +08:00
|
|
|
|
[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
|
|
|
void ClangdServer::workspaceSymbols(
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::StringRef Query, int Limit,
|
|
|
|
Callback<std::vector<SymbolInformation>> CB) {
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->run(
|
2020-07-03 05:09:25 +08:00
|
|
|
"getWorkspaceSymbols", /*Path=*/"",
|
2019-08-23 02:09:46 +08:00
|
|
|
[Query = Query.str(), Limit, CB = std::move(CB), this]() mutable {
|
|
|
|
CB(clangd::getWorkspaceSymbols(Query, Limit, Index,
|
2019-08-15 22:16:06 +08:00
|
|
|
WorkspaceRoot.getValueOr("")));
|
|
|
|
});
|
[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-01-07 23:45:19 +08:00
|
|
|
void ClangdServer::documentSymbols(llvm::StringRef File,
|
2018-11-23 23:21:19 +08:00
|
|
|
Callback<std::vector<DocumentSymbol>> CB) {
|
2019-08-15 22:16:06 +08:00
|
|
|
auto Action =
|
|
|
|
[CB = std::move(CB)](llvm::Expected<InputsAndAST> InpAST) mutable {
|
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
|
|
|
CB(clangd::getDocumentSymbols(InpAST->AST));
|
|
|
|
};
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithAST("DocumentSymbols", File, std::move(Action),
|
2021-03-11 20:43:59 +08:00
|
|
|
Transient);
|
2018-07-06 03:35:01 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Implement textDocument/foldingRange
Summary:
This patch introduces basic textDocument/foldingRange support. It relies on
textDocument/documentSymbols to collect all symbols and uses takes ranges
to create folds.
The next steps for textDocument/foldingRange support would be:
* Implementing FoldingRangeClientCapabilities and respecting respect client
preferences
* Specifying folding range kind
* Migrating from DocumentSymbol implementation to custom RecursiveASTVisitor flow that will allow more flexibility
* Supporting more folding range types: comments, PP conditional regions, includes and other code regions (e.g. public/private/protected sections of classes, control flow statement bodies)
Tested: (Neo)Vim (coc-clangd) and VSCode.
Related issue: https://github.com/clangd/clangd/issues/310
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: nridge, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D82436
2020-07-14 15:28:38 +08:00
|
|
|
void ClangdServer::foldingRanges(llvm::StringRef File,
|
|
|
|
Callback<std::vector<FoldingRange>> CB) {
|
|
|
|
auto Action =
|
|
|
|
[CB = std::move(CB)](llvm::Expected<InputsAndAST> InpAST) mutable {
|
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
|
|
|
CB(clangd::getFoldingRanges(InpAST->AST));
|
|
|
|
};
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithAST("FoldingRanges", File, std::move(Action),
|
2021-03-11 20:43:59 +08:00
|
|
|
Transient);
|
[clangd] Implement textDocument/foldingRange
Summary:
This patch introduces basic textDocument/foldingRange support. It relies on
textDocument/documentSymbols to collect all symbols and uses takes ranges
to create folds.
The next steps for textDocument/foldingRange support would be:
* Implementing FoldingRangeClientCapabilities and respecting respect client
preferences
* Specifying folding range kind
* Migrating from DocumentSymbol implementation to custom RecursiveASTVisitor flow that will allow more flexibility
* Supporting more folding range types: comments, PP conditional regions, includes and other code regions (e.g. public/private/protected sections of classes, control flow statement bodies)
Tested: (Neo)Vim (coc-clangd) and VSCode.
Related issue: https://github.com/clangd/clangd/issues/310
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: nridge, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D82436
2020-07-14 15:28:38 +08:00
|
|
|
}
|
|
|
|
|
2021-12-31 22:40:56 +08:00
|
|
|
void ClangdServer::findType(llvm::StringRef File, Position Pos,
|
|
|
|
Callback<std::vector<LocatedSymbol>> CB) {
|
|
|
|
auto Action =
|
|
|
|
[Pos, CB = std::move(CB)](llvm::Expected<InputsAndAST> InpAST) mutable {
|
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
|
|
|
CB(clangd::findType(InpAST->AST, Pos));
|
|
|
|
};
|
|
|
|
WorkScheduler->runWithAST("FindType", File, std::move(Action));
|
|
|
|
}
|
|
|
|
|
2020-11-18 20:25:09 +08:00
|
|
|
void ClangdServer::findImplementations(
|
|
|
|
PathRef File, Position Pos, Callback<std::vector<LocatedSymbol>> CB) {
|
|
|
|
auto Action = [Pos, CB = std::move(CB),
|
|
|
|
this](llvm::Expected<InputsAndAST> InpAST) mutable {
|
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
|
|
|
CB(clangd::findImplementations(InpAST->AST, Pos, Index));
|
|
|
|
};
|
|
|
|
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithAST("Implementations", File, std::move(Action));
|
2020-11-18 20:25:09 +08:00
|
|
|
}
|
|
|
|
|
2019-01-15 02:11:09 +08:00
|
|
|
void ClangdServer::findReferences(PathRef File, Position Pos, uint32_t Limit,
|
2019-11-18 18:35:00 +08:00
|
|
|
Callback<ReferencesResult> CB) {
|
2019-08-15 22:16:06 +08:00
|
|
|
auto Action = [Pos, Limit, CB = std::move(CB),
|
|
|
|
this](llvm::Expected<InputsAndAST> InpAST) mutable {
|
2018-09-05 19:53:07 +08:00
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
2019-01-15 02:11:09 +08:00
|
|
|
CB(clangd::findReferences(InpAST->AST, Pos, Limit, Index));
|
2018-09-05 19:53:07 +08:00
|
|
|
};
|
|
|
|
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithAST("References", File, std::move(Action));
|
2018-09-05 19:53:07 +08:00
|
|
|
}
|
|
|
|
|
2018-11-28 00:40:46 +08:00
|
|
|
void ClangdServer::symbolInfo(PathRef File, Position Pos,
|
|
|
|
Callback<std::vector<SymbolDetails>> CB) {
|
2019-08-15 22:16:06 +08:00
|
|
|
auto Action =
|
|
|
|
[Pos, CB = std::move(CB)](llvm::Expected<InputsAndAST> InpAST) mutable {
|
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
|
|
|
CB(clangd::getSymbolInfo(InpAST->AST, Pos));
|
|
|
|
};
|
|
|
|
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithAST("SymbolInfo", File, std::move(Action));
|
2018-11-28 00:40:46 +08:00
|
|
|
}
|
|
|
|
|
2020-03-25 07:51:50 +08:00
|
|
|
void ClangdServer::semanticRanges(PathRef File,
|
|
|
|
const std::vector<Position> &Positions,
|
|
|
|
Callback<std::vector<SelectionRange>> CB) {
|
|
|
|
auto Action = [Positions, CB = std::move(CB)](
|
|
|
|
llvm::Expected<InputsAndAST> InpAST) mutable {
|
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
|
|
|
std::vector<SelectionRange> Result;
|
|
|
|
for (const auto &Pos : Positions) {
|
|
|
|
if (auto Range = clangd::getSemanticRanges(InpAST->AST, Pos))
|
|
|
|
Result.push_back(std::move(*Range));
|
|
|
|
else
|
|
|
|
return CB(Range.takeError());
|
|
|
|
}
|
|
|
|
CB(std::move(Result));
|
|
|
|
};
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithAST("SemanticRanges", File, std::move(Action));
|
2019-09-17 18:28:05 +08:00
|
|
|
}
|
|
|
|
|
2019-12-17 02:08:51 +08:00
|
|
|
void ClangdServer::documentLinks(PathRef File,
|
|
|
|
Callback<std::vector<DocumentLink>> CB) {
|
|
|
|
auto Action =
|
|
|
|
[CB = std::move(CB)](llvm::Expected<InputsAndAST> InpAST) mutable {
|
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
|
|
|
CB(clangd::getDocumentLinks(InpAST->AST));
|
|
|
|
};
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithAST("DocumentLinks", File, std::move(Action),
|
2021-03-11 20:43:59 +08:00
|
|
|
Transient);
|
2019-12-17 02:08:51 +08:00
|
|
|
}
|
|
|
|
|
2020-03-24 09:24:47 +08:00
|
|
|
void ClangdServer::semanticHighlights(
|
|
|
|
PathRef File, Callback<std::vector<HighlightingToken>> CB) {
|
|
|
|
auto Action =
|
|
|
|
[CB = std::move(CB)](llvm::Expected<InputsAndAST> InpAST) mutable {
|
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
|
|
|
CB(clangd::getSemanticHighlightings(InpAST->AST));
|
|
|
|
};
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithAST("SemanticHighlights", File, std::move(Action),
|
2021-03-11 20:43:59 +08:00
|
|
|
Transient);
|
2020-03-24 09:24:47 +08:00
|
|
|
}
|
|
|
|
|
2021-04-24 03:17:43 +08:00
|
|
|
void ClangdServer::getAST(PathRef File, llvm::Optional<Range> R,
|
2020-10-17 02:03:48 +08:00
|
|
|
Callback<llvm::Optional<ASTNode>> CB) {
|
|
|
|
auto Action =
|
|
|
|
[R, CB(std::move(CB))](llvm::Expected<InputsAndAST> Inputs) mutable {
|
|
|
|
if (!Inputs)
|
|
|
|
return CB(Inputs.takeError());
|
2021-04-24 03:17:43 +08:00
|
|
|
if (!R) {
|
|
|
|
// It's safe to pass in the TU, as dumpAST() does not
|
|
|
|
// deserialize the preamble.
|
|
|
|
auto Node = DynTypedNode::create(
|
|
|
|
*Inputs->AST.getASTContext().getTranslationUnitDecl());
|
|
|
|
return CB(dumpAST(Node, Inputs->AST.getTokens(),
|
|
|
|
Inputs->AST.getASTContext()));
|
|
|
|
}
|
2020-10-17 02:03:48 +08:00
|
|
|
unsigned Start, End;
|
2021-04-24 03:17:43 +08:00
|
|
|
if (auto Offset = positionToOffset(Inputs->Inputs.Contents, R->start))
|
2020-10-17 02:03:48 +08:00
|
|
|
Start = *Offset;
|
|
|
|
else
|
|
|
|
return CB(Offset.takeError());
|
2021-04-24 03:17:43 +08:00
|
|
|
if (auto Offset = positionToOffset(Inputs->Inputs.Contents, R->end))
|
2020-10-17 02:03:48 +08:00
|
|
|
End = *Offset;
|
|
|
|
else
|
|
|
|
return CB(Offset.takeError());
|
|
|
|
bool Success = SelectionTree::createEach(
|
|
|
|
Inputs->AST.getASTContext(), Inputs->AST.getTokens(), Start, End,
|
|
|
|
[&](SelectionTree T) {
|
|
|
|
if (const SelectionTree::Node *N = T.commonAncestor()) {
|
|
|
|
CB(dumpAST(N->ASTNode, Inputs->AST.getTokens(),
|
|
|
|
Inputs->AST.getASTContext()));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
if (!Success)
|
|
|
|
CB(llvm::None);
|
|
|
|
};
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithAST("GetAST", File, std::move(Action));
|
2020-10-17 02:03:48 +08:00
|
|
|
}
|
|
|
|
|
2020-08-13 16:43:51 +08:00
|
|
|
void ClangdServer::customAction(PathRef File, llvm::StringRef Name,
|
|
|
|
Callback<InputsAndAST> Action) {
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->runWithAST(Name, File, std::move(Action));
|
2020-08-13 16:43:51 +08:00
|
|
|
}
|
|
|
|
|
2021-03-15 17:18:12 +08:00
|
|
|
void ClangdServer::diagnostics(PathRef File, Callback<std::vector<Diag>> CB) {
|
|
|
|
auto Action =
|
|
|
|
[CB = std::move(CB)](llvm::Expected<InputsAndAST> InpAST) mutable {
|
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
|
|
|
if (auto Diags = InpAST->AST.getDiagnostics())
|
|
|
|
return CB(*Diags);
|
|
|
|
// FIXME: Use ServerCancelled error once it is settled in LSP-3.17.
|
|
|
|
return CB(llvm::make_error<LSPError>("server is busy parsing includes",
|
|
|
|
ErrorCode::InternalError));
|
|
|
|
};
|
|
|
|
|
|
|
|
WorkScheduler->runWithAST("Diagnostics", File, std::move(Action));
|
|
|
|
}
|
|
|
|
|
2020-04-14 04:07:12 +08:00
|
|
|
llvm::StringMap<TUScheduler::FileStats> ClangdServer::fileStats() const {
|
2021-02-16 16:16:10 +08:00
|
|
|
return WorkScheduler->fileStats();
|
2018-01-25 22:32:21 +08:00
|
|
|
}
|
2018-02-13 16:59:23 +08:00
|
|
|
|
|
|
|
LLVM_NODISCARD bool
|
2019-01-07 23:45:19 +08:00
|
|
|
ClangdServer::blockUntilIdleForTest(llvm::Optional<double> TimeoutSeconds) {
|
2021-02-17 19:59:25 +08:00
|
|
|
// Order is important here: we don't want to block on A and then B,
|
|
|
|
// if B might schedule work on A.
|
|
|
|
|
|
|
|
// Nothing else can schedule work on TUScheduler, because it's not threadsafe
|
|
|
|
// and we're blocking the main thread.
|
2021-02-16 16:16:10 +08:00
|
|
|
if (!WorkScheduler->blockUntilIdle(timeoutSeconds(TimeoutSeconds)))
|
2021-02-17 19:59:25 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// Unfortunately we don't have strict topological order between the rest of
|
|
|
|
// the components. E.g. CDB broadcast triggers backrgound indexing.
|
|
|
|
// This queries the CDB which may discover new work if disk has changed.
|
|
|
|
//
|
|
|
|
// So try each one a few times in a loop.
|
|
|
|
// If there are no tricky interactions then all after the first are no-ops.
|
|
|
|
// Then on the last iteration, verify they're idle without waiting.
|
|
|
|
//
|
|
|
|
// There's a small chance they're juggling work and we didn't catch them :-(
|
|
|
|
for (llvm::Optional<double> Timeout :
|
|
|
|
{TimeoutSeconds, TimeoutSeconds, llvm::Optional<double>(0)}) {
|
|
|
|
if (!CDB.blockUntilIdle(timeoutSeconds(Timeout)))
|
|
|
|
return false;
|
|
|
|
if (BackgroundIdx && !BackgroundIdx->blockUntilIdleForTest(Timeout))
|
|
|
|
return false;
|
2021-03-04 23:21:01 +08:00
|
|
|
if (FeatureModules && llvm::any_of(*FeatureModules, [&](FeatureModule &M) {
|
2021-02-16 16:16:10 +08:00
|
|
|
return !M.blockUntilIdle(timeoutSeconds(Timeout));
|
|
|
|
}))
|
|
|
|
return false;
|
2021-02-17 19:59:25 +08:00
|
|
|
}
|
|
|
|
|
2021-02-16 16:16:10 +08:00
|
|
|
assert(WorkScheduler->blockUntilIdle(Deadline::zero()) &&
|
2021-02-17 19:59:25 +08:00
|
|
|
"Something scheduled work while we're blocking the main thread!");
|
|
|
|
return true;
|
2018-02-13 16:59:23 +08:00
|
|
|
}
|
2018-10-20 23:30:37 +08:00
|
|
|
|
2020-09-28 21:09:55 +08:00
|
|
|
void ClangdServer::profile(MemoryTree &MT) const {
|
|
|
|
if (DynamicIdx)
|
|
|
|
DynamicIdx->profile(MT.child("dynamic_index"));
|
|
|
|
if (BackgroundIdx)
|
|
|
|
BackgroundIdx->profile(MT.child("background_index"));
|
2021-02-16 16:16:10 +08:00
|
|
|
WorkScheduler->profile(MT.child("tuscheduler"));
|
2020-09-28 21:09:55 +08:00
|
|
|
}
|
2018-10-20 23:30:37 +08:00
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|