xref: /freebsd-src/contrib/llvm-project/clang/lib/ExtractAPI/DeclarationFragments.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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*0fca6ea1SDimitry Andric #include "clang/AST/ASTFwd.h"
165f757f3fSDimitry Andric #include "clang/AST/Decl.h"
175f757f3fSDimitry Andric #include "clang/AST/DeclCXX.h"
18*0fca6ea1SDimitry Andric #include "clang/AST/TemplateBase.h"
19*0fca6ea1SDimitry Andric #include "clang/AST/TemplateName.h"
205f757f3fSDimitry Andric #include "clang/AST/Type.h"
215f757f3fSDimitry Andric #include "clang/AST/TypeLoc.h"
2206c3fb27SDimitry Andric #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
2381ad6265SDimitry Andric #include "clang/Index/USRGeneration.h"
2481ad6265SDimitry Andric #include "llvm/ADT/StringSwitch.h"
25*0fca6ea1SDimitry Andric #include "llvm/Support/ErrorHandling.h"
26*0fca6ea1SDimitry Andric #include "llvm/Support/raw_ostream.h"
27*0fca6ea1SDimitry Andric #include <optional>
2881ad6265SDimitry Andric 
2981ad6265SDimitry Andric using namespace clang::extractapi;
3081ad6265SDimitry Andric using namespace llvm;
3181ad6265SDimitry Andric 
325f757f3fSDimitry Andric namespace {
335f757f3fSDimitry Andric 
345f757f3fSDimitry Andric void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo,
355f757f3fSDimitry Andric                              clang::FunctionTypeLoc &Block,
365f757f3fSDimitry Andric                              clang::FunctionProtoTypeLoc &BlockProto) {
375f757f3fSDimitry Andric   if (!TSInfo)
385f757f3fSDimitry Andric     return;
395f757f3fSDimitry Andric 
405f757f3fSDimitry Andric   clang::TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
415f757f3fSDimitry Andric   while (true) {
425f757f3fSDimitry Andric     // Look through qualified types
435f757f3fSDimitry Andric     if (auto QualifiedTL = TL.getAs<clang::QualifiedTypeLoc>()) {
445f757f3fSDimitry Andric       TL = QualifiedTL.getUnqualifiedLoc();
455f757f3fSDimitry Andric       continue;
465f757f3fSDimitry Andric     }
475f757f3fSDimitry Andric 
485f757f3fSDimitry Andric     if (auto AttrTL = TL.getAs<clang::AttributedTypeLoc>()) {
495f757f3fSDimitry Andric       TL = AttrTL.getModifiedLoc();
505f757f3fSDimitry Andric       continue;
515f757f3fSDimitry Andric     }
525f757f3fSDimitry Andric 
535f757f3fSDimitry Andric     // Try to get the function prototype behind the block pointer type,
545f757f3fSDimitry Andric     // then we're done.
555f757f3fSDimitry Andric     if (auto BlockPtr = TL.getAs<clang::BlockPointerTypeLoc>()) {
565f757f3fSDimitry Andric       TL = BlockPtr.getPointeeLoc().IgnoreParens();
575f757f3fSDimitry Andric       Block = TL.getAs<clang::FunctionTypeLoc>();
585f757f3fSDimitry Andric       BlockProto = TL.getAs<clang::FunctionProtoTypeLoc>();
595f757f3fSDimitry Andric     }
605f757f3fSDimitry Andric     break;
615f757f3fSDimitry Andric   }
625f757f3fSDimitry Andric }
635f757f3fSDimitry Andric 
645f757f3fSDimitry Andric } // namespace
655f757f3fSDimitry Andric 
66*0fca6ea1SDimitry Andric DeclarationFragments &
67*0fca6ea1SDimitry Andric DeclarationFragments::appendUnduplicatedTextCharacter(char Character) {
6881ad6265SDimitry Andric   if (!Fragments.empty()) {
6981ad6265SDimitry Andric     Fragment &Last = Fragments.back();
7081ad6265SDimitry Andric     if (Last.Kind == FragmentKind::Text) {
7181ad6265SDimitry Andric       // Merge the extra space into the last fragment if the last fragment is
7281ad6265SDimitry Andric       // also text.
73*0fca6ea1SDimitry Andric       if (Last.Spelling.back() != Character) { // avoid duplicates at end
74*0fca6ea1SDimitry Andric         Last.Spelling.push_back(Character);
7581ad6265SDimitry Andric       }
7681ad6265SDimitry Andric     } else {
7781ad6265SDimitry Andric       append("", FragmentKind::Text);
78*0fca6ea1SDimitry Andric       Fragments.back().Spelling.push_back(Character);
7981ad6265SDimitry Andric     }
8081ad6265SDimitry Andric   }
8181ad6265SDimitry Andric 
8281ad6265SDimitry Andric   return *this;
8381ad6265SDimitry Andric }
8481ad6265SDimitry Andric 
85*0fca6ea1SDimitry Andric DeclarationFragments &DeclarationFragments::appendSpace() {
86*0fca6ea1SDimitry Andric   return appendUnduplicatedTextCharacter(' ');
87*0fca6ea1SDimitry Andric }
88*0fca6ea1SDimitry Andric 
89*0fca6ea1SDimitry Andric DeclarationFragments &DeclarationFragments::appendSemicolon() {
90*0fca6ea1SDimitry Andric   return appendUnduplicatedTextCharacter(';');
91*0fca6ea1SDimitry Andric }
92*0fca6ea1SDimitry Andric 
93*0fca6ea1SDimitry Andric DeclarationFragments &DeclarationFragments::removeTrailingSemicolon() {
94*0fca6ea1SDimitry Andric   if (Fragments.empty())
95*0fca6ea1SDimitry Andric     return *this;
96*0fca6ea1SDimitry Andric 
97*0fca6ea1SDimitry Andric   Fragment &Last = Fragments.back();
98*0fca6ea1SDimitry Andric   if (Last.Kind == FragmentKind::Text && Last.Spelling.back() == ';')
99*0fca6ea1SDimitry Andric     Last.Spelling.pop_back();
100*0fca6ea1SDimitry Andric 
101*0fca6ea1SDimitry Andric   return *this;
102*0fca6ea1SDimitry Andric }
103*0fca6ea1SDimitry Andric 
10481ad6265SDimitry Andric StringRef DeclarationFragments::getFragmentKindString(
10581ad6265SDimitry Andric     DeclarationFragments::FragmentKind Kind) {
10681ad6265SDimitry Andric   switch (Kind) {
10781ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::None:
10881ad6265SDimitry Andric     return "none";
10981ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::Keyword:
11081ad6265SDimitry Andric     return "keyword";
11181ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::Attribute:
11281ad6265SDimitry Andric     return "attribute";
11381ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::NumberLiteral:
11481ad6265SDimitry Andric     return "number";
11581ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::StringLiteral:
11681ad6265SDimitry Andric     return "string";
11781ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::Identifier:
11881ad6265SDimitry Andric     return "identifier";
11981ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::TypeIdentifier:
12081ad6265SDimitry Andric     return "typeIdentifier";
12181ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::GenericParameter:
12281ad6265SDimitry Andric     return "genericParameter";
12381ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::ExternalParam:
12481ad6265SDimitry Andric     return "externalParam";
12581ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::InternalParam:
12681ad6265SDimitry Andric     return "internalParam";
12781ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::Text:
12881ad6265SDimitry Andric     return "text";
12981ad6265SDimitry Andric   }
13081ad6265SDimitry Andric 
13181ad6265SDimitry Andric   llvm_unreachable("Unhandled FragmentKind");
13281ad6265SDimitry Andric }
13381ad6265SDimitry Andric 
13481ad6265SDimitry Andric DeclarationFragments::FragmentKind
13581ad6265SDimitry Andric DeclarationFragments::parseFragmentKindFromString(StringRef S) {
13681ad6265SDimitry Andric   return llvm::StringSwitch<FragmentKind>(S)
13781ad6265SDimitry Andric       .Case("keyword", DeclarationFragments::FragmentKind::Keyword)
13881ad6265SDimitry Andric       .Case("attribute", DeclarationFragments::FragmentKind::Attribute)
13981ad6265SDimitry Andric       .Case("number", DeclarationFragments::FragmentKind::NumberLiteral)
14081ad6265SDimitry Andric       .Case("string", DeclarationFragments::FragmentKind::StringLiteral)
14181ad6265SDimitry Andric       .Case("identifier", DeclarationFragments::FragmentKind::Identifier)
14281ad6265SDimitry Andric       .Case("typeIdentifier",
14381ad6265SDimitry Andric             DeclarationFragments::FragmentKind::TypeIdentifier)
14481ad6265SDimitry Andric       .Case("genericParameter",
14581ad6265SDimitry Andric             DeclarationFragments::FragmentKind::GenericParameter)
14681ad6265SDimitry Andric       .Case("internalParam", DeclarationFragments::FragmentKind::InternalParam)
14781ad6265SDimitry Andric       .Case("externalParam", DeclarationFragments::FragmentKind::ExternalParam)
14881ad6265SDimitry Andric       .Case("text", DeclarationFragments::FragmentKind::Text)
14981ad6265SDimitry Andric       .Default(DeclarationFragments::FragmentKind::None);
15081ad6265SDimitry Andric }
15181ad6265SDimitry Andric 
1525f757f3fSDimitry Andric DeclarationFragments DeclarationFragments::getExceptionSpecificationString(
1535f757f3fSDimitry Andric     ExceptionSpecificationType ExceptionSpec) {
1545f757f3fSDimitry Andric   DeclarationFragments Fragments;
1555f757f3fSDimitry Andric   switch (ExceptionSpec) {
1565f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_None:
1575f757f3fSDimitry Andric     return Fragments;
1585f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_DynamicNone:
1595f757f3fSDimitry Andric     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
1605f757f3fSDimitry Andric         .append("throw", DeclarationFragments::FragmentKind::Keyword)
1615f757f3fSDimitry Andric         .append("(", DeclarationFragments::FragmentKind::Text)
1625f757f3fSDimitry Andric         .append(")", DeclarationFragments::FragmentKind::Text);
1635f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_Dynamic:
1645f757f3fSDimitry Andric     // FIXME: throw(int), get types of inner expression
1655f757f3fSDimitry Andric     return Fragments;
1665f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_BasicNoexcept:
1675f757f3fSDimitry Andric     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
1685f757f3fSDimitry Andric         .append("noexcept", DeclarationFragments::FragmentKind::Keyword);
1695f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_DependentNoexcept:
1705f757f3fSDimitry Andric     // FIXME: throw(conditional-expression), get expression
1715f757f3fSDimitry Andric     break;
1725f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_NoexceptFalse:
1735f757f3fSDimitry Andric     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
1745f757f3fSDimitry Andric         .append("noexcept", DeclarationFragments::FragmentKind::Keyword)
1755f757f3fSDimitry Andric         .append("(", DeclarationFragments::FragmentKind::Text)
1765f757f3fSDimitry Andric         .append("false", DeclarationFragments::FragmentKind::Keyword)
1775f757f3fSDimitry Andric         .append(")", DeclarationFragments::FragmentKind::Text);
1785f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_NoexceptTrue:
1795f757f3fSDimitry Andric     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
1805f757f3fSDimitry Andric         .append("noexcept", DeclarationFragments::FragmentKind::Keyword)
1815f757f3fSDimitry Andric         .append("(", DeclarationFragments::FragmentKind::Text)
1825f757f3fSDimitry Andric         .append("true", DeclarationFragments::FragmentKind::Keyword)
1835f757f3fSDimitry Andric         .append(")", DeclarationFragments::FragmentKind::Text);
1845f757f3fSDimitry Andric   default:
1855f757f3fSDimitry Andric     return Fragments;
1865f757f3fSDimitry Andric   }
1875f757f3fSDimitry Andric 
1885f757f3fSDimitry Andric   llvm_unreachable("Unhandled exception specification");
1895f757f3fSDimitry Andric }
1905f757f3fSDimitry Andric 
1915f757f3fSDimitry Andric DeclarationFragments
1925f757f3fSDimitry Andric DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) {
1935f757f3fSDimitry Andric   DeclarationFragments Fragments;
1945f757f3fSDimitry Andric   if (Record->isStruct())
1955f757f3fSDimitry Andric     Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);
1965f757f3fSDimitry Andric   else if (Record->isUnion())
1975f757f3fSDimitry Andric     Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);
1985f757f3fSDimitry Andric   else
1995f757f3fSDimitry Andric     Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);
2005f757f3fSDimitry Andric 
2015f757f3fSDimitry Andric   return Fragments;
2025f757f3fSDimitry Andric }
2035f757f3fSDimitry Andric 
20481ad6265SDimitry Andric // NNS stores C++ nested name specifiers, which are prefixes to qualified names.
20581ad6265SDimitry Andric // Build declaration fragments for NNS recursively so that we have the USR for
20681ad6265SDimitry Andric // every part in a qualified name, and also leaves the actual underlying type
20781ad6265SDimitry Andric // cleaner for its own fragment.
20881ad6265SDimitry Andric DeclarationFragments
20981ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS,
21081ad6265SDimitry Andric                                                 ASTContext &Context,
21181ad6265SDimitry Andric                                                 DeclarationFragments &After) {
21281ad6265SDimitry Andric   DeclarationFragments Fragments;
21381ad6265SDimitry Andric   if (NNS->getPrefix())
21481ad6265SDimitry Andric     Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After));
21581ad6265SDimitry Andric 
21681ad6265SDimitry Andric   switch (NNS->getKind()) {
21781ad6265SDimitry Andric   case NestedNameSpecifier::Identifier:
21881ad6265SDimitry Andric     Fragments.append(NNS->getAsIdentifier()->getName(),
21981ad6265SDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
22081ad6265SDimitry Andric     break;
22181ad6265SDimitry Andric 
22281ad6265SDimitry Andric   case NestedNameSpecifier::Namespace: {
22381ad6265SDimitry Andric     const NamespaceDecl *NS = NNS->getAsNamespace();
22481ad6265SDimitry Andric     if (NS->isAnonymousNamespace())
22581ad6265SDimitry Andric       return Fragments;
22681ad6265SDimitry Andric     SmallString<128> USR;
22781ad6265SDimitry Andric     index::generateUSRForDecl(NS, USR);
22881ad6265SDimitry Andric     Fragments.append(NS->getName(),
229bdd1243dSDimitry Andric                      DeclarationFragments::FragmentKind::Identifier, USR, NS);
23081ad6265SDimitry Andric     break;
23181ad6265SDimitry Andric   }
23281ad6265SDimitry Andric 
23381ad6265SDimitry Andric   case NestedNameSpecifier::NamespaceAlias: {
23481ad6265SDimitry Andric     const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias();
23581ad6265SDimitry Andric     SmallString<128> USR;
23681ad6265SDimitry Andric     index::generateUSRForDecl(Alias, USR);
23781ad6265SDimitry Andric     Fragments.append(Alias->getName(),
238bdd1243dSDimitry Andric                      DeclarationFragments::FragmentKind::Identifier, USR,
239bdd1243dSDimitry Andric                      Alias);
24081ad6265SDimitry Andric     break;
24181ad6265SDimitry Andric   }
24281ad6265SDimitry Andric 
24381ad6265SDimitry Andric   case NestedNameSpecifier::Global:
24481ad6265SDimitry Andric     // The global specifier `::` at the beginning. No stored value.
24581ad6265SDimitry Andric     break;
24681ad6265SDimitry Andric 
24781ad6265SDimitry Andric   case NestedNameSpecifier::Super:
24881ad6265SDimitry Andric     // Microsoft's `__super` specifier.
24981ad6265SDimitry Andric     Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword);
25081ad6265SDimitry Andric     break;
25181ad6265SDimitry Andric 
25281ad6265SDimitry Andric   case NestedNameSpecifier::TypeSpecWithTemplate:
25381ad6265SDimitry Andric     // A type prefixed by the `template` keyword.
25481ad6265SDimitry Andric     Fragments.append("template", DeclarationFragments::FragmentKind::Keyword);
25581ad6265SDimitry Andric     Fragments.appendSpace();
25681ad6265SDimitry Andric     // Fallthrough after adding the keyword to handle the actual type.
257bdd1243dSDimitry Andric     [[fallthrough]];
25881ad6265SDimitry Andric 
25981ad6265SDimitry Andric   case NestedNameSpecifier::TypeSpec: {
26081ad6265SDimitry Andric     const Type *T = NNS->getAsType();
26181ad6265SDimitry Andric     // FIXME: Handle C++ template specialization type
26281ad6265SDimitry Andric     Fragments.append(getFragmentsForType(T, Context, After));
26381ad6265SDimitry Andric     break;
26481ad6265SDimitry Andric   }
26581ad6265SDimitry Andric   }
26681ad6265SDimitry Andric 
26781ad6265SDimitry Andric   // Add the separator text `::` for this segment.
26881ad6265SDimitry Andric   return Fragments.append("::", DeclarationFragments::FragmentKind::Text);
26981ad6265SDimitry Andric }
27081ad6265SDimitry Andric 
27181ad6265SDimitry Andric // Recursively build the declaration fragments for an underlying `Type` with
27281ad6265SDimitry Andric // qualifiers removed.
27381ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
27481ad6265SDimitry Andric     const Type *T, ASTContext &Context, DeclarationFragments &After) {
27581ad6265SDimitry Andric   assert(T && "invalid type");
27681ad6265SDimitry Andric 
27781ad6265SDimitry Andric   DeclarationFragments Fragments;
27881ad6265SDimitry Andric 
2797a6dacacSDimitry Andric   // An ElaboratedType is a sugar for types that are referred to using an
2807a6dacacSDimitry Andric   // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a
2817a6dacacSDimitry Andric   // qualified name, e.g., `N::M::type`, or both.
2827a6dacacSDimitry Andric   if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) {
2837a6dacacSDimitry Andric     ElaboratedTypeKeyword Keyword = ET->getKeyword();
2847a6dacacSDimitry Andric     if (Keyword != ElaboratedTypeKeyword::None) {
2857a6dacacSDimitry Andric       Fragments
2867a6dacacSDimitry Andric           .append(ElaboratedType::getKeywordName(Keyword),
2877a6dacacSDimitry Andric                   DeclarationFragments::FragmentKind::Keyword)
2887a6dacacSDimitry Andric           .appendSpace();
2897a6dacacSDimitry Andric     }
2907a6dacacSDimitry Andric 
2917a6dacacSDimitry Andric     if (const NestedNameSpecifier *NNS = ET->getQualifier())
2927a6dacacSDimitry Andric       Fragments.append(getFragmentsForNNS(NNS, Context, After));
2937a6dacacSDimitry Andric 
2947a6dacacSDimitry Andric     // After handling the elaborated keyword or qualified name, build
2957a6dacacSDimitry Andric     // declaration fragments for the desugared underlying type.
2967a6dacacSDimitry Andric     return Fragments.append(getFragmentsForType(ET->desugar(), Context, After));
2977a6dacacSDimitry Andric   }
2987a6dacacSDimitry Andric 
2997a6dacacSDimitry Andric   // If the type is a typedefed type, get the underlying TypedefNameDecl for a
3007a6dacacSDimitry Andric   // direct reference to the typedef instead of the wrapped type.
3017a6dacacSDimitry Andric 
3027a6dacacSDimitry Andric   // 'id' type is a typedef for an ObjCObjectPointerType
3037a6dacacSDimitry Andric   //  we treat it as a typedef
3047a6dacacSDimitry Andric   if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) {
3057a6dacacSDimitry Andric     const TypedefNameDecl *Decl = TypedefTy->getDecl();
3067a6dacacSDimitry Andric     TypedefUnderlyingTypeResolver TypedefResolver(Context);
3077a6dacacSDimitry Andric     std::string USR = TypedefResolver.getUSRForType(QualType(T, 0));
3087a6dacacSDimitry Andric 
3097a6dacacSDimitry Andric     if (T->isObjCIdType()) {
3107a6dacacSDimitry Andric       return Fragments.append(Decl->getName(),
3117a6dacacSDimitry Andric                               DeclarationFragments::FragmentKind::Keyword);
3127a6dacacSDimitry Andric     }
3137a6dacacSDimitry Andric 
3147a6dacacSDimitry Andric     return Fragments.append(
3157a6dacacSDimitry Andric         Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier,
3167a6dacacSDimitry Andric         USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0)));
3177a6dacacSDimitry Andric   }
3187a6dacacSDimitry Andric 
31981ad6265SDimitry Andric   // Declaration fragments of a pointer type is the declaration fragments of
32006c3fb27SDimitry Andric   // the pointee type followed by a `*`,
3215f757f3fSDimitry Andric   if (T->isPointerType() && !T->isFunctionPointerType())
32281ad6265SDimitry Andric     return Fragments
32381ad6265SDimitry Andric         .append(getFragmentsForType(T->getPointeeType(), Context, After))
32481ad6265SDimitry Andric         .append(" *", DeclarationFragments::FragmentKind::Text);
32506c3fb27SDimitry Andric 
32606c3fb27SDimitry Andric   // For Objective-C `id` and `Class` pointers
32706c3fb27SDimitry Andric   // we do not spell out the `*`.
32806c3fb27SDimitry Andric   if (T->isObjCObjectPointerType() &&
32906c3fb27SDimitry Andric       !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) {
33006c3fb27SDimitry Andric 
33106c3fb27SDimitry Andric     Fragments.append(getFragmentsForType(T->getPointeeType(), Context, After));
33206c3fb27SDimitry Andric 
33306c3fb27SDimitry Andric     // id<protocol> is an qualified id type
33406c3fb27SDimitry Andric     // id<protocol>* is not an qualified id type
33506c3fb27SDimitry Andric     if (!T->getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) {
33606c3fb27SDimitry Andric       Fragments.append(" *", DeclarationFragments::FragmentKind::Text);
33706c3fb27SDimitry Andric     }
33806c3fb27SDimitry Andric 
33906c3fb27SDimitry Andric     return Fragments;
34081ad6265SDimitry Andric   }
34181ad6265SDimitry Andric 
34281ad6265SDimitry Andric   // Declaration fragments of a lvalue reference type is the declaration
34381ad6265SDimitry Andric   // fragments of the underlying type followed by a `&`.
34481ad6265SDimitry Andric   if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T))
34581ad6265SDimitry Andric     return Fragments
34681ad6265SDimitry Andric         .append(
34781ad6265SDimitry Andric             getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After))
34881ad6265SDimitry Andric         .append(" &", DeclarationFragments::FragmentKind::Text);
34981ad6265SDimitry Andric 
35081ad6265SDimitry Andric   // Declaration fragments of a rvalue reference type is the declaration
35181ad6265SDimitry Andric   // fragments of the underlying type followed by a `&&`.
35281ad6265SDimitry Andric   if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T))
35381ad6265SDimitry Andric     return Fragments
35481ad6265SDimitry Andric         .append(
35581ad6265SDimitry Andric             getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After))
35681ad6265SDimitry Andric         .append(" &&", DeclarationFragments::FragmentKind::Text);
35781ad6265SDimitry Andric 
35881ad6265SDimitry Andric   // Declaration fragments of an array-typed variable have two parts:
35981ad6265SDimitry Andric   // 1. the element type of the array that appears before the variable name;
36081ad6265SDimitry Andric   // 2. array brackets `[(0-9)?]` that appear after the variable name.
36181ad6265SDimitry Andric   if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) {
36281ad6265SDimitry Andric     // Build the "after" part first because the inner element type might also
36381ad6265SDimitry Andric     // be an array-type. For example `int matrix[3][4]` which has a type of
36481ad6265SDimitry Andric     // "(array 3 of (array 4 of ints))."
36581ad6265SDimitry Andric     // Push the array size part first to make sure they are in the right order.
36681ad6265SDimitry Andric     After.append("[", DeclarationFragments::FragmentKind::Text);
36781ad6265SDimitry Andric 
36881ad6265SDimitry Andric     switch (AT->getSizeModifier()) {
3695f757f3fSDimitry Andric     case ArraySizeModifier::Normal:
37081ad6265SDimitry Andric       break;
3715f757f3fSDimitry Andric     case ArraySizeModifier::Static:
37281ad6265SDimitry Andric       Fragments.append("static", DeclarationFragments::FragmentKind::Keyword);
37381ad6265SDimitry Andric       break;
3745f757f3fSDimitry Andric     case ArraySizeModifier::Star:
37581ad6265SDimitry Andric       Fragments.append("*", DeclarationFragments::FragmentKind::Text);
37681ad6265SDimitry Andric       break;
37781ad6265SDimitry Andric     }
37881ad6265SDimitry Andric 
37981ad6265SDimitry Andric     if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
38081ad6265SDimitry Andric       // FIXME: right now this would evaluate any expressions/macros written in
38181ad6265SDimitry Andric       // the original source to concrete values. For example
38281ad6265SDimitry Andric       // `int nums[MAX]` -> `int nums[100]`
38381ad6265SDimitry Andric       // `char *str[5 + 1]` -> `char *str[6]`
38481ad6265SDimitry Andric       SmallString<128> Size;
38581ad6265SDimitry Andric       CAT->getSize().toStringUnsigned(Size);
38681ad6265SDimitry Andric       After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral);
38781ad6265SDimitry Andric     }
38881ad6265SDimitry Andric 
38981ad6265SDimitry Andric     After.append("]", DeclarationFragments::FragmentKind::Text);
39081ad6265SDimitry Andric 
39181ad6265SDimitry Andric     return Fragments.append(
39281ad6265SDimitry Andric         getFragmentsForType(AT->getElementType(), Context, After));
39381ad6265SDimitry Andric   }
39481ad6265SDimitry Andric 
395*0fca6ea1SDimitry Andric   if (const TemplateSpecializationType *TemplSpecTy =
396*0fca6ea1SDimitry Andric           dyn_cast<TemplateSpecializationType>(T)) {
397*0fca6ea1SDimitry Andric     const auto TemplName = TemplSpecTy->getTemplateName();
398*0fca6ea1SDimitry Andric     std::string Str;
399*0fca6ea1SDimitry Andric     raw_string_ostream Stream(Str);
400*0fca6ea1SDimitry Andric     TemplName.print(Stream, Context.getPrintingPolicy(),
401*0fca6ea1SDimitry Andric                     TemplateName::Qualified::AsWritten);
402*0fca6ea1SDimitry Andric     SmallString<64> USR("");
403*0fca6ea1SDimitry Andric     if (const auto *TemplDecl = TemplName.getAsTemplateDecl())
404*0fca6ea1SDimitry Andric       index::generateUSRForDecl(TemplDecl, USR);
405*0fca6ea1SDimitry Andric 
406*0fca6ea1SDimitry Andric     return Fragments
407*0fca6ea1SDimitry Andric         .append(Str, DeclarationFragments::FragmentKind::TypeIdentifier, USR)
408*0fca6ea1SDimitry Andric         .append("<", DeclarationFragments::FragmentKind::Text)
409*0fca6ea1SDimitry Andric         .append(getFragmentsForTemplateArguments(
410*0fca6ea1SDimitry Andric             TemplSpecTy->template_arguments(), Context, std::nullopt))
411*0fca6ea1SDimitry Andric         .append(">", DeclarationFragments::FragmentKind::Text);
412*0fca6ea1SDimitry Andric   }
413*0fca6ea1SDimitry Andric 
41406c3fb27SDimitry Andric   // Everything we care about has been handled now, reduce to the canonical
41506c3fb27SDimitry Andric   // unqualified base type.
41606c3fb27SDimitry Andric   QualType Base = T->getCanonicalTypeUnqualified();
41706c3fb27SDimitry Andric 
41881ad6265SDimitry Andric   // If the base type is a TagType (struct/interface/union/class/enum), let's
41981ad6265SDimitry Andric   // get the underlying Decl for better names and USRs.
42081ad6265SDimitry Andric   if (const TagType *TagTy = dyn_cast<TagType>(Base)) {
42181ad6265SDimitry Andric     const TagDecl *Decl = TagTy->getDecl();
42281ad6265SDimitry Andric     // Anonymous decl, skip this fragment.
42381ad6265SDimitry Andric     if (Decl->getName().empty())
424*0fca6ea1SDimitry Andric       return Fragments.append("{ ... }",
425*0fca6ea1SDimitry Andric                               DeclarationFragments::FragmentKind::Text);
42681ad6265SDimitry Andric     SmallString<128> TagUSR;
42781ad6265SDimitry Andric     clang::index::generateUSRForDecl(Decl, TagUSR);
42881ad6265SDimitry Andric     return Fragments.append(Decl->getName(),
42981ad6265SDimitry Andric                             DeclarationFragments::FragmentKind::TypeIdentifier,
430bdd1243dSDimitry Andric                             TagUSR, Decl);
43181ad6265SDimitry Andric   }
43281ad6265SDimitry Andric 
43381ad6265SDimitry Andric   // If the base type is an ObjCInterfaceType, use the underlying
43481ad6265SDimitry Andric   // ObjCInterfaceDecl for the true USR.
43581ad6265SDimitry Andric   if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) {
43681ad6265SDimitry Andric     const auto *Decl = ObjCIT->getDecl();
43781ad6265SDimitry Andric     SmallString<128> USR;
43881ad6265SDimitry Andric     index::generateUSRForDecl(Decl, USR);
43981ad6265SDimitry Andric     return Fragments.append(Decl->getName(),
44081ad6265SDimitry Andric                             DeclarationFragments::FragmentKind::TypeIdentifier,
441bdd1243dSDimitry Andric                             USR, Decl);
44281ad6265SDimitry Andric   }
44381ad6265SDimitry Andric 
44481ad6265SDimitry Andric   // Default fragment builder for other kinds of types (BuiltinType etc.)
44581ad6265SDimitry Andric   SmallString<128> USR;
44681ad6265SDimitry Andric   clang::index::generateUSRForType(Base, Context, USR);
44781ad6265SDimitry Andric   Fragments.append(Base.getAsString(),
44881ad6265SDimitry Andric                    DeclarationFragments::FragmentKind::TypeIdentifier, USR);
44981ad6265SDimitry Andric 
45081ad6265SDimitry Andric   return Fragments;
45181ad6265SDimitry Andric }
45281ad6265SDimitry Andric 
45381ad6265SDimitry Andric DeclarationFragments
45481ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) {
45581ad6265SDimitry Andric   DeclarationFragments Fragments;
45681ad6265SDimitry Andric   if (Quals.hasConst())
45781ad6265SDimitry Andric     Fragments.append("const", DeclarationFragments::FragmentKind::Keyword);
45881ad6265SDimitry Andric   if (Quals.hasVolatile())
45981ad6265SDimitry Andric     Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword);
46081ad6265SDimitry Andric   if (Quals.hasRestrict())
46181ad6265SDimitry Andric     Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword);
46281ad6265SDimitry Andric 
46381ad6265SDimitry Andric   return Fragments;
46481ad6265SDimitry Andric }
46581ad6265SDimitry Andric 
46681ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
46781ad6265SDimitry Andric     const QualType QT, ASTContext &Context, DeclarationFragments &After) {
46881ad6265SDimitry Andric   assert(!QT.isNull() && "invalid type");
46981ad6265SDimitry Andric 
47081ad6265SDimitry Andric   if (const ParenType *PT = dyn_cast<ParenType>(QT)) {
47181ad6265SDimitry Andric     After.append(")", DeclarationFragments::FragmentKind::Text);
47281ad6265SDimitry Andric     return getFragmentsForType(PT->getInnerType(), Context, After)
47381ad6265SDimitry Andric         .append("(", DeclarationFragments::FragmentKind::Text);
47481ad6265SDimitry Andric   }
47581ad6265SDimitry Andric 
47681ad6265SDimitry Andric   const SplitQualType SQT = QT.split();
47781ad6265SDimitry Andric   DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals),
47881ad6265SDimitry Andric                        TypeFragments =
47981ad6265SDimitry Andric                            getFragmentsForType(SQT.Ty, Context, After);
4805f757f3fSDimitry Andric   if (QT.getAsString() == "_Bool")
4815f757f3fSDimitry Andric     TypeFragments.replace("bool", 0);
4825f757f3fSDimitry Andric 
48381ad6265SDimitry Andric   if (QualsFragments.getFragments().empty())
48481ad6265SDimitry Andric     return TypeFragments;
48581ad6265SDimitry Andric 
48681ad6265SDimitry Andric   // Use east qualifier for pointer types
48781ad6265SDimitry Andric   // For example:
48881ad6265SDimitry Andric   // ```
48981ad6265SDimitry Andric   // int *   const
49081ad6265SDimitry Andric   // ^----   ^----
49181ad6265SDimitry Andric   //  type    qualifier
49281ad6265SDimitry Andric   // ^-----------------
49381ad6265SDimitry Andric   //  const pointer to int
49481ad6265SDimitry Andric   // ```
49581ad6265SDimitry Andric   // should not be reconstructed as
49681ad6265SDimitry Andric   // ```
49781ad6265SDimitry Andric   // const       int       *
49881ad6265SDimitry Andric   // ^----       ^--
49981ad6265SDimitry Andric   //  qualifier   type
50081ad6265SDimitry Andric   // ^----------------     ^
50181ad6265SDimitry Andric   //  pointer to const int
50281ad6265SDimitry Andric   // ```
50381ad6265SDimitry Andric   if (SQT.Ty->isAnyPointerType())
50481ad6265SDimitry Andric     return TypeFragments.appendSpace().append(std::move(QualsFragments));
50581ad6265SDimitry Andric 
50681ad6265SDimitry Andric   return QualsFragments.appendSpace().append(std::move(TypeFragments));
50781ad6265SDimitry Andric }
50881ad6265SDimitry Andric 
5095f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace(
5105f757f3fSDimitry Andric     const NamespaceDecl *Decl) {
5115f757f3fSDimitry Andric   DeclarationFragments Fragments;
5125f757f3fSDimitry Andric   Fragments.append("namespace", DeclarationFragments::FragmentKind::Keyword);
5135f757f3fSDimitry Andric   if (!Decl->isAnonymousNamespace())
5145f757f3fSDimitry Andric     Fragments.appendSpace().append(
5155f757f3fSDimitry Andric         Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
516*0fca6ea1SDimitry Andric   return Fragments.appendSemicolon();
5175f757f3fSDimitry Andric }
5185f757f3fSDimitry Andric 
51981ad6265SDimitry Andric DeclarationFragments
52081ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
52181ad6265SDimitry Andric   DeclarationFragments Fragments;
5225f757f3fSDimitry Andric   if (Var->isConstexpr())
5235f757f3fSDimitry Andric     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
5245f757f3fSDimitry Andric         .appendSpace();
5255f757f3fSDimitry Andric 
52681ad6265SDimitry Andric   StorageClass SC = Var->getStorageClass();
52781ad6265SDimitry Andric   if (SC != SC_None)
52881ad6265SDimitry Andric     Fragments
52981ad6265SDimitry Andric         .append(VarDecl::getStorageClassSpecifierString(SC),
53081ad6265SDimitry Andric                 DeclarationFragments::FragmentKind::Keyword)
53181ad6265SDimitry Andric         .appendSpace();
53281ad6265SDimitry Andric 
53381ad6265SDimitry Andric   // Capture potential fragments that needs to be placed after the variable name
53481ad6265SDimitry Andric   // ```
53581ad6265SDimitry Andric   // int nums[5];
53681ad6265SDimitry Andric   // char (*ptr_to_array)[6];
53781ad6265SDimitry Andric   // ```
53881ad6265SDimitry Andric   DeclarationFragments After;
5395f757f3fSDimitry Andric   FunctionTypeLoc BlockLoc;
5405f757f3fSDimitry Andric   FunctionProtoTypeLoc BlockProtoLoc;
5415f757f3fSDimitry Andric   findTypeLocForBlockDecl(Var->getTypeSourceInfo(), BlockLoc, BlockProtoLoc);
5425f757f3fSDimitry Andric 
5435f757f3fSDimitry Andric   if (!BlockLoc) {
5445f757f3fSDimitry Andric     QualType T = Var->getTypeSourceInfo()
5455f757f3fSDimitry Andric                      ? Var->getTypeSourceInfo()->getType()
5465f757f3fSDimitry Andric                      : Var->getASTContext().getUnqualifiedObjCPointerType(
5475f757f3fSDimitry Andric                            Var->getType());
5485f757f3fSDimitry Andric 
5495f757f3fSDimitry Andric     Fragments.append(getFragmentsForType(T, Var->getASTContext(), After))
5505f757f3fSDimitry Andric         .appendSpace();
5515f757f3fSDimitry Andric   } else {
5525f757f3fSDimitry Andric     Fragments.append(getFragmentsForBlock(Var, BlockLoc, BlockProtoLoc, After));
5535f757f3fSDimitry Andric   }
5545f757f3fSDimitry Andric 
5555f757f3fSDimitry Andric   return Fragments
5565f757f3fSDimitry Andric       .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
5575f757f3fSDimitry Andric       .append(std::move(After))
558*0fca6ea1SDimitry Andric       .appendSemicolon();
5595f757f3fSDimitry Andric }
5605f757f3fSDimitry Andric 
5615f757f3fSDimitry Andric DeclarationFragments
5625f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) {
5635f757f3fSDimitry Andric   DeclarationFragments Fragments;
5645f757f3fSDimitry Andric   if (Var->isConstexpr())
5655f757f3fSDimitry Andric     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
5665f757f3fSDimitry Andric         .appendSpace();
5675f757f3fSDimitry Andric   QualType T =
5685f757f3fSDimitry Andric       Var->getTypeSourceInfo()
5695f757f3fSDimitry Andric           ? Var->getTypeSourceInfo()->getType()
5705f757f3fSDimitry Andric           : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType());
5715f757f3fSDimitry Andric 
5725f757f3fSDimitry Andric   // Might be a member, so might be static.
5735f757f3fSDimitry Andric   if (Var->isStaticDataMember())
5745f757f3fSDimitry Andric     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
5755f757f3fSDimitry Andric         .appendSpace();
5765f757f3fSDimitry Andric 
5775f757f3fSDimitry Andric   DeclarationFragments After;
5785f757f3fSDimitry Andric   DeclarationFragments ArgumentFragment =
5795f757f3fSDimitry Andric       getFragmentsForType(T, Var->getASTContext(), After);
580*0fca6ea1SDimitry Andric   if (StringRef(ArgumentFragment.begin()->Spelling)
581*0fca6ea1SDimitry Andric           .starts_with("type-parameter")) {
582*0fca6ea1SDimitry Andric     std::string ProperArgName = T.getAsString();
5835f757f3fSDimitry Andric     ArgumentFragment.begin()->Spelling.swap(ProperArgName);
5845f757f3fSDimitry Andric   }
5855f757f3fSDimitry Andric   Fragments.append(std::move(ArgumentFragment))
58681ad6265SDimitry Andric       .appendSpace()
58781ad6265SDimitry Andric       .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
588*0fca6ea1SDimitry Andric       .appendSemicolon();
5895f757f3fSDimitry Andric   return Fragments;
59081ad6265SDimitry Andric }
59181ad6265SDimitry Andric 
59281ad6265SDimitry Andric DeclarationFragments
59381ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) {
59481ad6265SDimitry Andric   DeclarationFragments Fragments, After;
59581ad6265SDimitry Andric 
5965f757f3fSDimitry Andric   auto *TSInfo = Param->getTypeSourceInfo();
5975f757f3fSDimitry Andric 
5985f757f3fSDimitry Andric   QualType T = TSInfo ? TSInfo->getType()
59981ad6265SDimitry Andric                       : Param->getASTContext().getUnqualifiedObjCPointerType(
60081ad6265SDimitry Andric                             Param->getType());
60181ad6265SDimitry Andric 
6025f757f3fSDimitry Andric   FunctionTypeLoc BlockLoc;
6035f757f3fSDimitry Andric   FunctionProtoTypeLoc BlockProtoLoc;
6045f757f3fSDimitry Andric   findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc);
60581ad6265SDimitry Andric 
6065f757f3fSDimitry Andric   DeclarationFragments TypeFragments;
6075f757f3fSDimitry Andric   if (BlockLoc)
6085f757f3fSDimitry Andric     TypeFragments.append(
6095f757f3fSDimitry Andric         getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After));
6105f757f3fSDimitry Andric   else
6115f757f3fSDimitry Andric     TypeFragments.append(getFragmentsForType(T, Param->getASTContext(), After));
6125f757f3fSDimitry Andric 
613*0fca6ea1SDimitry Andric   if (StringRef(TypeFragments.begin()->Spelling)
614*0fca6ea1SDimitry Andric           .starts_with("type-parameter")) {
615*0fca6ea1SDimitry Andric     std::string ProperArgName = Param->getOriginalType().getAsString();
6165f757f3fSDimitry Andric     TypeFragments.begin()->Spelling.swap(ProperArgName);
6175f757f3fSDimitry Andric   }
6185f757f3fSDimitry Andric 
6195f757f3fSDimitry Andric   if (Param->isObjCMethodParameter()) {
62081ad6265SDimitry Andric     Fragments.append("(", DeclarationFragments::FragmentKind::Text)
62181ad6265SDimitry Andric         .append(std::move(TypeFragments))
6225f757f3fSDimitry Andric         .append(std::move(After))
6235f757f3fSDimitry Andric         .append(") ", DeclarationFragments::FragmentKind::Text)
6245f757f3fSDimitry Andric         .append(Param->getName(),
6255f757f3fSDimitry Andric                 DeclarationFragments::FragmentKind::InternalParam);
6265f757f3fSDimitry Andric   } else {
6275f757f3fSDimitry Andric     Fragments.append(std::move(TypeFragments));
6285f757f3fSDimitry Andric     if (!T->isBlockPointerType())
6295f757f3fSDimitry Andric       Fragments.appendSpace();
6305f757f3fSDimitry Andric     Fragments
63181ad6265SDimitry Andric         .append(Param->getName(),
63281ad6265SDimitry Andric                 DeclarationFragments::FragmentKind::InternalParam)
63381ad6265SDimitry Andric         .append(std::move(After));
63481ad6265SDimitry Andric   }
6355f757f3fSDimitry Andric   return Fragments;
6365f757f3fSDimitry Andric }
6375f757f3fSDimitry Andric 
6385f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForBlock(
6395f757f3fSDimitry Andric     const NamedDecl *BlockDecl, FunctionTypeLoc &Block,
6405f757f3fSDimitry Andric     FunctionProtoTypeLoc &BlockProto, DeclarationFragments &After) {
6415f757f3fSDimitry Andric   DeclarationFragments Fragments;
6425f757f3fSDimitry Andric 
6435f757f3fSDimitry Andric   DeclarationFragments RetTyAfter;
6445f757f3fSDimitry Andric   auto ReturnValueFragment = getFragmentsForType(
6455f757f3fSDimitry Andric       Block.getTypePtr()->getReturnType(), BlockDecl->getASTContext(), After);
6465f757f3fSDimitry Andric 
6475f757f3fSDimitry Andric   Fragments.append(std::move(ReturnValueFragment))
6485f757f3fSDimitry Andric       .append(std::move(RetTyAfter))
6495f757f3fSDimitry Andric       .appendSpace()
6505f757f3fSDimitry Andric       .append("(^", DeclarationFragments::FragmentKind::Text);
6515f757f3fSDimitry Andric 
6525f757f3fSDimitry Andric   After.append(")", DeclarationFragments::FragmentKind::Text);
6535f757f3fSDimitry Andric   unsigned NumParams = Block.getNumParams();
6545f757f3fSDimitry Andric 
6555f757f3fSDimitry Andric   if (!BlockProto || NumParams == 0) {
6565f757f3fSDimitry Andric     if (BlockProto && BlockProto.getTypePtr()->isVariadic())
6575f757f3fSDimitry Andric       After.append("(...)", DeclarationFragments::FragmentKind::Text);
6585f757f3fSDimitry Andric     else
6595f757f3fSDimitry Andric       After.append("()", DeclarationFragments::FragmentKind::Text);
6605f757f3fSDimitry Andric   } else {
6615f757f3fSDimitry Andric     After.append("(", DeclarationFragments::FragmentKind::Text);
6625f757f3fSDimitry Andric     for (unsigned I = 0; I != NumParams; ++I) {
6635f757f3fSDimitry Andric       if (I)
6645f757f3fSDimitry Andric         After.append(", ", DeclarationFragments::FragmentKind::Text);
6655f757f3fSDimitry Andric       After.append(getFragmentsForParam(Block.getParam(I)));
6665f757f3fSDimitry Andric       if (I == NumParams - 1 && BlockProto.getTypePtr()->isVariadic())
6675f757f3fSDimitry Andric         After.append(", ...", DeclarationFragments::FragmentKind::Text);
6685f757f3fSDimitry Andric     }
6695f757f3fSDimitry Andric     After.append(")", DeclarationFragments::FragmentKind::Text);
6705f757f3fSDimitry Andric   }
6715f757f3fSDimitry Andric 
6725f757f3fSDimitry Andric   return Fragments;
6735f757f3fSDimitry Andric }
67481ad6265SDimitry Andric 
67581ad6265SDimitry Andric DeclarationFragments
67681ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
67781ad6265SDimitry Andric   DeclarationFragments Fragments;
67881ad6265SDimitry Andric   switch (Func->getStorageClass()) {
67981ad6265SDimitry Andric   case SC_None:
68081ad6265SDimitry Andric   case SC_PrivateExtern:
68181ad6265SDimitry Andric     break;
68281ad6265SDimitry Andric   case SC_Extern:
68381ad6265SDimitry Andric     Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword)
68481ad6265SDimitry Andric         .appendSpace();
68581ad6265SDimitry Andric     break;
68681ad6265SDimitry Andric   case SC_Static:
68781ad6265SDimitry Andric     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
68881ad6265SDimitry Andric         .appendSpace();
68981ad6265SDimitry Andric     break;
69081ad6265SDimitry Andric   case SC_Auto:
69181ad6265SDimitry Andric   case SC_Register:
69281ad6265SDimitry Andric     llvm_unreachable("invalid for functions");
69381ad6265SDimitry Andric   }
6945f757f3fSDimitry Andric   if (Func->isConsteval()) // if consteval, it is also constexpr
6955f757f3fSDimitry Andric     Fragments.append("consteval", DeclarationFragments::FragmentKind::Keyword)
6965f757f3fSDimitry Andric         .appendSpace();
6975f757f3fSDimitry Andric   else if (Func->isConstexpr())
6985f757f3fSDimitry Andric     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
6995f757f3fSDimitry Andric         .appendSpace();
70081ad6265SDimitry Andric 
70181ad6265SDimitry Andric   // FIXME: Is `after` actually needed here?
70281ad6265SDimitry Andric   DeclarationFragments After;
7035f757f3fSDimitry Andric   auto ReturnValueFragment =
7045f757f3fSDimitry Andric       getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After);
705*0fca6ea1SDimitry Andric   if (StringRef(ReturnValueFragment.begin()->Spelling)
706*0fca6ea1SDimitry Andric           .starts_with("type-parameter")) {
707*0fca6ea1SDimitry Andric     std::string ProperArgName = Func->getReturnType().getAsString();
7085f757f3fSDimitry Andric     ReturnValueFragment.begin()->Spelling.swap(ProperArgName);
7095f757f3fSDimitry Andric   }
7105f757f3fSDimitry Andric 
7115f757f3fSDimitry Andric   Fragments.append(std::move(ReturnValueFragment))
71281ad6265SDimitry Andric       .appendSpace()
713*0fca6ea1SDimitry Andric       .append(Func->getNameAsString(),
714*0fca6ea1SDimitry Andric               DeclarationFragments::FragmentKind::Identifier);
7155f757f3fSDimitry Andric 
7165f757f3fSDimitry Andric   if (Func->getTemplateSpecializationInfo()) {
7175f757f3fSDimitry Andric     Fragments.append("<", DeclarationFragments::FragmentKind::Text);
7185f757f3fSDimitry Andric 
7195f757f3fSDimitry Andric     for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) {
7205f757f3fSDimitry Andric       if (i)
7215f757f3fSDimitry Andric         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
7225f757f3fSDimitry Andric       Fragments.append(
7235f757f3fSDimitry Andric           getFragmentsForType(Func->getParamDecl(i)->getType(),
7245f757f3fSDimitry Andric                               Func->getParamDecl(i)->getASTContext(), After));
7255f757f3fSDimitry Andric     }
7265f757f3fSDimitry Andric     Fragments.append(">", DeclarationFragments::FragmentKind::Text);
7275f757f3fSDimitry Andric   }
7285f757f3fSDimitry Andric   Fragments.append(std::move(After));
72981ad6265SDimitry Andric 
73081ad6265SDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
7315f757f3fSDimitry Andric   unsigned NumParams = Func->getNumParams();
7325f757f3fSDimitry Andric   for (unsigned i = 0; i != NumParams; ++i) {
73381ad6265SDimitry Andric     if (i)
73481ad6265SDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
73581ad6265SDimitry Andric     Fragments.append(getFragmentsForParam(Func->getParamDecl(i)));
73681ad6265SDimitry Andric   }
7375f757f3fSDimitry Andric 
7385f757f3fSDimitry Andric   if (Func->isVariadic()) {
7395f757f3fSDimitry Andric     if (NumParams > 0)
7405f757f3fSDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
7415f757f3fSDimitry Andric     Fragments.append("...", DeclarationFragments::FragmentKind::Text);
7425f757f3fSDimitry Andric   }
74381ad6265SDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
74481ad6265SDimitry Andric 
7455f757f3fSDimitry Andric   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
7465f757f3fSDimitry Andric       Func->getExceptionSpecType()));
7475f757f3fSDimitry Andric 
748*0fca6ea1SDimitry Andric   return Fragments.appendSemicolon();
74981ad6265SDimitry Andric }
75081ad6265SDimitry Andric 
75181ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant(
75281ad6265SDimitry Andric     const EnumConstantDecl *EnumConstDecl) {
75381ad6265SDimitry Andric   DeclarationFragments Fragments;
75481ad6265SDimitry Andric   return Fragments.append(EnumConstDecl->getName(),
75581ad6265SDimitry Andric                           DeclarationFragments::FragmentKind::Identifier);
75681ad6265SDimitry Andric }
75781ad6265SDimitry Andric 
75881ad6265SDimitry Andric DeclarationFragments
75981ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {
76081ad6265SDimitry Andric   if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl())
76181ad6265SDimitry Andric     return getFragmentsForTypedef(TypedefNameDecl);
76281ad6265SDimitry Andric 
76381ad6265SDimitry Andric   DeclarationFragments Fragments, After;
76481ad6265SDimitry Andric   Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword);
76581ad6265SDimitry Andric 
76681ad6265SDimitry Andric   if (!EnumDecl->getName().empty())
76781ad6265SDimitry Andric     Fragments.appendSpace().append(
76881ad6265SDimitry Andric         EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier);
76981ad6265SDimitry Andric 
77081ad6265SDimitry Andric   QualType IntegerType = EnumDecl->getIntegerType();
77181ad6265SDimitry Andric   if (!IntegerType.isNull())
772*0fca6ea1SDimitry Andric     Fragments.appendSpace()
773*0fca6ea1SDimitry Andric         .append(": ", DeclarationFragments::FragmentKind::Text)
77481ad6265SDimitry Andric         .append(
77581ad6265SDimitry Andric             getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))
77681ad6265SDimitry Andric         .append(std::move(After));
77781ad6265SDimitry Andric 
778*0fca6ea1SDimitry Andric   if (EnumDecl->getName().empty())
779*0fca6ea1SDimitry Andric     Fragments.appendSpace().append("{ ... }",
780*0fca6ea1SDimitry Andric                                    DeclarationFragments::FragmentKind::Text);
781*0fca6ea1SDimitry Andric 
782*0fca6ea1SDimitry Andric   return Fragments.appendSemicolon();
78381ad6265SDimitry Andric }
78481ad6265SDimitry Andric 
78581ad6265SDimitry Andric DeclarationFragments
78681ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) {
78781ad6265SDimitry Andric   DeclarationFragments After;
7885f757f3fSDimitry Andric   DeclarationFragments Fragments;
7895f757f3fSDimitry Andric   if (Field->isMutable())
7905f757f3fSDimitry Andric     Fragments.append("mutable", DeclarationFragments::FragmentKind::Keyword)
7915f757f3fSDimitry Andric         .appendSpace();
7925f757f3fSDimitry Andric   return Fragments
7935f757f3fSDimitry Andric       .append(
7945f757f3fSDimitry Andric           getFragmentsForType(Field->getType(), Field->getASTContext(), After))
79581ad6265SDimitry Andric       .appendSpace()
79681ad6265SDimitry Andric       .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)
7975f757f3fSDimitry Andric       .append(std::move(After))
798*0fca6ea1SDimitry Andric       .appendSemicolon();
79981ad6265SDimitry Andric }
80081ad6265SDimitry Andric 
8017a6dacacSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
8027a6dacacSDimitry Andric     const RecordDecl *Record) {
80381ad6265SDimitry Andric   if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
80481ad6265SDimitry Andric     return getFragmentsForTypedef(TypedefNameDecl);
80581ad6265SDimitry Andric 
80681ad6265SDimitry Andric   DeclarationFragments Fragments;
8077a6dacacSDimitry Andric   if (Record->isUnion())
8087a6dacacSDimitry Andric     Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);
8097a6dacacSDimitry Andric   else
81081ad6265SDimitry Andric     Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);
81181ad6265SDimitry Andric 
812*0fca6ea1SDimitry Andric   Fragments.appendSpace();
81381ad6265SDimitry Andric   if (!Record->getName().empty())
814*0fca6ea1SDimitry Andric     Fragments.append(Record->getName(),
815*0fca6ea1SDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
816*0fca6ea1SDimitry Andric   else
817*0fca6ea1SDimitry Andric     Fragments.append("{ ... }", DeclarationFragments::FragmentKind::Text);
81806c3fb27SDimitry Andric 
819*0fca6ea1SDimitry Andric   return Fragments.appendSemicolon();
82081ad6265SDimitry Andric }
82181ad6265SDimitry Andric 
8225f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
8235f757f3fSDimitry Andric     const CXXRecordDecl *Record) {
8245f757f3fSDimitry Andric   if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
8255f757f3fSDimitry Andric     return getFragmentsForTypedef(TypedefNameDecl);
8265f757f3fSDimitry Andric 
8275f757f3fSDimitry Andric   DeclarationFragments Fragments;
8285f757f3fSDimitry Andric   Fragments.append(DeclarationFragments::getStructureTypeFragment(Record));
8295f757f3fSDimitry Andric 
8305f757f3fSDimitry Andric   if (!Record->getName().empty())
8315f757f3fSDimitry Andric     Fragments.appendSpace().append(
8325f757f3fSDimitry Andric         Record->getName(), DeclarationFragments::FragmentKind::Identifier);
8335f757f3fSDimitry Andric 
834*0fca6ea1SDimitry Andric   return Fragments.appendSemicolon();
8355f757f3fSDimitry Andric }
8365f757f3fSDimitry Andric 
8375f757f3fSDimitry Andric DeclarationFragments
8385f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(
8395f757f3fSDimitry Andric     const CXXMethodDecl *Method) {
8405f757f3fSDimitry Andric   DeclarationFragments Fragments;
8415f757f3fSDimitry Andric   std::string Name;
8425f757f3fSDimitry Andric   if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(Method)) {
8435f757f3fSDimitry Andric     Name = Method->getNameAsString();
8445f757f3fSDimitry Andric     if (Constructor->isExplicit())
8455f757f3fSDimitry Andric       Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
8465f757f3fSDimitry Andric           .appendSpace();
8475f757f3fSDimitry Andric   } else if (isa<CXXDestructorDecl>(Method))
8485f757f3fSDimitry Andric     Name = Method->getNameAsString();
8495f757f3fSDimitry Andric 
8505f757f3fSDimitry Andric   DeclarationFragments After;
8515f757f3fSDimitry Andric   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier)
8525f757f3fSDimitry Andric       .append(std::move(After));
8535f757f3fSDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
8545f757f3fSDimitry Andric   for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
8555f757f3fSDimitry Andric     if (i)
8565f757f3fSDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
8575f757f3fSDimitry Andric     Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
8585f757f3fSDimitry Andric   }
8595f757f3fSDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
8605f757f3fSDimitry Andric 
8615f757f3fSDimitry Andric   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
8625f757f3fSDimitry Andric       Method->getExceptionSpecType()));
8635f757f3fSDimitry Andric 
864*0fca6ea1SDimitry Andric   return Fragments.appendSemicolon();
8655f757f3fSDimitry Andric }
8665f757f3fSDimitry Andric 
8675f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
8685f757f3fSDimitry Andric     const CXXMethodDecl *Method) {
8695f757f3fSDimitry Andric   DeclarationFragments Fragments;
8705f757f3fSDimitry Andric   StringRef Name = Method->getName();
8715f757f3fSDimitry Andric   if (Method->isStatic())
8725f757f3fSDimitry Andric     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
8735f757f3fSDimitry Andric         .appendSpace();
8745f757f3fSDimitry Andric   if (Method->isConstexpr())
8755f757f3fSDimitry Andric     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
8765f757f3fSDimitry Andric         .appendSpace();
8775f757f3fSDimitry Andric   if (Method->isVolatile())
8785f757f3fSDimitry Andric     Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword)
8795f757f3fSDimitry Andric         .appendSpace();
8805f757f3fSDimitry Andric 
8815f757f3fSDimitry Andric   // Build return type
8825f757f3fSDimitry Andric   DeclarationFragments After;
8835f757f3fSDimitry Andric   Fragments
8845f757f3fSDimitry Andric       .append(getFragmentsForType(Method->getReturnType(),
8855f757f3fSDimitry Andric                                   Method->getASTContext(), After))
8865f757f3fSDimitry Andric       .appendSpace()
8875f757f3fSDimitry Andric       .append(Name, DeclarationFragments::FragmentKind::Identifier)
8885f757f3fSDimitry Andric       .append(std::move(After));
8895f757f3fSDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
8905f757f3fSDimitry Andric   for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
8915f757f3fSDimitry Andric     if (i)
8925f757f3fSDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
8935f757f3fSDimitry Andric     Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
8945f757f3fSDimitry Andric   }
8955f757f3fSDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
8965f757f3fSDimitry Andric 
8975f757f3fSDimitry Andric   if (Method->isConst())
8985f757f3fSDimitry Andric     Fragments.appendSpace().append("const",
8995f757f3fSDimitry Andric                                    DeclarationFragments::FragmentKind::Keyword);
9005f757f3fSDimitry Andric 
9015f757f3fSDimitry Andric   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
9025f757f3fSDimitry Andric       Method->getExceptionSpecType()));
9035f757f3fSDimitry Andric 
904*0fca6ea1SDimitry Andric   return Fragments.appendSemicolon();
9055f757f3fSDimitry Andric }
9065f757f3fSDimitry Andric 
9075f757f3fSDimitry Andric DeclarationFragments
9085f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForConversionFunction(
9095f757f3fSDimitry Andric     const CXXConversionDecl *ConversionFunction) {
9105f757f3fSDimitry Andric   DeclarationFragments Fragments;
9115f757f3fSDimitry Andric 
9125f757f3fSDimitry Andric   if (ConversionFunction->isExplicit())
9135f757f3fSDimitry Andric     Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
9145f757f3fSDimitry Andric         .appendSpace();
9155f757f3fSDimitry Andric 
9165f757f3fSDimitry Andric   Fragments.append("operator", DeclarationFragments::FragmentKind::Keyword)
9175f757f3fSDimitry Andric       .appendSpace();
9185f757f3fSDimitry Andric 
9195f757f3fSDimitry Andric   Fragments
9205f757f3fSDimitry Andric       .append(ConversionFunction->getConversionType().getAsString(),
9215f757f3fSDimitry Andric               DeclarationFragments::FragmentKind::TypeIdentifier)
9225f757f3fSDimitry Andric       .append("(", DeclarationFragments::FragmentKind::Text);
9235f757f3fSDimitry Andric   for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end;
9245f757f3fSDimitry Andric        ++i) {
9255f757f3fSDimitry Andric     if (i)
9265f757f3fSDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
9275f757f3fSDimitry Andric     Fragments.append(getFragmentsForParam(ConversionFunction->getParamDecl(i)));
9285f757f3fSDimitry Andric   }
9295f757f3fSDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
9305f757f3fSDimitry Andric 
9315f757f3fSDimitry Andric   if (ConversionFunction->isConst())
9325f757f3fSDimitry Andric     Fragments.appendSpace().append("const",
9335f757f3fSDimitry Andric                                    DeclarationFragments::FragmentKind::Keyword);
9345f757f3fSDimitry Andric 
935*0fca6ea1SDimitry Andric   return Fragments.appendSemicolon();
9365f757f3fSDimitry Andric }
9375f757f3fSDimitry Andric 
9385f757f3fSDimitry Andric DeclarationFragments
9395f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(
9405f757f3fSDimitry Andric     const CXXMethodDecl *Method) {
9415f757f3fSDimitry Andric   DeclarationFragments Fragments;
9425f757f3fSDimitry Andric 
9435f757f3fSDimitry Andric   // Build return type
9445f757f3fSDimitry Andric   DeclarationFragments After;
9455f757f3fSDimitry Andric   Fragments
9465f757f3fSDimitry Andric       .append(getFragmentsForType(Method->getReturnType(),
9475f757f3fSDimitry Andric                                   Method->getASTContext(), After))
9485f757f3fSDimitry Andric       .appendSpace()
9495f757f3fSDimitry Andric       .append(Method->getNameAsString(),
9505f757f3fSDimitry Andric               DeclarationFragments::FragmentKind::Identifier)
9515f757f3fSDimitry Andric       .append(std::move(After));
9525f757f3fSDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
9535f757f3fSDimitry Andric   for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
9545f757f3fSDimitry Andric     if (i)
9555f757f3fSDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
9565f757f3fSDimitry Andric     Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
9575f757f3fSDimitry Andric   }
9585f757f3fSDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
9595f757f3fSDimitry Andric 
9605f757f3fSDimitry Andric   if (Method->isConst())
9615f757f3fSDimitry Andric     Fragments.appendSpace().append("const",
9625f757f3fSDimitry Andric                                    DeclarationFragments::FragmentKind::Keyword);
9635f757f3fSDimitry Andric 
9645f757f3fSDimitry Andric   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
9655f757f3fSDimitry Andric       Method->getExceptionSpecType()));
9665f757f3fSDimitry Andric 
967*0fca6ea1SDimitry Andric   return Fragments.appendSemicolon();
9685f757f3fSDimitry Andric }
9695f757f3fSDimitry Andric 
9705f757f3fSDimitry Andric // Get fragments for template parameters, e.g. T in tempalte<typename T> ...
9715f757f3fSDimitry Andric DeclarationFragments
9725f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForTemplateParameters(
9735f757f3fSDimitry Andric     ArrayRef<NamedDecl *> ParameterArray) {
9745f757f3fSDimitry Andric   DeclarationFragments Fragments;
9755f757f3fSDimitry Andric   for (unsigned i = 0, end = ParameterArray.size(); i != end; ++i) {
9765f757f3fSDimitry Andric     if (i)
9775f757f3fSDimitry Andric       Fragments.append(",", DeclarationFragments::FragmentKind::Text)
9785f757f3fSDimitry Andric           .appendSpace();
9795f757f3fSDimitry Andric 
980*0fca6ea1SDimitry Andric     if (const auto *TemplateParam =
981*0fca6ea1SDimitry Andric             dyn_cast<TemplateTypeParmDecl>(ParameterArray[i])) {
9825f757f3fSDimitry Andric       if (TemplateParam->hasTypeConstraint())
9835f757f3fSDimitry Andric         Fragments.append(TemplateParam->getTypeConstraint()
9845f757f3fSDimitry Andric                              ->getNamedConcept()
9855f757f3fSDimitry Andric                              ->getName()
9865f757f3fSDimitry Andric                              .str(),
9875f757f3fSDimitry Andric                          DeclarationFragments::FragmentKind::TypeIdentifier);
9885f757f3fSDimitry Andric       else if (TemplateParam->wasDeclaredWithTypename())
989*0fca6ea1SDimitry Andric         Fragments.append("typename",
990*0fca6ea1SDimitry Andric                          DeclarationFragments::FragmentKind::Keyword);
9915f757f3fSDimitry Andric       else
9925f757f3fSDimitry Andric         Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);
9935f757f3fSDimitry Andric 
9945f757f3fSDimitry Andric       if (TemplateParam->isParameterPack())
9955f757f3fSDimitry Andric         Fragments.append("...", DeclarationFragments::FragmentKind::Text);
9965f757f3fSDimitry Andric 
997*0fca6ea1SDimitry Andric       if (!TemplateParam->getName().empty())
9985f757f3fSDimitry Andric         Fragments.appendSpace().append(
9995f757f3fSDimitry Andric             TemplateParam->getName(),
10005f757f3fSDimitry Andric             DeclarationFragments::FragmentKind::GenericParameter);
1001*0fca6ea1SDimitry Andric 
1002*0fca6ea1SDimitry Andric       if (TemplateParam->hasDefaultArgument()) {
1003*0fca6ea1SDimitry Andric         const auto Default = TemplateParam->getDefaultArgument();
1004*0fca6ea1SDimitry Andric         Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)
1005*0fca6ea1SDimitry Andric             .append(getFragmentsForTemplateArguments(
1006*0fca6ea1SDimitry Andric                 {Default.getArgument()}, TemplateParam->getASTContext(),
1007*0fca6ea1SDimitry Andric                 {Default}));
1008*0fca6ea1SDimitry Andric       }
1009*0fca6ea1SDimitry Andric     } else if (const auto *NTP =
1010*0fca6ea1SDimitry Andric                    dyn_cast<NonTypeTemplateParmDecl>(ParameterArray[i])) {
1011*0fca6ea1SDimitry Andric       DeclarationFragments After;
1012*0fca6ea1SDimitry Andric       const auto TyFragments =
1013*0fca6ea1SDimitry Andric           getFragmentsForType(NTP->getType(), NTP->getASTContext(), After);
1014*0fca6ea1SDimitry Andric       Fragments.append(std::move(TyFragments)).append(std::move(After));
1015*0fca6ea1SDimitry Andric 
1016*0fca6ea1SDimitry Andric       if (NTP->isParameterPack())
1017*0fca6ea1SDimitry Andric         Fragments.append("...", DeclarationFragments::FragmentKind::Text);
1018*0fca6ea1SDimitry Andric 
1019*0fca6ea1SDimitry Andric       if (!NTP->getName().empty())
1020*0fca6ea1SDimitry Andric         Fragments.appendSpace().append(
1021*0fca6ea1SDimitry Andric             NTP->getName(),
1022*0fca6ea1SDimitry Andric             DeclarationFragments::FragmentKind::GenericParameter);
1023*0fca6ea1SDimitry Andric 
1024*0fca6ea1SDimitry Andric       if (NTP->hasDefaultArgument()) {
1025*0fca6ea1SDimitry Andric         SmallString<8> ExprStr;
1026*0fca6ea1SDimitry Andric         raw_svector_ostream Output(ExprStr);
1027*0fca6ea1SDimitry Andric         NTP->getDefaultArgument().getArgument().print(
1028*0fca6ea1SDimitry Andric             NTP->getASTContext().getPrintingPolicy(), Output,
1029*0fca6ea1SDimitry Andric             /*IncludeType=*/false);
1030*0fca6ea1SDimitry Andric         Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)
1031*0fca6ea1SDimitry Andric             .append(ExprStr, DeclarationFragments::FragmentKind::Text);
1032*0fca6ea1SDimitry Andric       }
1033*0fca6ea1SDimitry Andric     } else if (const auto *TTP =
1034*0fca6ea1SDimitry Andric                    dyn_cast<TemplateTemplateParmDecl>(ParameterArray[i])) {
1035*0fca6ea1SDimitry Andric       Fragments.append("template", DeclarationFragments::FragmentKind::Keyword)
1036*0fca6ea1SDimitry Andric           .appendSpace()
1037*0fca6ea1SDimitry Andric           .append("<", DeclarationFragments::FragmentKind::Text)
1038*0fca6ea1SDimitry Andric           .append(getFragmentsForTemplateParameters(
1039*0fca6ea1SDimitry Andric               TTP->getTemplateParameters()->asArray()))
1040*0fca6ea1SDimitry Andric           .append(">", DeclarationFragments::FragmentKind::Text)
1041*0fca6ea1SDimitry Andric           .appendSpace()
1042*0fca6ea1SDimitry Andric           .append(TTP->wasDeclaredWithTypename() ? "typename" : "class",
1043*0fca6ea1SDimitry Andric                   DeclarationFragments::FragmentKind::Keyword);
1044*0fca6ea1SDimitry Andric 
1045*0fca6ea1SDimitry Andric       if (TTP->isParameterPack())
1046*0fca6ea1SDimitry Andric         Fragments.append("...", DeclarationFragments::FragmentKind::Text);
1047*0fca6ea1SDimitry Andric 
1048*0fca6ea1SDimitry Andric       if (!TTP->getName().empty())
1049*0fca6ea1SDimitry Andric         Fragments.appendSpace().append(
1050*0fca6ea1SDimitry Andric             TTP->getName(),
1051*0fca6ea1SDimitry Andric             DeclarationFragments::FragmentKind::GenericParameter);
1052*0fca6ea1SDimitry Andric       if (TTP->hasDefaultArgument()) {
1053*0fca6ea1SDimitry Andric         const auto Default = TTP->getDefaultArgument();
1054*0fca6ea1SDimitry Andric         Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)
1055*0fca6ea1SDimitry Andric             .append(getFragmentsForTemplateArguments(
1056*0fca6ea1SDimitry Andric                 {Default.getArgument()}, TTP->getASTContext(), {Default}));
1057*0fca6ea1SDimitry Andric       }
1058*0fca6ea1SDimitry Andric     }
10595f757f3fSDimitry Andric   }
10605f757f3fSDimitry Andric   return Fragments;
10615f757f3fSDimitry Andric }
10625f757f3fSDimitry Andric 
10635f757f3fSDimitry Andric // Get fragments for template arguments, e.g. int in template<typename T>
10645f757f3fSDimitry Andric // Foo<int>;
10655f757f3fSDimitry Andric //
10665f757f3fSDimitry Andric // Note: TemplateParameters is only necessary if the Decl is a
10675f757f3fSDimitry Andric // PartialSpecialization, where we need the parameters to deduce the name of the
10685f757f3fSDimitry Andric // generic arguments.
10695f757f3fSDimitry Andric DeclarationFragments
10705f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForTemplateArguments(
10715f757f3fSDimitry Andric     const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context,
1072*0fca6ea1SDimitry Andric     const std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs) {
10735f757f3fSDimitry Andric   DeclarationFragments Fragments;
10745f757f3fSDimitry Andric   for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) {
10755f757f3fSDimitry Andric     if (i)
10765f757f3fSDimitry Andric       Fragments.append(",", DeclarationFragments::FragmentKind::Text)
10775f757f3fSDimitry Andric           .appendSpace();
10785f757f3fSDimitry Andric 
1079*0fca6ea1SDimitry Andric     const auto &CTA = TemplateArguments[i];
1080*0fca6ea1SDimitry Andric     switch (CTA.getKind()) {
1081*0fca6ea1SDimitry Andric     case TemplateArgument::Type: {
10825f757f3fSDimitry Andric       DeclarationFragments After;
10835f757f3fSDimitry Andric       DeclarationFragments ArgumentFragment =
1084*0fca6ea1SDimitry Andric           getFragmentsForType(CTA.getAsType(), Context, After);
10855f757f3fSDimitry Andric 
1086*0fca6ea1SDimitry Andric       if (StringRef(ArgumentFragment.begin()->Spelling)
1087*0fca6ea1SDimitry Andric               .starts_with("type-parameter")) {
1088*0fca6ea1SDimitry Andric         if (TemplateArgumentLocs.has_value() &&
1089*0fca6ea1SDimitry Andric             TemplateArgumentLocs->size() > i) {
1090*0fca6ea1SDimitry Andric           std::string ProperArgName = TemplateArgumentLocs.value()[i]
1091*0fca6ea1SDimitry Andric                                           .getTypeSourceInfo()
1092*0fca6ea1SDimitry Andric                                           ->getType()
1093*0fca6ea1SDimitry Andric                                           .getAsString();
10945f757f3fSDimitry Andric           ArgumentFragment.begin()->Spelling.swap(ProperArgName);
1095*0fca6ea1SDimitry Andric         } else {
1096*0fca6ea1SDimitry Andric           auto &Spelling = ArgumentFragment.begin()->Spelling;
1097*0fca6ea1SDimitry Andric           Spelling.clear();
1098*0fca6ea1SDimitry Andric           raw_string_ostream OutStream(Spelling);
1099*0fca6ea1SDimitry Andric           CTA.print(Context.getPrintingPolicy(), OutStream, false);
1100*0fca6ea1SDimitry Andric           OutStream.flush();
11015f757f3fSDimitry Andric         }
1102*0fca6ea1SDimitry Andric       }
11035f757f3fSDimitry Andric 
1104*0fca6ea1SDimitry Andric       Fragments.append(std::move(ArgumentFragment));
1105*0fca6ea1SDimitry Andric       break;
1106*0fca6ea1SDimitry Andric     }
1107*0fca6ea1SDimitry Andric     case TemplateArgument::Declaration: {
1108*0fca6ea1SDimitry Andric       const auto *VD = CTA.getAsDecl();
1109*0fca6ea1SDimitry Andric       SmallString<128> USR;
1110*0fca6ea1SDimitry Andric       index::generateUSRForDecl(VD, USR);
1111*0fca6ea1SDimitry Andric       Fragments.append(VD->getNameAsString(),
1112*0fca6ea1SDimitry Andric                        DeclarationFragments::FragmentKind::Identifier, USR);
1113*0fca6ea1SDimitry Andric       break;
1114*0fca6ea1SDimitry Andric     }
1115*0fca6ea1SDimitry Andric     case TemplateArgument::NullPtr:
1116*0fca6ea1SDimitry Andric       Fragments.append("nullptr", DeclarationFragments::FragmentKind::Keyword);
1117*0fca6ea1SDimitry Andric       break;
1118*0fca6ea1SDimitry Andric 
1119*0fca6ea1SDimitry Andric     case TemplateArgument::Integral: {
1120*0fca6ea1SDimitry Andric       SmallString<4> Str;
1121*0fca6ea1SDimitry Andric       CTA.getAsIntegral().toString(Str);
1122*0fca6ea1SDimitry Andric       Fragments.append(Str, DeclarationFragments::FragmentKind::Text);
1123*0fca6ea1SDimitry Andric       break;
1124*0fca6ea1SDimitry Andric     }
1125*0fca6ea1SDimitry Andric 
1126*0fca6ea1SDimitry Andric     case TemplateArgument::StructuralValue: {
1127*0fca6ea1SDimitry Andric       const auto SVTy = CTA.getStructuralValueType();
1128*0fca6ea1SDimitry Andric       Fragments.append(CTA.getAsStructuralValue().getAsString(Context, SVTy),
1129*0fca6ea1SDimitry Andric                        DeclarationFragments::FragmentKind::Text);
1130*0fca6ea1SDimitry Andric       break;
1131*0fca6ea1SDimitry Andric     }
1132*0fca6ea1SDimitry Andric 
1133*0fca6ea1SDimitry Andric     case TemplateArgument::TemplateExpansion:
1134*0fca6ea1SDimitry Andric     case TemplateArgument::Template: {
1135*0fca6ea1SDimitry Andric       std::string Str;
1136*0fca6ea1SDimitry Andric       raw_string_ostream Stream(Str);
1137*0fca6ea1SDimitry Andric       CTA.getAsTemplate().print(Stream, Context.getPrintingPolicy());
1138*0fca6ea1SDimitry Andric       SmallString<64> USR("");
1139*0fca6ea1SDimitry Andric       if (const auto *TemplDecl =
1140*0fca6ea1SDimitry Andric               CTA.getAsTemplateOrTemplatePattern().getAsTemplateDecl())
1141*0fca6ea1SDimitry Andric         index::generateUSRForDecl(TemplDecl, USR);
1142*0fca6ea1SDimitry Andric       Fragments.append(Str, DeclarationFragments::FragmentKind::TypeIdentifier,
1143*0fca6ea1SDimitry Andric                        USR);
1144*0fca6ea1SDimitry Andric       if (CTA.getKind() == TemplateArgument::TemplateExpansion)
11455f757f3fSDimitry Andric         Fragments.append("...", DeclarationFragments::FragmentKind::Text);
1146*0fca6ea1SDimitry Andric       break;
1147*0fca6ea1SDimitry Andric     }
1148*0fca6ea1SDimitry Andric 
1149*0fca6ea1SDimitry Andric     case TemplateArgument::Pack:
1150*0fca6ea1SDimitry Andric       Fragments.append("<", DeclarationFragments::FragmentKind::Text)
1151*0fca6ea1SDimitry Andric           .append(getFragmentsForTemplateArguments(CTA.pack_elements(), Context,
1152*0fca6ea1SDimitry Andric                                                    {}))
1153*0fca6ea1SDimitry Andric           .append(">", DeclarationFragments::FragmentKind::Text);
1154*0fca6ea1SDimitry Andric       break;
1155*0fca6ea1SDimitry Andric 
1156*0fca6ea1SDimitry Andric     case TemplateArgument::Expression: {
1157*0fca6ea1SDimitry Andric       SmallString<8> ExprStr;
1158*0fca6ea1SDimitry Andric       raw_svector_ostream Output(ExprStr);
1159*0fca6ea1SDimitry Andric       CTA.getAsExpr()->printPretty(Output, nullptr,
1160*0fca6ea1SDimitry Andric                                    Context.getPrintingPolicy());
1161*0fca6ea1SDimitry Andric       Fragments.append(ExprStr, DeclarationFragments::FragmentKind::Text);
1162*0fca6ea1SDimitry Andric       break;
1163*0fca6ea1SDimitry Andric     }
1164*0fca6ea1SDimitry Andric 
1165*0fca6ea1SDimitry Andric     case TemplateArgument::Null:
1166*0fca6ea1SDimitry Andric       break;
1167*0fca6ea1SDimitry Andric     }
11685f757f3fSDimitry Andric   }
11695f757f3fSDimitry Andric   return Fragments;
11705f757f3fSDimitry Andric }
11715f757f3fSDimitry Andric 
11725f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept(
11735f757f3fSDimitry Andric     const ConceptDecl *Concept) {
11745f757f3fSDimitry Andric   DeclarationFragments Fragments;
11755f757f3fSDimitry Andric   return Fragments
11765f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1177*0fca6ea1SDimitry Andric       .appendSpace()
11785f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
11795f757f3fSDimitry Andric       .append(getFragmentsForTemplateParameters(
11805f757f3fSDimitry Andric           Concept->getTemplateParameters()->asArray()))
11815f757f3fSDimitry Andric       .append("> ", DeclarationFragments::FragmentKind::Text)
1182*0fca6ea1SDimitry Andric       .appendSpace()
11835f757f3fSDimitry Andric       .append("concept", DeclarationFragments::FragmentKind::Keyword)
11845f757f3fSDimitry Andric       .appendSpace()
11855f757f3fSDimitry Andric       .append(Concept->getName().str(),
11865f757f3fSDimitry Andric               DeclarationFragments::FragmentKind::Identifier)
1187*0fca6ea1SDimitry Andric       .appendSemicolon();
11885f757f3fSDimitry Andric }
11895f757f3fSDimitry Andric 
11905f757f3fSDimitry Andric DeclarationFragments
11915f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
11925f757f3fSDimitry Andric     const RedeclarableTemplateDecl *RedeclarableTemplate) {
11935f757f3fSDimitry Andric   DeclarationFragments Fragments;
11945f757f3fSDimitry Andric   Fragments.append("template", DeclarationFragments::FragmentKind::Keyword)
1195*0fca6ea1SDimitry Andric       .appendSpace()
11965f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
11975f757f3fSDimitry Andric       .append(getFragmentsForTemplateParameters(
11985f757f3fSDimitry Andric           RedeclarableTemplate->getTemplateParameters()->asArray()))
11995f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
12005f757f3fSDimitry Andric       .appendSpace();
12015f757f3fSDimitry Andric 
12025f757f3fSDimitry Andric   if (isa<TypeAliasTemplateDecl>(RedeclarableTemplate))
12035f757f3fSDimitry Andric     Fragments.appendSpace()
12045f757f3fSDimitry Andric         .append("using", DeclarationFragments::FragmentKind::Keyword)
12055f757f3fSDimitry Andric         .appendSpace()
12065f757f3fSDimitry Andric         .append(RedeclarableTemplate->getName(),
12075f757f3fSDimitry Andric                 DeclarationFragments::FragmentKind::Identifier);
12085f757f3fSDimitry Andric   // the templated records will be resposbible for injecting their templates
12095f757f3fSDimitry Andric   return Fragments.appendSpace();
12105f757f3fSDimitry Andric }
12115f757f3fSDimitry Andric 
12125f757f3fSDimitry Andric DeclarationFragments
12135f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization(
12145f757f3fSDimitry Andric     const ClassTemplateSpecializationDecl *Decl) {
12155f757f3fSDimitry Andric   DeclarationFragments Fragments;
12165f757f3fSDimitry Andric   return Fragments
12175f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1218*0fca6ea1SDimitry Andric       .appendSpace()
12195f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
12205f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
12215f757f3fSDimitry Andric       .appendSpace()
12225f757f3fSDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(
12235f757f3fSDimitry Andric           cast<CXXRecordDecl>(Decl)))
12245f757f3fSDimitry Andric       .pop_back() // there is an extra semicolon now
12255f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1226*0fca6ea1SDimitry Andric       .append(getFragmentsForTemplateArguments(
1227*0fca6ea1SDimitry Andric           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1228*0fca6ea1SDimitry Andric           Decl->getTemplateArgsAsWritten()->arguments()))
12295f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1230*0fca6ea1SDimitry Andric       .appendSemicolon();
12315f757f3fSDimitry Andric }
12325f757f3fSDimitry Andric 
12335f757f3fSDimitry Andric DeclarationFragments
12345f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization(
12355f757f3fSDimitry Andric     const ClassTemplatePartialSpecializationDecl *Decl) {
12365f757f3fSDimitry Andric   DeclarationFragments Fragments;
12375f757f3fSDimitry Andric   return Fragments
12385f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1239*0fca6ea1SDimitry Andric       .appendSpace()
12405f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
12415f757f3fSDimitry Andric       .append(getFragmentsForTemplateParameters(
12425f757f3fSDimitry Andric           Decl->getTemplateParameters()->asArray()))
12435f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
12445f757f3fSDimitry Andric       .appendSpace()
12455f757f3fSDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(
12465f757f3fSDimitry Andric           cast<CXXRecordDecl>(Decl)))
12475f757f3fSDimitry Andric       .pop_back() // there is an extra semicolon now
12485f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
12495f757f3fSDimitry Andric       .append(getFragmentsForTemplateArguments(
12505f757f3fSDimitry Andric           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1251*0fca6ea1SDimitry Andric           Decl->getTemplateArgsAsWritten()->arguments()))
12525f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1253*0fca6ea1SDimitry Andric       .appendSemicolon();
12545f757f3fSDimitry Andric }
12555f757f3fSDimitry Andric 
12565f757f3fSDimitry Andric DeclarationFragments
12575f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization(
12585f757f3fSDimitry Andric     const VarTemplateSpecializationDecl *Decl) {
12595f757f3fSDimitry Andric   DeclarationFragments Fragments;
12605f757f3fSDimitry Andric   return Fragments
12615f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1262*0fca6ea1SDimitry Andric       .appendSpace()
12635f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
12645f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
12655f757f3fSDimitry Andric       .appendSpace()
12665f757f3fSDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))
12675f757f3fSDimitry Andric       .pop_back() // there is an extra semicolon now
12685f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1269*0fca6ea1SDimitry Andric       .append(getFragmentsForTemplateArguments(
1270*0fca6ea1SDimitry Andric           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1271*0fca6ea1SDimitry Andric           Decl->getTemplateArgsAsWritten()->arguments()))
12725f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1273*0fca6ea1SDimitry Andric       .appendSemicolon();
12745f757f3fSDimitry Andric }
12755f757f3fSDimitry Andric 
12765f757f3fSDimitry Andric DeclarationFragments
12775f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization(
12785f757f3fSDimitry Andric     const VarTemplatePartialSpecializationDecl *Decl) {
12795f757f3fSDimitry Andric   DeclarationFragments Fragments;
12805f757f3fSDimitry Andric   return Fragments
12815f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1282*0fca6ea1SDimitry Andric       .appendSpace()
12835f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
12845f757f3fSDimitry Andric       // Partial specs may have new params.
12855f757f3fSDimitry Andric       .append(getFragmentsForTemplateParameters(
12865f757f3fSDimitry Andric           Decl->getTemplateParameters()->asArray()))
12875f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
12885f757f3fSDimitry Andric       .appendSpace()
12895f757f3fSDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))
12905f757f3fSDimitry Andric       .pop_back() // there is an extra semicolon now
12915f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
12925f757f3fSDimitry Andric       .append(getFragmentsForTemplateArguments(
12935f757f3fSDimitry Andric           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1294*0fca6ea1SDimitry Andric           Decl->getTemplateArgsAsWritten()->arguments()))
12955f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1296*0fca6ea1SDimitry Andric       .appendSemicolon();
12975f757f3fSDimitry Andric }
12985f757f3fSDimitry Andric 
12995f757f3fSDimitry Andric DeclarationFragments
13005f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(
13015f757f3fSDimitry Andric     const FunctionTemplateDecl *Decl) {
13025f757f3fSDimitry Andric   DeclarationFragments Fragments;
13035f757f3fSDimitry Andric   return Fragments
13045f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1305*0fca6ea1SDimitry Andric       .appendSpace()
13065f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
13075f757f3fSDimitry Andric       // Partial specs may have new params.
13085f757f3fSDimitry Andric       .append(getFragmentsForTemplateParameters(
13095f757f3fSDimitry Andric           Decl->getTemplateParameters()->asArray()))
13105f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
13115f757f3fSDimitry Andric       .appendSpace()
13125f757f3fSDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForFunction(
13135f757f3fSDimitry Andric           Decl->getAsFunction()));
13145f757f3fSDimitry Andric }
13155f757f3fSDimitry Andric 
13165f757f3fSDimitry Andric DeclarationFragments
13175f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization(
13185f757f3fSDimitry Andric     const FunctionDecl *Decl) {
13195f757f3fSDimitry Andric   DeclarationFragments Fragments;
13205f757f3fSDimitry Andric   return Fragments
13215f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1322*0fca6ea1SDimitry Andric       .appendSpace()
13235f757f3fSDimitry Andric       .append("<>", DeclarationFragments::FragmentKind::Text)
13245f757f3fSDimitry Andric       .appendSpace()
13255f757f3fSDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForFunction(Decl));
13265f757f3fSDimitry Andric }
13275f757f3fSDimitry Andric 
132881ad6265SDimitry Andric DeclarationFragments
132981ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name,
133081ad6265SDimitry Andric                                                   const MacroDirective *MD) {
133181ad6265SDimitry Andric   DeclarationFragments Fragments;
133281ad6265SDimitry Andric   Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword)
133381ad6265SDimitry Andric       .appendSpace();
133481ad6265SDimitry Andric   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
133581ad6265SDimitry Andric 
133681ad6265SDimitry Andric   auto *MI = MD->getMacroInfo();
133781ad6265SDimitry Andric 
133881ad6265SDimitry Andric   if (MI->isFunctionLike()) {
133981ad6265SDimitry Andric     Fragments.append("(", DeclarationFragments::FragmentKind::Text);
134081ad6265SDimitry Andric     unsigned numParameters = MI->getNumParams();
134181ad6265SDimitry Andric     if (MI->isC99Varargs())
134281ad6265SDimitry Andric       --numParameters;
134381ad6265SDimitry Andric     for (unsigned i = 0; i < numParameters; ++i) {
134481ad6265SDimitry Andric       if (i)
134581ad6265SDimitry Andric         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
134681ad6265SDimitry Andric       Fragments.append(MI->params()[i]->getName(),
134781ad6265SDimitry Andric                        DeclarationFragments::FragmentKind::InternalParam);
134881ad6265SDimitry Andric     }
134981ad6265SDimitry Andric     if (MI->isVariadic()) {
135081ad6265SDimitry Andric       if (numParameters && MI->isC99Varargs())
135181ad6265SDimitry Andric         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
135281ad6265SDimitry Andric       Fragments.append("...", DeclarationFragments::FragmentKind::Text);
135381ad6265SDimitry Andric     }
135481ad6265SDimitry Andric     Fragments.append(")", DeclarationFragments::FragmentKind::Text);
135581ad6265SDimitry Andric   }
135681ad6265SDimitry Andric   return Fragments;
135781ad6265SDimitry Andric }
135881ad6265SDimitry Andric 
135981ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory(
136081ad6265SDimitry Andric     const ObjCCategoryDecl *Category) {
136181ad6265SDimitry Andric   DeclarationFragments Fragments;
136281ad6265SDimitry Andric 
1363bdd1243dSDimitry Andric   auto *Interface = Category->getClassInterface();
136481ad6265SDimitry Andric   SmallString<128> InterfaceUSR;
1365bdd1243dSDimitry Andric   index::generateUSRForDecl(Interface, InterfaceUSR);
136681ad6265SDimitry Andric 
136781ad6265SDimitry Andric   Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
136881ad6265SDimitry Andric       .appendSpace()
1369*0fca6ea1SDimitry Andric       .append(Interface->getName(),
1370bdd1243dSDimitry Andric               DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR,
1371bdd1243dSDimitry Andric               Interface)
137281ad6265SDimitry Andric       .append(" (", DeclarationFragments::FragmentKind::Text)
137381ad6265SDimitry Andric       .append(Category->getName(),
137481ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Identifier)
137581ad6265SDimitry Andric       .append(")", DeclarationFragments::FragmentKind::Text);
137681ad6265SDimitry Andric 
137781ad6265SDimitry Andric   return Fragments;
137881ad6265SDimitry Andric }
137981ad6265SDimitry Andric 
138081ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface(
138181ad6265SDimitry Andric     const ObjCInterfaceDecl *Interface) {
138281ad6265SDimitry Andric   DeclarationFragments Fragments;
138381ad6265SDimitry Andric   // Build the base of the Objective-C interface declaration.
138481ad6265SDimitry Andric   Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
138581ad6265SDimitry Andric       .appendSpace()
138681ad6265SDimitry Andric       .append(Interface->getName(),
138781ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Identifier);
138881ad6265SDimitry Andric 
138981ad6265SDimitry Andric   // Build the inheritance part of the declaration.
139081ad6265SDimitry Andric   if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) {
139181ad6265SDimitry Andric     SmallString<128> SuperUSR;
139281ad6265SDimitry Andric     index::generateUSRForDecl(SuperClass, SuperUSR);
139381ad6265SDimitry Andric     Fragments.append(" : ", DeclarationFragments::FragmentKind::Text)
139481ad6265SDimitry Andric         .append(SuperClass->getName(),
1395bdd1243dSDimitry Andric                 DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR,
1396bdd1243dSDimitry Andric                 SuperClass);
139781ad6265SDimitry Andric   }
139881ad6265SDimitry Andric 
139981ad6265SDimitry Andric   return Fragments;
140081ad6265SDimitry Andric }
140181ad6265SDimitry Andric 
140281ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod(
140381ad6265SDimitry Andric     const ObjCMethodDecl *Method) {
140481ad6265SDimitry Andric   DeclarationFragments Fragments, After;
140581ad6265SDimitry Andric   // Build the instance/class method indicator.
140681ad6265SDimitry Andric   if (Method->isClassMethod())
140781ad6265SDimitry Andric     Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
140881ad6265SDimitry Andric   else if (Method->isInstanceMethod())
140981ad6265SDimitry Andric     Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
141081ad6265SDimitry Andric 
141181ad6265SDimitry Andric   // Build the return type.
141281ad6265SDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text)
141381ad6265SDimitry Andric       .append(getFragmentsForType(Method->getReturnType(),
141481ad6265SDimitry Andric                                   Method->getASTContext(), After))
141581ad6265SDimitry Andric       .append(std::move(After))
141681ad6265SDimitry Andric       .append(")", DeclarationFragments::FragmentKind::Text);
141781ad6265SDimitry Andric 
141881ad6265SDimitry Andric   // Build the selector part.
141981ad6265SDimitry Andric   Selector Selector = Method->getSelector();
142081ad6265SDimitry Andric   if (Selector.getNumArgs() == 0)
142181ad6265SDimitry Andric     // For Objective-C methods that don't take arguments, the first (and only)
142281ad6265SDimitry Andric     // slot of the selector is the method name.
142381ad6265SDimitry Andric     Fragments.appendSpace().append(
142481ad6265SDimitry Andric         Selector.getNameForSlot(0),
142581ad6265SDimitry Andric         DeclarationFragments::FragmentKind::Identifier);
142681ad6265SDimitry Andric 
142781ad6265SDimitry Andric   // For Objective-C methods that take arguments, build the selector slots.
142881ad6265SDimitry Andric   for (unsigned i = 0, end = Method->param_size(); i != end; ++i) {
142981ad6265SDimitry Andric     // Objective-C method selector parts are considered as identifiers instead
143081ad6265SDimitry Andric     // of "external parameters" as in Swift. This is because Objective-C method
143181ad6265SDimitry Andric     // symbols are referenced with the entire selector, instead of just the
143281ad6265SDimitry Andric     // method name in Swift.
143381ad6265SDimitry Andric     SmallString<32> ParamID(Selector.getNameForSlot(i));
143481ad6265SDimitry Andric     ParamID.append(":");
143581ad6265SDimitry Andric     Fragments.appendSpace().append(
143681ad6265SDimitry Andric         ParamID, DeclarationFragments::FragmentKind::Identifier);
143781ad6265SDimitry Andric 
143881ad6265SDimitry Andric     // Build the internal parameter.
143981ad6265SDimitry Andric     const ParmVarDecl *Param = Method->getParamDecl(i);
144081ad6265SDimitry Andric     Fragments.append(getFragmentsForParam(Param));
144181ad6265SDimitry Andric   }
144281ad6265SDimitry Andric 
1443*0fca6ea1SDimitry Andric   return Fragments.appendSemicolon();
144481ad6265SDimitry Andric }
144581ad6265SDimitry Andric 
144681ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
144781ad6265SDimitry Andric     const ObjCPropertyDecl *Property) {
144881ad6265SDimitry Andric   DeclarationFragments Fragments, After;
144981ad6265SDimitry Andric 
145081ad6265SDimitry Andric   // Build the Objective-C property keyword.
145181ad6265SDimitry Andric   Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword);
145281ad6265SDimitry Andric 
145306c3fb27SDimitry Andric   const auto Attributes = Property->getPropertyAttributesAsWritten();
145481ad6265SDimitry Andric   // Build the attributes if there is any associated with the property.
145581ad6265SDimitry Andric   if (Attributes != ObjCPropertyAttribute::kind_noattr) {
145681ad6265SDimitry Andric     // No leading comma for the first attribute.
145781ad6265SDimitry Andric     bool First = true;
145881ad6265SDimitry Andric     Fragments.append(" (", DeclarationFragments::FragmentKind::Text);
145981ad6265SDimitry Andric     // Helper function to render the attribute.
146081ad6265SDimitry Andric     auto RenderAttribute =
146181ad6265SDimitry Andric         [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling,
146281ad6265SDimitry Andric             StringRef Arg = "",
146381ad6265SDimitry Andric             DeclarationFragments::FragmentKind ArgKind =
146481ad6265SDimitry Andric                 DeclarationFragments::FragmentKind::Identifier) {
146581ad6265SDimitry Andric           // Check if the `Kind` attribute is set for this property.
146681ad6265SDimitry Andric           if ((Attributes & Kind) && !Spelling.empty()) {
146781ad6265SDimitry Andric             // Add a leading comma if this is not the first attribute rendered.
146881ad6265SDimitry Andric             if (!First)
146981ad6265SDimitry Andric               Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
147081ad6265SDimitry Andric             // Render the spelling of this attribute `Kind` as a keyword.
147181ad6265SDimitry Andric             Fragments.append(Spelling,
147281ad6265SDimitry Andric                              DeclarationFragments::FragmentKind::Keyword);
147381ad6265SDimitry Andric             // If this attribute takes in arguments (e.g. `getter=getterName`),
147481ad6265SDimitry Andric             // render the arguments.
147581ad6265SDimitry Andric             if (!Arg.empty())
147681ad6265SDimitry Andric               Fragments.append("=", DeclarationFragments::FragmentKind::Text)
147781ad6265SDimitry Andric                   .append(Arg, ArgKind);
147881ad6265SDimitry Andric             First = false;
147981ad6265SDimitry Andric           }
148081ad6265SDimitry Andric         };
148181ad6265SDimitry Andric 
148281ad6265SDimitry Andric     // Go through all possible Objective-C property attributes and render set
148381ad6265SDimitry Andric     // ones.
148481ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_class, "class");
148581ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct");
148681ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic");
148781ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic");
148881ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign");
148981ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain");
149081ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong");
149181ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy");
149281ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak");
149381ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained,
149481ad6265SDimitry Andric                     "unsafe_unretained");
149581ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite");
149681ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly");
149781ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter",
149881ad6265SDimitry Andric                     Property->getGetterName().getAsString());
149981ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter",
150081ad6265SDimitry Andric                     Property->getSetterName().getAsString());
150181ad6265SDimitry Andric 
150281ad6265SDimitry Andric     // Render nullability attributes.
150381ad6265SDimitry Andric     if (Attributes & ObjCPropertyAttribute::kind_nullability) {
150481ad6265SDimitry Andric       QualType Type = Property->getType();
150581ad6265SDimitry Andric       if (const auto Nullability =
150681ad6265SDimitry Andric               AttributedType::stripOuterNullability(Type)) {
150781ad6265SDimitry Andric         if (!First)
150881ad6265SDimitry Andric           Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
150981ad6265SDimitry Andric         if (*Nullability == NullabilityKind::Unspecified &&
151081ad6265SDimitry Andric             (Attributes & ObjCPropertyAttribute::kind_null_resettable))
151181ad6265SDimitry Andric           Fragments.append("null_resettable",
151281ad6265SDimitry Andric                            DeclarationFragments::FragmentKind::Keyword);
151381ad6265SDimitry Andric         else
151481ad6265SDimitry Andric           Fragments.append(
151581ad6265SDimitry Andric               getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true),
151681ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Keyword);
151781ad6265SDimitry Andric         First = false;
151881ad6265SDimitry Andric       }
151981ad6265SDimitry Andric     }
152081ad6265SDimitry Andric 
152181ad6265SDimitry Andric     Fragments.append(")", DeclarationFragments::FragmentKind::Text);
152281ad6265SDimitry Andric   }
152381ad6265SDimitry Andric 
15245f757f3fSDimitry Andric   Fragments.appendSpace();
15255f757f3fSDimitry Andric 
15265f757f3fSDimitry Andric   FunctionTypeLoc BlockLoc;
15275f757f3fSDimitry Andric   FunctionProtoTypeLoc BlockProtoLoc;
15285f757f3fSDimitry Andric   findTypeLocForBlockDecl(Property->getTypeSourceInfo(), BlockLoc,
15295f757f3fSDimitry Andric                           BlockProtoLoc);
15305f757f3fSDimitry Andric 
15315f757f3fSDimitry Andric   auto PropType = Property->getType();
15325f757f3fSDimitry Andric   if (!BlockLoc)
15335f757f3fSDimitry Andric     Fragments
15345f757f3fSDimitry Andric         .append(getFragmentsForType(PropType, Property->getASTContext(), After))
15355f757f3fSDimitry Andric         .appendSpace();
15365f757f3fSDimitry Andric   else
15375f757f3fSDimitry Andric     Fragments.append(
15385f757f3fSDimitry Andric         getFragmentsForBlock(Property, BlockLoc, BlockProtoLoc, After));
15395f757f3fSDimitry Andric 
15405f757f3fSDimitry Andric   return Fragments
154181ad6265SDimitry Andric       .append(Property->getName(),
154281ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Identifier)
15435f757f3fSDimitry Andric       .append(std::move(After))
1544*0fca6ea1SDimitry Andric       .appendSemicolon();
154581ad6265SDimitry Andric }
154681ad6265SDimitry Andric 
154781ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(
154881ad6265SDimitry Andric     const ObjCProtocolDecl *Protocol) {
154981ad6265SDimitry Andric   DeclarationFragments Fragments;
155081ad6265SDimitry Andric   // Build basic protocol declaration.
155181ad6265SDimitry Andric   Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword)
155281ad6265SDimitry Andric       .appendSpace()
155381ad6265SDimitry Andric       .append(Protocol->getName(),
155481ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Identifier);
155581ad6265SDimitry Andric 
155681ad6265SDimitry Andric   // If this protocol conforms to other protocols, build the conformance list.
155781ad6265SDimitry Andric   if (!Protocol->protocols().empty()) {
155881ad6265SDimitry Andric     Fragments.append(" <", DeclarationFragments::FragmentKind::Text);
155981ad6265SDimitry Andric     for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin();
156081ad6265SDimitry Andric          It != Protocol->protocol_end(); It++) {
156181ad6265SDimitry Andric       // Add a leading comma if this is not the first protocol rendered.
156281ad6265SDimitry Andric       if (It != Protocol->protocol_begin())
156381ad6265SDimitry Andric         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
156481ad6265SDimitry Andric 
156581ad6265SDimitry Andric       SmallString<128> USR;
156681ad6265SDimitry Andric       index::generateUSRForDecl(*It, USR);
156781ad6265SDimitry Andric       Fragments.append((*It)->getName(),
1568bdd1243dSDimitry Andric                        DeclarationFragments::FragmentKind::TypeIdentifier, USR,
1569bdd1243dSDimitry Andric                        *It);
157081ad6265SDimitry Andric     }
157181ad6265SDimitry Andric     Fragments.append(">", DeclarationFragments::FragmentKind::Text);
157281ad6265SDimitry Andric   }
157381ad6265SDimitry Andric 
157481ad6265SDimitry Andric   return Fragments;
157581ad6265SDimitry Andric }
157681ad6265SDimitry Andric 
157781ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(
157881ad6265SDimitry Andric     const TypedefNameDecl *Decl) {
157981ad6265SDimitry Andric   DeclarationFragments Fragments, After;
158081ad6265SDimitry Andric   Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword)
158181ad6265SDimitry Andric       .appendSpace()
158281ad6265SDimitry Andric       .append(getFragmentsForType(Decl->getUnderlyingType(),
158381ad6265SDimitry Andric                                   Decl->getASTContext(), After))
158481ad6265SDimitry Andric       .append(std::move(After))
158581ad6265SDimitry Andric       .appendSpace()
158681ad6265SDimitry Andric       .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
158781ad6265SDimitry Andric 
1588*0fca6ea1SDimitry Andric   return Fragments.appendSemicolon();
158981ad6265SDimitry Andric }
159081ad6265SDimitry Andric 
159181ad6265SDimitry Andric // Instantiate template for FunctionDecl.
159281ad6265SDimitry Andric template FunctionSignature
159381ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *);
159481ad6265SDimitry Andric 
159581ad6265SDimitry Andric // Instantiate template for ObjCMethodDecl.
159681ad6265SDimitry Andric template FunctionSignature
159781ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *);
159881ad6265SDimitry Andric 
159981ad6265SDimitry Andric // Subheading of a symbol defaults to its name.
160081ad6265SDimitry Andric DeclarationFragments
160181ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) {
160281ad6265SDimitry Andric   DeclarationFragments Fragments;
16035f757f3fSDimitry Andric   if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl))
16045f757f3fSDimitry Andric     Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(),
16055f757f3fSDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
16065f757f3fSDimitry Andric   else if (isa<CXXConversionDecl>(Decl)) {
16075f757f3fSDimitry Andric     Fragments.append(
16085f757f3fSDimitry Andric         cast<CXXConversionDecl>(Decl)->getConversionType().getAsString(),
16095f757f3fSDimitry Andric         DeclarationFragments::FragmentKind::Identifier);
16105f757f3fSDimitry Andric   } else if (isa<CXXMethodDecl>(Decl) &&
16115f757f3fSDimitry Andric              cast<CXXMethodDecl>(Decl)->isOverloadedOperator()) {
16125f757f3fSDimitry Andric     Fragments.append(Decl->getNameAsString(),
16135f757f3fSDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
1614*0fca6ea1SDimitry Andric   } else if (Decl->getIdentifier()) {
161581ad6265SDimitry Andric     Fragments.append(Decl->getName(),
161681ad6265SDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
1617*0fca6ea1SDimitry Andric   } else
1618*0fca6ea1SDimitry Andric     Fragments.append(Decl->getDeclName().getAsString(),
1619*0fca6ea1SDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
162081ad6265SDimitry Andric   return Fragments;
162181ad6265SDimitry Andric }
162281ad6265SDimitry Andric 
162381ad6265SDimitry Andric // Subheading of an Objective-C method is a `+` or `-` sign indicating whether
162481ad6265SDimitry Andric // it's a class method or an instance method, followed by the selector name.
162581ad6265SDimitry Andric DeclarationFragments
162681ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) {
162781ad6265SDimitry Andric   DeclarationFragments Fragments;
162881ad6265SDimitry Andric   if (Method->isClassMethod())
162981ad6265SDimitry Andric     Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
163081ad6265SDimitry Andric   else if (Method->isInstanceMethod())
163181ad6265SDimitry Andric     Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
163281ad6265SDimitry Andric 
163381ad6265SDimitry Andric   return Fragments.append(Method->getNameAsString(),
163481ad6265SDimitry Andric                           DeclarationFragments::FragmentKind::Identifier);
163581ad6265SDimitry Andric }
163681ad6265SDimitry Andric 
163781ad6265SDimitry Andric // Subheading of a symbol defaults to its name.
163881ad6265SDimitry Andric DeclarationFragments
163981ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) {
164081ad6265SDimitry Andric   DeclarationFragments Fragments;
164181ad6265SDimitry Andric   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
164281ad6265SDimitry Andric   return Fragments;
164381ad6265SDimitry Andric }
1644