clang-tools 10.0.0

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 "FindTarget.h"
14 #include "FormattedString.h"
15 #include "Logger.h"
16 #include "ParsedAST.h"
17 #include "Selection.h"
18 #include "SourceCode.h"
19 #include "index/SymbolCollector.h"
20 #include "clang/AST/ASTContext.h"
21 #include "clang/AST/ASTTypeTraits.h"
22 #include "clang/AST/Decl.h"
23 #include "clang/AST/DeclBase.h"
24 #include "clang/AST/DeclTemplate.h"
25 #include "clang/AST/Expr.h"
26 #include "clang/AST/ExprCXX.h"
27 #include "clang/AST/PrettyPrinter.h"
28 #include "clang/AST/Type.h"
29 #include "clang/Basic/Specifiers.h"
30 #include "clang/Index/IndexSymbol.h"
31 #include "llvm/ADT/None.h"
32 #include "llvm/ADT/Optional.h"
33 #include "llvm/ADT/STLExtras.h"
34 #include "llvm/ADT/SmallVector.h"
35 #include "llvm/ADT/StringExtras.h"
36 #include "llvm/ADT/StringRef.h"
37 #include "llvm/Support/Casting.h"
38 #include "llvm/Support/ErrorHandling.h"
39 #include "llvm/Support/raw_ostream.h"
40 #include <string>
41
42 namespace clang {
43 namespace clangd {
44 namespace {
45
46 PrintingPolicy printingPolicyForDecls(PrintingPolicy Base) {
47 PrintingPolicy Policy(Base);
48
49 Policy.AnonymousTagLocations = false;
50 Policy.TerseOutput = true;
51 Policy.PolishForDeclaration = true;
52 Policy.ConstantsAsWritten = true;
53 Policy.SuppressTagKeyword = false;
54
55 return Policy;
56 }
57
58 /// Given a declaration \p D, return a human-readable string representing the
59 /// local scope in which it is declared, i.e. class(es) and method name. Returns
60 /// an empty string if it is not local.
61 std::string getLocalScope(const Decl *D) {
62 std::vector<std::string> Scopes;
63 const DeclContext *DC = D->getDeclContext();
64 auto GetName = [](const TypeDecl *D) {
65 if (!D->getDeclName().isEmpty()) {
66 PrintingPolicy Policy = D->getASTContext().getPrintingPolicy();
67 Policy.SuppressScope = true;
68 return declaredType(D).getAsString(Policy);
69 }
70 if (auto RD = dyn_cast<RecordDecl>(D))
71 return ("(anonymous " + RD->getKindName() + ")").str();
72 return std::string("");
73 };
74 while (DC) {
75 if (const TypeDecl *TD = dyn_cast<TypeDecl>(DC))
76 Scopes.push_back(GetName(TD));
77 else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
78 Scopes.push_back(FD->getNameAsString());
79 DC = DC->getParent();
80 }
81
82 return llvm::join(llvm::reverse(Scopes), "::");
83 }
84
85 /// Returns the human-readable representation for namespace containing the
86 /// declaration \p D. Returns empty if it is contained global namespace.
87 std::string getNamespaceScope(const Decl *D) {
88 const DeclContext *DC = D->getDeclContext();
89
90 if (const TagDecl *TD = dyn_cast<TagDecl>(DC))
91 return getNamespaceScope(TD);
92 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
93 return getNamespaceScope(FD);
94 if (const NamespaceDecl *NSD = dyn_cast<NamespaceDecl>(DC)) {
95 // Skip inline/anon namespaces.
96 if (NSD->isInline() || NSD->isAnonymousNamespace())
97 return getNamespaceScope(NSD);
98 }
99 if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC))
100 return printQualifiedName(*ND);
101
102 return "";
103 }
104
105 std::string printDefinition(const Decl *D) {
106 std::string Definition;
107 llvm::raw_string_ostream OS(Definition);
108 PrintingPolicy Policy =
109 printingPolicyForDecls(D->getASTContext().getPrintingPolicy());
110 Policy.IncludeTagDefinition = false;
111 Policy.SuppressTemplateArgsInCXXConstructors = true;
112 Policy.SuppressTagKeyword = true;
113 D->print(OS, Policy);
114 OS.flush();
115 return Definition;
116 }
117
118 void printParams(llvm::raw_ostream &OS,
119 const std::vector<HoverInfo::Param> &Params) {
120 for (size_t I = 0, E = Params.size(); I != E; ++I) {
121 if (I)
122 OS << ", ";
123 OS << Params.at(I);
124 }
125 }
126
127 std::string printType(QualType QT, const PrintingPolicy &Policy) {
128 // TypePrinter doesn't resolve decltypes, so resolve them here.
129 // FIXME: This doesn't handle composite types that contain a decltype in them.
130 // We should rather have a printing policy for that.
131 while (const auto *DT = QT->getAs<DecltypeType>())
132 QT = DT->getUnderlyingType();
133 return QT.getAsString(Policy);
134 }
135
136 std::vector<HoverInfo::Param>
137 fetchTemplateParameters(const TemplateParameterList *Params,
138 const PrintingPolicy &PP) {
139 assert(Params);
140 std::vector<HoverInfo::Param> TempParameters;
141
142 for (const Decl *Param : *Params) {
143 HoverInfo::Param P;
144 if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
145 P.Type = TTP->wasDeclaredWithTypename() ? "typename" : "class";
146 if (TTP->isParameterPack())
147 *P.Type += "...";
148
149 if (!TTP->getName().empty())
150 P.Name = TTP->getNameAsString();
151 if (TTP->hasDefaultArgument())
152 P.Default = TTP->getDefaultArgument().getAsString(PP);
153 } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
154 if (IdentifierInfo *II = NTTP->getIdentifier())
155 P.Name = II->getName().str();
156
157 P.Type = printType(NTTP->getType(), PP);
158 if (NTTP->isParameterPack())
159 *P.Type += "...";
160
161 if (NTTP->hasDefaultArgument()) {
162 P.Default.emplace();
163 llvm::raw_string_ostream Out(*P.Default);
164 NTTP->getDefaultArgument()->printPretty(Out, nullptr, PP);
165 }
166 } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) {
167 P.Type.emplace();
168 llvm::raw_string_ostream OS(*P.Type);
169 OS << "template <";
170 printParams(OS,
171 fetchTemplateParameters(TTPD->getTemplateParameters(), PP));
172 OS << "> class"; // FIXME: TemplateTemplateParameter doesn't store the
173 // info on whether this param was a "typename" or
174 // "class".
175 if (!TTPD->getName().empty())
176 P.Name = TTPD->getNameAsString();
177 if (TTPD->hasDefaultArgument()) {
178 P.Default.emplace();
179 llvm::raw_string_ostream Out(*P.Default);
180 TTPD->getDefaultArgument().getArgument().print(PP, Out);
181 }
182 }
183 TempParameters.push_back(std::move(P));
184 }
185
186 return TempParameters;
187 }
188
189 const FunctionDecl *getUnderlyingFunction(const Decl *D) {
190 // Extract lambda from variables.
191 if (const VarDecl *VD = llvm::dyn_cast<VarDecl>(D)) {
192 auto QT = VD->getType();
193 if (!QT.isNull()) {
194 while (!QT->getPointeeType().isNull())
195 QT = QT->getPointeeType();
196
197 if (const auto *CD = QT->getAsCXXRecordDecl())
198 return CD->getLambdaCallOperator();
199 }
200 }
201
202 // Non-lambda functions.
203 return D->getAsFunction();
204 }
205
206 // Returns the decl that should be used for querying comments, either from index
207 // or AST.
208 const NamedDecl *getDeclForComment(const NamedDecl *D) {
209 if (const auto *TSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D)) {
210 // Template may not be instantiated e.g. if the type didn't need to be
211 // complete; fallback to primary template.
212 if (TSD->getTemplateSpecializationKind() == TSK_Undeclared)
213 return TSD->getSpecializedTemplate();
214 if (const auto *TIP = TSD->getTemplateInstantiationPattern())
215 return TIP;
216 }
217 if (const auto *TSD = llvm::dyn_cast<VarTemplateSpecializationDecl>(D)) {
218 if (TSD->getTemplateSpecializationKind() == TSK_Undeclared)
219 return TSD->getSpecializedTemplate();
220 if (const auto *TIP = TSD->getTemplateInstantiationPattern())
221 return TIP;
222 }
223 if (const auto *FD = D->getAsFunction())
224 if (const auto *TIP = FD->getTemplateInstantiationPattern())
225 return TIP;
226 return D;
227 }
228
229 // Look up information about D from the index, and add it to Hover.
230 void enhanceFromIndex(HoverInfo &Hover, const NamedDecl &ND,
231 const SymbolIndex *Index) {
232 assert(&ND == getDeclForComment(&ND));
233 // We only add documentation, so don't bother if we already have some.
234 if (!Hover.Documentation.empty() || !Index)
235 return;
236
237 // Skip querying for non-indexable symbols, there's no point.
238 // We're searching for symbols that might be indexed outside this main file.
239 if (!SymbolCollector::shouldCollectSymbol(ND, ND.getASTContext(),
240 SymbolCollector::Options(),
241 /*IsMainFileOnly=*/false))
242 return;
243 auto ID = getSymbolID(&ND);
244 if (!ID)
245 return;
246 LookupRequest Req;
247 Req.IDs.insert(*ID);
248 Index->lookup(
249 Req, [&](const Symbol &S) { Hover.Documentation = S.Documentation; });
250 }
251
252 // Populates Type, ReturnType, and Parameters for function-like decls.
253 void fillFunctionTypeAndParams(HoverInfo &HI, const Decl *D,
254 const FunctionDecl *FD,
255 const PrintingPolicy &Policy) {
256 HI.Parameters.emplace();
257 for (const ParmVarDecl *PVD : FD->parameters()) {
258 HI.Parameters->emplace_back();
259 auto &P = HI.Parameters->back();
260 if (!PVD->getType().isNull()) {
261 P.Type = printType(PVD->getType(), Policy);
262 } else {
263 std::string Param;
264 llvm::raw_string_ostream OS(Param);
265 PVD->dump(OS);
266 OS.flush();
267 elog("Got param with null type: {0}", Param);
268 }
269 if (!PVD->getName().empty())
270 P.Name = PVD->getNameAsString();
271 if (PVD->hasDefaultArg()) {
272 P.Default.emplace();
273 llvm::raw_string_ostream Out(*P.Default);
274 PVD->getDefaultArg()->printPretty(Out, nullptr, Policy);
275 }
276 }
277
278 // We don't want any type info, if name already contains it. This is true for
279 // constructors/destructors and conversion operators.
280 const auto NK = FD->getDeclName().getNameKind();
281 if (NK == DeclarationName::CXXConstructorName ||
282 NK == DeclarationName::CXXDestructorName ||
283 NK == DeclarationName::CXXConversionFunctionName)
284 return;
285
286 HI.ReturnType = printType(FD->getReturnType(), Policy);
287 QualType QT = FD->getType();
288 if (const VarDecl *VD = llvm::dyn_cast<VarDecl>(D)) // Lambdas
289 QT = VD->getType().getDesugaredType(D->getASTContext());
290 HI.Type = printType(QT, Policy);
291 // FIXME: handle variadics.
292 }
293
294 llvm::Optional<std::string> printExprValue(const Expr *E,
295 const ASTContext &Ctx) {
296 Expr::EvalResult Constant;
297 // Evaluating [[foo]]() as "&foo" isn't useful, and prevents us walking up
298 // to the enclosing call.
299 QualType T = E->getType();
300 if (T.isNull() || T->isFunctionType() || T->isFunctionPointerType() ||
301 T->isFunctionReferenceType())
302 return llvm::None;
303 // Attempt to evaluate. If expr is dependent, evaluation crashes!
304 if (E->isValueDependent() || !E->EvaluateAsRValue(Constant, Ctx))
305 return llvm::None;
306
307 // Show enums symbolically, not numerically like APValue::printPretty().
308 if (T->isEnumeralType() && Constant.Val.getInt().getMinSignedBits() <= 64) {
309 // Compare to int64_t to avoid bit-width match requirements.
310 int64_t Val = Constant.Val.getInt().getExtValue();
311 for (const EnumConstantDecl *ECD :
312 T->castAs<EnumType>()->getDecl()->enumerators())
313 if (ECD->getInitVal() == Val)
314 return llvm::formatv("{0} ({1})", ECD->getNameAsString(), Val).str();
315 }
316 return Constant.Val.getAsString(Ctx, E->getType());
317 }
318
319 llvm::Optional<std::string> printExprValue(const SelectionTree::Node *N,
320 const ASTContext &Ctx) {
321 for (; N; N = N->Parent) {
322 // Try to evaluate the first evaluatable enclosing expression.
323 if (const Expr *E = N->ASTNode.get<Expr>()) {
324 if (auto Val = printExprValue(E, Ctx))
325 return Val;
326 } else if (N->ASTNode.get<Decl>() || N->ASTNode.get<Stmt>()) {
327 // Refuse to cross certain non-exprs. (TypeLoc are OK as part of Exprs).
328 // This tries to ensure we're showing a value related to the cursor.
329 break;
330 }
331 }
332 return llvm::None;
333 }
334
335 /// Generate a \p Hover object given the declaration \p D.
336 HoverInfo getHoverContents(const NamedDecl *D, const SymbolIndex *Index) {
337 HoverInfo HI;
338 const ASTContext &Ctx = D->getASTContext();
339
340 HI.NamespaceScope = getNamespaceScope(D);
341 if (!HI.NamespaceScope->empty())
342 HI.NamespaceScope->append("::");
343 HI.LocalScope = getLocalScope(D);
344 if (!HI.LocalScope.empty())
345 HI.LocalScope.append("::");
346
347 PrintingPolicy Policy = printingPolicyForDecls(Ctx.getPrintingPolicy());
348 HI.Name = printName(Ctx, *D);
349 const auto *CommentD = getDeclForComment(D);
350 HI.Documentation = getDeclComment(Ctx, *CommentD);
351 enhanceFromIndex(HI, *CommentD, Index);
352
353 HI.Kind = index::getSymbolInfo(D).Kind;
354
355 // Fill in template params.
356 if (const TemplateDecl *TD = D->getDescribedTemplate()) {
357 HI.TemplateParameters =
358 fetchTemplateParameters(TD->getTemplateParameters(), Policy);
359 D = TD;
360 } else if (const FunctionDecl *FD = D->getAsFunction()) {
361 if (const auto *FTD = FD->getDescribedTemplate()) {
362 HI.TemplateParameters =
363 fetchTemplateParameters(FTD->getTemplateParameters(), Policy);
364 D = FTD;
365 }
366 }
367
368 // Fill in types and params.
369 if (const FunctionDecl *FD = getUnderlyingFunction(D))
370 fillFunctionTypeAndParams(HI, D, FD, Policy);
371 else if (const auto *VD = dyn_cast<ValueDecl>(D))
372 HI.Type = printType(VD->getType(), Policy);
373
374 // Fill in value with evaluated initializer if possible.
375 if (const auto *Var = dyn_cast<VarDecl>(D)) {
376 if (const Expr *Init = Var->getInit())
377 HI.Value = printExprValue(Init, Ctx);
378 } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
379 // Dependent enums (e.g. nested in template classes) don't have values yet.
380 if (!ECD->getType()->isDependentType())
381 HI.Value = ECD->getInitVal().toString(10);
382 }
383
384 HI.Definition = printDefinition(D);
385 return HI;
386 }
387
388 /// Generate a \p Hover object given the type \p T.
389 HoverInfo getHoverContents(QualType T, ASTContext &ASTCtx,
390 const SymbolIndex *Index) {
391 HoverInfo HI;
392
393 if (const auto *D = T->getAsTagDecl()) {
394 HI.Name = printName(ASTCtx, *D);
395 HI.Kind = index::getSymbolInfo(D).Kind;
396
397 const auto *CommentD = getDeclForComment(D);
398 HI.Documentation = getDeclComment(ASTCtx, *CommentD);
399 enhanceFromIndex(HI, *CommentD, Index);
400 } else {
401 // Builtin types
402 auto Policy = printingPolicyForDecls(ASTCtx.getPrintingPolicy());
403 Policy.SuppressTagKeyword = true;
404 HI.Name = T.getAsString(Policy);
405 }
406 return HI;
407 }
408
409 /// Generate a \p Hover object given the macro \p MacroDecl.
410 HoverInfo getHoverContents(const DefinedMacro &Macro, ParsedAST &AST) {
411 HoverInfo HI;
412 SourceManager &SM = AST.getSourceManager();
413 HI.Name = Macro.Name;
414 HI.Kind = index::SymbolKind::Macro;
415 // FIXME: Populate documentation
416 // FIXME: Pupulate parameters
417
418 // Try to get the full definition, not just the name
419 SourceLocation StartLoc = Macro.Info->getDefinitionLoc();
420 SourceLocation EndLoc = Macro.Info->getDefinitionEndLoc();
421 if (EndLoc.isValid()) {
422 EndLoc = Lexer::getLocForEndOfToken(EndLoc, 0, SM, AST.getLangOpts());
423 bool Invalid;
424 StringRef Buffer = SM.getBufferData(SM.getFileID(StartLoc), &Invalid);
425 if (!Invalid) {
426 unsigned StartOffset = SM.getFileOffset(StartLoc);
427 unsigned EndOffset = SM.getFileOffset(EndLoc);
428 if (EndOffset <= Buffer.size() && StartOffset < EndOffset)
429 HI.Definition =
430 ("#define " + Buffer.substr(StartOffset, EndOffset - StartOffset))
431 .str();
432 }
433 }
434 return HI;
435 }
436
437 bool isLiteral(const Expr *E) {
438 // Unfortunately there's no common base Literal classes inherits from
439 // (apart from Expr), therefore this is a nasty blacklist.
440 return llvm::isa<CharacterLiteral>(E) || llvm::isa<CompoundLiteralExpr>(E) ||
441 llvm::isa<CXXBoolLiteralExpr>(E) ||
442 llvm::isa<CXXNullPtrLiteralExpr>(E) ||
443 llvm::isa<FixedPointLiteral>(E) || llvm::isa<FloatingLiteral>(E) ||
444 llvm::isa<ImaginaryLiteral>(E) || llvm::isa<IntegerLiteral>(E) ||
445 llvm::isa<StringLiteral>(E) || llvm::isa<UserDefinedLiteral>(E);
446 }
447
448 llvm::StringLiteral getNameForExpr(const Expr *E) {
449 // FIXME: Come up with names for `special` expressions.
450 //
451 // It's an known issue for GCC5, https://godbolt.org/z/Z_tbgi. Work around
452 // that by using explicit conversion constructor.
453 //
454 // TODO: Once GCC5 is fully retired and not the minimal requirement as stated
455 // in `GettingStarted`, please remove the explicit conversion constructor.
456 return llvm::StringLiteral("expression");
457 }
458
459 // Generates hover info for evaluatable expressions.
460 // FIXME: Support hover for literals (esp user-defined)
461 llvm::Optional<HoverInfo> getHoverContents(const Expr *E, ParsedAST &AST) {
462 // There's not much value in hovering over "42" and getting a hover card
463 // saying "42 is an int", similar for other literals.
464 if (isLiteral(E))
465 return llvm::None;
466
467 HoverInfo HI;
468 // For expressions we currently print the type and the value, iff it is
469 // evaluatable.
470 if (auto Val = printExprValue(E, AST.getASTContext())) {
471 auto Policy =
472 printingPolicyForDecls(AST.getASTContext().getPrintingPolicy());
473 Policy.SuppressTagKeyword = true;
474 HI.Type = printType(E->getType(), Policy);
475 HI.Value = *Val;
476 HI.Name = getNameForExpr(E);
477 return HI;
478 }
479 return llvm::None;
480 }
481 } // namespace
482
483 llvm::Optional<HoverInfo> getHover(ParsedAST &AST, Position Pos,
484 format::FormatStyle Style,
485 const SymbolIndex *Index) {
486 const SourceManager &SM = AST.getSourceManager();
487 llvm::Optional<HoverInfo> HI;
488 SourceLocation SourceLocationBeg = SM.getMacroArgExpandedLocation(
489 getBeginningOfIdentifier(Pos, SM, AST.getLangOpts()));
490
491 if (auto Deduced = getDeducedType(AST.getASTContext(), SourceLocationBeg)) {
492 HI = getHoverContents(*Deduced, AST.getASTContext(), Index);
493 } else if (auto M = locateMacroAt(SourceLocationBeg, AST.getPreprocessor())) {
494 HI = getHoverContents(*M, AST);
495 } else {
496 auto Offset = positionToOffset(SM.getBufferData(SM.getMainFileID()), Pos);
497 if (!Offset) {
498 llvm::consumeError(Offset.takeError());
499 return llvm::None;
500 }
501 SelectionTree Selection(AST.getASTContext(), AST.getTokens(), *Offset);
502 std::vector<const Decl *> Result;
503 if (const SelectionTree::Node *N = Selection.commonAncestor()) {
504 auto Decls = explicitReferenceTargets(N->ASTNode, DeclRelation::Alias);
505 if (!Decls.empty()) {
506 HI = getHoverContents(Decls.front(), Index);
507 // Look for a close enclosing expression to show the value of.
508 if (!HI->Value)
509 HI->Value = printExprValue(N, AST.getASTContext());
510 } else if (const Expr *E = N->ASTNode.get<Expr>()) {
511 HI = getHoverContents(E, AST);
512 }
513 // FIXME: support hovers for other nodes?
514 // - built-in types
515 }
516 }
517
518 if (!HI)
519 return llvm::None;
520
521 auto Replacements = format::reformat(
522 Style, HI->Definition, tooling::Range(0, HI->Definition.size()));
523 if (auto Formatted =
524 tooling::applyAllReplacements(HI->Definition, Replacements))
525 HI->Definition = *Formatted;
526
527 HI->SymRange = getTokenRange(AST.getSourceManager(), AST.getLangOpts(),
528 SourceLocationBeg);
529 return HI;
530 }
531
532 markup::Document HoverInfo::present() const {
533 markup::Document Output;
534 // Header contains a text of the form:
535 // variable `var`
536 //
537 // class `X`
538 //
539 // function `foo`
540 //
541 // expression
542 //
543 // Note that we are making use of a level-3 heading because VSCode renders
544 // level 1 and 2 headers in a huge font, see
545 // https://github.com/microsoft/vscode/issues/88417 for details.
546 markup::Paragraph &Header = Output.addHeading(3);
547 if (Kind != index::SymbolKind::Unknown)
548 Header.appendText(index::getSymbolKindString(Kind));
549 assert(!Name.empty() && "hover triggered on a nameless symbol");
550 Header.appendCode(Name);
551
552 // Put a linebreak after header to increase readability.
553 Output.addRuler();
554 // Print Types on their own lines to reduce chances of getting line-wrapped by
555 // editor, as they might be long.
556 if (ReturnType) {
557 // For functions we display signature in a list form, e.g.:
558 // → `x`
559 // Parameters:
560 // - `bool param1`
561 // - `int param2 = 5`
562 Output.addParagraph().appendText("→").appendCode(*ReturnType);
563 if (Parameters && !Parameters->empty()) {
564 Output.addParagraph().appendText("Parameters:");
565 markup::BulletList &L = Output.addBulletList();
566 for (const auto &Param : *Parameters) {
567 std::string Buffer;
568 llvm::raw_string_ostream OS(Buffer);
569 OS << Param;
570 L.addItem().addParagraph().appendCode(std::move(OS.str()));
571 }
572 }
573 } else if (Type) {
574 Output.addParagraph().appendText("Type: ").appendCode(*Type);
575 }
576
577 if (Value) {
578 markup::Paragraph &P = Output.addParagraph();
579 P.appendText("Value =");
580 P.appendCode(*Value);
581 }
582
583 if (!Documentation.empty())
584 Output.addParagraph().appendText(Documentation);
585
586 if (!Definition.empty()) {
587 Output.addRuler();
588 std::string ScopeComment;
589 // Drop trailing "::".
590 if (!LocalScope.empty()) {
591 // Container name, e.g. class, method, function.
592 // We might want to propogate some info about container type to print
593 // function foo, class X, method X::bar, etc.
594 ScopeComment =
595 "// In " + llvm::StringRef(LocalScope).rtrim(':').str() + '\n';
596 } else if (NamespaceScope && !NamespaceScope->empty()) {
597 ScopeComment = "// In namespace " +
598 llvm::StringRef(*NamespaceScope).rtrim(':').str() + '\n';
599 }
600 // Note that we don't print anything for global namespace, to not annoy
601 // non-c++ projects or projects that are not making use of namespaces.
602 Output.addCodeBlock(ScopeComment + Definition);
603 }
604 return Output;
605 }
606
607 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
608 const HoverInfo::Param &P) {
609 std::vector<llvm::StringRef> Output;
610 if (P.Type)
611 Output.push_back(*P.Type);
612 if (P.Name)
613 Output.push_back(*P.Name);
614 OS << llvm::join(Output, " ");
615 if (P.Default)
616 OS << " = " << *P.Default;
617 return OS;
618 }
619
620 } // namespace clangd
621 } // namespace clang
FormattedString.h
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:208
Decl
const FunctionDecl * Decl
Definition: AvoidBindCheck.cpp:93
AST.h
clang::clangd::printQualifiedName
std::string printQualifiedName(const NamedDecl &ND)
Returns the qualified name of ND.
Definition: AST.cpp:169
clang::clangd::markup::Paragraph::appendCode
Paragraph & appendCode(std::string Code)
Append inline code, this translates to the ` block in markdown.
clang::clangd::getDeducedType
llvm::Optional< QualType > getDeducedType(ASTContext &ASTCtx, SourceLocation Loc)
Retrieves the deduced type at a given location (auto, decltype).
Definition: AST.cpp:418
clang::clangd::ParsedAST::getLangOpts
const LangOptions & getLangOpts() const
Definition: ParsedAST.h:80
clang::clangd::getSymbolID
llvm::Optional< SymbolID > getSymbolID(const Decl *D)
Gets the symbol ID for a declaration, if possible.
Definition: AST.cpp:286
clang::clangd::HoverInfo::Kind
index::SymbolKind Kind
Definition: Hover.h:57
clang::clangd::ParsedAST::getPreprocessor
Preprocessor & getPreprocessor()
Definition: ParsedAST.cpp:430
clang::clangd::SelectionTree::Node
Definition: Selection.h:95
clang::clangd::SymbolIndex
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
Definition: Index.h:85
clang::clangd::HoverInfo::Param::Name
llvm::Optional< std::string > Name
None for unnamed parameters.
Definition: Hover.h:35
SourceCode.h
Hover.h
clang::clangd::getBeginningOfIdentifier
SourceLocation getBeginningOfIdentifier(const Position &Pos, const SourceManager &SM, const LangOptions &LangOpts)
Get the beginning SourceLocation at a specified Pos in the main file.
Definition: SourceCode.cpp:277
clang::clangd::Position
Definition: Protocol.h:127
clang::clangd::HoverInfo::Type
llvm::Optional< std::string > Type
Pretty-printed variable type.
Definition: Hover.h:64
clang::clangd::TextDocumentSyncKind::None
Documents should not be synced at all.
clang::clangd::HoverInfo::Parameters
llvm::Optional< std::vector< Param > > Parameters
Set for functions, lambdas and macros with parameters.
Definition: Hover.h:68
clang::clangd::markup::BulletList::addItem
class Document & addItem()
clang::clangd::elog
void elog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:56
clang::clangd::DeclRelation::Alias
This declaration is an alias that was referred to.
clang::clangd::ParsedAST::getTokens
const syntax::TokenBuffer & getTokens() const
Tokens recorded while parsing the main file.
Definition: ParsedAST.h:102
clang::clangd::printType
std::string printType(const QualType QT, const DeclContext &CurContext)
Returns a QualType as string.
Definition: AST.cpp:305
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:424
clang::clangd::HoverInfo::Param
Represents parameters of a function, a template or a macro.
Definition: Hover.h:30
clang::clangd::HoverInfo::Param::Type
llvm::Optional< std::string > Type
The pretty-printed parameter type, e.g.
Definition: Hover.h:33
clang::clangd::Unknown
Definition: FuzzyMatch.h:56
Ctx
Context Ctx
Definition: TUScheduler.cpp:237
clang::clangd::getSymbolInfo
std::vector< SymbolDetails > getSymbolInfo(ParsedAST &AST, Position Pos)
Get info about symbols at Pos.
Definition: XRefs.cpp:519
clang::clangd::HoverInfo::Name
std::string Name
Name of the symbol, does not contain any "::".
Definition: Hover.h:55
clang::clangd::getHover
llvm::Optional< HoverInfo > getHover(ParsedAST &AST, Position Pos, format::FormatStyle Style, const SymbolIndex *Index)
Get the hover information when hovering at Pos.
Definition: Hover.cpp:483
clang::clangd::positionToOffset
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:155
clang::clangd::markup::Document::addCodeBlock
void addCodeBlock(std::string Code, std::string Language="cpp")
Adds a block of code.
clang::clangd::explicitReferenceTargets
llvm::SmallVector< const NamedDecl *, 1 > explicitReferenceTargets(DynTypedNode N, DeclRelationSet Mask)
Definition: FindTarget.cpp:519
CodeCompletionStrings.h
clang::clangd::HoverInfo::Param::Default
llvm::Optional< std::string > Default
None if no default is provided.
Definition: Hover.h:37
clang::clangd::declaredType
QualType declaredType(const TypeDecl *D)
Definition: AST.cpp:321
clang::clangd::markup::Paragraph::appendText
Paragraph & appendText(std::string Text)
Append plain text to the end of the string.
clang::clangd::RefKind::Definition
clang::clangd::getTokenRange
llvm::Optional< Range > getTokenRange(const SourceManager &SM, const LangOptions &LangOpts, SourceLocation TokLoc)
Returns the taken range at TokLoc.
Definition: SourceCode.cpp:227
Pos
Position Pos
Definition: SourceCode.cpp:772
clang::clangd::markup::Document
A format-agnostic representation for structured text.
Definition: FormattedString.h:82
clang::clangd::HoverInfo::LocalScope
std::string LocalScope
Remaining named contexts in symbol&#39;s qualified name, empty string means symbol is not local...
Definition: Hover.h:53
clang::clangd::CompletionItemKind::Constant
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:50
clang::clangd::ParsedAST
Stores and provides access to parsed AST.
Definition: ParsedAST.h:46
clang::clangd::ParsedAST::getSourceManager
SourceManager & getSourceManager()
Definition: ParsedAST.h:73
Logger.h
Offset
size_t Offset
Definition: CodeComplete.cpp:1022
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::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:202
clang::clangd::HoverInfo::ReturnType
llvm::Optional< std::string > ReturnType
Set for functions and lambadas.
Definition: Hover.h:66
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
SymbolCollector.h
ParsedAST.h
FindTarget.h
clang::clangd::markup::Document::addBulletList
BulletList & addBulletList()
clang::clangd::markup::Document::addRuler
void addRuler()
Inserts a horizontal separator to the document.
clang::tidy::bugprone::PP
static Preprocessor * PP
Definition: BadSignalToKillThreadCheck.cpp:28
clang::clangd::SelectionTree
Definition: Selection.h:65
Range
CharSourceRange Range
SourceRange for the file name.
Definition: IncludeOrderCheck.cpp:38
clang::clangd::HoverInfo::Value
llvm::Optional< std::string > Value
Contains the evaluated value of the symbol if available.
Definition: Hover.h:72
clang::clangd::markup::Paragraph
Represents parts of the markup that can contain strings, like inline code, code block or plain text...
Definition: FormattedString.h:43
clang::clangd::HoverInfo::present
markup::Document present() const
Produce a user-readable information.
Definition: Hover.cpp:532
clang::clangd::markup::Document::addHeading
Paragraph & addHeading(size_t Level)
Heading is a special type of paragraph that will be prepended with Level many &#39;#&#39;s in markdown...
E
const Expr * E
Definition: AvoidBindCheck.cpp:82
clang::clangd::markup::Document::addParagraph
Paragraph & addParagraph()
Adds a semantical block that will be separate from others.
clang::tidy::cppcoreguidelines::join
static std::string join(ArrayRef< SpecialMemberFunctionsCheck::SpecialMemberFunctionKind > SMFS, llvm::StringRef AndOr)
Definition: SpecialMemberFunctionsCheck.cpp:81
Base
std::unique_ptr< GlobalCompilationDatabase > Base
Definition: GlobalCompilationDatabaseTests.cpp:83
clang::clangd::operator<<
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
Definition: CodeComplete.cpp:1850
clang::clangd::HoverInfo::Documentation
std::string Documentation
Definition: Hover.h:58
clang::clangd::locateMacroAt
llvm::Optional< DefinedMacro > locateMacroAt(SourceLocation Loc, Preprocessor &PP)
Gets the macro at a specified Loc.
Definition: SourceCode.cpp:987
Selection.h
Index
const SymbolIndex * Index
Definition: Dexp.cpp:84
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::markup::BulletList
Represents a sequence of one or more documents.
Definition: FormattedString.h:69