clang-tools  7.0.0
ClangdServer.h
Go to the documentation of this file.
1 //===--- ClangdServer.h - Main clangd server code ----------------*- C++-*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDSERVER_H
11 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDSERVER_H
12 
13 #include "ClangdUnit.h"
14 #include "CodeComplete.h"
15 #include "FSProvider.h"
16 #include "Function.h"
18 #include "Protocol.h"
19 #include "TUScheduler.h"
20 #include "index/FileIndex.h"
21 #include "clang/Tooling/CompilationDatabase.h"
22 #include "clang/Tooling/Core/Replacement.h"
23 #include "llvm/ADT/IntrusiveRefCntPtr.h"
24 #include "llvm/ADT/Optional.h"
25 #include "llvm/ADT/StringRef.h"
26 #include <functional>
27 #include <future>
28 #include <string>
29 #include <type_traits>
30 #include <utility>
31 
32 namespace clang {
33 class PCHContainerOperations;
34 
35 namespace clangd {
36 
38 public:
39  virtual ~DiagnosticsConsumer() = default;
40 
41  /// Called by ClangdServer when \p Diagnostics for \p File are ready.
42  virtual void onDiagnosticsReady(PathRef File,
43  std::vector<Diag> Diagnostics) = 0;
44 };
45 
46 /// Provides API to manage ASTs for a collection of C++ files and request
47 /// various language features.
48 /// Currently supports async diagnostics, code completion, formatting and goto
49 /// definition.
50 class ClangdServer {
51 public:
52  struct Options {
53  /// To process requests asynchronously, ClangdServer spawns worker threads.
54  /// If 0, all requests are processed on the calling thread.
55  unsigned AsyncThreadsCount = getDefaultAsyncThreadsCount();
56 
57  /// AST caching policy. The default is to keep up to 3 ASTs in memory.
59 
60  /// Cached preambles are potentially large. If false, store them on disk.
61  bool StorePreamblesInMemory = true;
62 
63  /// If true, ClangdServer builds a dynamic in-memory index for symbols in
64  /// opened files and uses the index to augment code completion results.
65  bool BuildDynamicSymbolIndex = false;
66 
67  /// URI schemes to use when building the dynamic index.
68  /// If empty, the default schemes in SymbolCollector will be used.
69  std::vector<std::string> URISchemes;
70 
71  /// If set, use this index to augment code completion results.
72  SymbolIndex *StaticIndex = nullptr;
73 
74  /// The resource directory is used to find internal headers, overriding
75  /// defaults and -resource-dir compiler flag).
76  /// If None, ClangdServer calls CompilerInvocation::GetResourcePath() to
77  /// obtain the standard resource directory.
78  llvm::Optional<StringRef> ResourceDir = llvm::None;
79 
80  /// Time to wait after a new file version before computing diagnostics.
81  std::chrono::steady_clock::duration UpdateDebounce =
82  std::chrono::milliseconds(500);
83  };
84  // Sensible default options for use in tests.
85  // Features like indexing must be enabled if desired.
86  static Options optsForTest();
87 
88  /// Creates a new ClangdServer instance.
89  ///
90  /// ClangdServer uses \p CDB to obtain compilation arguments for parsing. Note
91  /// that ClangdServer only obtains compilation arguments once for each newly
92  /// added file (i.e., when processing a first call to addDocument) and reuses
93  /// those arguments for subsequent reparses. However, ClangdServer will check
94  /// if compilation arguments changed on calls to forceReparse().
95  ///
96  /// After each parsing request finishes, ClangdServer reports diagnostics to
97  /// \p DiagConsumer. Note that a callback to \p DiagConsumer happens on a
98  /// worker thread. Therefore, instances of \p DiagConsumer must properly
99  /// synchronize access to shared state.
101  DiagnosticsConsumer &DiagConsumer, const Options &Opts);
102 
103  /// Set the root path of the workspace.
104  void setRootPath(PathRef RootPath);
105 
106  /// Add a \p File to the list of tracked C++ files or update the contents if
107  /// \p File is already tracked. Also schedules parsing of the AST for it on a
108  /// separate thread. When the parsing is complete, DiagConsumer passed in
109  /// constructor will receive onDiagnosticsReady callback.
110  void addDocument(PathRef File, StringRef Contents,
112 
113  /// Remove \p File from list of tracked files, schedule a request to free
114  /// resources associated with it.
115  void removeDocument(PathRef File);
116 
117  /// Run code completion for \p File at \p Pos.
118  /// Request is processed asynchronously.
119  ///
120  /// This method should only be called for currently tracked files. However, it
121  /// is safe to call removeDocument for \p File after this method returns, even
122  /// while returned future is not yet ready.
123  /// A version of `codeComplete` that runs \p Callback on the processing thread
124  /// when codeComplete results become available.
126  const clangd::CodeCompleteOptions &Opts,
128 
129  /// Provide signature help for \p File at \p Pos. This method should only be
130  /// called for tracked files.
132 
133  /// Get definition of symbol at a specified \p Line and \p Column in \p File.
135  Callback<std::vector<Location>> CB);
136 
137  /// Helper function that returns a path to the corresponding source file when
138  /// given a header file and vice versa.
139  llvm::Optional<Path> switchSourceHeader(PathRef Path);
140 
141  /// Get document highlights for a given position.
143  Callback<std::vector<DocumentHighlight>> CB);
144 
145  /// Get code hover for a given position.
146  void findHover(PathRef File, Position Pos,
147  Callback<llvm::Optional<Hover>> CB);
148 
149  /// Retrieve the top symbols from the workspace matching a query.
150  void workspaceSymbols(StringRef Query, int Limit,
151  Callback<std::vector<SymbolInformation>> CB);
152 
153  /// Retrieve the symbols within the specified file.
154  void documentSymbols(StringRef File,
155  Callback<std::vector<SymbolInformation>> CB);
156 
157  /// Run formatting for \p Rng inside \p File with content \p Code.
158  llvm::Expected<tooling::Replacements> formatRange(StringRef Code,
159  PathRef File, Range Rng);
160 
161  /// Run formatting for the whole \p File with content \p Code.
162  llvm::Expected<tooling::Replacements> formatFile(StringRef Code,
163  PathRef File);
164 
165  /// Run formatting after a character was typed at \p Pos in \p File with
166  /// content \p Code.
167  llvm::Expected<tooling::Replacements>
168  formatOnType(StringRef Code, PathRef File, Position Pos);
169 
170  /// Rename all occurrences of the symbol at the \p Pos in \p File to
171  /// \p NewName.
172  void rename(PathRef File, Position Pos, llvm::StringRef NewName,
173  Callback<std::vector<tooling::Replacement>> CB);
174 
175  /// Only for testing purposes.
176  /// Waits until all requests to worker thread are finished and dumps AST for
177  /// \p File. \p File must be in the list of added documents.
178  void dumpAST(PathRef File, llvm::unique_function<void(std::string)> Callback);
179  /// Called when an event occurs for a watched file in the workspace.
180  void onFileEvent(const DidChangeWatchedFilesParams &Params);
181 
182  /// Returns estimated memory usage for each of the currently open files.
183  /// The order of results is unspecified.
184  /// Overall memory usage of clangd may be significantly more than reported
185  /// here, as this metric does not account (at least) for:
186  /// - memory occupied by static and dynamic index,
187  /// - memory required for in-flight requests,
188  /// FIXME: those metrics might be useful too, we should add them.
189  std::vector<std::pair<Path, std::size_t>> getUsedBytesPerFile() const;
190 
191  // Blocks the main thread until the server is idle. Only for use in tests.
192  // Returns false if the timeout expires.
193  LLVM_NODISCARD bool
194  blockUntilIdleForTest(llvm::Optional<double> TimeoutSeconds = 10);
195 
196 private:
197  /// FIXME: This stats several files to find a .clang-format file. I/O can be
198  /// slow. Think of a way to cache this.
199  llvm::Expected<tooling::Replacements>
200  formatCode(llvm::StringRef Code, PathRef File,
201  ArrayRef<tooling::Range> Ranges);
202 
203  typedef uint64_t DocVersion;
204 
205  void consumeDiagnostics(PathRef File, DocVersion Version,
206  std::vector<Diag> Diags);
207 
208  tooling::CompileCommand getCompileCommand(PathRef File);
209 
211  DiagnosticsConsumer &DiagConsumer;
212  FileSystemProvider &FSProvider;
213 
214  /// Used to synchronize diagnostic responses for added and removed files.
215  llvm::StringMap<DocVersion> InternalVersion;
216 
218  // The index used to look up symbols. This could be:
219  // - null (all index functionality is optional)
220  // - the dynamic index owned by ClangdServer (FileIdx)
221  // - the static index passed to the constructor
222  // - a merged view of a static and dynamic index (MergedIndex)
223  SymbolIndex *Index;
224  // If present, an up-to-date of symbols in open files. Read via Index.
225  std::unique_ptr<FileIndex> FileIdx;
226  // If present, a merged view of FileIdx and an external index. Read via Index.
227  std::unique_ptr<SymbolIndex> MergedIndex;
228  // If set, this represents the workspace path.
229  llvm::Optional<std::string> RootPath;
230  std::shared_ptr<PCHContainerOperations> PCHs;
231  /// Used to serialize diagnostic callbacks.
232  /// FIXME(ibiryukov): get rid of an extra map and put all version counters
233  /// into CppFile.
234  std::mutex DiagnosticsMutex;
235  /// Maps from a filename to the latest version of reported diagnostics.
236  llvm::StringMap<DocVersion> ReportedDiagnosticVersions;
237  // WorkScheduler has to be the last member, because its destructor has to be
238  // called before all other members to stop the worker thread that references
239  // ClangdServer.
240  TUScheduler WorkScheduler;
241 };
242 
243 } // namespace clangd
244 } // namespace clang
245 
246 #endif
WantDiagnostics
Determines whether diagnostics should be generated for a file snapshot.
Definition: TUScheduler.h:38
std::vector< Location > findDefinitions(ParsedAST &AST, Position Pos, const SymbolIndex *Index)
Get definition of symbol at a specified Pos.
Definition: XRefs.cpp:216
CodeCompleteResult codeComplete(PathRef FileName, const tooling::CompileCommand &Command, PrecompiledPreamble const *Preamble, const IncludeStructure &PreambleInclusions, StringRef Contents, Position Pos, IntrusiveRefCntPtr< vfs::FileSystem > VFS, std::shared_ptr< PCHContainerOperations > PCHs, CodeCompleteOptions Opts)
Get code completions at a specified Pos in FileName.
SignatureHelp signatureHelp(PathRef FileName, const tooling::CompileCommand &Command, PrecompiledPreamble const *Preamble, StringRef Contents, Position Pos, IntrusiveRefCntPtr< vfs::FileSystem > VFS, std::shared_ptr< PCHContainerOperations > PCHs)
Get signature help at a specified Pos in FileName.
void dumpAST(ParsedAST &AST, llvm::raw_ostream &OS)
For testing/debugging purposes.
Definition: ClangdUnit.cpp:119
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
Definition: Index.h:317
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:24
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
Definition: Function.h:28
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:58
StringRef Contents
Configuration of the AST retention policy.
Definition: TUScheduler.h:48
Provides compilation arguments used for parsing C and C++ files.
static llvm::cl::opt< Path > ResourceDir("resource-dir", llvm::cl::desc("Directory for system clang headers"), llvm::cl::init(""), llvm::cl::Hidden)
std::string Path
A typedef to represent a file path.
Definition: Path.h:21
virtual void onDiagnosticsReady(PathRef File, std::vector< Diag > Diagnostics)=0
Called by ClangdServer when Diagnostics for File are ready.
virtual ~DiagnosticsConsumer()=default
std::vector< DocumentHighlight > findDocumentHighlights(ParsedAST &AST, Position Pos)
Returns highlights for all usages of a symbol at Pos.
Definition: XRefs.cpp:391
Position Pos
unsigned getDefaultAsyncThreadsCount()
Returns a number of a default async threads to use for TUScheduler.
std::vector< std::string > URISchemes
URI schemes to use when building the dynamic index.
Definition: ClangdServer.h:69
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::shared_ptr< PCHContainerOperations > PCHs
Provides API to manage ASTs for a collection of C++ files and request various language features...
Definition: ClangdServer.h:50
Handles running tasks for ClangdServer and managing the resources (e.g., preambles and ASTs) for open...
Definition: TUScheduler.h:61
Diagnostics must not be generated for this snapshot.