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