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