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 |
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=*/.Min: std::chrono::milliseconds(50), |
165 | /*Max=*/.Max: std::chrono::milliseconds(500), |
166 | /*RebuildRatio=*/.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 = false; |
185 | |
186 | // If true, parse emplace-like functions in the preamble. |
187 | bool PreambleParseForwardingFunctions = true; |
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 (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-empty, formats only those regions. |
333 | void formatFile(PathRef File, const std::vector<Range> &Rngs, |
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(args: Range, args: Message) == std::tie(args: Other.Range, args: Other.Message); |
369 | } |
370 | bool operator<(const DiagRef &Other) const { |
371 | return std::tie(args: Range, args: Message) < std::tie(args: Other.Range, args: 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 &() 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 = false; |
500 | |
501 | // Whether the client supports folding only complete lines. |
502 | bool LineFoldingOnly = false; |
503 | |
504 | bool PreambleParseForwardingFunctions = true; |
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 | |