clang-tools  10.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 "CodeComplete.h"
11 #include "FindSymbols.h"
12 #include "Format.h"
13 #include "FormattedString.h"
14 #include "HeaderSourceSwitch.h"
15 #include "Headers.h"
16 #include "Logger.h"
17 #include "ParsedAST.h"
18 #include "Preamble.h"
19 #include "Protocol.h"
20 #include "SemanticHighlighting.h"
21 #include "SemanticSelection.h"
22 #include "SourceCode.h"
23 #include "TUScheduler.h"
24 #include "Trace.h"
25 #include "XRefs.h"
27 #include "index/FileIndex.h"
28 #include "index/Merge.h"
29 #include "refactor/Rename.h"
30 #include "refactor/Tweak.h"
31 #include "clang/Format/Format.h"
32 #include "clang/Frontend/CompilerInstance.h"
33 #include "clang/Frontend/CompilerInvocation.h"
34 #include "clang/Lex/Preprocessor.h"
35 #include "clang/Tooling/CompilationDatabase.h"
36 #include "clang/Tooling/Core/Replacement.h"
37 #include "llvm/ADT/ArrayRef.h"
38 #include "llvm/ADT/Optional.h"
39 #include "llvm/ADT/STLExtras.h"
40 #include "llvm/ADT/ScopeExit.h"
41 #include "llvm/ADT/StringRef.h"
42 #include "llvm/Support/Errc.h"
43 #include "llvm/Support/Error.h"
44 #include "llvm/Support/FileSystem.h"
45 #include "llvm/Support/Path.h"
46 #include "llvm/Support/raw_ostream.h"
47 #include <algorithm>
48 #include <future>
49 #include <memory>
50 #include <mutex>
51 #include <type_traits>
52 
53 namespace clang {
54 namespace clangd {
55 namespace {
56 
57 // Update the FileIndex with new ASTs and plumb the diagnostics responses.
58 struct UpdateIndexCallbacks : public ParsingCallbacks {
59  UpdateIndexCallbacks(FileIndex *FIndex, DiagnosticsConsumer &DiagConsumer,
60  bool SemanticHighlighting)
61  : FIndex(FIndex), DiagConsumer(DiagConsumer),
62  SemanticHighlighting(SemanticHighlighting) {}
63 
64  void onPreambleAST(PathRef Path, ASTContext &Ctx,
65  std::shared_ptr<clang::Preprocessor> PP,
66  const CanonicalIncludes &CanonIncludes) override {
67  if (FIndex)
68  FIndex->updatePreamble(Path, Ctx, std::move(PP), CanonIncludes);
69  }
70 
71  void onMainAST(PathRef Path, ParsedAST &AST, PublishFn Publish) override {
72  if (FIndex)
73  FIndex->updateMain(Path, AST);
74 
75  std::vector<Diag> Diagnostics = AST.getDiagnostics();
76  std::vector<HighlightingToken> Highlightings;
77  if (SemanticHighlighting)
78  Highlightings = getSemanticHighlightings(AST);
79 
80  Publish([&]() {
81  DiagConsumer.onDiagnosticsReady(Path, std::move(Diagnostics));
82  if (SemanticHighlighting)
83  DiagConsumer.onHighlightingsReady(Path, std::move(Highlightings));
84  });
85  }
86 
87  void onFailedAST(PathRef Path, std::vector<Diag> Diags,
88  PublishFn Publish) override {
89  Publish([&]() { DiagConsumer.onDiagnosticsReady(Path, Diags); });
90  }
91 
92  void onFileUpdated(PathRef File, const TUStatus &Status) override {
93  DiagConsumer.onFileUpdated(File, Status);
94  }
95 
96 private:
97  FileIndex *FIndex;
98  DiagnosticsConsumer &DiagConsumer;
99  bool SemanticHighlighting;
100 };
101 } // namespace
102 
105  Opts.UpdateDebounce = std::chrono::steady_clock::duration::zero(); // Faster!
106  Opts.StorePreamblesInMemory = true;
107  Opts.AsyncThreadsCount = 4; // Consistent!
108  Opts.SemanticHighlighting = true;
109  return Opts;
110 }
111 
115  const Options &Opts)
116  : FSProvider(FSProvider),
117  DynamicIdx(Opts.BuildDynamicSymbolIndex
118  ? new FileIndex(Opts.HeavyweightDynamicSymbolIndex)
119  : nullptr),
120  GetClangTidyOptions(Opts.GetClangTidyOptions),
121  SuggestMissingIncludes(Opts.SuggestMissingIncludes),
122  TweakFilter(Opts.TweakFilter), WorkspaceRoot(Opts.WorkspaceRoot),
123  // Pass a callback into `WorkScheduler` to extract symbols from a newly
124  // parsed file and rebuild the file index synchronously each time an AST
125  // is parsed.
126  // FIXME(ioeric): this can be slow and we may be able to index on less
127  // critical paths.
128  WorkScheduler(
129  CDB, Opts.AsyncThreadsCount, Opts.StorePreamblesInMemory,
130  std::make_unique<UpdateIndexCallbacks>(DynamicIdx.get(), DiagConsumer,
131  Opts.SemanticHighlighting),
132  Opts.UpdateDebounce, Opts.RetentionPolicy) {
133  // Adds an index to the stack, at higher priority than existing indexes.
134  auto AddIndex = [&](SymbolIndex *Idx) {
135  if (this->Index != nullptr) {
136  MergedIdx.push_back(std::make_unique<MergedIndex>(Idx, this->Index));
137  this->Index = MergedIdx.back().get();
138  } else {
139  this->Index = Idx;
140  }
141  };
142  if (Opts.StaticIndex)
143  AddIndex(Opts.StaticIndex);
144  if (Opts.BackgroundIndex) {
145  BackgroundIdx = std::make_unique<BackgroundIndex>(
146  Context::current().clone(), FSProvider, CDB,
148  [&CDB](llvm::StringRef File) { return CDB.getProjectInfo(File); }),
149  std::max(Opts.AsyncThreadsCount, 1u));
150  AddIndex(BackgroundIdx.get());
151  }
152  if (DynamicIdx)
153  AddIndex(DynamicIdx.get());
154 }
155 
157  WantDiagnostics WantDiags) {
158  auto FS = FSProvider.getFileSystem();
159 
160  ParseOptions Opts;
162  // FIXME: call tidy options builder on the worker thread, it can do IO.
163  if (GetClangTidyOptions)
164  Opts.ClangTidyOpts = GetClangTidyOptions(*FS, File);
165  Opts.SuggestMissingIncludes = SuggestMissingIncludes;
166 
167  // Compile command is set asynchronously during update, as it can be slow.
168  ParseInputs Inputs;
169  Inputs.FS = FS;
170  Inputs.Contents = Contents;
171  Inputs.Opts = std::move(Opts);
172  Inputs.Index = Index;
173  bool NewFile = WorkScheduler.update(File, Inputs, WantDiags);
174  // If we loaded Foo.h, we want to make sure Foo.cpp is indexed.
175  if (NewFile && BackgroundIdx)
176  BackgroundIdx->boostRelated(File);
177 }
178 
179 void ClangdServer::removeDocument(PathRef File) { WorkScheduler.remove(File); }
180 
181 llvm::StringRef ClangdServer::getDocument(PathRef File) const {
182  return WorkScheduler.getContents(File);
183 }
184 
186  const clangd::CodeCompleteOptions &Opts,
188  // Copy completion options for passing them to async task handler.
189  auto CodeCompleteOpts = Opts;
190  if (!CodeCompleteOpts.Index) // Respect overridden index.
191  CodeCompleteOpts.Index = Index;
192 
193  auto Task = [Pos, FS = FSProvider.getFileSystem(), CodeCompleteOpts,
194  File = File.str(), CB = std::move(CB),
195  this](llvm::Expected<InputsAndPreamble> IP) mutable {
196  if (!IP)
197  return CB(IP.takeError());
198  if (isCancelled())
199  return CB(llvm::make_error<CancelledError>());
200 
201  llvm::Optional<SpeculativeFuzzyFind> SpecFuzzyFind;
202  if (!IP->Preamble) {
203  // No speculation in Fallback mode, as it's supposed to be much faster
204  // without compiling.
205  vlog("Build for file {0} is not ready. Enter fallback mode.", File);
206  } else {
207  if (CodeCompleteOpts.Index && CodeCompleteOpts.SpeculativeIndexRequest) {
208  SpecFuzzyFind.emplace();
209  {
210  std::lock_guard<std::mutex> Lock(
211  CachedCompletionFuzzyFindRequestMutex);
212  SpecFuzzyFind->CachedReq =
213  CachedCompletionFuzzyFindRequestByFile[File];
214  }
215  }
216  }
217  // FIXME(ibiryukov): even if Preamble is non-null, we may want to check
218  // both the old and the new version in case only one of them matches.
220  File, IP->Command, IP->Preamble, IP->Contents, Pos, FS,
221  CodeCompleteOpts, SpecFuzzyFind ? SpecFuzzyFind.getPointer() : nullptr);
222  {
223  clang::clangd::trace::Span Tracer("Completion results callback");
224  CB(std::move(Result));
225  }
226  if (SpecFuzzyFind && SpecFuzzyFind->NewReq.hasValue()) {
227  std::lock_guard<std::mutex> Lock(CachedCompletionFuzzyFindRequestMutex);
228  CachedCompletionFuzzyFindRequestByFile[File] =
229  SpecFuzzyFind->NewReq.getValue();
230  }
231  // SpecFuzzyFind is only destroyed after speculative fuzzy find finishes.
232  // We don't want `codeComplete` to wait for the async call if it doesn't use
233  // the result (e.g. non-index completion, speculation fails), so that `CB`
234  // is called as soon as results are available.
235  };
236 
237  // We use a potentially-stale preamble because latency is critical here.
238  WorkScheduler.runWithPreamble(
239  "CodeComplete", File,
243  std::move(Task));
244 }
245 
248 
249  auto Action = [Pos, FS = FSProvider.getFileSystem(), File = File.str(),
250  CB = std::move(CB),
251  this](llvm::Expected<InputsAndPreamble> IP) mutable {
252  if (!IP)
253  return CB(IP.takeError());
254 
255  auto PreambleData = IP->Preamble;
256  CB(clangd::signatureHelp(File, IP->Command, PreambleData, IP->Contents, Pos,
257  FS, Index));
258  };
259 
260  // Unlike code completion, we wait for an up-to-date preamble here.
261  // Signature help is often triggered after code completion. If the code
262  // completion inserted a header to make the symbol available, then using
263  // the old preamble would yield useless results.
264  WorkScheduler.runWithPreamble("SignatureHelp", File, TUScheduler::Consistent,
265  std::move(Action));
266 }
267 
268 llvm::Expected<tooling::Replacements>
270  llvm::Expected<size_t> Begin = positionToOffset(Code, Rng.start);
271  if (!Begin)
272  return Begin.takeError();
273  llvm::Expected<size_t> End = positionToOffset(Code, Rng.end);
274  if (!End)
275  return End.takeError();
276  return formatCode(Code, File, {tooling::Range(*Begin, *End - *Begin)});
277 }
278 
279 llvm::Expected<tooling::Replacements>
281  // Format everything.
282  return formatCode(Code, File, {tooling::Range(0, Code.size())});
283 }
284 
285 llvm::Expected<std::vector<TextEdit>>
287  StringRef TriggerText) {
288  llvm::Expected<size_t> CursorPos = positionToOffset(Code, Pos);
289  if (!CursorPos)
290  return CursorPos.takeError();
291  auto FS = FSProvider.getFileSystem();
292  auto Style = format::getStyle(format::DefaultFormatStyle, File,
293  format::DefaultFallbackStyle, Code, FS.get());
294  if (!Style)
295  return Style.takeError();
296 
297  std::vector<TextEdit> Result;
298  for (const tooling::Replacement &R :
299  formatIncremental(Code, *CursorPos, TriggerText, *Style))
300  Result.push_back(replacementToEdit(Code, R));
301  return Result;
302 }
303 
305  Callback<llvm::Optional<Range>> CB) {
306  auto Action = [Pos, File = File.str(), CB = std::move(CB),
307  this](llvm::Expected<InputsAndAST> InpAST) mutable {
308  if (!InpAST)
309  return CB(InpAST.takeError());
310  auto &AST = InpAST->AST;
311  // Performing the rename isn't substantially more expensive than doing an
312  // AST-based check, so we just rename and throw away the results. We may
313  // have to revisit this when we support cross-file rename.
314  auto Changes = renameWithinFile(AST, File, Pos, "dummy", Index);
315  if (!Changes) {
316  // LSP says to return null on failure, but that will result in a generic
317  // failure message. If we send an LSP error response, clients can surface
318  // the message to users (VSCode does).
319  return CB(Changes.takeError());
320  }
321  SourceLocation Loc = getBeginningOfIdentifier(
322  Pos, AST.getSourceManager(), AST.getASTContext().getLangOpts());
323  if (auto Range = getTokenRange(AST.getSourceManager(),
324  AST.getASTContext().getLangOpts(), Loc))
325  return CB(*Range);
326  // Return null if the "rename" is not valid at the position.
327  CB(llvm::None);
328  };
329  WorkScheduler.runWithAST("PrepareRename", File, std::move(Action));
330 }
331 
332 void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
333  bool WantFormat, Callback<std::vector<TextEdit>> CB) {
334  auto Action = [File = File.str(), NewName = NewName.str(), Pos, WantFormat,
335  CB = std::move(CB),
336  this](llvm::Expected<InputsAndAST> InpAST) mutable {
337  if (!InpAST)
338  return CB(InpAST.takeError());
339  auto Changes = renameWithinFile(InpAST->AST, File, Pos, NewName, Index);
340  if (!Changes)
341  return CB(Changes.takeError());
342 
343  if (WantFormat) {
344  auto Style = getFormatStyleForFile(File, InpAST->Inputs.Contents,
345  InpAST->Inputs.FS.get());
346  if (auto Formatted =
347  cleanupAndFormat(InpAST->Inputs.Contents, *Changes, Style))
348  *Changes = std::move(*Formatted);
349  else
350  elog("Failed to format replacements: {0}", Formatted.takeError());
351  }
352 
353  std::vector<TextEdit> Edits;
354  for (const auto &Rep : *Changes)
355  Edits.push_back(replacementToEdit(InpAST->Inputs.Contents, Rep));
356  return CB(std::move(Edits));
357  };
358 
359  WorkScheduler.runWithAST("Rename", File, std::move(Action));
360 }
361 
362 static llvm::Expected<Tweak::Selection>
363 tweakSelection(const Range &Sel, const InputsAndAST &AST) {
364  auto Begin = positionToOffset(AST.Inputs.Contents, Sel.start);
365  if (!Begin)
366  return Begin.takeError();
367  auto End = positionToOffset(AST.Inputs.Contents, Sel.end);
368  if (!End)
369  return End.takeError();
370  return Tweak::Selection(AST.AST, *Begin, *End);
371 }
372 
374  Callback<std::vector<TweakRef>> CB) {
375  auto Action = [File = File.str(), Sel, CB = std::move(CB),
376  this](Expected<InputsAndAST> InpAST) mutable {
377  if (!InpAST)
378  return CB(InpAST.takeError());
379  auto Selection = tweakSelection(Sel, *InpAST);
380  if (!Selection)
381  return CB(Selection.takeError());
382  std::vector<TweakRef> Res;
383  for (auto &T : prepareTweaks(*Selection, TweakFilter))
384  Res.push_back({T->id(), T->title(), T->intent()});
385 
386  CB(std::move(Res));
387  };
388 
389  WorkScheduler.runWithAST("EnumerateTweaks", File, std::move(Action));
390 }
391 
392 void ClangdServer::applyTweak(PathRef File, Range Sel, StringRef TweakID,
394  auto Action =
395  [File = File.str(), Sel, TweakID = TweakID.str(), CB = std::move(CB),
396  FS = FSProvider.getFileSystem()](Expected<InputsAndAST> InpAST) mutable {
397  if (!InpAST)
398  return CB(InpAST.takeError());
399  auto Selection = tweakSelection(Sel, *InpAST);
400  if (!Selection)
401  return CB(Selection.takeError());
402  auto A = prepareTweak(TweakID, *Selection);
403  if (!A)
404  return CB(A.takeError());
405  auto Effect = (*A)->apply(*Selection);
406  if (!Effect)
407  return CB(Effect.takeError());
408  for (auto &It : Effect->ApplyEdits) {
409  Edit &E = It.second;
410  format::FormatStyle Style =
411  getFormatStyleForFile(File, E.InitialCode, FS.get());
412  if (llvm::Error Err = reformatEdit(E, Style))
413  elog("Failed to format {0}: {1}", It.first(), std::move(Err));
414  }
415  return CB(std::move(*Effect));
416  };
417  WorkScheduler.runWithAST("ApplyTweak", File, std::move(Action));
418 }
419 
421  llvm::unique_function<void(std::string)> Callback) {
422  auto Action = [Callback = std::move(Callback)](
423  llvm::Expected<InputsAndAST> InpAST) mutable {
424  if (!InpAST) {
425  llvm::consumeError(InpAST.takeError());
426  return Callback("<no-ast>");
427  }
428  std::string Result;
429 
430  llvm::raw_string_ostream ResultOS(Result);
431  clangd::dumpAST(InpAST->AST, ResultOS);
432  ResultOS.flush();
433 
434  Callback(Result);
435  };
436 
437  WorkScheduler.runWithAST("DumpAST", File, std::move(Action));
438 }
439 
441  Callback<std::vector<LocatedSymbol>> CB) {
442  auto Action = [Pos, CB = std::move(CB),
443  this](llvm::Expected<InputsAndAST> InpAST) mutable {
444  if (!InpAST)
445  return CB(InpAST.takeError());
446  CB(clangd::locateSymbolAt(InpAST->AST, Pos, Index));
447  };
448 
449  WorkScheduler.runWithAST("Definitions", File, std::move(Action));
450 }
451 
453  PathRef Path, Callback<llvm::Optional<clangd::Path>> CB) {
454  // We want to return the result as fast as possible, stragety is:
455  // 1) use the file-only heuristic, it requires some IO but it is much
456  // faster than building AST, but it only works when .h/.cc files are in
457  // the same directory.
458  // 2) if 1) fails, we use the AST&Index approach, it is slower but supports
459  // different code layout.
460  if (auto CorrespondingFile =
461  getCorrespondingHeaderOrSource(Path, FSProvider.getFileSystem()))
462  return CB(std::move(CorrespondingFile));
463  auto Action = [Path = Path.str(), CB = std::move(CB),
464  this](llvm::Expected<InputsAndAST> InpAST) mutable {
465  if (!InpAST)
466  return CB(InpAST.takeError());
467  CB(getCorrespondingHeaderOrSource(Path, InpAST->AST, Index));
468  };
469  WorkScheduler.runWithAST("SwitchHeaderSource", Path, std::move(Action));
470 }
471 
472 llvm::Expected<tooling::Replacements>
473 ClangdServer::formatCode(llvm::StringRef Code, PathRef File,
474  llvm::ArrayRef<tooling::Range> Ranges) {
475  // Call clang-format.
476  format::FormatStyle Style =
477  getFormatStyleForFile(File, Code, FSProvider.getFileSystem().get());
478  tooling::Replacements IncludeReplaces =
479  format::sortIncludes(Style, Code, Ranges, File);
480  auto Changed = tooling::applyAllReplacements(Code, IncludeReplaces);
481  if (!Changed)
482  return Changed.takeError();
483 
484  return IncludeReplaces.merge(format::reformat(
485  Style, *Changed,
486  tooling::calculateRangesAfterReplacements(IncludeReplaces, Ranges),
487  File));
488 }
489 
491  PathRef File, Position Pos, Callback<std::vector<DocumentHighlight>> CB) {
492  auto Action =
493  [Pos, CB = std::move(CB)](llvm::Expected<InputsAndAST> InpAST) mutable {
494  if (!InpAST)
495  return CB(InpAST.takeError());
496  CB(clangd::findDocumentHighlights(InpAST->AST, Pos));
497  };
498 
499  WorkScheduler.runWithAST("Highlights", File, std::move(Action));
500 }
501 
503  Callback<llvm::Optional<HoverInfo>> CB) {
504  auto Action = [File = File.str(), Pos, CB = std::move(CB),
505  this](llvm::Expected<InputsAndAST> InpAST) mutable {
506  if (!InpAST)
507  return CB(InpAST.takeError());
509  File, InpAST->Inputs.Contents, InpAST->Inputs.FS.get());
510  CB(clangd::getHover(InpAST->AST, Pos, std::move(Style), Index));
511  };
512 
513  WorkScheduler.runWithAST("Hover", File, std::move(Action));
514 }
515 
516 void ClangdServer::typeHierarchy(PathRef File, Position Pos, int Resolve,
517  TypeHierarchyDirection Direction,
518  Callback<Optional<TypeHierarchyItem>> CB) {
519  auto Action = [File = File.str(), Pos, Resolve, Direction, CB = std::move(CB),
520  this](Expected<InputsAndAST> InpAST) mutable {
521  if (!InpAST)
522  return CB(InpAST.takeError());
523  CB(clangd::getTypeHierarchy(InpAST->AST, Pos, Resolve, Direction, Index,
524  File));
525  };
526 
527  WorkScheduler.runWithAST("Type Hierarchy", File, std::move(Action));
528 }
529 
531  TypeHierarchyItem Item, int Resolve, TypeHierarchyDirection Direction,
532  Callback<llvm::Optional<TypeHierarchyItem>> CB) {
533  clangd::resolveTypeHierarchy(Item, Resolve, Direction, Index);
534  CB(Item);
535 }
536 
538  // FIXME: Do nothing for now. This will be used for indexing and potentially
539  // invalidating other caches.
540 }
541 
543  llvm::StringRef Query, int Limit,
544  Callback<std::vector<SymbolInformation>> CB) {
545  WorkScheduler.run(
546  "getWorkspaceSymbols",
547  [Query = Query.str(), Limit, CB = std::move(CB), this]() mutable {
548  CB(clangd::getWorkspaceSymbols(Query, Limit, Index,
549  WorkspaceRoot.getValueOr("")));
550  });
551 }
552 
553 void ClangdServer::documentSymbols(llvm::StringRef File,
554  Callback<std::vector<DocumentSymbol>> CB) {
555  auto Action =
556  [CB = std::move(CB)](llvm::Expected<InputsAndAST> InpAST) mutable {
557  if (!InpAST)
558  return CB(InpAST.takeError());
559  CB(clangd::getDocumentSymbols(InpAST->AST));
560  };
561  WorkScheduler.runWithAST("documentSymbols", File, std::move(Action));
562 }
563 
565  Callback<std::vector<Location>> CB) {
566  auto Action = [Pos, Limit, CB = std::move(CB),
567  this](llvm::Expected<InputsAndAST> InpAST) mutable {
568  if (!InpAST)
569  return CB(InpAST.takeError());
570  CB(clangd::findReferences(InpAST->AST, Pos, Limit, Index));
571  };
572 
573  WorkScheduler.runWithAST("References", File, std::move(Action));
574 }
575 
577  Callback<std::vector<SymbolDetails>> CB) {
578  auto Action =
579  [Pos, CB = std::move(CB)](llvm::Expected<InputsAndAST> InpAST) mutable {
580  if (!InpAST)
581  return CB(InpAST.takeError());
582  CB(clangd::getSymbolInfo(InpAST->AST, Pos));
583  };
584 
585  WorkScheduler.runWithAST("SymbolInfo", File, std::move(Action));
586 }
587 
589  Callback<std::vector<Range>> CB) {
590  auto Action =
591  [Pos, CB = std::move(CB)](llvm::Expected<InputsAndAST> InpAST) mutable {
592  if (!InpAST)
593  return CB(InpAST.takeError());
594  CB(clangd::getSemanticRanges(InpAST->AST, Pos));
595  };
596  WorkScheduler.runWithAST("SemanticRanges", File, std::move(Action));
597 }
598 
599 std::vector<std::pair<Path, std::size_t>>
601  return WorkScheduler.getUsedBytesPerFile();
602 }
603 
604 LLVM_NODISCARD bool
605 ClangdServer::blockUntilIdleForTest(llvm::Optional<double> TimeoutSeconds) {
606  return WorkScheduler.blockUntilIdle(timeoutSeconds(TimeoutSeconds)) &&
607  (!BackgroundIdx ||
608  BackgroundIdx->blockUntilIdleForTest(TimeoutSeconds));
609 }
610 
611 } // namespace clangd
612 } // namespace clang
SourceLocation Loc
&#39;#&#39; location in the include directive
int Limit
std::string Code
WantDiagnostics
Determines whether diagnostics should be generated for a file snapshot.
Definition: TUScheduler.h:47
void rename(PathRef File, Position Pos, llvm::StringRef NewName, bool WantFormat, Callback< std::vector< TextEdit >> CB)
Rename all occurrences of the symbol at the Pos in File to NewName.
std::vector< tooling::Replacement > formatIncremental(llvm::StringRef OriginalCode, unsigned OriginalCursor, llvm::StringRef InsertedText, format::FormatStyle Style)
Applies limited formatting around new InsertedText.
Definition: Format.cpp:246
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)
Cleanup and format the given replacements.
Definition: SourceCode.cpp:710
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:67
llvm::StringRef Contents
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:158
The preamble may be generated from an older version of the file.
Definition: TUScheduler.h:211
void typeHierarchy(PathRef File, Position Pos, int Resolve, TypeHierarchyDirection Direction, Callback< llvm::Optional< TypeHierarchyItem >> CB)
Get information about type hierarchy for a given position.
bool BackgroundIndex
If true, ClangdServer automatically indexes files in the current project on background threads...
Definition: ClangdServer.h:99
tooling::Replacements Changes
Definition: Format.cpp:108
llvm::Expected< std::unique_ptr< Tweak > > prepareTweak(StringRef ID, const Tweak::Selection &S)
Definition: Tweak.cpp:75
bool blockUntilIdle(Deadline D) const
Wait until there are no scheduled or running tasks.
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: ParsedAST.cpp:213
void onFileEvent(const DidChangeWatchedFilesParams &Params)
Called when an event occurs for a watched file in the workspace.
void resolveTypeHierarchy(TypeHierarchyItem &Item, int ResolveLevels, TypeHierarchyDirection Direction, const SymbolIndex *Index)
Definition: XRefs.cpp:1247
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
Definition: Index.h:85
static Factory createDiskBackedStorageFactory(std::function< llvm::Optional< ProjectInfo >(PathRef)> GetProjectInfo)
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:94
Besides accepting stale preamble, this also allow preamble to be absent (not ready or failed to build...
Definition: TUScheduler.h:214
SourceLocation getBeginningOfIdentifier(const Position &Pos, const SourceManager &SM, const LangOptions &LangOpts)
Get the beginning SourceLocation at a specified Pos in the main file.
Definition: SourceCode.cpp:279
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:23
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)
MockFSProvider FS
static Options optsForTest()
Documents should not be synced at all.
tidy::ClangTidyOptions ClangTidyOpts
Definition: Compiler.h:39
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:84
void vlog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:67
bool update(PathRef File, ParseInputs Inputs, WantDiagnostics WD)
Schedule an update for File.
std::string InitialCode
Definition: SourceCode.h:212
void elog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:56
void applyTweak(PathRef File, Range Sel, StringRef ID, Callback< Tweak::Effect > CB)
Apply the code tweak with a specified ID.
MockFSProvider FSProvider
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.
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:983
llvm::Optional< HoverInfo > getHover(ParsedAST &AST, Position Pos, format::FormatStyle Style, const SymbolIndex *Index)
Get the hover information when hovering at Pos.
Definition: XRefs.cpp:880
llvm::Expected< tooling::Replacements > renameWithinFile(ParsedAST &AST, llvm::StringRef File, Position Pos, llvm::StringRef NewName, const SymbolIndex *Index)
Renames all occurrences of the symbol at Pos to NewName.
Definition: Rename.cpp:162
Context clone() const
Clone this context object.
Definition: Context.cpp:20
void resolveTypeHierarchy(TypeHierarchyItem Item, int Resolve, TypeHierarchyDirection Direction, Callback< llvm::Optional< TypeHierarchyItem >> CB)
Resolve type hierarchy item in the given direction.
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:149
llvm::Expected< std::vector< TextEdit > > formatOnType(StringRef Code, PathRef File, Position Pos, StringRef TriggerText)
Run formatting after TriggerText was typed at Pos in File with content Code.
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:35
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.
enum clang::clangd::CodeCompleteOptions::CodeCompletionParse RunParser
void switchSourceHeader(PathRef Path, Callback< llvm::Optional< clangd::Path >> CB)
Switch to a corresponding source file when given a header file, and vice versa.
std::chrono::steady_clock::duration UpdateDebounce
Time to wait after a new file version before computing diagnostics.
Definition: ClangdServer.h:123
llvm::Expected< std::vector< Range > > getSemanticRanges(ParsedAST &AST, Position Pos)
Returns the list of all interesting ranges around the Position Pos.
void dumpAST(PathRef File, llvm::unique_function< void(std::string)> Callback)
Only for testing purposes.
llvm::Optional< Range > getTokenRange(const SourceManager &SM, const LangOptions &LangOpts, SourceLocation TokLoc)
Returns the taken range at TokLoc.
Definition: SourceCode.cpp:229
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:412
Input to prepare and apply tweaks.
Definition: Tweak.h:48
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)
Choose the clang-format style we should apply to a certain file.
Definition: SourceCode.cpp:696
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)
void findHover(PathRef File, Position Pos, Callback< llvm::Optional< HoverInfo >> CB)
Get code hover for a given position.
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:103
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:916
Block until we can run the parser (e.g.
Definition: CodeComplete.h:125
Information required to run clang, e.g. to parse AST or do code completion.
Definition: Compiler.h:44
llvm::Optional< Path > getCorrespondingHeaderOrSource(const Path &OriginalFile, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS)
Given a header file, returns the best matching source file, and vice visa.
bool StorePreamblesInMemory
Cached preambles are potentially large. If false, store them on disk.
Definition: ClangdServer.h:90
===– 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:609
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.
llvm::Optional< TypeHierarchyItem > getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels, TypeHierarchyDirection Direction, const SymbolIndex *Index, PathRef TUPath)
Get type hierarchy information at Pos.
Definition: XRefs.cpp:1213
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 prepareRename(PathRef File, Position Pos, Callback< llvm::Optional< Range >> CB)
Test the validity of a rename operation.
std::vector< HighlightingToken > getSemanticHighlightings(ParsedAST &AST)
llvm::StringRef getDocument(PathRef File) const
Get the contents of File, which should have been added.
void symbolInfo(PathRef File, Position Pos, Callback< std::vector< SymbolDetails >> CB)
Get symbol info for given position.
IgnoreDiagnostics DiagConsumer
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:238
void semanticRanges(PathRef File, Position Pos, Callback< std::vector< Range >> CB)
Get semantic ranges around a specified position in a file.
IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS
Definition: Compiler.h:46
PrecompiledPreamble Preamble
Definition: Preamble.h:52
static ClangTidyOptions getDefaults()
These options are used for all settings that haven&#39;t been overridden by the OptionsProvider.
Position end
The range&#39;s end position.
Definition: Protocol.h:161
llvm::StringRef getContents(PathRef File) const
Returns the current contents of the buffer for File, per last update().
The parsed preamble and associated data.
Definition: Preamble.h:45
Records an event whose duration is the lifetime of the Span object.
Definition: Trace.h:81
SymbolIndex * StaticIndex
If set, use this index to augment code completion results.
Definition: ClangdServer.h:102
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.
A set of edits generated for a single file.
Definition: SourceCode.h:210
The preamble is generated from the current version of the file.
Definition: TUScheduler.h:203
llvm::Error reformatEdit(Edit &E, const format::FormatStyle &Style)
Formats the edits and code around it according to Style.
bool SemanticHighlighting
Enable semantic highlighting features.
Definition: ClangdServer.h:133
std::vector< std::unique_ptr< Tweak > > prepareTweaks(const Tweak::Selection &S, llvm::function_ref< bool(const Tweak &)> Filter)
Calls prepare() on all tweaks that satisfy the filter, returning those that can run on the selection...
Definition: Tweak.cpp:57
void run(llvm::StringRef Name, llvm::unique_function< void()> Action)
Schedule an async task with no dependencies.
static cl::opt< std::string > FormatStyle("format-style", cl::desc(R"( Style for formatting code around applied fixes: - 'none' (default) turns off formatting - 'file' (literally 'file', not a placeholder) uses .clang-format file in the closest parent directory - '{ <json> }' specifies options inline, e.g. -format-style='{BasedOnStyle: llvm, IndentWidth: 8}' - 'llvm', 'google', 'webkit', 'mozilla' See clang-format documentation for the up-to-date information about formatting styles and options. This option overrides the 'FormatStyle` option in .clang-tidy file, if any. )"), cl::init("none"), cl::cat(ClangTidyCategory))
virtual llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > getFileSystem() const =0
Called by ClangdServer to obtain a vfs::FileSystem to be used for parsing.