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