xref: /freebsd/contrib/llvm-project/clang/lib/ExtractAPI/DeclarationFragments.cpp (revision 7351d001fc7f5a77a18a102e12a3ca2cbfd6988c)
1 //===- ExtractAPI/DeclarationFragments.cpp ----------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file implements Declaration Fragments related classes.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/ExtractAPI/DeclarationFragments.h"
15 #include "clang/AST/ASTFwd.h"
16 #include "clang/AST/Decl.h"
17 #include "clang/AST/DeclCXX.h"
18 #include "clang/AST/TemplateBase.h"
19 #include "clang/AST/TemplateName.h"
20 #include "clang/AST/Type.h"
21 #include "clang/AST/TypeLoc.h"
22 #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
23 #include "clang/Index/USRGeneration.h"
24 #include "llvm/ADT/StringSwitch.h"
25 #include "llvm/Support/ErrorHandling.h"
26 #include "llvm/Support/raw_ostream.h"
27 #include <optional>
28 
29 using namespace clang::extractapi;
30 using namespace llvm;
31 
32 namespace {
33 
findTypeLocForBlockDecl(const clang::TypeSourceInfo * TSInfo,clang::FunctionTypeLoc & Block,clang::FunctionProtoTypeLoc & BlockProto)34 void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo,
35                              clang::FunctionTypeLoc &Block,
36                              clang::FunctionProtoTypeLoc &BlockProto) {
37   if (!TSInfo)
38     return;
39 
40   clang::TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
41   while (true) {
42     // Look through qualified types
43     if (auto QualifiedTL = TL.getAs<clang::QualifiedTypeLoc>()) {
44       TL = QualifiedTL.getUnqualifiedLoc();
45       continue;
46     }
47 
48     if (auto AttrTL = TL.getAs<clang::AttributedTypeLoc>()) {
49       TL = AttrTL.getModifiedLoc();
50       continue;
51     }
52 
53     // Try to get the function prototype behind the block pointer type,
54     // then we're done.
55     if (auto BlockPtr = TL.getAs<clang::BlockPointerTypeLoc>()) {
56       TL = BlockPtr.getPointeeLoc().IgnoreParens();
57       Block = TL.getAs<clang::FunctionTypeLoc>();
58       BlockProto = TL.getAs<clang::FunctionProtoTypeLoc>();
59     }
60     break;
61   }
62 }
63 
64 } // namespace
65 
66 DeclarationFragments &
appendUnduplicatedTextCharacter(char Character)67 DeclarationFragments::appendUnduplicatedTextCharacter(char Character) {
68   if (!Fragments.empty()) {
69     Fragment &Last = Fragments.back();
70     if (Last.Kind == FragmentKind::Text) {
71       // Merge the extra space into the last fragment if the last fragment is
72       // also text.
73       if (Last.Spelling.back() != Character) { // avoid duplicates at end
74         Last.Spelling.push_back(Character);
75       }
76     } else {
77       append("", FragmentKind::Text);
78       Fragments.back().Spelling.push_back(Character);
79     }
80   }
81 
82   return *this;
83 }
84 
appendSpace()85 DeclarationFragments &DeclarationFragments::appendSpace() {
86   return appendUnduplicatedTextCharacter(' ');
87 }
88 
appendSemicolon()89 DeclarationFragments &DeclarationFragments::appendSemicolon() {
90   return appendUnduplicatedTextCharacter(';');
91 }
92 
removeTrailingSemicolon()93 DeclarationFragments &DeclarationFragments::removeTrailingSemicolon() {
94   if (Fragments.empty())
95     return *this;
96 
97   Fragment &Last = Fragments.back();
98   if (Last.Kind == FragmentKind::Text && Last.Spelling.back() == ';')
99     Last.Spelling.pop_back();
100 
101   return *this;
102 }
103 
getFragmentKindString(DeclarationFragments::FragmentKind Kind)104 StringRef DeclarationFragments::getFragmentKindString(
105     DeclarationFragments::FragmentKind Kind) {
106   switch (Kind) {
107   case DeclarationFragments::FragmentKind::None:
108     return "none";
109   case DeclarationFragments::FragmentKind::Keyword:
110     return "keyword";
111   case DeclarationFragments::FragmentKind::Attribute:
112     return "attribute";
113   case DeclarationFragments::FragmentKind::NumberLiteral:
114     return "number";
115   case DeclarationFragments::FragmentKind::StringLiteral:
116     return "string";
117   case DeclarationFragments::FragmentKind::Identifier:
118     return "identifier";
119   case DeclarationFragments::FragmentKind::TypeIdentifier:
120     return "typeIdentifier";
121   case DeclarationFragments::FragmentKind::GenericParameter:
122     return "genericParameter";
123   case DeclarationFragments::FragmentKind::ExternalParam:
124     return "externalParam";
125   case DeclarationFragments::FragmentKind::InternalParam:
126     return "internalParam";
127   case DeclarationFragments::FragmentKind::Text:
128     return "text";
129   }
130 
131   llvm_unreachable("Unhandled FragmentKind");
132 }
133 
134 DeclarationFragments::FragmentKind
parseFragmentKindFromString(StringRef S)135 DeclarationFragments::parseFragmentKindFromString(StringRef S) {
136   return llvm::StringSwitch<FragmentKind>(S)
137       .Case("keyword", DeclarationFragments::FragmentKind::Keyword)
138       .Case("attribute", DeclarationFragments::FragmentKind::Attribute)
139       .Case("number", DeclarationFragments::FragmentKind::NumberLiteral)
140       .Case("string", DeclarationFragments::FragmentKind::StringLiteral)
141       .Case("identifier", DeclarationFragments::FragmentKind::Identifier)
142       .Case("typeIdentifier",
143             DeclarationFragments::FragmentKind::TypeIdentifier)
144       .Case("genericParameter",
145             DeclarationFragments::FragmentKind::GenericParameter)
146       .Case("internalParam", DeclarationFragments::FragmentKind::InternalParam)
147       .Case("externalParam", DeclarationFragments::FragmentKind::ExternalParam)
148       .Case("text", DeclarationFragments::FragmentKind::Text)
149       .Default(DeclarationFragments::FragmentKind::None);
150 }
151 
getExceptionSpecificationString(ExceptionSpecificationType ExceptionSpec)152 DeclarationFragments DeclarationFragments::getExceptionSpecificationString(
153     ExceptionSpecificationType ExceptionSpec) {
154   DeclarationFragments Fragments;
155   switch (ExceptionSpec) {
156   case ExceptionSpecificationType::EST_None:
157     return Fragments;
158   case ExceptionSpecificationType::EST_DynamicNone:
159     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
160         .append("throw", DeclarationFragments::FragmentKind::Keyword)
161         .append("(", DeclarationFragments::FragmentKind::Text)
162         .append(")", DeclarationFragments::FragmentKind::Text);
163   case ExceptionSpecificationType::EST_Dynamic:
164     // FIXME: throw(int), get types of inner expression
165     return Fragments;
166   case ExceptionSpecificationType::EST_BasicNoexcept:
167     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
168         .append("noexcept", DeclarationFragments::FragmentKind::Keyword);
169   case ExceptionSpecificationType::EST_DependentNoexcept:
170     // FIXME: throw(conditional-expression), get expression
171     break;
172   case ExceptionSpecificationType::EST_NoexceptFalse:
173     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
174         .append("noexcept", DeclarationFragments::FragmentKind::Keyword)
175         .append("(", DeclarationFragments::FragmentKind::Text)
176         .append("false", DeclarationFragments::FragmentKind::Keyword)
177         .append(")", DeclarationFragments::FragmentKind::Text);
178   case ExceptionSpecificationType::EST_NoexceptTrue:
179     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
180         .append("noexcept", DeclarationFragments::FragmentKind::Keyword)
181         .append("(", DeclarationFragments::FragmentKind::Text)
182         .append("true", DeclarationFragments::FragmentKind::Keyword)
183         .append(")", DeclarationFragments::FragmentKind::Text);
184   default:
185     return Fragments;
186   }
187 
188   llvm_unreachable("Unhandled exception specification");
189 }
190 
191 DeclarationFragments
getStructureTypeFragment(const RecordDecl * Record)192 DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) {
193   DeclarationFragments Fragments;
194   if (Record->isStruct())
195     Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);
196   else if (Record->isUnion())
197     Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);
198   else
199     Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);
200 
201   return Fragments;
202 }
203 
204 // NNS stores C++ nested name specifiers, which are prefixes to qualified names.
205 // Build declaration fragments for NNS recursively so that we have the USR for
206 // every part in a qualified name, and also leaves the actual underlying type
207 // cleaner for its own fragment.
208 DeclarationFragments
getFragmentsForNNS(const NestedNameSpecifier * NNS,ASTContext & Context,DeclarationFragments & After)209 DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS,
210                                                 ASTContext &Context,
211                                                 DeclarationFragments &After) {
212   DeclarationFragments Fragments;
213   if (NNS->getPrefix())
214     Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After));
215 
216   switch (NNS->getKind()) {
217   case NestedNameSpecifier::Identifier:
218     Fragments.append(NNS->getAsIdentifier()->getName(),
219                      DeclarationFragments::FragmentKind::Identifier);
220     break;
221 
222   case NestedNameSpecifier::Namespace: {
223     const NamespaceDecl *NS = NNS->getAsNamespace();
224     if (NS->isAnonymousNamespace())
225       return Fragments;
226     SmallString<128> USR;
227     index::generateUSRForDecl(NS, USR);
228     Fragments.append(NS->getName(),
229                      DeclarationFragments::FragmentKind::Identifier, USR, NS);
230     break;
231   }
232 
233   case NestedNameSpecifier::NamespaceAlias: {
234     const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias();
235     SmallString<128> USR;
236     index::generateUSRForDecl(Alias, USR);
237     Fragments.append(Alias->getName(),
238                      DeclarationFragments::FragmentKind::Identifier, USR,
239                      Alias);
240     break;
241   }
242 
243   case NestedNameSpecifier::Global:
244     // The global specifier `::` at the beginning. No stored value.
245     break;
246 
247   case NestedNameSpecifier::Super:
248     // Microsoft's `__super` specifier.
249     Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword);
250     break;
251 
252   case NestedNameSpecifier::TypeSpec: {
253     const Type *T = NNS->getAsType();
254     // FIXME: Handle C++ template specialization type
255     Fragments.append(getFragmentsForType(T, Context, After));
256     break;
257   }
258   }
259 
260   // Add the separator text `::` for this segment.
261   return Fragments.append("::", DeclarationFragments::FragmentKind::Text);
262 }
263 
264 // Recursively build the declaration fragments for an underlying `Type` with
265 // qualifiers removed.
getFragmentsForType(const Type * T,ASTContext & Context,DeclarationFragments & After)266 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
267     const Type *T, ASTContext &Context, DeclarationFragments &After) {
268   assert(T && "invalid type");
269 
270   DeclarationFragments Fragments;
271 
272   if (const MacroQualifiedType *MQT = dyn_cast<MacroQualifiedType>(T)) {
273     Fragments.append(
274         getFragmentsForType(MQT->getUnderlyingType(), Context, After));
275     return Fragments;
276   }
277 
278   if (const AttributedType *AT = dyn_cast<AttributedType>(T)) {
279     // FIXME: Serialize Attributes correctly
280     Fragments.append(
281         getFragmentsForType(AT->getModifiedType(), Context, After));
282     return Fragments;
283   }
284 
285   // An ElaboratedType is a sugar for types that are referred to using an
286   // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a
287   // qualified name, e.g., `N::M::type`, or both.
288   if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) {
289     ElaboratedTypeKeyword Keyword = ET->getKeyword();
290     if (Keyword != ElaboratedTypeKeyword::None) {
291       Fragments
292           .append(ElaboratedType::getKeywordName(Keyword),
293                   DeclarationFragments::FragmentKind::Keyword)
294           .appendSpace();
295     }
296 
297     if (const NestedNameSpecifier *NNS = ET->getQualifier())
298       Fragments.append(getFragmentsForNNS(NNS, Context, After));
299 
300     // After handling the elaborated keyword or qualified name, build
301     // declaration fragments for the desugared underlying type.
302     return Fragments.append(getFragmentsForType(ET->desugar(), Context, After));
303   }
304 
305   // If the type is a typedefed type, get the underlying TypedefNameDecl for a
306   // direct reference to the typedef instead of the wrapped type.
307 
308   // 'id' type is a typedef for an ObjCObjectPointerType
309   //  we treat it as a typedef
310   if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) {
311     const TypedefNameDecl *Decl = TypedefTy->getDecl();
312     TypedefUnderlyingTypeResolver TypedefResolver(Context);
313     std::string USR = TypedefResolver.getUSRForType(QualType(T, 0));
314 
315     if (T->isObjCIdType()) {
316       return Fragments.append(Decl->getName(),
317                               DeclarationFragments::FragmentKind::Keyword);
318     }
319 
320     return Fragments.append(
321         Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier,
322         USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0)));
323   }
324 
325   // Declaration fragments of a pointer type is the declaration fragments of
326   // the pointee type followed by a `*`,
327   if (T->isPointerType() && !T->isFunctionPointerType()) {
328     QualType PointeeT = T->getPointeeType();
329     Fragments.append(getFragmentsForType(PointeeT, Context, After));
330     // If the pointee is itself a pointer, we do not want to insert a space
331     // before the `*` as the preceding character in the type name is a `*`.
332     if (!PointeeT->isAnyPointerType())
333       Fragments.appendSpace();
334     return Fragments.append("*", DeclarationFragments::FragmentKind::Text);
335   }
336 
337   // For Objective-C `id` and `Class` pointers
338   // we do not spell out the `*`.
339   if (T->isObjCObjectPointerType() &&
340       !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) {
341 
342     Fragments.append(getFragmentsForType(T->getPointeeType(), Context, After));
343 
344     // id<protocol> is an qualified id type
345     // id<protocol>* is not an qualified id type
346     if (!T->getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) {
347       Fragments.append(" *", DeclarationFragments::FragmentKind::Text);
348     }
349 
350     return Fragments;
351   }
352 
353   // Declaration fragments of a lvalue reference type is the declaration
354   // fragments of the underlying type followed by a `&`.
355   if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T))
356     return Fragments
357         .append(
358             getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After))
359         .append(" &", DeclarationFragments::FragmentKind::Text);
360 
361   // Declaration fragments of a rvalue reference type is the declaration
362   // fragments of the underlying type followed by a `&&`.
363   if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T))
364     return Fragments
365         .append(
366             getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After))
367         .append(" &&", DeclarationFragments::FragmentKind::Text);
368 
369   // Declaration fragments of an array-typed variable have two parts:
370   // 1. the element type of the array that appears before the variable name;
371   // 2. array brackets `[(0-9)?]` that appear after the variable name.
372   if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) {
373     // Build the "after" part first because the inner element type might also
374     // be an array-type. For example `int matrix[3][4]` which has a type of
375     // "(array 3 of (array 4 of ints))."
376     // Push the array size part first to make sure they are in the right order.
377     After.append("[", DeclarationFragments::FragmentKind::Text);
378 
379     switch (AT->getSizeModifier()) {
380     case ArraySizeModifier::Normal:
381       break;
382     case ArraySizeModifier::Static:
383       Fragments.append("static", DeclarationFragments::FragmentKind::Keyword);
384       break;
385     case ArraySizeModifier::Star:
386       Fragments.append("*", DeclarationFragments::FragmentKind::Text);
387       break;
388     }
389 
390     if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
391       // FIXME: right now this would evaluate any expressions/macros written in
392       // the original source to concrete values. For example
393       // `int nums[MAX]` -> `int nums[100]`
394       // `char *str[5 + 1]` -> `char *str[6]`
395       SmallString<128> Size;
396       CAT->getSize().toStringUnsigned(Size);
397       After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral);
398     }
399 
400     After.append("]", DeclarationFragments::FragmentKind::Text);
401 
402     return Fragments.append(
403         getFragmentsForType(AT->getElementType(), Context, After));
404   }
405 
406   if (const TemplateSpecializationType *TemplSpecTy =
407           dyn_cast<TemplateSpecializationType>(T)) {
408     const auto TemplName = TemplSpecTy->getTemplateName();
409     std::string Str;
410     raw_string_ostream Stream(Str);
411     TemplName.print(Stream, Context.getPrintingPolicy(),
412                     TemplateName::Qualified::AsWritten);
413     SmallString<64> USR("");
414     if (const auto *TemplDecl = TemplName.getAsTemplateDecl())
415       index::generateUSRForDecl(TemplDecl, USR);
416 
417     return Fragments
418         .append(Str, DeclarationFragments::FragmentKind::TypeIdentifier, USR)
419         .append("<", DeclarationFragments::FragmentKind::Text)
420         .append(getFragmentsForTemplateArguments(
421             TemplSpecTy->template_arguments(), Context, std::nullopt))
422         .append(">", DeclarationFragments::FragmentKind::Text);
423   }
424 
425   // Everything we care about has been handled now, reduce to the canonical
426   // unqualified base type.
427   QualType Base = T->getCanonicalTypeUnqualified();
428 
429   // If the base type is a TagType (struct/interface/union/class/enum), let's
430   // get the underlying Decl for better names and USRs.
431   if (const TagType *TagTy = dyn_cast<TagType>(Base)) {
432     const TagDecl *Decl = TagTy->getDecl();
433     // Anonymous decl, skip this fragment.
434     if (Decl->getName().empty())
435       return Fragments.append("{ ... }",
436                               DeclarationFragments::FragmentKind::Text);
437     SmallString<128> TagUSR;
438     clang::index::generateUSRForDecl(Decl, TagUSR);
439     return Fragments.append(Decl->getName(),
440                             DeclarationFragments::FragmentKind::TypeIdentifier,
441                             TagUSR, Decl);
442   }
443 
444   // If the base type is an ObjCInterfaceType, use the underlying
445   // ObjCInterfaceDecl for the true USR.
446   if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) {
447     const auto *Decl = ObjCIT->getDecl();
448     SmallString<128> USR;
449     index::generateUSRForDecl(Decl, USR);
450     return Fragments.append(Decl->getName(),
451                             DeclarationFragments::FragmentKind::TypeIdentifier,
452                             USR, Decl);
453   }
454 
455   // Default fragment builder for other kinds of types (BuiltinType etc.)
456   SmallString<128> USR;
457   clang::index::generateUSRForType(Base, Context, USR);
458   Fragments.append(Base.getAsString(),
459                    DeclarationFragments::FragmentKind::TypeIdentifier, USR);
460 
461   return Fragments;
462 }
463 
464 DeclarationFragments
getFragmentsForQualifiers(const Qualifiers Quals)465 DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) {
466   DeclarationFragments Fragments;
467   if (Quals.hasConst())
468     Fragments.append("const", DeclarationFragments::FragmentKind::Keyword);
469   if (Quals.hasVolatile())
470     Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword);
471   if (Quals.hasRestrict())
472     Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword);
473 
474   return Fragments;
475 }
476 
getFragmentsForType(const QualType QT,ASTContext & Context,DeclarationFragments & After)477 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
478     const QualType QT, ASTContext &Context, DeclarationFragments &After) {
479   assert(!QT.isNull() && "invalid type");
480 
481   if (const ParenType *PT = dyn_cast<ParenType>(QT)) {
482     After.append(")", DeclarationFragments::FragmentKind::Text);
483     return getFragmentsForType(PT->getInnerType(), Context, After)
484         .append("(", DeclarationFragments::FragmentKind::Text);
485   }
486 
487   const SplitQualType SQT = QT.split();
488   DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals),
489                        TypeFragments =
490                            getFragmentsForType(SQT.Ty, Context, After);
491   if (QT.getAsString() == "_Bool")
492     TypeFragments.replace("bool", 0);
493 
494   if (QualsFragments.getFragments().empty())
495     return TypeFragments;
496 
497   // Use east qualifier for pointer types
498   // For example:
499   // ```
500   // int *   const
501   // ^----   ^----
502   //  type    qualifier
503   // ^-----------------
504   //  const pointer to int
505   // ```
506   // should not be reconstructed as
507   // ```
508   // const       int       *
509   // ^----       ^--
510   //  qualifier   type
511   // ^----------------     ^
512   //  pointer to const int
513   // ```
514   if (SQT.Ty->isAnyPointerType())
515     return TypeFragments.appendSpace().append(std::move(QualsFragments));
516 
517   return QualsFragments.appendSpace().append(std::move(TypeFragments));
518 }
519 
getFragmentsForNamespace(const NamespaceDecl * Decl)520 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace(
521     const NamespaceDecl *Decl) {
522   DeclarationFragments Fragments;
523   Fragments.append("namespace", DeclarationFragments::FragmentKind::Keyword);
524   if (!Decl->isAnonymousNamespace())
525     Fragments.appendSpace().append(
526         Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
527   return Fragments.appendSemicolon();
528 }
529 
530 DeclarationFragments
getFragmentsForVar(const VarDecl * Var)531 DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
532   DeclarationFragments Fragments;
533   if (Var->isConstexpr())
534     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
535         .appendSpace();
536 
537   StorageClass SC = Var->getStorageClass();
538   if (SC != SC_None)
539     Fragments
540         .append(VarDecl::getStorageClassSpecifierString(SC),
541                 DeclarationFragments::FragmentKind::Keyword)
542         .appendSpace();
543 
544   // Capture potential fragments that needs to be placed after the variable name
545   // ```
546   // int nums[5];
547   // char (*ptr_to_array)[6];
548   // ```
549   DeclarationFragments After;
550   FunctionTypeLoc BlockLoc;
551   FunctionProtoTypeLoc BlockProtoLoc;
552   findTypeLocForBlockDecl(Var->getTypeSourceInfo(), BlockLoc, BlockProtoLoc);
553 
554   if (!BlockLoc) {
555     QualType T = Var->getTypeSourceInfo()
556                      ? Var->getTypeSourceInfo()->getType()
557                      : Var->getASTContext().getUnqualifiedObjCPointerType(
558                            Var->getType());
559 
560     Fragments.append(getFragmentsForType(T, Var->getASTContext(), After))
561         .appendSpace();
562   } else {
563     Fragments.append(getFragmentsForBlock(Var, BlockLoc, BlockProtoLoc, After));
564   }
565 
566   return Fragments
567       .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
568       .append(std::move(After))
569       .appendSemicolon();
570 }
571 
572 DeclarationFragments
getFragmentsForVarTemplate(const VarDecl * Var)573 DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) {
574   DeclarationFragments Fragments;
575   if (Var->isConstexpr())
576     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
577         .appendSpace();
578   QualType T =
579       Var->getTypeSourceInfo()
580           ? Var->getTypeSourceInfo()->getType()
581           : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType());
582 
583   // Might be a member, so might be static.
584   if (Var->isStaticDataMember())
585     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
586         .appendSpace();
587 
588   DeclarationFragments After;
589   DeclarationFragments ArgumentFragment =
590       getFragmentsForType(T, Var->getASTContext(), After);
591   if (StringRef(ArgumentFragment.begin()->Spelling)
592           .starts_with("type-parameter")) {
593     std::string ProperArgName = T.getAsString();
594     ArgumentFragment.begin()->Spelling.swap(ProperArgName);
595   }
596   Fragments.append(std::move(ArgumentFragment))
597       .appendSpace()
598       .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
599       .appendSemicolon();
600   return Fragments;
601 }
602 
603 DeclarationFragments
getFragmentsForParam(const ParmVarDecl * Param)604 DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) {
605   DeclarationFragments Fragments, After;
606 
607   auto *TSInfo = Param->getTypeSourceInfo();
608 
609   QualType T = TSInfo ? TSInfo->getType()
610                       : Param->getASTContext().getUnqualifiedObjCPointerType(
611                             Param->getType());
612 
613   FunctionTypeLoc BlockLoc;
614   FunctionProtoTypeLoc BlockProtoLoc;
615   findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc);
616 
617   DeclarationFragments TypeFragments;
618   if (BlockLoc)
619     TypeFragments.append(
620         getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After));
621   else
622     TypeFragments.append(getFragmentsForType(T, Param->getASTContext(), After));
623 
624   if (StringRef(TypeFragments.begin()->Spelling)
625           .starts_with("type-parameter")) {
626     std::string ProperArgName = Param->getOriginalType().getAsString();
627     TypeFragments.begin()->Spelling.swap(ProperArgName);
628   }
629 
630   if (Param->isObjCMethodParameter()) {
631     Fragments.append("(", DeclarationFragments::FragmentKind::Text)
632         .append(std::move(TypeFragments))
633         .append(std::move(After))
634         .append(") ", DeclarationFragments::FragmentKind::Text)
635         .append(Param->getName(),
636                 DeclarationFragments::FragmentKind::InternalParam);
637   } else {
638     Fragments.append(std::move(TypeFragments));
639     // If the type is a type alias, append the space
640     // even if the underlying type is a pointer type.
641     if (T->isTypedefNameType() ||
642         (!T->isAnyPointerType() && !T->isBlockPointerType()))
643       Fragments.appendSpace();
644     Fragments
645         .append(Param->getName(),
646                 DeclarationFragments::FragmentKind::InternalParam)
647         .append(std::move(After));
648   }
649   return Fragments;
650 }
651 
getFragmentsForBlock(const NamedDecl * BlockDecl,FunctionTypeLoc & Block,FunctionProtoTypeLoc & BlockProto,DeclarationFragments & After)652 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForBlock(
653     const NamedDecl *BlockDecl, FunctionTypeLoc &Block,
654     FunctionProtoTypeLoc &BlockProto, DeclarationFragments &After) {
655   DeclarationFragments Fragments;
656 
657   DeclarationFragments RetTyAfter;
658   auto ReturnValueFragment = getFragmentsForType(
659       Block.getTypePtr()->getReturnType(), BlockDecl->getASTContext(), After);
660 
661   Fragments.append(std::move(ReturnValueFragment))
662       .append(std::move(RetTyAfter))
663       .appendSpace()
664       .append("(^", DeclarationFragments::FragmentKind::Text);
665 
666   After.append(")", DeclarationFragments::FragmentKind::Text);
667   unsigned NumParams = Block.getNumParams();
668 
669   if (!BlockProto || NumParams == 0) {
670     if (BlockProto && BlockProto.getTypePtr()->isVariadic())
671       After.append("(...)", DeclarationFragments::FragmentKind::Text);
672     else
673       After.append("()", DeclarationFragments::FragmentKind::Text);
674   } else {
675     After.append("(", DeclarationFragments::FragmentKind::Text);
676     for (unsigned I = 0; I != NumParams; ++I) {
677       if (I)
678         After.append(", ", DeclarationFragments::FragmentKind::Text);
679       After.append(getFragmentsForParam(Block.getParam(I)));
680       if (I == NumParams - 1 && BlockProto.getTypePtr()->isVariadic())
681         After.append(", ...", DeclarationFragments::FragmentKind::Text);
682     }
683     After.append(")", DeclarationFragments::FragmentKind::Text);
684   }
685 
686   return Fragments;
687 }
688 
689 DeclarationFragments
getFragmentsForFunction(const FunctionDecl * Func)690 DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
691   DeclarationFragments Fragments;
692   switch (Func->getStorageClass()) {
693   case SC_None:
694   case SC_PrivateExtern:
695     break;
696   case SC_Extern:
697     Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword)
698         .appendSpace();
699     break;
700   case SC_Static:
701     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
702         .appendSpace();
703     break;
704   case SC_Auto:
705   case SC_Register:
706     llvm_unreachable("invalid for functions");
707   }
708   if (Func->isConsteval()) // if consteval, it is also constexpr
709     Fragments.append("consteval", DeclarationFragments::FragmentKind::Keyword)
710         .appendSpace();
711   else if (Func->isConstexpr())
712     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
713         .appendSpace();
714 
715   // FIXME: Is `after` actually needed here?
716   DeclarationFragments After;
717   QualType ReturnType = Func->getReturnType();
718   auto ReturnValueFragment =
719       getFragmentsForType(ReturnType, Func->getASTContext(), After);
720   if (StringRef(ReturnValueFragment.begin()->Spelling)
721           .starts_with("type-parameter")) {
722     std::string ProperArgName = ReturnType.getAsString();
723     ReturnValueFragment.begin()->Spelling.swap(ProperArgName);
724   }
725 
726   Fragments.append(std::move(ReturnValueFragment));
727   if (!ReturnType->isAnyPointerType())
728     Fragments.appendSpace();
729   Fragments.append(Func->getNameAsString(),
730                    DeclarationFragments::FragmentKind::Identifier);
731 
732   if (Func->getTemplateSpecializationInfo()) {
733     Fragments.append("<", DeclarationFragments::FragmentKind::Text);
734 
735     for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) {
736       if (i)
737         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
738       Fragments.append(
739           getFragmentsForType(Func->getParamDecl(i)->getType(),
740                               Func->getParamDecl(i)->getASTContext(), After));
741     }
742     Fragments.append(">", DeclarationFragments::FragmentKind::Text);
743   }
744   Fragments.append(std::move(After));
745 
746   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
747   unsigned NumParams = Func->getNumParams();
748   for (unsigned i = 0; i != NumParams; ++i) {
749     if (i)
750       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
751     Fragments.append(getFragmentsForParam(Func->getParamDecl(i)));
752   }
753 
754   if (Func->isVariadic()) {
755     if (NumParams > 0)
756       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
757     Fragments.append("...", DeclarationFragments::FragmentKind::Text);
758   }
759   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
760 
761   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
762       Func->getExceptionSpecType()));
763 
764   return Fragments.appendSemicolon();
765 }
766 
getFragmentsForEnumConstant(const EnumConstantDecl * EnumConstDecl)767 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant(
768     const EnumConstantDecl *EnumConstDecl) {
769   DeclarationFragments Fragments;
770   return Fragments.append(EnumConstDecl->getName(),
771                           DeclarationFragments::FragmentKind::Identifier);
772 }
773 
774 DeclarationFragments
getFragmentsForEnum(const EnumDecl * EnumDecl)775 DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {
776   if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl())
777     return getFragmentsForTypedef(TypedefNameDecl);
778 
779   DeclarationFragments Fragments, After;
780   Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword);
781 
782   if (!EnumDecl->getName().empty())
783     Fragments.appendSpace().append(
784         EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier);
785 
786   QualType IntegerType = EnumDecl->getIntegerType();
787   if (!IntegerType.isNull())
788     Fragments.appendSpace()
789         .append(": ", DeclarationFragments::FragmentKind::Text)
790         .append(
791             getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))
792         .append(std::move(After));
793 
794   if (EnumDecl->getName().empty())
795     Fragments.appendSpace().append("{ ... }",
796                                    DeclarationFragments::FragmentKind::Text);
797 
798   return Fragments.appendSemicolon();
799 }
800 
801 DeclarationFragments
getFragmentsForField(const FieldDecl * Field)802 DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) {
803   DeclarationFragments After;
804   DeclarationFragments Fragments;
805   if (Field->isMutable())
806     Fragments.append("mutable", DeclarationFragments::FragmentKind::Keyword)
807         .appendSpace();
808   return Fragments
809       .append(
810           getFragmentsForType(Field->getType(), Field->getASTContext(), After))
811       .appendSpace()
812       .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)
813       .append(std::move(After))
814       .appendSemicolon();
815 }
816 
getFragmentsForRecordDecl(const RecordDecl * Record)817 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
818     const RecordDecl *Record) {
819   if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
820     return getFragmentsForTypedef(TypedefNameDecl);
821 
822   DeclarationFragments Fragments;
823   if (Record->isUnion())
824     Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);
825   else
826     Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);
827 
828   Fragments.appendSpace();
829   if (!Record->getName().empty())
830     Fragments.append(Record->getName(),
831                      DeclarationFragments::FragmentKind::Identifier);
832   else
833     Fragments.append("{ ... }", DeclarationFragments::FragmentKind::Text);
834 
835   return Fragments.appendSemicolon();
836 }
837 
getFragmentsForCXXClass(const CXXRecordDecl * Record)838 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
839     const CXXRecordDecl *Record) {
840   if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
841     return getFragmentsForTypedef(TypedefNameDecl);
842 
843   DeclarationFragments Fragments;
844   Fragments.append(DeclarationFragments::getStructureTypeFragment(Record));
845 
846   if (!Record->getName().empty())
847     Fragments.appendSpace().append(
848         Record->getName(), DeclarationFragments::FragmentKind::Identifier);
849 
850   return Fragments.appendSemicolon();
851 }
852 
853 DeclarationFragments
getFragmentsForSpecialCXXMethod(const CXXMethodDecl * Method)854 DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(
855     const CXXMethodDecl *Method) {
856   DeclarationFragments Fragments;
857   std::string Name;
858   if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(Method)) {
859     Name = Method->getNameAsString();
860     if (Constructor->isExplicit())
861       Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
862           .appendSpace();
863   } else if (isa<CXXDestructorDecl>(Method))
864     Name = Method->getNameAsString();
865 
866   DeclarationFragments After;
867   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier)
868       .append(std::move(After));
869   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
870   for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
871     if (i)
872       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
873     Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
874   }
875   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
876 
877   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
878       Method->getExceptionSpecType()));
879 
880   return Fragments.appendSemicolon();
881 }
882 
getFragmentsForCXXMethod(const CXXMethodDecl * Method)883 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
884     const CXXMethodDecl *Method) {
885   DeclarationFragments Fragments;
886   StringRef Name = Method->getName();
887   if (Method->isStatic())
888     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
889         .appendSpace();
890   if (Method->isConstexpr())
891     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
892         .appendSpace();
893   if (Method->isVolatile())
894     Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword)
895         .appendSpace();
896   if (Method->isVirtual())
897     Fragments.append("virtual", DeclarationFragments::FragmentKind::Keyword)
898         .appendSpace();
899 
900   // Build return type
901   DeclarationFragments After;
902   Fragments
903       .append(getFragmentsForType(Method->getReturnType(),
904                                   Method->getASTContext(), After))
905       .appendSpace()
906       .append(Name, DeclarationFragments::FragmentKind::Identifier)
907       .append(std::move(After));
908   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
909   for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
910     if (i)
911       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
912     Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
913   }
914   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
915 
916   if (Method->isConst())
917     Fragments.appendSpace().append("const",
918                                    DeclarationFragments::FragmentKind::Keyword);
919 
920   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
921       Method->getExceptionSpecType()));
922 
923   return Fragments.appendSemicolon();
924 }
925 
926 DeclarationFragments
getFragmentsForConversionFunction(const CXXConversionDecl * ConversionFunction)927 DeclarationFragmentsBuilder::getFragmentsForConversionFunction(
928     const CXXConversionDecl *ConversionFunction) {
929   DeclarationFragments Fragments;
930 
931   if (ConversionFunction->isExplicit())
932     Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
933         .appendSpace();
934 
935   Fragments.append("operator", DeclarationFragments::FragmentKind::Keyword)
936       .appendSpace();
937 
938   Fragments
939       .append(ConversionFunction->getConversionType().getAsString(),
940               DeclarationFragments::FragmentKind::TypeIdentifier)
941       .append("(", DeclarationFragments::FragmentKind::Text);
942   for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end;
943        ++i) {
944     if (i)
945       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
946     Fragments.append(getFragmentsForParam(ConversionFunction->getParamDecl(i)));
947   }
948   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
949 
950   if (ConversionFunction->isConst())
951     Fragments.appendSpace().append("const",
952                                    DeclarationFragments::FragmentKind::Keyword);
953 
954   return Fragments.appendSemicolon();
955 }
956 
957 DeclarationFragments
getFragmentsForOverloadedOperator(const CXXMethodDecl * Method)958 DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(
959     const CXXMethodDecl *Method) {
960   DeclarationFragments Fragments;
961 
962   // Build return type
963   DeclarationFragments After;
964   Fragments
965       .append(getFragmentsForType(Method->getReturnType(),
966                                   Method->getASTContext(), After))
967       .appendSpace()
968       .append(Method->getNameAsString(),
969               DeclarationFragments::FragmentKind::Identifier)
970       .append(std::move(After));
971   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
972   for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
973     if (i)
974       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
975     Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
976   }
977   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
978 
979   if (Method->isConst())
980     Fragments.appendSpace().append("const",
981                                    DeclarationFragments::FragmentKind::Keyword);
982 
983   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
984       Method->getExceptionSpecType()));
985 
986   return Fragments.appendSemicolon();
987 }
988 
989 // Get fragments for template parameters, e.g. T in tempalte<typename T> ...
990 DeclarationFragments
getFragmentsForTemplateParameters(ArrayRef<NamedDecl * > ParameterArray)991 DeclarationFragmentsBuilder::getFragmentsForTemplateParameters(
992     ArrayRef<NamedDecl *> ParameterArray) {
993   DeclarationFragments Fragments;
994   for (unsigned i = 0, end = ParameterArray.size(); i != end; ++i) {
995     if (i)
996       Fragments.append(",", DeclarationFragments::FragmentKind::Text)
997           .appendSpace();
998 
999     if (const auto *TemplateParam =
1000             dyn_cast<TemplateTypeParmDecl>(ParameterArray[i])) {
1001       if (TemplateParam->hasTypeConstraint())
1002         Fragments.append(TemplateParam->getTypeConstraint()
1003                              ->getNamedConcept()
1004                              ->getName()
1005                              .str(),
1006                          DeclarationFragments::FragmentKind::TypeIdentifier);
1007       else if (TemplateParam->wasDeclaredWithTypename())
1008         Fragments.append("typename",
1009                          DeclarationFragments::FragmentKind::Keyword);
1010       else
1011         Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);
1012 
1013       if (TemplateParam->isParameterPack())
1014         Fragments.append("...", DeclarationFragments::FragmentKind::Text);
1015 
1016       if (!TemplateParam->getName().empty())
1017         Fragments.appendSpace().append(
1018             TemplateParam->getName(),
1019             DeclarationFragments::FragmentKind::GenericParameter);
1020 
1021       if (TemplateParam->hasDefaultArgument()) {
1022         const auto Default = TemplateParam->getDefaultArgument();
1023         Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)
1024             .append(getFragmentsForTemplateArguments(
1025                 {Default.getArgument()}, TemplateParam->getASTContext(),
1026                 {Default}));
1027       }
1028     } else if (const auto *NTP =
1029                    dyn_cast<NonTypeTemplateParmDecl>(ParameterArray[i])) {
1030       DeclarationFragments After;
1031       const auto TyFragments =
1032           getFragmentsForType(NTP->getType(), NTP->getASTContext(), After);
1033       Fragments.append(std::move(TyFragments)).append(std::move(After));
1034 
1035       if (NTP->isParameterPack())
1036         Fragments.append("...", DeclarationFragments::FragmentKind::Text);
1037 
1038       if (!NTP->getName().empty())
1039         Fragments.appendSpace().append(
1040             NTP->getName(),
1041             DeclarationFragments::FragmentKind::GenericParameter);
1042 
1043       if (NTP->hasDefaultArgument()) {
1044         SmallString<8> ExprStr;
1045         raw_svector_ostream Output(ExprStr);
1046         NTP->getDefaultArgument().getArgument().print(
1047             NTP->getASTContext().getPrintingPolicy(), Output,
1048             /*IncludeType=*/false);
1049         Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)
1050             .append(ExprStr, DeclarationFragments::FragmentKind::Text);
1051       }
1052     } else if (const auto *TTP =
1053                    dyn_cast<TemplateTemplateParmDecl>(ParameterArray[i])) {
1054       Fragments.append("template", DeclarationFragments::FragmentKind::Keyword)
1055           .appendSpace()
1056           .append("<", DeclarationFragments::FragmentKind::Text)
1057           .append(getFragmentsForTemplateParameters(
1058               TTP->getTemplateParameters()->asArray()))
1059           .append(">", DeclarationFragments::FragmentKind::Text)
1060           .appendSpace()
1061           .append(TTP->wasDeclaredWithTypename() ? "typename" : "class",
1062                   DeclarationFragments::FragmentKind::Keyword);
1063 
1064       if (TTP->isParameterPack())
1065         Fragments.append("...", DeclarationFragments::FragmentKind::Text);
1066 
1067       if (!TTP->getName().empty())
1068         Fragments.appendSpace().append(
1069             TTP->getName(),
1070             DeclarationFragments::FragmentKind::GenericParameter);
1071       if (TTP->hasDefaultArgument()) {
1072         const auto Default = TTP->getDefaultArgument();
1073         Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)
1074             .append(getFragmentsForTemplateArguments(
1075                 {Default.getArgument()}, TTP->getASTContext(), {Default}));
1076       }
1077     }
1078   }
1079   return Fragments;
1080 }
1081 
1082 // Get fragments for template arguments, e.g. int in template<typename T>
1083 // Foo<int>;
1084 //
1085 // Note: TemplateParameters is only necessary if the Decl is a
1086 // PartialSpecialization, where we need the parameters to deduce the name of the
1087 // generic arguments.
1088 DeclarationFragments
getFragmentsForTemplateArguments(const ArrayRef<TemplateArgument> TemplateArguments,ASTContext & Context,const std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs)1089 DeclarationFragmentsBuilder::getFragmentsForTemplateArguments(
1090     const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context,
1091     const std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs) {
1092   DeclarationFragments Fragments;
1093   for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) {
1094     if (i)
1095       Fragments.append(",", DeclarationFragments::FragmentKind::Text)
1096           .appendSpace();
1097 
1098     const auto &CTA = TemplateArguments[i];
1099     switch (CTA.getKind()) {
1100     case TemplateArgument::Type: {
1101       DeclarationFragments After;
1102       DeclarationFragments ArgumentFragment =
1103           getFragmentsForType(CTA.getAsType(), Context, After);
1104 
1105       if (StringRef(ArgumentFragment.begin()->Spelling)
1106               .starts_with("type-parameter")) {
1107         if (TemplateArgumentLocs.has_value() &&
1108             TemplateArgumentLocs->size() > i) {
1109           std::string ProperArgName = TemplateArgumentLocs.value()[i]
1110                                           .getTypeSourceInfo()
1111                                           ->getType()
1112                                           .getAsString();
1113           ArgumentFragment.begin()->Spelling.swap(ProperArgName);
1114         } else {
1115           auto &Spelling = ArgumentFragment.begin()->Spelling;
1116           Spelling.clear();
1117           raw_string_ostream OutStream(Spelling);
1118           CTA.print(Context.getPrintingPolicy(), OutStream, false);
1119         }
1120       }
1121 
1122       Fragments.append(std::move(ArgumentFragment));
1123       break;
1124     }
1125     case TemplateArgument::Declaration: {
1126       const auto *VD = CTA.getAsDecl();
1127       SmallString<128> USR;
1128       index::generateUSRForDecl(VD, USR);
1129       Fragments.append(VD->getNameAsString(),
1130                        DeclarationFragments::FragmentKind::Identifier, USR);
1131       break;
1132     }
1133     case TemplateArgument::NullPtr:
1134       Fragments.append("nullptr", DeclarationFragments::FragmentKind::Keyword);
1135       break;
1136 
1137     case TemplateArgument::Integral: {
1138       SmallString<4> Str;
1139       CTA.getAsIntegral().toString(Str);
1140       Fragments.append(Str, DeclarationFragments::FragmentKind::Text);
1141       break;
1142     }
1143 
1144     case TemplateArgument::StructuralValue: {
1145       const auto SVTy = CTA.getStructuralValueType();
1146       Fragments.append(CTA.getAsStructuralValue().getAsString(Context, SVTy),
1147                        DeclarationFragments::FragmentKind::Text);
1148       break;
1149     }
1150 
1151     case TemplateArgument::TemplateExpansion:
1152     case TemplateArgument::Template: {
1153       std::string Str;
1154       raw_string_ostream Stream(Str);
1155       CTA.getAsTemplate().print(Stream, Context.getPrintingPolicy());
1156       SmallString<64> USR("");
1157       if (const auto *TemplDecl =
1158               CTA.getAsTemplateOrTemplatePattern().getAsTemplateDecl())
1159         index::generateUSRForDecl(TemplDecl, USR);
1160       Fragments.append(Str, DeclarationFragments::FragmentKind::TypeIdentifier,
1161                        USR);
1162       if (CTA.getKind() == TemplateArgument::TemplateExpansion)
1163         Fragments.append("...", DeclarationFragments::FragmentKind::Text);
1164       break;
1165     }
1166 
1167     case TemplateArgument::Pack:
1168       Fragments.append("<", DeclarationFragments::FragmentKind::Text)
1169           .append(getFragmentsForTemplateArguments(CTA.pack_elements(), Context,
1170                                                    {}))
1171           .append(">", DeclarationFragments::FragmentKind::Text);
1172       break;
1173 
1174     case TemplateArgument::Expression: {
1175       SmallString<8> ExprStr;
1176       raw_svector_ostream Output(ExprStr);
1177       CTA.getAsExpr()->printPretty(Output, nullptr,
1178                                    Context.getPrintingPolicy());
1179       Fragments.append(ExprStr, DeclarationFragments::FragmentKind::Text);
1180       break;
1181     }
1182 
1183     case TemplateArgument::Null:
1184       break;
1185     }
1186   }
1187   return Fragments;
1188 }
1189 
getFragmentsForConcept(const ConceptDecl * Concept)1190 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept(
1191     const ConceptDecl *Concept) {
1192   DeclarationFragments Fragments;
1193   return Fragments
1194       .append("template", DeclarationFragments::FragmentKind::Keyword)
1195       .appendSpace()
1196       .append("<", DeclarationFragments::FragmentKind::Text)
1197       .append(getFragmentsForTemplateParameters(
1198           Concept->getTemplateParameters()->asArray()))
1199       .append("> ", DeclarationFragments::FragmentKind::Text)
1200       .appendSpace()
1201       .append("concept", DeclarationFragments::FragmentKind::Keyword)
1202       .appendSpace()
1203       .append(Concept->getName().str(),
1204               DeclarationFragments::FragmentKind::Identifier)
1205       .appendSemicolon();
1206 }
1207 
1208 DeclarationFragments
getFragmentsForRedeclarableTemplate(const RedeclarableTemplateDecl * RedeclarableTemplate)1209 DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
1210     const RedeclarableTemplateDecl *RedeclarableTemplate) {
1211   DeclarationFragments Fragments;
1212   Fragments.append("template", DeclarationFragments::FragmentKind::Keyword)
1213       .appendSpace()
1214       .append("<", DeclarationFragments::FragmentKind::Text)
1215       .append(getFragmentsForTemplateParameters(
1216           RedeclarableTemplate->getTemplateParameters()->asArray()))
1217       .append(">", DeclarationFragments::FragmentKind::Text)
1218       .appendSpace();
1219 
1220   if (isa<TypeAliasTemplateDecl>(RedeclarableTemplate))
1221     Fragments.appendSpace()
1222         .append("using", DeclarationFragments::FragmentKind::Keyword)
1223         .appendSpace()
1224         .append(RedeclarableTemplate->getName(),
1225                 DeclarationFragments::FragmentKind::Identifier);
1226   // the templated records will be resposbible for injecting their templates
1227   return Fragments.appendSpace();
1228 }
1229 
1230 DeclarationFragments
getFragmentsForClassTemplateSpecialization(const ClassTemplateSpecializationDecl * Decl)1231 DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization(
1232     const ClassTemplateSpecializationDecl *Decl) {
1233   DeclarationFragments Fragments;
1234   std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs = {};
1235   if (auto *TemplateArgs = Decl->getTemplateArgsAsWritten()) {
1236     TemplateArgumentLocs = TemplateArgs->arguments();
1237   }
1238   return Fragments
1239       .append("template", DeclarationFragments::FragmentKind::Keyword)
1240       .appendSpace()
1241       .append("<", DeclarationFragments::FragmentKind::Text)
1242       .append(">", DeclarationFragments::FragmentKind::Text)
1243       .appendSpace()
1244       .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(
1245           cast<CXXRecordDecl>(Decl)))
1246       .pop_back() // there is an extra semicolon now
1247       .append("<", DeclarationFragments::FragmentKind::Text)
1248       .append(getFragmentsForTemplateArguments(
1249           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1250           TemplateArgumentLocs))
1251       .append(">", DeclarationFragments::FragmentKind::Text)
1252       .appendSemicolon();
1253 }
1254 
1255 DeclarationFragments
getFragmentsForClassTemplatePartialSpecialization(const ClassTemplatePartialSpecializationDecl * Decl)1256 DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization(
1257     const ClassTemplatePartialSpecializationDecl *Decl) {
1258   DeclarationFragments Fragments;
1259   return Fragments
1260       .append("template", DeclarationFragments::FragmentKind::Keyword)
1261       .appendSpace()
1262       .append("<", DeclarationFragments::FragmentKind::Text)
1263       .append(getFragmentsForTemplateParameters(
1264           Decl->getTemplateParameters()->asArray()))
1265       .append(">", DeclarationFragments::FragmentKind::Text)
1266       .appendSpace()
1267       .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(
1268           cast<CXXRecordDecl>(Decl)))
1269       .pop_back() // there is an extra semicolon now
1270       .append("<", DeclarationFragments::FragmentKind::Text)
1271       .append(getFragmentsForTemplateArguments(
1272           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1273           Decl->getTemplateArgsAsWritten()->arguments()))
1274       .append(">", DeclarationFragments::FragmentKind::Text)
1275       .appendSemicolon();
1276 }
1277 
1278 DeclarationFragments
getFragmentsForVarTemplateSpecialization(const VarTemplateSpecializationDecl * Decl)1279 DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization(
1280     const VarTemplateSpecializationDecl *Decl) {
1281   DeclarationFragments Fragments;
1282   return Fragments
1283       .append("template", DeclarationFragments::FragmentKind::Keyword)
1284       .appendSpace()
1285       .append("<", DeclarationFragments::FragmentKind::Text)
1286       .append(">", DeclarationFragments::FragmentKind::Text)
1287       .appendSpace()
1288       .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))
1289       .pop_back() // there is an extra semicolon now
1290       .append("<", DeclarationFragments::FragmentKind::Text)
1291       .append(getFragmentsForTemplateArguments(
1292           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1293           Decl->getTemplateArgsAsWritten()->arguments()))
1294       .append(">", DeclarationFragments::FragmentKind::Text)
1295       .appendSemicolon();
1296 }
1297 
1298 DeclarationFragments
getFragmentsForVarTemplatePartialSpecialization(const VarTemplatePartialSpecializationDecl * Decl)1299 DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization(
1300     const VarTemplatePartialSpecializationDecl *Decl) {
1301   DeclarationFragments Fragments;
1302   return Fragments
1303       .append("template", DeclarationFragments::FragmentKind::Keyword)
1304       .appendSpace()
1305       .append("<", DeclarationFragments::FragmentKind::Text)
1306       // Partial specs may have new params.
1307       .append(getFragmentsForTemplateParameters(
1308           Decl->getTemplateParameters()->asArray()))
1309       .append(">", DeclarationFragments::FragmentKind::Text)
1310       .appendSpace()
1311       .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))
1312       .pop_back() // there is an extra semicolon now
1313       .append("<", DeclarationFragments::FragmentKind::Text)
1314       .append(getFragmentsForTemplateArguments(
1315           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1316           Decl->getTemplateArgsAsWritten()->arguments()))
1317       .append(">", DeclarationFragments::FragmentKind::Text)
1318       .appendSemicolon();
1319 }
1320 
1321 DeclarationFragments
getFragmentsForFunctionTemplate(const FunctionTemplateDecl * Decl)1322 DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(
1323     const FunctionTemplateDecl *Decl) {
1324   DeclarationFragments Fragments;
1325   return Fragments
1326       .append("template", DeclarationFragments::FragmentKind::Keyword)
1327       .appendSpace()
1328       .append("<", DeclarationFragments::FragmentKind::Text)
1329       // Partial specs may have new params.
1330       .append(getFragmentsForTemplateParameters(
1331           Decl->getTemplateParameters()->asArray()))
1332       .append(">", DeclarationFragments::FragmentKind::Text)
1333       .appendSpace()
1334       .append(DeclarationFragmentsBuilder::getFragmentsForFunction(
1335           Decl->getAsFunction()));
1336 }
1337 
1338 DeclarationFragments
getFragmentsForFunctionTemplateSpecialization(const FunctionDecl * Decl)1339 DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization(
1340     const FunctionDecl *Decl) {
1341   DeclarationFragments Fragments;
1342   return Fragments
1343       .append("template", DeclarationFragments::FragmentKind::Keyword)
1344       .appendSpace()
1345       .append("<>", DeclarationFragments::FragmentKind::Text)
1346       .appendSpace()
1347       .append(DeclarationFragmentsBuilder::getFragmentsForFunction(Decl));
1348 }
1349 
1350 DeclarationFragments
getFragmentsForMacro(StringRef Name,const MacroInfo * MI)1351 DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name,
1352                                                   const MacroInfo *MI) {
1353   DeclarationFragments Fragments;
1354   Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword)
1355       .appendSpace();
1356   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
1357 
1358   if (MI->isFunctionLike()) {
1359     Fragments.append("(", DeclarationFragments::FragmentKind::Text);
1360     unsigned numParameters = MI->getNumParams();
1361     if (MI->isC99Varargs())
1362       --numParameters;
1363     for (unsigned i = 0; i < numParameters; ++i) {
1364       if (i)
1365         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
1366       Fragments.append(MI->params()[i]->getName(),
1367                        DeclarationFragments::FragmentKind::InternalParam);
1368     }
1369     if (MI->isVariadic()) {
1370       if (numParameters && MI->isC99Varargs())
1371         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
1372       Fragments.append("...", DeclarationFragments::FragmentKind::Text);
1373     }
1374     Fragments.append(")", DeclarationFragments::FragmentKind::Text);
1375   }
1376   return Fragments;
1377 }
1378 
getFragmentsForObjCCategory(const ObjCCategoryDecl * Category)1379 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory(
1380     const ObjCCategoryDecl *Category) {
1381   DeclarationFragments Fragments;
1382 
1383   auto *Interface = Category->getClassInterface();
1384   SmallString<128> InterfaceUSR;
1385   index::generateUSRForDecl(Interface, InterfaceUSR);
1386 
1387   Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
1388       .appendSpace()
1389       .append(Interface->getName(),
1390               DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR,
1391               Interface)
1392       .append(" (", DeclarationFragments::FragmentKind::Text)
1393       .append(Category->getName(),
1394               DeclarationFragments::FragmentKind::Identifier)
1395       .append(")", DeclarationFragments::FragmentKind::Text);
1396 
1397   return Fragments;
1398 }
1399 
getFragmentsForObjCInterface(const ObjCInterfaceDecl * Interface)1400 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface(
1401     const ObjCInterfaceDecl *Interface) {
1402   DeclarationFragments Fragments;
1403   // Build the base of the Objective-C interface declaration.
1404   Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
1405       .appendSpace()
1406       .append(Interface->getName(),
1407               DeclarationFragments::FragmentKind::Identifier);
1408 
1409   // Build the inheritance part of the declaration.
1410   if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) {
1411     SmallString<128> SuperUSR;
1412     index::generateUSRForDecl(SuperClass, SuperUSR);
1413     Fragments.append(" : ", DeclarationFragments::FragmentKind::Text)
1414         .append(SuperClass->getName(),
1415                 DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR,
1416                 SuperClass);
1417   }
1418 
1419   return Fragments;
1420 }
1421 
getFragmentsForObjCMethod(const ObjCMethodDecl * Method)1422 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod(
1423     const ObjCMethodDecl *Method) {
1424   DeclarationFragments Fragments, After;
1425   // Build the instance/class method indicator.
1426   if (Method->isClassMethod())
1427     Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
1428   else if (Method->isInstanceMethod())
1429     Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
1430 
1431   // Build the return type.
1432   Fragments.append("(", DeclarationFragments::FragmentKind::Text)
1433       .append(getFragmentsForType(Method->getReturnType(),
1434                                   Method->getASTContext(), After))
1435       .append(std::move(After))
1436       .append(")", DeclarationFragments::FragmentKind::Text);
1437 
1438   // Build the selector part.
1439   Selector Selector = Method->getSelector();
1440   if (Selector.getNumArgs() == 0)
1441     // For Objective-C methods that don't take arguments, the first (and only)
1442     // slot of the selector is the method name.
1443     Fragments.appendSpace().append(
1444         Selector.getNameForSlot(0),
1445         DeclarationFragments::FragmentKind::Identifier);
1446 
1447   // For Objective-C methods that take arguments, build the selector slots.
1448   for (unsigned i = 0, end = Method->param_size(); i != end; ++i) {
1449     // Objective-C method selector parts are considered as identifiers instead
1450     // of "external parameters" as in Swift. This is because Objective-C method
1451     // symbols are referenced with the entire selector, instead of just the
1452     // method name in Swift.
1453     SmallString<32> ParamID(Selector.getNameForSlot(i));
1454     ParamID.append(":");
1455     Fragments.appendSpace().append(
1456         ParamID, DeclarationFragments::FragmentKind::Identifier);
1457 
1458     // Build the internal parameter.
1459     const ParmVarDecl *Param = Method->getParamDecl(i);
1460     Fragments.append(getFragmentsForParam(Param));
1461   }
1462 
1463   return Fragments.appendSemicolon();
1464 }
1465 
getFragmentsForObjCProperty(const ObjCPropertyDecl * Property)1466 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
1467     const ObjCPropertyDecl *Property) {
1468   DeclarationFragments Fragments, After;
1469 
1470   // Build the Objective-C property keyword.
1471   Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword);
1472 
1473   const auto Attributes = Property->getPropertyAttributesAsWritten();
1474   // Build the attributes if there is any associated with the property.
1475   if (Attributes != ObjCPropertyAttribute::kind_noattr) {
1476     // No leading comma for the first attribute.
1477     bool First = true;
1478     Fragments.append(" (", DeclarationFragments::FragmentKind::Text);
1479     // Helper function to render the attribute.
1480     auto RenderAttribute =
1481         [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling,
1482             StringRef Arg = "",
1483             DeclarationFragments::FragmentKind ArgKind =
1484                 DeclarationFragments::FragmentKind::Identifier) {
1485           // Check if the `Kind` attribute is set for this property.
1486           if ((Attributes & Kind) && !Spelling.empty()) {
1487             // Add a leading comma if this is not the first attribute rendered.
1488             if (!First)
1489               Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
1490             // Render the spelling of this attribute `Kind` as a keyword.
1491             Fragments.append(Spelling,
1492                              DeclarationFragments::FragmentKind::Keyword);
1493             // If this attribute takes in arguments (e.g. `getter=getterName`),
1494             // render the arguments.
1495             if (!Arg.empty())
1496               Fragments.append("=", DeclarationFragments::FragmentKind::Text)
1497                   .append(Arg, ArgKind);
1498             First = false;
1499           }
1500         };
1501 
1502     // Go through all possible Objective-C property attributes and render set
1503     // ones.
1504     RenderAttribute(ObjCPropertyAttribute::kind_class, "class");
1505     RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct");
1506     RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic");
1507     RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic");
1508     RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign");
1509     RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain");
1510     RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong");
1511     RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy");
1512     RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak");
1513     RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained,
1514                     "unsafe_unretained");
1515     RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite");
1516     RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly");
1517     RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter",
1518                     Property->getGetterName().getAsString());
1519     RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter",
1520                     Property->getSetterName().getAsString());
1521 
1522     // Render nullability attributes.
1523     if (Attributes & ObjCPropertyAttribute::kind_nullability) {
1524       QualType Type = Property->getType();
1525       if (const auto Nullability =
1526               AttributedType::stripOuterNullability(Type)) {
1527         if (!First)
1528           Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
1529         if (*Nullability == NullabilityKind::Unspecified &&
1530             (Attributes & ObjCPropertyAttribute::kind_null_resettable))
1531           Fragments.append("null_resettable",
1532                            DeclarationFragments::FragmentKind::Keyword);
1533         else
1534           Fragments.append(
1535               getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true),
1536               DeclarationFragments::FragmentKind::Keyword);
1537         First = false;
1538       }
1539     }
1540 
1541     Fragments.append(")", DeclarationFragments::FragmentKind::Text);
1542   }
1543 
1544   Fragments.appendSpace();
1545 
1546   FunctionTypeLoc BlockLoc;
1547   FunctionProtoTypeLoc BlockProtoLoc;
1548   findTypeLocForBlockDecl(Property->getTypeSourceInfo(), BlockLoc,
1549                           BlockProtoLoc);
1550 
1551   auto PropType = Property->getType();
1552   if (!BlockLoc)
1553     Fragments
1554         .append(getFragmentsForType(PropType, Property->getASTContext(), After))
1555         .appendSpace();
1556   else
1557     Fragments.append(
1558         getFragmentsForBlock(Property, BlockLoc, BlockProtoLoc, After));
1559 
1560   return Fragments
1561       .append(Property->getName(),
1562               DeclarationFragments::FragmentKind::Identifier)
1563       .append(std::move(After))
1564       .appendSemicolon();
1565 }
1566 
getFragmentsForObjCProtocol(const ObjCProtocolDecl * Protocol)1567 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(
1568     const ObjCProtocolDecl *Protocol) {
1569   DeclarationFragments Fragments;
1570   // Build basic protocol declaration.
1571   Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword)
1572       .appendSpace()
1573       .append(Protocol->getName(),
1574               DeclarationFragments::FragmentKind::Identifier);
1575 
1576   // If this protocol conforms to other protocols, build the conformance list.
1577   if (!Protocol->protocols().empty()) {
1578     Fragments.append(" <", DeclarationFragments::FragmentKind::Text);
1579     for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin();
1580          It != Protocol->protocol_end(); It++) {
1581       // Add a leading comma if this is not the first protocol rendered.
1582       if (It != Protocol->protocol_begin())
1583         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
1584 
1585       SmallString<128> USR;
1586       index::generateUSRForDecl(*It, USR);
1587       Fragments.append((*It)->getName(),
1588                        DeclarationFragments::FragmentKind::TypeIdentifier, USR,
1589                        *It);
1590     }
1591     Fragments.append(">", DeclarationFragments::FragmentKind::Text);
1592   }
1593 
1594   return Fragments;
1595 }
1596 
getFragmentsForTypedef(const TypedefNameDecl * Decl)1597 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(
1598     const TypedefNameDecl *Decl) {
1599   DeclarationFragments Fragments, After;
1600   Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword)
1601       .appendSpace()
1602       .append(getFragmentsForType(Decl->getUnderlyingType(),
1603                                   Decl->getASTContext(), After))
1604       .append(std::move(After))
1605       .appendSpace()
1606       .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
1607 
1608   return Fragments.appendSemicolon();
1609 }
1610 
1611 // Instantiate template for FunctionDecl.
1612 template FunctionSignature
1613 DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *);
1614 
1615 // Instantiate template for ObjCMethodDecl.
1616 template FunctionSignature
1617 DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *);
1618 
1619 // Subheading of a symbol defaults to its name.
1620 DeclarationFragments
getSubHeading(const NamedDecl * Decl)1621 DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) {
1622   DeclarationFragments Fragments;
1623   if (isa<CXXConstructorDecl>(Decl)) {
1624     Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(),
1625                      DeclarationFragments::FragmentKind::Identifier);
1626   } else if (isa<CXXDestructorDecl>(Decl)) {
1627     Fragments.append(cast<CXXDestructorDecl>(Decl)->getNameAsString(),
1628                      DeclarationFragments::FragmentKind::Identifier);
1629   } else if (isa<CXXConversionDecl>(Decl)) {
1630     Fragments.append(
1631         cast<CXXConversionDecl>(Decl)->getConversionType().getAsString(),
1632         DeclarationFragments::FragmentKind::Identifier);
1633   } else if (isa<CXXMethodDecl>(Decl) &&
1634              cast<CXXMethodDecl>(Decl)->isOverloadedOperator()) {
1635     Fragments.append(Decl->getNameAsString(),
1636                      DeclarationFragments::FragmentKind::Identifier);
1637   } else if (isa<TagDecl>(Decl) &&
1638              cast<TagDecl>(Decl)->getTypedefNameForAnonDecl()) {
1639     return getSubHeading(cast<TagDecl>(Decl)->getTypedefNameForAnonDecl());
1640   } else if (Decl->getIdentifier()) {
1641     Fragments.append(Decl->getName(),
1642                      DeclarationFragments::FragmentKind::Identifier);
1643   } else {
1644     Fragments.append(Decl->getDeclName().getAsString(),
1645                      DeclarationFragments::FragmentKind::Identifier);
1646   }
1647 
1648   return Fragments;
1649 }
1650 
1651 // Subheading of an Objective-C method is a `+` or `-` sign indicating whether
1652 // it's a class method or an instance method, followed by the selector name.
1653 DeclarationFragments
getSubHeading(const ObjCMethodDecl * Method)1654 DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) {
1655   DeclarationFragments Fragments;
1656   if (Method->isClassMethod())
1657     Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
1658   else if (Method->isInstanceMethod())
1659     Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
1660 
1661   return Fragments.append(Method->getNameAsString(),
1662                           DeclarationFragments::FragmentKind::Identifier);
1663 }
1664 
1665 // Subheading of a symbol defaults to its name.
1666 DeclarationFragments
getSubHeadingForMacro(StringRef Name)1667 DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) {
1668   DeclarationFragments Fragments;
1669   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
1670   return Fragments;
1671 }
1672