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::getFragmentsForObjCCategory(
530     const ObjCCategoryDecl *Category) {
531   DeclarationFragments Fragments;
532 
533   SmallString<128> InterfaceUSR;
534   index::generateUSRForDecl(Category->getClassInterface(), InterfaceUSR);
535 
536   Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
537       .appendSpace()
538       .append(Category->getClassInterface()->getName(),
539               DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR)
540       .append(" (", DeclarationFragments::FragmentKind::Text)
541       .append(Category->getName(),
542               DeclarationFragments::FragmentKind::Identifier)
543       .append(")", DeclarationFragments::FragmentKind::Text);
544 
545   return Fragments;
546 }
547 
548 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface(
549     const ObjCInterfaceDecl *Interface) {
550   DeclarationFragments Fragments;
551   // Build the base of the Objective-C interface declaration.
552   Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
553       .appendSpace()
554       .append(Interface->getName(),
555               DeclarationFragments::FragmentKind::Identifier);
556 
557   // Build the inheritance part of the declaration.
558   if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) {
559     SmallString<128> SuperUSR;
560     index::generateUSRForDecl(SuperClass, SuperUSR);
561     Fragments.append(" : ", DeclarationFragments::FragmentKind::Text)
562         .append(SuperClass->getName(),
563                 DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR);
564   }
565 
566   return Fragments;
567 }
568 
569 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod(
570     const ObjCMethodDecl *Method) {
571   DeclarationFragments Fragments, After;
572   // Build the instance/class method indicator.
573   if (Method->isClassMethod())
574     Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
575   else if (Method->isInstanceMethod())
576     Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
577 
578   // Build the return type.
579   Fragments.append("(", DeclarationFragments::FragmentKind::Text)
580       .append(getFragmentsForType(Method->getReturnType(),
581                                   Method->getASTContext(), After))
582       .append(std::move(After))
583       .append(")", DeclarationFragments::FragmentKind::Text);
584 
585   // Build the selector part.
586   Selector Selector = Method->getSelector();
587   if (Selector.getNumArgs() == 0)
588     // For Objective-C methods that don't take arguments, the first (and only)
589     // slot of the selector is the method name.
590     Fragments.appendSpace().append(
591         Selector.getNameForSlot(0),
592         DeclarationFragments::FragmentKind::Identifier);
593 
594   // For Objective-C methods that take arguments, build the selector slots.
595   for (unsigned i = 0, end = Method->param_size(); i != end; ++i) {
596     // Objective-C method selector parts are considered as identifiers instead
597     // of "external parameters" as in Swift. This is because Objective-C method
598     // symbols are referenced with the entire selector, instead of just the
599     // method name in Swift.
600     SmallString<32> ParamID(Selector.getNameForSlot(i));
601     ParamID.append(":");
602     Fragments.appendSpace().append(
603         ParamID, DeclarationFragments::FragmentKind::Identifier);
604 
605     // Build the internal parameter.
606     const ParmVarDecl *Param = Method->getParamDecl(i);
607     Fragments.append(getFragmentsForParam(Param));
608   }
609 
610   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
611 }
612 
613 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
614     const ObjCPropertyDecl *Property) {
615   DeclarationFragments Fragments, After;
616 
617   // Build the Objective-C property keyword.
618   Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword);
619 
620   const auto Attributes = Property->getPropertyAttributes();
621   // Build the attributes if there is any associated with the property.
622   if (Attributes != ObjCPropertyAttribute::kind_noattr) {
623     // No leading comma for the first attribute.
624     bool First = true;
625     Fragments.append(" (", DeclarationFragments::FragmentKind::Text);
626     // Helper function to render the attribute.
627     auto RenderAttribute =
628         [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling,
629             StringRef Arg = "",
630             DeclarationFragments::FragmentKind ArgKind =
631                 DeclarationFragments::FragmentKind::Identifier) {
632           // Check if the `Kind` attribute is set for this property.
633           if ((Attributes & Kind) && !Spelling.empty()) {
634             // Add a leading comma if this is not the first attribute rendered.
635             if (!First)
636               Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
637             // Render the spelling of this attribute `Kind` as a keyword.
638             Fragments.append(Spelling,
639                              DeclarationFragments::FragmentKind::Keyword);
640             // If this attribute takes in arguments (e.g. `getter=getterName`),
641             // render the arguments.
642             if (!Arg.empty())
643               Fragments.append("=", DeclarationFragments::FragmentKind::Text)
644                   .append(Arg, ArgKind);
645             First = false;
646           }
647         };
648 
649     // Go through all possible Objective-C property attributes and render set
650     // ones.
651     RenderAttribute(ObjCPropertyAttribute::kind_class, "class");
652     RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct");
653     RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic");
654     RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic");
655     RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign");
656     RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain");
657     RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong");
658     RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy");
659     RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak");
660     RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained,
661                     "unsafe_unretained");
662     RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite");
663     RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly");
664     RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter",
665                     Property->getGetterName().getAsString());
666     RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter",
667                     Property->getSetterName().getAsString());
668 
669     // Render nullability attributes.
670     if (Attributes & ObjCPropertyAttribute::kind_nullability) {
671       QualType Type = Property->getType();
672       if (const auto Nullability =
673               AttributedType::stripOuterNullability(Type)) {
674         if (!First)
675           Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
676         if (*Nullability == NullabilityKind::Unspecified &&
677             (Attributes & ObjCPropertyAttribute::kind_null_resettable))
678           Fragments.append("null_resettable",
679                            DeclarationFragments::FragmentKind::Keyword);
680         else
681           Fragments.append(
682               getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true),
683               DeclarationFragments::FragmentKind::Keyword);
684         First = false;
685       }
686     }
687 
688     Fragments.append(")", DeclarationFragments::FragmentKind::Text);
689   }
690 
691   // Build the property type and name, and return the completed fragments.
692   return Fragments.appendSpace()
693       .append(getFragmentsForType(Property->getType(),
694                                   Property->getASTContext(), After))
695       .append(Property->getName(),
696               DeclarationFragments::FragmentKind::Identifier)
697       .append(std::move(After));
698 }
699 
700 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(
701     const ObjCProtocolDecl *Protocol) {
702   DeclarationFragments Fragments;
703   // Build basic protocol declaration.
704   Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword)
705       .appendSpace()
706       .append(Protocol->getName(),
707               DeclarationFragments::FragmentKind::Identifier);
708 
709   // If this protocol conforms to other protocols, build the conformance list.
710   if (!Protocol->protocols().empty()) {
711     Fragments.append(" <", DeclarationFragments::FragmentKind::Text);
712     for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin();
713          It != Protocol->protocol_end(); It++) {
714       // Add a leading comma if this is not the first protocol rendered.
715       if (It != Protocol->protocol_begin())
716         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
717 
718       SmallString<128> USR;
719       index::generateUSRForDecl(*It, USR);
720       Fragments.append((*It)->getName(),
721                        DeclarationFragments::FragmentKind::TypeIdentifier, USR);
722     }
723     Fragments.append(">", DeclarationFragments::FragmentKind::Text);
724   }
725 
726   return Fragments;
727 }
728 
729 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(
730     const TypedefNameDecl *Decl) {
731   DeclarationFragments Fragments, After;
732   Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword)
733       .appendSpace()
734       .append(getFragmentsForType(Decl->getUnderlyingType(),
735                                   Decl->getASTContext(), After))
736       .append(std::move(After))
737       .appendSpace()
738       .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
739 
740   return Fragments;
741 }
742 
743 template <typename FunctionT>
744 FunctionSignature
745 DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) {
746   FunctionSignature Signature;
747 
748   DeclarationFragments ReturnType, After;
749   ReturnType
750       .append(getFragmentsForType(Function->getReturnType(),
751                                   Function->getASTContext(), After))
752       .append(std::move(After));
753   Signature.setReturnType(ReturnType);
754 
755   for (const auto *Param : Function->parameters())
756     Signature.addParameter(Param->getName(), getFragmentsForParam(Param));
757 
758   return Signature;
759 }
760 
761 // Instantiate template for FunctionDecl.
762 template FunctionSignature
763 DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *);
764 
765 // Instantiate template for ObjCMethodDecl.
766 template FunctionSignature
767 DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *);
768 
769 // Subheading of a symbol defaults to its name.
770 DeclarationFragments
771 DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) {
772   DeclarationFragments Fragments;
773   if (!Decl->getName().empty())
774     Fragments.append(Decl->getName(),
775                      DeclarationFragments::FragmentKind::Identifier);
776   return Fragments;
777 }
778 
779 // Subheading of an Objective-C method is a `+` or `-` sign indicating whether
780 // it's a class method or an instance method, followed by the selector name.
781 DeclarationFragments
782 DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) {
783   DeclarationFragments Fragments;
784   if (Method->isClassMethod())
785     Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
786   else if (Method->isInstanceMethod())
787     Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
788 
789   return Fragments.append(Method->getNameAsString(),
790                           DeclarationFragments::FragmentKind::Identifier);
791 }
792 
793 // Subheading of a symbol defaults to its name.
794 DeclarationFragments
795 DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) {
796   DeclarationFragments Fragments;
797   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
798   return Fragments;
799 }
800