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"
|
[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-05-29 18:01:00 +08:00
|
|
|
#include "FormattedString.h"
|
2019-09-25 18:30:22 +08:00
|
|
|
#include "HeaderSourceSwitch.h"
|
2018-02-16 22:15:55 +08:00
|
|
|
#include "Headers.h"
|
2019-09-09 20:28:44 +08:00
|
|
|
#include "Logger.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"
|
[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 "Trace.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"
|
2017-05-16 22:40:30 +08:00
|
|
|
#include "clang/Format/Format.h"
|
2017-05-16 17:38:59 +08:00
|
|
|
#include "clang/Frontend/CompilerInstance.h"
|
|
|
|
#include "clang/Frontend/CompilerInvocation.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-01-26 01:01:39 +08:00
|
|
|
#include "llvm/ADT/ScopeExit.h"
|
2018-06-13 17:20:41 +08:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
2017-10-26 20:28:13 +08:00
|
|
|
#include "llvm/Support/Errc.h"
|
[clangd] Interfaces for writing code tweaks
Summary:
The code tweaks are an implementation of mini-refactorings exposed
via the LSP code actions. They run in two stages:
- Stage 1. Decides whether the action is available to the user and
collects all the information required to finish the action.
Should be cheap, since this will run over all the actions known to
clangd on each textDocument/codeAction request from the client.
- Stage 2. Uses information from stage 1 to produce the actual edits
that the code action should perform. This stage can be expensive and
will only run if the user chooses to perform the specified action in
the UI.
One unfortunate consequence of this change is increased latency of
processing the textDocument/codeAction requests, which now wait for an
AST. However, we cannot avoid this with what we have available in the LSP
today.
Reviewers: kadircet, ioeric, hokein, sammccall
Reviewed By: sammccall
Subscribers: mgrang, mgorny, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D56267
llvm-svn: 352494
2019-01-29 22:17:36 +08:00
|
|
|
#include "llvm/Support/Error.h"
|
2017-05-16 17:38:59 +08:00
|
|
|
#include "llvm/Support/FileSystem.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>
|
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: 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,
|
|
|
|
ClangdServer::Callbacks *ServerCallbacks,
|
2020-03-24 07:31:14 +08:00
|
|
|
bool TheiaSemanticHighlighting)
|
2020-01-24 21:08:56 +08:00
|
|
|
: FIndex(FIndex), ServerCallbacks(ServerCallbacks),
|
2020-03-24 07:31:14 +08:00
|
|
|
TheiaSemanticHighlighting(TheiaSemanticHighlighting) {}
|
[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,
|
2019-02-05 00:19:57 +08:00
|
|
|
std::shared_ptr<clang::Preprocessor> PP,
|
|
|
|
const CanonicalIncludes &CanonIncludes) override {
|
2018-11-23 01:27:08 +08:00
|
|
|
if (FIndex)
|
[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
|
|
|
FIndex->updatePreamble(Path, Version, Ctx, std::move(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
|
|
|
|
|
|
|
std::vector<Diag> Diagnostics = AST.getDiagnostics();
|
|
|
|
std::vector<HighlightingToken> Highlightings;
|
2020-03-24 07:31:14 +08:00
|
|
|
if (TheiaSemanticHighlighting)
|
2019-07-19 21:51:01 +08:00
|
|
|
Highlightings = getSemanticHighlightings(AST);
|
2018-11-23 01:27:08 +08:00
|
|
|
|
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-03-24 07:31:14 +08:00
|
|
|
if (TheiaSemanticHighlighting)
|
[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->onHighlightingsReady(Path, AST.version(),
|
|
|
|
std::move(Highlightings));
|
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
|
|
|
}
|
|
|
|
|
2018-11-23 01:27:08 +08:00
|
|
|
private:
|
|
|
|
FileIndex *FIndex;
|
2020-01-24 21:08:56 +08:00
|
|
|
ClangdServer::Callbacks *ServerCallbacks;
|
2020-03-24 07:31:14 +08:00
|
|
|
bool TheiaSemanticHighlighting;
|
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!
|
2020-03-24 07:31:14 +08:00
|
|
|
Opts.TheiaSemanticHighlighting = true;
|
2018-03-06 01:28:54 +08:00
|
|
|
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;
|
|
|
|
return Opts;
|
|
|
|
}
|
|
|
|
|
2018-10-10 15:46:15 +08:00
|
|
|
ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB,
|
|
|
|
const FileSystemProvider &FSProvider,
|
2020-01-24 21:08:56 +08:00
|
|
|
const Options &Opts, Callbacks *Callbacks)
|
2019-04-15 20:32:28 +08:00
|
|
|
: FSProvider(FSProvider),
|
2018-10-16 16:53:52 +08:00
|
|
|
DynamicIdx(Opts.BuildDynamicSymbolIndex
|
[clangd] Cleanup: stop passing around list of supported URI schemes.
Summary:
Instead of passing around a list of supported URI schemes in clangd, we
expose an interface to convert a path to URI using any compatible scheme
that has been registered. It favors customized schemes and falls
back to "file" when no other scheme works.
Changes in this patch are:
- URI::create(AbsPath, URISchemes) -> URI::create(AbsPath). The new API finds a
compatible scheme from the registry.
- Remove URISchemes option everywhere (ClangdServer, SymbolCollecter, FileIndex etc).
- Unit tests will use "unittest" by default.
- Move "test" scheme from ClangdLSPServer to ClangdMain.cpp, and only
register the test scheme when lit-test or enable-lit-scheme is set.
(The new flag is added to make lit protocol.test work; I wonder if there
is alternative here.)
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D54800
llvm-svn: 347467
2018-11-22 23:02:05 +08:00
|
|
|
? new FileIndex(Opts.HeavyweightDynamicSymbolIndex)
|
2018-10-16 16:53:52 +08:00
|
|
|
: nullptr),
|
2019-05-21 01:30:46 +08:00
|
|
|
GetClangTidyOptions(Opts.GetClangTidyOptions),
|
2019-01-28 22:01:55 +08:00
|
|
|
SuggestMissingIncludes(Opts.SuggestMissingIncludes),
|
2020-03-31 22:09:49 +08:00
|
|
|
BuildRecoveryAST(Opts.BuildRecoveryAST), TweakFilter(Opts.TweakFilter),
|
|
|
|
WorkspaceRoot(Opts.WorkspaceRoot),
|
2018-01-31 16:51:16 +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.
|
2017-12-20 02:00:37 +08:00
|
|
|
// FIXME(ioeric): this can be slow and we may be able to index on less
|
|
|
|
// critical paths.
|
2020-02-03 18:18:13 +08:00
|
|
|
WorkScheduler(
|
|
|
|
CDB, TUScheduler::Options(Opts),
|
2020-03-24 07:31:14 +08:00
|
|
|
std::make_unique<UpdateIndexCallbacks>(
|
|
|
|
DynamicIdx.get(), Callbacks, Opts.TheiaSemanticHighlighting)) {
|
[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) {
|
2019-08-15 07:52:23 +08:00
|
|
|
BackgroundIdx = std::make_unique<BackgroundIndex>(
|
2019-01-22 17:10:20 +08:00
|
|
|
Context::current().clone(), FSProvider, 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); }),
|
[clangd] Show background index status using LSP 3.15 work-done progress notifications
Summary:
It simply shows the completed/total items on the background queue, e.g.
indexing: 233/1000
The denominator is reset to zero every time the queue goes idle.
The protocol is fairly complicated here (requires creating a remote "progress"
resource before sending updates). We implement the full protocol, but I've added
an extension allowing it to be skipped to reduce the burden on clients - in
particular the lit test takes this shortcut.
The addition of background index progress to DiagnosticConsumer seems ridiculous
at first glance, but I believe that interface is trending in the direction of
"ClangdServer callbacks" anyway. It's due for a rename, but otherwise actually
fits.
Reviewers: kadircet, usaxena95
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D73218
2020-01-23 02:41:45 +08:00
|
|
|
std::max(Opts.AsyncThreadsCount, 1u),
|
2020-01-24 21:08:56 +08:00
|
|
|
[Callbacks](BackgroundQueue::Stats S) {
|
|
|
|
if (Callbacks)
|
|
|
|
Callbacks->onBackgroundIndexProgress(S);
|
[clangd] Show background index status using LSP 3.15 work-done progress notifications
Summary:
It simply shows the completed/total items on the background queue, e.g.
indexing: 233/1000
The denominator is reset to zero every time the queue goes idle.
The protocol is fairly complicated here (requires creating a remote "progress"
resource before sending updates). We implement the full protocol, but I've added
an extension allowing it to be skipped to reduce the burden on clients - in
particular the lit test takes this shortcut.
The addition of background index progress to DiagnosticConsumer seems ridiculous
at first glance, but I believe that interface is trending in the direction of
"ClangdServer callbacks" anyway. It's due for a rename, but otherwise actually
fits.
Reviewers: kadircet, usaxena95
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D73218
2020-01-23 02:41:45 +08:00
|
|
|
});
|
[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());
|
2018-01-15 20:33:00 +08:00
|
|
|
}
|
2017-05-16 17:38:59 +08:00
|
|
|
|
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) {
|
2019-05-21 01:30:46 +08:00
|
|
|
auto FS = FSProvider.getFileSystem();
|
|
|
|
|
2019-01-28 22:01:55 +08:00
|
|
|
ParseOptions Opts;
|
|
|
|
Opts.ClangTidyOpts = tidy::ClangTidyOptions::getDefaults();
|
2019-05-21 01:30:46 +08:00
|
|
|
// FIXME: call tidy options builder on the worker thread, it can do IO.
|
|
|
|
if (GetClangTidyOptions)
|
|
|
|
Opts.ClangTidyOpts = GetClangTidyOptions(*FS, File);
|
2019-01-28 22:01:55 +08:00
|
|
|
Opts.SuggestMissingIncludes = SuggestMissingIncludes;
|
[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;
|
2019-05-21 01:30:46 +08:00
|
|
|
Inputs.FS = FS;
|
2020-01-29 03:23:46 +08:00
|
|
|
Inputs.Contents = std::string(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
|
|
|
Inputs.Version = Version.str();
|
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-03-31 22:09:49 +08:00
|
|
|
Inputs.Opts.BuildRecoveryAST = BuildRecoveryAST;
|
2019-07-12 18:18:42 +08:00
|
|
|
bool NewFile = WorkScheduler.update(File, Inputs, WantDiags);
|
|
|
|
// 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
|
|
|
}
|
|
|
|
|
2019-01-03 21:28:05 +08:00
|
|
|
void ClangdServer::removeDocument(PathRef 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
|
|
|
|
2019-08-15 22:16:06 +08:00
|
|
|
auto Task = [Pos, FS = FSProvider.getFileSystem(), CodeCompleteOpts,
|
|
|
|
File = File.str(), CB = std::move(CB),
|
|
|
|
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);
|
|
|
|
} else {
|
|
|
|
if (CodeCompleteOpts.Index && CodeCompleteOpts.SpeculativeIndexRequest) {
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
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(
|
2019-04-04 20:56:03 +08:00
|
|
|
File, IP->Command, IP->Preamble, IP->Contents, Pos, FS,
|
2018-10-02 18:43:55 +08:00
|
|
|
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.
|
2019-05-21 21:40:31 +08:00
|
|
|
WorkScheduler.runWithPreamble(
|
|
|
|
"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,
|
|
|
|
Callback<SignatureHelp> CB) {
|
2017-10-06 19:54:17 +08:00
|
|
|
|
2019-08-15 22:16:06 +08:00
|
|
|
auto Action = [Pos, FS = FSProvider.getFileSystem(), File = File.str(),
|
|
|
|
CB = std::move(CB),
|
|
|
|
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)
|
|
|
|
return CB(llvm::createStringError(llvm::inconvertibleErrorCode(),
|
|
|
|
"Failed to parse includes"));
|
|
|
|
|
|
|
|
CB(clangd::signatureHelp(File, IP->Command, *PreambleData, IP->Contents,
|
|
|
|
Pos, FS, Index));
|
2018-01-31 16:51:16 +08:00
|
|
|
};
|
2018-02-15 21:15:47 +08:00
|
|
|
|
2018-08-30 23:07:34 +08:00
|
|
|
// Unlike code completion, we wait for an up-to-date preamble here.
|
|
|
|
// Signature help is often triggered after code completion. If the code
|
|
|
|
// completion inserted a header to make the symbol available, then using
|
|
|
|
// the old preamble would yield useless results.
|
|
|
|
WorkScheduler.runWithPreamble("SignatureHelp", File, TUScheduler::Consistent,
|
2019-08-15 22:16:06 +08:00
|
|
|
std::move(Action));
|
2017-10-06 19:54:17 +08:00
|
|
|
}
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Expected<tooling::Replacements>
|
|
|
|
ClangdServer::formatRange(llvm::StringRef Code, PathRef File, Range Rng) {
|
|
|
|
llvm::Expected<size_t> Begin = positionToOffset(Code, Rng.start);
|
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 (!Begin)
|
|
|
|
return Begin.takeError();
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Expected<size_t> End = positionToOffset(Code, Rng.end);
|
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 (!End)
|
|
|
|
return End.takeError();
|
|
|
|
return formatCode(Code, File, {tooling::Range(*Begin, *End - *Begin)});
|
2017-05-16 22:40:30 +08:00
|
|
|
}
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Expected<tooling::Replacements>
|
|
|
|
ClangdServer::formatFile(llvm::StringRef Code, PathRef File) {
|
2017-05-16 22:40:30 +08:00
|
|
|
// Format everything.
|
|
|
|
return formatCode(Code, File, {tooling::Range(0, Code.size())});
|
|
|
|
}
|
|
|
|
|
[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
|
|
|
llvm::Expected<std::vector<TextEdit>>
|
|
|
|
ClangdServer::formatOnType(llvm::StringRef Code, PathRef File, Position Pos,
|
|
|
|
StringRef TriggerText) {
|
2019-01-07 23:45:19 +08:00
|
|
|
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)
|
|
|
|
return CursorPos.takeError();
|
[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
|
|
|
auto FS = FSProvider.getFileSystem();
|
|
|
|
auto Style = format::getStyle(format::DefaultFormatStyle, File,
|
|
|
|
format::DefaultFallbackStyle, Code, FS.get());
|
|
|
|
if (!Style)
|
|
|
|
return Style.takeError();
|
2017-05-16 22:40:30 +08:00
|
|
|
|
[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
|
|
|
std::vector<TextEdit> Result;
|
|
|
|
for (const tooling::Replacement &R :
|
|
|
|
formatIncremental(Code, *CursorPos, TriggerText, *Style))
|
|
|
|
Result.push_back(replacementToEdit(Code, R));
|
|
|
|
return Result;
|
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-02-19 22:37:36 +08:00
|
|
|
const RenameOptions &RenameOpts,
|
2019-07-24 15:49:23 +08:00
|
|
|
Callback<llvm::Optional<Range>> CB) {
|
2020-02-19 22:37:36 +08:00
|
|
|
auto Action = [Pos, File = File.str(), CB = std::move(CB), RenameOpts,
|
2019-08-15 22:16:06 +08:00
|
|
|
this](llvm::Expected<InputsAndAST> InpAST) mutable {
|
2019-07-24 15:49:23 +08:00
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
|
|
|
auto &AST = InpAST->AST;
|
2019-10-23 20:40:20 +08:00
|
|
|
const auto &SM = AST.getSourceManager();
|
[clangd] Replace raw lexer code with token buffer in prepare rename.
Summary:
there is a slight behavior change in this patch:
- before: `in^t a;`, returns our internal error message (no symbol at given location)
- after: `in^t a, returns null, and client displays their message (e.g.
e.g. "the element can't be renamed" in vscode).
both are sensible according LSP, and we'd save one `rename` call in the later case.
Reviewers: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D73610
2020-01-29 17:12:56 +08:00
|
|
|
auto Loc = sourceLocationInMainFile(SM, Pos);
|
|
|
|
if (!Loc)
|
|
|
|
return CB(Loc.takeError());
|
|
|
|
const auto *TouchingIdentifier =
|
|
|
|
spelledIdentifierTouching(*Loc, AST.getTokens());
|
|
|
|
if (!TouchingIdentifier)
|
|
|
|
return CB(llvm::None); // no rename on non-identifiers.
|
|
|
|
|
|
|
|
auto Range = halfOpenToRange(
|
|
|
|
SM, CharSourceRange::getCharRange(TouchingIdentifier->location(),
|
|
|
|
TouchingIdentifier->endLocation()));
|
2019-10-23 20:40:20 +08:00
|
|
|
|
2020-02-19 22:37:36 +08:00
|
|
|
if (RenameOpts.AllowCrossFile)
|
2019-10-23 20:40:20 +08:00
|
|
|
// FIXME: we now assume cross-file rename always succeeds, revisit this.
|
[clangd] Replace raw lexer code with token buffer in prepare rename.
Summary:
there is a slight behavior change in this patch:
- before: `in^t a;`, returns our internal error message (no symbol at given location)
- after: `in^t a, returns null, and client displays their message (e.g.
e.g. "the element can't be renamed" in vscode).
both are sensible according LSP, and we'd save one `rename` call in the later case.
Reviewers: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D73610
2020-01-29 17:12:56 +08:00
|
|
|
return CB(Range);
|
2019-10-23 20:40:20 +08:00
|
|
|
|
|
|
|
// Performing the local rename isn't substantially more expensive than
|
|
|
|
// doing an AST-based check, so we just rename and throw away the results.
|
2020-02-19 22:37:36 +08:00
|
|
|
auto Changes = clangd::rename({Pos, "dummy", AST, File, Index, RenameOpts,
|
2019-10-23 20:40:20 +08:00
|
|
|
/*GetDirtyBuffer=*/nullptr});
|
2019-07-24 15:49:23 +08:00
|
|
|
if (!Changes) {
|
|
|
|
// 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).
|
|
|
|
return CB(Changes.takeError());
|
|
|
|
}
|
[clangd] Replace raw lexer code with token buffer in prepare rename.
Summary:
there is a slight behavior change in this patch:
- before: `in^t a;`, returns our internal error message (no symbol at given location)
- after: `in^t a, returns null, and client displays their message (e.g.
e.g. "the element can't be renamed" in vscode).
both are sensible according LSP, and we'd save one `rename` call in the later case.
Reviewers: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D73610
2020-01-29 17:12:56 +08:00
|
|
|
return CB(Range);
|
2019-07-24 15:49:23 +08:00
|
|
|
};
|
2019-08-15 22:16:06 +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-02-19 22:37:36 +08:00
|
|
|
const RenameOptions &Opts, Callback<FileEdits> CB) {
|
2019-10-23 20:40:20 +08:00
|
|
|
// A snapshot of all file dirty buffers.
|
|
|
|
llvm::StringMap<std::string> Snapshot = WorkScheduler.getAllFileContents();
|
2020-02-19 22:37:36 +08:00
|
|
|
auto Action = [File = File.str(), NewName = NewName.str(), Pos, Opts,
|
2019-10-23 20:40:20 +08:00
|
|
|
CB = std::move(CB), Snapshot = std::move(Snapshot),
|
2019-08-15 22:16:06 +08:00
|
|
|
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());
|
2019-10-23 20:40:20 +08:00
|
|
|
auto GetDirtyBuffer =
|
|
|
|
[&Snapshot](PathRef AbsPath) -> llvm::Optional<std::string> {
|
|
|
|
auto It = Snapshot.find(AbsPath);
|
|
|
|
if (It == Snapshot.end())
|
|
|
|
return llvm::None;
|
|
|
|
return It->second;
|
|
|
|
};
|
2020-02-19 22:37:36 +08:00
|
|
|
auto Edits = clangd::rename(
|
|
|
|
{Pos, NewName, InpAST->AST, File, Index, Opts, GetDirtyBuffer});
|
2019-10-23 20:40:20 +08:00
|
|
|
if (!Edits)
|
|
|
|
return CB(Edits.takeError());
|
2019-06-20 01:25:24 +08:00
|
|
|
|
2020-02-19 22:37:36 +08:00
|
|
|
if (Opts.WantFormat) {
|
2019-07-10 21:44:22 +08:00
|
|
|
auto Style = getFormatStyleForFile(File, InpAST->Inputs.Contents,
|
|
|
|
InpAST->Inputs.FS.get());
|
2019-10-23 20:40:20 +08:00
|
|
|
llvm::Error Err = llvm::Error::success();
|
|
|
|
for (auto &E : *Edits)
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
return CB(std::move(*Edits));
|
2018-01-31 16:51:16 +08:00
|
|
|
};
|
2019-08-15 22:16:06 +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>>>
|
2019-02-01 23:09:47 +08:00
|
|
|
tweakSelection(const Range &Sel, const InputsAndAST &AST) {
|
|
|
|
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>(
|
|
|
|
AST.Inputs.Index, AST.AST, *Begin, *End, std::move(T)));
|
|
|
|
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
|
|
|
}
|
|
|
|
|
[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
|
|
|
void ClangdServer::enumerateTweaks(PathRef File, Range Sel,
|
|
|
|
Callback<std::vector<TweakRef>> CB) {
|
2019-08-15 22:16:06 +08:00
|
|
|
auto Action = [File = File.str(), Sel, CB = std::move(CB),
|
|
|
|
this](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());
|
2020-02-24 03:03:00 +08:00
|
|
|
auto Selections = tweakSelection(Sel, *InpAST);
|
|
|
|
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;
|
|
|
|
auto Filter = [&](const Tweak &T) {
|
|
|
|
return TweakFilter(T) && !PreparedTweaks.count(T.id());
|
|
|
|
};
|
|
|
|
for (const auto &Sel : *Selections) {
|
|
|
|
for (auto &T : prepareTweaks(*Sel, Filter)) {
|
|
|
|
Res.push_back({T->id(), T->title(), T->intent()});
|
|
|
|
PreparedTweaks.insert(T->id());
|
|
|
|
}
|
|
|
|
}
|
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));
|
|
|
|
};
|
|
|
|
|
[clangd] Cancel certain operations if the file changes before we start.
Summary:
Otherwise they can force us to build lots of snapshots that we don't need.
Particularly, try to do this for operations that are frequently
generated by editors without explicit user interaction, and where
editing the file makes the result less useful. (Code action
enumeration is a good example).
https://github.com/clangd/clangd/issues/298
This doesn't return the "right" LSP error code (ContentModified) to the client,
we need to teach the cancellation API to distinguish between different causes.
Reviewers: kadircet
Subscribers: ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75602
2020-03-04 21:04:17 +08:00
|
|
|
WorkScheduler.runWithAST("EnumerateTweaks", File, std::move(Action),
|
|
|
|
TUScheduler::InvalidateOnUpdate);
|
[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) {
|
2019-09-09 20:28:44 +08:00
|
|
|
auto Action =
|
|
|
|
[File = File.str(), Sel, TweakID = TweakID.str(), CB = std::move(CB),
|
|
|
|
FS = FSProvider.getFileSystem()](Expected<InputsAndAST> InpAST) mutable {
|
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
2020-02-24 03:03:00 +08:00
|
|
|
auto Selections = tweakSelection(Sel, *InpAST);
|
|
|
|
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) {
|
|
|
|
auto T = prepareTweak(TweakID, *Selection);
|
|
|
|
if (T) {
|
|
|
|
Effect = (*T)->apply(*Selection);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Effect = T.takeError();
|
|
|
|
}
|
|
|
|
assert(Effect.hasValue() && "Expected at least one selection");
|
|
|
|
if (*Effect) {
|
|
|
|
// Tweaks don't apply clang-format, do that centrally here.
|
|
|
|
for (auto &It : (*Effect)->ApplyEdits) {
|
|
|
|
Edit &E = It.second;
|
|
|
|
format::FormatStyle Style =
|
|
|
|
getFormatStyleForFile(File, E.InitialCode, FS.get());
|
|
|
|
if (llvm::Error Err = reformatEdit(E, Style))
|
|
|
|
elog("Failed to format {0}: {1}", It.first(), std::move(Err));
|
|
|
|
}
|
2019-09-09 20:28:44 +08:00
|
|
|
}
|
|
|
|
return CB(std::move(*Effect));
|
|
|
|
};
|
2019-08-15 22:16:06 +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
|
|
|
}
|
|
|
|
|
2018-02-15 21:15:47 +08:00
|
|
|
void ClangdServer::dumpAST(PathRef File,
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::unique_function<void(std::string)> Callback) {
|
2019-08-15 22:16:06 +08:00
|
|
|
auto Action = [Callback = std::move(Callback)](
|
|
|
|
llvm::Expected<InputsAndAST> InpAST) mutable {
|
2018-01-31 16:51:16 +08:00
|
|
|
if (!InpAST) {
|
2018-11-23 00:20:12 +08:00
|
|
|
llvm::consumeError(InpAST.takeError());
|
2018-02-15 21:15:47 +08:00
|
|
|
return Callback("<no-ast>");
|
2018-01-31 16:51:16 +08:00
|
|
|
}
|
|
|
|
std::string Result;
|
2017-08-01 23:51:38 +08:00
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::raw_string_ostream ResultOS(Result);
|
2018-01-31 16:51:16 +08:00
|
|
|
clangd::dumpAST(InpAST->AST, ResultOS);
|
2017-08-01 23:51:38 +08:00
|
|
|
ResultOS.flush();
|
2018-01-31 16:51:16 +08:00
|
|
|
|
2018-02-15 21:15:47 +08:00
|
|
|
Callback(Result);
|
2018-01-31 16:51:16 +08:00
|
|
|
};
|
2018-02-15 21:15:47 +08:00
|
|
|
|
2019-08-15 22:16:06 +08:00
|
|
|
WorkScheduler.runWithAST("DumpAST", File, std::move(Action));
|
2017-05-16 17:38:59 +08:00
|
|
|
}
|
2017-06-29 00:12:10 +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
|
|
|
|
2019-08-15 22:16:06 +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.
|
2020-01-29 03:23:46 +08:00
|
|
|
if (auto CorrespondingFile = getCorrespondingHeaderOrSource(
|
|
|
|
std::string(Path), FSProvider.getFileSystem()))
|
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));
|
|
|
|
};
|
|
|
|
WorkScheduler.runWithAST("SwitchHeaderSource", Path, std::move(Action));
|
2017-09-28 11:14:40 +08:00
|
|
|
}
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Expected<tooling::Replacements>
|
|
|
|
ClangdServer::formatCode(llvm::StringRef Code, PathRef File,
|
|
|
|
llvm::ArrayRef<tooling::Range> Ranges) {
|
2017-12-13 04:25:06 +08:00
|
|
|
// Call clang-format.
|
2019-05-06 16:39:17 +08:00
|
|
|
format::FormatStyle Style =
|
|
|
|
getFormatStyleForFile(File, Code, FSProvider.getFileSystem().get());
|
2018-03-06 18:42:50 +08:00
|
|
|
tooling::Replacements IncludeReplaces =
|
2019-05-06 16:39:17 +08:00
|
|
|
format::sortIncludes(Style, Code, Ranges, File);
|
2018-03-06 18:42:50 +08:00
|
|
|
auto Changed = tooling::applyAllReplacements(Code, IncludeReplaces);
|
|
|
|
if (!Changed)
|
|
|
|
return Changed.takeError();
|
|
|
|
|
|
|
|
return IncludeReplaces.merge(format::reformat(
|
2019-05-06 16:39:17 +08:00
|
|
|
Style, *Changed,
|
2018-03-06 18:42:50 +08:00
|
|
|
tooling::calculateRangesAfterReplacements(IncludeReplaces, Ranges),
|
|
|
|
File));
|
2017-12-13 04:25:06 +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));
|
|
|
|
};
|
|
|
|
|
[clangd] Cancel certain operations if the file changes before we start.
Summary:
Otherwise they can force us to build lots of snapshots that we don't need.
Particularly, try to do this for operations that are frequently
generated by editors without explicit user interaction, and where
editing the file makes the result less useful. (Code action
enumeration is a good example).
https://github.com/clangd/clangd/issues/298
This doesn't return the "right" LSP error code (ContentModified) to the client,
we need to teach the cancellation API to distinguish between different causes.
Reviewers: kadircet
Subscribers: ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75602
2020-03-04 21:04:17 +08:00
|
|
|
WorkScheduler.runWithAST("Highlights", File, std::move(Action),
|
|
|
|
TUScheduler::InvalidateOnUpdate);
|
[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());
|
2019-05-28 18:29:58 +08:00
|
|
|
format::FormatStyle Style = getFormatStyleForFile(
|
|
|
|
File, InpAST->Inputs.Contents, InpAST->Inputs.FS.get());
|
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
|
|
|
};
|
|
|
|
|
[clangd] Cancel certain operations if the file changes before we start.
Summary:
Otherwise they can force us to build lots of snapshots that we don't need.
Particularly, try to do this for operations that are frequently
generated by editors without explicit user interaction, and where
editing the file makes the result less useful. (Code action
enumeration is a good example).
https://github.com/clangd/clangd/issues/298
This doesn't return the "right" LSP error code (ContentModified) to the client,
we need to teach the cancellation API to distinguish between different causes.
Reviewers: kadircet
Subscribers: ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75602
2020-03-04 21:04:17 +08:00
|
|
|
WorkScheduler.runWithAST("Hover", File, std::move(Action),
|
|
|
|
TUScheduler::InvalidateOnUpdate);
|
[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
|
|
|
};
|
|
|
|
|
2019-08-15 22:16:06 +08:00
|
|
|
WorkScheduler.runWithAST("Type Hierarchy", 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) {
|
|
|
|
clangd::resolveTypeHierarchy(Item, Resolve, Direction, Index);
|
|
|
|
CB(Item);
|
|
|
|
}
|
|
|
|
|
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) {
|
2018-10-25 22:19:14 +08:00
|
|
|
WorkScheduler.run(
|
|
|
|
"getWorkspaceSymbols",
|
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));
|
|
|
|
};
|
[clangd] Cancel certain operations if the file changes before we start.
Summary:
Otherwise they can force us to build lots of snapshots that we don't need.
Particularly, try to do this for operations that are frequently
generated by editors without explicit user interaction, and where
editing the file makes the result less useful. (Code action
enumeration is a good example).
https://github.com/clangd/clangd/issues/298
This doesn't return the "right" LSP error code (ContentModified) to the client,
we need to teach the cancellation API to distinguish between different causes.
Reviewers: kadircet
Subscribers: ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75602
2020-03-04 21:04:17 +08:00
|
|
|
WorkScheduler.runWithAST("documentSymbols", File, std::move(Action),
|
|
|
|
TUScheduler::InvalidateOnUpdate);
|
2018-07-06 03:35:01 +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
|
|
|
};
|
|
|
|
|
2019-08-15 22:16:06 +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));
|
|
|
|
};
|
|
|
|
|
|
|
|
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));
|
|
|
|
};
|
2019-09-17 18:28:05 +08:00
|
|
|
WorkScheduler.runWithAST("SemanticRanges", File, std::move(Action));
|
|
|
|
}
|
|
|
|
|
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));
|
|
|
|
};
|
[clangd] Cancel certain operations if the file changes before we start.
Summary:
Otherwise they can force us to build lots of snapshots that we don't need.
Particularly, try to do this for operations that are frequently
generated by editors without explicit user interaction, and where
editing the file makes the result less useful. (Code action
enumeration is a good example).
https://github.com/clangd/clangd/issues/298
This doesn't return the "right" LSP error code (ContentModified) to the client,
we need to teach the cancellation API to distinguish between different causes.
Reviewers: kadircet
Subscribers: ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75602
2020-03-04 21:04:17 +08:00
|
|
|
WorkScheduler.runWithAST("DocumentLinks", File, std::move(Action),
|
|
|
|
TUScheduler::InvalidateOnUpdate);
|
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));
|
|
|
|
};
|
|
|
|
WorkScheduler.runWithAST("SemanticHighlights", File, std::move(Action),
|
|
|
|
TUScheduler::InvalidateOnUpdate);
|
|
|
|
}
|
|
|
|
|
2020-04-14 04:07:12 +08:00
|
|
|
llvm::StringMap<TUScheduler::FileStats> ClangdServer::fileStats() const {
|
|
|
|
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) {
|
[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
|
|
|
return WorkScheduler.blockUntilIdle(timeoutSeconds(TimeoutSeconds)) &&
|
|
|
|
(!BackgroundIdx ||
|
|
|
|
BackgroundIdx->blockUntilIdleForTest(TimeoutSeconds));
|
2018-02-13 16:59:23 +08:00
|
|
|
}
|
2018-10-20 23:30:37 +08:00
|
|
|
|
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|