clang-tools  16.0.0git
Hover.cpp
Go to the documentation of this file.
1 //===--- Hover.cpp - Information about code at the cursor location --------===//
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 "Hover.h"
10 
11 #include "AST.h"
12 #include "CodeCompletionStrings.h"
13 #include "Config.h"
14 #include "FindTarget.h"
15 #include "ParsedAST.h"
16 #include "Selection.h"
17 #include "SourceCode.h"
18 #include "index/SymbolCollector.h"
19 #include "support/Markup.h"
20 #include "clang/AST/ASTContext.h"
21 #include "clang/AST/ASTDiagnostic.h"
22 #include "clang/AST/ASTTypeTraits.h"
23 #include "clang/AST/Attr.h"
24 #include "clang/AST/Decl.h"
25 #include "clang/AST/DeclBase.h"
26 #include "clang/AST/DeclCXX.h"
27 #include "clang/AST/DeclObjC.h"
28 #include "clang/AST/DeclTemplate.h"
29 #include "clang/AST/Expr.h"
30 #include "clang/AST/ExprCXX.h"
31 #include "clang/AST/OperationKinds.h"
32 #include "clang/AST/PrettyPrinter.h"
33 #include "clang/AST/RecordLayout.h"
34 #include "clang/AST/Type.h"
35 #include "clang/Basic/CharInfo.h"
36 #include "clang/Basic/SourceLocation.h"
37 #include "clang/Basic/Specifiers.h"
38 #include "clang/Basic/TokenKinds.h"
39 #include "clang/Index/IndexSymbol.h"
40 #include "clang/Tooling/Syntax/Tokens.h"
41 #include "llvm/ADT/None.h"
42 #include "llvm/ADT/Optional.h"
43 #include "llvm/ADT/STLExtras.h"
44 #include "llvm/ADT/SmallVector.h"
45 #include "llvm/ADT/StringExtras.h"
46 #include "llvm/ADT/StringRef.h"
47 #include "llvm/Support/Casting.h"
48 #include "llvm/Support/Format.h"
49 #include "llvm/Support/ScopedPrinter.h"
50 #include "llvm/Support/raw_ostream.h"
51 #include <string>
52 
53 namespace clang {
54 namespace clangd {
55 namespace {
56 
57 PrintingPolicy getPrintingPolicy(PrintingPolicy Base) {
58  Base.AnonymousTagLocations = false;
59  Base.TerseOutput = true;
60  Base.PolishForDeclaration = true;
61  Base.ConstantsAsWritten = true;
62  Base.SuppressTemplateArgsInCXXConstructors = true;
63  return Base;
64 }
65 
66 /// Given a declaration \p D, return a human-readable string representing the
67 /// local scope in which it is declared, i.e. class(es) and method name. Returns
68 /// an empty string if it is not local.
69 std::string getLocalScope(const Decl *D) {
70  std::vector<std::string> Scopes;
71  const DeclContext *DC = D->getDeclContext();
72 
73  // ObjC scopes won't have multiple components for us to join, instead:
74  // - Methods: "-[Class methodParam1:methodParam2]"
75  // - Classes, categories, and protocols: "MyClass(Category)"
76  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC))
77  return printObjCMethod(*MD);
78  if (const ObjCContainerDecl *CD = dyn_cast<ObjCContainerDecl>(DC))
79  return printObjCContainer(*CD);
80 
81  auto GetName = [](const TypeDecl *D) {
82  if (!D->getDeclName().isEmpty()) {
83  PrintingPolicy Policy = D->getASTContext().getPrintingPolicy();
84  Policy.SuppressScope = true;
85  return declaredType(D).getAsString(Policy);
86  }
87  if (auto *RD = dyn_cast<RecordDecl>(D))
88  return ("(anonymous " + RD->getKindName() + ")").str();
89  return std::string("");
90  };
91  while (DC) {
92  if (const TypeDecl *TD = dyn_cast<TypeDecl>(DC))
93  Scopes.push_back(GetName(TD));
94  else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
95  Scopes.push_back(FD->getNameAsString());
96  DC = DC->getParent();
97  }
98 
99  return llvm::join(llvm::reverse(Scopes), "::");
100 }
101 
102 /// Returns the human-readable representation for namespace containing the
103 /// declaration \p D. Returns empty if it is contained global namespace.
104 std::string getNamespaceScope(const Decl *D) {
105  const DeclContext *DC = D->getDeclContext();
106 
107  // ObjC does not have the concept of namespaces, so instead we support
108  // local scopes.
109  if (isa<ObjCMethodDecl, ObjCContainerDecl>(DC))
110  return "";
111 
112  if (const TagDecl *TD = dyn_cast<TagDecl>(DC))
113  return getNamespaceScope(TD);
114  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
115  return getNamespaceScope(FD);
116  if (const NamespaceDecl *NSD = dyn_cast<NamespaceDecl>(DC)) {
117  // Skip inline/anon namespaces.
118  if (NSD->isInline() || NSD->isAnonymousNamespace())
119  return getNamespaceScope(NSD);
120  }
121  if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC))
122  return printQualifiedName(*ND);
123 
124  return "";
125 }
126 
127 std::string printDefinition(const Decl *D, PrintingPolicy PP,
128  const syntax::TokenBuffer &TB) {
129  if (auto *VD = llvm::dyn_cast<VarDecl>(D)) {
130  if (auto *IE = VD->getInit()) {
131  // Initializers might be huge and result in lots of memory allocations in
132  // some catostrophic cases. Such long lists are not useful in hover cards
133  // anyway.
134  if (200 < TB.expandedTokens(IE->getSourceRange()).size())
135  PP.SuppressInitializers = true;
136  }
137  }
138  std::string Definition;
139  llvm::raw_string_ostream OS(Definition);
140  D->print(OS, PP);
141  OS.flush();
142  return Definition;
143 }
144 
145 const char *getMarkdownLanguage(const ASTContext &Ctx) {
146  const auto &LangOpts = Ctx.getLangOpts();
147  if (LangOpts.ObjC && LangOpts.CPlusPlus)
148  return "objective-cpp";
149  return LangOpts.ObjC ? "objective-c" : "cpp";
150 }
151 
152 HoverInfo::PrintedType printType(QualType QT, ASTContext &ASTCtx,
153  const PrintingPolicy &PP) {
154  // TypePrinter doesn't resolve decltypes, so resolve them here.
155  // FIXME: This doesn't handle composite types that contain a decltype in them.
156  // We should rather have a printing policy for that.
157  while (!QT.isNull() && QT->isDecltypeType())
158  QT = QT->castAs<DecltypeType>()->getUnderlyingType();
159  HoverInfo::PrintedType Result;
160  llvm::raw_string_ostream OS(Result.Type);
161  // Special case: if the outer type is a tag type without qualifiers, then
162  // include the tag for extra clarity.
163  // This isn't very idiomatic, so don't attempt it for complex cases, including
164  // pointers/references, template specializations, etc.
165  if (!QT.isNull() && !QT.hasQualifiers() && PP.SuppressTagKeyword) {
166  if (auto *TT = llvm::dyn_cast<TagType>(QT.getTypePtr()))
167  OS << TT->getDecl()->getKindName() << " ";
168  }
169  QT.print(OS, PP);
170  OS.flush();
171 
172  const Config &Cfg = Config::current();
173  if (!QT.isNull() && Cfg.Hover.ShowAKA) {
174  bool ShouldAKA = false;
175  QualType DesugaredTy = clang::desugarForDiagnostic(ASTCtx, QT, ShouldAKA);
176  if (ShouldAKA)
177  Result.AKA = DesugaredTy.getAsString(PP);
178  }
179  return Result;
180 }
181 
182 HoverInfo::PrintedType printType(const TemplateTypeParmDecl *TTP) {
183  HoverInfo::PrintedType Result;
184  Result.Type = TTP->wasDeclaredWithTypename() ? "typename" : "class";
185  if (TTP->isParameterPack())
186  Result.Type += "...";
187  return Result;
188 }
189 
190 HoverInfo::PrintedType printType(const NonTypeTemplateParmDecl *NTTP,
191  const PrintingPolicy &PP) {
192  auto PrintedType = printType(NTTP->getType(), NTTP->getASTContext(), PP);
193  if (NTTP->isParameterPack()) {
194  PrintedType.Type += "...";
195  if (PrintedType.AKA)
196  *PrintedType.AKA += "...";
197  }
198  return PrintedType;
199 }
200 
201 HoverInfo::PrintedType printType(const TemplateTemplateParmDecl *TTP,
202  const PrintingPolicy &PP) {
203  HoverInfo::PrintedType Result;
204  llvm::raw_string_ostream OS(Result.Type);
205  OS << "template <";
206  llvm::StringRef Sep = "";
207  for (const Decl *Param : *TTP->getTemplateParameters()) {
208  OS << Sep;
209  Sep = ", ";
210  if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
211  OS << printType(TTP).Type;
212  else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param))
213  OS << printType(NTTP, PP).Type;
214  else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Param))
215  OS << printType(TTPD, PP).Type;
216  }
217  // FIXME: TemplateTemplateParameter doesn't store the info on whether this
218  // param was a "typename" or "class".
219  OS << "> class";
220  OS.flush();
221  return Result;
222 }
223 
224 std::vector<HoverInfo::Param>
225 fetchTemplateParameters(const TemplateParameterList *Params,
226  const PrintingPolicy &PP) {
227  assert(Params);
228  std::vector<HoverInfo::Param> TempParameters;
229 
230  for (const Decl *Param : *Params) {
231  HoverInfo::Param P;
232  if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
233  P.Type = printType(TTP);
234 
235  if (!TTP->getName().empty())
236  P.Name = TTP->getNameAsString();
237 
238  if (TTP->hasDefaultArgument())
239  P.Default = TTP->getDefaultArgument().getAsString(PP);
240  } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
241  P.Type = printType(NTTP, PP);
242 
243  if (IdentifierInfo *II = NTTP->getIdentifier())
244  P.Name = II->getName().str();
245 
246  if (NTTP->hasDefaultArgument()) {
247  P.Default.emplace();
248  llvm::raw_string_ostream Out(*P.Default);
249  NTTP->getDefaultArgument()->printPretty(Out, nullptr, PP);
250  }
251  } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) {
252  P.Type = printType(TTPD, PP);
253 
254  if (!TTPD->getName().empty())
255  P.Name = TTPD->getNameAsString();
256 
257  if (TTPD->hasDefaultArgument()) {
258  P.Default.emplace();
259  llvm::raw_string_ostream Out(*P.Default);
260  TTPD->getDefaultArgument().getArgument().print(PP, Out,
261  /*IncludeType*/ false);
262  }
263  }
264  TempParameters.push_back(std::move(P));
265  }
266 
267  return TempParameters;
268 }
269 
270 const FunctionDecl *getUnderlyingFunction(const Decl *D) {
271  // Extract lambda from variables.
272  if (const VarDecl *VD = llvm::dyn_cast<VarDecl>(D)) {
273  auto QT = VD->getType();
274  if (!QT.isNull()) {
275  while (!QT->getPointeeType().isNull())
276  QT = QT->getPointeeType();
277 
278  if (const auto *CD = QT->getAsCXXRecordDecl())
279  return CD->getLambdaCallOperator();
280  }
281  }
282 
283  // Non-lambda functions.
284  return D->getAsFunction();
285 }
286 
287 // Returns the decl that should be used for querying comments, either from index
288 // or AST.
289 const NamedDecl *getDeclForComment(const NamedDecl *D) {
290  const NamedDecl *DeclForComment = D;
291  if (const auto *TSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D)) {
292  // Template may not be instantiated e.g. if the type didn't need to be
293  // complete; fallback to primary template.
294  if (TSD->getTemplateSpecializationKind() == TSK_Undeclared)
295  DeclForComment = TSD->getSpecializedTemplate();
296  else if (const auto *TIP = TSD->getTemplateInstantiationPattern())
297  DeclForComment = TIP;
298  } else if (const auto *TSD =
299  llvm::dyn_cast<VarTemplateSpecializationDecl>(D)) {
300  if (TSD->getTemplateSpecializationKind() == TSK_Undeclared)
301  DeclForComment = TSD->getSpecializedTemplate();
302  else if (const auto *TIP = TSD->getTemplateInstantiationPattern())
303  DeclForComment = TIP;
304  } else if (const auto *FD = D->getAsFunction())
305  if (const auto *TIP = FD->getTemplateInstantiationPattern())
306  DeclForComment = TIP;
307  // Ensure that getDeclForComment(getDeclForComment(X)) = getDeclForComment(X).
308  // This is usually not needed, but in strange cases of comparision operators
309  // being instantiated from spasceship operater, which itself is a template
310  // instantiation the recursrive call is necessary.
311  if (D != DeclForComment)
312  DeclForComment = getDeclForComment(DeclForComment);
313  return DeclForComment;
314 }
315 
316 // Look up information about D from the index, and add it to Hover.
317 void enhanceFromIndex(HoverInfo &Hover, const NamedDecl &ND,
318  const SymbolIndex *Index) {
319  assert(&ND == getDeclForComment(&ND));
320  // We only add documentation, so don't bother if we already have some.
321  if (!Hover.Documentation.empty() || !Index)
322  return;
323 
324  // Skip querying for non-indexable symbols, there's no point.
325  // We're searching for symbols that might be indexed outside this main file.
326  if (!SymbolCollector::shouldCollectSymbol(ND, ND.getASTContext(),
327  SymbolCollector::Options(),
328  /*IsMainFileOnly=*/false))
329  return;
330  auto ID = getSymbolID(&ND);
331  if (!ID)
332  return;
333  LookupRequest Req;
334  Req.IDs.insert(ID);
335  Index->lookup(Req, [&](const Symbol &S) {
336  Hover.Documentation = std::string(S.Documentation);
337  });
338 }
339 
340 // Default argument might exist but be unavailable, in the case of unparsed
341 // arguments for example. This function returns the default argument if it is
342 // available.
343 const Expr *getDefaultArg(const ParmVarDecl *PVD) {
344  // Default argument can be unparsed or uninstantiated. For the former we
345  // can't do much, as token information is only stored in Sema and not
346  // attached to the AST node. For the latter though, it is safe to proceed as
347  // the expression is still valid.
348  if (!PVD->hasDefaultArg() || PVD->hasUnparsedDefaultArg())
349  return nullptr;
350  return PVD->hasUninstantiatedDefaultArg() ? PVD->getUninstantiatedDefaultArg()
351  : PVD->getDefaultArg();
352 }
353 
354 HoverInfo::Param toHoverInfoParam(const ParmVarDecl *PVD,
355  const PrintingPolicy &PP) {
356  HoverInfo::Param Out;
357  Out.Type = printType(PVD->getType(), PVD->getASTContext(), PP);
358  if (!PVD->getName().empty())
359  Out.Name = PVD->getNameAsString();
360  if (const Expr *DefArg = getDefaultArg(PVD)) {
361  Out.Default.emplace();
362  llvm::raw_string_ostream OS(*Out.Default);
363  DefArg->printPretty(OS, nullptr, PP);
364  }
365  return Out;
366 }
367 
368 // Populates Type, ReturnType, and Parameters for function-like decls.
369 void fillFunctionTypeAndParams(HoverInfo &HI, const Decl *D,
370  const FunctionDecl *FD,
371  const PrintingPolicy &PP) {
372  HI.Parameters.emplace();
373  for (const ParmVarDecl *PVD : FD->parameters())
374  HI.Parameters->emplace_back(toHoverInfoParam(PVD, PP));
375 
376  // We don't want any type info, if name already contains it. This is true for
377  // constructors/destructors and conversion operators.
378  const auto NK = FD->getDeclName().getNameKind();
379  if (NK == DeclarationName::CXXConstructorName ||
380  NK == DeclarationName::CXXDestructorName ||
381  NK == DeclarationName::CXXConversionFunctionName)
382  return;
383 
384  HI.ReturnType = printType(FD->getReturnType(), FD->getASTContext(), PP);
385  QualType QT = FD->getType();
386  if (const VarDecl *VD = llvm::dyn_cast<VarDecl>(D)) // Lambdas
387  QT = VD->getType().getDesugaredType(D->getASTContext());
388  HI.Type = printType(QT, D->getASTContext(), PP);
389  // FIXME: handle variadics.
390 }
391 
392 // Non-negative numbers are printed using min digits
393 // 0 => 0x0
394 // 100 => 0x64
395 // Negative numbers are sign-extended to 32/64 bits
396 // -2 => 0xfffffffe
397 // -2^32 => 0xfffffffeffffffff
398 static llvm::FormattedNumber printHex(const llvm::APSInt &V) {
399  uint64_t Bits = V.getExtValue();
400  if (V.isNegative() && V.getMinSignedBits() <= 32)
401  return llvm::format_hex(uint32_t(Bits), 0);
402  return llvm::format_hex(Bits, 0);
403 }
404 
405 llvm::Optional<std::string> printExprValue(const Expr *E,
406  const ASTContext &Ctx) {
407  // InitListExpr has two forms, syntactic and semantic. They are the same thing
408  // (refer to a same AST node) in most cases.
409  // When they are different, RAV returns the syntactic form, and we should feed
410  // the semantic form to EvaluateAsRValue.
411  if (const auto *ILE = llvm::dyn_cast<InitListExpr>(E)) {
412  if (!ILE->isSemanticForm())
413  E = ILE->getSemanticForm();
414  }
415 
416  // Evaluating [[foo]]() as "&foo" isn't useful, and prevents us walking up
417  // to the enclosing call. Evaluating an expression of void type doesn't
418  // produce a meaningful result.
419  QualType T = E->getType();
420  if (T.isNull() || T->isFunctionType() || T->isFunctionPointerType() ||
421  T->isFunctionReferenceType() || T->isVoidType())
422  return std::nullopt;
423 
424  Expr::EvalResult Constant;
425  // Attempt to evaluate. If expr is dependent, evaluation crashes!
426  if (E->isValueDependent() || !E->EvaluateAsRValue(Constant, Ctx) ||
427  // Disable printing for record-types, as they are usually confusing and
428  // might make clang crash while printing the expressions.
429  Constant.Val.isStruct() || Constant.Val.isUnion())
430  return std::nullopt;
431 
432  // Show enums symbolically, not numerically like APValue::printPretty().
433  if (T->isEnumeralType() && Constant.Val.isInt() &&
434  Constant.Val.getInt().getMinSignedBits() <= 64) {
435  // Compare to int64_t to avoid bit-width match requirements.
436  int64_t Val = Constant.Val.getInt().getExtValue();
437  for (const EnumConstantDecl *ECD :
438  T->castAs<EnumType>()->getDecl()->enumerators())
439  if (ECD->getInitVal() == Val)
440  return llvm::formatv("{0} ({1})", ECD->getNameAsString(),
441  printHex(Constant.Val.getInt()))
442  .str();
443  }
444  // Show hex value of integers if they're at least 10 (or negative!)
445  if (T->isIntegralOrEnumerationType() && Constant.Val.isInt() &&
446  Constant.Val.getInt().getMinSignedBits() <= 64 &&
447  Constant.Val.getInt().uge(10))
448  return llvm::formatv("{0} ({1})", Constant.Val.getAsString(Ctx, T),
449  printHex(Constant.Val.getInt()))
450  .str();
451  return Constant.Val.getAsString(Ctx, T);
452 }
453 
454 llvm::Optional<std::string> printExprValue(const SelectionTree::Node *N,
455  const ASTContext &Ctx) {
456  for (; N; N = N->Parent) {
457  // Try to evaluate the first evaluatable enclosing expression.
458  if (const Expr *E = N->ASTNode.get<Expr>()) {
459  // Once we cross an expression of type 'cv void', the evaluated result
460  // has nothing to do with our original cursor position.
461  if (!E->getType().isNull() && E->getType()->isVoidType())
462  break;
463  if (auto Val = printExprValue(E, Ctx))
464  return Val;
465  } else if (N->ASTNode.get<Decl>() || N->ASTNode.get<Stmt>()) {
466  // Refuse to cross certain non-exprs. (TypeLoc are OK as part of Exprs).
467  // This tries to ensure we're showing a value related to the cursor.
468  break;
469  }
470  }
471  return std::nullopt;
472 }
473 
474 llvm::Optional<StringRef> fieldName(const Expr *E) {
475  const auto *ME = llvm::dyn_cast<MemberExpr>(E->IgnoreCasts());
476  if (!ME || !llvm::isa<CXXThisExpr>(ME->getBase()->IgnoreCasts()))
477  return std::nullopt;
478  const auto *Field = llvm::dyn_cast<FieldDecl>(ME->getMemberDecl());
479  if (!Field || !Field->getDeclName().isIdentifier())
480  return std::nullopt;
481  return Field->getDeclName().getAsIdentifierInfo()->getName();
482 }
483 
484 // If CMD is of the form T foo() { return FieldName; } then returns "FieldName".
485 llvm::Optional<StringRef> getterVariableName(const CXXMethodDecl *CMD) {
486  assert(CMD->hasBody());
487  if (CMD->getNumParams() != 0 || CMD->isVariadic())
488  return std::nullopt;
489  const auto *Body = llvm::dyn_cast<CompoundStmt>(CMD->getBody());
490  const auto *OnlyReturn = (Body && Body->size() == 1)
491  ? llvm::dyn_cast<ReturnStmt>(Body->body_front())
492  : nullptr;
493  if (!OnlyReturn || !OnlyReturn->getRetValue())
494  return std::nullopt;
495  return fieldName(OnlyReturn->getRetValue());
496 }
497 
498 // If CMD is one of the forms:
499 // void foo(T arg) { FieldName = arg; }
500 // R foo(T arg) { FieldName = arg; return *this; }
501 // void foo(T arg) { FieldName = std::move(arg); }
502 // R foo(T arg) { FieldName = std::move(arg); return *this; }
503 // then returns "FieldName"
504 llvm::Optional<StringRef> setterVariableName(const CXXMethodDecl *CMD) {
505  assert(CMD->hasBody());
506  if (CMD->isConst() || CMD->getNumParams() != 1 || CMD->isVariadic())
507  return std::nullopt;
508  const ParmVarDecl *Arg = CMD->getParamDecl(0);
509  if (Arg->isParameterPack())
510  return std::nullopt;
511 
512  const auto *Body = llvm::dyn_cast<CompoundStmt>(CMD->getBody());
513  if (!Body || Body->size() == 0 || Body->size() > 2)
514  return std::nullopt;
515  // If the second statement exists, it must be `return this` or `return *this`.
516  if (Body->size() == 2) {
517  auto *Ret = llvm::dyn_cast<ReturnStmt>(Body->body_back());
518  if (!Ret || !Ret->getRetValue())
519  return std::nullopt;
520  const Expr *RetVal = Ret->getRetValue()->IgnoreCasts();
521  if (const auto *UO = llvm::dyn_cast<UnaryOperator>(RetVal)) {
522  if (UO->getOpcode() != UO_Deref)
523  return std::nullopt;
524  RetVal = UO->getSubExpr()->IgnoreCasts();
525  }
526  if (!llvm::isa<CXXThisExpr>(RetVal))
527  return std::nullopt;
528  }
529  // The first statement must be an assignment of the arg to a field.
530  const Expr *LHS, *RHS;
531  if (const auto *BO = llvm::dyn_cast<BinaryOperator>(Body->body_front())) {
532  if (BO->getOpcode() != BO_Assign)
533  return std::nullopt;
534  LHS = BO->getLHS();
535  RHS = BO->getRHS();
536  } else if (const auto *COCE =
537  llvm::dyn_cast<CXXOperatorCallExpr>(Body->body_front())) {
538  if (COCE->getOperator() != OO_Equal || COCE->getNumArgs() != 2)
539  return std::nullopt;
540  LHS = COCE->getArg(0);
541  RHS = COCE->getArg(1);
542  } else {
543  return std::nullopt;
544  }
545 
546  // Detect the case when the item is moved into the field.
547  if (auto *CE = llvm::dyn_cast<CallExpr>(RHS->IgnoreCasts())) {
548  if (CE->getNumArgs() != 1)
549  return std::nullopt;
550  auto *ND = llvm::dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl());
551  if (!ND || !ND->getIdentifier() || ND->getName() != "move" ||
552  !ND->isInStdNamespace())
553  return std::nullopt;
554  RHS = CE->getArg(0);
555  }
556 
557  auto *DRE = llvm::dyn_cast<DeclRefExpr>(RHS->IgnoreCasts());
558  if (!DRE || DRE->getDecl() != Arg)
559  return std::nullopt;
560  return fieldName(LHS);
561 }
562 
563 std::string synthesizeDocumentation(const NamedDecl *ND) {
564  if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(ND)) {
565  // Is this an ordinary, non-static method whose definition is visible?
566  if (CMD->getDeclName().isIdentifier() && !CMD->isStatic() &&
567  (CMD = llvm::dyn_cast_or_null<CXXMethodDecl>(CMD->getDefinition())) &&
568  CMD->hasBody()) {
569  if (const auto GetterField = getterVariableName(CMD))
570  return llvm::formatv("Trivial accessor for `{0}`.", *GetterField);
571  if (const auto SetterField = setterVariableName(CMD))
572  return llvm::formatv("Trivial setter for `{0}`.", *SetterField);
573  }
574  }
575  return "";
576 }
577 
578 /// Generate a \p Hover object given the declaration \p D.
579 HoverInfo getHoverContents(const NamedDecl *D, const PrintingPolicy &PP,
580  const SymbolIndex *Index,
581  const syntax::TokenBuffer &TB) {
582  HoverInfo HI;
583  auto &Ctx = D->getASTContext();
584 
585  HI.AccessSpecifier = getAccessSpelling(D->getAccess()).str();
586  HI.NamespaceScope = getNamespaceScope(D);
587  if (!HI.NamespaceScope->empty())
588  HI.NamespaceScope->append("::");
589  HI.LocalScope = getLocalScope(D);
590  if (!HI.LocalScope.empty())
591  HI.LocalScope.append("::");
592 
593  HI.Name = printName(Ctx, *D);
594  const auto *CommentD = getDeclForComment(D);
595  HI.Documentation = getDeclComment(Ctx, *CommentD);
596  enhanceFromIndex(HI, *CommentD, Index);
597  if (HI.Documentation.empty())
598  HI.Documentation = synthesizeDocumentation(D);
599 
600  HI.Kind = index::getSymbolInfo(D).Kind;
601 
602  // Fill in template params.
603  if (const TemplateDecl *TD = D->getDescribedTemplate()) {
604  HI.TemplateParameters =
605  fetchTemplateParameters(TD->getTemplateParameters(), PP);
606  D = TD;
607  } else if (const FunctionDecl *FD = D->getAsFunction()) {
608  if (const auto *FTD = FD->getDescribedTemplate()) {
609  HI.TemplateParameters =
610  fetchTemplateParameters(FTD->getTemplateParameters(), PP);
611  D = FTD;
612  }
613  }
614 
615  // Fill in types and params.
616  if (const FunctionDecl *FD = getUnderlyingFunction(D))
617  fillFunctionTypeAndParams(HI, D, FD, PP);
618  else if (const auto *VD = dyn_cast<ValueDecl>(D))
619  HI.Type = printType(VD->getType(), Ctx, PP);
620  else if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(D))
621  HI.Type = TTP->wasDeclaredWithTypename() ? "typename" : "class";
622  else if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(D))
623  HI.Type = printType(TTP, PP);
624  else if (const auto *VT = dyn_cast<VarTemplateDecl>(D))
625  HI.Type = printType(VT->getTemplatedDecl()->getType(), Ctx, PP);
626  else if (const auto *TN = dyn_cast<TypedefNameDecl>(D))
627  HI.Type = printType(TN->getUnderlyingType().getDesugaredType(Ctx), Ctx, PP);
628  else if (const auto *TAT = dyn_cast<TypeAliasTemplateDecl>(D))
629  HI.Type = printType(TAT->getTemplatedDecl()->getUnderlyingType(), Ctx, PP);
630 
631  // Fill in value with evaluated initializer if possible.
632  if (const auto *Var = dyn_cast<VarDecl>(D)) {
633  if (const Expr *Init = Var->getInit())
634  HI.Value = printExprValue(Init, Ctx);
635  } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
636  // Dependent enums (e.g. nested in template classes) don't have values yet.
637  if (!ECD->getType()->isDependentType())
638  HI.Value = toString(ECD->getInitVal(), 10);
639  }
640 
641  HI.Definition = printDefinition(D, PP, TB);
642  return HI;
643 }
644 
645 /// The standard defines __func__ as a "predefined variable".
646 llvm::Optional<HoverInfo>
647 getPredefinedExprHoverContents(const PredefinedExpr &PE, ASTContext &Ctx,
648  const PrintingPolicy &PP) {
649  HoverInfo HI;
650  HI.Name = PE.getIdentKindName();
651  HI.Kind = index::SymbolKind::Variable;
652  HI.Documentation = "Name of the current function (predefined variable)";
653  if (const StringLiteral *Name = PE.getFunctionName()) {
654  HI.Value.emplace();
655  llvm::raw_string_ostream OS(*HI.Value);
656  Name->outputString(OS);
657  HI.Type = printType(Name->getType(), Ctx, PP);
658  } else {
659  // Inside templates, the approximate type `const char[]` is still useful.
660  QualType StringType = Ctx.getIncompleteArrayType(
661  Ctx.CharTy.withConst(), ArrayType::ArraySizeModifier::Normal,
662  /*IndexTypeQuals=*/0);
663  HI.Type = printType(StringType, Ctx, PP);
664  }
665  return HI;
666 }
667 
668 /// Generate a \p Hover object given the macro \p MacroDecl.
669 HoverInfo getHoverContents(const DefinedMacro &Macro, const syntax::Token &Tok,
670  ParsedAST &AST) {
671  HoverInfo HI;
672  SourceManager &SM = AST.getSourceManager();
673  HI.Name = std::string(Macro.Name);
674  HI.Kind = index::SymbolKind::Macro;
675  // FIXME: Populate documentation
676  // FIXME: Populate parameters
677 
678  // Try to get the full definition, not just the name
679  SourceLocation StartLoc = Macro.Info->getDefinitionLoc();
680  SourceLocation EndLoc = Macro.Info->getDefinitionEndLoc();
681  // Ensure that EndLoc is a valid offset. For example it might come from
682  // preamble, and source file might've changed, in such a scenario EndLoc still
683  // stays valid, but getLocForEndOfToken will fail as it is no longer a valid
684  // offset.
685  // Note that this check is just to ensure there's text data inside the range.
686  // It will still succeed even when the data inside the range is irrelevant to
687  // macro definition.
688  if (SM.getPresumedLoc(EndLoc, /*UseLineDirectives=*/false).isValid()) {
689  EndLoc = Lexer::getLocForEndOfToken(EndLoc, 0, SM, AST.getLangOpts());
690  bool Invalid;
691  StringRef Buffer = SM.getBufferData(SM.getFileID(StartLoc), &Invalid);
692  if (!Invalid) {
693  unsigned StartOffset = SM.getFileOffset(StartLoc);
694  unsigned EndOffset = SM.getFileOffset(EndLoc);
695  if (EndOffset <= Buffer.size() && StartOffset < EndOffset)
696  HI.Definition =
697  ("#define " + Buffer.substr(StartOffset, EndOffset - StartOffset))
698  .str();
699  }
700  }
701 
702  if (auto Expansion = AST.getTokens().expansionStartingAt(&Tok)) {
703  // We drop expansion that's longer than the threshold.
704  // For extremely long expansion text, it's not readable from hover card
705  // anyway.
706  std::string ExpansionText;
707  for (const auto &ExpandedTok : Expansion->Expanded) {
708  ExpansionText += ExpandedTok.text(SM);
709  ExpansionText += " ";
710  if (ExpansionText.size() > 2048) {
711  ExpansionText.clear();
712  break;
713  }
714  }
715 
716  if (!ExpansionText.empty()) {
717  if (!HI.Definition.empty()) {
718  HI.Definition += "\n\n";
719  }
720  HI.Definition += "// Expands to\n";
721  HI.Definition += ExpansionText;
722  }
723  }
724  return HI;
725 }
726 
727 std::string typeAsDefinition(const HoverInfo::PrintedType &PType) {
728  std::string Result;
729  llvm::raw_string_ostream OS(Result);
730  OS << PType.Type;
731  if (PType.AKA)
732  OS << " // aka: " << *PType.AKA;
733  OS.flush();
734  return Result;
735 }
736 
737 llvm::Optional<HoverInfo> getThisExprHoverContents(const CXXThisExpr *CTE,
738  ASTContext &ASTCtx,
739  const PrintingPolicy &PP) {
740  QualType OriginThisType = CTE->getType()->getPointeeType();
741  QualType ClassType = declaredType(OriginThisType->getAsTagDecl());
742  // For partial specialization class, origin `this` pointee type will be
743  // parsed as `InjectedClassNameType`, which will ouput template arguments
744  // like "type-parameter-0-0". So we retrieve user written class type in this
745  // case.
746  QualType PrettyThisType = ASTCtx.getPointerType(
747  QualType(ClassType.getTypePtr(), OriginThisType.getCVRQualifiers()));
748 
749  HoverInfo HI;
750  HI.Name = "this";
751  HI.Definition = typeAsDefinition(printType(PrettyThisType, ASTCtx, PP));
752  return HI;
753 }
754 
755 /// Generate a HoverInfo object given the deduced type \p QT
756 HoverInfo getDeducedTypeHoverContents(QualType QT, const syntax::Token &Tok,
757  ASTContext &ASTCtx,
758  const PrintingPolicy &PP,
759  const SymbolIndex *Index) {
760  HoverInfo HI;
761  // FIXME: distinguish decltype(auto) vs decltype(expr)
762  HI.Name = tok::getTokenName(Tok.kind());
763  HI.Kind = index::SymbolKind::TypeAlias;
764 
765  if (QT->isUndeducedAutoType()) {
766  HI.Definition = "/* not deduced */";
767  } else {
768  HI.Definition = typeAsDefinition(printType(QT, ASTCtx, PP));
769 
770  if (const auto *D = QT->getAsTagDecl()) {
771  const auto *CommentD = getDeclForComment(D);
772  HI.Documentation = getDeclComment(ASTCtx, *CommentD);
773  enhanceFromIndex(HI, *CommentD, Index);
774  }
775  }
776 
777  return HI;
778 }
779 
780 HoverInfo getStringLiteralContents(const StringLiteral *SL,
781  const PrintingPolicy &PP) {
782  HoverInfo HI;
783 
784  HI.Name = "string-literal";
785  HI.Size = (SL->getLength() + 1) * SL->getCharByteWidth();
786  HI.Type = SL->getType().getAsString(PP).c_str();
787 
788  return HI;
789 }
790 
791 bool isLiteral(const Expr *E) {
792  // Unfortunately there's no common base Literal classes inherits from
793  // (apart from Expr), therefore these exclusions.
794  return llvm::isa<CompoundLiteralExpr>(E) ||
795  llvm::isa<CXXBoolLiteralExpr>(E) ||
796  llvm::isa<CXXNullPtrLiteralExpr>(E) ||
797  llvm::isa<FixedPointLiteral>(E) || llvm::isa<FloatingLiteral>(E) ||
798  llvm::isa<ImaginaryLiteral>(E) || llvm::isa<IntegerLiteral>(E) ||
799  llvm::isa<UserDefinedLiteral>(E);
800 }
801 
802 llvm::StringLiteral getNameForExpr(const Expr *E) {
803  // FIXME: Come up with names for `special` expressions.
804  //
805  // It's an known issue for GCC5, https://godbolt.org/z/Z_tbgi. Work around
806  // that by using explicit conversion constructor.
807  //
808  // TODO: Once GCC5 is fully retired and not the minimal requirement as stated
809  // in `GettingStarted`, please remove the explicit conversion constructor.
810  return llvm::StringLiteral("expression");
811 }
812 
813 // Generates hover info for `this` and evaluatable expressions.
814 // FIXME: Support hover for literals (esp user-defined)
815 llvm::Optional<HoverInfo> getHoverContents(const Expr *E, ParsedAST &AST,
816  const PrintingPolicy &PP,
817  const SymbolIndex *Index) {
818  // There's not much value in hovering over "42" and getting a hover card
819  // saying "42 is an int", similar for other literals.
820  if (isLiteral(E))
821  return std::nullopt;
822 
823  HoverInfo HI;
824  // Print the type and the size for string literals
825  if (const StringLiteral *SL = dyn_cast<StringLiteral>(E))
826  return getStringLiteralContents(SL, PP);
827  // For `this` expr we currently generate hover with pointee type.
828  if (const CXXThisExpr *CTE = dyn_cast<CXXThisExpr>(E))
829  return getThisExprHoverContents(CTE, AST.getASTContext(), PP);
830  if (const PredefinedExpr *PE = dyn_cast<PredefinedExpr>(E))
831  return getPredefinedExprHoverContents(*PE, AST.getASTContext(), PP);
832  // For expressions we currently print the type and the value, iff it is
833  // evaluatable.
834  if (auto Val = printExprValue(E, AST.getASTContext())) {
835  HI.Type = printType(E->getType(), AST.getASTContext(), PP);
836  HI.Value = *Val;
837  HI.Name = std::string(getNameForExpr(E));
838  return HI;
839  }
840  return std::nullopt;
841 }
842 
843 // Generates hover info for attributes.
844 llvm::Optional<HoverInfo> getHoverContents(const Attr *A, ParsedAST &AST) {
845  HoverInfo HI;
846  HI.Name = A->getSpelling();
847  if (A->hasScope())
848  HI.LocalScope = A->getScopeName()->getName().str();
849  {
850  llvm::raw_string_ostream OS(HI.Definition);
851  A->printPretty(OS, AST.getASTContext().getPrintingPolicy());
852  }
853  HI.Documentation = Attr::getDocumentation(A->getKind()).str();
854  return HI;
855 }
856 
857 bool isParagraphBreak(llvm::StringRef Rest) {
858  return Rest.ltrim(" \t").startswith("\n");
859 }
860 
861 bool punctuationIndicatesLineBreak(llvm::StringRef Line) {
862  constexpr llvm::StringLiteral Punctuation = R"txt(.:,;!?)txt";
863 
864  Line = Line.rtrim();
865  return !Line.empty() && Punctuation.contains(Line.back());
866 }
867 
868 bool isHardLineBreakIndicator(llvm::StringRef Rest) {
869  // '-'/'*' md list, '@'/'\' documentation command, '>' md blockquote,
870  // '#' headings, '`' code blocks
871  constexpr llvm::StringLiteral LinebreakIndicators = R"txt(-*@>#`)txt";
872 
873  Rest = Rest.ltrim(" \t");
874  if (Rest.empty())
875  return false;
876 
877  if (LinebreakIndicators.contains(Rest.front()))
878  return true;
879 
880  if (llvm::isDigit(Rest.front())) {
881  llvm::StringRef AfterDigit = Rest.drop_while(llvm::isDigit);
882  if (AfterDigit.startswith(".") || AfterDigit.startswith(")"))
883  return true;
884  }
885  return false;
886 }
887 
888 bool isHardLineBreakAfter(llvm::StringRef Line, llvm::StringRef Rest) {
889  // Should we also consider whether Line is short?
890  return punctuationIndicatesLineBreak(Line) || isHardLineBreakIndicator(Rest);
891 }
892 
893 void addLayoutInfo(const NamedDecl &ND, HoverInfo &HI) {
894  if (ND.isInvalidDecl())
895  return;
896 
897  const auto &Ctx = ND.getASTContext();
898  if (auto *RD = llvm::dyn_cast<RecordDecl>(&ND)) {
899  if (auto Size = Ctx.getTypeSizeInCharsIfKnown(RD->getTypeForDecl()))
900  HI.Size = Size->getQuantity();
901  return;
902  }
903 
904  if (const auto *FD = llvm::dyn_cast<FieldDecl>(&ND)) {
905  const auto *Record = FD->getParent();
906  if (Record)
907  Record = Record->getDefinition();
908  if (Record && !Record->isInvalidDecl() && !Record->isDependentType() &&
909  !FD->isBitField()) {
910  const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Record);
911  HI.Offset = Layout.getFieldOffset(FD->getFieldIndex()) / 8;
912  if (auto Size = Ctx.getTypeSizeInCharsIfKnown(FD->getType())) {
913  HI.Size = FD->isZeroSize(Ctx) ? 0 : Size->getQuantity();
914  unsigned EndOfField = *HI.Offset + *HI.Size;
915 
916  // Calculate padding following the field.
917  if (!Record->isUnion() &&
918  FD->getFieldIndex() + 1 < Layout.getFieldCount()) {
919  // Measure padding up to the next class field.
920  unsigned NextOffset =
921  Layout.getFieldOffset(FD->getFieldIndex() + 1) / 8;
922  if (NextOffset >= EndOfField) // next field could be a bitfield!
923  HI.Padding = NextOffset - EndOfField;
924  } else {
925  // Measure padding up to the end of the object.
926  HI.Padding = Layout.getSize().getQuantity() - EndOfField;
927  }
928  }
929  // Offset in a union is always zero, so not really useful to report.
930  if (Record->isUnion())
931  HI.Offset.reset();
932  }
933  return;
934  }
935 }
936 
937 // If N is passed as argument to a function, fill HI.CalleeArgInfo with
938 // information about that argument.
939 void maybeAddCalleeArgInfo(const SelectionTree::Node *N, HoverInfo &HI,
940  const PrintingPolicy &PP) {
941  const auto &OuterNode = N->outerImplicit();
942  if (!OuterNode.Parent)
943  return;
944  const auto *CE = OuterNode.Parent->ASTNode.get<CallExpr>();
945  if (!CE)
946  return;
947  const FunctionDecl *FD = CE->getDirectCallee();
948  // For non-function-call-like operatators (e.g. operator+, operator<<) it's
949  // not immediattely obvious what the "passed as" would refer to and, given
950  // fixed function signature, the value would be very low anyway, so we choose
951  // to not support that.
952  // Both variadic functions and operator() (especially relevant for lambdas)
953  // should be supported in the future.
954  if (!FD || FD->isOverloadedOperator() || FD->isVariadic())
955  return;
956 
957  // Find argument index for N.
958  for (unsigned I = 0; I < CE->getNumArgs() && I < FD->getNumParams(); ++I) {
959  if (CE->getArg(I) != OuterNode.ASTNode.get<Expr>())
960  continue;
961 
962  // Extract matching argument from function declaration.
963  if (const ParmVarDecl *PVD = FD->getParamDecl(I))
964  HI.CalleeArgInfo.emplace(toHoverInfoParam(PVD, PP));
965  break;
966  }
967  if (!HI.CalleeArgInfo)
968  return;
969 
970  // If we found a matching argument, also figure out if it's a
971  // [const-]reference. For this we need to walk up the AST from the arg itself
972  // to CallExpr and check all implicit casts, constructor calls, etc.
973  HoverInfo::PassType PassType;
974  if (const auto *E = N->ASTNode.get<Expr>()) {
975  if (E->getType().isConstQualified())
976  PassType.PassBy = HoverInfo::PassType::ConstRef;
977  }
978 
979  for (auto *CastNode = N->Parent;
980  CastNode != OuterNode.Parent && !PassType.Converted;
981  CastNode = CastNode->Parent) {
982  if (const auto *ImplicitCast = CastNode->ASTNode.get<ImplicitCastExpr>()) {
983  switch (ImplicitCast->getCastKind()) {
984  case CK_NoOp:
985  case CK_DerivedToBase:
986  case CK_UncheckedDerivedToBase:
987  // If it was a reference before, it's still a reference.
988  if (PassType.PassBy != HoverInfo::PassType::Value)
989  PassType.PassBy = ImplicitCast->getType().isConstQualified()
992  break;
993  case CK_LValueToRValue:
994  case CK_ArrayToPointerDecay:
995  case CK_FunctionToPointerDecay:
996  case CK_NullToPointer:
997  case CK_NullToMemberPointer:
998  // No longer a reference, but we do not show this as type conversion.
999  PassType.PassBy = HoverInfo::PassType::Value;
1000  break;
1001  default:
1002  PassType.PassBy = HoverInfo::PassType::Value;
1003  PassType.Converted = true;
1004  break;
1005  }
1006  } else if (const auto *CtorCall =
1007  CastNode->ASTNode.get<CXXConstructExpr>()) {
1008  // We want to be smart about copy constructors. They should not show up as
1009  // type conversion, but instead as passing by value.
1010  if (CtorCall->getConstructor()->isCopyConstructor())
1011  PassType.PassBy = HoverInfo::PassType::Value;
1012  else
1013  PassType.Converted = true;
1014  } else { // Unknown implicit node, assume type conversion.
1015  PassType.PassBy = HoverInfo::PassType::Value;
1016  PassType.Converted = true;
1017  }
1018  }
1019 
1020  HI.CallPassType.emplace(PassType);
1021 }
1022 
1023 const NamedDecl *pickDeclToUse(llvm::ArrayRef<const NamedDecl *> Candidates) {
1024  if (Candidates.empty())
1025  return nullptr;
1026 
1027  // This is e.g the case for
1028  // namespace ns { void foo(); }
1029  // void bar() { using ns::foo; f^oo(); }
1030  // One declaration in Candidates will refer to the using declaration,
1031  // which isn't really useful for Hover. So use the other one,
1032  // which in this example would be the actual declaration of foo.
1033  if (Candidates.size() <= 2) {
1034  if (llvm::isa<UsingDecl>(Candidates.front()))
1035  return Candidates.back();
1036  return Candidates.front();
1037  }
1038 
1039  // For something like
1040  // namespace ns { void foo(int); void foo(char); }
1041  // using ns::foo;
1042  // template <typename T> void bar() { fo^o(T{}); }
1043  // we actually want to show the using declaration,
1044  // it's not clear which declaration to pick otherwise.
1045  auto BaseDecls = llvm::make_filter_range(Candidates, [](const NamedDecl *D) {
1046  return llvm::isa<UsingDecl>(D);
1047  });
1048  if (std::distance(BaseDecls.begin(), BaseDecls.end()) == 1)
1049  return *BaseDecls.begin();
1050 
1051  return Candidates.front();
1052 }
1053 
1054 } // namespace
1055 
1056 llvm::Optional<HoverInfo> getHover(ParsedAST &AST, Position Pos,
1057  const format::FormatStyle &Style,
1058  const SymbolIndex *Index) {
1059  PrintingPolicy PP =
1060  getPrintingPolicy(AST.getASTContext().getPrintingPolicy());
1061  const SourceManager &SM = AST.getSourceManager();
1062  auto CurLoc = sourceLocationInMainFile(SM, Pos);
1063  if (!CurLoc) {
1064  llvm::consumeError(CurLoc.takeError());
1065  return std::nullopt;
1066  }
1067  const auto &TB = AST.getTokens();
1068  auto TokensTouchingCursor = syntax::spelledTokensTouching(*CurLoc, TB);
1069  // Early exit if there were no tokens around the cursor.
1070  if (TokensTouchingCursor.empty())
1071  return std::nullopt;
1072 
1073  // Show full header file path if cursor is on include directive.
1074  for (const auto &Inc : AST.getIncludeStructure().MainFileIncludes) {
1075  if (Inc.Resolved.empty() || Inc.HashLine != Pos.line)
1076  continue;
1077  HoverInfo HI;
1078  HI.Name = std::string(llvm::sys::path::filename(Inc.Resolved));
1079  // FIXME: We don't have a fitting value for Kind.
1080  HI.Definition =
1081  URIForFile::canonicalize(Inc.Resolved, AST.tuPath()).file().str();
1082  HI.DefinitionLanguage = "";
1083  return HI;
1084  }
1085 
1086  // To be used as a backup for highlighting the selected token, we use back as
1087  // it aligns better with biases elsewhere (editors tend to send the position
1088  // for the left of the hovered token).
1089  CharSourceRange HighlightRange =
1090  TokensTouchingCursor.back().range(SM).toCharRange(SM);
1091  llvm::Optional<HoverInfo> HI;
1092  // Macros and deducedtype only works on identifiers and auto/decltype keywords
1093  // respectively. Therefore they are only trggered on whichever works for them,
1094  // similar to SelectionTree::create().
1095  for (const auto &Tok : TokensTouchingCursor) {
1096  if (Tok.kind() == tok::identifier) {
1097  // Prefer the identifier token as a fallback highlighting range.
1098  HighlightRange = Tok.range(SM).toCharRange(SM);
1099  if (auto M = locateMacroAt(Tok, AST.getPreprocessor())) {
1100  HI = getHoverContents(*M, Tok, AST);
1101  break;
1102  }
1103  } else if (Tok.kind() == tok::kw_auto || Tok.kind() == tok::kw_decltype) {
1104  if (auto Deduced = getDeducedType(AST.getASTContext(), Tok.location())) {
1105  HI = getDeducedTypeHoverContents(*Deduced, Tok, AST.getASTContext(), PP,
1106  Index);
1107  HighlightRange = Tok.range(SM).toCharRange(SM);
1108  break;
1109  }
1110 
1111  // If we can't find interesting hover information for this
1112  // auto/decltype keyword, return nothing to avoid showing
1113  // irrelevant or incorrect informations.
1114  return std::nullopt;
1115  }
1116  }
1117 
1118  // If it wasn't auto/decltype or macro, look for decls and expressions.
1119  if (!HI) {
1120  auto Offset = SM.getFileOffset(*CurLoc);
1121  // Editors send the position on the left of the hovered character.
1122  // So our selection tree should be biased right. (Tested with VSCode).
1123  SelectionTree ST =
1125  if (const SelectionTree::Node *N = ST.commonAncestor()) {
1126  // FIXME: Fill in HighlightRange with range coming from N->ASTNode.
1127  auto Decls = explicitReferenceTargets(N->ASTNode, DeclRelation::Alias,
1128  AST.getHeuristicResolver());
1129  if (const auto *DeclToUse = pickDeclToUse(Decls)) {
1130  HI = getHoverContents(DeclToUse, PP, Index, TB);
1131  // Layout info only shown when hovering on the field/class itself.
1132  if (DeclToUse == N->ASTNode.get<Decl>())
1133  addLayoutInfo(*DeclToUse, *HI);
1134  // Look for a close enclosing expression to show the value of.
1135  if (!HI->Value)
1136  HI->Value = printExprValue(N, AST.getASTContext());
1137  maybeAddCalleeArgInfo(N, *HI, PP);
1138  } else if (const Expr *E = N->ASTNode.get<Expr>()) {
1139  HI = getHoverContents(E, AST, PP, Index);
1140  } else if (const Attr *A = N->ASTNode.get<Attr>()) {
1141  HI = getHoverContents(A, AST);
1142  }
1143  // FIXME: support hovers for other nodes?
1144  // - built-in types
1145  }
1146  }
1147 
1148  if (!HI)
1149  return std::nullopt;
1150 
1151  // Reformat Definition
1152  if (!HI->Definition.empty()) {
1153  auto Replacements = format::reformat(
1154  Style, HI->Definition, tooling::Range(0, HI->Definition.size()));
1155  if (auto Formatted =
1156  tooling::applyAllReplacements(HI->Definition, Replacements))
1157  HI->Definition = *Formatted;
1158  }
1159 
1160  HI->DefinitionLanguage = getMarkdownLanguage(AST.getASTContext());
1161  HI->SymRange = halfOpenToRange(SM, HighlightRange);
1162 
1163  return HI;
1164 }
1165 
1168 
1169  // Header contains a text of the form:
1170  // variable `var`
1171  //
1172  // class `X`
1173  //
1174  // function `foo`
1175  //
1176  // expression
1177  //
1178  // Note that we are making use of a level-3 heading because VSCode renders
1179  // level 1 and 2 headers in a huge font, see
1180  // https://github.com/microsoft/vscode/issues/88417 for details.
1181  markup::Paragraph &Header = Output.addHeading(3);
1183  Header.appendText(index::getSymbolKindString(Kind)).appendSpace();
1184  assert(!Name.empty() && "hover triggered on a nameless symbol");
1185  Header.appendCode(Name);
1186 
1187  // Put a linebreak after header to increase readability.
1188  Output.addRuler();
1189  // Print Types on their own lines to reduce chances of getting line-wrapped by
1190  // editor, as they might be long.
1191  if (ReturnType) {
1192  // For functions we display signature in a list form, e.g.:
1193  // → `x`
1194  // Parameters:
1195  // - `bool param1`
1196  // - `int param2 = 5`
1197  Output.addParagraph().appendText("→ ").appendCode(
1198  llvm::to_string(*ReturnType));
1199  }
1200 
1201  if (Parameters && !Parameters->empty()) {
1202  Output.addParagraph().appendText("Parameters: ");
1203  markup::BulletList &L = Output.addBulletList();
1204  for (const auto &Param : *Parameters)
1205  L.addItem().addParagraph().appendCode(llvm::to_string(Param));
1206  }
1207 
1208  // Don't print Type after Parameters or ReturnType as this will just duplicate
1209  // the information
1210  if (Type && !ReturnType && !Parameters)
1211  Output.addParagraph().appendText("Type: ").appendCode(
1212  llvm::to_string(*Type));
1213 
1214  if (Value) {
1215  markup::Paragraph &P = Output.addParagraph();
1216  P.appendText("Value = ");
1217  P.appendCode(*Value);
1218  }
1219 
1220  if (Offset)
1221  Output.addParagraph().appendText(
1222  llvm::formatv("Offset: {0} byte{1}", *Offset, *Offset == 1 ? "" : "s")
1223  .str());
1224  if (Size) {
1225  auto &P = Output.addParagraph().appendText(
1226  llvm::formatv("Size: {0} byte{1}", *Size, *Size == 1 ? "" : "s").str());
1227  if (Padding && *Padding != 0)
1228  P.appendText(llvm::formatv(" (+{0} padding)", *Padding).str());
1229  }
1230 
1231  if (CalleeArgInfo) {
1232  assert(CallPassType);
1233  std::string Buffer;
1234  llvm::raw_string_ostream OS(Buffer);
1235  OS << "Passed ";
1236  if (CallPassType->PassBy != HoverInfo::PassType::Value) {
1237  OS << "by ";
1239  OS << "const ";
1240  OS << "reference ";
1241  }
1242  if (CalleeArgInfo->Name)
1243  OS << "as " << CalleeArgInfo->Name;
1244  if (CallPassType->Converted && CalleeArgInfo->Type)
1245  OS << " (converted to " << CalleeArgInfo->Type->Type << ")";
1246  Output.addParagraph().appendText(OS.str());
1247  }
1248 
1249  if (!Documentation.empty())
1251 
1252  if (!Definition.empty()) {
1253  Output.addRuler();
1254  std::string Buffer;
1255 
1256  if (!Definition.empty()) {
1257  // Append scope comment, dropping trailing "::".
1258  // Note that we don't print anything for global namespace, to not annoy
1259  // non-c++ projects or projects that are not making use of namespaces.
1260  if (!LocalScope.empty()) {
1261  // Container name, e.g. class, method, function.
1262  // We might want to propagate some info about container type to print
1263  // function foo, class X, method X::bar, etc.
1264  Buffer +=
1265  "// In " + llvm::StringRef(LocalScope).rtrim(':').str() + '\n';
1266  } else if (NamespaceScope && !NamespaceScope->empty()) {
1267  Buffer += "// In namespace " +
1268  llvm::StringRef(*NamespaceScope).rtrim(':').str() + '\n';
1269  }
1270 
1271  if (!AccessSpecifier.empty()) {
1272  Buffer += AccessSpecifier + ": ";
1273  }
1274 
1275  Buffer += Definition;
1276  }
1277 
1278  Output.addCodeBlock(Buffer, DefinitionLanguage);
1279  }
1280 
1281  return Output;
1282 }
1283 
1284 // If the backtick at `Offset` starts a probable quoted range, return the range
1285 // (including the quotes).
1286 llvm::Optional<llvm::StringRef> getBacktickQuoteRange(llvm::StringRef Line,
1287  unsigned Offset) {
1288  assert(Line[Offset] == '`');
1289 
1290  // The open-quote is usually preceded by whitespace.
1291  llvm::StringRef Prefix = Line.substr(0, Offset);
1292  constexpr llvm::StringLiteral BeforeStartChars = " \t(=";
1293  if (!Prefix.empty() && !BeforeStartChars.contains(Prefix.back()))
1294  return std::nullopt;
1295 
1296  // The quoted string must be nonempty and usually has no leading/trailing ws.
1297  auto Next = Line.find('`', Offset + 1);
1298  if (Next == llvm::StringRef::npos)
1299  return std::nullopt;
1300  llvm::StringRef Contents = Line.slice(Offset + 1, Next);
1301  if (Contents.empty() || isWhitespace(Contents.front()) ||
1302  isWhitespace(Contents.back()))
1303  return std::nullopt;
1304 
1305  // The close-quote is usually followed by whitespace or punctuation.
1306  llvm::StringRef Suffix = Line.substr(Next + 1);
1307  constexpr llvm::StringLiteral AfterEndChars = " \t)=.,;:";
1308  if (!Suffix.empty() && !AfterEndChars.contains(Suffix.front()))
1309  return std::nullopt;
1310 
1311  return Line.slice(Offset, Next + 1);
1312 }
1313 
1315  // Probably this is appendText(Line), but scan for something interesting.
1316  for (unsigned I = 0; I < Line.size(); ++I) {
1317  switch (Line[I]) {
1318  case '`':
1319  if (auto Range = getBacktickQuoteRange(Line, I)) {
1320  Out.appendText(Line.substr(0, I));
1321  Out.appendCode(Range->trim("`"), /*Preserve=*/true);
1322  return parseDocumentationLine(Line.substr(I + Range->size()), Out);
1323  }
1324  break;
1325  }
1326  }
1327  Out.appendText(Line).appendSpace();
1328 }
1329 
1330 void parseDocumentation(llvm::StringRef Input, markup::Document &Output) {
1331  std::vector<llvm::StringRef> ParagraphLines;
1332  auto FlushParagraph = [&] {
1333  if (ParagraphLines.empty())
1334  return;
1335  auto &P = Output.addParagraph();
1336  for (llvm::StringRef Line : ParagraphLines)
1338  ParagraphLines.clear();
1339  };
1340 
1341  llvm::StringRef Line, Rest;
1342  for (std::tie(Line, Rest) = Input.split('\n');
1343  !(Line.empty() && Rest.empty());
1344  std::tie(Line, Rest) = Rest.split('\n')) {
1345 
1346  // After a linebreak remove spaces to avoid 4 space markdown code blocks.
1347  // FIXME: make FlushParagraph handle this.
1348  Line = Line.ltrim();
1349  if (!Line.empty())
1350  ParagraphLines.push_back(Line);
1351 
1352  if (isParagraphBreak(Rest) || isHardLineBreakAfter(Line, Rest)) {
1353  FlushParagraph();
1354  }
1355  }
1356  FlushParagraph();
1357 }
1358 
1359 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
1360  const HoverInfo::PrintedType &T) {
1361  OS << T.Type;
1362  if (T.AKA)
1363  OS << " (aka " << *T.AKA << ")";
1364  return OS;
1365 }
1366 
1367 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
1368  const HoverInfo::Param &P) {
1369  if (P.Type)
1370  OS << P.Type->Type;
1371  if (P.Name)
1372  OS << " " << *P.Name;
1373  if (P.Default)
1374  OS << " = " << *P.Default;
1375  if (P.Type && P.Type->AKA)
1376  OS << " (aka " << *P.Type->AKA << ")";
1377  return OS;
1378 }
1379 
1380 } // namespace clangd
1381 } // namespace clang
Range
CharSourceRange Range
SourceRange for the file name.
Definition: IncludeOrderCheck.cpp:39
clang::clangd::getDeclComment
std::string getDeclComment(const ASTContext &Ctx, const NamedDecl &Decl)
Similar to getDocComment, but returns the comment for a NamedDecl.
Definition: CodeCompletionStrings.cpp:73
clang::clangd::markup::BulletList
Represents a sequence of one or more documents.
Definition: Markup.h:80
Base
std::unique_ptr< GlobalCompilationDatabase > Base
Definition: GlobalCompilationDatabaseTests.cpp:85
Suffix
std::string Suffix
Definition: AddUsing.cpp:113
clang::clangd::locateMacroAt
llvm::Optional< DefinedMacro > locateMacroAt(const syntax::Token &SpelledTok, Preprocessor &PP)
Gets the macro referenced by SpelledTok.
Definition: SourceCode.cpp:977
Selection.h
clang::clangd::Config::Hover
struct clang::clangd::Config::@7 Hover
Configures hover feature.
E
const Expr * E
Definition: AvoidBindCheck.cpp:88
clang::clangd::HoverInfo::Type
llvm::Optional< PrintedType > Type
Printable variable type.
Definition: Hover.h:80
clang::clangd::declaredType
QualType declaredType(const TypeDecl *D)
Definition: AST.cpp:424
clang::doc::MD
static GeneratorRegistry::Add< MDGenerator > MD(MDGenerator::Format, "Generator for MD output.")
clang::clangd::HighlightingModifier::Deduced
@ Deduced
clang::clangd::HoverInfo::Offset
llvm::Optional< uint64_t > Offset
Contains the offset of fields within the enclosing class.
Definition: Hover.h:92
clang::clangd::markup::Paragraph
Represents parts of the markup that can contain strings, like inline code, code block or plain text.
Definition: Markup.h:43
FormatStyle
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))
clang::clangd::SymbolCollector::shouldCollectSymbol
static bool shouldCollectSymbol(const NamedDecl &ND, const ASTContext &ASTCtx, const Options &Opts, bool IsMainFileSymbol)
Returns true is ND should be collected.
Definition: SymbolCollector.cpp:467
clang::clangd::ParsedAST::getIncludeStructure
const IncludeStructure & getIncludeStructure() const
Definition: ParsedAST.cpp:757
clang::clangd::HoverInfo::Kind
index::SymbolKind Kind
Definition: Hover.h:70
clang::clangd::ParsedAST::getASTContext
ASTContext & getASTContext()
Note that the returned ast will not contain decls from the preamble that were not deserialized during...
Definition: ParsedAST.cpp:700
clang::clangd::markup::Paragraph::appendText
Paragraph & appendText(llvm::StringRef Text)
Append plain text to the end of the string.
Definition: Markup.cpp:423
clang::clangd::Punctuation
@ Punctuation
Definition: FuzzyMatch.h:45
clang::clangd::HoverInfo::CallPassType
llvm::Optional< PassType > CallPassType
Definition: Hover.h:108
Ctx
Context Ctx
Definition: TUScheduler.cpp:553
clang::clangd::markup::Document
A format-agnostic representation for structured text.
Definition: Markup.h:97
clang::clangd::printObjCMethod
std::string printObjCMethod(const ObjCMethodDecl &Method)
Print the Objective-C method name, including the full container name, e.g.
Definition: AST.cpp:308
clang::tidy::cppcoreguidelines::isLiteral
static bool isLiteral(const Expr *E)
Definition: PreferMemberInitializerCheck.cpp:37
clang::tidy::cppcoreguidelines::join
static std::string join(ArrayRef< SpecialMemberFunctionsCheck::SpecialMemberFunctionKind > SMFS, llvm::StringRef AndOr)
Definition: SpecialMemberFunctionsCheck.cpp:78
clang::clangd::HoverInfo::ReturnType
llvm::Optional< PrintedType > ReturnType
Set for functions and lambdas.
Definition: Hover.h:82
FindTarget.h
clang::clangd::IncludeStructure::MainFileIncludes
std::vector< Inclusion > MainFileIncludes
Definition: Headers.h:168
clang::clangd::getDeducedType
llvm::Optional< QualType > getDeducedType(ASTContext &ASTCtx, SourceLocation Loc)
Retrieves the deduced type at a given location (auto, decltype).
Definition: AST.cpp:567
clang::clangd::ParsedAST::getLangOpts
const LangOptions & getLangOpts() const
Definition: ParsedAST.h:81
clang::clangd::HighlightingKind::Macro
@ Macro
Pos
size_t Pos
Definition: NoLintDirectiveHandler.cpp:97
clang::clangd::HoverInfo::Parameters
llvm::Optional< std::vector< Param > > Parameters
Set for functions, lambdas and macros with parameters.
Definition: Hover.h:84
clang::clangd::HoverInfo::Size
llvm::Optional< uint64_t > Size
Contains the byte-size of fields and types where it's interesting.
Definition: Hover.h:90
clang::clangd::printType
std::string printType(const QualType QT, const DeclContext &CurContext, const llvm::StringRef Placeholder)
Returns a QualType as string.
Definition: AST.cpp:380
M
const google::protobuf::Message & M
Definition: Server.cpp:309
clang::clangd::markup::Paragraph::appendSpace
Paragraph & appendSpace()
Ensure there is space between the surrounding chunks.
Definition: Markup.cpp:417
Hover.h
clang::clangd::CompletionItemKind::Constant
@ Constant
clang::clangd::HoverInfo::Name
std::string Name
Name of the symbol, does not contain any "::".
Definition: Hover.h:68
Offset
size_t Offset
Definition: CodeComplete.cpp:1213
ns1::ns2::A
@ A
Definition: CategoricalFeature.h:3
clang::clangd::halfOpenToRange
Range halfOpenToRange(const SourceManager &SM, CharSourceRange R)
Definition: SourceCode.cpp:467
clang::clangd::Position
Definition: Protocol.h:156
ns1::ns2::D
@ D
Definition: CategoricalFeature.h:3
clang::tidy::bugprone::model::MixFlags::Invalid
@ Invalid
Sentinel bit pattern. DO NOT USE!
clang::clangd::HoverInfo::Definition
std::string Definition
Source code containing the definition of the symbol.
Definition: Hover.h:73
clang::clangd::SymbolIndex::lookup
virtual void lookup(const LookupRequest &Req, llvm::function_ref< void(const Symbol &)> Callback) const =0
Looks up symbols with any of the given symbol IDs and applies Callback on each matched symbol.
clang::clangd::printName
std::string printName(const ASTContext &Ctx, const NamedDecl &ND)
Prints unqualified name of the decl for the purpose of displaying it to the user.
Definition: AST.cpp:225
Config
static cl::opt< std::string > Config("config", cl::desc(R"( Specifies a configuration in YAML/JSON format: -config="{Checks:' *', CheckOptions:{x:y}}" When the value is empty, clang-tidy will attempt to find a file named .clang-tidy for each source file in its parent directories. )"), cl::init(""), cl::cat(ClangTidyCategory))
Decl
const FunctionDecl * Decl
Definition: AvoidBindCheck.cpp:100
CodeCompletionStrings.h
clang::clangd::SelectionTree::createRight
static SelectionTree createRight(ASTContext &AST, const syntax::TokenBuffer &Tokens, unsigned Begin, unsigned End)
Definition: Selection.cpp:1059
clang::clangd::Unknown
@ Unknown
Definition: FuzzyMatch.h:56
Line
int Line
Definition: PreprocessorTracker.cpp:514
clang::clangd::HoverInfo::Padding
llvm::Optional< uint64_t > Padding
Contains the padding following a field within the enclosing class.
Definition: Hover.h:94
clang::tidy::modernize::getTokenName
static StringRef getTokenName(const Token &Tok)
Definition: MacroToEnumCheck.cpp:78
clang::clangd::printQualifiedName
std::string printQualifiedName(const NamedDecl &ND)
Returns the qualified name of ND.
Definition: AST.cpp:183
Markup.h
clang::clangd::getSymbolInfo
std::vector< SymbolDetails > getSymbolInfo(ParsedAST &AST, Position Pos)
Get info about symbols at Pos.
Definition: XRefs.cpp:1480
clang::clangd::HoverInfo
Contains detailed information about a Symbol.
Definition: Hover.h:24
clang::clangd::HoverInfo::AccessSpecifier
std::string AccessSpecifier
Access specifier for declarations inside class/struct/unions, empty for others.
Definition: Hover.h:77
clang::clangd::HoverInfo::PassType::Ref
@ Ref
Definition: Hover.h:100
clang::clangd::toString
static const char * toString(OffsetEncoding OE)
Definition: Protocol.cpp:1393
clang::clangd::HoverInfo::Param::Name
llvm::Optional< std::string > Name
None for unnamed parameters.
Definition: Hover.h:48
clang::clangd::getHover
llvm::Optional< HoverInfo > getHover(ParsedAST &AST, Position Pos, const format::FormatStyle &Style, const SymbolIndex *Index)
Get the hover information when hovering at Pos.
Definition: Hover.cpp:1056
Name
Token Name
Definition: MacroToEnumCheck.cpp:89
clang::clangd::ParsedAST::getHeuristicResolver
const HeuristicResolver * getHeuristicResolver() const
Definition: ParsedAST.h:119
clang::clangd::SelectionTree
Definition: Selection.h:76
clang::clangd::explicitReferenceTargets
llvm::SmallVector< const NamedDecl *, 1 > explicitReferenceTargets(DynTypedNode N, DeclRelationSet Mask, const HeuristicResolver *Resolver)
Find declarations explicitly referenced in the source code defined by N.
Definition: FindTarget.cpp:575
clang::clangd::operator<<
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
Definition: CodeComplete.cpp:2217
clang::clangd::HoverInfo::NamespaceScope
llvm::Optional< std::string > NamespaceScope
For a variable named Bar, declared in clang::clangd::Foo::getFoo the following fields will hold:
Definition: Hover.h:63
clang::clangd::HoverInfo::Param::Default
llvm::Optional< std::string > Default
None if no default is provided.
Definition: Hover.h:50
clang::clangd::ParsedAST::getPreprocessor
Preprocessor & getPreprocessor()
Definition: ParsedAST.cpp:708
Output
std::string Output
Definition: TraceTests.cpp:159
clang::clangd::ParsedAST::tuPath
PathRef tuPath() const
Returns the path passed by the caller when building this AST.
Definition: ParsedAST.h:113
clang::clangd::SelectionTree::Node
Definition: Selection.h:122
clang::tidy::bugprone::PP
static Preprocessor * PP
Definition: BadSignalToKillThreadCheck.cpp:29
clang::clangd::markup::Paragraph::appendCode
Paragraph & appendCode(llvm::StringRef Code, bool Preserve=false)
Append inline code, this translates to the ` block in markdown.
Definition: Markup.cpp:436
clang::clangd::parseDocumentationLine
void parseDocumentationLine(llvm::StringRef Line, markup::Paragraph &Out)
Definition: Hover.cpp:1314
clang::clangd::SelectionTree::commonAncestor
const Node * commonAncestor() const
Definition: Selection.cpp:1089
clang::clangd::getSymbolID
SymbolID getSymbolID(const Decl *D)
Gets the symbol ID for a declaration. Returned SymbolID might be null.
Definition: AST.cpp:349
SourceCode.h
Index
const SymbolIndex * Index
Definition: Dexp.cpp:98
clang::clangd::SymbolIndex
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
Definition: Index.h:113
Config.h
CE
CaptureExpr CE
Definition: AvoidBindCheck.cpp:67
clang::clangd::HoverInfo::LocalScope
std::string LocalScope
Remaining named contexts in symbol's qualified name, empty string means symbol is not local.
Definition: Hover.h:66
clang::clangd::HoverInfo::DefinitionLanguage
const char * DefinitionLanguage
Definition: Hover.h:74
ID
static char ID
Definition: Logger.cpp:74
clang::clangd::HoverInfo::present
markup::Document present() const
Produce a user-readable information.
Definition: Hover.cpp:1166
clang::clangd::HoverInfo::PrintedType
Contains pretty-printed type and desugared type.
Definition: Hover.h:26
clang::clangd::Range
Definition: Protocol.h:185
clang::clangd::URIForFile::canonicalize
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)
Canonicalizes AbsPath via URI.
Definition: Protocol.cpp:45
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
OS
llvm::raw_string_ostream OS
Definition: TraceTests.cpp:160
clang::clangd::HoverInfo::CalleeArgInfo
llvm::Optional< Param > CalleeArgInfo
Definition: Hover.h:97
clang::clangd::ParsedAST::getTokens
const syntax::TokenBuffer & getTokens() const
Tokens recorded while parsing the main file.
Definition: ParsedAST.h:107
LangOpts
const LangOptions * LangOpts
Definition: ExtractFunction.cpp:375
clang::doc::Record
llvm::SmallVector< uint64_t, 1024 > Record
Definition: BitcodeReader.cpp:18
clang::clangd::HoverInfo::Value
llvm::Optional< std::string > Value
Contains the evaluated value of the symbol if available.
Definition: Hover.h:88
clang::clangd::Config::current
static const Config & current()
Returns the Config of the current Context, or an empty configuration.
Definition: Config.cpp:17
clang::clangd::parseDocumentation
void parseDocumentation(llvm::StringRef Input, markup::Document &Output)
Definition: Hover.cpp:1330
clang::clangd::URIForFile::file
llvm::StringRef file() const
Retrieves absolute path to the file.
Definition: Protocol.h:104
SymbolCollector.h
clang::clangd::getBacktickQuoteRange
llvm::Optional< llvm::StringRef > getBacktickQuoteRange(llvm::StringRef Line, unsigned Offset)
Definition: Hover.cpp:1286
clang::clangd::HoverInfo::PassType::Value
@ Value
Definition: Hover.h:100
clang::clangd::ParsedAST
Stores and provides access to parsed AST.
Definition: ParsedAST.h:46
clang::clangd::printObjCContainer
std::string printObjCContainer(const ObjCContainerDecl &C)
Print the Objective-C container name including categories, e.g. MyClass,.
Definition: AST.cpp:328
Field
const FieldDecl * Field
Definition: MemberwiseConstructor.cpp:260
Out
CompiledFragmentImpl & Out
Definition: ConfigCompile.cpp:99
clang::clangd::RefKind::Definition
@ Definition
clang::clangd::ParsedAST::getSourceManager
SourceManager & getSourceManager()
Definition: ParsedAST.h:74
clang::clangd::HoverInfo::Param
Represents parameters of a function, a template or a macro.
Definition: Hover.h:43
clang::clangd::HoverInfo::PassType::ConstRef
@ ConstRef
Definition: Hover.h:100
clang::clangd::HoverInfo::Param::Type
llvm::Optional< PrintedType > Type
The printable parameter type, e.g.
Definition: Hover.h:46
clang::clangd::sourceLocationInMainFile
llvm::Expected< SourceLocation > sourceLocationInMainFile(const SourceManager &SM, Position P)
Return the file location, corresponding to P.
Definition: SourceCode.cpp:457
clang::clangd::HoverInfo::Documentation
std::string Documentation
Definition: Hover.h:71
clang::clangd::Config::ShowAKA
bool ShowAKA
Whether hover show a.k.a type.
Definition: Config.h:131
clang::clangd::DeclRelation::Alias
@ Alias
This declaration is an alias that was referred to.
AST.h
ParsedAST.h