xref: /llvm-project/clang-tools-extra/clangd/ClangdServer.h (revision 61fe67a4017375fd675f75652e857e837f77fa51)
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 "CodeComplete.h"
13 #include "ConfigProvider.h"
14 #include "Diagnostics.h"
15 #include "DraftStore.h"
16 #include "FeatureModule.h"
17 #include "GlobalCompilationDatabase.h"
18 #include "Hover.h"
19 #include "ModulesBuilder.h"
20 #include "Protocol.h"
21 #include "SemanticHighlighting.h"
22 #include "TUScheduler.h"
23 #include "XRefs.h"
24 #include "index/Background.h"
25 #include "index/FileIndex.h"
26 #include "index/Index.h"
27 #include "refactor/Rename.h"
28 #include "refactor/Tweak.h"
29 #include "support/Function.h"
30 #include "support/MemoryTree.h"
31 #include "support/Path.h"
32 #include "support/ThreadsafeFS.h"
33 #include "clang/Tooling/Core/Replacement.h"
34 #include "llvm/ADT/ArrayRef.h"
35 #include "llvm/ADT/FunctionExtras.h"
36 #include "llvm/ADT/StringRef.h"
37 #include <functional>
38 #include <memory>
39 #include <optional>
40 #include <string>
41 #include <tuple>
42 #include <vector>
43 
44 namespace clang {
45 namespace clangd {
46 /// Manages a collection of source files and derived data (ASTs, indexes),
47 /// and provides language-aware features such as code completion.
48 ///
49 /// The primary client is ClangdLSPServer which exposes these features via
50 /// the Language Server protocol. ClangdServer may also be embedded directly,
51 /// though its API is not stable over time.
52 ///
53 /// ClangdServer should be used from a single thread. Many potentially-slow
54 /// operations have asynchronous APIs and deliver their results on another
55 /// thread.
56 /// Such operations support cancellation: if the caller sets up a cancelable
57 /// context, many operations will notice cancellation and fail early.
58 /// (ClangdLSPServer uses this to implement $/cancelRequest).
59 class ClangdServer {
60 public:
61   /// Interface with hooks for users of ClangdServer to be notified of events.
62   class Callbacks {
63   public:
64     virtual ~Callbacks() = default;
65 
66     /// Called by ClangdServer when \p Diagnostics for \p File are ready.
67     /// These pushed diagnostics might correspond to an older version of the
68     /// file, they do not interfere with "pull-based" ClangdServer::diagnostics.
69     /// May be called concurrently for separate files, not for a single file.
70     virtual void onDiagnosticsReady(PathRef File, llvm::StringRef Version,
71                                     llvm::ArrayRef<Diag> Diagnostics) {}
72     /// Called whenever the file status is updated.
73     /// May be called concurrently for separate files, not for a single file.
74     virtual void onFileUpdated(PathRef File, const TUStatus &Status) {}
75 
76     /// Called when background indexing tasks are enqueued/started/completed.
77     /// Not called concurrently.
78     virtual void
79     onBackgroundIndexProgress(const BackgroundQueue::Stats &Stats) {}
80 
81     /// Called when the meaning of a source code may have changed without an
82     /// edit. Usually clients assume that responses to requests are valid until
83     /// they next edit the file. If they're invalidated at other times, we
84     /// should tell the client. In particular, when an asynchronous preamble
85     /// build finishes, we can provide more accurate semantic tokens, so we
86     /// should tell the client to refresh.
87     virtual void onSemanticsMaybeChanged(PathRef File) {}
88 
89     /// Called by ClangdServer when some \p InactiveRegions for \p File are
90     /// ready.
91     virtual void onInactiveRegionsReady(PathRef File,
92                                         std::vector<Range> InactiveRegions) {}
93   };
94   /// Creates a context provider that loads and installs config.
95   /// Errors in loading config are reported as diagnostics via Callbacks.
96   /// (This is typically used as ClangdServer::Options::ContextProvider).
97   static std::function<Context(PathRef)>
98   createConfiguredContextProvider(const config::Provider *Provider,
99                                   ClangdServer::Callbacks *);
100 
101   struct Options {
102     /// To process requests asynchronously, ClangdServer spawns worker threads.
103     /// If this is zero, no threads are spawned. All work is done on the calling
104     /// thread, and callbacks are invoked before "async" functions return.
105     unsigned AsyncThreadsCount = getDefaultAsyncThreadsCount();
106 
107     /// AST caching policy. The default is to keep up to 3 ASTs in memory.
108     ASTRetentionPolicy RetentionPolicy;
109 
110     /// Cached preambles are potentially large. If false, store them on disk.
111     bool StorePreamblesInMemory = true;
112 
113     /// Call hierarchy's outgoing calls feature requires additional index
114     /// serving structures which increase memory usage. If false, these are
115     /// not created and the feature is not enabled.
116     bool EnableOutgoingCalls = true;
117 
118     /// This throttler controls which preambles may be built at a given time.
119     clangd::PreambleThrottler *PreambleThrottler = nullptr;
120 
121     /// Manages to build module files.
122     ModulesBuilder *ModulesManager = nullptr;
123 
124     /// If true, ClangdServer builds a dynamic in-memory index for symbols in
125     /// opened files and uses the index to augment code completion results.
126     bool BuildDynamicSymbolIndex = false;
127     /// If true, ClangdServer automatically indexes files in the current project
128     /// on background threads. The index is stored in the project root.
129     bool BackgroundIndex = false;
130     llvm::ThreadPriority BackgroundIndexPriority = llvm::ThreadPriority::Low;
131 
132     /// If set, use this index to augment code completion results.
133     SymbolIndex *StaticIndex = nullptr;
134 
135     /// If set, queried to derive a processing context for some work.
136     /// Usually used to inject Config (see createConfiguredContextProvider).
137     ///
138     /// When the provider is called, the active context will be that inherited
139     /// from the request (e.g. addDocument()), or from the ClangdServer
140     /// constructor if there is no such request (e.g. background indexing).
141     ///
142     /// The path is an absolute path of the file being processed.
143     /// If there is no particular file (e.g. project loading) then it is empty.
144     std::function<Context(PathRef)> ContextProvider;
145 
146     /// The Options provider to use when running clang-tidy. If null, clang-tidy
147     /// checks will be disabled.
148     TidyProviderRef ClangTidyProvider;
149 
150     /// Clangd's workspace root. Relevant for "workspace" operations not bound
151     /// to a particular file.
152     /// FIXME: If not set, should use the current working directory.
153     std::optional<std::string> WorkspaceRoot;
154 
155     /// The resource directory is used to find internal headers, overriding
156     /// defaults and -resource-dir compiler flag).
157     /// If std::nullopt, ClangdServer calls
158     /// CompilerInvocation::GetResourcePath() to obtain the standard resource
159     /// directory.
160     std::optional<std::string> ResourceDir;
161 
162     /// Time to wait after a new file version before computing diagnostics.
163     DebouncePolicy UpdateDebounce = DebouncePolicy{
164         /*Min=*/std::chrono::milliseconds(50),
165         /*Max=*/std::chrono::milliseconds(500),
166         /*RebuildRatio=*/1,
167     };
168 
169     /// Cancel certain requests if the file changes before they begin running.
170     /// This is useful for "transient" actions like enumerateTweaks that were
171     /// likely implicitly generated, and avoids redundant work if clients forget
172     /// to cancel. Clients that always cancel stale requests should clear this.
173     bool ImplicitCancellation = true;
174 
175     /// Clangd will execute compiler drivers matching one of these globs to
176     /// fetch system include path.
177     std::vector<std::string> QueryDriverGlobs;
178 
179     // Whether the client supports folding only complete lines.
180     bool LineFoldingOnly = false;
181 
182     FeatureModuleSet *FeatureModules = nullptr;
183     /// If true, use the dirty buffer contents when building Preambles.
184     bool UseDirtyHeaders = false;
185 
186     // If true, parse emplace-like functions in the preamble.
187     bool PreambleParseForwardingFunctions = false;
188 
189     /// Whether include fixer insertions for Objective-C code should use #import
190     /// instead of #include.
191     bool ImportInsertions = false;
192 
193     /// Whether to collect and publish information about inactive preprocessor
194     /// regions in the document.
195     bool PublishInactiveRegions = false;
196 
197     explicit operator TUScheduler::Options() const;
198   };
199   // Sensible default options for use in tests.
200   // Features like indexing must be enabled if desired.
201   static Options optsForTest();
202 
203   /// Creates a new ClangdServer instance.
204   ///
205   /// ClangdServer uses \p CDB to obtain compilation arguments for parsing. Note
206   /// that ClangdServer only obtains compilation arguments once for each newly
207   /// added file (i.e., when processing a first call to addDocument) and reuses
208   /// those arguments for subsequent reparses. However, ClangdServer will check
209   /// if compilation arguments changed on calls to forceReparse().
210   ClangdServer(const GlobalCompilationDatabase &CDB, const ThreadsafeFS &TFS,
211                const Options &Opts, Callbacks *Callbacks = nullptr);
212   ~ClangdServer();
213 
214   /// Gets the installed feature module of a given type, if any.
215   /// This exposes access the public interface of feature modules that have one.
216   template <typename Mod> Mod *featureModule() {
217     return FeatureModules ? FeatureModules->get<Mod>() : nullptr;
218   }
219   template <typename Mod> const Mod *featureModule() const {
220     return FeatureModules ? FeatureModules->get<Mod>() : nullptr;
221   }
222 
223   /// Add a \p File to the list of tracked C++ files or update the contents if
224   /// \p File is already tracked. Also schedules parsing of the AST for it on a
225   /// separate thread. When the parsing is complete, DiagConsumer passed in
226   /// constructor will receive onDiagnosticsReady callback.
227   /// Version identifies this snapshot and is propagated to ASTs, preambles,
228   /// diagnostics etc built from it. If empty, a version number is generated.
229   void addDocument(PathRef File, StringRef Contents,
230                    llvm::StringRef Version = "null",
231                    WantDiagnostics WD = WantDiagnostics::Auto,
232                    bool ForceRebuild = false);
233 
234   /// Remove \p File from list of tracked files, schedule a request to free
235   /// resources associated with it. Pending diagnostics for closed files may not
236   /// be delivered, even if requested with WantDiags::Auto or WantDiags::Yes.
237   /// An empty set of diagnostics will be delivered, with Version = "".
238   void removeDocument(PathRef File);
239 
240   /// Requests a reparse of currently opened files using their latest source.
241   /// This will typically only rebuild if something other than the source has
242   /// changed (e.g. the CDB yields different flags, or files included in the
243   /// preamble have been modified).
244   void reparseOpenFilesIfNeeded(
245       llvm::function_ref<bool(llvm::StringRef File)> Filter);
246 
247   /// Run code completion for \p File at \p Pos.
248   ///
249   /// This method should only be called for currently tracked files.
250   void codeComplete(PathRef File, Position Pos,
251                     const clangd::CodeCompleteOptions &Opts,
252                     Callback<CodeCompleteResult> CB);
253 
254   /// Provide signature help for \p File at \p Pos.  This method should only be
255   /// called for tracked files.
256   void signatureHelp(PathRef File, Position Pos, MarkupKind DocumentationFormat,
257                      Callback<SignatureHelp> CB);
258 
259   /// Find declaration/definition locations of symbol at a specified position.
260   void locateSymbolAt(PathRef File, Position Pos,
261                       Callback<std::vector<LocatedSymbol>> CB);
262 
263   /// Switch to a corresponding source file when given a header file, and vice
264   /// versa.
265   void switchSourceHeader(PathRef Path,
266                           Callback<std::optional<clangd::Path>> CB);
267 
268   /// Get document highlights for a given position.
269   void findDocumentHighlights(PathRef File, Position Pos,
270                               Callback<std::vector<DocumentHighlight>> CB);
271 
272   /// Get code hover for a given position.
273   void findHover(PathRef File, Position Pos,
274                  Callback<std::optional<HoverInfo>> CB);
275 
276   /// Get information about type hierarchy for a given position.
277   void typeHierarchy(PathRef File, Position Pos, int Resolve,
278                      TypeHierarchyDirection Direction,
279                      Callback<std::vector<TypeHierarchyItem>> CB);
280   /// Get direct parents of a type hierarchy item.
281   void superTypes(const TypeHierarchyItem &Item,
282                   Callback<std::optional<std::vector<TypeHierarchyItem>>> CB);
283   /// Get direct children of a type hierarchy item.
284   void subTypes(const TypeHierarchyItem &Item,
285                 Callback<std::vector<TypeHierarchyItem>> CB);
286 
287   /// Resolve type hierarchy item in the given direction.
288   void resolveTypeHierarchy(TypeHierarchyItem Item, int Resolve,
289                             TypeHierarchyDirection Direction,
290                             Callback<std::optional<TypeHierarchyItem>> CB);
291 
292   /// Get information about call hierarchy for a given position.
293   void prepareCallHierarchy(PathRef File, Position Pos,
294                             Callback<std::vector<CallHierarchyItem>> CB);
295 
296   /// Resolve incoming calls for a given call hierarchy item.
297   void incomingCalls(const CallHierarchyItem &Item,
298                      Callback<std::vector<CallHierarchyIncomingCall>>);
299 
300   /// Resolve outgoing calls for a given call hierarchy item.
301   void outgoingCalls(const CallHierarchyItem &Item,
302                      Callback<std::vector<CallHierarchyOutgoingCall>>);
303 
304   /// Resolve inlay hints for a given document.
305   void inlayHints(PathRef File, std::optional<Range> RestrictRange,
306                   Callback<std::vector<InlayHint>>);
307 
308   /// Retrieve the top symbols from the workspace matching a query.
309   void workspaceSymbols(StringRef Query, int Limit,
310                         Callback<std::vector<SymbolInformation>> CB);
311 
312   /// Retrieve the symbols within the specified file.
313   void documentSymbols(StringRef File,
314                        Callback<std::vector<DocumentSymbol>> CB);
315 
316   /// Retrieve ranges that can be used to fold code within the specified file.
317   void foldingRanges(StringRef File, Callback<std::vector<FoldingRange>> CB);
318 
319   /// Retrieve implementations for virtual method.
320   void findImplementations(PathRef File, Position Pos,
321                            Callback<std::vector<LocatedSymbol>> CB);
322 
323   /// Retrieve symbols for types referenced at \p Pos.
324   void findType(PathRef File, Position Pos,
325                 Callback<std::vector<LocatedSymbol>> CB);
326 
327   /// Retrieve locations for symbol references.
328   void findReferences(PathRef File, Position Pos, uint32_t Limit,
329                       bool AddContainer, Callback<ReferencesResult> CB);
330 
331   /// Run formatting for the \p File with content \p Code.
332   /// If \p Rng is non-null, formats only that region.
333   void formatFile(PathRef File, std::optional<Range> Rng,
334                   Callback<tooling::Replacements> CB);
335 
336   /// Run formatting after \p TriggerText was typed at \p Pos in \p File with
337   /// content \p Code.
338   void formatOnType(PathRef File, Position Pos, StringRef TriggerText,
339                     Callback<std::vector<TextEdit>> CB);
340 
341   /// Test the validity of a rename operation.
342   ///
343   /// If NewName is provided, it performs a name validation.
344   void prepareRename(PathRef File, Position Pos,
345                      std::optional<std::string> NewName,
346                      const RenameOptions &RenameOpts,
347                      Callback<RenameResult> CB);
348 
349   /// Rename all occurrences of the symbol at the \p Pos in \p File to
350   /// \p NewName.
351   /// If WantFormat is false, the final TextEdit will be not formatted,
352   /// embedders could use this method to get all occurrences of the symbol (e.g.
353   /// highlighting them in prepare stage).
354   void rename(PathRef File, Position Pos, llvm::StringRef NewName,
355               const RenameOptions &Opts, Callback<RenameResult> CB);
356 
357   struct TweakRef {
358     std::string ID;    /// ID to pass for applyTweak.
359     std::string Title; /// A single-line message to show in the UI.
360     llvm::StringLiteral Kind;
361   };
362 
363   // Ref to the clangd::Diag.
364   struct DiagRef {
365     clangd::Range Range;
366     std::string Message;
367     bool operator==(const DiagRef &Other) const {
368       return std::tie(Range, Message) == std::tie(Other.Range, Other.Message);
369     }
370     bool operator<(const DiagRef &Other) const {
371       return std::tie(Range, Message) < std::tie(Other.Range, Other.Message);
372     }
373   };
374 
375   struct CodeActionInputs {
376     std::string File;
377     Range Selection;
378 
379     /// Requested kind of actions to return.
380     std::vector<std::string> RequestedActionKinds;
381 
382     /// Diagnostics attached to the code action request.
383     std::vector<DiagRef> Diagnostics;
384 
385     /// Tweaks where Filter returns false will not be checked or included.
386     std::function<bool(const Tweak &)> TweakFilter;
387   };
388   struct CodeActionResult {
389     std::string Version;
390     struct QuickFix {
391       DiagRef Diag;
392       Fix F;
393     };
394     std::vector<QuickFix> QuickFixes;
395     std::vector<TweakRef> TweakRefs;
396     struct Rename {
397       DiagRef Diag;
398       std::string FixMessage;
399       std::string NewName;
400     };
401     std::vector<Rename> Renames;
402   };
403   /// Surface code actions (quick-fixes for diagnostics, or available code
404   /// tweaks) for a given range in a file.
405   void codeAction(const CodeActionInputs &Inputs,
406                   Callback<CodeActionResult> CB);
407 
408   /// Apply the code tweak with a specified \p ID.
409   void applyTweak(PathRef File, Range Sel, StringRef ID,
410                   Callback<Tweak::Effect> CB);
411 
412   /// Called when an event occurs for a watched file in the workspace.
413   void onFileEvent(const DidChangeWatchedFilesParams &Params);
414 
415   /// Get symbol info for given position.
416   /// Clangd extension - not part of official LSP.
417   void symbolInfo(PathRef File, Position Pos,
418                   Callback<std::vector<SymbolDetails>> CB);
419 
420   /// Get semantic ranges around a specified position in a file.
421   void semanticRanges(PathRef File, const std::vector<Position> &Pos,
422                       Callback<std::vector<SelectionRange>> CB);
423 
424   /// Get all document links in a file.
425   void documentLinks(PathRef File, Callback<std::vector<DocumentLink>> CB);
426 
427   void semanticHighlights(PathRef File,
428                           Callback<std::vector<HighlightingToken>>);
429 
430   /// Describe the AST subtree for a piece of code.
431   void getAST(PathRef File, std::optional<Range> R,
432               Callback<std::optional<ASTNode>> CB);
433 
434   /// Runs an arbitrary action that has access to the AST of the specified file.
435   /// The action will execute on one of ClangdServer's internal threads.
436   /// The AST is only valid for the duration of the callback.
437   /// As with other actions, the file must have been opened.
438   void customAction(PathRef File, llvm::StringRef Name,
439                     Callback<InputsAndAST> Action);
440 
441   /// Fetches diagnostics for current version of the \p File. This might fail if
442   /// server is busy (building a preamble) and would require a long time to
443   /// prepare diagnostics. If it fails, clients should wait for
444   /// onSemanticsMaybeChanged and then retry.
445   /// These 'pulled' diagnostics do not interfere with the diagnostics 'pushed'
446   /// to Callbacks::onDiagnosticsReady, and clients may use either or both.
447   void diagnostics(PathRef File, Callback<std::vector<Diag>> CB);
448 
449   /// Returns estimated memory usage and other statistics for each of the
450   /// currently open files.
451   /// Overall memory usage of clangd may be significantly more than reported
452   /// here, as this metric does not account (at least) for:
453   ///   - memory occupied by static and dynamic index,
454   ///   - memory required for in-flight requests,
455   /// FIXME: those metrics might be useful too, we should add them.
456   llvm::StringMap<TUScheduler::FileStats> fileStats() const;
457 
458   /// Gets the contents of a currently tracked file. Returns nullptr if the file
459   /// isn't being tracked.
460   std::shared_ptr<const std::string> getDraft(PathRef File) const;
461 
462   // Blocks the main thread until the server is idle. Only for use in tests.
463   // Returns false if the timeout expires.
464   // FIXME: various subcomponents each get the full timeout, so it's more of
465   // an order of magnitude than a hard deadline.
466   [[nodiscard]] bool
467   blockUntilIdleForTest(std::optional<double> TimeoutSeconds = 10);
468 
469   /// Builds a nested representation of memory used by components.
470   void profile(MemoryTree &MT) const;
471 
472 private:
473   FeatureModuleSet *FeatureModules;
474   const GlobalCompilationDatabase &CDB;
475   const ThreadsafeFS &getHeaderFS() const {
476     return UseDirtyHeaders ? *DirtyFS : TFS;
477   }
478   const ThreadsafeFS &TFS;
479 
480   Path ResourceDir;
481   // The index used to look up symbols. This could be:
482   //   - null (all index functionality is optional)
483   //   - the dynamic index owned by ClangdServer (DynamicIdx)
484   //   - the static index passed to the constructor
485   //   - a merged view of a static and dynamic index (MergedIndex)
486   const SymbolIndex *Index = nullptr;
487   // If present, an index of symbols in open files. Read via *Index.
488   std::unique_ptr<FileIndex> DynamicIdx;
489   // If present, the new "auto-index" maintained in background threads.
490   std::unique_ptr<BackgroundIndex> BackgroundIdx;
491   // Storage for merged views of the various indexes.
492   std::vector<std::unique_ptr<SymbolIndex>> MergedIdx;
493   // Manage module files.
494   ModulesBuilder *ModulesManager = nullptr;
495 
496   // When set, provides clang-tidy options for a specific file.
497   TidyProviderRef ClangTidyProvider;
498 
499   bool UseDirtyHeaders = false;
500 
501   // Whether the client supports folding only complete lines.
502   bool LineFoldingOnly = false;
503 
504   bool PreambleParseForwardingFunctions = false;
505 
506   bool ImportInsertions = false;
507 
508   bool PublishInactiveRegions = false;
509 
510   // GUARDED_BY(CachedCompletionFuzzyFindRequestMutex)
511   llvm::StringMap<std::optional<FuzzyFindRequest>>
512       CachedCompletionFuzzyFindRequestByFile;
513   mutable std::mutex CachedCompletionFuzzyFindRequestMutex;
514 
515   std::optional<std::string> WorkspaceRoot;
516   std::optional<AsyncTaskRunner> IndexTasks; // for stdlib indexing.
517   std::optional<TUScheduler> WorkScheduler;
518   // Invalidation policy used for actions that we assume are "transient".
519   TUScheduler::ASTActionInvalidation Transient;
520 
521   // Store of the current versions of the open documents.
522   // Only written from the main thread (despite being threadsafe).
523   DraftStore DraftMgr;
524 
525   std::unique_ptr<ThreadsafeFS> DirtyFS;
526 };
527 
528 } // namespace clangd
529 } // namespace clang
530 
531 #endif
532