Mercurial > hg > CbC > CbC_llvm
comparison clang-tools-extra/clangd/ClangdServer.h @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | 0572611fdcc8 |
comparison
equal
deleted
inserted
replaced
147:c2174574ed3a | 150:1d019706d866 |
---|---|
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 "Cancellation.h" | |
14 #include "CodeComplete.h" | |
15 #include "FSProvider.h" | |
16 #include "FormattedString.h" | |
17 #include "Function.h" | |
18 #include "GlobalCompilationDatabase.h" | |
19 #include "Hover.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 "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, | |
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, | |
82 std::vector<HighlightingToken> Highlightings) {} | |
83 | |
84 /// Called when background indexing tasks are enqueued/started/completed. | |
85 /// Not called concurrently. | |
86 virtual void | |
87 onBackgroundIndexProgress(const BackgroundQueue::Stats &Stats) {} | |
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. | |
97 ASTRetentionPolicy RetentionPolicy; | |
98 | |
99 /// Cached preambles are potentially large. If false, store them on disk. | |
100 bool StorePreamblesInMemory = true; | |
101 | |
102 /// If true, ClangdServer builds a dynamic in-memory index for symbols in | |
103 /// opened files and uses the index to augment code completion results. | |
104 bool BuildDynamicSymbolIndex = false; | |
105 /// Use a heavier and faster in-memory index implementation. | |
106 bool HeavyweightDynamicSymbolIndex = true; | |
107 /// If true, ClangdServer automatically indexes files in the current project | |
108 /// on background threads. The index is stored in the project root. | |
109 bool BackgroundIndex = false; | |
110 | |
111 /// If set, use this index to augment code completion results. | |
112 SymbolIndex *StaticIndex = nullptr; | |
113 | |
114 /// If set, enable clang-tidy in clangd and use to it get clang-tidy | |
115 /// configurations for a particular file. | |
116 /// Clangd supports only a small subset of ClangTidyOptions, these options | |
117 /// (Checks, CheckOptions) are about which clang-tidy checks will be | |
118 /// enabled. | |
119 ClangTidyOptionsBuilder GetClangTidyOptions; | |
120 | |
121 /// Clangd's workspace root. Relevant for "workspace" operations not bound | |
122 /// to a particular file. | |
123 /// FIXME: If not set, should use the current working directory. | |
124 llvm::Optional<std::string> WorkspaceRoot; | |
125 | |
126 /// The resource directory is used to find internal headers, overriding | |
127 /// defaults and -resource-dir compiler flag). | |
128 /// If None, ClangdServer calls CompilerInvocation::GetResourcePath() to | |
129 /// obtain the standard resource directory. | |
130 llvm::Optional<std::string> ResourceDir = llvm::None; | |
131 | |
132 /// Time to wait after a new file version before computing diagnostics. | |
133 DebouncePolicy UpdateDebounce = | |
134 DebouncePolicy::fixed(std::chrono::milliseconds(500)); | |
135 | |
136 bool SuggestMissingIncludes = false; | |
137 | |
138 /// Clangd will execute compiler drivers matching one of these globs to | |
139 /// fetch system include path. | |
140 std::vector<std::string> QueryDriverGlobs; | |
141 | |
142 /// Enable semantic highlighting features. | |
143 bool SemanticHighlighting = false; | |
144 | |
145 /// Enable cross-file rename feature. | |
146 bool CrossFileRename = false; | |
147 | |
148 /// Returns true if the tweak should be enabled. | |
149 std::function<bool(const Tweak &)> TweakFilter = [](const Tweak &T) { | |
150 return !T.hidden(); // only enable non-hidden tweaks. | |
151 }; | |
152 | |
153 explicit operator TUScheduler::Options() const; | |
154 }; | |
155 // Sensible default options for use in tests. | |
156 // Features like indexing must be enabled if desired. | |
157 static Options optsForTest(); | |
158 | |
159 /// Creates a new ClangdServer instance. | |
160 /// | |
161 /// ClangdServer uses \p CDB to obtain compilation arguments for parsing. Note | |
162 /// that ClangdServer only obtains compilation arguments once for each newly | |
163 /// added file (i.e., when processing a first call to addDocument) and reuses | |
164 /// those arguments for subsequent reparses. However, ClangdServer will check | |
165 /// if compilation arguments changed on calls to forceReparse(). | |
166 ClangdServer(const GlobalCompilationDatabase &CDB, | |
167 const FileSystemProvider &FSProvider, const Options &Opts, | |
168 Callbacks *Callbacks = nullptr); | |
169 | |
170 /// Add a \p File to the list of tracked C++ files or update the contents if | |
171 /// \p File is already tracked. Also schedules parsing of the AST for it on a | |
172 /// separate thread. When the parsing is complete, DiagConsumer passed in | |
173 /// constructor will receive onDiagnosticsReady callback. | |
174 void addDocument(PathRef File, StringRef Contents, | |
175 WantDiagnostics WD = WantDiagnostics::Auto, | |
176 bool ForceRebuild = false); | |
177 | |
178 /// Get the contents of \p File, which should have been added. | |
179 llvm::StringRef getDocument(PathRef File) const; | |
180 | |
181 /// Remove \p File from list of tracked files, schedule a request to free | |
182 /// resources associated with it. Pending diagnostics for closed files may not | |
183 /// be delivered, even if requested with WantDiags::Auto or WantDiags::Yes. | |
184 void removeDocument(PathRef File); | |
185 | |
186 /// Run code completion for \p File at \p Pos. | |
187 /// Request is processed asynchronously. | |
188 /// | |
189 /// This method should only be called for currently tracked files. However, it | |
190 /// is safe to call removeDocument for \p File after this method returns, even | |
191 /// while returned future is not yet ready. | |
192 /// A version of `codeComplete` that runs \p Callback on the processing thread | |
193 /// when codeComplete results become available. | |
194 void codeComplete(PathRef File, Position Pos, | |
195 const clangd::CodeCompleteOptions &Opts, | |
196 Callback<CodeCompleteResult> CB); | |
197 | |
198 /// Provide signature help for \p File at \p Pos. This method should only be | |
199 /// called for tracked files. | |
200 void signatureHelp(PathRef File, Position Pos, Callback<SignatureHelp> CB); | |
201 | |
202 /// Find declaration/definition locations of symbol at a specified position. | |
203 void locateSymbolAt(PathRef File, Position Pos, | |
204 Callback<std::vector<LocatedSymbol>> CB); | |
205 | |
206 /// Switch to a corresponding source file when given a header file, and vice | |
207 /// versa. | |
208 void switchSourceHeader(PathRef Path, | |
209 Callback<llvm::Optional<clangd::Path>> CB); | |
210 | |
211 /// Get document highlights for a given position. | |
212 void findDocumentHighlights(PathRef File, Position Pos, | |
213 Callback<std::vector<DocumentHighlight>> CB); | |
214 | |
215 /// Get code hover for a given position. | |
216 void findHover(PathRef File, Position Pos, | |
217 Callback<llvm::Optional<HoverInfo>> CB); | |
218 | |
219 /// Get information about type hierarchy for a given position. | |
220 void typeHierarchy(PathRef File, Position Pos, int Resolve, | |
221 TypeHierarchyDirection Direction, | |
222 Callback<llvm::Optional<TypeHierarchyItem>> CB); | |
223 | |
224 /// Resolve type hierarchy item in the given direction. | |
225 void resolveTypeHierarchy(TypeHierarchyItem Item, int Resolve, | |
226 TypeHierarchyDirection Direction, | |
227 Callback<llvm::Optional<TypeHierarchyItem>> CB); | |
228 | |
229 /// Retrieve the top symbols from the workspace matching a query. | |
230 void workspaceSymbols(StringRef Query, int Limit, | |
231 Callback<std::vector<SymbolInformation>> CB); | |
232 | |
233 /// Retrieve the symbols within the specified file. | |
234 void documentSymbols(StringRef File, | |
235 Callback<std::vector<DocumentSymbol>> CB); | |
236 | |
237 /// Retrieve locations for symbol references. | |
238 void findReferences(PathRef File, Position Pos, uint32_t Limit, | |
239 Callback<ReferencesResult> CB); | |
240 | |
241 /// Run formatting for \p Rng inside \p File with content \p Code. | |
242 llvm::Expected<tooling::Replacements> formatRange(StringRef Code, | |
243 PathRef File, Range Rng); | |
244 | |
245 /// Run formatting for the whole \p File with content \p Code. | |
246 llvm::Expected<tooling::Replacements> formatFile(StringRef Code, | |
247 PathRef File); | |
248 | |
249 /// Run formatting after \p TriggerText was typed at \p Pos in \p File with | |
250 /// content \p Code. | |
251 llvm::Expected<std::vector<TextEdit>> formatOnType(StringRef Code, | |
252 PathRef File, Position Pos, | |
253 StringRef TriggerText); | |
254 | |
255 /// Test the validity of a rename operation. | |
256 void prepareRename(PathRef File, Position Pos, | |
257 Callback<llvm::Optional<Range>> CB); | |
258 | |
259 /// Rename all occurrences of the symbol at the \p Pos in \p File to | |
260 /// \p NewName. | |
261 /// If WantFormat is false, the final TextEdit will be not formatted, | |
262 /// embedders could use this method to get all occurrences of the symbol (e.g. | |
263 /// highlighting them in prepare stage). | |
264 void rename(PathRef File, Position Pos, llvm::StringRef NewName, | |
265 bool WantFormat, Callback<FileEdits> CB); | |
266 | |
267 struct TweakRef { | |
268 std::string ID; /// ID to pass for applyTweak. | |
269 std::string Title; /// A single-line message to show in the UI. | |
270 Tweak::Intent Intent; | |
271 }; | |
272 /// Enumerate the code tweaks available to the user at a specified point. | |
273 void enumerateTweaks(PathRef File, Range Sel, | |
274 Callback<std::vector<TweakRef>> CB); | |
275 | |
276 /// Apply the code tweak with a specified \p ID. | |
277 void applyTweak(PathRef File, Range Sel, StringRef ID, | |
278 Callback<Tweak::Effect> CB); | |
279 | |
280 /// Only for testing purposes. | |
281 /// Waits until all requests to worker thread are finished and dumps AST for | |
282 /// \p File. \p File must be in the list of added documents. | |
283 void dumpAST(PathRef File, llvm::unique_function<void(std::string)> Callback); | |
284 /// Called when an event occurs for a watched file in the workspace. | |
285 void onFileEvent(const DidChangeWatchedFilesParams &Params); | |
286 | |
287 /// Get symbol info for given position. | |
288 /// Clangd extension - not part of official LSP. | |
289 void symbolInfo(PathRef File, Position Pos, | |
290 Callback<std::vector<SymbolDetails>> CB); | |
291 | |
292 /// Get semantic ranges around a specified position in a file. | |
293 void semanticRanges(PathRef File, Position Pos, | |
294 Callback<std::vector<Range>> CB); | |
295 | |
296 /// Get all document links in a file. | |
297 void documentLinks(PathRef File, Callback<std::vector<DocumentLink>> CB); | |
298 | |
299 /// Returns estimated memory usage for each of the currently open files. | |
300 /// The order of results is unspecified. | |
301 /// Overall memory usage of clangd may be significantly more than reported | |
302 /// here, as this metric does not account (at least) for: | |
303 /// - memory occupied by static and dynamic index, | |
304 /// - memory required for in-flight requests, | |
305 /// FIXME: those metrics might be useful too, we should add them. | |
306 std::vector<std::pair<Path, std::size_t>> getUsedBytesPerFile() const; | |
307 | |
308 // Blocks the main thread until the server is idle. Only for use in tests. | |
309 // Returns false if the timeout expires. | |
310 LLVM_NODISCARD bool | |
311 blockUntilIdleForTest(llvm::Optional<double> TimeoutSeconds = 10); | |
312 | |
313 private: | |
314 /// FIXME: This stats several files to find a .clang-format file. I/O can be | |
315 /// slow. Think of a way to cache this. | |
316 llvm::Expected<tooling::Replacements> | |
317 formatCode(llvm::StringRef Code, PathRef File, | |
318 ArrayRef<tooling::Range> Ranges); | |
319 | |
320 const FileSystemProvider &FSProvider; | |
321 | |
322 Path ResourceDir; | |
323 // The index used to look up symbols. This could be: | |
324 // - null (all index functionality is optional) | |
325 // - the dynamic index owned by ClangdServer (DynamicIdx) | |
326 // - the static index passed to the constructor | |
327 // - a merged view of a static and dynamic index (MergedIndex) | |
328 const SymbolIndex *Index = nullptr; | |
329 // If present, an index of symbols in open files. Read via *Index. | |
330 std::unique_ptr<FileIndex> DynamicIdx; | |
331 // If present, the new "auto-index" maintained in background threads. | |
332 std::unique_ptr<BackgroundIndex> BackgroundIdx; | |
333 // Storage for merged views of the various indexes. | |
334 std::vector<std::unique_ptr<SymbolIndex>> MergedIdx; | |
335 | |
336 // When set, provides clang-tidy options for a specific file. | |
337 ClangTidyOptionsBuilder GetClangTidyOptions; | |
338 | |
339 // If this is true, suggest include insertion fixes for diagnostic errors that | |
340 // can be caused by missing includes (e.g. member access in incomplete type). | |
341 bool SuggestMissingIncludes = false; | |
342 | |
343 bool CrossFileRename = false; | |
344 | |
345 std::function<bool(const Tweak &)> TweakFilter; | |
346 | |
347 // GUARDED_BY(CachedCompletionFuzzyFindRequestMutex) | |
348 llvm::StringMap<llvm::Optional<FuzzyFindRequest>> | |
349 CachedCompletionFuzzyFindRequestByFile; | |
350 mutable std::mutex CachedCompletionFuzzyFindRequestMutex; | |
351 | |
352 llvm::Optional<std::string> WorkspaceRoot; | |
353 // WorkScheduler has to be the last member, because its destructor has to be | |
354 // called before all other members to stop the worker thread that references | |
355 // ClangdServer. | |
356 TUScheduler WorkScheduler; | |
357 }; | |
358 | |
359 } // namespace clangd | |
360 } // namespace clang | |
361 | |
362 #endif |