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