xref: /freebsd/contrib/llvm-project/clang/lib/ExtractAPI/DeclarationFragments.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
181ad6265SDimitry Andric //===- ExtractAPI/DeclarationFragments.cpp ----------------------*- C++ -*-===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric ///
981ad6265SDimitry Andric /// \file
1081ad6265SDimitry Andric /// This file implements Declaration Fragments related classes.
1181ad6265SDimitry Andric ///
1281ad6265SDimitry Andric //===----------------------------------------------------------------------===//
1381ad6265SDimitry Andric 
1481ad6265SDimitry Andric #include "clang/ExtractAPI/DeclarationFragments.h"
15*06c3fb27SDimitry Andric #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
1681ad6265SDimitry Andric #include "clang/Index/USRGeneration.h"
1781ad6265SDimitry Andric #include "llvm/ADT/StringSwitch.h"
1881ad6265SDimitry Andric 
1981ad6265SDimitry Andric using namespace clang::extractapi;
2081ad6265SDimitry Andric using namespace llvm;
2181ad6265SDimitry Andric 
2281ad6265SDimitry Andric DeclarationFragments &DeclarationFragments::appendSpace() {
2381ad6265SDimitry Andric   if (!Fragments.empty()) {
2481ad6265SDimitry Andric     Fragment &Last = Fragments.back();
2581ad6265SDimitry Andric     if (Last.Kind == FragmentKind::Text) {
2681ad6265SDimitry Andric       // Merge the extra space into the last fragment if the last fragment is
2781ad6265SDimitry Andric       // also text.
2881ad6265SDimitry Andric       if (Last.Spelling.back() != ' ') { // avoid extra trailing spaces.
2981ad6265SDimitry Andric         Last.Spelling.push_back(' ');
3081ad6265SDimitry Andric       }
3181ad6265SDimitry Andric     } else {
3281ad6265SDimitry Andric       append(" ", FragmentKind::Text);
3381ad6265SDimitry Andric     }
3481ad6265SDimitry Andric   }
3581ad6265SDimitry Andric 
3681ad6265SDimitry Andric   return *this;
3781ad6265SDimitry Andric }
3881ad6265SDimitry Andric 
3981ad6265SDimitry Andric StringRef DeclarationFragments::getFragmentKindString(
4081ad6265SDimitry Andric     DeclarationFragments::FragmentKind Kind) {
4181ad6265SDimitry Andric   switch (Kind) {
4281ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::None:
4381ad6265SDimitry Andric     return "none";
4481ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::Keyword:
4581ad6265SDimitry Andric     return "keyword";
4681ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::Attribute:
4781ad6265SDimitry Andric     return "attribute";
4881ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::NumberLiteral:
4981ad6265SDimitry Andric     return "number";
5081ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::StringLiteral:
5181ad6265SDimitry Andric     return "string";
5281ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::Identifier:
5381ad6265SDimitry Andric     return "identifier";
5481ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::TypeIdentifier:
5581ad6265SDimitry Andric     return "typeIdentifier";
5681ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::GenericParameter:
5781ad6265SDimitry Andric     return "genericParameter";
5881ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::ExternalParam:
5981ad6265SDimitry Andric     return "externalParam";
6081ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::InternalParam:
6181ad6265SDimitry Andric     return "internalParam";
6281ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::Text:
6381ad6265SDimitry Andric     return "text";
6481ad6265SDimitry Andric   }
6581ad6265SDimitry Andric 
6681ad6265SDimitry Andric   llvm_unreachable("Unhandled FragmentKind");
6781ad6265SDimitry Andric }
6881ad6265SDimitry Andric 
6981ad6265SDimitry Andric DeclarationFragments::FragmentKind
7081ad6265SDimitry Andric DeclarationFragments::parseFragmentKindFromString(StringRef S) {
7181ad6265SDimitry Andric   return llvm::StringSwitch<FragmentKind>(S)
7281ad6265SDimitry Andric       .Case("keyword", DeclarationFragments::FragmentKind::Keyword)
7381ad6265SDimitry Andric       .Case("attribute", DeclarationFragments::FragmentKind::Attribute)
7481ad6265SDimitry Andric       .Case("number", DeclarationFragments::FragmentKind::NumberLiteral)
7581ad6265SDimitry Andric       .Case("string", DeclarationFragments::FragmentKind::StringLiteral)
7681ad6265SDimitry Andric       .Case("identifier", DeclarationFragments::FragmentKind::Identifier)
7781ad6265SDimitry Andric       .Case("typeIdentifier",
7881ad6265SDimitry Andric             DeclarationFragments::FragmentKind::TypeIdentifier)
7981ad6265SDimitry Andric       .Case("genericParameter",
8081ad6265SDimitry Andric             DeclarationFragments::FragmentKind::GenericParameter)
8181ad6265SDimitry Andric       .Case("internalParam", DeclarationFragments::FragmentKind::InternalParam)
8281ad6265SDimitry Andric       .Case("externalParam", DeclarationFragments::FragmentKind::ExternalParam)
8381ad6265SDimitry Andric       .Case("text", DeclarationFragments::FragmentKind::Text)
8481ad6265SDimitry Andric       .Default(DeclarationFragments::FragmentKind::None);
8581ad6265SDimitry Andric }
8681ad6265SDimitry Andric 
8781ad6265SDimitry Andric // NNS stores C++ nested name specifiers, which are prefixes to qualified names.
8881ad6265SDimitry Andric // Build declaration fragments for NNS recursively so that we have the USR for
8981ad6265SDimitry Andric // every part in a qualified name, and also leaves the actual underlying type
9081ad6265SDimitry Andric // cleaner for its own fragment.
9181ad6265SDimitry Andric DeclarationFragments
9281ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS,
9381ad6265SDimitry Andric                                                 ASTContext &Context,
9481ad6265SDimitry Andric                                                 DeclarationFragments &After) {
9581ad6265SDimitry Andric   DeclarationFragments Fragments;
9681ad6265SDimitry Andric   if (NNS->getPrefix())
9781ad6265SDimitry Andric     Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After));
9881ad6265SDimitry Andric 
9981ad6265SDimitry Andric   switch (NNS->getKind()) {
10081ad6265SDimitry Andric   case NestedNameSpecifier::Identifier:
10181ad6265SDimitry Andric     Fragments.append(NNS->getAsIdentifier()->getName(),
10281ad6265SDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
10381ad6265SDimitry Andric     break;
10481ad6265SDimitry Andric 
10581ad6265SDimitry Andric   case NestedNameSpecifier::Namespace: {
10681ad6265SDimitry Andric     const NamespaceDecl *NS = NNS->getAsNamespace();
10781ad6265SDimitry Andric     if (NS->isAnonymousNamespace())
10881ad6265SDimitry Andric       return Fragments;
10981ad6265SDimitry Andric     SmallString<128> USR;
11081ad6265SDimitry Andric     index::generateUSRForDecl(NS, USR);
11181ad6265SDimitry Andric     Fragments.append(NS->getName(),
112bdd1243dSDimitry Andric                      DeclarationFragments::FragmentKind::Identifier, USR, NS);
11381ad6265SDimitry Andric     break;
11481ad6265SDimitry Andric   }
11581ad6265SDimitry Andric 
11681ad6265SDimitry Andric   case NestedNameSpecifier::NamespaceAlias: {
11781ad6265SDimitry Andric     const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias();
11881ad6265SDimitry Andric     SmallString<128> USR;
11981ad6265SDimitry Andric     index::generateUSRForDecl(Alias, USR);
12081ad6265SDimitry Andric     Fragments.append(Alias->getName(),
121bdd1243dSDimitry Andric                      DeclarationFragments::FragmentKind::Identifier, USR,
122bdd1243dSDimitry Andric                      Alias);
12381ad6265SDimitry Andric     break;
12481ad6265SDimitry Andric   }
12581ad6265SDimitry Andric 
12681ad6265SDimitry Andric   case NestedNameSpecifier::Global:
12781ad6265SDimitry Andric     // The global specifier `::` at the beginning. No stored value.
12881ad6265SDimitry Andric     break;
12981ad6265SDimitry Andric 
13081ad6265SDimitry Andric   case NestedNameSpecifier::Super:
13181ad6265SDimitry Andric     // Microsoft's `__super` specifier.
13281ad6265SDimitry Andric     Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword);
13381ad6265SDimitry Andric     break;
13481ad6265SDimitry Andric 
13581ad6265SDimitry Andric   case NestedNameSpecifier::TypeSpecWithTemplate:
13681ad6265SDimitry Andric     // A type prefixed by the `template` keyword.
13781ad6265SDimitry Andric     Fragments.append("template", DeclarationFragments::FragmentKind::Keyword);
13881ad6265SDimitry Andric     Fragments.appendSpace();
13981ad6265SDimitry Andric     // Fallthrough after adding the keyword to handle the actual type.
140bdd1243dSDimitry Andric     [[fallthrough]];
14181ad6265SDimitry Andric 
14281ad6265SDimitry Andric   case NestedNameSpecifier::TypeSpec: {
14381ad6265SDimitry Andric     const Type *T = NNS->getAsType();
14481ad6265SDimitry Andric     // FIXME: Handle C++ template specialization type
14581ad6265SDimitry Andric     Fragments.append(getFragmentsForType(T, Context, After));
14681ad6265SDimitry Andric     break;
14781ad6265SDimitry Andric   }
14881ad6265SDimitry Andric   }
14981ad6265SDimitry Andric 
15081ad6265SDimitry Andric   // Add the separator text `::` for this segment.
15181ad6265SDimitry Andric   return Fragments.append("::", DeclarationFragments::FragmentKind::Text);
15281ad6265SDimitry Andric }
15381ad6265SDimitry Andric 
15481ad6265SDimitry Andric // Recursively build the declaration fragments for an underlying `Type` with
15581ad6265SDimitry Andric // qualifiers removed.
15681ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
15781ad6265SDimitry Andric     const Type *T, ASTContext &Context, DeclarationFragments &After) {
15881ad6265SDimitry Andric   assert(T && "invalid type");
15981ad6265SDimitry Andric 
16081ad6265SDimitry Andric   DeclarationFragments Fragments;
16181ad6265SDimitry Andric 
16281ad6265SDimitry Andric   // Declaration fragments of a pointer type is the declaration fragments of
163*06c3fb27SDimitry Andric   // the pointee type followed by a `*`,
164*06c3fb27SDimitry Andric   if (T->isPointerType())
16581ad6265SDimitry Andric     return Fragments
16681ad6265SDimitry Andric         .append(getFragmentsForType(T->getPointeeType(), Context, After))
16781ad6265SDimitry Andric         .append(" *", DeclarationFragments::FragmentKind::Text);
168*06c3fb27SDimitry Andric 
169*06c3fb27SDimitry Andric   // For Objective-C `id` and `Class` pointers
170*06c3fb27SDimitry Andric   // we do not spell out the `*`.
171*06c3fb27SDimitry Andric   if (T->isObjCObjectPointerType() &&
172*06c3fb27SDimitry Andric       !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) {
173*06c3fb27SDimitry Andric 
174*06c3fb27SDimitry Andric     Fragments.append(getFragmentsForType(T->getPointeeType(), Context, After));
175*06c3fb27SDimitry Andric 
176*06c3fb27SDimitry Andric     // id<protocol> is an qualified id type
177*06c3fb27SDimitry Andric     // id<protocol>* is not an qualified id type
178*06c3fb27SDimitry Andric     if (!T->getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) {
179*06c3fb27SDimitry Andric       Fragments.append(" *", DeclarationFragments::FragmentKind::Text);
180*06c3fb27SDimitry Andric     }
181*06c3fb27SDimitry Andric 
182*06c3fb27SDimitry Andric     return Fragments;
18381ad6265SDimitry Andric   }
18481ad6265SDimitry Andric 
18581ad6265SDimitry Andric   // Declaration fragments of a lvalue reference type is the declaration
18681ad6265SDimitry Andric   // fragments of the underlying type followed by a `&`.
18781ad6265SDimitry Andric   if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T))
18881ad6265SDimitry Andric     return Fragments
18981ad6265SDimitry Andric         .append(
19081ad6265SDimitry Andric             getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After))
19181ad6265SDimitry Andric         .append(" &", DeclarationFragments::FragmentKind::Text);
19281ad6265SDimitry Andric 
19381ad6265SDimitry Andric   // Declaration fragments of a rvalue reference type is the declaration
19481ad6265SDimitry Andric   // fragments of the underlying type followed by a `&&`.
19581ad6265SDimitry Andric   if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T))
19681ad6265SDimitry Andric     return Fragments
19781ad6265SDimitry Andric         .append(
19881ad6265SDimitry Andric             getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After))
19981ad6265SDimitry Andric         .append(" &&", DeclarationFragments::FragmentKind::Text);
20081ad6265SDimitry Andric 
20181ad6265SDimitry Andric   // Declaration fragments of an array-typed variable have two parts:
20281ad6265SDimitry Andric   // 1. the element type of the array that appears before the variable name;
20381ad6265SDimitry Andric   // 2. array brackets `[(0-9)?]` that appear after the variable name.
20481ad6265SDimitry Andric   if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) {
20581ad6265SDimitry Andric     // Build the "after" part first because the inner element type might also
20681ad6265SDimitry Andric     // be an array-type. For example `int matrix[3][4]` which has a type of
20781ad6265SDimitry Andric     // "(array 3 of (array 4 of ints))."
20881ad6265SDimitry Andric     // Push the array size part first to make sure they are in the right order.
20981ad6265SDimitry Andric     After.append("[", DeclarationFragments::FragmentKind::Text);
21081ad6265SDimitry Andric 
21181ad6265SDimitry Andric     switch (AT->getSizeModifier()) {
21281ad6265SDimitry Andric     case ArrayType::Normal:
21381ad6265SDimitry Andric       break;
21481ad6265SDimitry Andric     case ArrayType::Static:
21581ad6265SDimitry Andric       Fragments.append("static", DeclarationFragments::FragmentKind::Keyword);
21681ad6265SDimitry Andric       break;
21781ad6265SDimitry Andric     case ArrayType::Star:
21881ad6265SDimitry Andric       Fragments.append("*", DeclarationFragments::FragmentKind::Text);
21981ad6265SDimitry Andric       break;
22081ad6265SDimitry Andric     }
22181ad6265SDimitry Andric 
22281ad6265SDimitry Andric     if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
22381ad6265SDimitry Andric       // FIXME: right now this would evaluate any expressions/macros written in
22481ad6265SDimitry Andric       // the original source to concrete values. For example
22581ad6265SDimitry Andric       // `int nums[MAX]` -> `int nums[100]`
22681ad6265SDimitry Andric       // `char *str[5 + 1]` -> `char *str[6]`
22781ad6265SDimitry Andric       SmallString<128> Size;
22881ad6265SDimitry Andric       CAT->getSize().toStringUnsigned(Size);
22981ad6265SDimitry Andric       After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral);
23081ad6265SDimitry Andric     }
23181ad6265SDimitry Andric 
23281ad6265SDimitry Andric     After.append("]", DeclarationFragments::FragmentKind::Text);
23381ad6265SDimitry Andric 
23481ad6265SDimitry Andric     return Fragments.append(
23581ad6265SDimitry Andric         getFragmentsForType(AT->getElementType(), Context, After));
23681ad6265SDimitry Andric   }
23781ad6265SDimitry Andric 
23881ad6265SDimitry Andric   // An ElaboratedType is a sugar for types that are referred to using an
23981ad6265SDimitry Andric   // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a
24081ad6265SDimitry Andric   // qualified name, e.g., `N::M::type`, or both.
24181ad6265SDimitry Andric   if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) {
24281ad6265SDimitry Andric     ElaboratedTypeKeyword Keyword = ET->getKeyword();
24381ad6265SDimitry Andric     if (Keyword != ETK_None) {
24481ad6265SDimitry Andric       Fragments
24581ad6265SDimitry Andric           .append(ElaboratedType::getKeywordName(Keyword),
24681ad6265SDimitry Andric                   DeclarationFragments::FragmentKind::Keyword)
24781ad6265SDimitry Andric           .appendSpace();
24881ad6265SDimitry Andric     }
24981ad6265SDimitry Andric 
25081ad6265SDimitry Andric     if (const NestedNameSpecifier *NNS = ET->getQualifier())
25181ad6265SDimitry Andric       Fragments.append(getFragmentsForNNS(NNS, Context, After));
25281ad6265SDimitry Andric 
25381ad6265SDimitry Andric     // After handling the elaborated keyword or qualified name, build
25481ad6265SDimitry Andric     // declaration fragments for the desugared underlying type.
25581ad6265SDimitry Andric     return Fragments.append(getFragmentsForType(ET->desugar(), Context, After));
25681ad6265SDimitry Andric   }
25781ad6265SDimitry Andric 
25881ad6265SDimitry Andric   // If the type is a typedefed type, get the underlying TypedefNameDecl for a
25981ad6265SDimitry Andric   // direct reference to the typedef instead of the wrapped type.
260*06c3fb27SDimitry Andric 
261*06c3fb27SDimitry Andric   // 'id' type is a typedef for an ObjCObjectPointerType
262*06c3fb27SDimitry Andric   //  we treat it as a typedef
26381ad6265SDimitry Andric   if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) {
26481ad6265SDimitry Andric     const TypedefNameDecl *Decl = TypedefTy->getDecl();
265bdd1243dSDimitry Andric     TypedefUnderlyingTypeResolver TypedefResolver(Context);
266bdd1243dSDimitry Andric     std::string USR = TypedefResolver.getUSRForType(QualType(T, 0));
267*06c3fb27SDimitry Andric 
268*06c3fb27SDimitry Andric     if (T->isObjCIdType()) {
269*06c3fb27SDimitry Andric       return Fragments.append(Decl->getName(),
270*06c3fb27SDimitry Andric                               DeclarationFragments::FragmentKind::Keyword);
271*06c3fb27SDimitry Andric     }
272*06c3fb27SDimitry Andric 
273bdd1243dSDimitry Andric     return Fragments.append(
274bdd1243dSDimitry Andric         Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier,
275bdd1243dSDimitry Andric         USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0)));
27681ad6265SDimitry Andric   }
27781ad6265SDimitry Andric 
278*06c3fb27SDimitry Andric   // Everything we care about has been handled now, reduce to the canonical
279*06c3fb27SDimitry Andric   // unqualified base type.
280*06c3fb27SDimitry Andric   QualType Base = T->getCanonicalTypeUnqualified();
281*06c3fb27SDimitry Andric 
28281ad6265SDimitry Andric   // If the base type is a TagType (struct/interface/union/class/enum), let's
28381ad6265SDimitry Andric   // get the underlying Decl for better names and USRs.
28481ad6265SDimitry Andric   if (const TagType *TagTy = dyn_cast<TagType>(Base)) {
28581ad6265SDimitry Andric     const TagDecl *Decl = TagTy->getDecl();
28681ad6265SDimitry Andric     // Anonymous decl, skip this fragment.
28781ad6265SDimitry Andric     if (Decl->getName().empty())
28881ad6265SDimitry Andric       return Fragments;
28981ad6265SDimitry Andric     SmallString<128> TagUSR;
29081ad6265SDimitry Andric     clang::index::generateUSRForDecl(Decl, TagUSR);
29181ad6265SDimitry Andric     return Fragments.append(Decl->getName(),
29281ad6265SDimitry Andric                             DeclarationFragments::FragmentKind::TypeIdentifier,
293bdd1243dSDimitry Andric                             TagUSR, Decl);
29481ad6265SDimitry Andric   }
29581ad6265SDimitry Andric 
29681ad6265SDimitry Andric   // If the base type is an ObjCInterfaceType, use the underlying
29781ad6265SDimitry Andric   // ObjCInterfaceDecl for the true USR.
29881ad6265SDimitry Andric   if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) {
29981ad6265SDimitry Andric     const auto *Decl = ObjCIT->getDecl();
30081ad6265SDimitry Andric     SmallString<128> USR;
30181ad6265SDimitry Andric     index::generateUSRForDecl(Decl, USR);
30281ad6265SDimitry Andric     return Fragments.append(Decl->getName(),
30381ad6265SDimitry Andric                             DeclarationFragments::FragmentKind::TypeIdentifier,
304bdd1243dSDimitry Andric                             USR, Decl);
30581ad6265SDimitry Andric   }
30681ad6265SDimitry Andric 
30781ad6265SDimitry Andric   // Default fragment builder for other kinds of types (BuiltinType etc.)
30881ad6265SDimitry Andric   SmallString<128> USR;
30981ad6265SDimitry Andric   clang::index::generateUSRForType(Base, Context, USR);
31081ad6265SDimitry Andric   Fragments.append(Base.getAsString(),
31181ad6265SDimitry Andric                    DeclarationFragments::FragmentKind::TypeIdentifier, USR);
31281ad6265SDimitry Andric 
31381ad6265SDimitry Andric   return Fragments;
31481ad6265SDimitry Andric }
31581ad6265SDimitry Andric 
31681ad6265SDimitry Andric DeclarationFragments
31781ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) {
31881ad6265SDimitry Andric   DeclarationFragments Fragments;
31981ad6265SDimitry Andric   if (Quals.hasConst())
32081ad6265SDimitry Andric     Fragments.append("const", DeclarationFragments::FragmentKind::Keyword);
32181ad6265SDimitry Andric   if (Quals.hasVolatile())
32281ad6265SDimitry Andric     Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword);
32381ad6265SDimitry Andric   if (Quals.hasRestrict())
32481ad6265SDimitry Andric     Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword);
32581ad6265SDimitry Andric 
32681ad6265SDimitry Andric   return Fragments;
32781ad6265SDimitry Andric }
32881ad6265SDimitry Andric 
32981ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
33081ad6265SDimitry Andric     const QualType QT, ASTContext &Context, DeclarationFragments &After) {
33181ad6265SDimitry Andric   assert(!QT.isNull() && "invalid type");
33281ad6265SDimitry Andric 
33381ad6265SDimitry Andric   if (const ParenType *PT = dyn_cast<ParenType>(QT)) {
33481ad6265SDimitry Andric     After.append(")", DeclarationFragments::FragmentKind::Text);
33581ad6265SDimitry Andric     return getFragmentsForType(PT->getInnerType(), Context, After)
33681ad6265SDimitry Andric         .append("(", DeclarationFragments::FragmentKind::Text);
33781ad6265SDimitry Andric   }
33881ad6265SDimitry Andric 
33981ad6265SDimitry Andric   const SplitQualType SQT = QT.split();
34081ad6265SDimitry Andric   DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals),
34181ad6265SDimitry Andric                        TypeFragments =
34281ad6265SDimitry Andric                            getFragmentsForType(SQT.Ty, Context, After);
34381ad6265SDimitry Andric   if (QualsFragments.getFragments().empty())
34481ad6265SDimitry Andric     return TypeFragments;
34581ad6265SDimitry Andric 
34681ad6265SDimitry Andric   // Use east qualifier for pointer types
34781ad6265SDimitry Andric   // For example:
34881ad6265SDimitry Andric   // ```
34981ad6265SDimitry Andric   // int *   const
35081ad6265SDimitry Andric   // ^----   ^----
35181ad6265SDimitry Andric   //  type    qualifier
35281ad6265SDimitry Andric   // ^-----------------
35381ad6265SDimitry Andric   //  const pointer to int
35481ad6265SDimitry Andric   // ```
35581ad6265SDimitry Andric   // should not be reconstructed as
35681ad6265SDimitry Andric   // ```
35781ad6265SDimitry Andric   // const       int       *
35881ad6265SDimitry Andric   // ^----       ^--
35981ad6265SDimitry Andric   //  qualifier   type
36081ad6265SDimitry Andric   // ^----------------     ^
36181ad6265SDimitry Andric   //  pointer to const int
36281ad6265SDimitry Andric   // ```
36381ad6265SDimitry Andric   if (SQT.Ty->isAnyPointerType())
36481ad6265SDimitry Andric     return TypeFragments.appendSpace().append(std::move(QualsFragments));
36581ad6265SDimitry Andric 
36681ad6265SDimitry Andric   return QualsFragments.appendSpace().append(std::move(TypeFragments));
36781ad6265SDimitry Andric }
36881ad6265SDimitry Andric 
36981ad6265SDimitry Andric DeclarationFragments
37081ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
37181ad6265SDimitry Andric   DeclarationFragments Fragments;
37281ad6265SDimitry Andric   StorageClass SC = Var->getStorageClass();
37381ad6265SDimitry Andric   if (SC != SC_None)
37481ad6265SDimitry Andric     Fragments
37581ad6265SDimitry Andric         .append(VarDecl::getStorageClassSpecifierString(SC),
37681ad6265SDimitry Andric                 DeclarationFragments::FragmentKind::Keyword)
37781ad6265SDimitry Andric         .appendSpace();
37881ad6265SDimitry Andric   QualType T =
37981ad6265SDimitry Andric       Var->getTypeSourceInfo()
38081ad6265SDimitry Andric           ? Var->getTypeSourceInfo()->getType()
38181ad6265SDimitry Andric           : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType());
38281ad6265SDimitry Andric 
38381ad6265SDimitry Andric   // Capture potential fragments that needs to be placed after the variable name
38481ad6265SDimitry Andric   // ```
38581ad6265SDimitry Andric   // int nums[5];
38681ad6265SDimitry Andric   // char (*ptr_to_array)[6];
38781ad6265SDimitry Andric   // ```
38881ad6265SDimitry Andric   DeclarationFragments After;
38981ad6265SDimitry Andric   return Fragments.append(getFragmentsForType(T, Var->getASTContext(), After))
39081ad6265SDimitry Andric       .appendSpace()
39181ad6265SDimitry Andric       .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
39281ad6265SDimitry Andric       .append(std::move(After));
39381ad6265SDimitry Andric }
39481ad6265SDimitry Andric 
39581ad6265SDimitry Andric DeclarationFragments
39681ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) {
39781ad6265SDimitry Andric   DeclarationFragments Fragments, After;
39881ad6265SDimitry Andric 
39981ad6265SDimitry Andric   QualType T = Param->getTypeSourceInfo()
40081ad6265SDimitry Andric                    ? Param->getTypeSourceInfo()->getType()
40181ad6265SDimitry Andric                    : Param->getASTContext().getUnqualifiedObjCPointerType(
40281ad6265SDimitry Andric                          Param->getType());
40381ad6265SDimitry Andric 
40481ad6265SDimitry Andric   DeclarationFragments TypeFragments =
40581ad6265SDimitry Andric       getFragmentsForType(T, Param->getASTContext(), After);
40681ad6265SDimitry Andric 
40781ad6265SDimitry Andric   if (Param->isObjCMethodParameter())
40881ad6265SDimitry Andric     Fragments.append("(", DeclarationFragments::FragmentKind::Text)
40981ad6265SDimitry Andric         .append(std::move(TypeFragments))
41081ad6265SDimitry Andric         .append(") ", DeclarationFragments::FragmentKind::Text);
41181ad6265SDimitry Andric   else
41281ad6265SDimitry Andric     Fragments.append(std::move(TypeFragments)).appendSpace();
41381ad6265SDimitry Andric 
41481ad6265SDimitry Andric   return Fragments
41581ad6265SDimitry Andric       .append(Param->getName(),
41681ad6265SDimitry Andric               DeclarationFragments::FragmentKind::InternalParam)
41781ad6265SDimitry Andric       .append(std::move(After));
41881ad6265SDimitry Andric }
41981ad6265SDimitry Andric 
42081ad6265SDimitry Andric DeclarationFragments
42181ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
42281ad6265SDimitry Andric   DeclarationFragments Fragments;
42381ad6265SDimitry Andric   // FIXME: Handle template specialization
42481ad6265SDimitry Andric   switch (Func->getStorageClass()) {
42581ad6265SDimitry Andric   case SC_None:
42681ad6265SDimitry Andric   case SC_PrivateExtern:
42781ad6265SDimitry Andric     break;
42881ad6265SDimitry Andric   case SC_Extern:
42981ad6265SDimitry Andric     Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword)
43081ad6265SDimitry Andric         .appendSpace();
43181ad6265SDimitry Andric     break;
43281ad6265SDimitry Andric   case SC_Static:
43381ad6265SDimitry Andric     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
43481ad6265SDimitry Andric         .appendSpace();
43581ad6265SDimitry Andric     break;
43681ad6265SDimitry Andric   case SC_Auto:
43781ad6265SDimitry Andric   case SC_Register:
43881ad6265SDimitry Andric     llvm_unreachable("invalid for functions");
43981ad6265SDimitry Andric   }
44081ad6265SDimitry Andric   // FIXME: Handle C++ function specifiers: constexpr, consteval, explicit, etc.
44181ad6265SDimitry Andric 
44281ad6265SDimitry Andric   // FIXME: Is `after` actually needed here?
44381ad6265SDimitry Andric   DeclarationFragments After;
44481ad6265SDimitry Andric   Fragments
44581ad6265SDimitry Andric       .append(getFragmentsForType(Func->getReturnType(), Func->getASTContext(),
44681ad6265SDimitry Andric                                   After))
44781ad6265SDimitry Andric       .appendSpace()
44881ad6265SDimitry Andric       .append(Func->getName(), DeclarationFragments::FragmentKind::Identifier)
44981ad6265SDimitry Andric       .append(std::move(After));
45081ad6265SDimitry Andric 
45181ad6265SDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
45281ad6265SDimitry Andric   for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) {
45381ad6265SDimitry Andric     if (i)
45481ad6265SDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
45581ad6265SDimitry Andric     Fragments.append(getFragmentsForParam(Func->getParamDecl(i)));
45681ad6265SDimitry Andric   }
45781ad6265SDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
45881ad6265SDimitry Andric 
45981ad6265SDimitry Andric   // FIXME: Handle exception specifiers: throw, noexcept
460*06c3fb27SDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
46181ad6265SDimitry Andric }
46281ad6265SDimitry Andric 
46381ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant(
46481ad6265SDimitry Andric     const EnumConstantDecl *EnumConstDecl) {
46581ad6265SDimitry Andric   DeclarationFragments Fragments;
46681ad6265SDimitry Andric   return Fragments.append(EnumConstDecl->getName(),
46781ad6265SDimitry Andric                           DeclarationFragments::FragmentKind::Identifier);
46881ad6265SDimitry Andric }
46981ad6265SDimitry Andric 
47081ad6265SDimitry Andric DeclarationFragments
47181ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {
47281ad6265SDimitry Andric   if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl())
47381ad6265SDimitry Andric     return getFragmentsForTypedef(TypedefNameDecl);
47481ad6265SDimitry Andric 
47581ad6265SDimitry Andric   DeclarationFragments Fragments, After;
47681ad6265SDimitry Andric   Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword);
47781ad6265SDimitry Andric 
47881ad6265SDimitry Andric   if (!EnumDecl->getName().empty())
47981ad6265SDimitry Andric     Fragments.appendSpace().append(
48081ad6265SDimitry Andric         EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier);
48181ad6265SDimitry Andric 
48281ad6265SDimitry Andric   QualType IntegerType = EnumDecl->getIntegerType();
48381ad6265SDimitry Andric   if (!IntegerType.isNull())
48481ad6265SDimitry Andric     Fragments.append(": ", DeclarationFragments::FragmentKind::Text)
48581ad6265SDimitry Andric         .append(
48681ad6265SDimitry Andric             getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))
48781ad6265SDimitry Andric         .append(std::move(After));
48881ad6265SDimitry Andric 
489*06c3fb27SDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
49081ad6265SDimitry Andric }
49181ad6265SDimitry Andric 
49281ad6265SDimitry Andric DeclarationFragments
49381ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) {
49481ad6265SDimitry Andric   DeclarationFragments After;
49581ad6265SDimitry Andric   return getFragmentsForType(Field->getType(), Field->getASTContext(), After)
49681ad6265SDimitry Andric       .appendSpace()
49781ad6265SDimitry Andric       .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)
49881ad6265SDimitry Andric       .append(std::move(After));
49981ad6265SDimitry Andric }
50081ad6265SDimitry Andric 
50181ad6265SDimitry Andric DeclarationFragments
50281ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForStruct(const RecordDecl *Record) {
50381ad6265SDimitry Andric   if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
50481ad6265SDimitry Andric     return getFragmentsForTypedef(TypedefNameDecl);
50581ad6265SDimitry Andric 
50681ad6265SDimitry Andric   DeclarationFragments Fragments;
50781ad6265SDimitry Andric   Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);
50881ad6265SDimitry Andric 
50981ad6265SDimitry Andric   if (!Record->getName().empty())
51081ad6265SDimitry Andric     Fragments.appendSpace().append(
51181ad6265SDimitry Andric         Record->getName(), DeclarationFragments::FragmentKind::Identifier);
512*06c3fb27SDimitry Andric 
513*06c3fb27SDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
51481ad6265SDimitry Andric }
51581ad6265SDimitry Andric 
51681ad6265SDimitry Andric DeclarationFragments
51781ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name,
51881ad6265SDimitry Andric                                                   const MacroDirective *MD) {
51981ad6265SDimitry Andric   DeclarationFragments Fragments;
52081ad6265SDimitry Andric   Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword)
52181ad6265SDimitry Andric       .appendSpace();
52281ad6265SDimitry Andric   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
52381ad6265SDimitry Andric 
52481ad6265SDimitry Andric   auto *MI = MD->getMacroInfo();
52581ad6265SDimitry Andric 
52681ad6265SDimitry Andric   if (MI->isFunctionLike()) {
52781ad6265SDimitry Andric     Fragments.append("(", DeclarationFragments::FragmentKind::Text);
52881ad6265SDimitry Andric     unsigned numParameters = MI->getNumParams();
52981ad6265SDimitry Andric     if (MI->isC99Varargs())
53081ad6265SDimitry Andric       --numParameters;
53181ad6265SDimitry Andric     for (unsigned i = 0; i < numParameters; ++i) {
53281ad6265SDimitry Andric       if (i)
53381ad6265SDimitry Andric         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
53481ad6265SDimitry Andric       Fragments.append(MI->params()[i]->getName(),
53581ad6265SDimitry Andric                        DeclarationFragments::FragmentKind::InternalParam);
53681ad6265SDimitry Andric     }
53781ad6265SDimitry Andric     if (MI->isVariadic()) {
53881ad6265SDimitry Andric       if (numParameters && MI->isC99Varargs())
53981ad6265SDimitry Andric         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
54081ad6265SDimitry Andric       Fragments.append("...", DeclarationFragments::FragmentKind::Text);
54181ad6265SDimitry Andric     }
54281ad6265SDimitry Andric     Fragments.append(")", DeclarationFragments::FragmentKind::Text);
54381ad6265SDimitry Andric   }
54481ad6265SDimitry Andric   return Fragments;
54581ad6265SDimitry Andric }
54681ad6265SDimitry Andric 
54781ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory(
54881ad6265SDimitry Andric     const ObjCCategoryDecl *Category) {
54981ad6265SDimitry Andric   DeclarationFragments Fragments;
55081ad6265SDimitry Andric 
551bdd1243dSDimitry Andric   auto *Interface = Category->getClassInterface();
55281ad6265SDimitry Andric   SmallString<128> InterfaceUSR;
553bdd1243dSDimitry Andric   index::generateUSRForDecl(Interface, InterfaceUSR);
55481ad6265SDimitry Andric 
55581ad6265SDimitry Andric   Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
55681ad6265SDimitry Andric       .appendSpace()
55781ad6265SDimitry Andric       .append(Category->getClassInterface()->getName(),
558bdd1243dSDimitry Andric               DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR,
559bdd1243dSDimitry Andric               Interface)
56081ad6265SDimitry Andric       .append(" (", DeclarationFragments::FragmentKind::Text)
56181ad6265SDimitry Andric       .append(Category->getName(),
56281ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Identifier)
56381ad6265SDimitry Andric       .append(")", DeclarationFragments::FragmentKind::Text);
56481ad6265SDimitry Andric 
56581ad6265SDimitry Andric   return Fragments;
56681ad6265SDimitry Andric }
56781ad6265SDimitry Andric 
56881ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface(
56981ad6265SDimitry Andric     const ObjCInterfaceDecl *Interface) {
57081ad6265SDimitry Andric   DeclarationFragments Fragments;
57181ad6265SDimitry Andric   // Build the base of the Objective-C interface declaration.
57281ad6265SDimitry Andric   Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
57381ad6265SDimitry Andric       .appendSpace()
57481ad6265SDimitry Andric       .append(Interface->getName(),
57581ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Identifier);
57681ad6265SDimitry Andric 
57781ad6265SDimitry Andric   // Build the inheritance part of the declaration.
57881ad6265SDimitry Andric   if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) {
57981ad6265SDimitry Andric     SmallString<128> SuperUSR;
58081ad6265SDimitry Andric     index::generateUSRForDecl(SuperClass, SuperUSR);
58181ad6265SDimitry Andric     Fragments.append(" : ", DeclarationFragments::FragmentKind::Text)
58281ad6265SDimitry Andric         .append(SuperClass->getName(),
583bdd1243dSDimitry Andric                 DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR,
584bdd1243dSDimitry Andric                 SuperClass);
58581ad6265SDimitry Andric   }
58681ad6265SDimitry Andric 
58781ad6265SDimitry Andric   return Fragments;
58881ad6265SDimitry Andric }
58981ad6265SDimitry Andric 
59081ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod(
59181ad6265SDimitry Andric     const ObjCMethodDecl *Method) {
59281ad6265SDimitry Andric   DeclarationFragments Fragments, After;
59381ad6265SDimitry Andric   // Build the instance/class method indicator.
59481ad6265SDimitry Andric   if (Method->isClassMethod())
59581ad6265SDimitry Andric     Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
59681ad6265SDimitry Andric   else if (Method->isInstanceMethod())
59781ad6265SDimitry Andric     Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
59881ad6265SDimitry Andric 
59981ad6265SDimitry Andric   // Build the return type.
60081ad6265SDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text)
60181ad6265SDimitry Andric       .append(getFragmentsForType(Method->getReturnType(),
60281ad6265SDimitry Andric                                   Method->getASTContext(), After))
60381ad6265SDimitry Andric       .append(std::move(After))
60481ad6265SDimitry Andric       .append(")", DeclarationFragments::FragmentKind::Text);
60581ad6265SDimitry Andric 
60681ad6265SDimitry Andric   // Build the selector part.
60781ad6265SDimitry Andric   Selector Selector = Method->getSelector();
60881ad6265SDimitry Andric   if (Selector.getNumArgs() == 0)
60981ad6265SDimitry Andric     // For Objective-C methods that don't take arguments, the first (and only)
61081ad6265SDimitry Andric     // slot of the selector is the method name.
61181ad6265SDimitry Andric     Fragments.appendSpace().append(
61281ad6265SDimitry Andric         Selector.getNameForSlot(0),
61381ad6265SDimitry Andric         DeclarationFragments::FragmentKind::Identifier);
61481ad6265SDimitry Andric 
61581ad6265SDimitry Andric   // For Objective-C methods that take arguments, build the selector slots.
61681ad6265SDimitry Andric   for (unsigned i = 0, end = Method->param_size(); i != end; ++i) {
61781ad6265SDimitry Andric     // Objective-C method selector parts are considered as identifiers instead
61881ad6265SDimitry Andric     // of "external parameters" as in Swift. This is because Objective-C method
61981ad6265SDimitry Andric     // symbols are referenced with the entire selector, instead of just the
62081ad6265SDimitry Andric     // method name in Swift.
62181ad6265SDimitry Andric     SmallString<32> ParamID(Selector.getNameForSlot(i));
62281ad6265SDimitry Andric     ParamID.append(":");
62381ad6265SDimitry Andric     Fragments.appendSpace().append(
62481ad6265SDimitry Andric         ParamID, DeclarationFragments::FragmentKind::Identifier);
62581ad6265SDimitry Andric 
62681ad6265SDimitry Andric     // Build the internal parameter.
62781ad6265SDimitry Andric     const ParmVarDecl *Param = Method->getParamDecl(i);
62881ad6265SDimitry Andric     Fragments.append(getFragmentsForParam(Param));
62981ad6265SDimitry Andric   }
63081ad6265SDimitry Andric 
63181ad6265SDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
63281ad6265SDimitry Andric }
63381ad6265SDimitry Andric 
63481ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
63581ad6265SDimitry Andric     const ObjCPropertyDecl *Property) {
63681ad6265SDimitry Andric   DeclarationFragments Fragments, After;
63781ad6265SDimitry Andric 
63881ad6265SDimitry Andric   // Build the Objective-C property keyword.
63981ad6265SDimitry Andric   Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword);
64081ad6265SDimitry Andric 
641*06c3fb27SDimitry Andric   const auto Attributes = Property->getPropertyAttributesAsWritten();
64281ad6265SDimitry Andric   // Build the attributes if there is any associated with the property.
64381ad6265SDimitry Andric   if (Attributes != ObjCPropertyAttribute::kind_noattr) {
64481ad6265SDimitry Andric     // No leading comma for the first attribute.
64581ad6265SDimitry Andric     bool First = true;
64681ad6265SDimitry Andric     Fragments.append(" (", DeclarationFragments::FragmentKind::Text);
64781ad6265SDimitry Andric     // Helper function to render the attribute.
64881ad6265SDimitry Andric     auto RenderAttribute =
64981ad6265SDimitry Andric         [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling,
65081ad6265SDimitry Andric             StringRef Arg = "",
65181ad6265SDimitry Andric             DeclarationFragments::FragmentKind ArgKind =
65281ad6265SDimitry Andric                 DeclarationFragments::FragmentKind::Identifier) {
65381ad6265SDimitry Andric           // Check if the `Kind` attribute is set for this property.
65481ad6265SDimitry Andric           if ((Attributes & Kind) && !Spelling.empty()) {
65581ad6265SDimitry Andric             // Add a leading comma if this is not the first attribute rendered.
65681ad6265SDimitry Andric             if (!First)
65781ad6265SDimitry Andric               Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
65881ad6265SDimitry Andric             // Render the spelling of this attribute `Kind` as a keyword.
65981ad6265SDimitry Andric             Fragments.append(Spelling,
66081ad6265SDimitry Andric                              DeclarationFragments::FragmentKind::Keyword);
66181ad6265SDimitry Andric             // If this attribute takes in arguments (e.g. `getter=getterName`),
66281ad6265SDimitry Andric             // render the arguments.
66381ad6265SDimitry Andric             if (!Arg.empty())
66481ad6265SDimitry Andric               Fragments.append("=", DeclarationFragments::FragmentKind::Text)
66581ad6265SDimitry Andric                   .append(Arg, ArgKind);
66681ad6265SDimitry Andric             First = false;
66781ad6265SDimitry Andric           }
66881ad6265SDimitry Andric         };
66981ad6265SDimitry Andric 
67081ad6265SDimitry Andric     // Go through all possible Objective-C property attributes and render set
67181ad6265SDimitry Andric     // ones.
67281ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_class, "class");
67381ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct");
67481ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic");
67581ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic");
67681ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign");
67781ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain");
67881ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong");
67981ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy");
68081ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak");
68181ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained,
68281ad6265SDimitry Andric                     "unsafe_unretained");
68381ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite");
68481ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly");
68581ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter",
68681ad6265SDimitry Andric                     Property->getGetterName().getAsString());
68781ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter",
68881ad6265SDimitry Andric                     Property->getSetterName().getAsString());
68981ad6265SDimitry Andric 
69081ad6265SDimitry Andric     // Render nullability attributes.
69181ad6265SDimitry Andric     if (Attributes & ObjCPropertyAttribute::kind_nullability) {
69281ad6265SDimitry Andric       QualType Type = Property->getType();
69381ad6265SDimitry Andric       if (const auto Nullability =
69481ad6265SDimitry Andric               AttributedType::stripOuterNullability(Type)) {
69581ad6265SDimitry Andric         if (!First)
69681ad6265SDimitry Andric           Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
69781ad6265SDimitry Andric         if (*Nullability == NullabilityKind::Unspecified &&
69881ad6265SDimitry Andric             (Attributes & ObjCPropertyAttribute::kind_null_resettable))
69981ad6265SDimitry Andric           Fragments.append("null_resettable",
70081ad6265SDimitry Andric                            DeclarationFragments::FragmentKind::Keyword);
70181ad6265SDimitry Andric         else
70281ad6265SDimitry Andric           Fragments.append(
70381ad6265SDimitry Andric               getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true),
70481ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Keyword);
70581ad6265SDimitry Andric         First = false;
70681ad6265SDimitry Andric       }
70781ad6265SDimitry Andric     }
70881ad6265SDimitry Andric 
70981ad6265SDimitry Andric     Fragments.append(")", DeclarationFragments::FragmentKind::Text);
71081ad6265SDimitry Andric   }
71181ad6265SDimitry Andric 
71281ad6265SDimitry Andric   // Build the property type and name, and return the completed fragments.
71381ad6265SDimitry Andric   return Fragments.appendSpace()
71481ad6265SDimitry Andric       .append(getFragmentsForType(Property->getType(),
71581ad6265SDimitry Andric                                   Property->getASTContext(), After))
716bdd1243dSDimitry Andric       .appendSpace()
71781ad6265SDimitry Andric       .append(Property->getName(),
71881ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Identifier)
71981ad6265SDimitry Andric       .append(std::move(After));
72081ad6265SDimitry Andric }
72181ad6265SDimitry Andric 
72281ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(
72381ad6265SDimitry Andric     const ObjCProtocolDecl *Protocol) {
72481ad6265SDimitry Andric   DeclarationFragments Fragments;
72581ad6265SDimitry Andric   // Build basic protocol declaration.
72681ad6265SDimitry Andric   Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword)
72781ad6265SDimitry Andric       .appendSpace()
72881ad6265SDimitry Andric       .append(Protocol->getName(),
72981ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Identifier);
73081ad6265SDimitry Andric 
73181ad6265SDimitry Andric   // If this protocol conforms to other protocols, build the conformance list.
73281ad6265SDimitry Andric   if (!Protocol->protocols().empty()) {
73381ad6265SDimitry Andric     Fragments.append(" <", DeclarationFragments::FragmentKind::Text);
73481ad6265SDimitry Andric     for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin();
73581ad6265SDimitry Andric          It != Protocol->protocol_end(); It++) {
73681ad6265SDimitry Andric       // Add a leading comma if this is not the first protocol rendered.
73781ad6265SDimitry Andric       if (It != Protocol->protocol_begin())
73881ad6265SDimitry Andric         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
73981ad6265SDimitry Andric 
74081ad6265SDimitry Andric       SmallString<128> USR;
74181ad6265SDimitry Andric       index::generateUSRForDecl(*It, USR);
74281ad6265SDimitry Andric       Fragments.append((*It)->getName(),
743bdd1243dSDimitry Andric                        DeclarationFragments::FragmentKind::TypeIdentifier, USR,
744bdd1243dSDimitry Andric                        *It);
74581ad6265SDimitry Andric     }
74681ad6265SDimitry Andric     Fragments.append(">", DeclarationFragments::FragmentKind::Text);
74781ad6265SDimitry Andric   }
74881ad6265SDimitry Andric 
74981ad6265SDimitry Andric   return Fragments;
75081ad6265SDimitry Andric }
75181ad6265SDimitry Andric 
75281ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(
75381ad6265SDimitry Andric     const TypedefNameDecl *Decl) {
75481ad6265SDimitry Andric   DeclarationFragments Fragments, After;
75581ad6265SDimitry Andric   Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword)
75681ad6265SDimitry Andric       .appendSpace()
75781ad6265SDimitry Andric       .append(getFragmentsForType(Decl->getUnderlyingType(),
75881ad6265SDimitry Andric                                   Decl->getASTContext(), After))
75981ad6265SDimitry Andric       .append(std::move(After))
76081ad6265SDimitry Andric       .appendSpace()
76181ad6265SDimitry Andric       .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
76281ad6265SDimitry Andric 
763*06c3fb27SDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
76481ad6265SDimitry Andric }
76581ad6265SDimitry Andric 
76681ad6265SDimitry Andric template <typename FunctionT>
76781ad6265SDimitry Andric FunctionSignature
76881ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) {
76981ad6265SDimitry Andric   FunctionSignature Signature;
77081ad6265SDimitry Andric 
77181ad6265SDimitry Andric   DeclarationFragments ReturnType, After;
77281ad6265SDimitry Andric   ReturnType
77381ad6265SDimitry Andric       .append(getFragmentsForType(Function->getReturnType(),
77481ad6265SDimitry Andric                                   Function->getASTContext(), After))
77581ad6265SDimitry Andric       .append(std::move(After));
77681ad6265SDimitry Andric   Signature.setReturnType(ReturnType);
77781ad6265SDimitry Andric 
77881ad6265SDimitry Andric   for (const auto *Param : Function->parameters())
77981ad6265SDimitry Andric     Signature.addParameter(Param->getName(), getFragmentsForParam(Param));
78081ad6265SDimitry Andric 
78181ad6265SDimitry Andric   return Signature;
78281ad6265SDimitry Andric }
78381ad6265SDimitry Andric 
78481ad6265SDimitry Andric // Instantiate template for FunctionDecl.
78581ad6265SDimitry Andric template FunctionSignature
78681ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *);
78781ad6265SDimitry Andric 
78881ad6265SDimitry Andric // Instantiate template for ObjCMethodDecl.
78981ad6265SDimitry Andric template FunctionSignature
79081ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *);
79181ad6265SDimitry Andric 
79281ad6265SDimitry Andric // Subheading of a symbol defaults to its name.
79381ad6265SDimitry Andric DeclarationFragments
79481ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) {
79581ad6265SDimitry Andric   DeclarationFragments Fragments;
79681ad6265SDimitry Andric   if (!Decl->getName().empty())
79781ad6265SDimitry Andric     Fragments.append(Decl->getName(),
79881ad6265SDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
79981ad6265SDimitry Andric   return Fragments;
80081ad6265SDimitry Andric }
80181ad6265SDimitry Andric 
80281ad6265SDimitry Andric // Subheading of an Objective-C method is a `+` or `-` sign indicating whether
80381ad6265SDimitry Andric // it's a class method or an instance method, followed by the selector name.
80481ad6265SDimitry Andric DeclarationFragments
80581ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) {
80681ad6265SDimitry Andric   DeclarationFragments Fragments;
80781ad6265SDimitry Andric   if (Method->isClassMethod())
80881ad6265SDimitry Andric     Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
80981ad6265SDimitry Andric   else if (Method->isInstanceMethod())
81081ad6265SDimitry Andric     Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
81181ad6265SDimitry Andric 
81281ad6265SDimitry Andric   return Fragments.append(Method->getNameAsString(),
81381ad6265SDimitry Andric                           DeclarationFragments::FragmentKind::Identifier);
81481ad6265SDimitry Andric }
81581ad6265SDimitry Andric 
81681ad6265SDimitry Andric // Subheading of a symbol defaults to its name.
81781ad6265SDimitry Andric DeclarationFragments
81881ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) {
81981ad6265SDimitry Andric   DeclarationFragments Fragments;
82081ad6265SDimitry Andric   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
82181ad6265SDimitry Andric   return Fragments;
82281ad6265SDimitry Andric }
823