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