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 "ClangdUnit.h"
11 #include "CodeComplete.h"
12 #include "FindSymbols.h"
13 #include "Format.h"
14 #include "FormattedString.h"
15 #include "Headers.h"
16 #include "Protocol.h"
17 #include "SemanticHighlighting.h"
18 #include "SourceCode.h"
19 #include "TUScheduler.h"
20 #include "Trace.h"
21 #include "XRefs.h"
23 #include "index/FileIndex.h"
24 #include "index/Merge.h"
25 #include "refactor/Rename.h"
26 #include "refactor/Tweak.h"
27 #include "clang/Format/Format.h"
28 #include "clang/Frontend/CompilerInstance.h"
29 #include "clang/Frontend/CompilerInvocation.h"
30 #include "clang/Lex/Preprocessor.h"
31 #include "clang/Tooling/CompilationDatabase.h"
32 #include "clang/Tooling/Core/Replacement.h"
33 #include "llvm/ADT/ArrayRef.h"
34 #include "llvm/ADT/Optional.h"
35 #include "llvm/ADT/STLExtras.h"
36 #include "llvm/ADT/ScopeExit.h"
37 #include "llvm/ADT/StringRef.h"
38 #include "llvm/Support/Errc.h"
39 #include "llvm/Support/Error.h"
40 #include "llvm/Support/FileSystem.h"
41 #include "llvm/Support/Path.h"
42 #include "llvm/Support/raw_ostream.h"
43 #include <future>
44 #include <memory>
45 #include <mutex>
46 
47 namespace clang {
48 namespace clangd {
49 namespace {
50 
51 // Update the FileIndex with new ASTs and plumb the diagnostics responses.
52 struct UpdateIndexCallbacks : public ParsingCallbacks {
53  UpdateIndexCallbacks(FileIndex *FIndex, DiagnosticsConsumer &DiagConsumer,
54  bool SemanticHighlighting)
55  : FIndex(FIndex), DiagConsumer(DiagConsumer),
56  SemanticHighlighting(SemanticHighlighting) {}
57 
58  void onPreambleAST(PathRef Path, ASTContext &Ctx,
59  std::shared_ptr<clang::Preprocessor> PP,
60  const CanonicalIncludes &CanonIncludes) override {
61  if (FIndex)
62  FIndex->updatePreamble(Path, Ctx, std::move(PP), CanonIncludes);
63  }
64 
65  void onMainAST(PathRef Path, ParsedAST &AST, PublishFn Publish) override {
66  if (FIndex)
67  FIndex->updateMain(Path, AST);
68 
69  std::vector<Diag> Diagnostics = AST.getDiagnostics();
70  std::vector<HighlightingToken> Highlightings;
71  if (SemanticHighlighting)
72  Highlightings = getSemanticHighlightings(AST);
73 
74  Publish([&]() {
75  DiagConsumer.onDiagnosticsReady(Path, std::move(Diagnostics));
76  if (SemanticHighlighting)
77  DiagConsumer.onHighlightingsReady(Path, std::move(Highlightings));
78  });
79  }
80 
81  void onFileUpdated(PathRef File, const TUStatus &Status) override {
82  DiagConsumer.onFileUpdated(File, Status);
83  }
84 
85 private:
86  FileIndex *FIndex;
87  DiagnosticsConsumer &DiagConsumer;
88  bool SemanticHighlighting;
89 };
90 } // namespace
91 
94  Opts.UpdateDebounce = std::chrono::steady_clock::duration::zero(); // Faster!
95  Opts.StorePreamblesInMemory = true;
96  Opts.AsyncThreadsCount = 4; // Consistent!
97  Opts.SemanticHighlighting = true;
98  return Opts;
99 }
100 
104  const Options &Opts)
105  : FSProvider(FSProvider),
106  DynamicIdx(Opts.BuildDynamicSymbolIndex
107  ? new FileIndex(Opts.HeavyweightDynamicSymbolIndex)
108  : nullptr),
109  GetClangTidyOptions(Opts.GetClangTidyOptions),
111  TweakFilter(Opts.TweakFilter),
112  WorkspaceRoot(Opts.WorkspaceRoot),
113  // Pass a callback into `WorkScheduler` to extract symbols from a newly
114  // parsed file and rebuild the file index synchronously each time an AST
115  // is parsed.
116  // FIXME(ioeric): this can be slow and we may be able to index on less
117  // critical paths.
118  WorkScheduler(
119  CDB, Opts.AsyncThreadsCount, Opts.StorePreamblesInMemory,
120  llvm::make_unique<UpdateIndexCallbacks>(
121  DynamicIdx.get(), DiagConsumer, Opts.SemanticHighlighting),
122  Opts.UpdateDebounce, Opts.RetentionPolicy) {
123  // Adds an index to the stack, at higher priority than existing indexes.
124  auto AddIndex = [&](SymbolIndex *Idx) {
125  if (this->Index != nullptr) {
126  MergedIdx.push_back(llvm::make_unique<MergedIndex>(Idx, this->Index));
127  this->Index = MergedIdx.back().get();
128  } else {
129  this->Index = Idx;
130  }
131  };
132  if (Opts.StaticIndex)
133  AddIndex(Opts.StaticIndex);
134  if (Opts.BackgroundIndex) {
135  BackgroundIdx = llvm::make_unique<BackgroundIndex>(
136  Context::current().clone(), FSProvider, CDB,
138  [&CDB](llvm::StringRef File) { return CDB.getProjectInfo(File); }));
139  AddIndex(BackgroundIdx.get());
140  }
141  if (DynamicIdx)
142  AddIndex(DynamicIdx.get());
143 }
144 
146  WantDiagnostics WantDiags) {
147  auto FS = FSProvider.getFileSystem();
148 
149  ParseOptions Opts;
151  // FIXME: call tidy options builder on the worker thread, it can do IO.
152  if (GetClangTidyOptions)
153  Opts.ClangTidyOpts = GetClangTidyOptions(*FS, File);
154  Opts.SuggestMissingIncludes = SuggestMissingIncludes;
155 
156  // Compile command is set asynchronously during update, as it can be slow.
157  ParseInputs Inputs;
158  Inputs.FS = FS;
159  Inputs.Contents = Contents;
160  Inputs.Opts = std::move(Opts);
161  Inputs.Index = Index;
162  bool NewFile = WorkScheduler.update(File, Inputs, WantDiags);
163  // If we loaded Foo.h, we want to make sure Foo.cpp is indexed.
164  if (NewFile && BackgroundIdx)
165  BackgroundIdx->boostRelated(File);
166 }
167 
168 void ClangdServer::removeDocument(PathRef File) { WorkScheduler.remove(File); }
169 
170 llvm::StringRef ClangdServer::getDocument(PathRef File) const {
171  return WorkScheduler.getContents(File);
172 }
173 
175  const clangd::CodeCompleteOptions &Opts,
177  // Copy completion options for passing them to async task handler.
178  auto CodeCompleteOpts = Opts;
179  if (!CodeCompleteOpts.Index) // Respect overridden index.
180  CodeCompleteOpts.Index = Index;
181 
182  auto FS = FSProvider.getFileSystem();
183  auto Task = [Pos, FS, CodeCompleteOpts,
184  this](Path File, Callback<CodeCompleteResult> CB,
185  llvm::Expected<InputsAndPreamble> IP) {
186  if (!IP)
187  return CB(IP.takeError());
188  if (isCancelled())
189  return CB(llvm::make_error<CancelledError>());
190 
191  llvm::Optional<SpeculativeFuzzyFind> SpecFuzzyFind;
192  if (!IP->Preamble) {
193  // No speculation in Fallback mode, as it's supposed to be much faster
194  // without compiling.
195  vlog("Build for file {0} is not ready. Enter fallback mode.", File);
196  } else {
197  if (CodeCompleteOpts.Index && CodeCompleteOpts.SpeculativeIndexRequest) {
198  SpecFuzzyFind.emplace();
199  {
200  std::lock_guard<std::mutex> Lock(
201  CachedCompletionFuzzyFindRequestMutex);
202  SpecFuzzyFind->CachedReq =
203  CachedCompletionFuzzyFindRequestByFile[File];
204  }
205  }
206  }
207  // FIXME(ibiryukov): even if Preamble is non-null, we may want to check
208  // both the old and the new version in case only one of them matches.
210  File, IP->Command, IP->Preamble, IP->Contents, Pos, FS,
211  CodeCompleteOpts, SpecFuzzyFind ? SpecFuzzyFind.getPointer() : nullptr);
212  {
213  clang::clangd::trace::Span Tracer("Completion results callback");
214  CB(std::move(Result));
215  }
216  if (SpecFuzzyFind && SpecFuzzyFind->NewReq.hasValue()) {
217  std::lock_guard<std::mutex> Lock(CachedCompletionFuzzyFindRequestMutex);
218  CachedCompletionFuzzyFindRequestByFile[File] =
219  SpecFuzzyFind->NewReq.getValue();
220  }
221  // SpecFuzzyFind is only destroyed after speculative fuzzy find finishes.
222  // We don't want `codeComplete` to wait for the async call if it doesn't use
223  // the result (e.g. non-index completion, speculation fails), so that `CB`
224  // is called as soon as results are available.
225  };
226 
227  // We use a potentially-stale preamble because latency is critical here.
228  WorkScheduler.runWithPreamble(
229  "CodeComplete", File,
233  Bind(Task, File.str(), std::move(CB)));
234 }
235 
238 
239  auto FS = FSProvider.getFileSystem();
240  auto *Index = this->Index;
241  auto Action = [Pos, FS, Index](Path File, Callback<SignatureHelp> CB,
242  llvm::Expected<InputsAndPreamble> IP) {
243  if (!IP)
244  return CB(IP.takeError());
245 
246  auto PreambleData = IP->Preamble;
247  CB(clangd::signatureHelp(File, IP->Command, PreambleData, IP->Contents, Pos,
248  FS, Index));
249  };
250 
251  // Unlike code completion, we wait for an up-to-date preamble here.
252  // Signature help is often triggered after code completion. If the code
253  // completion inserted a header to make the symbol available, then using
254  // the old preamble would yield useless results.
255  WorkScheduler.runWithPreamble("SignatureHelp", File, TUScheduler::Consistent,
256  Bind(Action, File.str(), std::move(CB)));
257 }
258 
259 llvm::Expected<tooling::Replacements>
260 ClangdServer::formatRange(llvm::StringRef Code, PathRef File, Range Rng) {
261  llvm::Expected<size_t> Begin = positionToOffset(Code, Rng.start);
262  if (!Begin)
263  return Begin.takeError();
264  llvm::Expected<size_t> End = positionToOffset(Code, Rng.end);
265  if (!End)
266  return End.takeError();
267  return formatCode(Code, File, {tooling::Range(*Begin, *End - *Begin)});
268 }
269 
270 llvm::Expected<tooling::Replacements>
271 ClangdServer::formatFile(llvm::StringRef Code, PathRef File) {
272  // Format everything.
273  return formatCode(Code, File, {tooling::Range(0, Code.size())});
274 }
275 
276 llvm::Expected<std::vector<TextEdit>>
277 ClangdServer::formatOnType(llvm::StringRef Code, PathRef File, Position Pos,
278  StringRef TriggerText) {
279  llvm::Expected<size_t> CursorPos = positionToOffset(Code, Pos);
280  if (!CursorPos)
281  return CursorPos.takeError();
282  auto FS = FSProvider.getFileSystem();
283  auto Style = format::getStyle(format::DefaultFormatStyle, File,
284  format::DefaultFallbackStyle, Code, FS.get());
285  if (!Style)
286  return Style.takeError();
287 
288  std::vector<TextEdit> Result;
289  for (const tooling::Replacement &R :
290  formatIncremental(Code, *CursorPos, TriggerText, *Style))
291  Result.push_back(replacementToEdit(Code, R));
292  return Result;
293 }
294 
295 void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
296  bool WantFormat, Callback<std::vector<TextEdit>> CB) {
297  auto Action = [Pos, WantFormat, this](Path File, std::string NewName,
299  llvm::Expected<InputsAndAST> InpAST) {
300  if (!InpAST)
301  return CB(InpAST.takeError());
302  auto Changes = renameWithinFile(InpAST->AST, File, Pos, NewName, Index);
303  if (!Changes)
304  return CB(Changes.takeError());
305 
306  if (WantFormat) {
307  auto Style = getFormatStyleForFile(File, InpAST->Inputs.Contents,
308  InpAST->Inputs.FS.get());
309  if (auto Formatted =
310  cleanupAndFormat(InpAST->Inputs.Contents, *Changes, Style))
311  *Changes = std::move(*Formatted);
312  else
313  elog("Failed to format replacements: {0}", Formatted.takeError());
314  }
315 
316  std::vector<TextEdit> Edits;
317  for (const auto &Rep : *Changes)
318  Edits.push_back(replacementToEdit(InpAST->Inputs.Contents, Rep));
319  return CB(std::move(Edits));
320  };
321 
322  WorkScheduler.runWithAST(
323  "Rename", File, Bind(Action, File.str(), NewName.str(), std::move(CB)));
324 }
325 
326 static llvm::Expected<Tweak::Selection>
327 tweakSelection(const Range &Sel, const InputsAndAST &AST) {
328  auto Begin = positionToOffset(AST.Inputs.Contents, Sel.start);
329  if (!Begin)
330  return Begin.takeError();
331  auto End = positionToOffset(AST.Inputs.Contents, Sel.end);
332  if (!End)
333  return End.takeError();
334  return Tweak::Selection(AST.AST, *Begin, *End);
335 }
336 
338  Callback<std::vector<TweakRef>> CB) {
339  auto Action = [this, Sel](decltype(CB) CB, std::string File,
340  Expected<InputsAndAST> InpAST) {
341  if (!InpAST)
342  return CB(InpAST.takeError());
343  auto Selection = tweakSelection(Sel, *InpAST);
344  if (!Selection)
345  return CB(Selection.takeError());
346  std::vector<TweakRef> Res;
347  for (auto &T : prepareTweaks(*Selection, TweakFilter))
348  Res.push_back({T->id(), T->title(), T->intent()});
349 
350  CB(std::move(Res));
351  };
352 
353  WorkScheduler.runWithAST("EnumerateTweaks", File,
354  Bind(Action, std::move(CB), File.str()));
355 }
356 
357 void ClangdServer::applyTweak(PathRef File, Range Sel, StringRef TweakID,
359  auto Action = [Sel](decltype(CB) CB, std::string File, std::string TweakID,
360  Expected<InputsAndAST> InpAST) {
361  if (!InpAST)
362  return CB(InpAST.takeError());
363  auto Selection = tweakSelection(Sel, *InpAST);
364  if (!Selection)
365  return CB(Selection.takeError());
366  auto A = prepareTweak(TweakID, *Selection);
367  if (!A)
368  return CB(A.takeError());
369  auto Effect = (*A)->apply(*Selection);
370  if (!Effect)
371  return CB(Effect.takeError());
372  if (Effect->ApplyEdit) {
373  // FIXME: this function has I/O operations (find .clang-format file),
374  // figure out a way to cache the format style.
375  auto Style = getFormatStyleForFile(File, InpAST->Inputs.Contents,
376  InpAST->Inputs.FS.get());
377  if (auto Formatted = cleanupAndFormat(InpAST->Inputs.Contents,
378  *Effect->ApplyEdit, Style))
379  Effect->ApplyEdit = std::move(*Formatted);
380  else
381  elog("Failed to format replacements: {0}", Formatted.takeError());
382  }
383  return CB(std::move(*Effect));
384  };
385  WorkScheduler.runWithAST(
386  "ApplyTweak", File,
387  Bind(Action, std::move(CB), File.str(), TweakID.str()));
388 }
389 
391  llvm::unique_function<void(std::string)> Callback) {
392  auto Action = [](decltype(Callback) Callback,
393  llvm::Expected<InputsAndAST> InpAST) {
394  if (!InpAST) {
395  llvm::consumeError(InpAST.takeError());
396  return Callback("<no-ast>");
397  }
398  std::string Result;
399 
400  llvm::raw_string_ostream ResultOS(Result);
401  clangd::dumpAST(InpAST->AST, ResultOS);
402  ResultOS.flush();
403 
404  Callback(Result);
405  };
406 
407  WorkScheduler.runWithAST("DumpAST", File, Bind(Action, std::move(Callback)));
408 }
409 
411  Callback<std::vector<LocatedSymbol>> CB) {
412  auto Action = [Pos, this](decltype(CB) CB,
413  llvm::Expected<InputsAndAST> InpAST) {
414  if (!InpAST)
415  return CB(InpAST.takeError());
416  CB(clangd::locateSymbolAt(InpAST->AST, Pos, Index));
417  };
418 
419  WorkScheduler.runWithAST("Definitions", File, Bind(Action, std::move(CB)));
420 }
421 
422 llvm::Optional<Path> ClangdServer::switchSourceHeader(PathRef Path) {
423 
424  llvm::StringRef SourceExtensions[] = {".cpp", ".c", ".cc", ".cxx",
425  ".c++", ".m", ".mm"};
426  llvm::StringRef HeaderExtensions[] = {".h", ".hh", ".hpp", ".hxx", ".inc"};
427 
428  llvm::StringRef PathExt = llvm::sys::path::extension(Path);
429 
430  // Lookup in a list of known extensions.
431  auto SourceIter =
432  llvm::find_if(SourceExtensions, [&PathExt](PathRef SourceExt) {
433  return SourceExt.equals_lower(PathExt);
434  });
435  bool IsSource = SourceIter != std::end(SourceExtensions);
436 
437  auto HeaderIter =
438  llvm::find_if(HeaderExtensions, [&PathExt](PathRef HeaderExt) {
439  return HeaderExt.equals_lower(PathExt);
440  });
441 
442  bool IsHeader = HeaderIter != std::end(HeaderExtensions);
443 
444  // We can only switch between the known extensions.
445  if (!IsSource && !IsHeader)
446  return None;
447 
448  // Array to lookup extensions for the switch. An opposite of where original
449  // extension was found.
450  llvm::ArrayRef<llvm::StringRef> NewExts;
451  if (IsSource)
452  NewExts = HeaderExtensions;
453  else
454  NewExts = SourceExtensions;
455 
456  // Storage for the new path.
457  llvm::SmallString<128> NewPath = llvm::StringRef(Path);
458 
459  // Instance of vfs::FileSystem, used for file existence checks.
460  auto FS = FSProvider.getFileSystem();
461 
462  // Loop through switched extension candidates.
463  for (llvm::StringRef NewExt : NewExts) {
464  llvm::sys::path::replace_extension(NewPath, NewExt);
465  if (FS->exists(NewPath))
466  return NewPath.str().str(); // First str() to convert from SmallString to
467  // StringRef, second to convert from StringRef
468  // to std::string
469 
470  // Also check NewExt in upper-case, just in case.
471  llvm::sys::path::replace_extension(NewPath, NewExt.upper());
472  if (FS->exists(NewPath))
473  return NewPath.str().str();
474  }
475 
476  return None;
477 }
478 
479 llvm::Expected<tooling::Replacements>
480 ClangdServer::formatCode(llvm::StringRef Code, PathRef File,
481  llvm::ArrayRef<tooling::Range> Ranges) {
482  // Call clang-format.
483  format::FormatStyle Style =
484  getFormatStyleForFile(File, Code, FSProvider.getFileSystem().get());
485  tooling::Replacements IncludeReplaces =
486  format::sortIncludes(Style, Code, Ranges, File);
487  auto Changed = tooling::applyAllReplacements(Code, IncludeReplaces);
488  if (!Changed)
489  return Changed.takeError();
490 
491  return IncludeReplaces.merge(format::reformat(
492  Style, *Changed,
493  tooling::calculateRangesAfterReplacements(IncludeReplaces, Ranges),
494  File));
495 }
496 
498  PathRef File, Position Pos, Callback<std::vector<DocumentHighlight>> CB) {
500  llvm::Expected<InputsAndAST> InpAST) {
501  if (!InpAST)
502  return CB(InpAST.takeError());
503  CB(clangd::findDocumentHighlights(InpAST->AST, Pos));
504  };
505 
506  WorkScheduler.runWithAST("Highlights", File, Bind(Action, std::move(CB)));
507 }
508 
510  Callback<llvm::Optional<HoverInfo>> CB) {
511  auto Action = [Pos, this](decltype(CB) CB, Path File,
512  llvm::Expected<InputsAndAST> InpAST) {
513  if (!InpAST)
514  return CB(InpAST.takeError());
516  File, InpAST->Inputs.Contents, InpAST->Inputs.FS.get());
517  CB(clangd::getHover(InpAST->AST, Pos, std::move(Style), Index));
518  };
519 
520  WorkScheduler.runWithAST("Hover", File,
521  Bind(Action, std::move(CB), File.str()));
522 }
523 
524 void ClangdServer::typeHierarchy(PathRef File, Position Pos, int Resolve,
525  TypeHierarchyDirection Direction,
526  Callback<Optional<TypeHierarchyItem>> CB) {
527  std::string FileCopy = File; // copy will be captured by the lambda
528  auto Action = [FileCopy, Pos, Resolve, Direction,
529  this](decltype(CB) CB, Expected<InputsAndAST> InpAST) {
530  if (!InpAST)
531  return CB(InpAST.takeError());
532  CB(clangd::getTypeHierarchy(InpAST->AST, Pos, Resolve, Direction, Index,
533  FileCopy));
534  };
535 
536  WorkScheduler.runWithAST("Type Hierarchy", File, Bind(Action, std::move(CB)));
537 }
538 
540  TypeHierarchyItem Item, int Resolve, TypeHierarchyDirection Direction,
541  Callback<llvm::Optional<TypeHierarchyItem>> CB) {
542  clangd::resolveTypeHierarchy(Item, Resolve, Direction, Index);
543  CB(Item);
544 }
545 
547  // FIXME: Do nothing for now. This will be used for indexing and potentially
548  // invalidating other caches.
549 }
550 
552  llvm::StringRef Query, int Limit,
553  Callback<std::vector<SymbolInformation>> CB) {
554  std::string QueryCopy = Query;
555  WorkScheduler.run(
556  "getWorkspaceSymbols",
557  Bind(
558  [QueryCopy, Limit, this](decltype(CB) CB) {
559  CB(clangd::getWorkspaceSymbols(QueryCopy, Limit, Index,
560  WorkspaceRoot.getValueOr("")));
561  },
562  std::move(CB)));
563 }
564 
565 void ClangdServer::documentSymbols(llvm::StringRef File,
566  Callback<std::vector<DocumentSymbol>> CB) {
568  llvm::Expected<InputsAndAST> InpAST) {
569  if (!InpAST)
570  return CB(InpAST.takeError());
571  CB(clangd::getDocumentSymbols(InpAST->AST));
572  };
573  WorkScheduler.runWithAST("documentSymbols", File,
574  Bind(Action, std::move(CB)));
575 }
576 
578  Callback<std::vector<Location>> CB) {
579  auto Action = [Pos, Limit, this](Callback<std::vector<Location>> CB,
580  llvm::Expected<InputsAndAST> InpAST) {
581  if (!InpAST)
582  return CB(InpAST.takeError());
583  CB(clangd::findReferences(InpAST->AST, Pos, Limit, Index));
584  };
585 
586  WorkScheduler.runWithAST("References", File, Bind(Action, std::move(CB)));
587 }
588 
590  Callback<std::vector<SymbolDetails>> CB) {
592  llvm::Expected<InputsAndAST> InpAST) {
593  if (!InpAST)
594  return CB(InpAST.takeError());
595  CB(clangd::getSymbolInfo(InpAST->AST, Pos));
596  };
597 
598  WorkScheduler.runWithAST("SymbolInfo", File, Bind(Action, std::move(CB)));
599 }
600 
601 std::vector<std::pair<Path, std::size_t>>
603  return WorkScheduler.getUsedBytesPerFile();
604 }
605 
606 LLVM_NODISCARD bool
607 ClangdServer::blockUntilIdleForTest(llvm::Optional<double> TimeoutSeconds) {
608  return WorkScheduler.blockUntilIdle(timeoutSeconds(TimeoutSeconds)) &&
609  (!BackgroundIdx ||
610  BackgroundIdx->blockUntilIdleForTest(TimeoutSeconds));
611 }
612 
613 } // namespace clangd
614 } // namespace clang
int Limit
WantDiagnostics
Determines whether diagnostics should be generated for a file snapshot.
Definition: TUScheduler.h:44
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)
Definition: SourceCode.cpp:503
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:74
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:203
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:100
tooling::Replacements Changes
Definition: Format.cpp:108
llvm::Expected< std::unique_ptr< Tweak > > prepareTweak(StringRef ID, const Tweak::Selection &S)
Definition: Tweak.cpp:69
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: ClangdUnit.cpp:282
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:1255
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:93
Besides accepting stale preamble, this also allow preamble to be absent (not ready or failed to build...
Definition: TUScheduler.h:206
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:85
void vlog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:67
bool update(PathRef File, ParseInputs Inputs, WantDiagnostics WD)
Schedule an update for File.
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.
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))
Context Ctx
std::vector< SymbolDetails > getSymbolInfo(ParsedAST &AST, Position Pos)
Get info about symbols at Pos.
Definition: XRefs.cpp:992
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:899
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:160
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:141
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
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:32
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
std::chrono::steady_clock::duration UpdateDebounce
Time to wait after a new file version before computing diagnostics.
Definition: ClangdServer.h:124
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:436
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)
Choose the clang-format style we should apply to a certain file.
Definition: SourceCode.cpp:489
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:104
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:935
Block until we can run the parser (e.g.
Definition: CodeComplete.h:126
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:91
===– 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:402
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:1221
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.
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
Definition: Rename.cpp:36
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:261
IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS
Definition: Compiler.h:46
PrecompiledPreamble Preamble
Definition: ClangdUnit.h:57
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:160
llvm::StringRef getContents(PathRef File) const
Returns the current contents of the buffer for File, per last update().
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:103
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:195
llvm::Optional< Path > switchSourceHeader(PathRef Path)
Helper function that returns a path to the corresponding source file when given a header file and vic...
bool SemanticHighlighting
Enable semantic highlighting features.
Definition: ClangdServer.h:134
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:51
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.