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