clang-tools  9.0.0svn
ClangdServer.cpp
Go to the documentation of this file.
1 //===--- ClangdServer.cpp - 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 #include "ClangdServer.h"
10 #include "ClangdUnit.h"
11 #include "CodeComplete.h"
12 #include "FindSymbols.h"
13 #include "Headers.h"
14 #include "Protocol.h"
15 #include "SourceCode.h"
16 #include "TUScheduler.h"
17 #include "Trace.h"
19 #include "index/FileIndex.h"
20 #include "index/Merge.h"
21 #include "refactor/Tweak.h"
22 #include "clang/Format/Format.h"
23 #include "clang/Frontend/CompilerInstance.h"
24 #include "clang/Frontend/CompilerInvocation.h"
25 #include "clang/Lex/Preprocessor.h"
26 #include "clang/Tooling/CompilationDatabase.h"
27 #include "clang/Tooling/Core/Replacement.h"
28 #include "clang/Tooling/Refactoring/RefactoringResultConsumer.h"
29 #include "clang/Tooling/Refactoring/Rename/RenamingAction.h"
30 #include "llvm/ADT/ArrayRef.h"
31 #include "llvm/ADT/Optional.h"
32 #include "llvm/ADT/ScopeExit.h"
33 #include "llvm/ADT/StringRef.h"
34 #include "llvm/Support/Errc.h"
35 #include "llvm/Support/Error.h"
36 #include "llvm/Support/FileSystem.h"
37 #include "llvm/Support/Path.h"
38 #include "llvm/Support/raw_ostream.h"
39 #include <future>
40 #include <memory>
41 #include <mutex>
42 
43 namespace clang {
44 namespace clangd {
45 namespace {
46 
47 // Expand a DiagnosticError to make it print-friendly (print the detailed
48 // message, rather than "clang diagnostic").
49 llvm::Error expandDiagnostics(llvm::Error Err, DiagnosticsEngine &DE) {
50  if (auto Diag = DiagnosticError::take(Err)) {
51  llvm::cantFail(std::move(Err));
52  SmallVector<char, 128> DiagMessage;
53  Diag->second.EmitToString(DE, DiagMessage);
54  return llvm::make_error<llvm::StringError>(DiagMessage,
55  llvm::inconvertibleErrorCode());
56  }
57  return Err;
58 }
59 
60 class RefactoringResultCollector final
61  : public tooling::RefactoringResultConsumer {
62 public:
63  void handleError(llvm::Error Err) override {
64  assert(!Result.hasValue());
65  Result = std::move(Err);
66  }
67 
68  // Using the handle(SymbolOccurrences) from parent class.
69  using tooling::RefactoringResultConsumer::handle;
70 
71  void handle(tooling::AtomicChanges SourceReplacements) override {
72  assert(!Result.hasValue());
73  Result = std::move(SourceReplacements);
74  }
75 
76  llvm::Optional<llvm::Expected<tooling::AtomicChanges>> Result;
77 };
78 
79 // Update the FileIndex with new ASTs and plumb the diagnostics responses.
80 struct UpdateIndexCallbacks : public ParsingCallbacks {
81  UpdateIndexCallbacks(FileIndex *FIndex, DiagnosticsConsumer &DiagConsumer)
82  : FIndex(FIndex), DiagConsumer(DiagConsumer) {}
83 
84  void onPreambleAST(PathRef Path, ASTContext &Ctx,
85  std::shared_ptr<clang::Preprocessor> PP,
86  const CanonicalIncludes &CanonIncludes) override {
87  if (FIndex)
88  FIndex->updatePreamble(Path, Ctx, std::move(PP), CanonIncludes);
89  }
90 
91  void onMainAST(PathRef Path, ParsedAST &AST) override {
92  if (FIndex)
93  FIndex->updateMain(Path, AST);
94  }
95 
96  void onDiagnostics(PathRef File, std::vector<Diag> Diags) override {
97  DiagConsumer.onDiagnosticsReady(File, std::move(Diags));
98  }
99 
100  void onFileUpdated(PathRef File, const TUStatus &Status) override {
101  DiagConsumer.onFileUpdated(File, Status);
102  }
103 
104 private:
105  FileIndex *FIndex;
106  DiagnosticsConsumer &DiagConsumer;
107 };
108 } // namespace
109 
112  Opts.UpdateDebounce = std::chrono::steady_clock::duration::zero(); // Faster!
113  Opts.StorePreamblesInMemory = true;
114  Opts.AsyncThreadsCount = 4; // Consistent!
115  return Opts;
116 }
117 
119  const FileSystemProvider &FSProvider,
120  DiagnosticsConsumer &DiagConsumer,
121  const Options &Opts)
122  : FSProvider(FSProvider),
123  DynamicIdx(Opts.BuildDynamicSymbolIndex
124  ? new FileIndex(Opts.HeavyweightDynamicSymbolIndex)
125  : nullptr),
126  ClangTidyOptProvider(Opts.ClangTidyOptProvider),
128  WorkspaceRoot(Opts.WorkspaceRoot),
129  // Pass a callback into `WorkScheduler` to extract symbols from a newly
130  // parsed file and rebuild the file index synchronously each time an AST
131  // is parsed.
132  // FIXME(ioeric): this can be slow and we may be able to index on less
133  // critical paths.
134  WorkScheduler(CDB, Opts.AsyncThreadsCount, Opts.StorePreamblesInMemory,
135  llvm::make_unique<UpdateIndexCallbacks>(DynamicIdx.get(),
136  DiagConsumer),
137  Opts.UpdateDebounce, Opts.RetentionPolicy) {
138  // Adds an index to the stack, at higher priority than existing indexes.
139  auto AddIndex = [&](SymbolIndex *Idx) {
140  if (this->Index != nullptr) {
141  MergedIdx.push_back(llvm::make_unique<MergedIndex>(Idx, this->Index));
142  this->Index = MergedIdx.back().get();
143  } else {
144  this->Index = Idx;
145  }
146  };
147  if (Opts.StaticIndex)
148  AddIndex(Opts.StaticIndex);
149  if (Opts.BackgroundIndex) {
150  BackgroundIdx = llvm::make_unique<BackgroundIndex>(
151  Context::current().clone(), FSProvider, CDB,
154  AddIndex(BackgroundIdx.get());
155  }
156  if (DynamicIdx)
157  AddIndex(DynamicIdx.get());
158 }
159 
161  WantDiagnostics WantDiags) {
162  ParseOptions Opts;
164  if (ClangTidyOptProvider)
165  Opts.ClangTidyOpts = ClangTidyOptProvider->getOptions(File);
166  Opts.SuggestMissingIncludes = SuggestMissingIncludes;
167 
168  // Compile command is set asynchronously during update, as it can be slow.
169  ParseInputs Inputs;
170  Inputs.FS = FSProvider.getFileSystem();
171  Inputs.Contents = Contents;
172  Inputs.Opts = std::move(Opts);
173  Inputs.Index = Index;
174  WorkScheduler.update(File, Inputs, WantDiags);
175 }
176 
177 void ClangdServer::removeDocument(PathRef File) { WorkScheduler.remove(File); }
178 
180  const clangd::CodeCompleteOptions &Opts,
182  // Copy completion options for passing them to async task handler.
183  auto CodeCompleteOpts = Opts;
184  if (!CodeCompleteOpts.Index) // Respect overridden index.
185  CodeCompleteOpts.Index = Index;
186 
187  auto FS = FSProvider.getFileSystem();
188  auto Task = [Pos, FS, CodeCompleteOpts,
190  llvm::Expected<InputsAndPreamble> IP) {
191  if (!IP)
192  return CB(IP.takeError());
193  if (isCancelled())
194  return CB(llvm::make_error<CancelledError>());
195 
196  llvm::Optional<SpeculativeFuzzyFind> SpecFuzzyFind;
197  if (!IP->Preamble) {
198  // No speculation in Fallback mode, as it's supposed to be much faster
199  // without compiling.
200  vlog("Build for file {0} is not ready. Enter fallback mode.", File);
201  } else {
202  if (CodeCompleteOpts.Index && CodeCompleteOpts.SpeculativeIndexRequest) {
203  SpecFuzzyFind.emplace();
204  {
205  std::lock_guard<std::mutex> Lock(
206  CachedCompletionFuzzyFindRequestMutex);
207  SpecFuzzyFind->CachedReq =
208  CachedCompletionFuzzyFindRequestByFile[File];
209  }
210  }
211  }
212  // FIXME(ibiryukov): even if Preamble is non-null, we may want to check
213  // both the old and the new version in case only one of them matches.
215  File, IP->Command, IP->Preamble, IP->Contents, Pos, FS,
216  CodeCompleteOpts, SpecFuzzyFind ? SpecFuzzyFind.getPointer() : nullptr);
217  {
218  clang::clangd::trace::Span Tracer("Completion results callback");
219  CB(std::move(Result));
220  }
221  if (SpecFuzzyFind && SpecFuzzyFind->NewReq.hasValue()) {
222  std::lock_guard<std::mutex> Lock(CachedCompletionFuzzyFindRequestMutex);
223  CachedCompletionFuzzyFindRequestByFile[File] =
224  SpecFuzzyFind->NewReq.getValue();
225  }
226  // SpecFuzzyFind is only destroyed after speculative fuzzy find finishes.
227  // We don't want `codeComplete` to wait for the async call if it doesn't use
228  // the result (e.g. non-index completion, speculation fails), so that `CB`
229  // is called as soon as results are available.
230  };
231 
232  // We use a potentially-stale preamble because latency is critical here.
233  WorkScheduler.runWithPreamble("CodeComplete", File,
236  Bind(Task, File.str(), std::move(CB)));
237 }
238 
241 
242  auto FS = FSProvider.getFileSystem();
243  auto *Index = this->Index;
244  auto Action = [Pos, FS, Index](Path File, Callback<SignatureHelp> CB,
245  llvm::Expected<InputsAndPreamble> IP) {
246  if (!IP)
247  return CB(IP.takeError());
248 
249  auto PreambleData = IP->Preamble;
250  CB(clangd::signatureHelp(File, IP->Command, PreambleData, IP->Contents, Pos,
251  FS, Index));
252  };
253 
254  // Unlike code completion, we wait for an up-to-date preamble here.
255  // Signature help is often triggered after code completion. If the code
256  // completion inserted a header to make the symbol available, then using
257  // the old preamble would yield useless results.
258  WorkScheduler.runWithPreamble("SignatureHelp", File, TUScheduler::Consistent,
259  Bind(Action, File.str(), std::move(CB)));
260 }
261 
262 llvm::Expected<tooling::Replacements>
263 ClangdServer::formatRange(llvm::StringRef Code, PathRef File, Range Rng) {
264  llvm::Expected<size_t> Begin = positionToOffset(Code, Rng.start);
265  if (!Begin)
266  return Begin.takeError();
267  llvm::Expected<size_t> End = positionToOffset(Code, Rng.end);
268  if (!End)
269  return End.takeError();
270  return formatCode(Code, File, {tooling::Range(*Begin, *End - *Begin)});
271 }
272 
273 llvm::Expected<tooling::Replacements>
274 ClangdServer::formatFile(llvm::StringRef Code, PathRef File) {
275  // Format everything.
276  return formatCode(Code, File, {tooling::Range(0, Code.size())});
277 }
278 
279 llvm::Expected<tooling::Replacements>
280 ClangdServer::formatOnType(llvm::StringRef Code, PathRef File, Position Pos) {
281  // Look for the previous opening brace from the character position and
282  // format starting from there.
283  llvm::Expected<size_t> CursorPos = positionToOffset(Code, Pos);
284  if (!CursorPos)
285  return CursorPos.takeError();
286  size_t PreviousLBracePos =
287  llvm::StringRef(Code).find_last_of('{', *CursorPos);
288  if (PreviousLBracePos == llvm::StringRef::npos)
289  PreviousLBracePos = *CursorPos;
290  size_t Len = *CursorPos - PreviousLBracePos;
291 
292  return formatCode(Code, File, {tooling::Range(PreviousLBracePos, Len)});
293 }
294 
295 void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
296  Callback<std::vector<TextEdit>> CB) {
297  auto Action = [Pos](Path File, std::string NewName,
299  llvm::Expected<InputsAndAST> InpAST) {
300  if (!InpAST)
301  return CB(InpAST.takeError());
302  auto &AST = InpAST->AST;
303 
304  RefactoringResultCollector ResultCollector;
305  const SourceManager &SourceMgr = AST.getASTContext().getSourceManager();
306  SourceLocation SourceLocationBeg =
307  clangd::getBeginningOfIdentifier(AST, Pos, SourceMgr.getMainFileID());
308  tooling::RefactoringRuleContext Context(
309  AST.getASTContext().getSourceManager());
310  Context.setASTContext(AST.getASTContext());
311  auto Rename = clang::tooling::RenameOccurrences::initiate(
312  Context, SourceRange(SourceLocationBeg), NewName);
313  if (!Rename)
314  return CB(expandDiagnostics(Rename.takeError(),
315  AST.getASTContext().getDiagnostics()));
316 
317  Rename->invoke(ResultCollector, Context);
318 
319  assert(ResultCollector.Result.hasValue());
320  if (!ResultCollector.Result.getValue())
321  return CB(expandDiagnostics(ResultCollector.Result->takeError(),
322  AST.getASTContext().getDiagnostics()));
323 
324  std::vector<TextEdit> Replacements;
325  for (const tooling::AtomicChange &Change : ResultCollector.Result->get()) {
326  tooling::Replacements ChangeReps = Change.getReplacements();
327  for (const auto &Rep : ChangeReps) {
328  // FIXME: Right now we only support renaming the main file, so we
329  // drop replacements not for the main file. In the future, we might
330  // consider to support:
331  // * rename in any included header
332  // * rename only in the "main" header
333  // * provide an error if there are symbols we won't rename (e.g.
334  // std::vector)
335  // * rename globally in project
336  // * rename in open files
337  if (Rep.getFilePath() == File)
338  Replacements.push_back(
339  replacementToEdit(InpAST->Inputs.Contents, Rep));
340  }
341  }
342  return CB(std::move(Replacements));
343  };
344 
345  WorkScheduler.runWithAST(
346  "Rename", File, Bind(Action, File.str(), NewName.str(), std::move(CB)));
347 }
348 
349 static llvm::Expected<Tweak::Selection>
350 tweakSelection(const Range &Sel, const InputsAndAST &AST) {
351  auto Begin = positionToOffset(AST.Inputs.Contents, Sel.start);
352  if (!Begin)
353  return Begin.takeError();
354  auto End = positionToOffset(AST.Inputs.Contents, Sel.end);
355  if (!End)
356  return End.takeError();
357  return Tweak::Selection(AST.AST, *Begin, *End);
358 }
359 
361  Callback<std::vector<TweakRef>> CB) {
362  auto Action = [Sel](decltype(CB) CB, std::string File,
363  Expected<InputsAndAST> InpAST) {
364  if (!InpAST)
365  return CB(InpAST.takeError());
366  auto Selection = tweakSelection(Sel, *InpAST);
367  if (!Selection)
368  return CB(Selection.takeError());
369  std::vector<TweakRef> Res;
370  for (auto &T : prepareTweaks(*Selection))
371  Res.push_back({T->id(), T->title()});
372  CB(std::move(Res));
373  };
374 
375  WorkScheduler.runWithAST("EnumerateTweaks", File,
376  Bind(Action, std::move(CB), File.str()));
377 }
378 
379 void ClangdServer::applyTweak(PathRef File, Range Sel, StringRef TweakID,
381  auto Action = [Sel](decltype(CB) CB, std::string File, std::string TweakID,
382  Expected<InputsAndAST> InpAST) {
383  if (!InpAST)
384  return CB(InpAST.takeError());
385  auto Selection = tweakSelection(Sel, *InpAST);
386  if (!Selection)
387  return CB(Selection.takeError());
388  auto A = prepareTweak(TweakID, *Selection);
389  if (!A)
390  return CB(A.takeError());
391  auto RawReplacements = (*A)->apply(*Selection);
392  if (!RawReplacements)
393  return CB(RawReplacements.takeError());
394  // FIXME: this function has I/O operations (find .clang-format file), figure
395  // out a way to cache the format style.
396  auto Style = getFormatStyleForFile(File, InpAST->Inputs.Contents,
397  InpAST->Inputs.FS.get());
398  return CB(
399  cleanupAndFormat(InpAST->Inputs.Contents, *RawReplacements, Style));
400  };
401  WorkScheduler.runWithAST(
402  "ApplyTweak", File,
403  Bind(Action, std::move(CB), File.str(), TweakID.str()));
404 }
405 
407  llvm::unique_function<void(std::string)> Callback) {
408  auto Action = [](decltype(Callback) Callback,
409  llvm::Expected<InputsAndAST> InpAST) {
410  if (!InpAST) {
411  llvm::consumeError(InpAST.takeError());
412  return Callback("<no-ast>");
413  }
414  std::string Result;
415 
416  llvm::raw_string_ostream ResultOS(Result);
417  clangd::dumpAST(InpAST->AST, ResultOS);
418  ResultOS.flush();
419 
420  Callback(Result);
421  };
422 
423  WorkScheduler.runWithAST("DumpAST", File, Bind(Action, std::move(Callback)));
424 }
425 
427  Callback<std::vector<LocatedSymbol>> CB) {
428  auto Action = [Pos, this](decltype(CB) CB,
429  llvm::Expected<InputsAndAST> InpAST) {
430  if (!InpAST)
431  return CB(InpAST.takeError());
432  CB(clangd::locateSymbolAt(InpAST->AST, Pos, Index));
433  };
434 
435  WorkScheduler.runWithAST("Definitions", File, Bind(Action, std::move(CB)));
436 }
437 
439 
440  llvm::StringRef SourceExtensions[] = {".cpp", ".c", ".cc", ".cxx",
441  ".c++", ".m", ".mm"};
442  llvm::StringRef HeaderExtensions[] = {".h", ".hh", ".hpp", ".hxx", ".inc"};
443 
444  llvm::StringRef PathExt = llvm::sys::path::extension(Path);
445 
446  // Lookup in a list of known extensions.
447  auto SourceIter =
448  llvm::find_if(SourceExtensions, [&PathExt](PathRef SourceExt) {
449  return SourceExt.equals_lower(PathExt);
450  });
451  bool IsSource = SourceIter != std::end(SourceExtensions);
452 
453  auto HeaderIter =
454  llvm::find_if(HeaderExtensions, [&PathExt](PathRef HeaderExt) {
455  return HeaderExt.equals_lower(PathExt);
456  });
457 
458  bool IsHeader = HeaderIter != std::end(HeaderExtensions);
459 
460  // We can only switch between the known extensions.
461  if (!IsSource && !IsHeader)
462  return None;
463 
464  // Array to lookup extensions for the switch. An opposite of where original
465  // extension was found.
466  llvm::ArrayRef<llvm::StringRef> NewExts;
467  if (IsSource)
468  NewExts = HeaderExtensions;
469  else
470  NewExts = SourceExtensions;
471 
472  // Storage for the new path.
473  llvm::SmallString<128> NewPath = llvm::StringRef(Path);
474 
475  // Instance of vfs::FileSystem, used for file existence checks.
476  auto FS = FSProvider.getFileSystem();
477 
478  // Loop through switched extension candidates.
479  for (llvm::StringRef NewExt : NewExts) {
480  llvm::sys::path::replace_extension(NewPath, NewExt);
481  if (FS->exists(NewPath))
482  return NewPath.str().str(); // First str() to convert from SmallString to
483  // StringRef, second to convert from StringRef
484  // to std::string
485 
486  // Also check NewExt in upper-case, just in case.
487  llvm::sys::path::replace_extension(NewPath, NewExt.upper());
488  if (FS->exists(NewPath))
489  return NewPath.str().str();
490  }
491 
492  return None;
493 }
494 
495 llvm::Expected<tooling::Replacements>
496 ClangdServer::formatCode(llvm::StringRef Code, PathRef File,
497  llvm::ArrayRef<tooling::Range> Ranges) {
498  // Call clang-format.
499  auto FS = FSProvider.getFileSystem();
500  auto Style = format::getStyle(format::DefaultFormatStyle, File,
501  format::DefaultFallbackStyle, Code, FS.get());
502  if (!Style)
503  return Style.takeError();
504 
505  tooling::Replacements IncludeReplaces =
506  format::sortIncludes(*Style, Code, Ranges, File);
507  auto Changed = tooling::applyAllReplacements(Code, IncludeReplaces);
508  if (!Changed)
509  return Changed.takeError();
510 
511  return IncludeReplaces.merge(format::reformat(
512  Style.get(), *Changed,
513  tooling::calculateRangesAfterReplacements(IncludeReplaces, Ranges),
514  File));
515 }
516 
518  PathRef File, Position Pos, Callback<std::vector<DocumentHighlight>> CB) {
520  llvm::Expected<InputsAndAST> InpAST) {
521  if (!InpAST)
522  return CB(InpAST.takeError());
523  CB(clangd::findDocumentHighlights(InpAST->AST, Pos));
524  };
525 
526  WorkScheduler.runWithAST("Highlights", File, Bind(Action, std::move(CB)));
527 }
528 
530  Callback<llvm::Optional<Hover>> CB) {
531  auto Action = [Pos](Callback<llvm::Optional<Hover>> CB,
532  llvm::Expected<InputsAndAST> InpAST) {
533  if (!InpAST)
534  return CB(InpAST.takeError());
535  CB(clangd::getHover(InpAST->AST, Pos));
536  };
537 
538  WorkScheduler.runWithAST("Hover", File, Bind(Action, std::move(CB)));
539 }
540 
541 void ClangdServer::typeHierarchy(PathRef File, Position Pos, int Resolve,
542  TypeHierarchyDirection Direction,
543  Callback<Optional<TypeHierarchyItem>> CB) {
544  auto Action = [Pos, Resolve, Direction](decltype(CB) CB,
545  Expected<InputsAndAST> InpAST) {
546  if (!InpAST)
547  return CB(InpAST.takeError());
548  CB(clangd::getTypeHierarchy(InpAST->AST, Pos, Resolve, Direction));
549  };
550 
551  WorkScheduler.runWithAST("Type Hierarchy", File, Bind(Action, std::move(CB)));
552 }
553 
555  // FIXME: Do nothing for now. This will be used for indexing and potentially
556  // invalidating other caches.
557 }
558 
560  llvm::StringRef Query, int Limit,
561  Callback<std::vector<SymbolInformation>> CB) {
562  std::string QueryCopy = Query;
563  WorkScheduler.run(
564  "getWorkspaceSymbols",
565  Bind(
566  [QueryCopy, Limit, this](decltype(CB) CB) {
567  CB(clangd::getWorkspaceSymbols(QueryCopy, Limit, Index,
568  WorkspaceRoot.getValueOr("")));
569  },
570  std::move(CB)));
571 }
572 
573 void ClangdServer::documentSymbols(llvm::StringRef File,
574  Callback<std::vector<DocumentSymbol>> CB) {
576  llvm::Expected<InputsAndAST> InpAST) {
577  if (!InpAST)
578  return CB(InpAST.takeError());
579  CB(clangd::getDocumentSymbols(InpAST->AST));
580  };
581  WorkScheduler.runWithAST("documentSymbols", File,
582  Bind(Action, std::move(CB)));
583 }
584 
585 void ClangdServer::findReferences(PathRef File, Position Pos, uint32_t Limit,
586  Callback<std::vector<Location>> CB) {
587  auto Action = [Pos, Limit, this](Callback<std::vector<Location>> CB,
588  llvm::Expected<InputsAndAST> InpAST) {
589  if (!InpAST)
590  return CB(InpAST.takeError());
591  CB(clangd::findReferences(InpAST->AST, Pos, Limit, Index));
592  };
593 
594  WorkScheduler.runWithAST("References", File, Bind(Action, std::move(CB)));
595 }
596 
598  Callback<std::vector<SymbolDetails>> CB) {
600  llvm::Expected<InputsAndAST> InpAST) {
601  if (!InpAST)
602  return CB(InpAST.takeError());
603  CB(clangd::getSymbolInfo(InpAST->AST, Pos));
604  };
605 
606  WorkScheduler.runWithAST("SymbolInfo", File, Bind(Action, std::move(CB)));
607 }
608 
609 std::vector<std::pair<Path, std::size_t>>
611  return WorkScheduler.getUsedBytesPerFile();
612 }
613 
614 LLVM_NODISCARD bool
615 ClangdServer::blockUntilIdleForTest(llvm::Optional<double> TimeoutSeconds) {
616  return WorkScheduler.blockUntilIdle(timeoutSeconds(TimeoutSeconds)) &&
617  (!BackgroundIdx ||
618  BackgroundIdx->blockUntilIdleForTest(TimeoutSeconds));
619 }
620 
621 } // namespace clangd
622 } // namespace clang
llvm::Optional< Hover > getHover(ParsedAST &AST, Position Pos)
Get the hover information when hovering at Pos.
Definition: XRefs.cpp:708
WantDiagnostics
Determines whether diagnostics should be generated for a file snapshot.
Definition: TUScheduler.h:43
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...
llvm::Expected< tooling::Replacements > cleanupAndFormat(StringRef Code, const tooling::Replacements &Replaces, const format::FormatStyle &Style)
Definition: SourceCode.cpp:386
llvm::Expected< std::vector< SymbolInformation > > getWorkspaceSymbols(llvm::StringRef Query, int Limit, const SymbolIndex *const Index, llvm::StringRef HintPath)
Searches for the symbols matching Query.
Definition: FindSymbols.cpp:43
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:157
The preamble may be generated from an older version of the file.
Definition: TUScheduler.h:186
void typeHierarchy(PathRef File, Position Pos, int Resolve, TypeHierarchyDirection Direction, Callback< llvm::Optional< TypeHierarchyItem >> CB)
Get information about type hierarchy for a given position.
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:88
llvm::Expected< std::unique_ptr< Tweak > > prepareTweak(StringRef ID, const Tweak::Selection &S)
Definition: Tweak.cpp:66
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:242
void onFileEvent(const DidChangeWatchedFilesParams &Params)
Called when an event occurs for a watched file in the workspace.
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
Definition: Index.h:77
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:82
Besides accepting stale preamble, this also allow preamble to be absent (not ready or failed to build...
Definition: TUScheduler.h:189
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:23
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:28
LLVM_NODISCARD bool blockUntilIdleForTest(llvm::Optional< double > TimeoutSeconds=10)
std::vector< std::unique_ptr< Tweak > > prepareTweaks(const Tweak::Selection &S)
Calls prepare() on all tweaks, returning those that can run on the selection.
Definition: Tweak.cpp:49
static Options optsForTest()
Documents should not be synced at all.
tidy::ClangTidyOptions ClangTidyOpts
Definition: Compiler.h:39
void applyTweak(PathRef File, Range Sel, StringRef ID, Callback< tooling::Replacements > CB)
Apply the code tweak with a specified ID.
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:72
void vlog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:67
static llvm::Expected< Tweak::Selection > tweakSelection(const Range &Sel, const InputsAndAST &AST)
SignatureHelp signatureHelp(PathRef FileName, const tooling::CompileCommand &Command, const PreambleData *Preamble, llvm::StringRef Contents, Position Pos, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, const SymbolIndex *Index)
bool isCancelled(const Context &Ctx)
True if the current context is within a cancelable task which was cancelled.
static llvm::cl::opt< bool > SuggestMissingIncludes("suggest-missing-includes", llvm::cl::desc("Attempts to fix diagnostic errors caused by missing " "includes using index."), llvm::cl::init(true))
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:781
Context clone() const
Clone this context object.
Definition: Context.cpp:20
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:131
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:81
void rename(PathRef File, Position Pos, llvm::StringRef NewName, Callback< std::vector< TextEdit >> CB)
Rename all occurrences of the symbol at the Pos in File to NewName.
llvm::unique_function< void()> Action
std::string Path
A typedef to represent a file path.
Definition: Path.h:20
static const Context & current()
Returns the context for the current thread, creating it if needed.
Definition: Context.cpp:27
const ParseInputs & Inputs
Definition: TUScheduler.h:31
llvm::Optional< TypeHierarchyItem > getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels, TypeHierarchyDirection Direction)
Get type hierarchy information at Pos.
Definition: XRefs.cpp:975
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:116
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:443
A context is an immutable container for per-request data that must be propagated through layers that ...
Definition: Context.h:69
size_t BackgroundIndexRebuildPeriodMs
If set to non-zero, the background index rebuilds the symbol index periodically every BuildIndexPerio...
Definition: ClangdServer.h:92
Input to prepare and apply tweaks.
Definition: Tweak.h:42
std::vector< std::pair< Path, std::size_t > > getUsedBytesPerFile() const
Returns estimated memory usage for each of the currently open files.
format::FormatStyle getFormatStyleForFile(llvm::StringRef File, llvm::StringRef Content, llvm::vfs::FileSystem *FS)
Definition: SourceCode.cpp:372
void enumerateTweaks(PathRef File, Range Sel, Callback< std::vector< TweakRef >> CB)
Enumerate the code tweaks available to the user at a specified point.
CodeCompleteResult codeComplete(PathRef FileName, const tooling::CompileCommand &Command, const PreambleData *Preamble, llvm::StringRef Contents, Position Pos, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, CodeCompleteOptions Opts, SpeculativeFuzzyFind *SpecFuzzyFind)
const SymbolIndex * Index
Definition: Compiler.h:49
const SymbolIndex * Index
If Index is set, it is used to augment the code completion results.
Definition: CodeComplete.h:101
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:728
Information required to run clang, e.g. to parse AST or do code completion.
Definition: Compiler.h:44
bool StorePreamblesInMemory
Cached preambles are potentially large. If false, store them on disk.
Definition: ClangdServer.h:78
SourceLocation getBeginningOfIdentifier(ParsedAST &Unit, const Position &Pos, const FileID FID)
Get the beginning SourceLocation at a specified Pos.
Definition: ClangdUnit.cpp:575
===– 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:99
TextEdit replacementToEdit(llvm::StringRef Code, const tooling::Replacement &R)
Definition: SourceCode.cpp:291
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...
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.
void locateSymbolAt(PathRef File, Position Pos, Callback< std::vector< LocatedSymbol >> CB)
Find declaration/definition locations of symbol at a specified position.
std::vector< LocatedSymbol > locateSymbolAt(ParsedAST &AST, Position Pos, const SymbolIndex *Index)
Get definition of symbol at a specified Pos.
Definition: XRefs.cpp:271
IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS
Definition: Compiler.h:46
PrecompiledPreamble Preamble
Definition: ClangdUnit.h:55
static ClangTidyOptions getDefaults()
These options are used for all settings that haven&#39;t been overridden by the OptionsProvider.
ClangTidyOptions getOptions(llvm::StringRef FileName)
Returns options applying to a specific translation unit with the specified FileName.
Position end
The range&#39;s end position.
Definition: Protocol.h:160
bool AllowFallback
Whether to allow falling back to code completion without compiling files (using identifiers in the cu...
Definition: CodeComplete.h:122
Records an event whose duration is the lifetime of the Span object.
Definition: Trace.h:82
SymbolIndex * StaticIndex
If set, use this index to augment code completion results.
Definition: ClangdServer.h:95
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:178
llvm::Optional< Path > switchSourceHeader(PathRef Path)
Helper function that returns a path to the corresponding source file when given a header file and vic...
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.