clang-tools  11.0.0git
ClangdServer.h
Go to the documentation of this file.
1 //===--- ClangdServer.h - Main clangd server code ----------------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDSERVER_H
10 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDSERVER_H
11 
12 #include "../clang-tidy/ClangTidyOptions.h"
13 #include "CodeComplete.h"
14 #include "ConfigProvider.h"
16 #include "Hover.h"
17 #include "Protocol.h"
18 #include "SemanticHighlighting.h"
19 #include "TUScheduler.h"
20 #include "XRefs.h"
21 #include "index/Background.h"
22 #include "index/FileIndex.h"
23 #include "index/Index.h"
24 #include "refactor/Rename.h"
25 #include "refactor/Tweak.h"
26 #include "support/Cancellation.h"
27 #include "support/Function.h"
28 #include "support/ThreadsafeFS.h"
29 #include "clang/Tooling/CompilationDatabase.h"
30 #include "clang/Tooling/Core/Replacement.h"
31 #include "llvm/ADT/FunctionExtras.h"
32 #include "llvm/ADT/IntrusiveRefCntPtr.h"
33 #include "llvm/ADT/Optional.h"
34 #include "llvm/ADT/StringRef.h"
35 #include <functional>
36 #include <future>
37 #include <string>
38 #include <type_traits>
39 #include <utility>
40 
41 namespace clang {
42 namespace clangd {
43 
44 /// When set, used by ClangdServer to get clang-tidy options for each particular
45 /// file. Must be thread-safe. We use this instead of ClangTidyOptionsProvider
46 /// to allow reading tidy configs from the VFS used for parsing.
47 using ClangTidyOptionsBuilder = std::function<tidy::ClangTidyOptions(
48  llvm::vfs::FileSystem &, llvm::StringRef /*File*/)>;
49 
50 /// Manages a collection of source files and derived data (ASTs, indexes),
51 /// and provides language-aware features such as code completion.
52 ///
53 /// The primary client is ClangdLSPServer which exposes these features via
54 /// the Language Server protocol. ClangdServer may also be embedded directly,
55 /// though its API is not stable over time.
56 ///
57 /// ClangdServer should be used from a single thread. Many potentially-slow
58 /// operations have asynchronous APIs and deliver their results on another
59 /// thread.
60 /// Such operations support cancellation: if the caller sets up a cancelable
61 /// context, many operations will notice cancellation and fail early.
62 /// (ClangdLSPServer uses this to implement $/cancelRequest).
63 class ClangdServer {
64 public:
65  /// Interface with hooks for users of ClangdServer to be notified of events.
66  class Callbacks {
67  public:
68  virtual ~Callbacks() = default;
69 
70  /// Called by ClangdServer when \p Diagnostics for \p File are ready.
71  /// May be called concurrently for separate files, not for a single file.
72  virtual void onDiagnosticsReady(PathRef File, llvm::StringRef Version,
73  std::vector<Diag> Diagnostics) {}
74  /// Called whenever the file status is updated.
75  /// May be called concurrently for separate files, not for a single file.
76  virtual void onFileUpdated(PathRef File, const TUStatus &Status) {}
77 
78  /// Called by ClangdServer when some \p Highlightings for \p File are ready.
79  /// May be called concurrently for separate files, not for a single file.
80  virtual void
81  onHighlightingsReady(PathRef File, llvm::StringRef Version,
82  std::vector<HighlightingToken> Highlightings) {}
83 
84  /// Called when background indexing tasks are enqueued/started/completed.
85  /// Not called concurrently.
86  virtual void
88  };
89 
90  struct Options {
91  /// To process requests asynchronously, ClangdServer spawns worker threads.
92  /// If this is zero, no threads are spawned. All work is done on the calling
93  /// thread, and callbacks are invoked before "async" functions return.
94  unsigned AsyncThreadsCount = getDefaultAsyncThreadsCount();
95 
96  /// AST caching policy. The default is to keep up to 3 ASTs in memory.
98 
99  /// Cached preambles are potentially large. If false, store them on disk.
100  bool StorePreamblesInMemory = true;
101  /// Reuse even stale preambles, and rebuild them in the background.
102  /// This improves latency at the cost of accuracy.
103  bool AsyncPreambleBuilds = true;
104 
105  /// If true, ClangdServer builds a dynamic in-memory index for symbols in
106  /// opened files and uses the index to augment code completion results.
107  bool BuildDynamicSymbolIndex = false;
108  /// Use a heavier and faster in-memory index implementation.
109  bool HeavyweightDynamicSymbolIndex = true;
110  /// If true, ClangdServer automatically indexes files in the current project
111  /// on background threads. The index is stored in the project root.
112  bool BackgroundIndex = false;
113 
114  /// If set, use this index to augment code completion results.
115  SymbolIndex *StaticIndex = nullptr;
116 
117  /// If set, queried to obtain the configuration to handle each request.
118  config::Provider *ConfigProvider = nullptr;
119 
120  /// If set, enable clang-tidy in clangd and use to it get clang-tidy
121  /// configurations for a particular file.
122  /// Clangd supports only a small subset of ClangTidyOptions, these options
123  /// (Checks, CheckOptions) are about which clang-tidy checks will be
124  /// enabled.
126 
127  /// If true, turn on the `-frecovery-ast` clang flag.
128  bool BuildRecoveryAST = true;
129 
130  /// If true, turn on the `-frecovery-ast-type` clang flag.
131  bool PreserveRecoveryASTType = false;
132 
133  /// Clangd's workspace root. Relevant for "workspace" operations not bound
134  /// to a particular file.
135  /// FIXME: If not set, should use the current working directory.
136  llvm::Optional<std::string> WorkspaceRoot;
137 
138  /// The resource directory is used to find internal headers, overriding
139  /// defaults and -resource-dir compiler flag).
140  /// If None, ClangdServer calls CompilerInvocation::GetResourcePath() to
141  /// obtain the standard resource directory.
142  llvm::Optional<std::string> ResourceDir = llvm::None;
143 
144  /// Time to wait after a new file version before computing diagnostics.
145  DebouncePolicy UpdateDebounce = DebouncePolicy{
146  /*Min=*/std::chrono::milliseconds(50),
147  /*Max=*/std::chrono::milliseconds(500),
148  /*RebuildRatio=*/1,
149  };
150 
151  bool SuggestMissingIncludes = false;
152 
153  /// Clangd will execute compiler drivers matching one of these globs to
154  /// fetch system include path.
155  std::vector<std::string> QueryDriverGlobs;
156 
157  /// Enable notification-based semantic highlighting.
158  bool TheiaSemanticHighlighting = false;
159 
160  /// Returns true if the tweak should be enabled.
161  std::function<bool(const Tweak &)> TweakFilter = [](const Tweak &T) {
162  return !T.hidden(); // only enable non-hidden tweaks.
163  };
164 
165  explicit operator TUScheduler::Options() const;
166  };
167  // Sensible default options for use in tests.
168  // Features like indexing must be enabled if desired.
169  static Options optsForTest();
170 
171  /// Creates a new ClangdServer instance.
172  ///
173  /// ClangdServer uses \p CDB to obtain compilation arguments for parsing. Note
174  /// that ClangdServer only obtains compilation arguments once for each newly
175  /// added file (i.e., when processing a first call to addDocument) and reuses
176  /// those arguments for subsequent reparses. However, ClangdServer will check
177  /// if compilation arguments changed on calls to forceReparse().
178  ClangdServer(const GlobalCompilationDatabase &CDB, const ThreadsafeFS &TFS,
179  const Options &Opts, Callbacks *Callbacks = nullptr);
180 
181  /// Add a \p File to the list of tracked C++ files or update the contents if
182  /// \p File is already tracked. Also schedules parsing of the AST for it on a
183  /// separate thread. When the parsing is complete, DiagConsumer passed in
184  /// constructor will receive onDiagnosticsReady callback.
185  /// Version identifies this snapshot and is propagated to ASTs, preambles,
186  /// diagnostics etc built from it.
187  void addDocument(PathRef File, StringRef Contents,
188  llvm::StringRef Version = "null",
190  bool ForceRebuild = false);
191 
192  /// Remove \p File from list of tracked files, schedule a request to free
193  /// resources associated with it. Pending diagnostics for closed files may not
194  /// be delivered, even if requested with WantDiags::Auto or WantDiags::Yes.
195  /// An empty set of diagnostics will be delivered, with Version = "".
196  void removeDocument(PathRef File);
197 
198  /// Run code completion for \p File at \p Pos.
199  /// Request is processed asynchronously.
200  ///
201  /// This method should only be called for currently tracked files. However, it
202  /// is safe to call removeDocument for \p File after this method returns, even
203  /// while returned future is not yet ready.
204  /// A version of `codeComplete` that runs \p Callback on the processing thread
205  /// when codeComplete results become available.
206  void codeComplete(PathRef File, Position Pos,
207  const clangd::CodeCompleteOptions &Opts,
209 
210  /// Provide signature help for \p File at \p Pos. This method should only be
211  /// called for tracked files.
213 
214  /// Find declaration/definition locations of symbol at a specified position.
215  void locateSymbolAt(PathRef File, Position Pos,
216  Callback<std::vector<LocatedSymbol>> CB);
217 
218  /// Switch to a corresponding source file when given a header file, and vice
219  /// versa.
221  Callback<llvm::Optional<clangd::Path>> CB);
222 
223  /// Get document highlights for a given position.
224  void findDocumentHighlights(PathRef File, Position Pos,
225  Callback<std::vector<DocumentHighlight>> CB);
226 
227  /// Get code hover for a given position.
228  void findHover(PathRef File, Position Pos,
229  Callback<llvm::Optional<HoverInfo>> CB);
230 
231  /// Get information about type hierarchy for a given position.
232  void typeHierarchy(PathRef File, Position Pos, int Resolve,
233  TypeHierarchyDirection Direction,
234  Callback<llvm::Optional<TypeHierarchyItem>> CB);
235 
236  /// Resolve type hierarchy item in the given direction.
237  void resolveTypeHierarchy(TypeHierarchyItem Item, int Resolve,
238  TypeHierarchyDirection Direction,
239  Callback<llvm::Optional<TypeHierarchyItem>> CB);
240 
241  /// Retrieve the top symbols from the workspace matching a query.
242  void workspaceSymbols(StringRef Query, int Limit,
243  Callback<std::vector<SymbolInformation>> CB);
244 
245  /// Retrieve the symbols within the specified file.
246  void documentSymbols(StringRef File,
247  Callback<std::vector<DocumentSymbol>> CB);
248 
249  /// Retrieve locations for symbol references.
250  void findReferences(PathRef File, Position Pos, uint32_t Limit,
252 
253  /// Run formatting for \p Rng inside \p File with content \p Code.
254  void formatRange(PathRef File, StringRef Code, Range Rng,
256 
257  /// Run formatting for the whole \p File with content \p Code.
258  void formatFile(PathRef File, StringRef Code,
260 
261  /// Run formatting after \p TriggerText was typed at \p Pos in \p File with
262  /// content \p Code.
263  void formatOnType(PathRef File, StringRef Code, Position Pos,
264  StringRef TriggerText, Callback<std::vector<TextEdit>> CB);
265 
266  /// Test the validity of a rename operation.
267  void prepareRename(PathRef File, Position Pos,
268  const RenameOptions &RenameOpts,
269  Callback<llvm::Optional<Range>> CB);
270 
271  /// Rename all occurrences of the symbol at the \p Pos in \p File to
272  /// \p NewName.
273  /// If WantFormat is false, the final TextEdit will be not formatted,
274  /// embedders could use this method to get all occurrences of the symbol (e.g.
275  /// highlighting them in prepare stage).
276  void rename(PathRef File, Position Pos, llvm::StringRef NewName,
277  const RenameOptions &Opts, Callback<FileEdits> CB);
278 
279  struct TweakRef {
280  std::string ID; /// ID to pass for applyTweak.
281  std::string Title; /// A single-line message to show in the UI.
283  };
284  /// Enumerate the code tweaks available to the user at a specified point.
285  void enumerateTweaks(PathRef File, Range Sel,
286  Callback<std::vector<TweakRef>> CB);
287 
288  /// Apply the code tweak with a specified \p ID.
289  void applyTweak(PathRef File, Range Sel, StringRef ID,
291 
292  /// Only for testing purposes.
293  /// Waits until all requests to worker thread are finished and dumps AST for
294  /// \p File. \p File must be in the list of added documents.
295  void dumpAST(PathRef File, llvm::unique_function<void(std::string)> Callback);
296  /// Called when an event occurs for a watched file in the workspace.
297  void onFileEvent(const DidChangeWatchedFilesParams &Params);
298 
299  /// Get symbol info for given position.
300  /// Clangd extension - not part of official LSP.
301  void symbolInfo(PathRef File, Position Pos,
302  Callback<std::vector<SymbolDetails>> CB);
303 
304  /// Get semantic ranges around a specified position in a file.
305  void semanticRanges(PathRef File, const std::vector<Position> &Pos,
306  Callback<std::vector<SelectionRange>> CB);
307 
308  /// Get all document links in a file.
309  void documentLinks(PathRef File, Callback<std::vector<DocumentLink>> CB);
310 
311  void semanticHighlights(PathRef File,
312  Callback<std::vector<HighlightingToken>>);
313 
314  /// Returns estimated memory usage and other statistics for each of the
315  /// currently open files.
316  /// Overall memory usage of clangd may be significantly more than reported
317  /// here, as this metric does not account (at least) for:
318  /// - memory occupied by static and dynamic index,
319  /// - memory required for in-flight requests,
320  /// FIXME: those metrics might be useful too, we should add them.
321  llvm::StringMap<TUScheduler::FileStats> fileStats() const;
322 
323  // Blocks the main thread until the server is idle. Only for use in tests.
324  // Returns false if the timeout expires.
325  LLVM_NODISCARD bool
326  blockUntilIdleForTest(llvm::Optional<double> TimeoutSeconds = 10);
327 
328 private:
329  void formatCode(PathRef File, llvm::StringRef Code,
330  ArrayRef<tooling::Range> Ranges,
332 
333  /// Derives a context for a task processing the specified source file.
334  /// This includes the current configuration (see Options::ConfigProvider).
335  /// The empty string means no particular file is the target.
336  /// Rather than called by each feature, this is exposed to the components
337  /// that control worker threads, like TUScheduler and BackgroundIndex.
338  /// This means it's OK to do some IO here, and it cuts across all features.
339  Context createProcessingContext(PathRef) const;
340  config::Provider *ConfigProvider = nullptr;
341 
342  const ThreadsafeFS &TFS;
343 
344  Path ResourceDir;
345  // The index used to look up symbols. This could be:
346  // - null (all index functionality is optional)
347  // - the dynamic index owned by ClangdServer (DynamicIdx)
348  // - the static index passed to the constructor
349  // - a merged view of a static and dynamic index (MergedIndex)
350  const SymbolIndex *Index = nullptr;
351  // If present, an index of symbols in open files. Read via *Index.
352  std::unique_ptr<FileIndex> DynamicIdx;
353  // If present, the new "auto-index" maintained in background threads.
354  std::unique_ptr<BackgroundIndex> BackgroundIdx;
355  // Storage for merged views of the various indexes.
356  std::vector<std::unique_ptr<SymbolIndex>> MergedIdx;
357 
358  // When set, provides clang-tidy options for a specific file.
359  ClangTidyOptionsBuilder GetClangTidyOptions;
360 
361  // If this is true, suggest include insertion fixes for diagnostic errors that
362  // can be caused by missing includes (e.g. member access in incomplete type).
363  bool SuggestMissingIncludes = false;
364 
365  // If true, preserve expressions in AST for broken code.
366  bool BuildRecoveryAST = true;
367  // If true, preserve the type for recovery AST.
368  bool PreserveRecoveryASTType = false;
369 
370  std::function<bool(const Tweak &)> TweakFilter;
371 
372  // GUARDED_BY(CachedCompletionFuzzyFindRequestMutex)
373  llvm::StringMap<llvm::Optional<FuzzyFindRequest>>
374  CachedCompletionFuzzyFindRequestByFile;
375  mutable std::mutex CachedCompletionFuzzyFindRequestMutex;
376 
377  llvm::Optional<std::string> WorkspaceRoot;
378  // WorkScheduler has to be the last member, because its destructor has to be
379  // called before all other members to stop the worker thread that references
380  // ClangdServer.
381  TUScheduler WorkScheduler;
382 };
383 
384 } // namespace clangd
385 } // namespace clang
386 
387 #endif
A source of configuration fragments.
std::string Code
virtual void onBackgroundIndexProgress(const BackgroundQueue::Stats &Stats)
Called when background indexing tasks are enqueued/started/completed.
Definition: ClangdServer.h:87
WantDiagnostics
Determines whether diagnostics should be generated for a file snapshot.
Definition: TUScheduler.h:48
void codeComplete(PathRef File, Position Pos, const clangd::CodeCompleteOptions &Opts, Callback< CodeCompleteResult > CB)
Run code completion for File at Pos.
void typeHierarchy(PathRef File, Position Pos, int Resolve, TypeHierarchyDirection Direction, Callback< llvm::Optional< TypeHierarchyItem >> CB)
Get information about type hierarchy for a given position.
void onFileEvent(const DidChangeWatchedFilesParams &Params)
Called when an event occurs for a watched file in the workspace.
Intent
Output of a tweak.
Definition: Tweak.h:71
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
Definition: Index.h:85
void addDocument(PathRef File, StringRef Contents, llvm::StringRef Version="null", WantDiagnostics WD=WantDiagnostics::Auto, bool ForceRebuild=false)
Add a File to the list of tracked C++ files or update the contents if File is already tracked...
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:23
void semanticRanges(PathRef File, const std::vector< Position > &Pos, Callback< std::vector< SelectionRange >> CB)
Get semantic ranges around a specified position in a file.
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
Definition: Function.h:28
LLVM_NODISCARD bool blockUntilIdleForTest(llvm::Optional< double > TimeoutSeconds=10)
static Options optsForTest()
Tweak::Intent Intent
A single-line message to show in the UI.
Definition: ClangdServer.h:282
Documents should not be synced at all.
ASTRetentionPolicy RetentionPolicy
AST caching policy. The default is to keep up to 3 ASTs in memory.
Definition: ClangdServer.h:97
void findDocumentHighlights(PathRef File, Position Pos, Callback< std::vector< DocumentHighlight >> CB)
Get document highlights for a given position.
void applyTweak(PathRef File, Range Sel, StringRef ID, Callback< Tweak::Effect > CB)
Apply the code tweak with a specified ID.
Configuration of the AST retention policy.
Definition: TUScheduler.h:58
llvm::StringRef Contents
void semanticHighlights(PathRef File, Callback< std::vector< HighlightingToken >>)
std::string Title
ID to pass for applyTweak.
Definition: ClangdServer.h:281
void formatFile(PathRef File, StringRef Code, Callback< tooling::Replacements > CB)
Run formatting for the whole File with content Code.
void rename(PathRef File, Position Pos, llvm::StringRef NewName, const RenameOptions &Opts, Callback< FileEdits > CB)
Rename all occurrences of the symbol at the Pos in File to NewName.
Provides compilation arguments used for parsing C and C++ files.
void formatRange(PathRef File, StringRef Code, Range Rng, Callback< tooling::Replacements > CB)
Run formatting for Rng inside File with content Code.
void documentLinks(PathRef File, Callback< std::vector< DocumentLink >> CB)
Get all document links in a file.
void resolveTypeHierarchy(TypeHierarchyItem Item, int Resolve, TypeHierarchyDirection Direction, Callback< llvm::Optional< TypeHierarchyItem >> CB)
Resolve type hierarchy item in the given direction.
std::string Path
A typedef to represent a file path.
Definition: Path.h:20
RenameOptions RenameOpts
ClangdServer(const GlobalCompilationDatabase &CDB, const ThreadsafeFS &TFS, const Options &Opts, Callbacks *Callbacks=nullptr)
Creates a new ClangdServer instance.
std::function< tidy::ClangTidyOptions(llvm::vfs::FileSystem &, llvm::StringRef)> ClangTidyOptionsBuilder
When set, used by ClangdServer to get clang-tidy options for each particular file.
Definition: ClangdServer.h:48
void prepareRename(PathRef File, Position Pos, const RenameOptions &RenameOpts, Callback< llvm::Optional< Range >> CB)
Test the validity of a rename operation.
void switchSourceHeader(PathRef Path, Callback< llvm::Optional< clangd::Path >> CB)
Switch to a corresponding source file when given a header file, and vice versa.
llvm::StringMap< TUScheduler::FileStats > fileStats() const
Returns estimated memory usage and other statistics for each of the currently open files...
void dumpAST(PathRef File, llvm::unique_function< void(std::string)> Callback)
Only for testing purposes.
void documentSymbols(StringRef File, Callback< std::vector< DocumentSymbol >> CB)
Retrieve the symbols within the specified file.
Position Pos
Definition: SourceCode.cpp:649
A context is an immutable container for per-request data that must be propagated through layers that ...
Definition: Context.h:69
void enumerateTweaks(PathRef File, Range Sel, Callback< std::vector< TweakRef >> CB)
Enumerate the code tweaks available to the user at a specified point.
virtual void onHighlightingsReady(PathRef File, llvm::StringRef Version, std::vector< HighlightingToken > Highlightings)
Called by ClangdServer when some Highlightings for File are ready.
Definition: ClangdServer.h:81
llvm::Optional< std::string > WorkspaceRoot
Clangd&#39;s workspace root.
Definition: ClangdServer.h:136
void findHover(PathRef File, Position Pos, Callback< llvm::Optional< HoverInfo >> CB)
Get code hover for a given position.
unsigned getDefaultAsyncThreadsCount()
Returns a number of a default async threads to use for TUScheduler.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Wrapper for vfs::FileSystem for use in multithreaded programs like clangd.
Definition: ThreadsafeFS.h:28
virtual void onFileUpdated(PathRef File, const TUStatus &Status)
Called whenever the file status is updated.
Definition: ClangdServer.h:76
Interface with hooks for users of ClangdServer to be notified of events.
Definition: ClangdServer.h:66
std::vector< std::string > QueryDriverGlobs
Clangd will execute compiler drivers matching one of these globs to fetch system include path...
Definition: ClangdServer.h:155
void removeDocument(PathRef File)
Remove File from list of tracked files, schedule a request to free resources associated with it...
An interface base for small context-sensitive refactoring actions.
Definition: Tweak.h:46
void symbolInfo(PathRef File, Position Pos, Callback< std::vector< SymbolDetails >> CB)
Get symbol info for given position.
void findReferences(PathRef File, Position Pos, uint32_t Limit, Callback< ReferencesResult > CB)
Retrieve locations for symbol references.
void locateSymbolAt(PathRef File, Position Pos, Callback< std::vector< LocatedSymbol >> CB)
Find declaration/definition locations of symbol at a specified position.
Manages a collection of source files and derived data (ASTs, indexes), and provides language-aware fe...
Definition: ClangdServer.h:63
ClangTidyOptionsBuilder GetClangTidyOptions
If set, enable clang-tidy in clangd and use to it get clang-tidy configurations for a particular file...
Definition: ClangdServer.h:125
Handles running tasks for ClangdServer and managing the resources (e.g., preambles and ASTs) for open...
Definition: TUScheduler.h:176
void formatOnType(PathRef File, StringRef Code, Position Pos, StringRef TriggerText, Callback< std::vector< TextEdit >> CB)
Run formatting after TriggerText was typed at Pos in File with content Code.
void workspaceSymbols(StringRef Query, int Limit, Callback< std::vector< SymbolInformation >> CB)
Retrieve the top symbols from the workspace matching a query.
Clangd may wait after an update to see if another one comes along.
Definition: TUScheduler.h:69
virtual void onDiagnosticsReady(PathRef File, llvm::StringRef Version, std::vector< Diag > Diagnostics)
Called by ClangdServer when Diagnostics for File are ready.
Definition: ClangdServer.h:72
Diagnostics must not be generated for this snapshot.
void signatureHelp(PathRef File, Position Pos, Callback< SignatureHelp > CB)
Provide signature help for File at Pos.