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"
|
2019-01-28 22:01:55 +08:00
|
|
|
#include "ClangdUnit.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"
|
2018-02-16 22:15:55 +08:00
|
|
|
#include "Headers.h"
|
2017-12-19 20:23:48 +08:00
|
|
|
#include "SourceCode.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-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"
|
[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-11-16 02:04:56 +08:00
|
|
|
#include "clang/Tooling/Refactoring/RefactoringResultConsumer.h"
|
|
|
|
#include "clang/Tooling/Refactoring/Rename/RenamingAction.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"
|
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"
|
|
|
|
#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>
|
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 {
|
|
|
|
|
2017-11-09 19:30:04 +08:00
|
|
|
class RefactoringResultCollector final
|
|
|
|
: public tooling::RefactoringResultConsumer {
|
|
|
|
public:
|
2019-01-07 23:45:19 +08:00
|
|
|
void handleError(llvm::Error Err) override {
|
2017-11-09 19:30:04 +08:00
|
|
|
assert(!Result.hasValue());
|
|
|
|
// FIXME: figure out a way to return better message for DiagnosticError.
|
|
|
|
// clangd uses llvm::toString to convert the Err to string, however, for
|
|
|
|
// DiagnosticError, only "clang diagnostic" will be generated.
|
|
|
|
Result = std::move(Err);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Using the handle(SymbolOccurrences) from parent class.
|
|
|
|
using tooling::RefactoringResultConsumer::handle;
|
|
|
|
|
|
|
|
void handle(tooling::AtomicChanges SourceReplacements) override {
|
|
|
|
assert(!Result.hasValue());
|
|
|
|
Result = std::move(SourceReplacements);
|
|
|
|
}
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Optional<llvm::Expected<tooling::AtomicChanges>> Result;
|
2017-11-09 19:30:04 +08:00
|
|
|
};
|
|
|
|
|
2018-11-23 01:27:08 +08:00
|
|
|
// Update the FileIndex with new ASTs and plumb the diagnostics responses.
|
|
|
|
struct UpdateIndexCallbacks : public ParsingCallbacks {
|
|
|
|
UpdateIndexCallbacks(FileIndex *FIndex, DiagnosticsConsumer &DiagConsumer)
|
|
|
|
: FIndex(FIndex), DiagConsumer(DiagConsumer) {}
|
[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-11-23 01:27:08 +08:00
|
|
|
void onPreambleAST(PathRef Path, 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)
|
2019-02-05 00:19:57 +08:00
|
|
|
FIndex->updatePreamble(Path, Ctx, std::move(PP), CanonIncludes);
|
2018-11-23 01:27:08 +08:00
|
|
|
}
|
2018-09-18 18:30:44 +08:00
|
|
|
|
2018-11-23 01:27:08 +08:00
|
|
|
void onMainAST(PathRef Path, ParsedAST &AST) override {
|
|
|
|
if (FIndex)
|
2018-09-18 21:35:16 +08:00
|
|
|
FIndex->updateMain(Path, AST);
|
2018-11-23 01:27:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void onDiagnostics(PathRef File, std::vector<Diag> Diags) override {
|
|
|
|
DiagConsumer.onDiagnosticsReady(File, std::move(Diags));
|
|
|
|
}
|
|
|
|
|
2018-12-06 17:41:04 +08:00
|
|
|
void onFileUpdated(PathRef File, const TUStatus &Status) override {
|
|
|
|
DiagConsumer.onFileUpdated(File, Status);
|
|
|
|
}
|
|
|
|
|
2018-11-23 01:27:08 +08:00
|
|
|
private:
|
|
|
|
FileIndex *FIndex;
|
|
|
|
DiagnosticsConsumer &DiagConsumer;
|
|
|
|
};
|
|
|
|
} // 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;
|
|
|
|
Opts.UpdateDebounce = std::chrono::steady_clock::duration::zero(); // Faster!
|
|
|
|
Opts.StorePreamblesInMemory = true;
|
|
|
|
Opts.AsyncThreadsCount = 4; // Consistent!
|
|
|
|
return Opts;
|
|
|
|
}
|
|
|
|
|
2018-10-10 15:46:15 +08:00
|
|
|
ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB,
|
|
|
|
const FileSystemProvider &FSProvider,
|
2018-03-06 01:28:54 +08:00
|
|
|
DiagnosticsConsumer &DiagConsumer,
|
|
|
|
const Options &Opts)
|
2018-11-23 01:27:08 +08:00
|
|
|
: CDB(CDB), 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-01-22 17:39:05 +08:00
|
|
|
ClangTidyOptProvider(Opts.ClangTidyOptProvider),
|
2019-01-28 22:01:55 +08:00
|
|
|
SuggestMissingIncludes(Opts.SuggestMissingIncludes),
|
2018-10-19 23:42:23 +08:00
|
|
|
WorkspaceRoot(Opts.WorkspaceRoot),
|
2018-01-31 16:51:16 +08:00
|
|
|
PCHs(std::make_shared<PCHContainerOperations>()),
|
|
|
|
// 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.
|
[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
|
|
|
WorkScheduler(Opts.AsyncThreadsCount, Opts.StorePreamblesInMemory,
|
2018-11-23 01:27:08 +08:00
|
|
|
llvm::make_unique<UpdateIndexCallbacks>(DynamicIdx.get(),
|
|
|
|
DiagConsumer),
|
2018-08-22 20:43:17 +08:00
|
|
|
Opts.UpdateDebounce, Opts.RetentionPolicy) {
|
[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) {
|
|
|
|
MergedIdx.push_back(llvm::make_unique<MergedIndex>(Idx, this->Index));
|
|
|
|
this->Index = MergedIdx.back().get();
|
|
|
|
} else {
|
|
|
|
this->Index = Idx;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
if (Opts.StaticIndex)
|
|
|
|
AddIndex(Opts.StaticIndex);
|
|
|
|
if (Opts.BackgroundIndex) {
|
|
|
|
BackgroundIdx = llvm::make_unique<BackgroundIndex>(
|
2019-01-22 17:10:20 +08:00
|
|
|
Context::current().clone(), FSProvider, CDB,
|
2018-12-18 23:39:33 +08:00
|
|
|
BackgroundIndexStorage::createDiskBackedStorageFactory(),
|
|
|
|
Opts.BackgroundIndexRebuildPeriodMs);
|
[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,
|
2018-06-13 17:20:41 +08:00
|
|
|
WantDiagnostics WantDiags) {
|
2019-01-28 22:01:55 +08:00
|
|
|
ParseOptions Opts;
|
|
|
|
Opts.ClangTidyOpts = tidy::ClangTidyOptions::getDefaults();
|
2019-01-22 17:39:05 +08:00
|
|
|
if (ClangTidyOptProvider)
|
2019-01-28 22:01:55 +08:00
|
|
|
Opts.ClangTidyOpts = ClangTidyOptProvider->getOptions(File);
|
2019-02-06 23:24:50 +08:00
|
|
|
// FIXME: cache this.
|
|
|
|
Opts.Style =
|
|
|
|
getFormatStyleForFile(File, Contents, FSProvider.getFileSystem().get());
|
2019-01-28 22:01:55 +08:00
|
|
|
Opts.SuggestMissingIncludes = SuggestMissingIncludes;
|
2018-12-06 17:41:04 +08:00
|
|
|
// FIXME: some build systems like Bazel will take time to preparing
|
|
|
|
// environment to build the file, it would be nice if we could emit a
|
|
|
|
// "PreparingBuild" status to inform users, it is non-trivial given the
|
|
|
|
// current implementation.
|
2019-01-28 22:01:55 +08:00
|
|
|
ParseInputs Inputs;
|
|
|
|
Inputs.CompileCommand = getCompileCommand(File);
|
|
|
|
Inputs.FS = FSProvider.getFileSystem();
|
|
|
|
Inputs.Contents = Contents;
|
|
|
|
Inputs.Opts = std::move(Opts);
|
|
|
|
Inputs.Index = Index;
|
|
|
|
WorkScheduler.update(File, Inputs, WantDiags);
|
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
|
|
|
|
|
|
|
// Copy PCHs to avoid accessing this->PCHs concurrently
|
|
|
|
std::shared_ptr<PCHContainerOperations> PCHs = this->PCHs;
|
2018-03-13 07:22:35 +08:00
|
|
|
auto FS = FSProvider.getFileSystem();
|
[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
|
|
|
|
|
|
|
auto Task = [PCHs, Pos, FS, CodeCompleteOpts,
|
|
|
|
this](Path File, Callback<CodeCompleteResult> CB,
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Expected<InputsAndPreamble> IP) {
|
2018-03-16 22:30:42 +08:00
|
|
|
if (!IP)
|
|
|
|
return CB(IP.takeError());
|
2018-09-03 22:39:34 +08:00
|
|
|
if (isCancelled())
|
2019-01-07 23:45:19 +08:00
|
|
|
return CB(llvm::make_error<CancelledError>());
|
2018-03-16 22:30:42 +08:00
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Optional<SpeculativeFuzzyFind> SpecFuzzyFind;
|
[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
|
|
|
if (CodeCompleteOpts.Index && CodeCompleteOpts.SpeculativeIndexRequest) {
|
|
|
|
SpecFuzzyFind.emplace();
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> Lock(CachedCompletionFuzzyFindRequestMutex);
|
|
|
|
SpecFuzzyFind->CachedReq = CachedCompletionFuzzyFindRequestByFile[File];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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(
|
2018-10-02 18:43:55 +08:00
|
|
|
File, IP->Command, IP->Preamble, IP->Contents, Pos, FS, PCHs,
|
|
|
|
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.
|
|
|
|
WorkScheduler.runWithPreamble("CodeComplete", File, TUScheduler::Stale,
|
2018-03-15 02:31:48 +08:00
|
|
|
Bind(Task, File.str(), std::move(CB)));
|
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
|
|
|
|
2018-02-15 21:15:47 +08:00
|
|
|
auto PCHs = this->PCHs;
|
2018-03-13 07:22:35 +08:00
|
|
|
auto FS = FSProvider.getFileSystem();
|
2018-08-17 17:32:30 +08:00
|
|
|
auto *Index = this->Index;
|
|
|
|
auto Action = [Pos, FS, PCHs, Index](Path File, Callback<SignatureHelp> CB,
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Expected<InputsAndPreamble> IP) {
|
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
|
|
|
|
2018-01-31 16:51:16 +08:00
|
|
|
auto PreambleData = IP->Preamble;
|
2018-10-02 18:43:55 +08:00
|
|
|
CB(clangd::signatureHelp(File, IP->Command, PreambleData, IP->Contents, Pos,
|
|
|
|
FS, PCHs, 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,
|
2018-03-15 02:31:48 +08:00
|
|
|
Bind(Action, File.str(), std::move(CB)));
|
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())});
|
|
|
|
}
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Expected<tooling::Replacements>
|
|
|
|
ClangdServer::formatOnType(llvm::StringRef Code, PathRef File, Position Pos) {
|
2017-05-16 22:40:30 +08:00
|
|
|
// Look for the previous opening brace from the character position and
|
|
|
|
// format starting from there.
|
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();
|
2019-01-07 23:45:19 +08:00
|
|
|
size_t PreviousLBracePos =
|
|
|
|
llvm::StringRef(Code).find_last_of('{', *CursorPos);
|
|
|
|
if (PreviousLBracePos == llvm::StringRef::npos)
|
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
|
|
|
PreviousLBracePos = *CursorPos;
|
|
|
|
size_t Len = *CursorPos - PreviousLBracePos;
|
2017-05-16 22:40:30 +08:00
|
|
|
|
|
|
|
return formatCode(Code, File, {tooling::Range(PreviousLBracePos, Len)});
|
|
|
|
}
|
2017-05-16 17:38:59 +08:00
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
|
2018-03-13 07:22:35 +08:00
|
|
|
Callback<std::vector<tooling::Replacement>> CB) {
|
2018-02-15 21:15:47 +08:00
|
|
|
auto Action = [Pos](Path File, std::string NewName,
|
2018-03-13 07:22:35 +08:00
|
|
|
Callback<std::vector<tooling::Replacement>> CB,
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Expected<InputsAndAST> InpAST) {
|
2018-01-31 16:51:16 +08:00
|
|
|
if (!InpAST)
|
2018-03-13 07:22:35 +08:00
|
|
|
return CB(InpAST.takeError());
|
2018-01-31 16:51:16 +08:00
|
|
|
auto &AST = InpAST->AST;
|
|
|
|
|
|
|
|
RefactoringResultCollector ResultCollector;
|
|
|
|
const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
|
2017-11-09 19:30:04 +08:00
|
|
|
SourceLocation SourceLocationBeg =
|
[clangd] Fix unicode handling, using UTF-16 where LSP requires it.
Summary:
The Language Server Protocol unfortunately mandates that locations in files
be represented by line/column pairs, where the "column" is actually an index
into the UTF-16-encoded text of the line.
(This is because VSCode is written in JavaScript, which is UTF-16-native).
Internally clangd treats source files at UTF-8, the One True Encoding, and
generally deals with byte offsets (though there are exceptions).
Before this patch, conversions between offsets and LSP Position pretended
that Position.character was UTF-8 bytes, which is only true for ASCII lines.
Now we examine the text to convert correctly (but don't actually need to
transcode it, due to some nice details of the encodings).
The updated functions in SourceCode are the blessed way to interact with
the Position.character field, and anything else is likely to be wrong.
So I also updated the other accesses:
- CodeComplete needs a "clang-style" line/column, with column in utf-8 bytes.
This is now converted via Position -> offset -> clang line/column
(a new function is added to SourceCode.h for the second conversion).
- getBeginningOfIdentifier skipped backwards in UTF-16 space, which is will
behave badly when it splits a surrogate pair. Skipping backwards in UTF-8
coordinates gives the lexer a fighting chance of getting this right.
While here, I clarified(?) the logic comments, fixed a bug with identifiers
containing digits, simplified the signature slightly and added a test.
This seems likely to cause problems with editors that have the same bug, and
treat the protocol as if columns are UTF-8 bytes. But we can find and fix those.
Reviewers: hokein
Subscribers: klimek, ilya-biryukov, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D46035
llvm-svn: 331029
2018-04-27 19:59:28 +08:00
|
|
|
clangd::getBeginningOfIdentifier(AST, Pos, SourceMgr.getMainFileID());
|
2017-11-09 19:30:04 +08:00
|
|
|
tooling::RefactoringRuleContext Context(
|
2018-01-31 16:51:16 +08:00
|
|
|
AST.getASTContext().getSourceManager());
|
|
|
|
Context.setASTContext(AST.getASTContext());
|
2017-11-09 19:30:04 +08:00
|
|
|
auto Rename = clang::tooling::RenameOccurrences::initiate(
|
2018-02-15 21:15:47 +08:00
|
|
|
Context, SourceRange(SourceLocationBeg), NewName);
|
2018-01-31 16:51:16 +08:00
|
|
|
if (!Rename)
|
2018-03-13 07:22:35 +08:00
|
|
|
return CB(Rename.takeError());
|
2018-01-31 16:51:16 +08:00
|
|
|
|
2017-11-09 19:30:04 +08:00
|
|
|
Rename->invoke(ResultCollector, Context);
|
2018-01-31 16:51:16 +08:00
|
|
|
|
|
|
|
assert(ResultCollector.Result.hasValue());
|
|
|
|
if (!ResultCollector.Result.getValue())
|
2018-03-13 07:22:35 +08:00
|
|
|
return CB(ResultCollector.Result->takeError());
|
2018-01-31 16:51:16 +08:00
|
|
|
|
|
|
|
std::vector<tooling::Replacement> Replacements;
|
|
|
|
for (const tooling::AtomicChange &Change : ResultCollector.Result->get()) {
|
|
|
|
tooling::Replacements ChangeReps = Change.getReplacements();
|
|
|
|
for (const auto &Rep : ChangeReps) {
|
|
|
|
// FIXME: Right now we only support renaming the main file, so we
|
|
|
|
// drop replacements not for the main file. In the future, we might
|
|
|
|
// consider to support:
|
|
|
|
// * rename in any included header
|
|
|
|
// * rename only in the "main" header
|
|
|
|
// * provide an error if there are symbols we won't rename (e.g.
|
|
|
|
// std::vector)
|
|
|
|
// * rename globally in project
|
|
|
|
// * rename in open files
|
|
|
|
if (Rep.getFilePath() == File)
|
|
|
|
Replacements.push_back(Rep);
|
|
|
|
}
|
2017-11-09 19:30:04 +08:00
|
|
|
}
|
2018-03-13 07:22:35 +08:00
|
|
|
return CB(std::move(Replacements));
|
2018-01-31 16:51:16 +08:00
|
|
|
};
|
2018-02-15 21:15:47 +08:00
|
|
|
|
|
|
|
WorkScheduler.runWithAST(
|
2018-03-13 07:22:35 +08:00
|
|
|
"Rename", File, Bind(Action, File.str(), NewName.str(), std::move(CB)));
|
2017-11-09 19:30:04 +08:00
|
|
|
}
|
|
|
|
|
2019-02-01 23:09:47 +08:00
|
|
|
static llvm::Expected<Tweak::Selection>
|
|
|
|
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();
|
|
|
|
return Tweak::Selection(AST.AST, *Begin, *End);
|
|
|
|
}
|
|
|
|
|
[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) {
|
|
|
|
auto Action = [Sel](decltype(CB) CB, std::string File,
|
|
|
|
Expected<InputsAndAST> InpAST) {
|
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
2019-02-01 23:09:47 +08:00
|
|
|
auto Selection = tweakSelection(Sel, *InpAST);
|
|
|
|
if (!Selection)
|
|
|
|
return CB(Selection.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;
|
2019-02-01 23:09:47 +08:00
|
|
|
for (auto &T : prepareTweaks(*Selection))
|
[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
|
|
|
Res.push_back({T->id(), T->title()});
|
|
|
|
CB(std::move(Res));
|
|
|
|
};
|
|
|
|
|
|
|
|
WorkScheduler.runWithAST("EnumerateTweaks", File,
|
|
|
|
Bind(Action, std::move(CB), File.str()));
|
|
|
|
}
|
|
|
|
|
2019-02-01 13:41:50 +08:00
|
|
|
void ClangdServer::applyTweak(PathRef File, Range Sel, StringRef TweakID,
|
[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
|
|
|
Callback<tooling::Replacements> CB) {
|
2019-02-01 13:41:50 +08:00
|
|
|
auto Action = [Sel](decltype(CB) CB, std::string File, std::string TweakID,
|
|
|
|
Expected<InputsAndAST> InpAST) {
|
[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());
|
2019-02-01 23:09:47 +08:00
|
|
|
auto Selection = tweakSelection(Sel, *InpAST);
|
|
|
|
if (!Selection)
|
|
|
|
return CB(Selection.takeError());
|
|
|
|
auto A = prepareTweak(TweakID, *Selection);
|
[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 (!A)
|
|
|
|
return CB(A.takeError());
|
2019-02-06 23:24:50 +08:00
|
|
|
return CB((*A)->apply(*Selection, InpAST->Inputs.Opts.Style));
|
[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
|
|
|
WorkScheduler.runWithAST(
|
|
|
|
"ApplyTweak", File,
|
|
|
|
Bind(Action, std::move(CB), File.str(), TweakID.str()));
|
[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) {
|
|
|
|
auto Action = [](decltype(Callback) Callback,
|
|
|
|
llvm::Expected<InputsAndAST> InpAST) {
|
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
|
|
|
|
2018-02-23 15:54:17 +08:00
|
|
|
WorkScheduler.runWithAST("DumpAST", File, Bind(Action, std::move(Callback)));
|
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) {
|
|
|
|
auto Action = [Pos, this](decltype(CB) CB,
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Expected<InputsAndAST> InpAST) {
|
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
|
|
|
|
2018-03-13 07:22:35 +08:00
|
|
|
WorkScheduler.runWithAST("Definitions", File, Bind(Action, std::move(CB)));
|
2017-06-29 00:12:10 +08:00
|
|
|
}
|
2017-08-14 16:17:24 +08:00
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Optional<Path> ClangdServer::switchSourceHeader(PathRef Path) {
|
2017-09-28 11:14:40 +08:00
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::StringRef SourceExtensions[] = {".cpp", ".c", ".cc", ".cxx",
|
|
|
|
".c++", ".m", ".mm"};
|
|
|
|
llvm::StringRef HeaderExtensions[] = {".h", ".hh", ".hpp", ".hxx", ".inc"};
|
2017-09-28 11:14:40 +08:00
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::StringRef PathExt = llvm::sys::path::extension(Path);
|
2017-09-28 11:14:40 +08:00
|
|
|
|
|
|
|
// Lookup in a list of known extensions.
|
|
|
|
auto SourceIter =
|
2018-10-07 22:49:41 +08:00
|
|
|
llvm::find_if(SourceExtensions, [&PathExt](PathRef SourceExt) {
|
|
|
|
return SourceExt.equals_lower(PathExt);
|
|
|
|
});
|
2017-09-28 11:14:40 +08:00
|
|
|
bool IsSource = SourceIter != std::end(SourceExtensions);
|
|
|
|
|
|
|
|
auto HeaderIter =
|
2018-10-07 22:49:41 +08:00
|
|
|
llvm::find_if(HeaderExtensions, [&PathExt](PathRef HeaderExt) {
|
|
|
|
return HeaderExt.equals_lower(PathExt);
|
|
|
|
});
|
2017-09-28 11:14:40 +08:00
|
|
|
|
|
|
|
bool IsHeader = HeaderIter != std::end(HeaderExtensions);
|
|
|
|
|
2018-05-22 21:29:37 +08:00
|
|
|
// We can only switch between the known extensions.
|
2017-09-28 11:14:40 +08:00
|
|
|
if (!IsSource && !IsHeader)
|
2018-10-20 23:30:37 +08:00
|
|
|
return None;
|
2017-09-28 11:14:40 +08:00
|
|
|
|
|
|
|
// Array to lookup extensions for the switch. An opposite of where original
|
|
|
|
// extension was found.
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::ArrayRef<llvm::StringRef> NewExts;
|
2017-09-28 11:14:40 +08:00
|
|
|
if (IsSource)
|
|
|
|
NewExts = HeaderExtensions;
|
|
|
|
else
|
|
|
|
NewExts = SourceExtensions;
|
|
|
|
|
|
|
|
// Storage for the new path.
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::SmallString<128> NewPath = llvm::StringRef(Path);
|
2017-09-28 11:14:40 +08:00
|
|
|
|
|
|
|
// Instance of vfs::FileSystem, used for file existence checks.
|
2018-03-13 07:22:35 +08:00
|
|
|
auto FS = FSProvider.getFileSystem();
|
2017-09-28 11:14:40 +08:00
|
|
|
|
|
|
|
// Loop through switched extension candidates.
|
2019-01-07 23:45:19 +08:00
|
|
|
for (llvm::StringRef NewExt : NewExts) {
|
|
|
|
llvm::sys::path::replace_extension(NewPath, NewExt);
|
2017-09-28 11:14:40 +08:00
|
|
|
if (FS->exists(NewPath))
|
|
|
|
return NewPath.str().str(); // First str() to convert from SmallString to
|
|
|
|
// StringRef, second to convert from StringRef
|
|
|
|
// to std::string
|
2017-10-06 22:39:39 +08:00
|
|
|
|
2017-09-28 11:14:40 +08:00
|
|
|
// Also check NewExt in upper-case, just in case.
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::sys::path::replace_extension(NewPath, NewExt.upper());
|
2017-09-28 11:14:40 +08:00
|
|
|
if (FS->exists(NewPath))
|
|
|
|
return NewPath.str().str();
|
|
|
|
}
|
|
|
|
|
2018-10-20 23:30:37 +08:00
|
|
|
return None;
|
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.
|
2018-03-13 07:22:35 +08:00
|
|
|
auto FS = FSProvider.getFileSystem();
|
2018-06-26 20:49:09 +08:00
|
|
|
auto Style = format::getStyle(format::DefaultFormatStyle, File,
|
|
|
|
format::DefaultFallbackStyle, Code, FS.get());
|
2018-03-06 18:42:50 +08:00
|
|
|
if (!Style)
|
|
|
|
return Style.takeError();
|
|
|
|
|
|
|
|
tooling::Replacements IncludeReplaces =
|
|
|
|
format::sortIncludes(*Style, Code, Ranges, File);
|
|
|
|
auto Changed = tooling::applyAllReplacements(Code, IncludeReplaces);
|
|
|
|
if (!Changed)
|
|
|
|
return Changed.takeError();
|
|
|
|
|
|
|
|
return IncludeReplaces.merge(format::reformat(
|
|
|
|
Style.get(), *Changed,
|
|
|
|
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) {
|
2018-06-05 22:07:45 +08:00
|
|
|
auto Action = [Pos](Callback<std::vector<DocumentHighlight>> CB,
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Expected<InputsAndAST> InpAST) {
|
2018-01-31 16:51:16 +08:00
|
|
|
if (!InpAST)
|
2018-03-13 07:22:35 +08:00
|
|
|
return CB(InpAST.takeError());
|
|
|
|
CB(clangd::findDocumentHighlights(InpAST->AST, Pos));
|
2018-01-31 16:51:16 +08:00
|
|
|
};
|
2018-02-15 21:15:47 +08:00
|
|
|
|
2018-03-13 07:22:35 +08:00
|
|
|
WorkScheduler.runWithAST("Highlights", File, Bind(Action, std::move(CB)));
|
[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-01-07 23:45:19 +08:00
|
|
|
Callback<llvm::Optional<Hover>> CB) {
|
|
|
|
auto Action = [Pos](Callback<llvm::Optional<Hover>> CB,
|
|
|
|
llvm::Expected<InputsAndAST> InpAST) {
|
[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());
|
|
|
|
CB(clangd::getHover(InpAST->AST, Pos));
|
[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-03-13 07:22:35 +08:00
|
|
|
WorkScheduler.runWithAST("Hover", File, Bind(Action, std::move(CB)));
|
[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
|
|
|
}
|
|
|
|
|
2018-06-13 17:20:41 +08:00
|
|
|
tooling::CompileCommand ClangdServer::getCompileCommand(PathRef File) {
|
2018-08-28 18:57:45 +08:00
|
|
|
trace::Span Span("GetCompileCommand");
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Optional<tooling::CompileCommand> C = CDB.getCompileCommand(File);
|
2018-06-13 17:20:41 +08:00
|
|
|
if (!C) // FIXME: Suppress diagnostics? Let the user know?
|
|
|
|
C = CDB.getFallbackCommand(File);
|
|
|
|
return std::move(*C);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
std::string QueryCopy = Query;
|
|
|
|
WorkScheduler.run(
|
|
|
|
"getWorkspaceSymbols",
|
|
|
|
Bind(
|
|
|
|
[QueryCopy, Limit, this](decltype(CB) CB) {
|
|
|
|
CB(clangd::getWorkspaceSymbols(QueryCopy, Limit, Index,
|
|
|
|
WorkspaceRoot.getValueOr("")));
|
|
|
|
},
|
|
|
|
std::move(CB)));
|
[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) {
|
|
|
|
auto Action = [](Callback<std::vector<DocumentSymbol>> CB,
|
|
|
|
llvm::Expected<InputsAndAST> InpAST) {
|
2018-07-06 03:35:01 +08:00
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
|
|
|
CB(clangd::getDocumentSymbols(InpAST->AST));
|
|
|
|
};
|
|
|
|
WorkScheduler.runWithAST("documentSymbols", File,
|
|
|
|
Bind(Action, std::move(CB)));
|
|
|
|
}
|
|
|
|
|
2019-01-15 02:11:09 +08:00
|
|
|
void ClangdServer::findReferences(PathRef File, Position Pos, uint32_t Limit,
|
2018-09-05 19:53:07 +08:00
|
|
|
Callback<std::vector<Location>> CB) {
|
2019-01-15 02:11:09 +08:00
|
|
|
auto Action = [Pos, Limit, this](Callback<std::vector<Location>> CB,
|
|
|
|
llvm::Expected<InputsAndAST> InpAST) {
|
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
|
|
|
};
|
|
|
|
|
|
|
|
WorkScheduler.runWithAST("References", File, Bind(Action, std::move(CB)));
|
|
|
|
}
|
|
|
|
|
2018-11-28 00:40:46 +08:00
|
|
|
void ClangdServer::symbolInfo(PathRef File, Position Pos,
|
|
|
|
Callback<std::vector<SymbolDetails>> CB) {
|
|
|
|
auto Action = [Pos](Callback<std::vector<SymbolDetails>> CB,
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Expected<InputsAndAST> InpAST) {
|
2018-11-28 00:40:46 +08:00
|
|
|
if (!InpAST)
|
|
|
|
return CB(InpAST.takeError());
|
|
|
|
CB(clangd::getSymbolInfo(InpAST->AST, Pos));
|
|
|
|
};
|
|
|
|
|
|
|
|
WorkScheduler.runWithAST("SymbolInfo", File, Bind(Action, std::move(CB)));
|
|
|
|
}
|
|
|
|
|
2018-01-25 22:32:21 +08:00
|
|
|
std::vector<std::pair<Path, std::size_t>>
|
|
|
|
ClangdServer::getUsedBytesPerFile() const {
|
2018-01-31 16:51:16 +08:00
|
|
|
return WorkScheduler.getUsedBytesPerFile();
|
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
|