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