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