2018-01-31 16:51:16 +08:00
|
|
|
//===--- TUScheduler.h -------------------------------------------*-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
|
2018-01-31 16:51:16 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_TUSCHEDULER_H
|
|
|
|
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_TUSCHEDULER_H
|
|
|
|
|
2021-01-10 23:23:03 +08:00
|
|
|
#include "ASTSignals.h"
|
2019-09-04 15:35:00 +08:00
|
|
|
#include "Compiler.h"
|
[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
|
|
|
#include "Diagnostics.h"
|
2019-04-15 20:32:28 +08:00
|
|
|
#include "GlobalCompilationDatabase.h"
|
2019-02-05 00:19:57 +08:00
|
|
|
#include "index/CanonicalIncludes.h"
|
[clangd] Move non-clang base pieces into separate support/ lib. NFCI
Summary:
This enforces layering, reduces a sprawling clangd/ directory, and makes life
easier for embedders.
Reviewers: kbobyrev
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D79014
2020-04-28 23:49:17 +08:00
|
|
|
#include "support/Function.h"
|
2020-09-28 21:38:26 +08:00
|
|
|
#include "support/MemoryTree.h"
|
[clangd] Move non-clang base pieces into separate support/ lib. NFCI
Summary:
This enforces layering, reduces a sprawling clangd/ directory, and makes life
easier for embedders.
Reviewers: kbobyrev
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D79014
2020-04-28 23:49:17 +08:00
|
|
|
#include "support/Path.h"
|
|
|
|
#include "support/Threading.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 "llvm/ADT/Optional.h"
|
2019-07-19 21:51:01 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2018-02-08 15:37:35 +08:00
|
|
|
#include "llvm/ADT/StringMap.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 "llvm/ADT/StringRef.h"
|
2020-02-03 18:18:13 +08:00
|
|
|
#include <chrono>
|
2021-06-02 02:00:08 +08:00
|
|
|
#include <string>
|
2018-01-31 16:51:16 +08:00
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
2019-09-04 15:35:00 +08:00
|
|
|
class ParsedAST;
|
|
|
|
struct PreambleData;
|
2018-03-02 16:56:37 +08:00
|
|
|
|
2018-01-31 16:51:16 +08:00
|
|
|
/// Returns a number of a default async threads to use for TUScheduler.
|
|
|
|
/// Returned value is always >= 1 (i.e. will not cause requests to be processed
|
|
|
|
/// synchronously).
|
|
|
|
unsigned getDefaultAsyncThreadsCount();
|
|
|
|
|
|
|
|
struct InputsAndAST {
|
|
|
|
const ParseInputs &Inputs;
|
|
|
|
ParsedAST &AST;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct InputsAndPreamble {
|
2018-03-15 01:46:52 +08:00
|
|
|
llvm::StringRef Contents;
|
|
|
|
const tooling::CompileCommand &Command;
|
2020-01-04 23:28:41 +08:00
|
|
|
// This can be nullptr if no preamble is available.
|
2018-01-31 16:51:16 +08:00
|
|
|
const PreambleData *Preamble;
|
2021-01-10 23:23:03 +08:00
|
|
|
// This can be nullptr if no ASTSignals are available.
|
|
|
|
const ASTSignals *Signals;
|
2018-01-31 16:51:16 +08:00
|
|
|
};
|
|
|
|
|
2018-02-22 21:11:12 +08:00
|
|
|
/// Determines whether diagnostics should be generated for a file snapshot.
|
|
|
|
enum class WantDiagnostics {
|
|
|
|
Yes, /// Diagnostics must be generated for this snapshot.
|
|
|
|
No, /// Diagnostics must not be generated for this snapshot.
|
|
|
|
Auto, /// Diagnostics must be generated for this snapshot or a subsequent one,
|
|
|
|
/// within a bounded amount of time.
|
|
|
|
};
|
|
|
|
|
[clangd] Keep only a limited number of idle ASTs in memory
Summary:
After this commit, clangd will only keep the last 3 accessed ASTs in
memory. Preambles for each of the opened files are still kept in
memory to make completion and AST rebuilds fast.
AST rebuilds are usually fast enough, but having the last ASTs in
memory still considerably improves latency of operations like
findDefinition and documeneHighlight, which are often sent multiple
times a second when moving around the code. So keeping some of the last
accessed ASTs in memory seems like a reasonable tradeoff.
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: malaperle, arphaman, klimek, javed.absar, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D47063
llvm-svn: 333737
2018-06-01 18:08:43 +08:00
|
|
|
/// Configuration of the AST retention policy. This only covers retention of
|
|
|
|
/// *idle* ASTs. If queue has operations requiring the AST, they might be
|
|
|
|
/// kept in memory.
|
|
|
|
struct ASTRetentionPolicy {
|
|
|
|
/// Maximum number of ASTs to be retained in memory when there are no pending
|
|
|
|
/// requests for them.
|
|
|
|
unsigned MaxRetainedASTs = 3;
|
|
|
|
};
|
|
|
|
|
2020-02-04 22:41:39 +08:00
|
|
|
/// Clangd may wait after an update to see if another one comes along.
|
|
|
|
/// This is so we rebuild once the user stops typing, not when they start.
|
|
|
|
/// Debounce may be disabled/interrupted if we must build this version.
|
|
|
|
/// The debounce time is responsive to user preferences and rebuild time.
|
|
|
|
/// In the future, we could also consider different types of edits.
|
|
|
|
struct DebouncePolicy {
|
|
|
|
using clock = std::chrono::steady_clock;
|
|
|
|
|
|
|
|
/// The minimum time that we always debounce for.
|
|
|
|
clock::duration Min = /*zero*/ {};
|
|
|
|
/// The maximum time we may debounce for.
|
|
|
|
clock::duration Max = /*zero*/ {};
|
|
|
|
/// Target debounce, as a fraction of file rebuild time.
|
|
|
|
/// e.g. RebuildRatio = 2, recent builds took 200ms => debounce for 400ms.
|
|
|
|
float RebuildRatio = 1;
|
|
|
|
|
|
|
|
/// Compute the time to debounce based on this policy and recent build times.
|
|
|
|
clock::duration compute(llvm::ArrayRef<clock::duration> History) const;
|
|
|
|
/// A policy that always returns the same duration, useful for tests.
|
|
|
|
static DebouncePolicy fixed(clock::duration);
|
|
|
|
};
|
|
|
|
|
2020-03-18 02:08:23 +08:00
|
|
|
enum class PreambleAction {
|
|
|
|
Idle,
|
|
|
|
Building,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ASTAction {
|
|
|
|
enum Kind {
|
|
|
|
Queued, // The action is pending in the thread task queue to be run.
|
|
|
|
RunningAction, // Started running actions on the TU.
|
|
|
|
Building, // The AST is being built.
|
2018-12-06 17:41:04 +08:00
|
|
|
Idle, // Indicates the worker thread is idle, and ready to run any upcoming
|
|
|
|
// actions.
|
|
|
|
};
|
2020-03-18 02:08:23 +08:00
|
|
|
ASTAction() = default;
|
|
|
|
ASTAction(Kind K, llvm::StringRef Name) : K(K), Name(Name) {}
|
|
|
|
Kind K = ASTAction::Idle;
|
2018-12-06 17:41:04 +08:00
|
|
|
/// The name of the action currently running, e.g. Update, GoToDef, Hover.
|
|
|
|
/// Empty if we are in the idle state.
|
|
|
|
std::string Name;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Internal status of the TU in TUScheduler.
|
|
|
|
struct TUStatus {
|
|
|
|
struct BuildDetails {
|
|
|
|
/// Indicates whether clang failed to build the TU.
|
|
|
|
bool BuildFailed = false;
|
|
|
|
/// Indicates whether we reused the prebuilt AST.
|
|
|
|
bool ReuseAST = false;
|
|
|
|
};
|
2018-12-20 23:39:12 +08:00
|
|
|
/// Serialize this to an LSP file status item.
|
|
|
|
FileStatus render(PathRef File) const;
|
2018-12-06 17:41:04 +08:00
|
|
|
|
2020-03-18 02:08:23 +08:00
|
|
|
PreambleAction PreambleActivity = PreambleAction::Idle;
|
|
|
|
ASTAction ASTActivity;
|
|
|
|
/// Stores status of the last build for the translation unit.
|
2018-12-06 17:41:04 +08:00
|
|
|
BuildDetails Details;
|
|
|
|
};
|
|
|
|
|
[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
|
|
|
class ParsingCallbacks {
|
|
|
|
public:
|
|
|
|
virtual ~ParsingCallbacks() = default;
|
|
|
|
|
|
|
|
/// Called on the AST that was built for emitting the preamble. The built AST
|
|
|
|
/// contains only AST nodes from the #include directives at the start of the
|
|
|
|
/// file. AST node in the current file should be observed on onMainAST call.
|
[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
|
|
|
virtual void onPreambleAST(PathRef Path, llvm::StringRef Version,
|
2021-12-15 09:13:26 +08:00
|
|
|
ASTContext &Ctx, Preprocessor &PP,
|
2019-02-05 00:19:57 +08:00
|
|
|
const CanonicalIncludes &) {}
|
2019-07-19 21:51:01 +08:00
|
|
|
|
|
|
|
/// The argument function is run under the critical section guarding against
|
|
|
|
/// races when closing the files.
|
|
|
|
using PublishFn = llvm::function_ref<void(llvm::function_ref<void()>)>;
|
[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
|
|
|
/// Called on the AST built for the file itself. Note that preamble AST nodes
|
|
|
|
/// are not deserialized and should be processed in the onPreambleAST call
|
|
|
|
/// instead.
|
|
|
|
/// The \p AST always contains all AST nodes for the main file itself, and
|
|
|
|
/// only a portion of the AST nodes deserialized from the preamble. Note that
|
|
|
|
/// some nodes from the preamble may have been deserialized and may also be
|
|
|
|
/// accessed from the main file AST, e.g. redecls of functions from preamble,
|
|
|
|
/// etc. Clients are expected to process only the AST nodes from the main file
|
|
|
|
/// in this callback (obtained via ParsedAST::getLocalTopLevelDecls) to obtain
|
|
|
|
/// optimal performance.
|
2019-07-19 21:51:01 +08:00
|
|
|
///
|
2021-01-28 08:16:47 +08:00
|
|
|
/// When information about the file (e.g. diagnostics) is
|
2019-07-19 21:51:01 +08:00
|
|
|
/// published to clients, this should be wrapped in Publish, e.g.
|
|
|
|
/// void onMainAST(...) {
|
2021-01-28 08:16:47 +08:00
|
|
|
/// Diags = renderDiagnostics();
|
|
|
|
/// Publish([&] { notifyDiagnostics(Path, Diags); });
|
2019-07-19 21:51:01 +08:00
|
|
|
/// }
|
|
|
|
/// This guarantees that clients will see results in the correct sequence if
|
|
|
|
/// the file is concurrently closed and/or reopened. (The lambda passed to
|
|
|
|
/// Publish() may never run in this case).
|
|
|
|
virtual void onMainAST(PathRef Path, ParsedAST &AST, PublishFn Publish) {}
|
2018-12-06 17:41:04 +08:00
|
|
|
|
[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
|
|
|
/// Called whenever the AST fails to build. \p Diags will have the diagnostics
|
|
|
|
/// that led to failure.
|
[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
|
|
|
virtual void onFailedAST(PathRef Path, llvm::StringRef Version,
|
|
|
|
std::vector<Diag> Diags, PublishFn Publish) {}
|
[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
|
|
|
/// Called whenever the TU status is updated.
|
|
|
|
virtual void onFileUpdated(PathRef File, const TUStatus &Status) {}
|
2021-05-19 19:45:44 +08:00
|
|
|
|
|
|
|
/// Preamble for the TU have changed. This might imply new semantics (e.g.
|
|
|
|
/// different highlightings). Any actions on the file are guranteed to see new
|
|
|
|
/// preamble after the callback.
|
|
|
|
virtual void onPreamblePublished(PathRef File) {}
|
[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-01-31 16:51:16 +08:00
|
|
|
/// Handles running tasks for ClangdServer and managing the resources (e.g.,
|
|
|
|
/// preambles and ASTs) for opened files.
|
|
|
|
/// TUScheduler is not thread-safe, only one thread should be providing updates
|
|
|
|
/// and scheduling tasks.
|
|
|
|
/// Callbacks are run on a threadpool and it's appropriate to do slow work in
|
2018-02-19 17:56:28 +08:00
|
|
|
/// them. Each task has a name, used for tracing (should be UpperCamelCase).
|
2018-01-31 16:51:16 +08:00
|
|
|
class TUScheduler {
|
|
|
|
public:
|
2020-02-03 18:18:13 +08:00
|
|
|
struct Options {
|
|
|
|
/// Number of concurrent actions.
|
|
|
|
/// Governs per-file worker threads and threads spawned for other tasks.
|
|
|
|
/// (This does not prevent threads being spawned, but rather blocks them).
|
|
|
|
/// If 0, executes actions synchronously on the calling thread.
|
|
|
|
unsigned AsyncThreadsCount = getDefaultAsyncThreadsCount();
|
|
|
|
|
|
|
|
/// Cache (large) preamble data in RAM rather than temporary files on disk.
|
|
|
|
bool StorePreamblesInMemory = false;
|
|
|
|
|
|
|
|
/// Time to wait after an update to see if another one comes along.
|
|
|
|
/// This tries to ensure we rebuild once the user stops typing.
|
2020-02-04 22:41:39 +08:00
|
|
|
DebouncePolicy UpdateDebounce;
|
2020-02-03 18:18:13 +08:00
|
|
|
|
|
|
|
/// Determines when to keep idle ASTs in memory for future use.
|
|
|
|
ASTRetentionPolicy RetentionPolicy;
|
2020-04-08 03:18:00 +08:00
|
|
|
|
2020-07-03 05:09:25 +08:00
|
|
|
/// Used to create a context that wraps each single operation.
|
|
|
|
/// Typically to inject per-file configuration.
|
|
|
|
/// If the path is empty, context sholud be "generic".
|
|
|
|
std::function<Context(PathRef)> ContextProvider;
|
2020-02-03 18:18:13 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
TUScheduler(const GlobalCompilationDatabase &CDB, const Options &Opts,
|
|
|
|
std::unique_ptr<ParsingCallbacks> ASTCallbacks = nullptr);
|
2018-02-08 15:37:35 +08:00
|
|
|
~TUScheduler();
|
2018-01-31 16:51:16 +08:00
|
|
|
|
2020-04-14 04:07:12 +08:00
|
|
|
struct FileStats {
|
2020-09-28 21:38:26 +08:00
|
|
|
std::size_t UsedBytesAST = 0;
|
|
|
|
std::size_t UsedBytesPreamble = 0;
|
2020-04-14 04:07:12 +08:00
|
|
|
unsigned PreambleBuilds = 0;
|
|
|
|
unsigned ASTBuilds = 0;
|
|
|
|
};
|
|
|
|
/// Returns resources used for each of the currently open files.
|
|
|
|
/// Results are inherently racy as they measure activity of other threads.
|
|
|
|
llvm::StringMap<FileStats> fileStats() const;
|
2018-01-31 16:51:16 +08:00
|
|
|
|
[clangd] Keep only a limited number of idle ASTs in memory
Summary:
After this commit, clangd will only keep the last 3 accessed ASTs in
memory. Preambles for each of the opened files are still kept in
memory to make completion and AST rebuilds fast.
AST rebuilds are usually fast enough, but having the last ASTs in
memory still considerably improves latency of operations like
findDefinition and documeneHighlight, which are often sent multiple
times a second when moving around the code. So keeping some of the last
accessed ASTs in memory seems like a reasonable tradeoff.
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: malaperle, arphaman, klimek, javed.absar, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D47063
llvm-svn: 333737
2018-06-01 18:08:43 +08:00
|
|
|
/// Returns a list of files with ASTs currently stored in memory. This method
|
|
|
|
/// is not very reliable and is only used for test. E.g., the results will not
|
|
|
|
/// contain files that currently run something over their AST.
|
|
|
|
std::vector<Path> getFilesWithCachedAST() const;
|
|
|
|
|
2019-07-12 18:18:42 +08:00
|
|
|
/// Schedule an update for \p File.
|
|
|
|
/// The compile command in \p Inputs is ignored; worker queries CDB to get
|
|
|
|
/// the actual compile command.
|
2019-04-15 20:32:28 +08:00
|
|
|
/// If diagnostics are requested (Yes), and the context is cancelled
|
|
|
|
/// before they are prepared, they may be skipped if eventual-consistency
|
|
|
|
/// permits it (i.e. WantDiagnostics is downgraded to Auto).
|
2019-07-12 18:18:42 +08:00
|
|
|
/// Returns true if the file was not previously tracked.
|
|
|
|
bool update(PathRef File, ParseInputs Inputs, WantDiagnostics WD);
|
2018-01-31 16:51:16 +08:00
|
|
|
|
|
|
|
/// Remove \p File from the list of tracked files and schedule removal of its
|
[clangd] Cleanup: make diagnostics callbacks from TUScheduler non-racy
Summary:
Previously, removeDoc followed by an addDoc to TUScheduler resulted in
racy diagnostic responses, i.e. the old dianostics could be delivered
to the client after the new ones by TUScheduler.
To workaround this, we tracked a version number in ClangdServer and
discarded stale diagnostics. After this commit, the TUScheduler will
stop delivering diagnostics for removed files and the workaround in
ClangdServer is not required anymore.
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: javed.absar, ioeric, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D54829
llvm-svn: 347468
2018-11-22 23:39:54 +08:00
|
|
|
/// resources. Pending diagnostics for closed files may not be delivered, even
|
|
|
|
/// if requested with WantDiags::Auto or WantDiags::Yes.
|
2018-02-08 15:37:35 +08:00
|
|
|
void remove(PathRef File);
|
2018-01-31 16:51:16 +08:00
|
|
|
|
2018-10-25 22:19:14 +08:00
|
|
|
/// Schedule an async task with no dependencies.
|
2020-07-03 05:09:25 +08:00
|
|
|
/// Path may be empty (it is used only to set the Context).
|
|
|
|
void run(llvm::StringRef Name, llvm::StringRef Path,
|
|
|
|
llvm::unique_function<void()> Action);
|
2018-10-25 22:19:14 +08:00
|
|
|
|
2021-01-26 05:56:03 +08:00
|
|
|
/// Similar to run, except the task is expected to be quick.
|
|
|
|
/// This function will not honor AsyncThreadsCount (except
|
|
|
|
/// if threading is disabled with AsyncThreadsCount=0)
|
|
|
|
/// It is intended to run quick tasks that need to run ASAP
|
|
|
|
void runQuick(llvm::StringRef Name, llvm::StringRef Path,
|
|
|
|
llvm::unique_function<void()> Action);
|
|
|
|
|
[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
|
|
|
/// Defines how a runWithAST action is implicitly cancelled by other actions.
|
|
|
|
enum ASTActionInvalidation {
|
|
|
|
/// The request will run unless explicitly cancelled.
|
|
|
|
NoInvalidation,
|
|
|
|
/// The request will be implicitly cancelled by a subsequent update().
|
|
|
|
/// (Only if the request was not yet cancelled).
|
|
|
|
/// Useful for requests that are generated by clients, without any explicit
|
|
|
|
/// user action. These can otherwise e.g. force every version to be built.
|
|
|
|
InvalidateOnUpdate,
|
|
|
|
};
|
|
|
|
|
2018-01-31 16:51:16 +08:00
|
|
|
/// Schedule an async read of the AST. \p Action will be called when AST is
|
|
|
|
/// ready. The AST passed to \p Action refers to the version of \p File
|
|
|
|
/// tracked at the time of the call, even if new updates are received before
|
|
|
|
/// \p Action is executed.
|
|
|
|
/// If an error occurs during processing, it is forwarded to the \p Action
|
|
|
|
/// callback.
|
2020-03-05 08:04:44 +08:00
|
|
|
/// If the context is cancelled before the AST is ready, or the invalidation
|
|
|
|
/// policy is triggered, the callback will receive a CancelledError.
|
2018-02-19 17:56:28 +08:00
|
|
|
void runWithAST(llvm::StringRef Name, PathRef File,
|
[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
|
|
|
Callback<InputsAndAST> Action,
|
|
|
|
ASTActionInvalidation = NoInvalidation);
|
2018-01-31 16:51:16 +08:00
|
|
|
|
2018-08-30 23:07:34 +08:00
|
|
|
/// Controls whether preamble reads wait for the preamble to be up-to-date.
|
|
|
|
enum PreambleConsistency {
|
|
|
|
/// The preamble may be generated from an older version of the file.
|
|
|
|
/// Reading from locations in the preamble may cause files to be re-read.
|
|
|
|
/// This gives callers two options:
|
|
|
|
/// - validate that the preamble is still valid, and only use it if so
|
|
|
|
/// - accept that the preamble contents may be outdated, and try to avoid
|
|
|
|
/// reading source code from headers.
|
|
|
|
/// This is the fastest option, usually a preamble is available immediately.
|
|
|
|
Stale,
|
[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
|
|
|
/// Besides accepting stale preamble, this also allow preamble to be absent
|
|
|
|
/// (not ready or failed to build).
|
|
|
|
StaleOrAbsent,
|
2018-08-30 23:07:34 +08:00
|
|
|
};
|
[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
|
|
|
|
2018-08-30 23:07:34 +08:00
|
|
|
/// Schedule an async read of the preamble.
|
[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
|
|
|
/// If there's no up-to-date preamble, we follow the PreambleConsistency
|
|
|
|
/// policy.
|
2018-08-30 23:07:34 +08:00
|
|
|
/// If an error occurs, it is forwarded to the \p Action callback.
|
[clangd] Respect task cancellation in TUScheduler.
Summary:
- Reads are never executed if canceled before ready-to run.
In practice, we finalize cancelled reads eagerly and out-of-order.
- Cancelled reads don't prevent prior updates from being elided, as they don't
actually depend on the result of the update.
- Updates are downgraded from WantDiagnostics::Yes to WantDiagnostics::Auto when
cancelled, which allows them to be elided when all dependent reads are
cancelled and there are subsequent writes. (e.g. when the queue is backed up
with cancelled requests).
The queue operations aren't optimal (we scan the whole queue for cancelled
tasks every time the scheduler runs, and check cancellation twice in the end).
However I believe these costs are still trivial in practice (compared to any
AST operation) and the logic can be cleanly separated from the rest of the
scheduler.
Reviewers: ilya-biryukov
Subscribers: javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D54746
llvm-svn: 347450
2018-11-22 18:22:16 +08:00
|
|
|
/// Context cancellation is ignored and should be handled by the Action.
|
|
|
|
/// (In practice, the Action is almost always executed immediately).
|
2018-03-13 07:22:35 +08:00
|
|
|
void runWithPreamble(llvm::StringRef Name, PathRef File,
|
2018-08-30 23:07:34 +08:00
|
|
|
PreambleConsistency Consistency,
|
2018-03-13 07:22:35 +08:00
|
|
|
Callback<InputsAndPreamble> Action);
|
2018-01-31 16:51:16 +08:00
|
|
|
|
2018-02-13 16:59:23 +08:00
|
|
|
/// Wait until there are no scheduled or running tasks.
|
|
|
|
/// Mostly useful for synchronizing tests.
|
|
|
|
bool blockUntilIdle(Deadline D) const;
|
|
|
|
|
2018-01-31 16:51:16 +08:00
|
|
|
private:
|
2018-02-08 15:37:35 +08:00
|
|
|
/// This class stores per-file data in the Files map.
|
|
|
|
struct FileData;
|
2018-01-31 16:51:16 +08:00
|
|
|
|
[clangd] Keep only a limited number of idle ASTs in memory
Summary:
After this commit, clangd will only keep the last 3 accessed ASTs in
memory. Preambles for each of the opened files are still kept in
memory to make completion and AST rebuilds fast.
AST rebuilds are usually fast enough, but having the last ASTs in
memory still considerably improves latency of operations like
findDefinition and documeneHighlight, which are often sent multiple
times a second when moving around the code. So keeping some of the last
accessed ASTs in memory seems like a reasonable tradeoff.
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: malaperle, arphaman, klimek, javed.absar, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D47063
llvm-svn: 333737
2018-06-01 18:08:43 +08:00
|
|
|
public:
|
|
|
|
/// Responsible for retaining and rebuilding idle ASTs. An implementation is
|
|
|
|
/// an LRU cache.
|
|
|
|
class ASTCache;
|
2021-02-24 09:43:53 +08:00
|
|
|
/// Tracks headers included by open files, to get known-good compile commands.
|
|
|
|
class HeaderIncluderCache;
|
[clangd] Keep only a limited number of idle ASTs in memory
Summary:
After this commit, clangd will only keep the last 3 accessed ASTs in
memory. Preambles for each of the opened files are still kept in
memory to make completion and AST rebuilds fast.
AST rebuilds are usually fast enough, but having the last ASTs in
memory still considerably improves latency of operations like
findDefinition and documeneHighlight, which are often sent multiple
times a second when moving around the code. So keeping some of the last
accessed ASTs in memory seems like a reasonable tradeoff.
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: malaperle, arphaman, klimek, javed.absar, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D47063
llvm-svn: 333737
2018-06-01 18:08:43 +08:00
|
|
|
|
2018-08-09 17:05:45 +08:00
|
|
|
// The file being built/processed in the current thread. This is a hack in
|
|
|
|
// order to get the file name into the index implementations. Do not depend on
|
|
|
|
// this inside clangd.
|
|
|
|
// FIXME: remove this when there is proper index support via build system
|
|
|
|
// integration.
|
2020-07-03 05:09:25 +08:00
|
|
|
// FIXME: move to ClangdServer via createProcessingContext.
|
2018-08-09 17:05:45 +08:00
|
|
|
static llvm::Optional<llvm::StringRef> getFileBeingProcessedInContext();
|
|
|
|
|
2020-09-28 21:38:26 +08:00
|
|
|
void profile(MemoryTree &MT) const;
|
|
|
|
|
[clangd] Keep only a limited number of idle ASTs in memory
Summary:
After this commit, clangd will only keep the last 3 accessed ASTs in
memory. Preambles for each of the opened files are still kept in
memory to make completion and AST rebuilds fast.
AST rebuilds are usually fast enough, but having the last ASTs in
memory still considerably improves latency of operations like
findDefinition and documeneHighlight, which are often sent multiple
times a second when moving around the code. So keeping some of the last
accessed ASTs in memory seems like a reasonable tradeoff.
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: malaperle, arphaman, klimek, javed.absar, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D47063
llvm-svn: 333737
2018-06-01 18:08:43 +08:00
|
|
|
private:
|
2021-01-26 05:56:03 +08:00
|
|
|
void runWithSemaphore(llvm::StringRef Name, llvm::StringRef Path,
|
|
|
|
llvm::unique_function<void()> Action, Semaphore &Sem);
|
|
|
|
|
2019-04-15 20:32:28 +08:00
|
|
|
const GlobalCompilationDatabase &CDB;
|
2020-07-15 02:24:32 +08:00
|
|
|
Options Opts;
|
2018-09-04 00:37:59 +08:00
|
|
|
std::unique_ptr<ParsingCallbacks> Callbacks; // not nullptr
|
2018-02-08 15:37:35 +08:00
|
|
|
Semaphore Barrier;
|
2021-01-26 05:56:03 +08:00
|
|
|
Semaphore QuickRunBarrier;
|
2018-02-08 15:37:35 +08:00
|
|
|
llvm::StringMap<std::unique_ptr<FileData>> Files;
|
[clangd] Keep only a limited number of idle ASTs in memory
Summary:
After this commit, clangd will only keep the last 3 accessed ASTs in
memory. Preambles for each of the opened files are still kept in
memory to make completion and AST rebuilds fast.
AST rebuilds are usually fast enough, but having the last ASTs in
memory still considerably improves latency of operations like
findDefinition and documeneHighlight, which are often sent multiple
times a second when moving around the code. So keeping some of the last
accessed ASTs in memory seems like a reasonable tradeoff.
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: malaperle, arphaman, klimek, javed.absar, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D47063
llvm-svn: 333737
2018-06-01 18:08:43 +08:00
|
|
|
std::unique_ptr<ASTCache> IdleASTs;
|
2021-02-24 09:43:53 +08:00
|
|
|
std::unique_ptr<HeaderIncluderCache> HeaderIncluders;
|
2018-02-08 15:37:35 +08:00
|
|
|
// None when running tasks synchronously and non-None when running tasks
|
|
|
|
// asynchronously.
|
2018-02-13 16:59:23 +08:00
|
|
|
llvm::Optional<AsyncTaskRunner> PreambleTasks;
|
|
|
|
llvm::Optional<AsyncTaskRunner> WorkerThreads;
|
2021-06-02 02:00:08 +08:00
|
|
|
// Used to create contexts for operations that are not bound to a particular
|
|
|
|
// file (e.g. index queries).
|
|
|
|
std::string LastActiveFile;
|
2018-01-31 16:51:16 +08:00
|
|
|
};
|
2018-08-09 17:05:45 +08:00
|
|
|
|
2018-01-31 16:51:16 +08:00
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|
|
|
|
|
|
|
|
#endif
|