clang-tools  8.0.0
ClangdServer.cpp
Go to the documentation of this file.
1 //===--- ClangdServer.cpp - 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 #include "ClangdServer.h"
11 #include "CodeComplete.h"
12 #include "FindSymbols.h"
13 #include "Headers.h"
14 #include "SourceCode.h"
15 #include "Trace.h"
16 #include "XRefs.h"
17 #include "index/FileIndex.h"
18 #include "index/Merge.h"
19 #include "clang/Format/Format.h"
20 #include "clang/Frontend/CompilerInstance.h"
21 #include "clang/Frontend/CompilerInvocation.h"
22 #include "clang/Lex/Preprocessor.h"
23 #include "clang/Tooling/CompilationDatabase.h"
24 #include "clang/Tooling/Refactoring/RefactoringResultConsumer.h"
25 #include "clang/Tooling/Refactoring/Rename/RenamingAction.h"
26 #include "llvm/ADT/ArrayRef.h"
27 #include "llvm/ADT/Optional.h"
28 #include "llvm/ADT/ScopeExit.h"
29 #include "llvm/ADT/StringRef.h"
30 #include "llvm/Support/Errc.h"
31 #include "llvm/Support/FileSystem.h"
32 #include "llvm/Support/Path.h"
33 #include "llvm/Support/raw_ostream.h"
34 #include <future>
35 #include <mutex>
36 
37 namespace clang {
38 namespace clangd {
39 namespace {
40 
41 class RefactoringResultCollector final
42  : public tooling::RefactoringResultConsumer {
43 public:
44  void handleError(llvm::Error Err) override {
45  assert(!Result.hasValue());
46  // FIXME: figure out a way to return better message for DiagnosticError.
47  // clangd uses llvm::toString to convert the Err to string, however, for
48  // DiagnosticError, only "clang diagnostic" will be generated.
49  Result = std::move(Err);
50  }
51 
52  // Using the handle(SymbolOccurrences) from parent class.
53  using tooling::RefactoringResultConsumer::handle;
54 
55  void handle(tooling::AtomicChanges SourceReplacements) override {
56  assert(!Result.hasValue());
57  Result = std::move(SourceReplacements);
58  }
59 
60  llvm::Optional<llvm::Expected<tooling::AtomicChanges>> Result;
61 };
62 
63 // Update the FileIndex with new ASTs and plumb the diagnostics responses.
64 struct UpdateIndexCallbacks : public ParsingCallbacks {
65  UpdateIndexCallbacks(FileIndex *FIndex, DiagnosticsConsumer &DiagConsumer)
66  : FIndex(FIndex), DiagConsumer(DiagConsumer) {}
67 
68  void onPreambleAST(PathRef Path, ASTContext &Ctx,
69  std::shared_ptr<clang::Preprocessor> PP) override {
70  if (FIndex)
71  FIndex->updatePreamble(Path, Ctx, std::move(PP));
72  }
73 
74  void onMainAST(PathRef Path, ParsedAST &AST) override {
75  if (FIndex)
76  FIndex->updateMain(Path, AST);
77  }
78 
79  void onDiagnostics(PathRef File, std::vector<Diag> Diags) override {
80  DiagConsumer.onDiagnosticsReady(File, std::move(Diags));
81  }
82 
83  void onFileUpdated(PathRef File, const TUStatus &Status) override {
84  DiagConsumer.onFileUpdated(File, Status);
85  }
86 
87 private:
88  FileIndex *FIndex;
89  DiagnosticsConsumer &DiagConsumer;
90 };
91 } // namespace
92 
95  Opts.UpdateDebounce = std::chrono::steady_clock::duration::zero(); // Faster!
96  Opts.StorePreamblesInMemory = true;
97  Opts.AsyncThreadsCount = 4; // Consistent!
98  return Opts;
99 }
100 
102  const FileSystemProvider &FSProvider,
103  DiagnosticsConsumer &DiagConsumer,
104  const Options &Opts)
105  : CDB(CDB), FSProvider(FSProvider),
106  DynamicIdx(Opts.BuildDynamicSymbolIndex
107  ? new FileIndex(Opts.HeavyweightDynamicSymbolIndex)
108  : nullptr),
109  WorkspaceRoot(Opts.WorkspaceRoot),
110  PCHs(std::make_shared<PCHContainerOperations>()),
111  // Pass a callback into `WorkScheduler` to extract symbols from a newly
112  // parsed file and rebuild the file index synchronously each time an AST
113  // is parsed.
114  // FIXME(ioeric): this can be slow and we may be able to index on less
115  // critical paths.
116  WorkScheduler(Opts.AsyncThreadsCount, Opts.StorePreamblesInMemory,
117  llvm::make_unique<UpdateIndexCallbacks>(DynamicIdx.get(),
118  DiagConsumer),
119  Opts.UpdateDebounce, Opts.RetentionPolicy) {
120  // Adds an index to the stack, at higher priority than existing indexes.
121  auto AddIndex = [&](SymbolIndex *Idx) {
122  if (this->Index != nullptr) {
123  MergedIdx.push_back(llvm::make_unique<MergedIndex>(Idx, this->Index));
124  this->Index = MergedIdx.back().get();
125  } else {
126  this->Index = Idx;
127  }
128  };
129  if (Opts.StaticIndex)
130  AddIndex(Opts.StaticIndex);
131  if (Opts.BackgroundIndex) {
132  BackgroundIdx = llvm::make_unique<BackgroundIndex>(
133  Context::current().clone(), FSProvider, CDB,
136  AddIndex(BackgroundIdx.get());
137  }
138  if (DynamicIdx)
139  AddIndex(DynamicIdx.get());
140 }
141 
143  WantDiagnostics WantDiags) {
144  // FIXME: some build systems like Bazel will take time to preparing
145  // environment to build the file, it would be nice if we could emit a
146  // "PreparingBuild" status to inform users, it is non-trivial given the
147  // current implementation.
148  WorkScheduler.update(File,
149  ParseInputs{getCompileCommand(File),
150  FSProvider.getFileSystem(), Contents.str()},
151  WantDiags);
152 }
153 
154 void ClangdServer::removeDocument(PathRef File) { WorkScheduler.remove(File); }
155 
157  const clangd::CodeCompleteOptions &Opts,
159  // Copy completion options for passing them to async task handler.
160  auto CodeCompleteOpts = Opts;
161  if (!CodeCompleteOpts.Index) // Respect overridden index.
162  CodeCompleteOpts.Index = Index;
163 
164  // Copy PCHs to avoid accessing this->PCHs concurrently
165  std::shared_ptr<PCHContainerOperations> PCHs = this->PCHs;
166  auto FS = FSProvider.getFileSystem();
167 
168  auto Task = [PCHs, Pos, FS, CodeCompleteOpts,
170  llvm::Expected<InputsAndPreamble> IP) {
171  if (!IP)
172  return CB(IP.takeError());
173  if (isCancelled())
174  return CB(llvm::make_error<CancelledError>());
175 
176  llvm::Optional<SpeculativeFuzzyFind> SpecFuzzyFind;
177  if (CodeCompleteOpts.Index && CodeCompleteOpts.SpeculativeIndexRequest) {
178  SpecFuzzyFind.emplace();
179  {
180  std::lock_guard<std::mutex> Lock(CachedCompletionFuzzyFindRequestMutex);
181  SpecFuzzyFind->CachedReq = CachedCompletionFuzzyFindRequestByFile[File];
182  }
183  }
184 
185  // FIXME(ibiryukov): even if Preamble is non-null, we may want to check
186  // both the old and the new version in case only one of them matches.
188  File, IP->Command, IP->Preamble, IP->Contents, Pos, FS, PCHs,
189  CodeCompleteOpts, SpecFuzzyFind ? SpecFuzzyFind.getPointer() : nullptr);
190  {
191  clang::clangd::trace::Span Tracer("Completion results callback");
192  CB(std::move(Result));
193  }
194  if (SpecFuzzyFind && SpecFuzzyFind->NewReq.hasValue()) {
195  std::lock_guard<std::mutex> Lock(CachedCompletionFuzzyFindRequestMutex);
196  CachedCompletionFuzzyFindRequestByFile[File] =
197  SpecFuzzyFind->NewReq.getValue();
198  }
199  // SpecFuzzyFind is only destroyed after speculative fuzzy find finishes.
200  // We don't want `codeComplete` to wait for the async call if it doesn't use
201  // the result (e.g. non-index completion, speculation fails), so that `CB`
202  // is called as soon as results are available.
203  };
204 
205  // We use a potentially-stale preamble because latency is critical here.
206  WorkScheduler.runWithPreamble("CodeComplete", File, TUScheduler::Stale,
207  Bind(Task, File.str(), std::move(CB)));
208 }
209 
212 
213  auto PCHs = this->PCHs;
214  auto FS = FSProvider.getFileSystem();
215  auto *Index = this->Index;
216  auto Action = [Pos, FS, PCHs, Index](Path File, Callback<SignatureHelp> CB,
217  llvm::Expected<InputsAndPreamble> IP) {
218  if (!IP)
219  return CB(IP.takeError());
220 
221  auto PreambleData = IP->Preamble;
222  CB(clangd::signatureHelp(File, IP->Command, PreambleData, IP->Contents, Pos,
223  FS, PCHs, Index));
224  };
225 
226  // Unlike code completion, we wait for an up-to-date preamble here.
227  // Signature help is often triggered after code completion. If the code
228  // completion inserted a header to make the symbol available, then using
229  // the old preamble would yield useless results.
230  WorkScheduler.runWithPreamble("SignatureHelp", File, TUScheduler::Consistent,
231  Bind(Action, File.str(), std::move(CB)));
232 }
233 
234 llvm::Expected<tooling::Replacements>
235 ClangdServer::formatRange(llvm::StringRef Code, PathRef File, Range Rng) {
236  llvm::Expected<size_t> Begin = positionToOffset(Code, Rng.start);
237  if (!Begin)
238  return Begin.takeError();
239  llvm::Expected<size_t> End = positionToOffset(Code, Rng.end);
240  if (!End)
241  return End.takeError();
242  return formatCode(Code, File, {tooling::Range(*Begin, *End - *Begin)});
243 }
244 
245 llvm::Expected<tooling::Replacements>
246 ClangdServer::formatFile(llvm::StringRef Code, PathRef File) {
247  // Format everything.
248  return formatCode(Code, File, {tooling::Range(0, Code.size())});
249 }
250 
251 llvm::Expected<tooling::Replacements>
253  // Look for the previous opening brace from the character position and
254  // format starting from there.
255  llvm::Expected<size_t> CursorPos = positionToOffset(Code, Pos);
256  if (!CursorPos)
257  return CursorPos.takeError();
258  size_t PreviousLBracePos =
259  llvm::StringRef(Code).find_last_of('{', *CursorPos);
260  if (PreviousLBracePos == llvm::StringRef::npos)
261  PreviousLBracePos = *CursorPos;
262  size_t Len = *CursorPos - PreviousLBracePos;
263 
264  return formatCode(Code, File, {tooling::Range(PreviousLBracePos, Len)});
265 }
266 
267 void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
268  Callback<std::vector<tooling::Replacement>> CB) {
269  auto Action = [Pos](Path File, std::string NewName,
271  llvm::Expected<InputsAndAST> InpAST) {
272  if (!InpAST)
273  return CB(InpAST.takeError());
274  auto &AST = InpAST->AST;
275 
276  RefactoringResultCollector ResultCollector;
277  const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
278  SourceLocation SourceLocationBeg =
279  clangd::getBeginningOfIdentifier(AST, Pos, SourceMgr.getMainFileID());
280  tooling::RefactoringRuleContext Context(
281  AST.getASTContext().getSourceManager());
282  Context.setASTContext(AST.getASTContext());
283  auto Rename = clang::tooling::RenameOccurrences::initiate(
284  Context, SourceRange(SourceLocationBeg), NewName);
285  if (!Rename)
286  return CB(Rename.takeError());
287 
288  Rename->invoke(ResultCollector, Context);
289 
290  assert(ResultCollector.Result.hasValue());
291  if (!ResultCollector.Result.getValue())
292  return CB(ResultCollector.Result->takeError());
293 
294  std::vector<tooling::Replacement> Replacements;
295  for (const tooling::AtomicChange &Change : ResultCollector.Result->get()) {
296  tooling::Replacements ChangeReps = Change.getReplacements();
297  for (const auto &Rep : ChangeReps) {
298  // FIXME: Right now we only support renaming the main file, so we
299  // drop replacements not for the main file. In the future, we might
300  // consider to support:
301  // * rename in any included header
302  // * rename only in the "main" header
303  // * provide an error if there are symbols we won't rename (e.g.
304  // std::vector)
305  // * rename globally in project
306  // * rename in open files
307  if (Rep.getFilePath() == File)
308  Replacements.push_back(Rep);
309  }
310  }
311  return CB(std::move(Replacements));
312  };
313 
314  WorkScheduler.runWithAST(
315  "Rename", File, Bind(Action, File.str(), NewName.str(), std::move(CB)));
316 }
317 
319  llvm::unique_function<void(std::string)> Callback) {
320  auto Action = [](decltype(Callback) Callback,
321  llvm::Expected<InputsAndAST> InpAST) {
322  if (!InpAST) {
323  llvm::consumeError(InpAST.takeError());
324  return Callback("<no-ast>");
325  }
326  std::string Result;
327 
328  llvm::raw_string_ostream ResultOS(Result);
329  clangd::dumpAST(InpAST->AST, ResultOS);
330  ResultOS.flush();
331 
332  Callback(Result);
333  };
334 
335  WorkScheduler.runWithAST("DumpAST", File, Bind(Action, std::move(Callback)));
336 }
337 
339  Callback<std::vector<Location>> CB) {
340  auto Action = [Pos, this](Callback<std::vector<Location>> CB,
341  llvm::Expected<InputsAndAST> InpAST) {
342  if (!InpAST)
343  return CB(InpAST.takeError());
344  CB(clangd::findDefinitions(InpAST->AST, Pos, Index));
345  };
346 
347  WorkScheduler.runWithAST("Definitions", File, Bind(Action, std::move(CB)));
348 }
349 
351 
352  llvm::StringRef SourceExtensions[] = {".cpp", ".c", ".cc", ".cxx",
353  ".c++", ".m", ".mm"};
354  llvm::StringRef HeaderExtensions[] = {".h", ".hh", ".hpp", ".hxx", ".inc"};
355 
356  llvm::StringRef PathExt = llvm::sys::path::extension(Path);
357 
358  // Lookup in a list of known extensions.
359  auto SourceIter =
360  llvm::find_if(SourceExtensions, [&PathExt](PathRef SourceExt) {
361  return SourceExt.equals_lower(PathExt);
362  });
363  bool IsSource = SourceIter != std::end(SourceExtensions);
364 
365  auto HeaderIter =
366  llvm::find_if(HeaderExtensions, [&PathExt](PathRef HeaderExt) {
367  return HeaderExt.equals_lower(PathExt);
368  });
369 
370  bool IsHeader = HeaderIter != std::end(HeaderExtensions);
371 
372  // We can only switch between the known extensions.
373  if (!IsSource && !IsHeader)
374  return None;
375 
376  // Array to lookup extensions for the switch. An opposite of where original
377  // extension was found.
378  llvm::ArrayRef<llvm::StringRef> NewExts;
379  if (IsSource)
380  NewExts = HeaderExtensions;
381  else
382  NewExts = SourceExtensions;
383 
384  // Storage for the new path.
385  llvm::SmallString<128> NewPath = llvm::StringRef(Path);
386 
387  // Instance of vfs::FileSystem, used for file existence checks.
388  auto FS = FSProvider.getFileSystem();
389 
390  // Loop through switched extension candidates.
391  for (llvm::StringRef NewExt : NewExts) {
392  llvm::sys::path::replace_extension(NewPath, NewExt);
393  if (FS->exists(NewPath))
394  return NewPath.str().str(); // First str() to convert from SmallString to
395  // StringRef, second to convert from StringRef
396  // to std::string
397 
398  // Also check NewExt in upper-case, just in case.
399  llvm::sys::path::replace_extension(NewPath, NewExt.upper());
400  if (FS->exists(NewPath))
401  return NewPath.str().str();
402  }
403 
404  return None;
405 }
406 
407 llvm::Expected<tooling::Replacements>
408 ClangdServer::formatCode(llvm::StringRef Code, PathRef File,
409  llvm::ArrayRef<tooling::Range> Ranges) {
410  // Call clang-format.
411  auto FS = FSProvider.getFileSystem();
412  auto Style = format::getStyle(format::DefaultFormatStyle, File,
413  format::DefaultFallbackStyle, Code, FS.get());
414  if (!Style)
415  return Style.takeError();
416 
417  tooling::Replacements IncludeReplaces =
418  format::sortIncludes(*Style, Code, Ranges, File);
419  auto Changed = tooling::applyAllReplacements(Code, IncludeReplaces);
420  if (!Changed)
421  return Changed.takeError();
422 
423  return IncludeReplaces.merge(format::reformat(
424  Style.get(), *Changed,
425  tooling::calculateRangesAfterReplacements(IncludeReplaces, Ranges),
426  File));
427 }
428 
430  PathRef File, Position Pos, Callback<std::vector<DocumentHighlight>> CB) {
432  llvm::Expected<InputsAndAST> InpAST) {
433  if (!InpAST)
434  return CB(InpAST.takeError());
435  CB(clangd::findDocumentHighlights(InpAST->AST, Pos));
436  };
437 
438  WorkScheduler.runWithAST("Highlights", File, Bind(Action, std::move(CB)));
439 }
440 
442  Callback<llvm::Optional<Hover>> CB) {
444  llvm::Expected<InputsAndAST> InpAST) {
445  if (!InpAST)
446  return CB(InpAST.takeError());
447  CB(clangd::getHover(InpAST->AST, Pos));
448  };
449 
450  WorkScheduler.runWithAST("Hover", File, Bind(Action, std::move(CB)));
451 }
452 
453 tooling::CompileCommand ClangdServer::getCompileCommand(PathRef File) {
454  trace::Span Span("GetCompileCommand");
455  llvm::Optional<tooling::CompileCommand> C = CDB.getCompileCommand(File);
456  if (!C) // FIXME: Suppress diagnostics? Let the user know?
457  C = CDB.getFallbackCommand(File);
458  return std::move(*C);
459 }
460 
462  // FIXME: Do nothing for now. This will be used for indexing and potentially
463  // invalidating other caches.
464 }
465 
467  llvm::StringRef Query, int Limit,
468  Callback<std::vector<SymbolInformation>> CB) {
469  std::string QueryCopy = Query;
470  WorkScheduler.run(
471  "getWorkspaceSymbols",
472  Bind(
473  [QueryCopy, Limit, this](decltype(CB) CB) {
474  CB(clangd::getWorkspaceSymbols(QueryCopy, Limit, Index,
475  WorkspaceRoot.getValueOr("")));
476  },
477  std::move(CB)));
478 }
479 
480 void ClangdServer::documentSymbols(llvm::StringRef File,
481  Callback<std::vector<DocumentSymbol>> CB) {
483  llvm::Expected<InputsAndAST> InpAST) {
484  if (!InpAST)
485  return CB(InpAST.takeError());
486  CB(clangd::getDocumentSymbols(InpAST->AST));
487  };
488  WorkScheduler.runWithAST("documentSymbols", File,
489  Bind(Action, std::move(CB)));
490 }
491 
493  Callback<std::vector<Location>> CB) {
494  auto Action = [Pos, Limit, this](Callback<std::vector<Location>> CB,
495  llvm::Expected<InputsAndAST> InpAST) {
496  if (!InpAST)
497  return CB(InpAST.takeError());
498  CB(clangd::findReferences(InpAST->AST, Pos, Limit, Index));
499  };
500 
501  WorkScheduler.runWithAST("References", File, Bind(Action, std::move(CB)));
502 }
503 
505  Callback<std::vector<SymbolDetails>> CB) {
507  llvm::Expected<InputsAndAST> InpAST) {
508  if (!InpAST)
509  return CB(InpAST.takeError());
510  CB(clangd::getSymbolInfo(InpAST->AST, Pos));
511  };
512 
513  WorkScheduler.runWithAST("SymbolInfo", File, Bind(Action, std::move(CB)));
514 }
515 
516 std::vector<std::pair<Path, std::size_t>>
518  return WorkScheduler.getUsedBytesPerFile();
519 }
520 
521 LLVM_NODISCARD bool
522 ClangdServer::blockUntilIdleForTest(llvm::Optional<double> TimeoutSeconds) {
523  return WorkScheduler.blockUntilIdle(timeoutSeconds(TimeoutSeconds)) &&
524  (!BackgroundIdx ||
525  BackgroundIdx->blockUntilIdleForTest(TimeoutSeconds));
526 }
527 
528 } // namespace clangd
529 } // namespace clang
SignatureHelp signatureHelp(PathRef FileName, const tooling::CompileCommand &Command, const PreambleData *Preamble, llvm::StringRef Contents, Position Pos, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, std::shared_ptr< PCHContainerOperations > PCHs, const SymbolIndex *Index)
llvm::Optional< Hover > getHover(ParsedAST &AST, Position Pos)
Get the hover information when hovering at Pos.
Definition: XRefs.cpp:686
void findDefinitions(PathRef File, Position Pos, Callback< std::vector< Location >> CB)
Get definition of symbol at a specified Line and Column in File.
WantDiagnostics
Determines whether diagnostics should be generated for a file snapshot.
Definition: TUScheduler.h:39
std::vector< Location > findDefinitions(ParsedAST &AST, Position Pos, const SymbolIndex *Index)
Get definition of symbol at a specified Pos.
Definition: XRefs.cpp:244
void addDocument(PathRef File, StringRef Contents, WantDiagnostics WD=WantDiagnostics::Auto)
Add a File to the list of tracked C++ files or update the contents if File is already tracked...
CodeCompleteResult codeComplete(PathRef FileName, const tooling::CompileCommand &Command, const PreambleData *Preamble, llvm::StringRef Contents, Position Pos, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, std::shared_ptr< PCHContainerOperations > PCHs, CodeCompleteOptions Opts, SpeculativeFuzzyFind *SpecFuzzyFind)
llvm::Expected< std::vector< SymbolInformation > > getWorkspaceSymbols(llvm::StringRef Query, int Limit, const SymbolIndex *const Index, llvm::StringRef HintPath)
Searches for the symbols matching Query.
llvm::StringRef Contents
Some operations such as code completion produce a set of candidates.
void codeComplete(PathRef File, Position Pos, const clangd::CodeCompleteOptions &Opts, Callback< CodeCompleteResult > CB)
Run code completion for File at Pos.
Position start
The range&#39;s start position.
Definition: Protocol.h:156
The preamble may be generated from an older version of the file.
Definition: TUScheduler.h:179
llvm::Expected< tooling::Replacements > formatOnType(StringRef Code, PathRef File, Position Pos)
Run formatting after a character was typed at Pos in File with content Code.
bool BackgroundIndex
If true, ClangdServer automatically indexes files in the current project on background threads...
Definition: ClangdServer.h:87
bool blockUntilIdle(Deadline D) const
Wait until there are no scheduled or running tasks.
void findHover(PathRef File, Position Pos, Callback< llvm::Optional< Hover >> CB)
Get code hover for a given position.
void remove(PathRef File)
Remove File from the list of tracked files and schedule removal of its resources. ...
void dumpAST(ParsedAST &AST, llvm::raw_ostream &OS)
For testing/debugging purposes.
Definition: ClangdUnit.cpp:222
void onFileEvent(const DidChangeWatchedFilesParams &Params)
Called when an event occurs for a watched file in the workspace.
virtual llvm::Optional< tooling::CompileCommand > getCompileCommand(PathRef File, ProjectInfo *=nullptr) const =0
If there are any known-good commands for building this file, returns one.
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
Definition: Index.h:487
ClangdServer(const GlobalCompilationDatabase &CDB, const FileSystemProvider &FSProvider, DiagnosticsConsumer &DiagConsumer, const Options &Opts)
Creates a new ClangdServer instance.
This manages symbols from files and an in-memory index on all symbols.
Definition: FileIndex.h:81
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:24
void update(PathRef File, ParseInputs Inputs, WantDiagnostics WD)
Schedule an update for File.
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
Definition: Function.h:29
LLVM_NODISCARD bool blockUntilIdleForTest(llvm::Optional< double > TimeoutSeconds=10)
static Options optsForTest()
Documents should not be synced at all.
void findDocumentHighlights(PathRef File, Position Pos, Callback< std::vector< DocumentHighlight >> CB)
Get document highlights for a given position.
unsigned AsyncThreadsCount
To process requests asynchronously, ClangdServer spawns worker threads.
Definition: ClangdServer.h:71
bool isCancelled(const Context &Ctx)
True if the current context is within a cancelable task which was cancelled.
void findReferences(PathRef File, Position Pos, uint32_t Limit, Callback< std::vector< Location >> CB)
Retrieve locations for symbol references.
Provides compilation arguments used for parsing C and C++ files.
Context Ctx
std::vector< SymbolDetails > getSymbolInfo(ParsedAST &AST, Position Pos)
Get info about symbols at Pos.
Definition: XRefs.cpp:765
Context clone() const
Clone this context object.
Definition: Context.cpp:21
llvm::Expected< size_t > positionToOffset(llvm::StringRef Code, Position P, bool AllowColumnsBeyondLineLength)
Turn a [line, column] pair into an offset in Code.
Definition: SourceCode.cpp:81
ForwardBinder< Func, Args... > Bind(Func F, Args &&... As)
Creates an object that stores a callable (F) and first arguments to the callable (As) and allows to c...
Definition: Function.h:82
llvm::unique_function< void()> Action
std::string Path
A typedef to represent a file path.
Definition: Path.h:21
static const Context & current()
Returns the context for the current thread, creating it if needed.
Definition: Context.cpp:28
std::vector< std::pair< Path, std::size_t > > getUsedBytesPerFile() const
Returns estimated memory usage for each of the currently open files.
void runWithPreamble(llvm::StringRef Name, PathRef File, PreambleConsistency Consistency, Callback< InputsAndPreamble > Action)
Schedule an async read of the preamble.
std::chrono::steady_clock::duration UpdateDebounce
Time to wait after a new file version before computing diagnostics.
Definition: ClangdServer.h:108
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
void dumpAST(PathRef File, llvm::unique_function< void(std::string)> Callback)
Only for testing purposes.
void documentSymbols(StringRef File, Callback< std::vector< DocumentSymbol >> CB)
Retrieve the symbols within the specified file.
std::vector< DocumentHighlight > findDocumentHighlights(ParsedAST &AST, Position Pos)
Returns highlights for all usages of a symbol at Pos.
Definition: XRefs.cpp:434
A context is an immutable container for per-request data that must be propagated through layers that ...
Definition: Context.h:70
void rename(PathRef File, Position Pos, llvm::StringRef NewName, Callback< std::vector< tooling::Replacement >> CB)
Rename all occurrences of the symbol at the Pos in File to NewName.
size_t BackgroundIndexRebuildPeriodMs
If set to non-zero, the background index rebuilds the symbol index periodically every BuildIndexPerio...
Definition: ClangdServer.h:91
std::vector< std::pair< Path, std::size_t > > getUsedBytesPerFile() const
Returns estimated memory usage for each of the currently open files.
Position Pos
const SymbolIndex * Index
If Index is set, it is used to augment the code completion results.
Definition: CodeComplete.h:96
llvm::Expected< tooling::Replacements > formatRange(StringRef Code, PathRef File, Range Rng)
Run formatting for Rng inside File with content Code.
std::vector< Location > findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, const SymbolIndex *Index)
Returns reference locations of the symbol at a specified Pos.
Definition: XRefs.cpp:706
Information required to run clang, e.g. to parse AST or do code completion.
Definition: ClangdUnit.h:64
bool StorePreamblesInMemory
Cached preambles are potentially large. If false, store them on disk.
Definition: ClangdServer.h:77
SourceLocation getBeginningOfIdentifier(ParsedAST &Unit, const Position &Pos, const FileID FID)
Get the beginning SourceLocation at a specified Pos.
Definition: ClangdUnit.cpp:545
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Deadline timeoutSeconds(llvm::Optional< double > Seconds)
Makes a deadline from a timeout in seconds. None means wait forever.
Definition: Threading.cpp:95
llvm::Expected< std::vector< DocumentSymbol > > getDocumentSymbols(ParsedAST &AST)
Retrieves the symbols contained in the "main file" section of an AST in the same order that they appe...
std::shared_ptr< PCHContainerOperations > PCHs
CharSourceRange Range
SourceRange for the file name.
void removeDocument(PathRef File)
Remove File from list of tracked files, schedule a request to free resources associated with it...
void runWithAST(llvm::StringRef Name, PathRef File, Callback< InputsAndAST > Action)
Schedule an async read of the AST.
void symbolInfo(PathRef File, Position Pos, Callback< std::vector< SymbolDetails >> CB)
Get symbol info for given position.
PrecompiledPreamble Preamble
Definition: ClangdUnit.h:53
Position end
The range&#39;s end position.
Definition: Protocol.h:159
Records an event whose duration is the lifetime of the Span object.
Definition: Trace.h:83
SymbolIndex * StaticIndex
If set, use this index to augment code completion results.
Definition: ClangdServer.h:94
void workspaceSymbols(StringRef Query, int Limit, Callback< std::vector< SymbolInformation >> CB)
Retrieve the top symbols from the workspace matching a query.
llvm::Expected< tooling::Replacements > formatFile(StringRef Code, PathRef File)
Run formatting for the whole File with content Code.
void signatureHelp(PathRef File, Position Pos, Callback< SignatureHelp > CB)
Provide signature help for File at Pos.
The preamble is generated from the current version of the file.
Definition: TUScheduler.h:171
llvm::Optional< Path > switchSourceHeader(PathRef Path)
Helper function that returns a path to the corresponding source file when given a header file and vic...
virtual tooling::CompileCommand getFallbackCommand(PathRef File) const
Makes a guess at how to build a file.
void run(llvm::StringRef Name, llvm::unique_function< void()> Action)
Schedule an async task with no dependencies.
virtual llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > getFileSystem() const =0
Called by ClangdServer to obtain a vfs::FileSystem to be used for parsing.