xref: /llvm-project/clang/lib/ExtractAPI/DeclarationFragments.cpp (revision 33fa40cc9659b7b56a9b440edc0587ff58793cac)
189f6b26fSZixu Wang //===- ExtractAPI/DeclarationFragments.cpp ----------------------*- C++ -*-===//
289f6b26fSZixu Wang //
389f6b26fSZixu Wang // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
489f6b26fSZixu Wang // See https://llvm.org/LICENSE.txt for license information.
589f6b26fSZixu Wang // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
689f6b26fSZixu Wang //
789f6b26fSZixu Wang //===----------------------------------------------------------------------===//
889f6b26fSZixu Wang ///
989f6b26fSZixu Wang /// \file
1089f6b26fSZixu Wang /// This file implements Declaration Fragments related classes.
1189f6b26fSZixu Wang ///
1289f6b26fSZixu Wang //===----------------------------------------------------------------------===//
1389f6b26fSZixu Wang 
1489f6b26fSZixu Wang #include "clang/ExtractAPI/DeclarationFragments.h"
157a674793SDaniel Grumberg #include "clang/AST/ASTFwd.h"
1675f55eb3SErick Velez #include "clang/AST/Decl.h"
1775f55eb3SErick Velez #include "clang/AST/DeclCXX.h"
187a674793SDaniel Grumberg #include "clang/AST/TemplateBase.h"
197a674793SDaniel Grumberg #include "clang/AST/TemplateName.h"
206b89fab8SDaniel Grumberg #include "clang/AST/Type.h"
216b89fab8SDaniel Grumberg #include "clang/AST/TypeLoc.h"
22142c3d9dSDaniel Grumberg #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
2389f6b26fSZixu Wang #include "clang/Index/USRGeneration.h"
2489f6b26fSZixu Wang #include "llvm/ADT/StringSwitch.h"
257a674793SDaniel Grumberg #include "llvm/Support/ErrorHandling.h"
267a674793SDaniel Grumberg #include "llvm/Support/raw_ostream.h"
277a674793SDaniel Grumberg #include <optional>
2889f6b26fSZixu Wang 
2989f6b26fSZixu Wang using namespace clang::extractapi;
3089f6b26fSZixu Wang using namespace llvm;
3189f6b26fSZixu Wang 
326b89fab8SDaniel Grumberg namespace {
336b89fab8SDaniel Grumberg 
346b89fab8SDaniel Grumberg void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo,
356b89fab8SDaniel Grumberg                              clang::FunctionTypeLoc &Block,
366b89fab8SDaniel Grumberg                              clang::FunctionProtoTypeLoc &BlockProto) {
376b89fab8SDaniel Grumberg   if (!TSInfo)
386b89fab8SDaniel Grumberg     return;
396b89fab8SDaniel Grumberg 
406b89fab8SDaniel Grumberg   clang::TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
416b89fab8SDaniel Grumberg   while (true) {
426b89fab8SDaniel Grumberg     // Look through qualified types
436b89fab8SDaniel Grumberg     if (auto QualifiedTL = TL.getAs<clang::QualifiedTypeLoc>()) {
446b89fab8SDaniel Grumberg       TL = QualifiedTL.getUnqualifiedLoc();
456b89fab8SDaniel Grumberg       continue;
466b89fab8SDaniel Grumberg     }
476b89fab8SDaniel Grumberg 
486b89fab8SDaniel Grumberg     if (auto AttrTL = TL.getAs<clang::AttributedTypeLoc>()) {
496b89fab8SDaniel Grumberg       TL = AttrTL.getModifiedLoc();
506b89fab8SDaniel Grumberg       continue;
516b89fab8SDaniel Grumberg     }
526b89fab8SDaniel Grumberg 
536b89fab8SDaniel Grumberg     // Try to get the function prototype behind the block pointer type,
546b89fab8SDaniel Grumberg     // then we're done.
556b89fab8SDaniel Grumberg     if (auto BlockPtr = TL.getAs<clang::BlockPointerTypeLoc>()) {
566b89fab8SDaniel Grumberg       TL = BlockPtr.getPointeeLoc().IgnoreParens();
576b89fab8SDaniel Grumberg       Block = TL.getAs<clang::FunctionTypeLoc>();
586b89fab8SDaniel Grumberg       BlockProto = TL.getAs<clang::FunctionProtoTypeLoc>();
596b89fab8SDaniel Grumberg     }
606b89fab8SDaniel Grumberg     break;
616b89fab8SDaniel Grumberg   }
626b89fab8SDaniel Grumberg }
636b89fab8SDaniel Grumberg 
646b89fab8SDaniel Grumberg } // namespace
656b89fab8SDaniel Grumberg 
66e05c1b46SDaniel Grumberg DeclarationFragments &
67e05c1b46SDaniel Grumberg DeclarationFragments::appendUnduplicatedTextCharacter(char Character) {
6889f6b26fSZixu Wang   if (!Fragments.empty()) {
69fe2c77a0SZixu Wang     Fragment &Last = Fragments.back();
7089f6b26fSZixu Wang     if (Last.Kind == FragmentKind::Text) {
7189f6b26fSZixu Wang       // Merge the extra space into the last fragment if the last fragment is
7289f6b26fSZixu Wang       // also text.
73e05c1b46SDaniel Grumberg       if (Last.Spelling.back() != Character) { // avoid duplicates at end
74e05c1b46SDaniel Grumberg         Last.Spelling.push_back(Character);
7589f6b26fSZixu Wang       }
7689f6b26fSZixu Wang     } else {
7789f6b26fSZixu Wang       append("", FragmentKind::Text);
78e05c1b46SDaniel Grumberg       Fragments.back().Spelling.push_back(Character);
7989f6b26fSZixu Wang     }
8089f6b26fSZixu Wang   }
8189f6b26fSZixu Wang 
8289f6b26fSZixu Wang   return *this;
8389f6b26fSZixu Wang }
8489f6b26fSZixu Wang 
85e05c1b46SDaniel Grumberg DeclarationFragments &DeclarationFragments::appendSpace() {
86e05c1b46SDaniel Grumberg   return appendUnduplicatedTextCharacter(' ');
87e05c1b46SDaniel Grumberg }
88e05c1b46SDaniel Grumberg 
89e05c1b46SDaniel Grumberg DeclarationFragments &DeclarationFragments::appendSemicolon() {
90e05c1b46SDaniel Grumberg   return appendUnduplicatedTextCharacter(';');
91e05c1b46SDaniel Grumberg }
92e05c1b46SDaniel Grumberg 
93e05c1b46SDaniel Grumberg DeclarationFragments &DeclarationFragments::removeTrailingSemicolon() {
94e05c1b46SDaniel Grumberg   if (Fragments.empty())
95e05c1b46SDaniel Grumberg     return *this;
96e05c1b46SDaniel Grumberg 
97e05c1b46SDaniel Grumberg   Fragment &Last = Fragments.back();
98e05c1b46SDaniel Grumberg   if (Last.Kind == FragmentKind::Text && Last.Spelling.back() == ';')
99e05c1b46SDaniel Grumberg     Last.Spelling.pop_back();
100e05c1b46SDaniel Grumberg 
101e05c1b46SDaniel Grumberg   return *this;
102e05c1b46SDaniel Grumberg }
103e05c1b46SDaniel Grumberg 
10489f6b26fSZixu Wang StringRef DeclarationFragments::getFragmentKindString(
10589f6b26fSZixu Wang     DeclarationFragments::FragmentKind Kind) {
10689f6b26fSZixu Wang   switch (Kind) {
10789f6b26fSZixu Wang   case DeclarationFragments::FragmentKind::None:
10889f6b26fSZixu Wang     return "none";
10989f6b26fSZixu Wang   case DeclarationFragments::FragmentKind::Keyword:
11089f6b26fSZixu Wang     return "keyword";
11189f6b26fSZixu Wang   case DeclarationFragments::FragmentKind::Attribute:
11289f6b26fSZixu Wang     return "attribute";
11389f6b26fSZixu Wang   case DeclarationFragments::FragmentKind::NumberLiteral:
11489f6b26fSZixu Wang     return "number";
11589f6b26fSZixu Wang   case DeclarationFragments::FragmentKind::StringLiteral:
11689f6b26fSZixu Wang     return "string";
11789f6b26fSZixu Wang   case DeclarationFragments::FragmentKind::Identifier:
11889f6b26fSZixu Wang     return "identifier";
11989f6b26fSZixu Wang   case DeclarationFragments::FragmentKind::TypeIdentifier:
12089f6b26fSZixu Wang     return "typeIdentifier";
12189f6b26fSZixu Wang   case DeclarationFragments::FragmentKind::GenericParameter:
12289f6b26fSZixu Wang     return "genericParameter";
12389f6b26fSZixu Wang   case DeclarationFragments::FragmentKind::ExternalParam:
12489f6b26fSZixu Wang     return "externalParam";
12589f6b26fSZixu Wang   case DeclarationFragments::FragmentKind::InternalParam:
12689f6b26fSZixu Wang     return "internalParam";
12789f6b26fSZixu Wang   case DeclarationFragments::FragmentKind::Text:
12889f6b26fSZixu Wang     return "text";
12989f6b26fSZixu Wang   }
13089f6b26fSZixu Wang 
13189f6b26fSZixu Wang   llvm_unreachable("Unhandled FragmentKind");
13289f6b26fSZixu Wang }
13389f6b26fSZixu Wang 
13489f6b26fSZixu Wang DeclarationFragments::FragmentKind
13589f6b26fSZixu Wang DeclarationFragments::parseFragmentKindFromString(StringRef S) {
13689f6b26fSZixu Wang   return llvm::StringSwitch<FragmentKind>(S)
13789f6b26fSZixu Wang       .Case("keyword", DeclarationFragments::FragmentKind::Keyword)
13889f6b26fSZixu Wang       .Case("attribute", DeclarationFragments::FragmentKind::Attribute)
13989f6b26fSZixu Wang       .Case("number", DeclarationFragments::FragmentKind::NumberLiteral)
14089f6b26fSZixu Wang       .Case("string", DeclarationFragments::FragmentKind::StringLiteral)
14189f6b26fSZixu Wang       .Case("identifier", DeclarationFragments::FragmentKind::Identifier)
14289f6b26fSZixu Wang       .Case("typeIdentifier",
14389f6b26fSZixu Wang             DeclarationFragments::FragmentKind::TypeIdentifier)
14489f6b26fSZixu Wang       .Case("genericParameter",
14589f6b26fSZixu Wang             DeclarationFragments::FragmentKind::GenericParameter)
14689f6b26fSZixu Wang       .Case("internalParam", DeclarationFragments::FragmentKind::InternalParam)
14789f6b26fSZixu Wang       .Case("externalParam", DeclarationFragments::FragmentKind::ExternalParam)
14889f6b26fSZixu Wang       .Case("text", DeclarationFragments::FragmentKind::Text)
14989f6b26fSZixu Wang       .Default(DeclarationFragments::FragmentKind::None);
15089f6b26fSZixu Wang }
15189f6b26fSZixu Wang 
15275f55eb3SErick Velez DeclarationFragments DeclarationFragments::getExceptionSpecificationString(
15375f55eb3SErick Velez     ExceptionSpecificationType ExceptionSpec) {
15475f55eb3SErick Velez   DeclarationFragments Fragments;
15575f55eb3SErick Velez   switch (ExceptionSpec) {
15675f55eb3SErick Velez   case ExceptionSpecificationType::EST_None:
15775f55eb3SErick Velez     return Fragments;
15875f55eb3SErick Velez   case ExceptionSpecificationType::EST_DynamicNone:
15975f55eb3SErick Velez     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
16075f55eb3SErick Velez         .append("throw", DeclarationFragments::FragmentKind::Keyword)
16175f55eb3SErick Velez         .append("(", DeclarationFragments::FragmentKind::Text)
16275f55eb3SErick Velez         .append(")", DeclarationFragments::FragmentKind::Text);
16375f55eb3SErick Velez   case ExceptionSpecificationType::EST_Dynamic:
16475f55eb3SErick Velez     // FIXME: throw(int), get types of inner expression
16575f55eb3SErick Velez     return Fragments;
16675f55eb3SErick Velez   case ExceptionSpecificationType::EST_BasicNoexcept:
16775f55eb3SErick Velez     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
16875f55eb3SErick Velez         .append("noexcept", DeclarationFragments::FragmentKind::Keyword);
16975f55eb3SErick Velez   case ExceptionSpecificationType::EST_DependentNoexcept:
17075f55eb3SErick Velez     // FIXME: throw(conditional-expression), get expression
17175f55eb3SErick Velez     break;
17275f55eb3SErick Velez   case ExceptionSpecificationType::EST_NoexceptFalse:
17375f55eb3SErick Velez     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
17475f55eb3SErick Velez         .append("noexcept", DeclarationFragments::FragmentKind::Keyword)
17575f55eb3SErick Velez         .append("(", DeclarationFragments::FragmentKind::Text)
17675f55eb3SErick Velez         .append("false", DeclarationFragments::FragmentKind::Keyword)
17775f55eb3SErick Velez         .append(")", DeclarationFragments::FragmentKind::Text);
17875f55eb3SErick Velez   case ExceptionSpecificationType::EST_NoexceptTrue:
17975f55eb3SErick Velez     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
18075f55eb3SErick Velez         .append("noexcept", DeclarationFragments::FragmentKind::Keyword)
18175f55eb3SErick Velez         .append("(", DeclarationFragments::FragmentKind::Text)
18275f55eb3SErick Velez         .append("true", DeclarationFragments::FragmentKind::Keyword)
18375f55eb3SErick Velez         .append(")", DeclarationFragments::FragmentKind::Text);
18475f55eb3SErick Velez   default:
18575f55eb3SErick Velez     return Fragments;
18675f55eb3SErick Velez   }
18775f55eb3SErick Velez 
18875f55eb3SErick Velez   llvm_unreachable("Unhandled exception specification");
18975f55eb3SErick Velez }
19075f55eb3SErick Velez 
19175f55eb3SErick Velez DeclarationFragments
19275f55eb3SErick Velez DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) {
19375f55eb3SErick Velez   DeclarationFragments Fragments;
19475f55eb3SErick Velez   if (Record->isStruct())
19575f55eb3SErick Velez     Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);
19675f55eb3SErick Velez   else if (Record->isUnion())
19775f55eb3SErick Velez     Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);
19875f55eb3SErick Velez   else
19975f55eb3SErick Velez     Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);
20075f55eb3SErick Velez 
20175f55eb3SErick Velez   return Fragments;
20275f55eb3SErick Velez }
20375f55eb3SErick Velez 
20489f6b26fSZixu Wang // NNS stores C++ nested name specifiers, which are prefixes to qualified names.
20589f6b26fSZixu Wang // Build declaration fragments for NNS recursively so that we have the USR for
20689f6b26fSZixu Wang // every part in a qualified name, and also leaves the actual underlying type
20789f6b26fSZixu Wang // cleaner for its own fragment.
20889f6b26fSZixu Wang DeclarationFragments
20989f6b26fSZixu Wang DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS,
21089f6b26fSZixu Wang                                                 ASTContext &Context,
21189f6b26fSZixu Wang                                                 DeclarationFragments &After) {
21289f6b26fSZixu Wang   DeclarationFragments Fragments;
21389f6b26fSZixu Wang   if (NNS->getPrefix())
21489f6b26fSZixu Wang     Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After));
21589f6b26fSZixu Wang 
21689f6b26fSZixu Wang   switch (NNS->getKind()) {
21789f6b26fSZixu Wang   case NestedNameSpecifier::Identifier:
21889f6b26fSZixu Wang     Fragments.append(NNS->getAsIdentifier()->getName(),
21989f6b26fSZixu Wang                      DeclarationFragments::FragmentKind::Identifier);
22089f6b26fSZixu Wang     break;
22189f6b26fSZixu Wang 
22289f6b26fSZixu Wang   case NestedNameSpecifier::Namespace: {
22389f6b26fSZixu Wang     const NamespaceDecl *NS = NNS->getAsNamespace();
22489f6b26fSZixu Wang     if (NS->isAnonymousNamespace())
22589f6b26fSZixu Wang       return Fragments;
22689f6b26fSZixu Wang     SmallString<128> USR;
22789f6b26fSZixu Wang     index::generateUSRForDecl(NS, USR);
22889f6b26fSZixu Wang     Fragments.append(NS->getName(),
2297a851921SDaniel Grumberg                      DeclarationFragments::FragmentKind::Identifier, USR, NS);
23089f6b26fSZixu Wang     break;
23189f6b26fSZixu Wang   }
23289f6b26fSZixu Wang 
23389f6b26fSZixu Wang   case NestedNameSpecifier::NamespaceAlias: {
23489f6b26fSZixu Wang     const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias();
23589f6b26fSZixu Wang     SmallString<128> USR;
23689f6b26fSZixu Wang     index::generateUSRForDecl(Alias, USR);
23789f6b26fSZixu Wang     Fragments.append(Alias->getName(),
2387a851921SDaniel Grumberg                      DeclarationFragments::FragmentKind::Identifier, USR,
2397a851921SDaniel Grumberg                      Alias);
24089f6b26fSZixu Wang     break;
24189f6b26fSZixu Wang   }
24289f6b26fSZixu Wang 
24389f6b26fSZixu Wang   case NestedNameSpecifier::Global:
24489f6b26fSZixu Wang     // The global specifier `::` at the beginning. No stored value.
24589f6b26fSZixu Wang     break;
24689f6b26fSZixu Wang 
24789f6b26fSZixu Wang   case NestedNameSpecifier::Super:
24889f6b26fSZixu Wang     // Microsoft's `__super` specifier.
24989f6b26fSZixu Wang     Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword);
25089f6b26fSZixu Wang     break;
25189f6b26fSZixu Wang 
25289f6b26fSZixu Wang   case NestedNameSpecifier::TypeSpecWithTemplate:
25389f6b26fSZixu Wang     // A type prefixed by the `template` keyword.
25489f6b26fSZixu Wang     Fragments.append("template", DeclarationFragments::FragmentKind::Keyword);
25589f6b26fSZixu Wang     Fragments.appendSpace();
25689f6b26fSZixu Wang     // Fallthrough after adding the keyword to handle the actual type.
2573f18f7c0SFangrui Song     [[fallthrough]];
25889f6b26fSZixu Wang 
25989f6b26fSZixu Wang   case NestedNameSpecifier::TypeSpec: {
26089f6b26fSZixu Wang     const Type *T = NNS->getAsType();
26189f6b26fSZixu Wang     // FIXME: Handle C++ template specialization type
26289f6b26fSZixu Wang     Fragments.append(getFragmentsForType(T, Context, After));
26389f6b26fSZixu Wang     break;
26489f6b26fSZixu Wang   }
26589f6b26fSZixu Wang   }
26689f6b26fSZixu Wang 
26789f6b26fSZixu Wang   // Add the separator text `::` for this segment.
26889f6b26fSZixu Wang   return Fragments.append("::", DeclarationFragments::FragmentKind::Text);
26989f6b26fSZixu Wang }
27089f6b26fSZixu Wang 
27189f6b26fSZixu Wang // Recursively build the declaration fragments for an underlying `Type` with
27289f6b26fSZixu Wang // qualifiers removed.
27389f6b26fSZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
27489f6b26fSZixu Wang     const Type *T, ASTContext &Context, DeclarationFragments &After) {
27589f6b26fSZixu Wang   assert(T && "invalid type");
27689f6b26fSZixu Wang 
27789f6b26fSZixu Wang   DeclarationFragments Fragments;
27889f6b26fSZixu Wang 
279cf1ad281SDaniel Grumberg   if (const MacroQualifiedType *MQT = dyn_cast<MacroQualifiedType>(T)) {
280cf1ad281SDaniel Grumberg     Fragments.append(
281cf1ad281SDaniel Grumberg         getFragmentsForType(MQT->getUnderlyingType(), Context, After));
282cf1ad281SDaniel Grumberg     return Fragments;
283cf1ad281SDaniel Grumberg   }
284cf1ad281SDaniel Grumberg 
285cf1ad281SDaniel Grumberg   if (const AttributedType *AT = dyn_cast<AttributedType>(T)) {
286cf1ad281SDaniel Grumberg     // FIXME: Serialize Attributes correctly
287cf1ad281SDaniel Grumberg     Fragments.append(
288cf1ad281SDaniel Grumberg         getFragmentsForType(AT->getModifiedType(), Context, After));
289cf1ad281SDaniel Grumberg     return Fragments;
290cf1ad281SDaniel Grumberg   }
291cf1ad281SDaniel Grumberg 
292c5532124SDaniel Grumberg   // An ElaboratedType is a sugar for types that are referred to using an
293c5532124SDaniel Grumberg   // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a
294c5532124SDaniel Grumberg   // qualified name, e.g., `N::M::type`, or both.
295c5532124SDaniel Grumberg   if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) {
296c5532124SDaniel Grumberg     ElaboratedTypeKeyword Keyword = ET->getKeyword();
297c5532124SDaniel Grumberg     if (Keyword != ElaboratedTypeKeyword::None) {
298c5532124SDaniel Grumberg       Fragments
299c5532124SDaniel Grumberg           .append(ElaboratedType::getKeywordName(Keyword),
300c5532124SDaniel Grumberg                   DeclarationFragments::FragmentKind::Keyword)
301c5532124SDaniel Grumberg           .appendSpace();
302c5532124SDaniel Grumberg     }
303c5532124SDaniel Grumberg 
304c5532124SDaniel Grumberg     if (const NestedNameSpecifier *NNS = ET->getQualifier())
305c5532124SDaniel Grumberg       Fragments.append(getFragmentsForNNS(NNS, Context, After));
306c5532124SDaniel Grumberg 
307c5532124SDaniel Grumberg     // After handling the elaborated keyword or qualified name, build
308c5532124SDaniel Grumberg     // declaration fragments for the desugared underlying type.
309c5532124SDaniel Grumberg     return Fragments.append(getFragmentsForType(ET->desugar(), Context, After));
310c5532124SDaniel Grumberg   }
311c5532124SDaniel Grumberg 
312c5532124SDaniel Grumberg   // If the type is a typedefed type, get the underlying TypedefNameDecl for a
313c5532124SDaniel Grumberg   // direct reference to the typedef instead of the wrapped type.
314c5532124SDaniel Grumberg 
315c5532124SDaniel Grumberg   // 'id' type is a typedef for an ObjCObjectPointerType
316c5532124SDaniel Grumberg   //  we treat it as a typedef
317c5532124SDaniel Grumberg   if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) {
318c5532124SDaniel Grumberg     const TypedefNameDecl *Decl = TypedefTy->getDecl();
319c5532124SDaniel Grumberg     TypedefUnderlyingTypeResolver TypedefResolver(Context);
320c5532124SDaniel Grumberg     std::string USR = TypedefResolver.getUSRForType(QualType(T, 0));
321c5532124SDaniel Grumberg 
322c5532124SDaniel Grumberg     if (T->isObjCIdType()) {
323c5532124SDaniel Grumberg       return Fragments.append(Decl->getName(),
324c5532124SDaniel Grumberg                               DeclarationFragments::FragmentKind::Keyword);
325c5532124SDaniel Grumberg     }
326c5532124SDaniel Grumberg 
327c5532124SDaniel Grumberg     return Fragments.append(
328c5532124SDaniel Grumberg         Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier,
329c5532124SDaniel Grumberg         USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0)));
330c5532124SDaniel Grumberg   }
331c5532124SDaniel Grumberg 
33289f6b26fSZixu Wang   // Declaration fragments of a pointer type is the declaration fragments of
333a590d863SNagaChaitanya Vellanki   // the pointee type followed by a `*`,
3346b89fab8SDaniel Grumberg   if (T->isPointerType() && !T->isFunctionPointerType())
33589f6b26fSZixu Wang     return Fragments
33689f6b26fSZixu Wang         .append(getFragmentsForType(T->getPointeeType(), Context, After))
33789f6b26fSZixu Wang         .append(" *", DeclarationFragments::FragmentKind::Text);
338a590d863SNagaChaitanya Vellanki 
339a590d863SNagaChaitanya Vellanki   // For Objective-C `id` and `Class` pointers
340a590d863SNagaChaitanya Vellanki   // we do not spell out the `*`.
341a590d863SNagaChaitanya Vellanki   if (T->isObjCObjectPointerType() &&
342a590d863SNagaChaitanya Vellanki       !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) {
343a590d863SNagaChaitanya Vellanki 
344a590d863SNagaChaitanya Vellanki     Fragments.append(getFragmentsForType(T->getPointeeType(), Context, After));
345a590d863SNagaChaitanya Vellanki 
346a590d863SNagaChaitanya Vellanki     // id<protocol> is an qualified id type
347a590d863SNagaChaitanya Vellanki     // id<protocol>* is not an qualified id type
348a590d863SNagaChaitanya Vellanki     if (!T->getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) {
349a590d863SNagaChaitanya Vellanki       Fragments.append(" *", DeclarationFragments::FragmentKind::Text);
350a590d863SNagaChaitanya Vellanki     }
351a590d863SNagaChaitanya Vellanki 
352a590d863SNagaChaitanya Vellanki     return Fragments;
35389f6b26fSZixu Wang   }
35489f6b26fSZixu Wang 
35589f6b26fSZixu Wang   // Declaration fragments of a lvalue reference type is the declaration
35689f6b26fSZixu Wang   // fragments of the underlying type followed by a `&`.
35789f6b26fSZixu Wang   if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T))
35889f6b26fSZixu Wang     return Fragments
35989f6b26fSZixu Wang         .append(
36089f6b26fSZixu Wang             getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After))
36189f6b26fSZixu Wang         .append(" &", DeclarationFragments::FragmentKind::Text);
36289f6b26fSZixu Wang 
36389f6b26fSZixu Wang   // Declaration fragments of a rvalue reference type is the declaration
36489f6b26fSZixu Wang   // fragments of the underlying type followed by a `&&`.
36589f6b26fSZixu Wang   if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T))
36689f6b26fSZixu Wang     return Fragments
36789f6b26fSZixu Wang         .append(
36889f6b26fSZixu Wang             getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After))
36989f6b26fSZixu Wang         .append(" &&", DeclarationFragments::FragmentKind::Text);
37089f6b26fSZixu Wang 
37189f6b26fSZixu Wang   // Declaration fragments of an array-typed variable have two parts:
37289f6b26fSZixu Wang   // 1. the element type of the array that appears before the variable name;
37389f6b26fSZixu Wang   // 2. array brackets `[(0-9)?]` that appear after the variable name.
37489f6b26fSZixu Wang   if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) {
37589f6b26fSZixu Wang     // Build the "after" part first because the inner element type might also
37689f6b26fSZixu Wang     // be an array-type. For example `int matrix[3][4]` which has a type of
37789f6b26fSZixu Wang     // "(array 3 of (array 4 of ints))."
37889f6b26fSZixu Wang     // Push the array size part first to make sure they are in the right order.
37989f6b26fSZixu Wang     After.append("[", DeclarationFragments::FragmentKind::Text);
38089f6b26fSZixu Wang 
38189f6b26fSZixu Wang     switch (AT->getSizeModifier()) {
38249fd28d9SVlad Serebrennikov     case ArraySizeModifier::Normal:
38389f6b26fSZixu Wang       break;
38449fd28d9SVlad Serebrennikov     case ArraySizeModifier::Static:
38589f6b26fSZixu Wang       Fragments.append("static", DeclarationFragments::FragmentKind::Keyword);
38689f6b26fSZixu Wang       break;
38749fd28d9SVlad Serebrennikov     case ArraySizeModifier::Star:
38889f6b26fSZixu Wang       Fragments.append("*", DeclarationFragments::FragmentKind::Text);
38989f6b26fSZixu Wang       break;
39089f6b26fSZixu Wang     }
39189f6b26fSZixu Wang 
39289f6b26fSZixu Wang     if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
39389f6b26fSZixu Wang       // FIXME: right now this would evaluate any expressions/macros written in
39489f6b26fSZixu Wang       // the original source to concrete values. For example
39589f6b26fSZixu Wang       // `int nums[MAX]` -> `int nums[100]`
39689f6b26fSZixu Wang       // `char *str[5 + 1]` -> `char *str[6]`
39789f6b26fSZixu Wang       SmallString<128> Size;
39889f6b26fSZixu Wang       CAT->getSize().toStringUnsigned(Size);
39989f6b26fSZixu Wang       After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral);
40089f6b26fSZixu Wang     }
40189f6b26fSZixu Wang 
40289f6b26fSZixu Wang     After.append("]", DeclarationFragments::FragmentKind::Text);
40389f6b26fSZixu Wang 
40489f6b26fSZixu Wang     return Fragments.append(
40589f6b26fSZixu Wang         getFragmentsForType(AT->getElementType(), Context, After));
40689f6b26fSZixu Wang   }
40789f6b26fSZixu Wang 
4087a674793SDaniel Grumberg   if (const TemplateSpecializationType *TemplSpecTy =
4097a674793SDaniel Grumberg           dyn_cast<TemplateSpecializationType>(T)) {
4107a674793SDaniel Grumberg     const auto TemplName = TemplSpecTy->getTemplateName();
4117a674793SDaniel Grumberg     std::string Str;
4127a674793SDaniel Grumberg     raw_string_ostream Stream(Str);
4137a674793SDaniel Grumberg     TemplName.print(Stream, Context.getPrintingPolicy(),
4147a674793SDaniel Grumberg                     TemplateName::Qualified::AsWritten);
4157a674793SDaniel Grumberg     SmallString<64> USR("");
4167a674793SDaniel Grumberg     if (const auto *TemplDecl = TemplName.getAsTemplateDecl())
4177a674793SDaniel Grumberg       index::generateUSRForDecl(TemplDecl, USR);
4187a674793SDaniel Grumberg 
4197a674793SDaniel Grumberg     return Fragments
4207a674793SDaniel Grumberg         .append(Str, DeclarationFragments::FragmentKind::TypeIdentifier, USR)
4217a674793SDaniel Grumberg         .append("<", DeclarationFragments::FragmentKind::Text)
4227a674793SDaniel Grumberg         .append(getFragmentsForTemplateArguments(
4237a674793SDaniel Grumberg             TemplSpecTy->template_arguments(), Context, std::nullopt))
4247a674793SDaniel Grumberg         .append(">", DeclarationFragments::FragmentKind::Text);
4257a674793SDaniel Grumberg   }
4267a674793SDaniel Grumberg 
427c13ccf1fSNagaChaitanya Vellanki   // Everything we care about has been handled now, reduce to the canonical
428c13ccf1fSNagaChaitanya Vellanki   // unqualified base type.
429c13ccf1fSNagaChaitanya Vellanki   QualType Base = T->getCanonicalTypeUnqualified();
430c13ccf1fSNagaChaitanya Vellanki 
4319fc45ca0SDaniel Grumberg   // If the base type is a TagType (struct/interface/union/class/enum), let's
4329fc45ca0SDaniel Grumberg   // get the underlying Decl for better names and USRs.
4339fc45ca0SDaniel Grumberg   if (const TagType *TagTy = dyn_cast<TagType>(Base)) {
4349fc45ca0SDaniel Grumberg     const TagDecl *Decl = TagTy->getDecl();
4359fc45ca0SDaniel Grumberg     // Anonymous decl, skip this fragment.
4369fc45ca0SDaniel Grumberg     if (Decl->getName().empty())
4372bcbe40fSDaniel Grumberg       return Fragments.append("{ ... }",
4382bcbe40fSDaniel Grumberg                               DeclarationFragments::FragmentKind::Text);
4399fc45ca0SDaniel Grumberg     SmallString<128> TagUSR;
4409fc45ca0SDaniel Grumberg     clang::index::generateUSRForDecl(Decl, TagUSR);
4419fc45ca0SDaniel Grumberg     return Fragments.append(Decl->getName(),
4429fc45ca0SDaniel Grumberg                             DeclarationFragments::FragmentKind::TypeIdentifier,
4437a851921SDaniel Grumberg                             TagUSR, Decl);
4449fc45ca0SDaniel Grumberg   }
4459fc45ca0SDaniel Grumberg 
4469b36e126SZixu Wang   // If the base type is an ObjCInterfaceType, use the underlying
4479b36e126SZixu Wang   // ObjCInterfaceDecl for the true USR.
4489b36e126SZixu Wang   if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) {
4499b36e126SZixu Wang     const auto *Decl = ObjCIT->getDecl();
4509b36e126SZixu Wang     SmallString<128> USR;
4519b36e126SZixu Wang     index::generateUSRForDecl(Decl, USR);
4529b36e126SZixu Wang     return Fragments.append(Decl->getName(),
4539b36e126SZixu Wang                             DeclarationFragments::FragmentKind::TypeIdentifier,
4547a851921SDaniel Grumberg                             USR, Decl);
4559b36e126SZixu Wang   }
4569b36e126SZixu Wang 
45789f6b26fSZixu Wang   // Default fragment builder for other kinds of types (BuiltinType etc.)
45889f6b26fSZixu Wang   SmallString<128> USR;
45989f6b26fSZixu Wang   clang::index::generateUSRForType(Base, Context, USR);
46089f6b26fSZixu Wang   Fragments.append(Base.getAsString(),
46189f6b26fSZixu Wang                    DeclarationFragments::FragmentKind::TypeIdentifier, USR);
46289f6b26fSZixu Wang 
46389f6b26fSZixu Wang   return Fragments;
46489f6b26fSZixu Wang }
46589f6b26fSZixu Wang 
46689f6b26fSZixu Wang DeclarationFragments
46789f6b26fSZixu Wang DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) {
46889f6b26fSZixu Wang   DeclarationFragments Fragments;
46989f6b26fSZixu Wang   if (Quals.hasConst())
47089f6b26fSZixu Wang     Fragments.append("const", DeclarationFragments::FragmentKind::Keyword);
47189f6b26fSZixu Wang   if (Quals.hasVolatile())
47289f6b26fSZixu Wang     Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword);
47389f6b26fSZixu Wang   if (Quals.hasRestrict())
47489f6b26fSZixu Wang     Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword);
47589f6b26fSZixu Wang 
47689f6b26fSZixu Wang   return Fragments;
47789f6b26fSZixu Wang }
47889f6b26fSZixu Wang 
47989f6b26fSZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
48089f6b26fSZixu Wang     const QualType QT, ASTContext &Context, DeclarationFragments &After) {
48189f6b26fSZixu Wang   assert(!QT.isNull() && "invalid type");
48289f6b26fSZixu Wang 
48389f6b26fSZixu Wang   if (const ParenType *PT = dyn_cast<ParenType>(QT)) {
48489f6b26fSZixu Wang     After.append(")", DeclarationFragments::FragmentKind::Text);
48589f6b26fSZixu Wang     return getFragmentsForType(PT->getInnerType(), Context, After)
48689f6b26fSZixu Wang         .append("(", DeclarationFragments::FragmentKind::Text);
48789f6b26fSZixu Wang   }
48889f6b26fSZixu Wang 
48989f6b26fSZixu Wang   const SplitQualType SQT = QT.split();
49089f6b26fSZixu Wang   DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals),
49189f6b26fSZixu Wang                        TypeFragments =
49289f6b26fSZixu Wang                            getFragmentsForType(SQT.Ty, Context, After);
493e8174456SErick Velez   if (QT.getAsString() == "_Bool")
494e8174456SErick Velez     TypeFragments.replace("bool", 0);
495e8174456SErick Velez 
49689f6b26fSZixu Wang   if (QualsFragments.getFragments().empty())
49789f6b26fSZixu Wang     return TypeFragments;
49889f6b26fSZixu Wang 
49989f6b26fSZixu Wang   // Use east qualifier for pointer types
50089f6b26fSZixu Wang   // For example:
50189f6b26fSZixu Wang   // ```
50289f6b26fSZixu Wang   // int *   const
50389f6b26fSZixu Wang   // ^----   ^----
50489f6b26fSZixu Wang   //  type    qualifier
50589f6b26fSZixu Wang   // ^-----------------
50689f6b26fSZixu Wang   //  const pointer to int
50789f6b26fSZixu Wang   // ```
50889f6b26fSZixu Wang   // should not be reconstructed as
50989f6b26fSZixu Wang   // ```
51089f6b26fSZixu Wang   // const       int       *
51189f6b26fSZixu Wang   // ^----       ^--
51289f6b26fSZixu Wang   //  qualifier   type
51389f6b26fSZixu Wang   // ^----------------     ^
51489f6b26fSZixu Wang   //  pointer to const int
51589f6b26fSZixu Wang   // ```
51689f6b26fSZixu Wang   if (SQT.Ty->isAnyPointerType())
51789f6b26fSZixu Wang     return TypeFragments.appendSpace().append(std::move(QualsFragments));
51889f6b26fSZixu Wang 
51989f6b26fSZixu Wang   return QualsFragments.appendSpace().append(std::move(TypeFragments));
52089f6b26fSZixu Wang }
52189f6b26fSZixu Wang 
52208f034f9SErick Velez DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace(
52308f034f9SErick Velez     const NamespaceDecl *Decl) {
52408f034f9SErick Velez   DeclarationFragments Fragments;
52508f034f9SErick Velez   Fragments.append("namespace", DeclarationFragments::FragmentKind::Keyword);
52608f034f9SErick Velez   if (!Decl->isAnonymousNamespace())
52708f034f9SErick Velez     Fragments.appendSpace().append(
52808f034f9SErick Velez         Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
529e05c1b46SDaniel Grumberg   return Fragments.appendSemicolon();
53008f034f9SErick Velez }
53108f034f9SErick Velez 
53289f6b26fSZixu Wang DeclarationFragments
53389f6b26fSZixu Wang DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
53489f6b26fSZixu Wang   DeclarationFragments Fragments;
53575f55eb3SErick Velez   if (Var->isConstexpr())
53675f55eb3SErick Velez     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
53775f55eb3SErick Velez         .appendSpace();
53875f55eb3SErick Velez 
53989f6b26fSZixu Wang   StorageClass SC = Var->getStorageClass();
54089f6b26fSZixu Wang   if (SC != SC_None)
54189f6b26fSZixu Wang     Fragments
54289f6b26fSZixu Wang         .append(VarDecl::getStorageClassSpecifierString(SC),
54389f6b26fSZixu Wang                 DeclarationFragments::FragmentKind::Keyword)
54489f6b26fSZixu Wang         .appendSpace();
54589f6b26fSZixu Wang 
54689f6b26fSZixu Wang   // Capture potential fragments that needs to be placed after the variable name
54789f6b26fSZixu Wang   // ```
54889f6b26fSZixu Wang   // int nums[5];
54989f6b26fSZixu Wang   // char (*ptr_to_array)[6];
55089f6b26fSZixu Wang   // ```
55189f6b26fSZixu Wang   DeclarationFragments After;
5526b89fab8SDaniel Grumberg   FunctionTypeLoc BlockLoc;
5536b89fab8SDaniel Grumberg   FunctionProtoTypeLoc BlockProtoLoc;
5546b89fab8SDaniel Grumberg   findTypeLocForBlockDecl(Var->getTypeSourceInfo(), BlockLoc, BlockProtoLoc);
5556b89fab8SDaniel Grumberg 
5566b89fab8SDaniel Grumberg   if (!BlockLoc) {
5576b89fab8SDaniel Grumberg     QualType T = Var->getTypeSourceInfo()
5586b89fab8SDaniel Grumberg                      ? Var->getTypeSourceInfo()->getType()
5596b89fab8SDaniel Grumberg                      : Var->getASTContext().getUnqualifiedObjCPointerType(
5606b89fab8SDaniel Grumberg                            Var->getType());
5616b89fab8SDaniel Grumberg 
5626b89fab8SDaniel Grumberg     Fragments.append(getFragmentsForType(T, Var->getASTContext(), After))
5636b89fab8SDaniel Grumberg         .appendSpace();
5646b89fab8SDaniel Grumberg   } else {
5656b89fab8SDaniel Grumberg     Fragments.append(getFragmentsForBlock(Var, BlockLoc, BlockProtoLoc, After));
5666b89fab8SDaniel Grumberg   }
5676b89fab8SDaniel Grumberg 
5686b89fab8SDaniel Grumberg   return Fragments
56989f6b26fSZixu Wang       .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
570422bcd10SErick Velez       .append(std::move(After))
571e05c1b46SDaniel Grumberg       .appendSemicolon();
57289f6b26fSZixu Wang }
57389f6b26fSZixu Wang 
57489f6b26fSZixu Wang DeclarationFragments
5758d8c8981SErick Velez DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) {
5768d8c8981SErick Velez   DeclarationFragments Fragments;
5778d8c8981SErick Velez   if (Var->isConstexpr())
5788d8c8981SErick Velez     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
5798d8c8981SErick Velez         .appendSpace();
5808d8c8981SErick Velez   QualType T =
5818d8c8981SErick Velez       Var->getTypeSourceInfo()
5828d8c8981SErick Velez           ? Var->getTypeSourceInfo()->getType()
5838d8c8981SErick Velez           : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType());
5848d8c8981SErick Velez 
585634b2fd2SErick Velez   // Might be a member, so might be static.
586634b2fd2SErick Velez   if (Var->isStaticDataMember())
587634b2fd2SErick Velez     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
588634b2fd2SErick Velez         .appendSpace();
589634b2fd2SErick Velez 
5908d8c8981SErick Velez   DeclarationFragments After;
5918d8c8981SErick Velez   DeclarationFragments ArgumentFragment =
5928d8c8981SErick Velez       getFragmentsForType(T, Var->getASTContext(), After);
59326648daeSKazu Hirata   if (StringRef(ArgumentFragment.begin()->Spelling)
59426648daeSKazu Hirata           .starts_with("type-parameter")) {
5952b6c038eSErick Velez     std::string ProperArgName = T.getAsString();
5968d8c8981SErick Velez     ArgumentFragment.begin()->Spelling.swap(ProperArgName);
5978d8c8981SErick Velez   }
5988d8c8981SErick Velez   Fragments.append(std::move(ArgumentFragment))
5998d8c8981SErick Velez       .appendSpace()
6008d8c8981SErick Velez       .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
601e05c1b46SDaniel Grumberg       .appendSemicolon();
6028d8c8981SErick Velez   return Fragments;
6038d8c8981SErick Velez }
6048d8c8981SErick Velez 
6058d8c8981SErick Velez DeclarationFragments
60689f6b26fSZixu Wang DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) {
60789f6b26fSZixu Wang   DeclarationFragments Fragments, After;
60889f6b26fSZixu Wang 
6096b89fab8SDaniel Grumberg   auto *TSInfo = Param->getTypeSourceInfo();
6106b89fab8SDaniel Grumberg 
6116b89fab8SDaniel Grumberg   QualType T = TSInfo ? TSInfo->getType()
61289f6b26fSZixu Wang                       : Param->getASTContext().getUnqualifiedObjCPointerType(
61389f6b26fSZixu Wang                             Param->getType());
61489f6b26fSZixu Wang 
6156b89fab8SDaniel Grumberg   FunctionTypeLoc BlockLoc;
6166b89fab8SDaniel Grumberg   FunctionProtoTypeLoc BlockProtoLoc;
6176b89fab8SDaniel Grumberg   findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc);
6186b89fab8SDaniel Grumberg 
6196b89fab8SDaniel Grumberg   DeclarationFragments TypeFragments;
6206b89fab8SDaniel Grumberg   if (BlockLoc)
6216b89fab8SDaniel Grumberg     TypeFragments.append(
6226b89fab8SDaniel Grumberg         getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After));
6236b89fab8SDaniel Grumberg   else
6246b89fab8SDaniel Grumberg     TypeFragments.append(getFragmentsForType(T, Param->getASTContext(), After));
6256b89fab8SDaniel Grumberg 
62626648daeSKazu Hirata   if (StringRef(TypeFragments.begin()->Spelling)
62726648daeSKazu Hirata           .starts_with("type-parameter")) {
6282b6c038eSErick Velez     std::string ProperArgName = Param->getOriginalType().getAsString();
62980b787e8SErick Velez     TypeFragments.begin()->Spelling.swap(ProperArgName);
63080b787e8SErick Velez   }
63189f6b26fSZixu Wang 
6326b89fab8SDaniel Grumberg   if (Param->isObjCMethodParameter()) {
63389f6b26fSZixu Wang     Fragments.append("(", DeclarationFragments::FragmentKind::Text)
63489f6b26fSZixu Wang         .append(std::move(TypeFragments))
6356b89fab8SDaniel Grumberg         .append(std::move(After))
6366b89fab8SDaniel Grumberg         .append(") ", DeclarationFragments::FragmentKind::Text)
6376b89fab8SDaniel Grumberg         .append(Param->getName(),
6386b89fab8SDaniel Grumberg                 DeclarationFragments::FragmentKind::InternalParam);
6396b89fab8SDaniel Grumberg   } else {
6406b89fab8SDaniel Grumberg     Fragments.append(std::move(TypeFragments));
6416b89fab8SDaniel Grumberg     if (!T->isBlockPointerType())
6426b89fab8SDaniel Grumberg       Fragments.appendSpace();
6436b89fab8SDaniel Grumberg     Fragments
64489f6b26fSZixu Wang         .append(Param->getName(),
64589f6b26fSZixu Wang                 DeclarationFragments::FragmentKind::InternalParam)
64689f6b26fSZixu Wang         .append(std::move(After));
64789f6b26fSZixu Wang   }
6486b89fab8SDaniel Grumberg   return Fragments;
6496b89fab8SDaniel Grumberg }
6506b89fab8SDaniel Grumberg 
6516b89fab8SDaniel Grumberg DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForBlock(
6526b89fab8SDaniel Grumberg     const NamedDecl *BlockDecl, FunctionTypeLoc &Block,
6536b89fab8SDaniel Grumberg     FunctionProtoTypeLoc &BlockProto, DeclarationFragments &After) {
6546b89fab8SDaniel Grumberg   DeclarationFragments Fragments;
6556b89fab8SDaniel Grumberg 
6566b89fab8SDaniel Grumberg   DeclarationFragments RetTyAfter;
6576b89fab8SDaniel Grumberg   auto ReturnValueFragment = getFragmentsForType(
6586b89fab8SDaniel Grumberg       Block.getTypePtr()->getReturnType(), BlockDecl->getASTContext(), After);
6596b89fab8SDaniel Grumberg 
6606b89fab8SDaniel Grumberg   Fragments.append(std::move(ReturnValueFragment))
6616b89fab8SDaniel Grumberg       .append(std::move(RetTyAfter))
6626b89fab8SDaniel Grumberg       .appendSpace()
6636b89fab8SDaniel Grumberg       .append("(^", DeclarationFragments::FragmentKind::Text);
6646b89fab8SDaniel Grumberg 
6656b89fab8SDaniel Grumberg   After.append(")", DeclarationFragments::FragmentKind::Text);
6666b89fab8SDaniel Grumberg   unsigned NumParams = Block.getNumParams();
6676b89fab8SDaniel Grumberg 
6686b89fab8SDaniel Grumberg   if (!BlockProto || NumParams == 0) {
6696b89fab8SDaniel Grumberg     if (BlockProto && BlockProto.getTypePtr()->isVariadic())
6706b89fab8SDaniel Grumberg       After.append("(...)", DeclarationFragments::FragmentKind::Text);
6716b89fab8SDaniel Grumberg     else
6726b89fab8SDaniel Grumberg       After.append("()", DeclarationFragments::FragmentKind::Text);
6736b89fab8SDaniel Grumberg   } else {
6746b89fab8SDaniel Grumberg     After.append("(", DeclarationFragments::FragmentKind::Text);
6756b89fab8SDaniel Grumberg     for (unsigned I = 0; I != NumParams; ++I) {
6766b89fab8SDaniel Grumberg       if (I)
6776b89fab8SDaniel Grumberg         After.append(", ", DeclarationFragments::FragmentKind::Text);
6786b89fab8SDaniel Grumberg       After.append(getFragmentsForParam(Block.getParam(I)));
6796b89fab8SDaniel Grumberg       if (I == NumParams - 1 && BlockProto.getTypePtr()->isVariadic())
6806b89fab8SDaniel Grumberg         After.append(", ...", DeclarationFragments::FragmentKind::Text);
6816b89fab8SDaniel Grumberg     }
6826b89fab8SDaniel Grumberg     After.append(")", DeclarationFragments::FragmentKind::Text);
6836b89fab8SDaniel Grumberg   }
6846b89fab8SDaniel Grumberg 
6856b89fab8SDaniel Grumberg   return Fragments;
6866b89fab8SDaniel Grumberg }
68789f6b26fSZixu Wang 
68889f6b26fSZixu Wang DeclarationFragments
68989f6b26fSZixu Wang DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
69089f6b26fSZixu Wang   DeclarationFragments Fragments;
69189f6b26fSZixu Wang   switch (Func->getStorageClass()) {
69289f6b26fSZixu Wang   case SC_None:
69389f6b26fSZixu Wang   case SC_PrivateExtern:
69489f6b26fSZixu Wang     break;
69589f6b26fSZixu Wang   case SC_Extern:
69689f6b26fSZixu Wang     Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword)
69789f6b26fSZixu Wang         .appendSpace();
69889f6b26fSZixu Wang     break;
69989f6b26fSZixu Wang   case SC_Static:
70089f6b26fSZixu Wang     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
70189f6b26fSZixu Wang         .appendSpace();
70289f6b26fSZixu Wang     break;
70389f6b26fSZixu Wang   case SC_Auto:
70489f6b26fSZixu Wang   case SC_Register:
70589f6b26fSZixu Wang     llvm_unreachable("invalid for functions");
70689f6b26fSZixu Wang   }
70775f55eb3SErick Velez   if (Func->isConsteval()) // if consteval, it is also constexpr
70875f55eb3SErick Velez     Fragments.append("consteval", DeclarationFragments::FragmentKind::Keyword)
70975f55eb3SErick Velez         .appendSpace();
71075f55eb3SErick Velez   else if (Func->isConstexpr())
71175f55eb3SErick Velez     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
71275f55eb3SErick Velez         .appendSpace();
71389f6b26fSZixu Wang 
71489f6b26fSZixu Wang   // FIXME: Is `after` actually needed here?
71589f6b26fSZixu Wang   DeclarationFragments After;
71680b787e8SErick Velez   auto ReturnValueFragment =
71780b787e8SErick Velez       getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After);
71826648daeSKazu Hirata   if (StringRef(ReturnValueFragment.begin()->Spelling)
71926648daeSKazu Hirata           .starts_with("type-parameter")) {
7202b6c038eSErick Velez     std::string ProperArgName = Func->getReturnType().getAsString();
72180b787e8SErick Velez     ReturnValueFragment.begin()->Spelling.swap(ProperArgName);
72280b787e8SErick Velez   }
72380b787e8SErick Velez 
72480b787e8SErick Velez   Fragments.append(std::move(ReturnValueFragment))
72589f6b26fSZixu Wang       .appendSpace()
7262c13194eSDaniel Grumberg       .append(Func->getNameAsString(),
7272c13194eSDaniel Grumberg               DeclarationFragments::FragmentKind::Identifier);
72880b787e8SErick Velez 
72980b787e8SErick Velez   if (Func->getTemplateSpecializationInfo()) {
73080b787e8SErick Velez     Fragments.append("<", DeclarationFragments::FragmentKind::Text);
73180b787e8SErick Velez 
73280b787e8SErick Velez     for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) {
73380b787e8SErick Velez       if (i)
73480b787e8SErick Velez         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
73580b787e8SErick Velez       Fragments.append(
73680b787e8SErick Velez           getFragmentsForType(Func->getParamDecl(i)->getType(),
73780b787e8SErick Velez                               Func->getParamDecl(i)->getASTContext(), After));
73880b787e8SErick Velez     }
73980b787e8SErick Velez     Fragments.append(">", DeclarationFragments::FragmentKind::Text);
74080b787e8SErick Velez   }
74180b787e8SErick Velez   Fragments.append(std::move(After));
74289f6b26fSZixu Wang 
74389f6b26fSZixu Wang   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
7446b89fab8SDaniel Grumberg   unsigned NumParams = Func->getNumParams();
7456b89fab8SDaniel Grumberg   for (unsigned i = 0; i != NumParams; ++i) {
74689f6b26fSZixu Wang     if (i)
74789f6b26fSZixu Wang       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
74889f6b26fSZixu Wang     Fragments.append(getFragmentsForParam(Func->getParamDecl(i)));
74989f6b26fSZixu Wang   }
7506b89fab8SDaniel Grumberg 
7516b89fab8SDaniel Grumberg   if (Func->isVariadic()) {
7526b89fab8SDaniel Grumberg     if (NumParams > 0)
7536b89fab8SDaniel Grumberg       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
7546b89fab8SDaniel Grumberg     Fragments.append("...", DeclarationFragments::FragmentKind::Text);
7556b89fab8SDaniel Grumberg   }
75689f6b26fSZixu Wang   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
75789f6b26fSZixu Wang 
75875f55eb3SErick Velez   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
75975f55eb3SErick Velez       Func->getExceptionSpecType()));
76075f55eb3SErick Velez 
761e05c1b46SDaniel Grumberg   return Fragments.appendSemicolon();
76289f6b26fSZixu Wang }
76389f6b26fSZixu Wang 
76471b4c226SZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant(
76571b4c226SZixu Wang     const EnumConstantDecl *EnumConstDecl) {
76671b4c226SZixu Wang   DeclarationFragments Fragments;
76771b4c226SZixu Wang   return Fragments.append(EnumConstDecl->getName(),
76871b4c226SZixu Wang                           DeclarationFragments::FragmentKind::Identifier);
76971b4c226SZixu Wang }
77071b4c226SZixu Wang 
77171b4c226SZixu Wang DeclarationFragments
77271b4c226SZixu Wang DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {
7739fc45ca0SDaniel Grumberg   if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl())
7749fc45ca0SDaniel Grumberg     return getFragmentsForTypedef(TypedefNameDecl);
77571b4c226SZixu Wang 
77671b4c226SZixu Wang   DeclarationFragments Fragments, After;
77771b4c226SZixu Wang   Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword);
77871b4c226SZixu Wang 
77971b4c226SZixu Wang   if (!EnumDecl->getName().empty())
78071b4c226SZixu Wang     Fragments.appendSpace().append(
78171b4c226SZixu Wang         EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier);
78271b4c226SZixu Wang 
78371b4c226SZixu Wang   QualType IntegerType = EnumDecl->getIntegerType();
78471b4c226SZixu Wang   if (!IntegerType.isNull())
7852bcbe40fSDaniel Grumberg     Fragments.appendSpace()
7862bcbe40fSDaniel Grumberg         .append(": ", DeclarationFragments::FragmentKind::Text)
78771b4c226SZixu Wang         .append(
78871b4c226SZixu Wang             getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))
78971b4c226SZixu Wang         .append(std::move(After));
79071b4c226SZixu Wang 
7912bcbe40fSDaniel Grumberg   if (EnumDecl->getName().empty())
7922bcbe40fSDaniel Grumberg     Fragments.appendSpace().append("{ ... }",
7932bcbe40fSDaniel Grumberg                                    DeclarationFragments::FragmentKind::Text);
7942bcbe40fSDaniel Grumberg 
795e05c1b46SDaniel Grumberg   return Fragments.appendSemicolon();
79671b4c226SZixu Wang }
79771b4c226SZixu Wang 
7985bb5704cSZixu Wang DeclarationFragments
7995bb5704cSZixu Wang DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) {
8005bb5704cSZixu Wang   DeclarationFragments After;
80175f55eb3SErick Velez   DeclarationFragments Fragments;
80275f55eb3SErick Velez   if (Field->isMutable())
80375f55eb3SErick Velez     Fragments.append("mutable", DeclarationFragments::FragmentKind::Keyword)
80475f55eb3SErick Velez         .appendSpace();
80575f55eb3SErick Velez   return Fragments
80675f55eb3SErick Velez       .append(
80775f55eb3SErick Velez           getFragmentsForType(Field->getType(), Field->getASTContext(), After))
8085bb5704cSZixu Wang       .appendSpace()
8095bb5704cSZixu Wang       .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)
810422bcd10SErick Velez       .append(std::move(After))
811e05c1b46SDaniel Grumberg       .appendSemicolon();
8125bb5704cSZixu Wang }
8135bb5704cSZixu Wang 
81469fedaf8SDaniel Grumberg DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
81569fedaf8SDaniel Grumberg     const RecordDecl *Record) {
8169fc45ca0SDaniel Grumberg   if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
8179fc45ca0SDaniel Grumberg     return getFragmentsForTypedef(TypedefNameDecl);
8185bb5704cSZixu Wang 
8195bb5704cSZixu Wang   DeclarationFragments Fragments;
82069fedaf8SDaniel Grumberg   if (Record->isUnion())
82169fedaf8SDaniel Grumberg     Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);
82269fedaf8SDaniel Grumberg   else
8235bb5704cSZixu Wang     Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);
8245bb5704cSZixu Wang 
8252bcbe40fSDaniel Grumberg   Fragments.appendSpace();
8265bb5704cSZixu Wang   if (!Record->getName().empty())
8272bcbe40fSDaniel Grumberg     Fragments.append(Record->getName(),
8282bcbe40fSDaniel Grumberg                      DeclarationFragments::FragmentKind::Identifier);
8292bcbe40fSDaniel Grumberg   else
8302bcbe40fSDaniel Grumberg     Fragments.append("{ ... }", DeclarationFragments::FragmentKind::Text);
831afce10c5SNagaChaitanya Vellanki 
832e05c1b46SDaniel Grumberg   return Fragments.appendSemicolon();
833529a0570SDaniel Grumberg }
8345bb5704cSZixu Wang 
83575f55eb3SErick Velez DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
83675f55eb3SErick Velez     const CXXRecordDecl *Record) {
83775f55eb3SErick Velez   if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
83875f55eb3SErick Velez     return getFragmentsForTypedef(TypedefNameDecl);
83975f55eb3SErick Velez 
84075f55eb3SErick Velez   DeclarationFragments Fragments;
84175f55eb3SErick Velez   Fragments.append(DeclarationFragments::getStructureTypeFragment(Record));
84275f55eb3SErick Velez 
84375f55eb3SErick Velez   if (!Record->getName().empty())
84475f55eb3SErick Velez     Fragments.appendSpace().append(
84575f55eb3SErick Velez         Record->getName(), DeclarationFragments::FragmentKind::Identifier);
84675f55eb3SErick Velez 
847e05c1b46SDaniel Grumberg   return Fragments.appendSemicolon();
84875f55eb3SErick Velez }
84975f55eb3SErick Velez 
85075f55eb3SErick Velez DeclarationFragments
85175f55eb3SErick Velez DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(
85275f55eb3SErick Velez     const CXXMethodDecl *Method) {
85375f55eb3SErick Velez   DeclarationFragments Fragments;
85475f55eb3SErick Velez   std::string Name;
855847186ebSElizabeth Andrews   if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(Method)) {
85675f55eb3SErick Velez     Name = Method->getNameAsString();
857847186ebSElizabeth Andrews     if (Constructor->isExplicit())
85875f55eb3SErick Velez       Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
85975f55eb3SErick Velez           .appendSpace();
86075f55eb3SErick Velez   } else if (isa<CXXDestructorDecl>(Method))
86175f55eb3SErick Velez     Name = Method->getNameAsString();
86275f55eb3SErick Velez 
86375f55eb3SErick Velez   DeclarationFragments After;
86475f55eb3SErick Velez   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier)
86575f55eb3SErick Velez       .append(std::move(After));
86675f55eb3SErick Velez   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
86775f55eb3SErick Velez   for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
86875f55eb3SErick Velez     if (i)
86975f55eb3SErick Velez       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
87075f55eb3SErick Velez     Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
87175f55eb3SErick Velez   }
87275f55eb3SErick Velez   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
87375f55eb3SErick Velez 
87475f55eb3SErick Velez   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
87575f55eb3SErick Velez       Method->getExceptionSpecType()));
87675f55eb3SErick Velez 
877e05c1b46SDaniel Grumberg   return Fragments.appendSemicolon();
87875f55eb3SErick Velez }
87975f55eb3SErick Velez 
88075f55eb3SErick Velez DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
88175f55eb3SErick Velez     const CXXMethodDecl *Method) {
88275f55eb3SErick Velez   DeclarationFragments Fragments;
88375f55eb3SErick Velez   StringRef Name = Method->getName();
88475f55eb3SErick Velez   if (Method->isStatic())
88575f55eb3SErick Velez     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
88675f55eb3SErick Velez         .appendSpace();
88775f55eb3SErick Velez   if (Method->isConstexpr())
88875f55eb3SErick Velez     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
88975f55eb3SErick Velez         .appendSpace();
89075f55eb3SErick Velez   if (Method->isVolatile())
89175f55eb3SErick Velez     Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword)
89275f55eb3SErick Velez         .appendSpace();
89375f55eb3SErick Velez 
89475f55eb3SErick Velez   // Build return type
89575f55eb3SErick Velez   DeclarationFragments After;
89675f55eb3SErick Velez   Fragments
89775f55eb3SErick Velez       .append(getFragmentsForType(Method->getReturnType(),
89875f55eb3SErick Velez                                   Method->getASTContext(), After))
89975f55eb3SErick Velez       .appendSpace()
90075f55eb3SErick Velez       .append(Name, DeclarationFragments::FragmentKind::Identifier)
90175f55eb3SErick Velez       .append(std::move(After));
90275f55eb3SErick Velez   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
90375f55eb3SErick Velez   for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
90475f55eb3SErick Velez     if (i)
90575f55eb3SErick Velez       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
90675f55eb3SErick Velez     Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
90775f55eb3SErick Velez   }
90875f55eb3SErick Velez   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
90975f55eb3SErick Velez 
91075f55eb3SErick Velez   if (Method->isConst())
91175f55eb3SErick Velez     Fragments.appendSpace().append("const",
91275f55eb3SErick Velez                                    DeclarationFragments::FragmentKind::Keyword);
91375f55eb3SErick Velez 
91475f55eb3SErick Velez   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
91575f55eb3SErick Velez       Method->getExceptionSpecType()));
91675f55eb3SErick Velez 
917e05c1b46SDaniel Grumberg   return Fragments.appendSemicolon();
91875f55eb3SErick Velez }
91975f55eb3SErick Velez 
92075f55eb3SErick Velez DeclarationFragments
92175f55eb3SErick Velez DeclarationFragmentsBuilder::getFragmentsForConversionFunction(
92275f55eb3SErick Velez     const CXXConversionDecl *ConversionFunction) {
92375f55eb3SErick Velez   DeclarationFragments Fragments;
92475f55eb3SErick Velez 
92575f55eb3SErick Velez   if (ConversionFunction->isExplicit())
92675f55eb3SErick Velez     Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
92775f55eb3SErick Velez         .appendSpace();
92875f55eb3SErick Velez 
92975f55eb3SErick Velez   Fragments.append("operator", DeclarationFragments::FragmentKind::Keyword)
93075f55eb3SErick Velez       .appendSpace();
93175f55eb3SErick Velez 
93275f55eb3SErick Velez   Fragments
93375f55eb3SErick Velez       .append(ConversionFunction->getConversionType().getAsString(),
93475f55eb3SErick Velez               DeclarationFragments::FragmentKind::TypeIdentifier)
93575f55eb3SErick Velez       .append("(", DeclarationFragments::FragmentKind::Text);
93675f55eb3SErick Velez   for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end;
93775f55eb3SErick Velez        ++i) {
93875f55eb3SErick Velez     if (i)
93975f55eb3SErick Velez       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
94075f55eb3SErick Velez     Fragments.append(getFragmentsForParam(ConversionFunction->getParamDecl(i)));
94175f55eb3SErick Velez   }
94275f55eb3SErick Velez   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
94375f55eb3SErick Velez 
94475f55eb3SErick Velez   if (ConversionFunction->isConst())
94575f55eb3SErick Velez     Fragments.appendSpace().append("const",
94675f55eb3SErick Velez                                    DeclarationFragments::FragmentKind::Keyword);
94775f55eb3SErick Velez 
948e05c1b46SDaniel Grumberg   return Fragments.appendSemicolon();
94975f55eb3SErick Velez }
95075f55eb3SErick Velez 
95175f55eb3SErick Velez DeclarationFragments
95275f55eb3SErick Velez DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(
95375f55eb3SErick Velez     const CXXMethodDecl *Method) {
95475f55eb3SErick Velez   DeclarationFragments Fragments;
95575f55eb3SErick Velez 
95675f55eb3SErick Velez   // Build return type
95775f55eb3SErick Velez   DeclarationFragments After;
95875f55eb3SErick Velez   Fragments
95975f55eb3SErick Velez       .append(getFragmentsForType(Method->getReturnType(),
96075f55eb3SErick Velez                                   Method->getASTContext(), After))
96175f55eb3SErick Velez       .appendSpace()
96275f55eb3SErick Velez       .append(Method->getNameAsString(),
96375f55eb3SErick Velez               DeclarationFragments::FragmentKind::Identifier)
96475f55eb3SErick Velez       .append(std::move(After));
96575f55eb3SErick Velez   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
96675f55eb3SErick Velez   for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
96775f55eb3SErick Velez     if (i)
96875f55eb3SErick Velez       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
96975f55eb3SErick Velez     Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
97075f55eb3SErick Velez   }
97175f55eb3SErick Velez   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
97275f55eb3SErick Velez 
97375f55eb3SErick Velez   if (Method->isConst())
97475f55eb3SErick Velez     Fragments.appendSpace().append("const",
97575f55eb3SErick Velez                                    DeclarationFragments::FragmentKind::Keyword);
97675f55eb3SErick Velez 
97775f55eb3SErick Velez   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
97875f55eb3SErick Velez       Method->getExceptionSpecType()));
97975f55eb3SErick Velez 
980e05c1b46SDaniel Grumberg   return Fragments.appendSemicolon();
98175f55eb3SErick Velez }
98275f55eb3SErick Velez 
9837ba37f4eSErick Velez // Get fragments for template parameters, e.g. T in tempalte<typename T> ...
9847ba37f4eSErick Velez DeclarationFragments
9857ba37f4eSErick Velez DeclarationFragmentsBuilder::getFragmentsForTemplateParameters(
9867ba37f4eSErick Velez     ArrayRef<NamedDecl *> ParameterArray) {
9877ba37f4eSErick Velez   DeclarationFragments Fragments;
9887ba37f4eSErick Velez   for (unsigned i = 0, end = ParameterArray.size(); i != end; ++i) {
9897ba37f4eSErick Velez     if (i)
9907ba37f4eSErick Velez       Fragments.append(",", DeclarationFragments::FragmentKind::Text)
9917ba37f4eSErick Velez           .appendSpace();
9927ba37f4eSErick Velez 
9937a674793SDaniel Grumberg     if (const auto *TemplateParam =
9947a674793SDaniel Grumberg             dyn_cast<TemplateTypeParmDecl>(ParameterArray[i])) {
9957ba37f4eSErick Velez       if (TemplateParam->hasTypeConstraint())
9967ba37f4eSErick Velez         Fragments.append(TemplateParam->getTypeConstraint()
9977ba37f4eSErick Velez                              ->getNamedConcept()
9987ba37f4eSErick Velez                              ->getName()
9997ba37f4eSErick Velez                              .str(),
10007ba37f4eSErick Velez                          DeclarationFragments::FragmentKind::TypeIdentifier);
10017ba37f4eSErick Velez       else if (TemplateParam->wasDeclaredWithTypename())
10027a674793SDaniel Grumberg         Fragments.append("typename",
10037a674793SDaniel Grumberg                          DeclarationFragments::FragmentKind::Keyword);
10047ba37f4eSErick Velez       else
10057ba37f4eSErick Velez         Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);
10067ba37f4eSErick Velez 
10077ba37f4eSErick Velez       if (TemplateParam->isParameterPack())
10087ba37f4eSErick Velez         Fragments.append("...", DeclarationFragments::FragmentKind::Text);
10097ba37f4eSErick Velez 
10107a674793SDaniel Grumberg       if (!TemplateParam->getName().empty())
10117ba37f4eSErick Velez         Fragments.appendSpace().append(
10127ba37f4eSErick Velez             TemplateParam->getName(),
10137ba37f4eSErick Velez             DeclarationFragments::FragmentKind::GenericParameter);
10147a674793SDaniel Grumberg 
10157a674793SDaniel Grumberg       if (TemplateParam->hasDefaultArgument()) {
1016e42b799bSMatheus Izvekov         const auto Default = TemplateParam->getDefaultArgument();
10177a674793SDaniel Grumberg         Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)
1018e42b799bSMatheus Izvekov             .append(getFragmentsForTemplateArguments(
1019e42b799bSMatheus Izvekov                 {Default.getArgument()}, TemplateParam->getASTContext(),
1020e42b799bSMatheus Izvekov                 {Default}));
10217a674793SDaniel Grumberg       }
10227a674793SDaniel Grumberg     } else if (const auto *NTP =
10237a674793SDaniel Grumberg                    dyn_cast<NonTypeTemplateParmDecl>(ParameterArray[i])) {
10247a674793SDaniel Grumberg       DeclarationFragments After;
10257a674793SDaniel Grumberg       const auto TyFragments =
10267a674793SDaniel Grumberg           getFragmentsForType(NTP->getType(), NTP->getASTContext(), After);
10277a674793SDaniel Grumberg       Fragments.append(std::move(TyFragments)).append(std::move(After));
10287a674793SDaniel Grumberg 
10297a674793SDaniel Grumberg       if (NTP->isParameterPack())
10307a674793SDaniel Grumberg         Fragments.append("...", DeclarationFragments::FragmentKind::Text);
10317a674793SDaniel Grumberg 
10327a674793SDaniel Grumberg       if (!NTP->getName().empty())
10337a674793SDaniel Grumberg         Fragments.appendSpace().append(
10347a674793SDaniel Grumberg             NTP->getName(),
10357a674793SDaniel Grumberg             DeclarationFragments::FragmentKind::GenericParameter);
10367a674793SDaniel Grumberg 
10377a674793SDaniel Grumberg       if (NTP->hasDefaultArgument()) {
10387a674793SDaniel Grumberg         SmallString<8> ExprStr;
10397a674793SDaniel Grumberg         raw_svector_ostream Output(ExprStr);
10402bde13cdSMatheus Izvekov         NTP->getDefaultArgument().getArgument().print(
10412bde13cdSMatheus Izvekov             NTP->getASTContext().getPrintingPolicy(), Output,
10422bde13cdSMatheus Izvekov             /*IncludeType=*/false);
10437a674793SDaniel Grumberg         Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)
10447a674793SDaniel Grumberg             .append(ExprStr, DeclarationFragments::FragmentKind::Text);
10457a674793SDaniel Grumberg       }
10467a674793SDaniel Grumberg     } else if (const auto *TTP =
10477a674793SDaniel Grumberg                    dyn_cast<TemplateTemplateParmDecl>(ParameterArray[i])) {
10487a674793SDaniel Grumberg       Fragments.append("template", DeclarationFragments::FragmentKind::Keyword)
10497a674793SDaniel Grumberg           .appendSpace()
10507a674793SDaniel Grumberg           .append("<", DeclarationFragments::FragmentKind::Text)
10517a674793SDaniel Grumberg           .append(getFragmentsForTemplateParameters(
10527a674793SDaniel Grumberg               TTP->getTemplateParameters()->asArray()))
10537a674793SDaniel Grumberg           .append(">", DeclarationFragments::FragmentKind::Text)
10547a674793SDaniel Grumberg           .appendSpace()
10557a674793SDaniel Grumberg           .append(TTP->wasDeclaredWithTypename() ? "typename" : "class",
10567a674793SDaniel Grumberg                   DeclarationFragments::FragmentKind::Keyword);
10577a674793SDaniel Grumberg 
10587a674793SDaniel Grumberg       if (TTP->isParameterPack())
10597a674793SDaniel Grumberg         Fragments.append("...", DeclarationFragments::FragmentKind::Text);
10607a674793SDaniel Grumberg 
10617a674793SDaniel Grumberg       if (!TTP->getName().empty())
10627a674793SDaniel Grumberg         Fragments.appendSpace().append(
10637a674793SDaniel Grumberg             TTP->getName(),
10647a674793SDaniel Grumberg             DeclarationFragments::FragmentKind::GenericParameter);
10657a674793SDaniel Grumberg       if (TTP->hasDefaultArgument()) {
10667a674793SDaniel Grumberg         const auto Default = TTP->getDefaultArgument();
10677a674793SDaniel Grumberg         Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)
10687a674793SDaniel Grumberg             .append(getFragmentsForTemplateArguments(
10697a674793SDaniel Grumberg                 {Default.getArgument()}, TTP->getASTContext(), {Default}));
10707a674793SDaniel Grumberg       }
10717a674793SDaniel Grumberg     }
10727ba37f4eSErick Velez   }
10737ba37f4eSErick Velez   return Fragments;
10747ba37f4eSErick Velez }
10757ba37f4eSErick Velez 
10767ba37f4eSErick Velez // Get fragments for template arguments, e.g. int in template<typename T>
10777ba37f4eSErick Velez // Foo<int>;
10787ba37f4eSErick Velez //
10797ba37f4eSErick Velez // Note: TemplateParameters is only necessary if the Decl is a
10807ba37f4eSErick Velez // PartialSpecialization, where we need the parameters to deduce the name of the
10817ba37f4eSErick Velez // generic arguments.
10827ba37f4eSErick Velez DeclarationFragments
10837ba37f4eSErick Velez DeclarationFragmentsBuilder::getFragmentsForTemplateArguments(
10847ba37f4eSErick Velez     const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context,
10852b6c038eSErick Velez     const std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs) {
10867ba37f4eSErick Velez   DeclarationFragments Fragments;
10877ba37f4eSErick Velez   for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) {
10887ba37f4eSErick Velez     if (i)
10897ba37f4eSErick Velez       Fragments.append(",", DeclarationFragments::FragmentKind::Text)
10907ba37f4eSErick Velez           .appendSpace();
10917ba37f4eSErick Velez 
10927a674793SDaniel Grumberg     const auto &CTA = TemplateArguments[i];
10937a674793SDaniel Grumberg     switch (CTA.getKind()) {
10947a674793SDaniel Grumberg     case TemplateArgument::Type: {
10957ba37f4eSErick Velez       DeclarationFragments After;
10967ba37f4eSErick Velez       DeclarationFragments ArgumentFragment =
10977a674793SDaniel Grumberg           getFragmentsForType(CTA.getAsType(), Context, After);
10987ba37f4eSErick Velez 
109926648daeSKazu Hirata       if (StringRef(ArgumentFragment.begin()->Spelling)
110026648daeSKazu Hirata               .starts_with("type-parameter")) {
1101ab7e6b66SDaniel Grumberg         if (TemplateArgumentLocs.has_value() &&
1102ab7e6b66SDaniel Grumberg             TemplateArgumentLocs->size() > i) {
11032b6c038eSErick Velez           std::string ProperArgName = TemplateArgumentLocs.value()[i]
11042b6c038eSErick Velez                                           .getTypeSourceInfo()
11052b6c038eSErick Velez                                           ->getType()
11062b6c038eSErick Velez                                           .getAsString();
11077ba37f4eSErick Velez           ArgumentFragment.begin()->Spelling.swap(ProperArgName);
1108ab7e6b66SDaniel Grumberg         } else {
1109ab7e6b66SDaniel Grumberg           auto &Spelling = ArgumentFragment.begin()->Spelling;
1110ab7e6b66SDaniel Grumberg           Spelling.clear();
1111ab7e6b66SDaniel Grumberg           raw_string_ostream OutStream(Spelling);
1112ab7e6b66SDaniel Grumberg           CTA.print(Context.getPrintingPolicy(), OutStream, false);
11137ba37f4eSErick Velez         }
1114ab7e6b66SDaniel Grumberg       }
1115ab7e6b66SDaniel Grumberg 
11167ba37f4eSErick Velez       Fragments.append(std::move(ArgumentFragment));
11177a674793SDaniel Grumberg       break;
11187a674793SDaniel Grumberg     }
11197a674793SDaniel Grumberg     case TemplateArgument::Declaration: {
11207a674793SDaniel Grumberg       const auto *VD = CTA.getAsDecl();
11217a674793SDaniel Grumberg       SmallString<128> USR;
11227a674793SDaniel Grumberg       index::generateUSRForDecl(VD, USR);
11237a674793SDaniel Grumberg       Fragments.append(VD->getNameAsString(),
11247a674793SDaniel Grumberg                        DeclarationFragments::FragmentKind::Identifier, USR);
11257a674793SDaniel Grumberg       break;
11267a674793SDaniel Grumberg     }
11277a674793SDaniel Grumberg     case TemplateArgument::NullPtr:
11287a674793SDaniel Grumberg       Fragments.append("nullptr", DeclarationFragments::FragmentKind::Keyword);
11297a674793SDaniel Grumberg       break;
11307ba37f4eSErick Velez 
11317a674793SDaniel Grumberg     case TemplateArgument::Integral: {
11327a674793SDaniel Grumberg       SmallString<4> Str;
11337a674793SDaniel Grumberg       CTA.getAsIntegral().toString(Str);
11347a674793SDaniel Grumberg       Fragments.append(Str, DeclarationFragments::FragmentKind::Text);
11357a674793SDaniel Grumberg       break;
11367a674793SDaniel Grumberg     }
11377a674793SDaniel Grumberg 
11387a674793SDaniel Grumberg     case TemplateArgument::StructuralValue: {
11397a674793SDaniel Grumberg       const auto SVTy = CTA.getStructuralValueType();
11407a674793SDaniel Grumberg       Fragments.append(CTA.getAsStructuralValue().getAsString(Context, SVTy),
11417a674793SDaniel Grumberg                        DeclarationFragments::FragmentKind::Text);
11427a674793SDaniel Grumberg       break;
11437a674793SDaniel Grumberg     }
11447a674793SDaniel Grumberg 
11457a674793SDaniel Grumberg     case TemplateArgument::TemplateExpansion:
11467a674793SDaniel Grumberg     case TemplateArgument::Template: {
11477a674793SDaniel Grumberg       std::string Str;
11487a674793SDaniel Grumberg       raw_string_ostream Stream(Str);
11497a674793SDaniel Grumberg       CTA.getAsTemplate().print(Stream, Context.getPrintingPolicy());
11507a674793SDaniel Grumberg       SmallString<64> USR("");
11517a674793SDaniel Grumberg       if (const auto *TemplDecl =
11527a674793SDaniel Grumberg               CTA.getAsTemplateOrTemplatePattern().getAsTemplateDecl())
11537a674793SDaniel Grumberg         index::generateUSRForDecl(TemplDecl, USR);
11547a674793SDaniel Grumberg       Fragments.append(Str, DeclarationFragments::FragmentKind::TypeIdentifier,
11557a674793SDaniel Grumberg                        USR);
11567a674793SDaniel Grumberg       if (CTA.getKind() == TemplateArgument::TemplateExpansion)
11577ba37f4eSErick Velez         Fragments.append("...", DeclarationFragments::FragmentKind::Text);
11587a674793SDaniel Grumberg       break;
11597a674793SDaniel Grumberg     }
11607a674793SDaniel Grumberg 
11617a674793SDaniel Grumberg     case TemplateArgument::Pack:
11627a674793SDaniel Grumberg       Fragments.append("<", DeclarationFragments::FragmentKind::Text)
11637a674793SDaniel Grumberg           .append(getFragmentsForTemplateArguments(CTA.pack_elements(), Context,
11647a674793SDaniel Grumberg                                                    {}))
11657a674793SDaniel Grumberg           .append(">", DeclarationFragments::FragmentKind::Text);
11667a674793SDaniel Grumberg       break;
11677a674793SDaniel Grumberg 
11687a674793SDaniel Grumberg     case TemplateArgument::Expression: {
11697a674793SDaniel Grumberg       SmallString<8> ExprStr;
11707a674793SDaniel Grumberg       raw_svector_ostream Output(ExprStr);
11717a674793SDaniel Grumberg       CTA.getAsExpr()->printPretty(Output, nullptr,
11727a674793SDaniel Grumberg                                    Context.getPrintingPolicy());
11737a674793SDaniel Grumberg       Fragments.append(ExprStr, DeclarationFragments::FragmentKind::Text);
11747a674793SDaniel Grumberg       break;
11757a674793SDaniel Grumberg     }
11767a674793SDaniel Grumberg 
11777a674793SDaniel Grumberg     case TemplateArgument::Null:
11787a674793SDaniel Grumberg       break;
11797a674793SDaniel Grumberg     }
11807ba37f4eSErick Velez   }
11817ba37f4eSErick Velez   return Fragments;
11827ba37f4eSErick Velez }
11837ba37f4eSErick Velez 
11847ba37f4eSErick Velez DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept(
11857ba37f4eSErick Velez     const ConceptDecl *Concept) {
11867ba37f4eSErick Velez   DeclarationFragments Fragments;
11877ba37f4eSErick Velez   return Fragments
11887ba37f4eSErick Velez       .append("template", DeclarationFragments::FragmentKind::Keyword)
11897a674793SDaniel Grumberg       .appendSpace()
11907ba37f4eSErick Velez       .append("<", DeclarationFragments::FragmentKind::Text)
11917ba37f4eSErick Velez       .append(getFragmentsForTemplateParameters(
11927ba37f4eSErick Velez           Concept->getTemplateParameters()->asArray()))
11937ba37f4eSErick Velez       .append("> ", DeclarationFragments::FragmentKind::Text)
11947a674793SDaniel Grumberg       .appendSpace()
11957ba37f4eSErick Velez       .append("concept", DeclarationFragments::FragmentKind::Keyword)
11967ba37f4eSErick Velez       .appendSpace()
11977ba37f4eSErick Velez       .append(Concept->getName().str(),
11987ba37f4eSErick Velez               DeclarationFragments::FragmentKind::Identifier)
1199e05c1b46SDaniel Grumberg       .appendSemicolon();
12007ba37f4eSErick Velez }
12017ba37f4eSErick Velez 
12027ba37f4eSErick Velez DeclarationFragments
12037ba37f4eSErick Velez DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
12047ba37f4eSErick Velez     const RedeclarableTemplateDecl *RedeclarableTemplate) {
12057ba37f4eSErick Velez   DeclarationFragments Fragments;
12067ba37f4eSErick Velez   Fragments.append("template", DeclarationFragments::FragmentKind::Keyword)
12077a674793SDaniel Grumberg       .appendSpace()
12087ba37f4eSErick Velez       .append("<", DeclarationFragments::FragmentKind::Text)
12097ba37f4eSErick Velez       .append(getFragmentsForTemplateParameters(
12107ba37f4eSErick Velez           RedeclarableTemplate->getTemplateParameters()->asArray()))
12117ba37f4eSErick Velez       .append(">", DeclarationFragments::FragmentKind::Text)
12127ba37f4eSErick Velez       .appendSpace();
12137ba37f4eSErick Velez 
12147ba37f4eSErick Velez   if (isa<TypeAliasTemplateDecl>(RedeclarableTemplate))
12157ba37f4eSErick Velez     Fragments.appendSpace()
12167ba37f4eSErick Velez         .append("using", DeclarationFragments::FragmentKind::Keyword)
12177ba37f4eSErick Velez         .appendSpace()
12187ba37f4eSErick Velez         .append(RedeclarableTemplate->getName(),
12197ba37f4eSErick Velez                 DeclarationFragments::FragmentKind::Identifier);
12207ba37f4eSErick Velez   // the templated records will be resposbible for injecting their templates
12217ba37f4eSErick Velez   return Fragments.appendSpace();
12227ba37f4eSErick Velez }
12237ba37f4eSErick Velez 
12247ba37f4eSErick Velez DeclarationFragments
12257ba37f4eSErick Velez DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization(
12267ba37f4eSErick Velez     const ClassTemplateSpecializationDecl *Decl) {
12277ba37f4eSErick Velez   DeclarationFragments Fragments;
12287ba37f4eSErick Velez   return Fragments
12297ba37f4eSErick Velez       .append("template", DeclarationFragments::FragmentKind::Keyword)
12307a674793SDaniel Grumberg       .appendSpace()
12317ba37f4eSErick Velez       .append("<", DeclarationFragments::FragmentKind::Text)
12327ba37f4eSErick Velez       .append(">", DeclarationFragments::FragmentKind::Text)
12337ba37f4eSErick Velez       .appendSpace()
12347ba37f4eSErick Velez       .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(
12357ba37f4eSErick Velez           cast<CXXRecordDecl>(Decl)))
12367ba37f4eSErick Velez       .pop_back() // there is an extra semicolon now
12377ba37f4eSErick Velez       .append("<", DeclarationFragments::FragmentKind::Text)
1238ab7e6b66SDaniel Grumberg       .append(getFragmentsForTemplateArguments(
1239ab7e6b66SDaniel Grumberg           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1240ab7e6b66SDaniel Grumberg           Decl->getTemplateArgsAsWritten()->arguments()))
12417ba37f4eSErick Velez       .append(">", DeclarationFragments::FragmentKind::Text)
1242e05c1b46SDaniel Grumberg       .appendSemicolon();
12437ba37f4eSErick Velez }
12447ba37f4eSErick Velez 
12457ba37f4eSErick Velez DeclarationFragments
12467ba37f4eSErick Velez DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization(
12477ba37f4eSErick Velez     const ClassTemplatePartialSpecializationDecl *Decl) {
12487ba37f4eSErick Velez   DeclarationFragments Fragments;
12497ba37f4eSErick Velez   return Fragments
12507ba37f4eSErick Velez       .append("template", DeclarationFragments::FragmentKind::Keyword)
12517a674793SDaniel Grumberg       .appendSpace()
12527ba37f4eSErick Velez       .append("<", DeclarationFragments::FragmentKind::Text)
12537ba37f4eSErick Velez       .append(getFragmentsForTemplateParameters(
12547ba37f4eSErick Velez           Decl->getTemplateParameters()->asArray()))
12557ba37f4eSErick Velez       .append(">", DeclarationFragments::FragmentKind::Text)
12567ba37f4eSErick Velez       .appendSpace()
12577ba37f4eSErick Velez       .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(
12587ba37f4eSErick Velez           cast<CXXRecordDecl>(Decl)))
12597ba37f4eSErick Velez       .pop_back() // there is an extra semicolon now
12607ba37f4eSErick Velez       .append("<", DeclarationFragments::FragmentKind::Text)
12617ba37f4eSErick Velez       .append(getFragmentsForTemplateArguments(
12627ba37f4eSErick Velez           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
12632b6c038eSErick Velez           Decl->getTemplateArgsAsWritten()->arguments()))
12647ba37f4eSErick Velez       .append(">", DeclarationFragments::FragmentKind::Text)
1265e05c1b46SDaniel Grumberg       .appendSemicolon();
12667ba37f4eSErick Velez }
12677ba37f4eSErick Velez 
1268529a0570SDaniel Grumberg DeclarationFragments
12698d8c8981SErick Velez DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization(
12708d8c8981SErick Velez     const VarTemplateSpecializationDecl *Decl) {
12718d8c8981SErick Velez   DeclarationFragments Fragments;
12728d8c8981SErick Velez   return Fragments
12738d8c8981SErick Velez       .append("template", DeclarationFragments::FragmentKind::Keyword)
12747a674793SDaniel Grumberg       .appendSpace()
12758d8c8981SErick Velez       .append("<", DeclarationFragments::FragmentKind::Text)
12768d8c8981SErick Velez       .append(">", DeclarationFragments::FragmentKind::Text)
12778d8c8981SErick Velez       .appendSpace()
12788d8c8981SErick Velez       .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))
12798d8c8981SErick Velez       .pop_back() // there is an extra semicolon now
12808d8c8981SErick Velez       .append("<", DeclarationFragments::FragmentKind::Text)
1281ab7e6b66SDaniel Grumberg       .append(getFragmentsForTemplateArguments(
1282ab7e6b66SDaniel Grumberg           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1283ab7e6b66SDaniel Grumberg           Decl->getTemplateArgsAsWritten()->arguments()))
12848d8c8981SErick Velez       .append(">", DeclarationFragments::FragmentKind::Text)
1285e05c1b46SDaniel Grumberg       .appendSemicolon();
12868d8c8981SErick Velez }
12878d8c8981SErick Velez 
12888d8c8981SErick Velez DeclarationFragments
12898d8c8981SErick Velez DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization(
12908d8c8981SErick Velez     const VarTemplatePartialSpecializationDecl *Decl) {
12918d8c8981SErick Velez   DeclarationFragments Fragments;
12928d8c8981SErick Velez   return Fragments
12938d8c8981SErick Velez       .append("template", DeclarationFragments::FragmentKind::Keyword)
12947a674793SDaniel Grumberg       .appendSpace()
12958d8c8981SErick Velez       .append("<", DeclarationFragments::FragmentKind::Text)
12968d8c8981SErick Velez       // Partial specs may have new params.
12978d8c8981SErick Velez       .append(getFragmentsForTemplateParameters(
12988d8c8981SErick Velez           Decl->getTemplateParameters()->asArray()))
12998d8c8981SErick Velez       .append(">", DeclarationFragments::FragmentKind::Text)
13008d8c8981SErick Velez       .appendSpace()
13018d8c8981SErick Velez       .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))
13028d8c8981SErick Velez       .pop_back() // there is an extra semicolon now
13038d8c8981SErick Velez       .append("<", DeclarationFragments::FragmentKind::Text)
13048d8c8981SErick Velez       .append(getFragmentsForTemplateArguments(
13058d8c8981SErick Velez           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
13062b6c038eSErick Velez           Decl->getTemplateArgsAsWritten()->arguments()))
13078d8c8981SErick Velez       .append(">", DeclarationFragments::FragmentKind::Text)
1308e05c1b46SDaniel Grumberg       .appendSemicolon();
13098d8c8981SErick Velez }
13108d8c8981SErick Velez 
13118d8c8981SErick Velez DeclarationFragments
131280b787e8SErick Velez DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(
131380b787e8SErick Velez     const FunctionTemplateDecl *Decl) {
131480b787e8SErick Velez   DeclarationFragments Fragments;
131580b787e8SErick Velez   return Fragments
131680b787e8SErick Velez       .append("template", DeclarationFragments::FragmentKind::Keyword)
13177a674793SDaniel Grumberg       .appendSpace()
131880b787e8SErick Velez       .append("<", DeclarationFragments::FragmentKind::Text)
131980b787e8SErick Velez       // Partial specs may have new params.
132080b787e8SErick Velez       .append(getFragmentsForTemplateParameters(
132180b787e8SErick Velez           Decl->getTemplateParameters()->asArray()))
132280b787e8SErick Velez       .append(">", DeclarationFragments::FragmentKind::Text)
132380b787e8SErick Velez       .appendSpace()
132480b787e8SErick Velez       .append(DeclarationFragmentsBuilder::getFragmentsForFunction(
132580b787e8SErick Velez           Decl->getAsFunction()));
132680b787e8SErick Velez }
132780b787e8SErick Velez 
132880b787e8SErick Velez DeclarationFragments
132980b787e8SErick Velez DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization(
133080b787e8SErick Velez     const FunctionDecl *Decl) {
133180b787e8SErick Velez   DeclarationFragments Fragments;
133280b787e8SErick Velez   return Fragments
133380b787e8SErick Velez       .append("template", DeclarationFragments::FragmentKind::Keyword)
13347a674793SDaniel Grumberg       .appendSpace()
133580b787e8SErick Velez       .append("<>", DeclarationFragments::FragmentKind::Text)
133680b787e8SErick Velez       .appendSpace()
133780b787e8SErick Velez       .append(DeclarationFragmentsBuilder::getFragmentsForFunction(Decl));
133880b787e8SErick Velez }
133980b787e8SErick Velez 
134080b787e8SErick Velez DeclarationFragments
1341529a0570SDaniel Grumberg DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name,
1342b1b24d75SDaniel Grumberg                                                   const MacroInfo *MI) {
1343529a0570SDaniel Grumberg   DeclarationFragments Fragments;
1344529a0570SDaniel Grumberg   Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword)
1345529a0570SDaniel Grumberg       .appendSpace();
1346529a0570SDaniel Grumberg   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
1347529a0570SDaniel Grumberg 
1348529a0570SDaniel Grumberg   if (MI->isFunctionLike()) {
1349529a0570SDaniel Grumberg     Fragments.append("(", DeclarationFragments::FragmentKind::Text);
1350529a0570SDaniel Grumberg     unsigned numParameters = MI->getNumParams();
1351529a0570SDaniel Grumberg     if (MI->isC99Varargs())
1352529a0570SDaniel Grumberg       --numParameters;
1353529a0570SDaniel Grumberg     for (unsigned i = 0; i < numParameters; ++i) {
1354529a0570SDaniel Grumberg       if (i)
1355529a0570SDaniel Grumberg         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
1356529a0570SDaniel Grumberg       Fragments.append(MI->params()[i]->getName(),
1357529a0570SDaniel Grumberg                        DeclarationFragments::FragmentKind::InternalParam);
1358529a0570SDaniel Grumberg     }
1359529a0570SDaniel Grumberg     if (MI->isVariadic()) {
1360529a0570SDaniel Grumberg       if (numParameters && MI->isC99Varargs())
1361529a0570SDaniel Grumberg         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
1362529a0570SDaniel Grumberg       Fragments.append("...", DeclarationFragments::FragmentKind::Text);
1363529a0570SDaniel Grumberg     }
1364529a0570SDaniel Grumberg     Fragments.append(")", DeclarationFragments::FragmentKind::Text);
1365529a0570SDaniel Grumberg   }
13665bb5704cSZixu Wang   return Fragments;
13675bb5704cSZixu Wang }
13685bb5704cSZixu Wang 
1369178aad9bSZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory(
1370178aad9bSZixu Wang     const ObjCCategoryDecl *Category) {
1371178aad9bSZixu Wang   DeclarationFragments Fragments;
1372178aad9bSZixu Wang 
13737a851921SDaniel Grumberg   auto *Interface = Category->getClassInterface();
1374178aad9bSZixu Wang   SmallString<128> InterfaceUSR;
13757a851921SDaniel Grumberg   index::generateUSRForDecl(Interface, InterfaceUSR);
1376178aad9bSZixu Wang 
1377178aad9bSZixu Wang   Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
1378178aad9bSZixu Wang       .appendSpace()
1379e05c1b46SDaniel Grumberg       .append(Interface->getName(),
13807a851921SDaniel Grumberg               DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR,
13817a851921SDaniel Grumberg               Interface)
1382178aad9bSZixu Wang       .append(" (", DeclarationFragments::FragmentKind::Text)
1383178aad9bSZixu Wang       .append(Category->getName(),
1384178aad9bSZixu Wang               DeclarationFragments::FragmentKind::Identifier)
1385178aad9bSZixu Wang       .append(")", DeclarationFragments::FragmentKind::Text);
1386178aad9bSZixu Wang 
1387178aad9bSZixu Wang   return Fragments;
1388178aad9bSZixu Wang }
1389178aad9bSZixu Wang 
13909b36e126SZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface(
13919b36e126SZixu Wang     const ObjCInterfaceDecl *Interface) {
13929b36e126SZixu Wang   DeclarationFragments Fragments;
13939b36e126SZixu Wang   // Build the base of the Objective-C interface declaration.
13949b36e126SZixu Wang   Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
13959b36e126SZixu Wang       .appendSpace()
13969b36e126SZixu Wang       .append(Interface->getName(),
13979b36e126SZixu Wang               DeclarationFragments::FragmentKind::Identifier);
139889f6b26fSZixu Wang 
13999b36e126SZixu Wang   // Build the inheritance part of the declaration.
14009b36e126SZixu Wang   if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) {
14019b36e126SZixu Wang     SmallString<128> SuperUSR;
14029b36e126SZixu Wang     index::generateUSRForDecl(SuperClass, SuperUSR);
14039b36e126SZixu Wang     Fragments.append(" : ", DeclarationFragments::FragmentKind::Text)
14049b36e126SZixu Wang         .append(SuperClass->getName(),
14057a851921SDaniel Grumberg                 DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR,
14067a851921SDaniel Grumberg                 SuperClass);
140789f6b26fSZixu Wang   }
140889f6b26fSZixu Wang 
14099b36e126SZixu Wang   return Fragments;
14109b36e126SZixu Wang }
141189f6b26fSZixu Wang 
14129b36e126SZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod(
14139b36e126SZixu Wang     const ObjCMethodDecl *Method) {
14149b36e126SZixu Wang   DeclarationFragments Fragments, After;
14159b36e126SZixu Wang   // Build the instance/class method indicator.
14169b36e126SZixu Wang   if (Method->isClassMethod())
14179b36e126SZixu Wang     Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
14189b36e126SZixu Wang   else if (Method->isInstanceMethod())
14199b36e126SZixu Wang     Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
14209b36e126SZixu Wang 
14219b36e126SZixu Wang   // Build the return type.
14229b36e126SZixu Wang   Fragments.append("(", DeclarationFragments::FragmentKind::Text)
14239b36e126SZixu Wang       .append(getFragmentsForType(Method->getReturnType(),
14249b36e126SZixu Wang                                   Method->getASTContext(), After))
14259b36e126SZixu Wang       .append(std::move(After))
14269b36e126SZixu Wang       .append(")", DeclarationFragments::FragmentKind::Text);
14279b36e126SZixu Wang 
14289b36e126SZixu Wang   // Build the selector part.
14299b36e126SZixu Wang   Selector Selector = Method->getSelector();
14309b36e126SZixu Wang   if (Selector.getNumArgs() == 0)
14319b36e126SZixu Wang     // For Objective-C methods that don't take arguments, the first (and only)
14329b36e126SZixu Wang     // slot of the selector is the method name.
14339b36e126SZixu Wang     Fragments.appendSpace().append(
14349b36e126SZixu Wang         Selector.getNameForSlot(0),
14359b36e126SZixu Wang         DeclarationFragments::FragmentKind::Identifier);
14369b36e126SZixu Wang 
14379b36e126SZixu Wang   // For Objective-C methods that take arguments, build the selector slots.
14389b36e126SZixu Wang   for (unsigned i = 0, end = Method->param_size(); i != end; ++i) {
14394048aad8SZixu Wang     // Objective-C method selector parts are considered as identifiers instead
14404048aad8SZixu Wang     // of "external parameters" as in Swift. This is because Objective-C method
14414048aad8SZixu Wang     // symbols are referenced with the entire selector, instead of just the
14424048aad8SZixu Wang     // method name in Swift.
14434048aad8SZixu Wang     SmallString<32> ParamID(Selector.getNameForSlot(i));
14444048aad8SZixu Wang     ParamID.append(":");
14454048aad8SZixu Wang     Fragments.appendSpace().append(
14464048aad8SZixu Wang         ParamID, DeclarationFragments::FragmentKind::Identifier);
14479b36e126SZixu Wang 
14489b36e126SZixu Wang     // Build the internal parameter.
14499b36e126SZixu Wang     const ParmVarDecl *Param = Method->getParamDecl(i);
14509b36e126SZixu Wang     Fragments.append(getFragmentsForParam(Param));
14519b36e126SZixu Wang   }
14529b36e126SZixu Wang 
1453e05c1b46SDaniel Grumberg   return Fragments.appendSemicolon();
14549b36e126SZixu Wang }
14559b36e126SZixu Wang 
14569b36e126SZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
14579b36e126SZixu Wang     const ObjCPropertyDecl *Property) {
14589b36e126SZixu Wang   DeclarationFragments Fragments, After;
14599b36e126SZixu Wang 
14609b36e126SZixu Wang   // Build the Objective-C property keyword.
14619b36e126SZixu Wang   Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword);
14629b36e126SZixu Wang 
146332b53cf9SUsman Akinyemi   const auto Attributes = Property->getPropertyAttributesAsWritten();
14649b36e126SZixu Wang   // Build the attributes if there is any associated with the property.
14659b36e126SZixu Wang   if (Attributes != ObjCPropertyAttribute::kind_noattr) {
14669b36e126SZixu Wang     // No leading comma for the first attribute.
14679b36e126SZixu Wang     bool First = true;
14689b36e126SZixu Wang     Fragments.append(" (", DeclarationFragments::FragmentKind::Text);
14699b36e126SZixu Wang     // Helper function to render the attribute.
14709b36e126SZixu Wang     auto RenderAttribute =
14719b36e126SZixu Wang         [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling,
14729b36e126SZixu Wang             StringRef Arg = "",
14739b36e126SZixu Wang             DeclarationFragments::FragmentKind ArgKind =
14749b36e126SZixu Wang                 DeclarationFragments::FragmentKind::Identifier) {
14759b36e126SZixu Wang           // Check if the `Kind` attribute is set for this property.
14769b36e126SZixu Wang           if ((Attributes & Kind) && !Spelling.empty()) {
14779b36e126SZixu Wang             // Add a leading comma if this is not the first attribute rendered.
14789b36e126SZixu Wang             if (!First)
14799b36e126SZixu Wang               Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
14809b36e126SZixu Wang             // Render the spelling of this attribute `Kind` as a keyword.
14819b36e126SZixu Wang             Fragments.append(Spelling,
14829b36e126SZixu Wang                              DeclarationFragments::FragmentKind::Keyword);
14839b36e126SZixu Wang             // If this attribute takes in arguments (e.g. `getter=getterName`),
14849b36e126SZixu Wang             // render the arguments.
14859b36e126SZixu Wang             if (!Arg.empty())
14869b36e126SZixu Wang               Fragments.append("=", DeclarationFragments::FragmentKind::Text)
14879b36e126SZixu Wang                   .append(Arg, ArgKind);
14889b36e126SZixu Wang             First = false;
14899b36e126SZixu Wang           }
14909b36e126SZixu Wang         };
14919b36e126SZixu Wang 
14929b36e126SZixu Wang     // Go through all possible Objective-C property attributes and render set
14939b36e126SZixu Wang     // ones.
14949b36e126SZixu Wang     RenderAttribute(ObjCPropertyAttribute::kind_class, "class");
14959b36e126SZixu Wang     RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct");
14969b36e126SZixu Wang     RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic");
14979b36e126SZixu Wang     RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic");
14989b36e126SZixu Wang     RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign");
14999b36e126SZixu Wang     RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain");
15009b36e126SZixu Wang     RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong");
15019b36e126SZixu Wang     RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy");
15029b36e126SZixu Wang     RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak");
15039b36e126SZixu Wang     RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained,
15049b36e126SZixu Wang                     "unsafe_unretained");
15059b36e126SZixu Wang     RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite");
15069b36e126SZixu Wang     RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly");
15079b36e126SZixu Wang     RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter",
15089b36e126SZixu Wang                     Property->getGetterName().getAsString());
15099b36e126SZixu Wang     RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter",
15109b36e126SZixu Wang                     Property->getSetterName().getAsString());
15119b36e126SZixu Wang 
15129b36e126SZixu Wang     // Render nullability attributes.
15139b36e126SZixu Wang     if (Attributes & ObjCPropertyAttribute::kind_nullability) {
15149b36e126SZixu Wang       QualType Type = Property->getType();
15159b36e126SZixu Wang       if (const auto Nullability =
15169b36e126SZixu Wang               AttributedType::stripOuterNullability(Type)) {
15179b36e126SZixu Wang         if (!First)
15189b36e126SZixu Wang           Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
15199b36e126SZixu Wang         if (*Nullability == NullabilityKind::Unspecified &&
15209b36e126SZixu Wang             (Attributes & ObjCPropertyAttribute::kind_null_resettable))
15219b36e126SZixu Wang           Fragments.append("null_resettable",
15229b36e126SZixu Wang                            DeclarationFragments::FragmentKind::Keyword);
15239b36e126SZixu Wang         else
15249b36e126SZixu Wang           Fragments.append(
15259b36e126SZixu Wang               getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true),
15269b36e126SZixu Wang               DeclarationFragments::FragmentKind::Keyword);
15279b36e126SZixu Wang         First = false;
15289b36e126SZixu Wang       }
15299b36e126SZixu Wang     }
15309b36e126SZixu Wang 
15319b36e126SZixu Wang     Fragments.append(")", DeclarationFragments::FragmentKind::Text);
15329b36e126SZixu Wang   }
15339b36e126SZixu Wang 
15346b89fab8SDaniel Grumberg   Fragments.appendSpace();
15356b89fab8SDaniel Grumberg 
15366b89fab8SDaniel Grumberg   FunctionTypeLoc BlockLoc;
15376b89fab8SDaniel Grumberg   FunctionProtoTypeLoc BlockProtoLoc;
15386b89fab8SDaniel Grumberg   findTypeLocForBlockDecl(Property->getTypeSourceInfo(), BlockLoc,
15396b89fab8SDaniel Grumberg                           BlockProtoLoc);
15406b89fab8SDaniel Grumberg 
15416b89fab8SDaniel Grumberg   auto PropType = Property->getType();
15426b89fab8SDaniel Grumberg   if (!BlockLoc)
15436b89fab8SDaniel Grumberg     Fragments
15446b89fab8SDaniel Grumberg         .append(getFragmentsForType(PropType, Property->getASTContext(), After))
15456b89fab8SDaniel Grumberg         .appendSpace();
15466b89fab8SDaniel Grumberg   else
15476b89fab8SDaniel Grumberg     Fragments.append(
15486b89fab8SDaniel Grumberg         getFragmentsForBlock(Property, BlockLoc, BlockProtoLoc, After));
15496b89fab8SDaniel Grumberg 
15506b89fab8SDaniel Grumberg   return Fragments
15519b36e126SZixu Wang       .append(Property->getName(),
15529b36e126SZixu Wang               DeclarationFragments::FragmentKind::Identifier)
15536b89fab8SDaniel Grumberg       .append(std::move(After))
1554e05c1b46SDaniel Grumberg       .appendSemicolon();
15559b36e126SZixu Wang }
15569b36e126SZixu Wang 
1557d1d34bafSZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(
1558d1d34bafSZixu Wang     const ObjCProtocolDecl *Protocol) {
1559d1d34bafSZixu Wang   DeclarationFragments Fragments;
1560d1d34bafSZixu Wang   // Build basic protocol declaration.
1561d1d34bafSZixu Wang   Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword)
1562d1d34bafSZixu Wang       .appendSpace()
1563d1d34bafSZixu Wang       .append(Protocol->getName(),
1564d1d34bafSZixu Wang               DeclarationFragments::FragmentKind::Identifier);
1565d1d34bafSZixu Wang 
1566d1d34bafSZixu Wang   // If this protocol conforms to other protocols, build the conformance list.
1567d1d34bafSZixu Wang   if (!Protocol->protocols().empty()) {
1568d1d34bafSZixu Wang     Fragments.append(" <", DeclarationFragments::FragmentKind::Text);
1569d1d34bafSZixu Wang     for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin();
1570d1d34bafSZixu Wang          It != Protocol->protocol_end(); It++) {
1571d1d34bafSZixu Wang       // Add a leading comma if this is not the first protocol rendered.
1572d1d34bafSZixu Wang       if (It != Protocol->protocol_begin())
1573d1d34bafSZixu Wang         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
1574d1d34bafSZixu Wang 
1575d1d34bafSZixu Wang       SmallString<128> USR;
1576d1d34bafSZixu Wang       index::generateUSRForDecl(*It, USR);
1577d1d34bafSZixu Wang       Fragments.append((*It)->getName(),
15787a851921SDaniel Grumberg                        DeclarationFragments::FragmentKind::TypeIdentifier, USR,
15797a851921SDaniel Grumberg                        *It);
1580d1d34bafSZixu Wang     }
1581d1d34bafSZixu Wang     Fragments.append(">", DeclarationFragments::FragmentKind::Text);
1582d1d34bafSZixu Wang   }
1583d1d34bafSZixu Wang 
1584d1d34bafSZixu Wang   return Fragments;
1585d1d34bafSZixu Wang }
1586d1d34bafSZixu Wang 
15879fc45ca0SDaniel Grumberg DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(
15889fc45ca0SDaniel Grumberg     const TypedefNameDecl *Decl) {
15899fc45ca0SDaniel Grumberg   DeclarationFragments Fragments, After;
15909fc45ca0SDaniel Grumberg   Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword)
15919fc45ca0SDaniel Grumberg       .appendSpace()
15929fc45ca0SDaniel Grumberg       .append(getFragmentsForType(Decl->getUnderlyingType(),
15939fc45ca0SDaniel Grumberg                                   Decl->getASTContext(), After))
15949fc45ca0SDaniel Grumberg       .append(std::move(After))
15959fc45ca0SDaniel Grumberg       .appendSpace()
15969fc45ca0SDaniel Grumberg       .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
15979fc45ca0SDaniel Grumberg 
1598e05c1b46SDaniel Grumberg   return Fragments.appendSemicolon();
15999fc45ca0SDaniel Grumberg }
16009fc45ca0SDaniel Grumberg 
16019b36e126SZixu Wang // Instantiate template for FunctionDecl.
16029b36e126SZixu Wang template FunctionSignature
16039b36e126SZixu Wang DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *);
16049b36e126SZixu Wang 
16059b36e126SZixu Wang // Instantiate template for ObjCMethodDecl.
16069b36e126SZixu Wang template FunctionSignature
16079b36e126SZixu Wang DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *);
16089b36e126SZixu Wang 
160989f6b26fSZixu Wang // Subheading of a symbol defaults to its name.
161089f6b26fSZixu Wang DeclarationFragments
161189f6b26fSZixu Wang DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) {
161289f6b26fSZixu Wang   DeclarationFragments Fragments;
161375f55eb3SErick Velez   if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl))
161475f55eb3SErick Velez     Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(),
161575f55eb3SErick Velez                      DeclarationFragments::FragmentKind::Identifier);
161675f55eb3SErick Velez   else if (isa<CXXConversionDecl>(Decl)) {
161775f55eb3SErick Velez     Fragments.append(
161875f55eb3SErick Velez         cast<CXXConversionDecl>(Decl)->getConversionType().getAsString(),
161975f55eb3SErick Velez         DeclarationFragments::FragmentKind::Identifier);
162075f55eb3SErick Velez   } else if (isa<CXXMethodDecl>(Decl) &&
162175f55eb3SErick Velez              cast<CXXMethodDecl>(Decl)->isOverloadedOperator()) {
162275f55eb3SErick Velez     Fragments.append(Decl->getNameAsString(),
162375f55eb3SErick Velez                      DeclarationFragments::FragmentKind::Identifier);
1624*33fa40ccSDaniel Grumberg   } else if (isa<TagDecl>(Decl) &&
1625*33fa40ccSDaniel Grumberg              cast<TagDecl>(Decl)->getTypedefNameForAnonDecl()) {
1626*33fa40ccSDaniel Grumberg     return getSubHeading(cast<TagDecl>(Decl)->getTypedefNameForAnonDecl());
16272c13194eSDaniel Grumberg   } else if (Decl->getIdentifier()) {
162889f6b26fSZixu Wang     Fragments.append(Decl->getName(),
162989f6b26fSZixu Wang                      DeclarationFragments::FragmentKind::Identifier);
16302c13194eSDaniel Grumberg   } else
16312c13194eSDaniel Grumberg     Fragments.append(Decl->getDeclName().getAsString(),
16322c13194eSDaniel Grumberg                      DeclarationFragments::FragmentKind::Identifier);
163389f6b26fSZixu Wang   return Fragments;
163489f6b26fSZixu Wang }
16359b36e126SZixu Wang 
16369b36e126SZixu Wang // Subheading of an Objective-C method is a `+` or `-` sign indicating whether
16379b36e126SZixu Wang // it's a class method or an instance method, followed by the selector name.
16389b36e126SZixu Wang DeclarationFragments
16399b36e126SZixu Wang DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) {
16409b36e126SZixu Wang   DeclarationFragments Fragments;
16419b36e126SZixu Wang   if (Method->isClassMethod())
16429b36e126SZixu Wang     Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
16439b36e126SZixu Wang   else if (Method->isInstanceMethod())
16449b36e126SZixu Wang     Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
16459b36e126SZixu Wang 
16469b36e126SZixu Wang   return Fragments.append(Method->getNameAsString(),
16479b36e126SZixu Wang                           DeclarationFragments::FragmentKind::Identifier);
16489b36e126SZixu Wang }
1649529a0570SDaniel Grumberg 
1650529a0570SDaniel Grumberg // Subheading of a symbol defaults to its name.
1651529a0570SDaniel Grumberg DeclarationFragments
1652529a0570SDaniel Grumberg DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) {
1653529a0570SDaniel Grumberg   DeclarationFragments Fragments;
1654529a0570SDaniel Grumberg   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
1655529a0570SDaniel Grumberg   return Fragments;
1656529a0570SDaniel Grumberg }
1657