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 "TypedefUnderlyingTypeResolver.h"
16 #include "clang/Index/USRGeneration.h"
17 #include "llvm/ADT/StringSwitch.h"
18 
19 using namespace clang::extractapi;
20 using namespace llvm;
21 
22 DeclarationFragments &DeclarationFragments::appendSpace() {
23   if (!Fragments.empty()) {
24     Fragment Last = Fragments.back();
25     if (Last.Kind == FragmentKind::Text) {
26       // Merge the extra space into the last fragment if the last fragment is
27       // also text.
28       if (Last.Spelling.back() != ' ') { // avoid extra trailing spaces.
29         Last.Spelling.push_back(' ');
30       }
31     } else {
32       append(" ", FragmentKind::Text);
33     }
34   }
35 
36   return *this;
37 }
38 
39 StringRef DeclarationFragments::getFragmentKindString(
40     DeclarationFragments::FragmentKind Kind) {
41   switch (Kind) {
42   case DeclarationFragments::FragmentKind::None:
43     return "none";
44   case DeclarationFragments::FragmentKind::Keyword:
45     return "keyword";
46   case DeclarationFragments::FragmentKind::Attribute:
47     return "attribute";
48   case DeclarationFragments::FragmentKind::NumberLiteral:
49     return "number";
50   case DeclarationFragments::FragmentKind::StringLiteral:
51     return "string";
52   case DeclarationFragments::FragmentKind::Identifier:
53     return "identifier";
54   case DeclarationFragments::FragmentKind::TypeIdentifier:
55     return "typeIdentifier";
56   case DeclarationFragments::FragmentKind::GenericParameter:
57     return "genericParameter";
58   case DeclarationFragments::FragmentKind::ExternalParam:
59     return "externalParam";
60   case DeclarationFragments::FragmentKind::InternalParam:
61     return "internalParam";
62   case DeclarationFragments::FragmentKind::Text:
63     return "text";
64   }
65 
66   llvm_unreachable("Unhandled FragmentKind");
67 }
68 
69 DeclarationFragments::FragmentKind
70 DeclarationFragments::parseFragmentKindFromString(StringRef S) {
71   return llvm::StringSwitch<FragmentKind>(S)
72       .Case("keyword", DeclarationFragments::FragmentKind::Keyword)
73       .Case("attribute", DeclarationFragments::FragmentKind::Attribute)
74       .Case("number", DeclarationFragments::FragmentKind::NumberLiteral)
75       .Case("string", DeclarationFragments::FragmentKind::StringLiteral)
76       .Case("identifier", DeclarationFragments::FragmentKind::Identifier)
77       .Case("typeIdentifier",
78             DeclarationFragments::FragmentKind::TypeIdentifier)
79       .Case("genericParameter",
80             DeclarationFragments::FragmentKind::GenericParameter)
81       .Case("internalParam", DeclarationFragments::FragmentKind::InternalParam)
82       .Case("externalParam", DeclarationFragments::FragmentKind::ExternalParam)
83       .Case("text", DeclarationFragments::FragmentKind::Text)
84       .Default(DeclarationFragments::FragmentKind::None);
85 }
86 
87 // NNS stores C++ nested name specifiers, which are prefixes to qualified names.
88 // Build declaration fragments for NNS recursively so that we have the USR for
89 // every part in a qualified name, and also leaves the actual underlying type
90 // cleaner for its own fragment.
91 DeclarationFragments
92 DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS,
93                                                 ASTContext &Context,
94                                                 DeclarationFragments &After) {
95   DeclarationFragments Fragments;
96   if (NNS->getPrefix())
97     Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After));
98 
99   switch (NNS->getKind()) {
100   case NestedNameSpecifier::Identifier:
101     Fragments.append(NNS->getAsIdentifier()->getName(),
102                      DeclarationFragments::FragmentKind::Identifier);
103     break;
104 
105   case NestedNameSpecifier::Namespace: {
106     const NamespaceDecl *NS = NNS->getAsNamespace();
107     if (NS->isAnonymousNamespace())
108       return Fragments;
109     SmallString<128> USR;
110     index::generateUSRForDecl(NS, USR);
111     Fragments.append(NS->getName(),
112                      DeclarationFragments::FragmentKind::Identifier, USR);
113     break;
114   }
115 
116   case NestedNameSpecifier::NamespaceAlias: {
117     const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias();
118     SmallString<128> USR;
119     index::generateUSRForDecl(Alias, USR);
120     Fragments.append(Alias->getName(),
121                      DeclarationFragments::FragmentKind::Identifier, USR);
122     break;
123   }
124 
125   case NestedNameSpecifier::Global:
126     // The global specifier `::` at the beginning. No stored value.
127     break;
128 
129   case NestedNameSpecifier::Super:
130     // Microsoft's `__super` specifier.
131     Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword);
132     break;
133 
134   case NestedNameSpecifier::TypeSpecWithTemplate:
135     // A type prefixed by the `template` keyword.
136     Fragments.append("template", DeclarationFragments::FragmentKind::Keyword);
137     Fragments.appendSpace();
138     // Fallthrough after adding the keyword to handle the actual type.
139     LLVM_FALLTHROUGH;
140 
141   case NestedNameSpecifier::TypeSpec: {
142     const Type *T = NNS->getAsType();
143     // FIXME: Handle C++ template specialization type
144     Fragments.append(getFragmentsForType(T, Context, After));
145     break;
146   }
147   }
148 
149   // Add the separator text `::` for this segment.
150   return Fragments.append("::", DeclarationFragments::FragmentKind::Text);
151 }
152 
153 // Recursively build the declaration fragments for an underlying `Type` with
154 // qualifiers removed.
155 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
156     const Type *T, ASTContext &Context, DeclarationFragments &After) {
157   assert(T && "invalid type");
158 
159   DeclarationFragments Fragments;
160 
161   // Declaration fragments of a pointer type is the declaration fragments of
162   // the pointee type followed by a `*`, except for Objective-C `id` and `Class`
163   // pointers, where we do not spell out the `*`.
164   if (T->isPointerType() ||
165       (T->isObjCObjectPointerType() &&
166        !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType())) {
167     return Fragments
168         .append(getFragmentsForType(T->getPointeeType(), Context, After))
169         .append(" *", DeclarationFragments::FragmentKind::Text);
170   }
171 
172   // Declaration fragments of a lvalue reference type is the declaration
173   // fragments of the underlying type followed by a `&`.
174   if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T))
175     return Fragments
176         .append(
177             getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After))
178         .append(" &", DeclarationFragments::FragmentKind::Text);
179 
180   // Declaration fragments of a rvalue reference type is the declaration
181   // fragments of the underlying type followed by a `&&`.
182   if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T))
183     return Fragments
184         .append(
185             getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After))
186         .append(" &&", DeclarationFragments::FragmentKind::Text);
187 
188   // Declaration fragments of an array-typed variable have two parts:
189   // 1. the element type of the array that appears before the variable name;
190   // 2. array brackets `[(0-9)?]` that appear after the variable name.
191   if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) {
192     // Build the "after" part first because the inner element type might also
193     // be an array-type. For example `int matrix[3][4]` which has a type of
194     // "(array 3 of (array 4 of ints))."
195     // Push the array size part first to make sure they are in the right order.
196     After.append("[", DeclarationFragments::FragmentKind::Text);
197 
198     switch (AT->getSizeModifier()) {
199     case ArrayType::Normal:
200       break;
201     case ArrayType::Static:
202       Fragments.append("static", DeclarationFragments::FragmentKind::Keyword);
203       break;
204     case ArrayType::Star:
205       Fragments.append("*", DeclarationFragments::FragmentKind::Text);
206       break;
207     }
208 
209     if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
210       // FIXME: right now this would evaluate any expressions/macros written in
211       // the original source to concrete values. For example
212       // `int nums[MAX]` -> `int nums[100]`
213       // `char *str[5 + 1]` -> `char *str[6]`
214       SmallString<128> Size;
215       CAT->getSize().toStringUnsigned(Size);
216       After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral);
217     }
218 
219     After.append("]", DeclarationFragments::FragmentKind::Text);
220 
221     return Fragments.append(
222         getFragmentsForType(AT->getElementType(), Context, After));
223   }
224 
225   // An ElaboratedType is a sugar for types that are referred to using an
226   // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a
227   // qualified name, e.g., `N::M::type`, or both.
228   if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) {
229     ElaboratedTypeKeyword Keyword = ET->getKeyword();
230     if (Keyword != ETK_None) {
231       Fragments
232           .append(ElaboratedType::getKeywordName(Keyword),
233                   DeclarationFragments::FragmentKind::Keyword)
234           .appendSpace();
235     }
236 
237     if (const NestedNameSpecifier *NNS = ET->getQualifier())
238       Fragments.append(getFragmentsForNNS(NNS, Context, After));
239 
240     // After handling the elaborated keyword or qualified name, build
241     // declaration fragments for the desugared underlying type.
242     return Fragments.append(getFragmentsForType(ET->desugar(), Context, After));
243   }
244 
245   // Everything we care about has been handled now, reduce to the canonical
246   // unqualified base type.
247   QualType Base = T->getCanonicalTypeUnqualified();
248 
249   // Render Objective-C `id`/`instancetype` as keywords.
250   if (T->isObjCIdType())
251     return Fragments.append(Base.getAsString(),
252                             DeclarationFragments::FragmentKind::Keyword);
253 
254   // If the type is a typedefed type, get the underlying TypedefNameDecl for a
255   // direct reference to the typedef instead of the wrapped type.
256   if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) {
257     const TypedefNameDecl *Decl = TypedefTy->getDecl();
258     std::string USR =
259         TypedefUnderlyingTypeResolver(Context).getUSRForType(QualType(T, 0));
260     return Fragments.append(Decl->getName(),
261                             DeclarationFragments::FragmentKind::TypeIdentifier,
262                             USR);
263   }
264 
265   // If the base type is a TagType (struct/interface/union/class/enum), let's
266   // get the underlying Decl for better names and USRs.
267   if (const TagType *TagTy = dyn_cast<TagType>(Base)) {
268     const TagDecl *Decl = TagTy->getDecl();
269     // Anonymous decl, skip this fragment.
270     if (Decl->getName().empty())
271       return Fragments;
272     SmallString<128> TagUSR;
273     clang::index::generateUSRForDecl(Decl, TagUSR);
274     return Fragments.append(Decl->getName(),
275                             DeclarationFragments::FragmentKind::TypeIdentifier,
276                             TagUSR);
277   }
278 
279   // If the base type is an ObjCInterfaceType, use the underlying
280   // ObjCInterfaceDecl for the true USR.
281   if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) {
282     const auto *Decl = ObjCIT->getDecl();
283     SmallString<128> USR;
284     index::generateUSRForDecl(Decl, USR);
285     return Fragments.append(Decl->getName(),
286                             DeclarationFragments::FragmentKind::TypeIdentifier,
287                             USR);
288   }
289 
290   // Default fragment builder for other kinds of types (BuiltinType etc.)
291   SmallString<128> USR;
292   clang::index::generateUSRForType(Base, Context, USR);
293   Fragments.append(Base.getAsString(),
294                    DeclarationFragments::FragmentKind::TypeIdentifier, USR);
295 
296   return Fragments;
297 }
298 
299 DeclarationFragments
300 DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) {
301   DeclarationFragments Fragments;
302   if (Quals.hasConst())
303     Fragments.append("const", DeclarationFragments::FragmentKind::Keyword);
304   if (Quals.hasVolatile())
305     Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword);
306   if (Quals.hasRestrict())
307     Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword);
308 
309   return Fragments;
310 }
311 
312 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
313     const QualType QT, ASTContext &Context, DeclarationFragments &After) {
314   assert(!QT.isNull() && "invalid type");
315 
316   if (const ParenType *PT = dyn_cast<ParenType>(QT)) {
317     After.append(")", DeclarationFragments::FragmentKind::Text);
318     return getFragmentsForType(PT->getInnerType(), Context, After)
319         .append("(", DeclarationFragments::FragmentKind::Text);
320   }
321 
322   const SplitQualType SQT = QT.split();
323   DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals),
324                        TypeFragments =
325                            getFragmentsForType(SQT.Ty, Context, After);
326   if (QualsFragments.getFragments().empty())
327     return TypeFragments;
328 
329   // Use east qualifier for pointer types
330   // For example:
331   // ```
332   // int *   const
333   // ^----   ^----
334   //  type    qualifier
335   // ^-----------------
336   //  const pointer to int
337   // ```
338   // should not be reconstructed as
339   // ```
340   // const       int       *
341   // ^----       ^--
342   //  qualifier   type
343   // ^----------------     ^
344   //  pointer to const int
345   // ```
346   if (SQT.Ty->isAnyPointerType())
347     return TypeFragments.appendSpace().append(std::move(QualsFragments));
348 
349   return QualsFragments.appendSpace().append(std::move(TypeFragments));
350 }
351 
352 DeclarationFragments
353 DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
354   DeclarationFragments Fragments;
355   StorageClass SC = Var->getStorageClass();
356   if (SC != SC_None)
357     Fragments
358         .append(VarDecl::getStorageClassSpecifierString(SC),
359                 DeclarationFragments::FragmentKind::Keyword)
360         .appendSpace();
361   QualType T =
362       Var->getTypeSourceInfo()
363           ? Var->getTypeSourceInfo()->getType()
364           : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType());
365 
366   // Capture potential fragments that needs to be placed after the variable name
367   // ```
368   // int nums[5];
369   // char (*ptr_to_array)[6];
370   // ```
371   DeclarationFragments After;
372   return Fragments.append(getFragmentsForType(T, Var->getASTContext(), After))
373       .appendSpace()
374       .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
375       .append(std::move(After));
376 }
377 
378 DeclarationFragments
379 DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) {
380   DeclarationFragments Fragments, After;
381 
382   QualType T = Param->getTypeSourceInfo()
383                    ? Param->getTypeSourceInfo()->getType()
384                    : Param->getASTContext().getUnqualifiedObjCPointerType(
385                          Param->getType());
386 
387   DeclarationFragments TypeFragments =
388       getFragmentsForType(T, Param->getASTContext(), After);
389 
390   if (Param->isObjCMethodParameter())
391     Fragments.append("(", DeclarationFragments::FragmentKind::Text)
392         .append(std::move(TypeFragments))
393         .append(")", DeclarationFragments::FragmentKind::Text);
394   else
395     Fragments.append(std::move(TypeFragments)).appendSpace();
396 
397   return Fragments
398       .append(Param->getName(),
399               DeclarationFragments::FragmentKind::InternalParam)
400       .append(std::move(After));
401 }
402 
403 DeclarationFragments
404 DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
405   DeclarationFragments Fragments;
406   // FIXME: Handle template specialization
407   switch (Func->getStorageClass()) {
408   case SC_None:
409   case SC_PrivateExtern:
410     break;
411   case SC_Extern:
412     Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword)
413         .appendSpace();
414     break;
415   case SC_Static:
416     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
417         .appendSpace();
418     break;
419   case SC_Auto:
420   case SC_Register:
421     llvm_unreachable("invalid for functions");
422   }
423   // FIXME: Handle C++ function specifiers: constexpr, consteval, explicit, etc.
424 
425   // FIXME: Is `after` actually needed here?
426   DeclarationFragments After;
427   Fragments
428       .append(getFragmentsForType(Func->getReturnType(), Func->getASTContext(),
429                                   After))
430       .appendSpace()
431       .append(Func->getName(), DeclarationFragments::FragmentKind::Identifier)
432       .append(std::move(After));
433 
434   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
435   for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) {
436     if (i)
437       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
438     Fragments.append(getFragmentsForParam(Func->getParamDecl(i)));
439   }
440   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
441 
442   // FIXME: Handle exception specifiers: throw, noexcept
443   return Fragments;
444 }
445 
446 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant(
447     const EnumConstantDecl *EnumConstDecl) {
448   DeclarationFragments Fragments;
449   return Fragments.append(EnumConstDecl->getName(),
450                           DeclarationFragments::FragmentKind::Identifier);
451 }
452 
453 DeclarationFragments
454 DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {
455   if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl())
456     return getFragmentsForTypedef(TypedefNameDecl);
457 
458   DeclarationFragments Fragments, After;
459   Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword);
460 
461   if (!EnumDecl->getName().empty())
462     Fragments.appendSpace().append(
463         EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier);
464 
465   QualType IntegerType = EnumDecl->getIntegerType();
466   if (!IntegerType.isNull())
467     Fragments.append(": ", DeclarationFragments::FragmentKind::Text)
468         .append(
469             getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))
470         .append(std::move(After));
471 
472   return Fragments;
473 }
474 
475 DeclarationFragments
476 DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) {
477   DeclarationFragments After;
478   return getFragmentsForType(Field->getType(), Field->getASTContext(), After)
479       .appendSpace()
480       .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)
481       .append(std::move(After));
482 }
483 
484 DeclarationFragments
485 DeclarationFragmentsBuilder::getFragmentsForStruct(const RecordDecl *Record) {
486   if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
487     return getFragmentsForTypedef(TypedefNameDecl);
488 
489   DeclarationFragments Fragments;
490   Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);
491 
492   if (!Record->getName().empty())
493     Fragments.appendSpace().append(
494         Record->getName(), DeclarationFragments::FragmentKind::Identifier);
495   return Fragments;
496 }
497 
498 DeclarationFragments
499 DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name,
500                                                   const MacroDirective *MD) {
501   DeclarationFragments Fragments;
502   Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword)
503       .appendSpace();
504   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
505 
506   auto *MI = MD->getMacroInfo();
507 
508   if (MI->isFunctionLike()) {
509     Fragments.append("(", DeclarationFragments::FragmentKind::Text);
510     unsigned numParameters = MI->getNumParams();
511     if (MI->isC99Varargs())
512       --numParameters;
513     for (unsigned i = 0; i < numParameters; ++i) {
514       if (i)
515         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
516       Fragments.append(MI->params()[i]->getName(),
517                        DeclarationFragments::FragmentKind::InternalParam);
518     }
519     if (MI->isVariadic()) {
520       if (numParameters && MI->isC99Varargs())
521         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
522       Fragments.append("...", DeclarationFragments::FragmentKind::Text);
523     }
524     Fragments.append(")", DeclarationFragments::FragmentKind::Text);
525   }
526   return Fragments;
527 }
528 
529 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface(
530     const ObjCInterfaceDecl *Interface) {
531   DeclarationFragments Fragments;
532   // Build the base of the Objective-C interface declaration.
533   Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
534       .appendSpace()
535       .append(Interface->getName(),
536               DeclarationFragments::FragmentKind::Identifier);
537 
538   // Build the inheritance part of the declaration.
539   if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) {
540     SmallString<128> SuperUSR;
541     index::generateUSRForDecl(SuperClass, SuperUSR);
542     Fragments.append(" : ", DeclarationFragments::FragmentKind::Text)
543         .append(SuperClass->getName(),
544                 DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR);
545   }
546 
547   return Fragments;
548 }
549 
550 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod(
551     const ObjCMethodDecl *Method) {
552   DeclarationFragments Fragments, After;
553   // Build the instance/class method indicator.
554   if (Method->isClassMethod())
555     Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
556   else if (Method->isInstanceMethod())
557     Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
558 
559   // Build the return type.
560   Fragments.append("(", DeclarationFragments::FragmentKind::Text)
561       .append(getFragmentsForType(Method->getReturnType(),
562                                   Method->getASTContext(), After))
563       .append(std::move(After))
564       .append(")", DeclarationFragments::FragmentKind::Text);
565 
566   // Build the selector part.
567   Selector Selector = Method->getSelector();
568   if (Selector.getNumArgs() == 0)
569     // For Objective-C methods that don't take arguments, the first (and only)
570     // slot of the selector is the method name.
571     Fragments.appendSpace().append(
572         Selector.getNameForSlot(0),
573         DeclarationFragments::FragmentKind::Identifier);
574 
575   // For Objective-C methods that take arguments, build the selector slots.
576   for (unsigned i = 0, end = Method->param_size(); i != end; ++i) {
577     Fragments.appendSpace()
578         .append(Selector.getNameForSlot(i),
579                 // The first slot is the name of the method, record as an
580                 // identifier, otherwise as exteranl parameters.
581                 i == 0 ? DeclarationFragments::FragmentKind::Identifier
582                        : DeclarationFragments::FragmentKind::ExternalParam)
583         .append(":", DeclarationFragments::FragmentKind::Text);
584 
585     // Build the internal parameter.
586     const ParmVarDecl *Param = Method->getParamDecl(i);
587     Fragments.append(getFragmentsForParam(Param));
588   }
589 
590   return Fragments;
591 }
592 
593 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
594     const ObjCPropertyDecl *Property) {
595   DeclarationFragments Fragments, After;
596 
597   // Build the Objective-C property keyword.
598   Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword);
599 
600   const auto Attributes = Property->getPropertyAttributes();
601   // Build the attributes if there is any associated with the property.
602   if (Attributes != ObjCPropertyAttribute::kind_noattr) {
603     // No leading comma for the first attribute.
604     bool First = true;
605     Fragments.append(" (", DeclarationFragments::FragmentKind::Text);
606     // Helper function to render the attribute.
607     auto RenderAttribute =
608         [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling,
609             StringRef Arg = "",
610             DeclarationFragments::FragmentKind ArgKind =
611                 DeclarationFragments::FragmentKind::Identifier) {
612           // Check if the `Kind` attribute is set for this property.
613           if ((Attributes & Kind) && !Spelling.empty()) {
614             // Add a leading comma if this is not the first attribute rendered.
615             if (!First)
616               Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
617             // Render the spelling of this attribute `Kind` as a keyword.
618             Fragments.append(Spelling,
619                              DeclarationFragments::FragmentKind::Keyword);
620             // If this attribute takes in arguments (e.g. `getter=getterName`),
621             // render the arguments.
622             if (!Arg.empty())
623               Fragments.append("=", DeclarationFragments::FragmentKind::Text)
624                   .append(Arg, ArgKind);
625             First = false;
626           }
627         };
628 
629     // Go through all possible Objective-C property attributes and render set
630     // ones.
631     RenderAttribute(ObjCPropertyAttribute::kind_class, "class");
632     RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct");
633     RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic");
634     RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic");
635     RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign");
636     RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain");
637     RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong");
638     RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy");
639     RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak");
640     RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained,
641                     "unsafe_unretained");
642     RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite");
643     RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly");
644     RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter",
645                     Property->getGetterName().getAsString());
646     RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter",
647                     Property->getSetterName().getAsString());
648 
649     // Render nullability attributes.
650     if (Attributes & ObjCPropertyAttribute::kind_nullability) {
651       QualType Type = Property->getType();
652       if (const auto Nullability =
653               AttributedType::stripOuterNullability(Type)) {
654         if (!First)
655           Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
656         if (*Nullability == NullabilityKind::Unspecified &&
657             (Attributes & ObjCPropertyAttribute::kind_null_resettable))
658           Fragments.append("null_resettable",
659                            DeclarationFragments::FragmentKind::Keyword);
660         else
661           Fragments.append(
662               getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true),
663               DeclarationFragments::FragmentKind::Keyword);
664         First = false;
665       }
666     }
667 
668     Fragments.append(")", DeclarationFragments::FragmentKind::Text);
669   }
670 
671   // Build the property type and name, and return the completed fragments.
672   return Fragments.appendSpace()
673       .append(getFragmentsForType(Property->getType(),
674                                   Property->getASTContext(), After))
675       .append(Property->getName(),
676               DeclarationFragments::FragmentKind::Identifier)
677       .append(std::move(After));
678 }
679 
680 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(
681     const ObjCProtocolDecl *Protocol) {
682   DeclarationFragments Fragments;
683   // Build basic protocol declaration.
684   Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword)
685       .appendSpace()
686       .append(Protocol->getName(),
687               DeclarationFragments::FragmentKind::Identifier);
688 
689   // If this protocol conforms to other protocols, build the conformance list.
690   if (!Protocol->protocols().empty()) {
691     Fragments.append(" <", DeclarationFragments::FragmentKind::Text);
692     for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin();
693          It != Protocol->protocol_end(); It++) {
694       // Add a leading comma if this is not the first protocol rendered.
695       if (It != Protocol->protocol_begin())
696         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
697 
698       SmallString<128> USR;
699       index::generateUSRForDecl(*It, USR);
700       Fragments.append((*It)->getName(),
701                        DeclarationFragments::FragmentKind::TypeIdentifier, USR);
702     }
703     Fragments.append(">", DeclarationFragments::FragmentKind::Text);
704   }
705 
706   return Fragments;
707 }
708 
709 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(
710     const TypedefNameDecl *Decl) {
711   DeclarationFragments Fragments, After;
712   Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword)
713       .appendSpace()
714       .append(getFragmentsForType(Decl->getUnderlyingType(),
715                                   Decl->getASTContext(), After))
716       .append(std::move(After))
717       .appendSpace()
718       .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
719 
720   return Fragments;
721 }
722 
723 template <typename FunctionT>
724 FunctionSignature
725 DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) {
726   FunctionSignature Signature;
727 
728   DeclarationFragments ReturnType, After;
729   ReturnType
730       .append(getFragmentsForType(Function->getReturnType(),
731                                   Function->getASTContext(), After))
732       .append(std::move(After));
733   Signature.setReturnType(ReturnType);
734 
735   for (const auto *Param : Function->parameters())
736     Signature.addParameter(Param->getName(), getFragmentsForParam(Param));
737 
738   return Signature;
739 }
740 
741 // Instantiate template for FunctionDecl.
742 template FunctionSignature
743 DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *);
744 
745 // Instantiate template for ObjCMethodDecl.
746 template FunctionSignature
747 DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *);
748 
749 // Subheading of a symbol defaults to its name.
750 DeclarationFragments
751 DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) {
752   DeclarationFragments Fragments;
753   if (!Decl->getName().empty())
754     Fragments.append(Decl->getName(),
755                      DeclarationFragments::FragmentKind::Identifier);
756   return Fragments;
757 }
758 
759 // Subheading of an Objective-C method is a `+` or `-` sign indicating whether
760 // it's a class method or an instance method, followed by the selector name.
761 DeclarationFragments
762 DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) {
763   DeclarationFragments Fragments;
764   if (Method->isClassMethod())
765     Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
766   else if (Method->isInstanceMethod())
767     Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
768 
769   return Fragments.append(Method->getNameAsString(),
770                           DeclarationFragments::FragmentKind::Identifier);
771 }
772 
773 // Subheading of a symbol defaults to its name.
774 DeclarationFragments
775 DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) {
776   DeclarationFragments Fragments;
777   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
778   return Fragments;
779 }
780