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