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*5f757f3fSDimitry Andric #include "clang/AST/Decl.h" 16*5f757f3fSDimitry Andric #include "clang/AST/DeclCXX.h" 17*5f757f3fSDimitry Andric #include "clang/AST/QualTypeNames.h" 18*5f757f3fSDimitry Andric #include "clang/AST/Type.h" 19*5f757f3fSDimitry Andric #include "clang/AST/TypeLoc.h" 20*5f757f3fSDimitry Andric #include "clang/Basic/OperatorKinds.h" 2106c3fb27SDimitry Andric #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h" 2281ad6265SDimitry Andric #include "clang/Index/USRGeneration.h" 2381ad6265SDimitry Andric #include "llvm/ADT/StringSwitch.h" 24*5f757f3fSDimitry Andric #include <typeinfo> 2581ad6265SDimitry Andric 2681ad6265SDimitry Andric using namespace clang::extractapi; 2781ad6265SDimitry Andric using namespace llvm; 2881ad6265SDimitry Andric 29*5f757f3fSDimitry Andric namespace { 30*5f757f3fSDimitry Andric 31*5f757f3fSDimitry Andric void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo, 32*5f757f3fSDimitry Andric clang::FunctionTypeLoc &Block, 33*5f757f3fSDimitry Andric clang::FunctionProtoTypeLoc &BlockProto) { 34*5f757f3fSDimitry Andric if (!TSInfo) 35*5f757f3fSDimitry Andric return; 36*5f757f3fSDimitry Andric 37*5f757f3fSDimitry Andric clang::TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc(); 38*5f757f3fSDimitry Andric while (true) { 39*5f757f3fSDimitry Andric // Look through qualified types 40*5f757f3fSDimitry Andric if (auto QualifiedTL = TL.getAs<clang::QualifiedTypeLoc>()) { 41*5f757f3fSDimitry Andric TL = QualifiedTL.getUnqualifiedLoc(); 42*5f757f3fSDimitry Andric continue; 43*5f757f3fSDimitry Andric } 44*5f757f3fSDimitry Andric 45*5f757f3fSDimitry Andric if (auto AttrTL = TL.getAs<clang::AttributedTypeLoc>()) { 46*5f757f3fSDimitry Andric TL = AttrTL.getModifiedLoc(); 47*5f757f3fSDimitry Andric continue; 48*5f757f3fSDimitry Andric } 49*5f757f3fSDimitry Andric 50*5f757f3fSDimitry Andric // Try to get the function prototype behind the block pointer type, 51*5f757f3fSDimitry Andric // then we're done. 52*5f757f3fSDimitry Andric if (auto BlockPtr = TL.getAs<clang::BlockPointerTypeLoc>()) { 53*5f757f3fSDimitry Andric TL = BlockPtr.getPointeeLoc().IgnoreParens(); 54*5f757f3fSDimitry Andric Block = TL.getAs<clang::FunctionTypeLoc>(); 55*5f757f3fSDimitry Andric BlockProto = TL.getAs<clang::FunctionProtoTypeLoc>(); 56*5f757f3fSDimitry Andric } 57*5f757f3fSDimitry Andric break; 58*5f757f3fSDimitry Andric } 59*5f757f3fSDimitry Andric } 60*5f757f3fSDimitry Andric 61*5f757f3fSDimitry Andric } // namespace 62*5f757f3fSDimitry Andric 6381ad6265SDimitry Andric DeclarationFragments &DeclarationFragments::appendSpace() { 6481ad6265SDimitry Andric if (!Fragments.empty()) { 6581ad6265SDimitry Andric Fragment &Last = Fragments.back(); 6681ad6265SDimitry Andric if (Last.Kind == FragmentKind::Text) { 6781ad6265SDimitry Andric // Merge the extra space into the last fragment if the last fragment is 6881ad6265SDimitry Andric // also text. 6981ad6265SDimitry Andric if (Last.Spelling.back() != ' ') { // avoid extra trailing spaces. 7081ad6265SDimitry Andric Last.Spelling.push_back(' '); 7181ad6265SDimitry Andric } 7281ad6265SDimitry Andric } else { 7381ad6265SDimitry Andric append(" ", FragmentKind::Text); 7481ad6265SDimitry Andric } 7581ad6265SDimitry Andric } 7681ad6265SDimitry Andric 7781ad6265SDimitry Andric return *this; 7881ad6265SDimitry Andric } 7981ad6265SDimitry Andric 8081ad6265SDimitry Andric StringRef DeclarationFragments::getFragmentKindString( 8181ad6265SDimitry Andric DeclarationFragments::FragmentKind Kind) { 8281ad6265SDimitry Andric switch (Kind) { 8381ad6265SDimitry Andric case DeclarationFragments::FragmentKind::None: 8481ad6265SDimitry Andric return "none"; 8581ad6265SDimitry Andric case DeclarationFragments::FragmentKind::Keyword: 8681ad6265SDimitry Andric return "keyword"; 8781ad6265SDimitry Andric case DeclarationFragments::FragmentKind::Attribute: 8881ad6265SDimitry Andric return "attribute"; 8981ad6265SDimitry Andric case DeclarationFragments::FragmentKind::NumberLiteral: 9081ad6265SDimitry Andric return "number"; 9181ad6265SDimitry Andric case DeclarationFragments::FragmentKind::StringLiteral: 9281ad6265SDimitry Andric return "string"; 9381ad6265SDimitry Andric case DeclarationFragments::FragmentKind::Identifier: 9481ad6265SDimitry Andric return "identifier"; 9581ad6265SDimitry Andric case DeclarationFragments::FragmentKind::TypeIdentifier: 9681ad6265SDimitry Andric return "typeIdentifier"; 9781ad6265SDimitry Andric case DeclarationFragments::FragmentKind::GenericParameter: 9881ad6265SDimitry Andric return "genericParameter"; 9981ad6265SDimitry Andric case DeclarationFragments::FragmentKind::ExternalParam: 10081ad6265SDimitry Andric return "externalParam"; 10181ad6265SDimitry Andric case DeclarationFragments::FragmentKind::InternalParam: 10281ad6265SDimitry Andric return "internalParam"; 10381ad6265SDimitry Andric case DeclarationFragments::FragmentKind::Text: 10481ad6265SDimitry Andric return "text"; 10581ad6265SDimitry Andric } 10681ad6265SDimitry Andric 10781ad6265SDimitry Andric llvm_unreachable("Unhandled FragmentKind"); 10881ad6265SDimitry Andric } 10981ad6265SDimitry Andric 11081ad6265SDimitry Andric DeclarationFragments::FragmentKind 11181ad6265SDimitry Andric DeclarationFragments::parseFragmentKindFromString(StringRef S) { 11281ad6265SDimitry Andric return llvm::StringSwitch<FragmentKind>(S) 11381ad6265SDimitry Andric .Case("keyword", DeclarationFragments::FragmentKind::Keyword) 11481ad6265SDimitry Andric .Case("attribute", DeclarationFragments::FragmentKind::Attribute) 11581ad6265SDimitry Andric .Case("number", DeclarationFragments::FragmentKind::NumberLiteral) 11681ad6265SDimitry Andric .Case("string", DeclarationFragments::FragmentKind::StringLiteral) 11781ad6265SDimitry Andric .Case("identifier", DeclarationFragments::FragmentKind::Identifier) 11881ad6265SDimitry Andric .Case("typeIdentifier", 11981ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier) 12081ad6265SDimitry Andric .Case("genericParameter", 12181ad6265SDimitry Andric DeclarationFragments::FragmentKind::GenericParameter) 12281ad6265SDimitry Andric .Case("internalParam", DeclarationFragments::FragmentKind::InternalParam) 12381ad6265SDimitry Andric .Case("externalParam", DeclarationFragments::FragmentKind::ExternalParam) 12481ad6265SDimitry Andric .Case("text", DeclarationFragments::FragmentKind::Text) 12581ad6265SDimitry Andric .Default(DeclarationFragments::FragmentKind::None); 12681ad6265SDimitry Andric } 12781ad6265SDimitry Andric 128*5f757f3fSDimitry Andric DeclarationFragments DeclarationFragments::getExceptionSpecificationString( 129*5f757f3fSDimitry Andric ExceptionSpecificationType ExceptionSpec) { 130*5f757f3fSDimitry Andric DeclarationFragments Fragments; 131*5f757f3fSDimitry Andric switch (ExceptionSpec) { 132*5f757f3fSDimitry Andric case ExceptionSpecificationType::EST_None: 133*5f757f3fSDimitry Andric return Fragments; 134*5f757f3fSDimitry Andric case ExceptionSpecificationType::EST_DynamicNone: 135*5f757f3fSDimitry Andric return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) 136*5f757f3fSDimitry Andric .append("throw", DeclarationFragments::FragmentKind::Keyword) 137*5f757f3fSDimitry Andric .append("(", DeclarationFragments::FragmentKind::Text) 138*5f757f3fSDimitry Andric .append(")", DeclarationFragments::FragmentKind::Text); 139*5f757f3fSDimitry Andric case ExceptionSpecificationType::EST_Dynamic: 140*5f757f3fSDimitry Andric // FIXME: throw(int), get types of inner expression 141*5f757f3fSDimitry Andric return Fragments; 142*5f757f3fSDimitry Andric case ExceptionSpecificationType::EST_BasicNoexcept: 143*5f757f3fSDimitry Andric return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) 144*5f757f3fSDimitry Andric .append("noexcept", DeclarationFragments::FragmentKind::Keyword); 145*5f757f3fSDimitry Andric case ExceptionSpecificationType::EST_DependentNoexcept: 146*5f757f3fSDimitry Andric // FIXME: throw(conditional-expression), get expression 147*5f757f3fSDimitry Andric break; 148*5f757f3fSDimitry Andric case ExceptionSpecificationType::EST_NoexceptFalse: 149*5f757f3fSDimitry Andric return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) 150*5f757f3fSDimitry Andric .append("noexcept", DeclarationFragments::FragmentKind::Keyword) 151*5f757f3fSDimitry Andric .append("(", DeclarationFragments::FragmentKind::Text) 152*5f757f3fSDimitry Andric .append("false", DeclarationFragments::FragmentKind::Keyword) 153*5f757f3fSDimitry Andric .append(")", DeclarationFragments::FragmentKind::Text); 154*5f757f3fSDimitry Andric case ExceptionSpecificationType::EST_NoexceptTrue: 155*5f757f3fSDimitry Andric return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) 156*5f757f3fSDimitry Andric .append("noexcept", DeclarationFragments::FragmentKind::Keyword) 157*5f757f3fSDimitry Andric .append("(", DeclarationFragments::FragmentKind::Text) 158*5f757f3fSDimitry Andric .append("true", DeclarationFragments::FragmentKind::Keyword) 159*5f757f3fSDimitry Andric .append(")", DeclarationFragments::FragmentKind::Text); 160*5f757f3fSDimitry Andric default: 161*5f757f3fSDimitry Andric return Fragments; 162*5f757f3fSDimitry Andric } 163*5f757f3fSDimitry Andric 164*5f757f3fSDimitry Andric llvm_unreachable("Unhandled exception specification"); 165*5f757f3fSDimitry Andric } 166*5f757f3fSDimitry Andric 167*5f757f3fSDimitry Andric DeclarationFragments 168*5f757f3fSDimitry Andric DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) { 169*5f757f3fSDimitry Andric DeclarationFragments Fragments; 170*5f757f3fSDimitry Andric if (Record->isStruct()) 171*5f757f3fSDimitry Andric Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword); 172*5f757f3fSDimitry Andric else if (Record->isUnion()) 173*5f757f3fSDimitry Andric Fragments.append("union", DeclarationFragments::FragmentKind::Keyword); 174*5f757f3fSDimitry Andric else 175*5f757f3fSDimitry Andric Fragments.append("class", DeclarationFragments::FragmentKind::Keyword); 176*5f757f3fSDimitry Andric 177*5f757f3fSDimitry Andric return Fragments; 178*5f757f3fSDimitry Andric } 179*5f757f3fSDimitry Andric 18081ad6265SDimitry Andric // NNS stores C++ nested name specifiers, which are prefixes to qualified names. 18181ad6265SDimitry Andric // Build declaration fragments for NNS recursively so that we have the USR for 18281ad6265SDimitry Andric // every part in a qualified name, and also leaves the actual underlying type 18381ad6265SDimitry Andric // cleaner for its own fragment. 18481ad6265SDimitry Andric DeclarationFragments 18581ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS, 18681ad6265SDimitry Andric ASTContext &Context, 18781ad6265SDimitry Andric DeclarationFragments &After) { 18881ad6265SDimitry Andric DeclarationFragments Fragments; 18981ad6265SDimitry Andric if (NNS->getPrefix()) 19081ad6265SDimitry Andric Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After)); 19181ad6265SDimitry Andric 19281ad6265SDimitry Andric switch (NNS->getKind()) { 19381ad6265SDimitry Andric case NestedNameSpecifier::Identifier: 19481ad6265SDimitry Andric Fragments.append(NNS->getAsIdentifier()->getName(), 19581ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 19681ad6265SDimitry Andric break; 19781ad6265SDimitry Andric 19881ad6265SDimitry Andric case NestedNameSpecifier::Namespace: { 19981ad6265SDimitry Andric const NamespaceDecl *NS = NNS->getAsNamespace(); 20081ad6265SDimitry Andric if (NS->isAnonymousNamespace()) 20181ad6265SDimitry Andric return Fragments; 20281ad6265SDimitry Andric SmallString<128> USR; 20381ad6265SDimitry Andric index::generateUSRForDecl(NS, USR); 20481ad6265SDimitry Andric Fragments.append(NS->getName(), 205bdd1243dSDimitry Andric DeclarationFragments::FragmentKind::Identifier, USR, NS); 20681ad6265SDimitry Andric break; 20781ad6265SDimitry Andric } 20881ad6265SDimitry Andric 20981ad6265SDimitry Andric case NestedNameSpecifier::NamespaceAlias: { 21081ad6265SDimitry Andric const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias(); 21181ad6265SDimitry Andric SmallString<128> USR; 21281ad6265SDimitry Andric index::generateUSRForDecl(Alias, USR); 21381ad6265SDimitry Andric Fragments.append(Alias->getName(), 214bdd1243dSDimitry Andric DeclarationFragments::FragmentKind::Identifier, USR, 215bdd1243dSDimitry Andric Alias); 21681ad6265SDimitry Andric break; 21781ad6265SDimitry Andric } 21881ad6265SDimitry Andric 21981ad6265SDimitry Andric case NestedNameSpecifier::Global: 22081ad6265SDimitry Andric // The global specifier `::` at the beginning. No stored value. 22181ad6265SDimitry Andric break; 22281ad6265SDimitry Andric 22381ad6265SDimitry Andric case NestedNameSpecifier::Super: 22481ad6265SDimitry Andric // Microsoft's `__super` specifier. 22581ad6265SDimitry Andric Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword); 22681ad6265SDimitry Andric break; 22781ad6265SDimitry Andric 22881ad6265SDimitry Andric case NestedNameSpecifier::TypeSpecWithTemplate: 22981ad6265SDimitry Andric // A type prefixed by the `template` keyword. 23081ad6265SDimitry Andric Fragments.append("template", DeclarationFragments::FragmentKind::Keyword); 23181ad6265SDimitry Andric Fragments.appendSpace(); 23281ad6265SDimitry Andric // Fallthrough after adding the keyword to handle the actual type. 233bdd1243dSDimitry Andric [[fallthrough]]; 23481ad6265SDimitry Andric 23581ad6265SDimitry Andric case NestedNameSpecifier::TypeSpec: { 23681ad6265SDimitry Andric const Type *T = NNS->getAsType(); 23781ad6265SDimitry Andric // FIXME: Handle C++ template specialization type 23881ad6265SDimitry Andric Fragments.append(getFragmentsForType(T, Context, After)); 23981ad6265SDimitry Andric break; 24081ad6265SDimitry Andric } 24181ad6265SDimitry Andric } 24281ad6265SDimitry Andric 24381ad6265SDimitry Andric // Add the separator text `::` for this segment. 24481ad6265SDimitry Andric return Fragments.append("::", DeclarationFragments::FragmentKind::Text); 24581ad6265SDimitry Andric } 24681ad6265SDimitry Andric 24781ad6265SDimitry Andric // Recursively build the declaration fragments for an underlying `Type` with 24881ad6265SDimitry Andric // qualifiers removed. 24981ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( 25081ad6265SDimitry Andric const Type *T, ASTContext &Context, DeclarationFragments &After) { 25181ad6265SDimitry Andric assert(T && "invalid type"); 25281ad6265SDimitry Andric 25381ad6265SDimitry Andric DeclarationFragments Fragments; 25481ad6265SDimitry Andric 25581ad6265SDimitry Andric // Declaration fragments of a pointer type is the declaration fragments of 25606c3fb27SDimitry Andric // the pointee type followed by a `*`, 257*5f757f3fSDimitry Andric if (T->isPointerType() && !T->isFunctionPointerType()) 25881ad6265SDimitry Andric return Fragments 25981ad6265SDimitry Andric .append(getFragmentsForType(T->getPointeeType(), Context, After)) 26081ad6265SDimitry Andric .append(" *", DeclarationFragments::FragmentKind::Text); 26106c3fb27SDimitry Andric 26206c3fb27SDimitry Andric // For Objective-C `id` and `Class` pointers 26306c3fb27SDimitry Andric // we do not spell out the `*`. 26406c3fb27SDimitry Andric if (T->isObjCObjectPointerType() && 26506c3fb27SDimitry Andric !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) { 26606c3fb27SDimitry Andric 26706c3fb27SDimitry Andric Fragments.append(getFragmentsForType(T->getPointeeType(), Context, After)); 26806c3fb27SDimitry Andric 26906c3fb27SDimitry Andric // id<protocol> is an qualified id type 27006c3fb27SDimitry Andric // id<protocol>* is not an qualified id type 27106c3fb27SDimitry Andric if (!T->getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) { 27206c3fb27SDimitry Andric Fragments.append(" *", DeclarationFragments::FragmentKind::Text); 27306c3fb27SDimitry Andric } 27406c3fb27SDimitry Andric 27506c3fb27SDimitry Andric return Fragments; 27681ad6265SDimitry Andric } 27781ad6265SDimitry Andric 27881ad6265SDimitry Andric // Declaration fragments of a lvalue reference type is the declaration 27981ad6265SDimitry Andric // fragments of the underlying type followed by a `&`. 28081ad6265SDimitry Andric if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T)) 28181ad6265SDimitry Andric return Fragments 28281ad6265SDimitry Andric .append( 28381ad6265SDimitry Andric getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After)) 28481ad6265SDimitry Andric .append(" &", DeclarationFragments::FragmentKind::Text); 28581ad6265SDimitry Andric 28681ad6265SDimitry Andric // Declaration fragments of a rvalue reference type is the declaration 28781ad6265SDimitry Andric // fragments of the underlying type followed by a `&&`. 28881ad6265SDimitry Andric if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T)) 28981ad6265SDimitry Andric return Fragments 29081ad6265SDimitry Andric .append( 29181ad6265SDimitry Andric getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After)) 29281ad6265SDimitry Andric .append(" &&", DeclarationFragments::FragmentKind::Text); 29381ad6265SDimitry Andric 29481ad6265SDimitry Andric // Declaration fragments of an array-typed variable have two parts: 29581ad6265SDimitry Andric // 1. the element type of the array that appears before the variable name; 29681ad6265SDimitry Andric // 2. array brackets `[(0-9)?]` that appear after the variable name. 29781ad6265SDimitry Andric if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) { 29881ad6265SDimitry Andric // Build the "after" part first because the inner element type might also 29981ad6265SDimitry Andric // be an array-type. For example `int matrix[3][4]` which has a type of 30081ad6265SDimitry Andric // "(array 3 of (array 4 of ints))." 30181ad6265SDimitry Andric // Push the array size part first to make sure they are in the right order. 30281ad6265SDimitry Andric After.append("[", DeclarationFragments::FragmentKind::Text); 30381ad6265SDimitry Andric 30481ad6265SDimitry Andric switch (AT->getSizeModifier()) { 305*5f757f3fSDimitry Andric case ArraySizeModifier::Normal: 30681ad6265SDimitry Andric break; 307*5f757f3fSDimitry Andric case ArraySizeModifier::Static: 30881ad6265SDimitry Andric Fragments.append("static", DeclarationFragments::FragmentKind::Keyword); 30981ad6265SDimitry Andric break; 310*5f757f3fSDimitry Andric case ArraySizeModifier::Star: 31181ad6265SDimitry Andric Fragments.append("*", DeclarationFragments::FragmentKind::Text); 31281ad6265SDimitry Andric break; 31381ad6265SDimitry Andric } 31481ad6265SDimitry Andric 31581ad6265SDimitry Andric if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) { 31681ad6265SDimitry Andric // FIXME: right now this would evaluate any expressions/macros written in 31781ad6265SDimitry Andric // the original source to concrete values. For example 31881ad6265SDimitry Andric // `int nums[MAX]` -> `int nums[100]` 31981ad6265SDimitry Andric // `char *str[5 + 1]` -> `char *str[6]` 32081ad6265SDimitry Andric SmallString<128> Size; 32181ad6265SDimitry Andric CAT->getSize().toStringUnsigned(Size); 32281ad6265SDimitry Andric After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral); 32381ad6265SDimitry Andric } 32481ad6265SDimitry Andric 32581ad6265SDimitry Andric After.append("]", DeclarationFragments::FragmentKind::Text); 32681ad6265SDimitry Andric 32781ad6265SDimitry Andric return Fragments.append( 32881ad6265SDimitry Andric getFragmentsForType(AT->getElementType(), Context, After)); 32981ad6265SDimitry Andric } 33081ad6265SDimitry Andric 33181ad6265SDimitry Andric // An ElaboratedType is a sugar for types that are referred to using an 33281ad6265SDimitry Andric // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a 33381ad6265SDimitry Andric // qualified name, e.g., `N::M::type`, or both. 33481ad6265SDimitry Andric if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) { 33581ad6265SDimitry Andric ElaboratedTypeKeyword Keyword = ET->getKeyword(); 336*5f757f3fSDimitry Andric if (Keyword != ElaboratedTypeKeyword::None) { 33781ad6265SDimitry Andric Fragments 33881ad6265SDimitry Andric .append(ElaboratedType::getKeywordName(Keyword), 33981ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword) 34081ad6265SDimitry Andric .appendSpace(); 34181ad6265SDimitry Andric } 34281ad6265SDimitry Andric 34381ad6265SDimitry Andric if (const NestedNameSpecifier *NNS = ET->getQualifier()) 34481ad6265SDimitry Andric Fragments.append(getFragmentsForNNS(NNS, Context, After)); 34581ad6265SDimitry Andric 34681ad6265SDimitry Andric // After handling the elaborated keyword or qualified name, build 34781ad6265SDimitry Andric // declaration fragments for the desugared underlying type. 34881ad6265SDimitry Andric return Fragments.append(getFragmentsForType(ET->desugar(), Context, After)); 34981ad6265SDimitry Andric } 35081ad6265SDimitry Andric 35181ad6265SDimitry Andric // If the type is a typedefed type, get the underlying TypedefNameDecl for a 35281ad6265SDimitry Andric // direct reference to the typedef instead of the wrapped type. 35306c3fb27SDimitry Andric 35406c3fb27SDimitry Andric // 'id' type is a typedef for an ObjCObjectPointerType 35506c3fb27SDimitry Andric // we treat it as a typedef 35681ad6265SDimitry Andric if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) { 35781ad6265SDimitry Andric const TypedefNameDecl *Decl = TypedefTy->getDecl(); 358bdd1243dSDimitry Andric TypedefUnderlyingTypeResolver TypedefResolver(Context); 359bdd1243dSDimitry Andric std::string USR = TypedefResolver.getUSRForType(QualType(T, 0)); 36006c3fb27SDimitry Andric 36106c3fb27SDimitry Andric if (T->isObjCIdType()) { 36206c3fb27SDimitry Andric return Fragments.append(Decl->getName(), 36306c3fb27SDimitry Andric DeclarationFragments::FragmentKind::Keyword); 36406c3fb27SDimitry Andric } 36506c3fb27SDimitry Andric 366bdd1243dSDimitry Andric return Fragments.append( 367bdd1243dSDimitry Andric Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier, 368bdd1243dSDimitry Andric USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0))); 36981ad6265SDimitry Andric } 37081ad6265SDimitry Andric 37106c3fb27SDimitry Andric // Everything we care about has been handled now, reduce to the canonical 37206c3fb27SDimitry Andric // unqualified base type. 37306c3fb27SDimitry Andric QualType Base = T->getCanonicalTypeUnqualified(); 37406c3fb27SDimitry Andric 37581ad6265SDimitry Andric // If the base type is a TagType (struct/interface/union/class/enum), let's 37681ad6265SDimitry Andric // get the underlying Decl for better names and USRs. 37781ad6265SDimitry Andric if (const TagType *TagTy = dyn_cast<TagType>(Base)) { 37881ad6265SDimitry Andric const TagDecl *Decl = TagTy->getDecl(); 37981ad6265SDimitry Andric // Anonymous decl, skip this fragment. 38081ad6265SDimitry Andric if (Decl->getName().empty()) 38181ad6265SDimitry Andric return Fragments; 38281ad6265SDimitry Andric SmallString<128> TagUSR; 38381ad6265SDimitry Andric clang::index::generateUSRForDecl(Decl, TagUSR); 38481ad6265SDimitry Andric return Fragments.append(Decl->getName(), 38581ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, 386bdd1243dSDimitry Andric TagUSR, Decl); 38781ad6265SDimitry Andric } 38881ad6265SDimitry Andric 38981ad6265SDimitry Andric // If the base type is an ObjCInterfaceType, use the underlying 39081ad6265SDimitry Andric // ObjCInterfaceDecl for the true USR. 39181ad6265SDimitry Andric if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) { 39281ad6265SDimitry Andric const auto *Decl = ObjCIT->getDecl(); 39381ad6265SDimitry Andric SmallString<128> USR; 39481ad6265SDimitry Andric index::generateUSRForDecl(Decl, USR); 39581ad6265SDimitry Andric return Fragments.append(Decl->getName(), 39681ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, 397bdd1243dSDimitry Andric USR, Decl); 39881ad6265SDimitry Andric } 39981ad6265SDimitry Andric 40081ad6265SDimitry Andric // Default fragment builder for other kinds of types (BuiltinType etc.) 40181ad6265SDimitry Andric SmallString<128> USR; 40281ad6265SDimitry Andric clang::index::generateUSRForType(Base, Context, USR); 40381ad6265SDimitry Andric Fragments.append(Base.getAsString(), 40481ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, USR); 40581ad6265SDimitry Andric 40681ad6265SDimitry Andric return Fragments; 40781ad6265SDimitry Andric } 40881ad6265SDimitry Andric 40981ad6265SDimitry Andric DeclarationFragments 41081ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) { 41181ad6265SDimitry Andric DeclarationFragments Fragments; 41281ad6265SDimitry Andric if (Quals.hasConst()) 41381ad6265SDimitry Andric Fragments.append("const", DeclarationFragments::FragmentKind::Keyword); 41481ad6265SDimitry Andric if (Quals.hasVolatile()) 41581ad6265SDimitry Andric Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword); 41681ad6265SDimitry Andric if (Quals.hasRestrict()) 41781ad6265SDimitry Andric Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword); 41881ad6265SDimitry Andric 41981ad6265SDimitry Andric return Fragments; 42081ad6265SDimitry Andric } 42181ad6265SDimitry Andric 42281ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( 42381ad6265SDimitry Andric const QualType QT, ASTContext &Context, DeclarationFragments &After) { 42481ad6265SDimitry Andric assert(!QT.isNull() && "invalid type"); 42581ad6265SDimitry Andric 42681ad6265SDimitry Andric if (const ParenType *PT = dyn_cast<ParenType>(QT)) { 42781ad6265SDimitry Andric After.append(")", DeclarationFragments::FragmentKind::Text); 42881ad6265SDimitry Andric return getFragmentsForType(PT->getInnerType(), Context, After) 42981ad6265SDimitry Andric .append("(", DeclarationFragments::FragmentKind::Text); 43081ad6265SDimitry Andric } 43181ad6265SDimitry Andric 43281ad6265SDimitry Andric const SplitQualType SQT = QT.split(); 43381ad6265SDimitry Andric DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals), 43481ad6265SDimitry Andric TypeFragments = 43581ad6265SDimitry Andric getFragmentsForType(SQT.Ty, Context, After); 436*5f757f3fSDimitry Andric if (QT.getAsString() == "_Bool") 437*5f757f3fSDimitry Andric TypeFragments.replace("bool", 0); 438*5f757f3fSDimitry Andric 43981ad6265SDimitry Andric if (QualsFragments.getFragments().empty()) 44081ad6265SDimitry Andric return TypeFragments; 44181ad6265SDimitry Andric 44281ad6265SDimitry Andric // Use east qualifier for pointer types 44381ad6265SDimitry Andric // For example: 44481ad6265SDimitry Andric // ``` 44581ad6265SDimitry Andric // int * const 44681ad6265SDimitry Andric // ^---- ^---- 44781ad6265SDimitry Andric // type qualifier 44881ad6265SDimitry Andric // ^----------------- 44981ad6265SDimitry Andric // const pointer to int 45081ad6265SDimitry Andric // ``` 45181ad6265SDimitry Andric // should not be reconstructed as 45281ad6265SDimitry Andric // ``` 45381ad6265SDimitry Andric // const int * 45481ad6265SDimitry Andric // ^---- ^-- 45581ad6265SDimitry Andric // qualifier type 45681ad6265SDimitry Andric // ^---------------- ^ 45781ad6265SDimitry Andric // pointer to const int 45881ad6265SDimitry Andric // ``` 45981ad6265SDimitry Andric if (SQT.Ty->isAnyPointerType()) 46081ad6265SDimitry Andric return TypeFragments.appendSpace().append(std::move(QualsFragments)); 46181ad6265SDimitry Andric 46281ad6265SDimitry Andric return QualsFragments.appendSpace().append(std::move(TypeFragments)); 46381ad6265SDimitry Andric } 46481ad6265SDimitry Andric 465*5f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace( 466*5f757f3fSDimitry Andric const NamespaceDecl *Decl) { 467*5f757f3fSDimitry Andric DeclarationFragments Fragments; 468*5f757f3fSDimitry Andric Fragments.append("namespace", DeclarationFragments::FragmentKind::Keyword); 469*5f757f3fSDimitry Andric if (!Decl->isAnonymousNamespace()) 470*5f757f3fSDimitry Andric Fragments.appendSpace().append( 471*5f757f3fSDimitry Andric Decl->getName(), DeclarationFragments::FragmentKind::Identifier); 472*5f757f3fSDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 473*5f757f3fSDimitry Andric } 474*5f757f3fSDimitry Andric 47581ad6265SDimitry Andric DeclarationFragments 47681ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) { 47781ad6265SDimitry Andric DeclarationFragments Fragments; 478*5f757f3fSDimitry Andric if (Var->isConstexpr()) 479*5f757f3fSDimitry Andric Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 480*5f757f3fSDimitry Andric .appendSpace(); 481*5f757f3fSDimitry Andric 48281ad6265SDimitry Andric StorageClass SC = Var->getStorageClass(); 48381ad6265SDimitry Andric if (SC != SC_None) 48481ad6265SDimitry Andric Fragments 48581ad6265SDimitry Andric .append(VarDecl::getStorageClassSpecifierString(SC), 48681ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword) 48781ad6265SDimitry Andric .appendSpace(); 48881ad6265SDimitry Andric 48981ad6265SDimitry Andric // Capture potential fragments that needs to be placed after the variable name 49081ad6265SDimitry Andric // ``` 49181ad6265SDimitry Andric // int nums[5]; 49281ad6265SDimitry Andric // char (*ptr_to_array)[6]; 49381ad6265SDimitry Andric // ``` 49481ad6265SDimitry Andric DeclarationFragments After; 495*5f757f3fSDimitry Andric FunctionTypeLoc BlockLoc; 496*5f757f3fSDimitry Andric FunctionProtoTypeLoc BlockProtoLoc; 497*5f757f3fSDimitry Andric findTypeLocForBlockDecl(Var->getTypeSourceInfo(), BlockLoc, BlockProtoLoc); 498*5f757f3fSDimitry Andric 499*5f757f3fSDimitry Andric if (!BlockLoc) { 500*5f757f3fSDimitry Andric QualType T = Var->getTypeSourceInfo() 501*5f757f3fSDimitry Andric ? Var->getTypeSourceInfo()->getType() 502*5f757f3fSDimitry Andric : Var->getASTContext().getUnqualifiedObjCPointerType( 503*5f757f3fSDimitry Andric Var->getType()); 504*5f757f3fSDimitry Andric 505*5f757f3fSDimitry Andric Fragments.append(getFragmentsForType(T, Var->getASTContext(), After)) 506*5f757f3fSDimitry Andric .appendSpace(); 507*5f757f3fSDimitry Andric } else { 508*5f757f3fSDimitry Andric Fragments.append(getFragmentsForBlock(Var, BlockLoc, BlockProtoLoc, After)); 509*5f757f3fSDimitry Andric } 510*5f757f3fSDimitry Andric 511*5f757f3fSDimitry Andric return Fragments 512*5f757f3fSDimitry Andric .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) 513*5f757f3fSDimitry Andric .append(std::move(After)) 514*5f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text); 515*5f757f3fSDimitry Andric } 516*5f757f3fSDimitry Andric 517*5f757f3fSDimitry Andric DeclarationFragments 518*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) { 519*5f757f3fSDimitry Andric DeclarationFragments Fragments; 520*5f757f3fSDimitry Andric if (Var->isConstexpr()) 521*5f757f3fSDimitry Andric Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 522*5f757f3fSDimitry Andric .appendSpace(); 523*5f757f3fSDimitry Andric QualType T = 524*5f757f3fSDimitry Andric Var->getTypeSourceInfo() 525*5f757f3fSDimitry Andric ? Var->getTypeSourceInfo()->getType() 526*5f757f3fSDimitry Andric : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType()); 527*5f757f3fSDimitry Andric 528*5f757f3fSDimitry Andric // Might be a member, so might be static. 529*5f757f3fSDimitry Andric if (Var->isStaticDataMember()) 530*5f757f3fSDimitry Andric Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) 531*5f757f3fSDimitry Andric .appendSpace(); 532*5f757f3fSDimitry Andric 533*5f757f3fSDimitry Andric DeclarationFragments After; 534*5f757f3fSDimitry Andric DeclarationFragments ArgumentFragment = 535*5f757f3fSDimitry Andric getFragmentsForType(T, Var->getASTContext(), After); 536*5f757f3fSDimitry Andric if (ArgumentFragment.begin()->Spelling.substr(0, 14).compare( 537*5f757f3fSDimitry Andric "type-parameter") == 0) { 538*5f757f3fSDimitry Andric std::string ProperArgName = getNameForTemplateArgument( 539*5f757f3fSDimitry Andric Var->getDescribedVarTemplate()->getTemplateParameters()->asArray(), 540*5f757f3fSDimitry Andric ArgumentFragment.begin()->Spelling); 541*5f757f3fSDimitry Andric ArgumentFragment.begin()->Spelling.swap(ProperArgName); 542*5f757f3fSDimitry Andric } 543*5f757f3fSDimitry Andric Fragments.append(std::move(ArgumentFragment)) 54481ad6265SDimitry Andric .appendSpace() 54581ad6265SDimitry Andric .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) 546*5f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text); 547*5f757f3fSDimitry Andric return Fragments; 54881ad6265SDimitry Andric } 54981ad6265SDimitry Andric 55081ad6265SDimitry Andric DeclarationFragments 55181ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) { 55281ad6265SDimitry Andric DeclarationFragments Fragments, After; 55381ad6265SDimitry Andric 554*5f757f3fSDimitry Andric auto *TSInfo = Param->getTypeSourceInfo(); 555*5f757f3fSDimitry Andric 556*5f757f3fSDimitry Andric QualType T = TSInfo ? TSInfo->getType() 55781ad6265SDimitry Andric : Param->getASTContext().getUnqualifiedObjCPointerType( 55881ad6265SDimitry Andric Param->getType()); 55981ad6265SDimitry Andric 560*5f757f3fSDimitry Andric FunctionTypeLoc BlockLoc; 561*5f757f3fSDimitry Andric FunctionProtoTypeLoc BlockProtoLoc; 562*5f757f3fSDimitry Andric findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc); 56381ad6265SDimitry Andric 564*5f757f3fSDimitry Andric DeclarationFragments TypeFragments; 565*5f757f3fSDimitry Andric if (BlockLoc) 566*5f757f3fSDimitry Andric TypeFragments.append( 567*5f757f3fSDimitry Andric getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After)); 568*5f757f3fSDimitry Andric else 569*5f757f3fSDimitry Andric TypeFragments.append(getFragmentsForType(T, Param->getASTContext(), After)); 570*5f757f3fSDimitry Andric 571*5f757f3fSDimitry Andric if (TypeFragments.begin()->Spelling.substr(0, 14).compare("type-parameter") == 572*5f757f3fSDimitry Andric 0) { 573*5f757f3fSDimitry Andric std::string ProperArgName = getNameForTemplateArgument( 574*5f757f3fSDimitry Andric dyn_cast<FunctionDecl>(Param->getDeclContext()) 575*5f757f3fSDimitry Andric ->getDescribedFunctionTemplate() 576*5f757f3fSDimitry Andric ->getTemplateParameters() 577*5f757f3fSDimitry Andric ->asArray(), 578*5f757f3fSDimitry Andric TypeFragments.begin()->Spelling); 579*5f757f3fSDimitry Andric TypeFragments.begin()->Spelling.swap(ProperArgName); 580*5f757f3fSDimitry Andric } 581*5f757f3fSDimitry Andric 582*5f757f3fSDimitry Andric if (Param->isObjCMethodParameter()) { 58381ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text) 58481ad6265SDimitry Andric .append(std::move(TypeFragments)) 585*5f757f3fSDimitry Andric .append(std::move(After)) 586*5f757f3fSDimitry Andric .append(") ", DeclarationFragments::FragmentKind::Text) 587*5f757f3fSDimitry Andric .append(Param->getName(), 588*5f757f3fSDimitry Andric DeclarationFragments::FragmentKind::InternalParam); 589*5f757f3fSDimitry Andric } else { 590*5f757f3fSDimitry Andric Fragments.append(std::move(TypeFragments)); 591*5f757f3fSDimitry Andric if (!T->isBlockPointerType()) 592*5f757f3fSDimitry Andric Fragments.appendSpace(); 593*5f757f3fSDimitry Andric Fragments 59481ad6265SDimitry Andric .append(Param->getName(), 59581ad6265SDimitry Andric DeclarationFragments::FragmentKind::InternalParam) 59681ad6265SDimitry Andric .append(std::move(After)); 59781ad6265SDimitry Andric } 598*5f757f3fSDimitry Andric return Fragments; 599*5f757f3fSDimitry Andric } 600*5f757f3fSDimitry Andric 601*5f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForBlock( 602*5f757f3fSDimitry Andric const NamedDecl *BlockDecl, FunctionTypeLoc &Block, 603*5f757f3fSDimitry Andric FunctionProtoTypeLoc &BlockProto, DeclarationFragments &After) { 604*5f757f3fSDimitry Andric DeclarationFragments Fragments; 605*5f757f3fSDimitry Andric 606*5f757f3fSDimitry Andric DeclarationFragments RetTyAfter; 607*5f757f3fSDimitry Andric auto ReturnValueFragment = getFragmentsForType( 608*5f757f3fSDimitry Andric Block.getTypePtr()->getReturnType(), BlockDecl->getASTContext(), After); 609*5f757f3fSDimitry Andric 610*5f757f3fSDimitry Andric Fragments.append(std::move(ReturnValueFragment)) 611*5f757f3fSDimitry Andric .append(std::move(RetTyAfter)) 612*5f757f3fSDimitry Andric .appendSpace() 613*5f757f3fSDimitry Andric .append("(^", DeclarationFragments::FragmentKind::Text); 614*5f757f3fSDimitry Andric 615*5f757f3fSDimitry Andric After.append(")", DeclarationFragments::FragmentKind::Text); 616*5f757f3fSDimitry Andric unsigned NumParams = Block.getNumParams(); 617*5f757f3fSDimitry Andric 618*5f757f3fSDimitry Andric if (!BlockProto || NumParams == 0) { 619*5f757f3fSDimitry Andric if (BlockProto && BlockProto.getTypePtr()->isVariadic()) 620*5f757f3fSDimitry Andric After.append("(...)", DeclarationFragments::FragmentKind::Text); 621*5f757f3fSDimitry Andric else 622*5f757f3fSDimitry Andric After.append("()", DeclarationFragments::FragmentKind::Text); 623*5f757f3fSDimitry Andric } else { 624*5f757f3fSDimitry Andric After.append("(", DeclarationFragments::FragmentKind::Text); 625*5f757f3fSDimitry Andric for (unsigned I = 0; I != NumParams; ++I) { 626*5f757f3fSDimitry Andric if (I) 627*5f757f3fSDimitry Andric After.append(", ", DeclarationFragments::FragmentKind::Text); 628*5f757f3fSDimitry Andric After.append(getFragmentsForParam(Block.getParam(I))); 629*5f757f3fSDimitry Andric if (I == NumParams - 1 && BlockProto.getTypePtr()->isVariadic()) 630*5f757f3fSDimitry Andric After.append(", ...", DeclarationFragments::FragmentKind::Text); 631*5f757f3fSDimitry Andric } 632*5f757f3fSDimitry Andric After.append(")", DeclarationFragments::FragmentKind::Text); 633*5f757f3fSDimitry Andric } 634*5f757f3fSDimitry Andric 635*5f757f3fSDimitry Andric return Fragments; 636*5f757f3fSDimitry Andric } 63781ad6265SDimitry Andric 63881ad6265SDimitry Andric DeclarationFragments 63981ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) { 64081ad6265SDimitry Andric DeclarationFragments Fragments; 64181ad6265SDimitry Andric // FIXME: Handle template specialization 64281ad6265SDimitry Andric switch (Func->getStorageClass()) { 64381ad6265SDimitry Andric case SC_None: 64481ad6265SDimitry Andric case SC_PrivateExtern: 64581ad6265SDimitry Andric break; 64681ad6265SDimitry Andric case SC_Extern: 64781ad6265SDimitry Andric Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword) 64881ad6265SDimitry Andric .appendSpace(); 64981ad6265SDimitry Andric break; 65081ad6265SDimitry Andric case SC_Static: 65181ad6265SDimitry Andric Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) 65281ad6265SDimitry Andric .appendSpace(); 65381ad6265SDimitry Andric break; 65481ad6265SDimitry Andric case SC_Auto: 65581ad6265SDimitry Andric case SC_Register: 65681ad6265SDimitry Andric llvm_unreachable("invalid for functions"); 65781ad6265SDimitry Andric } 658*5f757f3fSDimitry Andric if (Func->isConsteval()) // if consteval, it is also constexpr 659*5f757f3fSDimitry Andric Fragments.append("consteval", DeclarationFragments::FragmentKind::Keyword) 660*5f757f3fSDimitry Andric .appendSpace(); 661*5f757f3fSDimitry Andric else if (Func->isConstexpr()) 662*5f757f3fSDimitry Andric Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 663*5f757f3fSDimitry Andric .appendSpace(); 66481ad6265SDimitry Andric 66581ad6265SDimitry Andric // FIXME: Is `after` actually needed here? 66681ad6265SDimitry Andric DeclarationFragments After; 667*5f757f3fSDimitry Andric auto ReturnValueFragment = 668*5f757f3fSDimitry Andric getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After); 669*5f757f3fSDimitry Andric if (ReturnValueFragment.begin()->Spelling.substr(0, 14).compare( 670*5f757f3fSDimitry Andric "type-parameter") == 0) { 671*5f757f3fSDimitry Andric std::string ProperArgName = 672*5f757f3fSDimitry Andric getNameForTemplateArgument(Func->getDescribedFunctionTemplate() 673*5f757f3fSDimitry Andric ->getTemplateParameters() 674*5f757f3fSDimitry Andric ->asArray(), 675*5f757f3fSDimitry Andric ReturnValueFragment.begin()->Spelling); 676*5f757f3fSDimitry Andric ReturnValueFragment.begin()->Spelling.swap(ProperArgName); 677*5f757f3fSDimitry Andric } 678*5f757f3fSDimitry Andric 679*5f757f3fSDimitry Andric Fragments.append(std::move(ReturnValueFragment)) 68081ad6265SDimitry Andric .appendSpace() 681*5f757f3fSDimitry Andric .append(Func->getName(), DeclarationFragments::FragmentKind::Identifier); 682*5f757f3fSDimitry Andric 683*5f757f3fSDimitry Andric if (Func->getTemplateSpecializationInfo()) { 684*5f757f3fSDimitry Andric Fragments.append("<", DeclarationFragments::FragmentKind::Text); 685*5f757f3fSDimitry Andric 686*5f757f3fSDimitry Andric for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) { 687*5f757f3fSDimitry Andric if (i) 688*5f757f3fSDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 689*5f757f3fSDimitry Andric Fragments.append( 690*5f757f3fSDimitry Andric getFragmentsForType(Func->getParamDecl(i)->getType(), 691*5f757f3fSDimitry Andric Func->getParamDecl(i)->getASTContext(), After)); 692*5f757f3fSDimitry Andric } 693*5f757f3fSDimitry Andric Fragments.append(">", DeclarationFragments::FragmentKind::Text); 694*5f757f3fSDimitry Andric } 695*5f757f3fSDimitry Andric Fragments.append(std::move(After)); 69681ad6265SDimitry Andric 69781ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text); 698*5f757f3fSDimitry Andric unsigned NumParams = Func->getNumParams(); 699*5f757f3fSDimitry Andric for (unsigned i = 0; i != NumParams; ++i) { 70081ad6265SDimitry Andric if (i) 70181ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 70281ad6265SDimitry Andric Fragments.append(getFragmentsForParam(Func->getParamDecl(i))); 70381ad6265SDimitry Andric } 704*5f757f3fSDimitry Andric 705*5f757f3fSDimitry Andric if (Func->isVariadic()) { 706*5f757f3fSDimitry Andric if (NumParams > 0) 707*5f757f3fSDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 708*5f757f3fSDimitry Andric Fragments.append("...", DeclarationFragments::FragmentKind::Text); 709*5f757f3fSDimitry Andric } 71081ad6265SDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 71181ad6265SDimitry Andric 712*5f757f3fSDimitry Andric Fragments.append(DeclarationFragments::getExceptionSpecificationString( 713*5f757f3fSDimitry Andric Func->getExceptionSpecType())); 714*5f757f3fSDimitry Andric 71506c3fb27SDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 71681ad6265SDimitry Andric } 71781ad6265SDimitry Andric 71881ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant( 71981ad6265SDimitry Andric const EnumConstantDecl *EnumConstDecl) { 72081ad6265SDimitry Andric DeclarationFragments Fragments; 72181ad6265SDimitry Andric return Fragments.append(EnumConstDecl->getName(), 72281ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 72381ad6265SDimitry Andric } 72481ad6265SDimitry Andric 72581ad6265SDimitry Andric DeclarationFragments 72681ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) { 72781ad6265SDimitry Andric if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl()) 72881ad6265SDimitry Andric return getFragmentsForTypedef(TypedefNameDecl); 72981ad6265SDimitry Andric 73081ad6265SDimitry Andric DeclarationFragments Fragments, After; 73181ad6265SDimitry Andric Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword); 73281ad6265SDimitry Andric 73381ad6265SDimitry Andric if (!EnumDecl->getName().empty()) 73481ad6265SDimitry Andric Fragments.appendSpace().append( 73581ad6265SDimitry Andric EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier); 73681ad6265SDimitry Andric 73781ad6265SDimitry Andric QualType IntegerType = EnumDecl->getIntegerType(); 73881ad6265SDimitry Andric if (!IntegerType.isNull()) 73981ad6265SDimitry Andric Fragments.append(": ", DeclarationFragments::FragmentKind::Text) 74081ad6265SDimitry Andric .append( 74181ad6265SDimitry Andric getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After)) 74281ad6265SDimitry Andric .append(std::move(After)); 74381ad6265SDimitry Andric 74406c3fb27SDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 74581ad6265SDimitry Andric } 74681ad6265SDimitry Andric 74781ad6265SDimitry Andric DeclarationFragments 74881ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) { 74981ad6265SDimitry Andric DeclarationFragments After; 750*5f757f3fSDimitry Andric DeclarationFragments Fragments; 751*5f757f3fSDimitry Andric if (Field->isMutable()) 752*5f757f3fSDimitry Andric Fragments.append("mutable", DeclarationFragments::FragmentKind::Keyword) 753*5f757f3fSDimitry Andric .appendSpace(); 754*5f757f3fSDimitry Andric return Fragments 755*5f757f3fSDimitry Andric .append( 756*5f757f3fSDimitry Andric getFragmentsForType(Field->getType(), Field->getASTContext(), After)) 75781ad6265SDimitry Andric .appendSpace() 75881ad6265SDimitry Andric .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier) 759*5f757f3fSDimitry Andric .append(std::move(After)) 760*5f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text); 76181ad6265SDimitry Andric } 76281ad6265SDimitry Andric 76381ad6265SDimitry Andric DeclarationFragments 76481ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForStruct(const RecordDecl *Record) { 76581ad6265SDimitry Andric if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl()) 76681ad6265SDimitry Andric return getFragmentsForTypedef(TypedefNameDecl); 76781ad6265SDimitry Andric 76881ad6265SDimitry Andric DeclarationFragments Fragments; 76981ad6265SDimitry Andric Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword); 77081ad6265SDimitry Andric 77181ad6265SDimitry Andric if (!Record->getName().empty()) 77281ad6265SDimitry Andric Fragments.appendSpace().append( 77381ad6265SDimitry Andric Record->getName(), DeclarationFragments::FragmentKind::Identifier); 77406c3fb27SDimitry Andric 77506c3fb27SDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 77681ad6265SDimitry Andric } 77781ad6265SDimitry Andric 778*5f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass( 779*5f757f3fSDimitry Andric const CXXRecordDecl *Record) { 780*5f757f3fSDimitry Andric if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl()) 781*5f757f3fSDimitry Andric return getFragmentsForTypedef(TypedefNameDecl); 782*5f757f3fSDimitry Andric 783*5f757f3fSDimitry Andric DeclarationFragments Fragments; 784*5f757f3fSDimitry Andric Fragments.append(DeclarationFragments::getStructureTypeFragment(Record)); 785*5f757f3fSDimitry Andric 786*5f757f3fSDimitry Andric if (!Record->getName().empty()) 787*5f757f3fSDimitry Andric Fragments.appendSpace().append( 788*5f757f3fSDimitry Andric Record->getName(), DeclarationFragments::FragmentKind::Identifier); 789*5f757f3fSDimitry Andric 790*5f757f3fSDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 791*5f757f3fSDimitry Andric } 792*5f757f3fSDimitry Andric 793*5f757f3fSDimitry Andric DeclarationFragments 794*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod( 795*5f757f3fSDimitry Andric const CXXMethodDecl *Method) { 796*5f757f3fSDimitry Andric DeclarationFragments Fragments; 797*5f757f3fSDimitry Andric std::string Name; 798*5f757f3fSDimitry Andric if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(Method)) { 799*5f757f3fSDimitry Andric Name = Method->getNameAsString(); 800*5f757f3fSDimitry Andric if (Constructor->isExplicit()) 801*5f757f3fSDimitry Andric Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword) 802*5f757f3fSDimitry Andric .appendSpace(); 803*5f757f3fSDimitry Andric } else if (isa<CXXDestructorDecl>(Method)) 804*5f757f3fSDimitry Andric Name = Method->getNameAsString(); 805*5f757f3fSDimitry Andric 806*5f757f3fSDimitry Andric DeclarationFragments After; 807*5f757f3fSDimitry Andric Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier) 808*5f757f3fSDimitry Andric .append(std::move(After)); 809*5f757f3fSDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text); 810*5f757f3fSDimitry Andric for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) { 811*5f757f3fSDimitry Andric if (i) 812*5f757f3fSDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 813*5f757f3fSDimitry Andric Fragments.append(getFragmentsForParam(Method->getParamDecl(i))); 814*5f757f3fSDimitry Andric } 815*5f757f3fSDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 816*5f757f3fSDimitry Andric 817*5f757f3fSDimitry Andric Fragments.append(DeclarationFragments::getExceptionSpecificationString( 818*5f757f3fSDimitry Andric Method->getExceptionSpecType())); 819*5f757f3fSDimitry Andric 820*5f757f3fSDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 821*5f757f3fSDimitry Andric } 822*5f757f3fSDimitry Andric 823*5f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod( 824*5f757f3fSDimitry Andric const CXXMethodDecl *Method) { 825*5f757f3fSDimitry Andric DeclarationFragments Fragments; 826*5f757f3fSDimitry Andric StringRef Name = Method->getName(); 827*5f757f3fSDimitry Andric if (Method->isStatic()) 828*5f757f3fSDimitry Andric Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) 829*5f757f3fSDimitry Andric .appendSpace(); 830*5f757f3fSDimitry Andric if (Method->isConstexpr()) 831*5f757f3fSDimitry Andric Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 832*5f757f3fSDimitry Andric .appendSpace(); 833*5f757f3fSDimitry Andric if (Method->isVolatile()) 834*5f757f3fSDimitry Andric Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword) 835*5f757f3fSDimitry Andric .appendSpace(); 836*5f757f3fSDimitry Andric 837*5f757f3fSDimitry Andric // Build return type 838*5f757f3fSDimitry Andric DeclarationFragments After; 839*5f757f3fSDimitry Andric Fragments 840*5f757f3fSDimitry Andric .append(getFragmentsForType(Method->getReturnType(), 841*5f757f3fSDimitry Andric Method->getASTContext(), After)) 842*5f757f3fSDimitry Andric .appendSpace() 843*5f757f3fSDimitry Andric .append(Name, DeclarationFragments::FragmentKind::Identifier) 844*5f757f3fSDimitry Andric .append(std::move(After)); 845*5f757f3fSDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text); 846*5f757f3fSDimitry Andric for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) { 847*5f757f3fSDimitry Andric if (i) 848*5f757f3fSDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 849*5f757f3fSDimitry Andric Fragments.append(getFragmentsForParam(Method->getParamDecl(i))); 850*5f757f3fSDimitry Andric } 851*5f757f3fSDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 852*5f757f3fSDimitry Andric 853*5f757f3fSDimitry Andric if (Method->isConst()) 854*5f757f3fSDimitry Andric Fragments.appendSpace().append("const", 855*5f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Keyword); 856*5f757f3fSDimitry Andric 857*5f757f3fSDimitry Andric Fragments.append(DeclarationFragments::getExceptionSpecificationString( 858*5f757f3fSDimitry Andric Method->getExceptionSpecType())); 859*5f757f3fSDimitry Andric 860*5f757f3fSDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 861*5f757f3fSDimitry Andric } 862*5f757f3fSDimitry Andric 863*5f757f3fSDimitry Andric DeclarationFragments 864*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForConversionFunction( 865*5f757f3fSDimitry Andric const CXXConversionDecl *ConversionFunction) { 866*5f757f3fSDimitry Andric DeclarationFragments Fragments; 867*5f757f3fSDimitry Andric 868*5f757f3fSDimitry Andric if (ConversionFunction->isExplicit()) 869*5f757f3fSDimitry Andric Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword) 870*5f757f3fSDimitry Andric .appendSpace(); 871*5f757f3fSDimitry Andric 872*5f757f3fSDimitry Andric Fragments.append("operator", DeclarationFragments::FragmentKind::Keyword) 873*5f757f3fSDimitry Andric .appendSpace(); 874*5f757f3fSDimitry Andric 875*5f757f3fSDimitry Andric Fragments 876*5f757f3fSDimitry Andric .append(ConversionFunction->getConversionType().getAsString(), 877*5f757f3fSDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier) 878*5f757f3fSDimitry Andric .append("(", DeclarationFragments::FragmentKind::Text); 879*5f757f3fSDimitry Andric for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end; 880*5f757f3fSDimitry Andric ++i) { 881*5f757f3fSDimitry Andric if (i) 882*5f757f3fSDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 883*5f757f3fSDimitry Andric Fragments.append(getFragmentsForParam(ConversionFunction->getParamDecl(i))); 884*5f757f3fSDimitry Andric } 885*5f757f3fSDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 886*5f757f3fSDimitry Andric 887*5f757f3fSDimitry Andric if (ConversionFunction->isConst()) 888*5f757f3fSDimitry Andric Fragments.appendSpace().append("const", 889*5f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Keyword); 890*5f757f3fSDimitry Andric 891*5f757f3fSDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 892*5f757f3fSDimitry Andric } 893*5f757f3fSDimitry Andric 894*5f757f3fSDimitry Andric DeclarationFragments 895*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator( 896*5f757f3fSDimitry Andric const CXXMethodDecl *Method) { 897*5f757f3fSDimitry Andric DeclarationFragments Fragments; 898*5f757f3fSDimitry Andric 899*5f757f3fSDimitry Andric // Build return type 900*5f757f3fSDimitry Andric DeclarationFragments After; 901*5f757f3fSDimitry Andric Fragments 902*5f757f3fSDimitry Andric .append(getFragmentsForType(Method->getReturnType(), 903*5f757f3fSDimitry Andric Method->getASTContext(), After)) 904*5f757f3fSDimitry Andric .appendSpace() 905*5f757f3fSDimitry Andric .append(Method->getNameAsString(), 906*5f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Identifier) 907*5f757f3fSDimitry Andric .append(std::move(After)); 908*5f757f3fSDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text); 909*5f757f3fSDimitry Andric for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) { 910*5f757f3fSDimitry Andric if (i) 911*5f757f3fSDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 912*5f757f3fSDimitry Andric Fragments.append(getFragmentsForParam(Method->getParamDecl(i))); 913*5f757f3fSDimitry Andric } 914*5f757f3fSDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 915*5f757f3fSDimitry Andric 916*5f757f3fSDimitry Andric if (Method->isConst()) 917*5f757f3fSDimitry Andric Fragments.appendSpace().append("const", 918*5f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Keyword); 919*5f757f3fSDimitry Andric 920*5f757f3fSDimitry Andric Fragments.append(DeclarationFragments::getExceptionSpecificationString( 921*5f757f3fSDimitry Andric Method->getExceptionSpecType())); 922*5f757f3fSDimitry Andric 923*5f757f3fSDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 924*5f757f3fSDimitry Andric } 925*5f757f3fSDimitry Andric 926*5f757f3fSDimitry Andric // Get fragments for template parameters, e.g. T in tempalte<typename T> ... 927*5f757f3fSDimitry Andric DeclarationFragments 928*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForTemplateParameters( 929*5f757f3fSDimitry Andric ArrayRef<NamedDecl *> ParameterArray) { 930*5f757f3fSDimitry Andric DeclarationFragments Fragments; 931*5f757f3fSDimitry Andric for (unsigned i = 0, end = ParameterArray.size(); i != end; ++i) { 932*5f757f3fSDimitry Andric if (i) 933*5f757f3fSDimitry Andric Fragments.append(",", DeclarationFragments::FragmentKind::Text) 934*5f757f3fSDimitry Andric .appendSpace(); 935*5f757f3fSDimitry Andric 936*5f757f3fSDimitry Andric const auto *TemplateParam = 937*5f757f3fSDimitry Andric dyn_cast<TemplateTypeParmDecl>(ParameterArray[i]); 938*5f757f3fSDimitry Andric if (!TemplateParam) 939*5f757f3fSDimitry Andric continue; 940*5f757f3fSDimitry Andric if (TemplateParam->hasTypeConstraint()) 941*5f757f3fSDimitry Andric Fragments.append(TemplateParam->getTypeConstraint() 942*5f757f3fSDimitry Andric ->getNamedConcept() 943*5f757f3fSDimitry Andric ->getName() 944*5f757f3fSDimitry Andric .str(), 945*5f757f3fSDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier); 946*5f757f3fSDimitry Andric else if (TemplateParam->wasDeclaredWithTypename()) 947*5f757f3fSDimitry Andric Fragments.append("typename", DeclarationFragments::FragmentKind::Keyword); 948*5f757f3fSDimitry Andric else 949*5f757f3fSDimitry Andric Fragments.append("class", DeclarationFragments::FragmentKind::Keyword); 950*5f757f3fSDimitry Andric 951*5f757f3fSDimitry Andric if (TemplateParam->isParameterPack()) 952*5f757f3fSDimitry Andric Fragments.append("...", DeclarationFragments::FragmentKind::Text); 953*5f757f3fSDimitry Andric 954*5f757f3fSDimitry Andric Fragments.appendSpace().append( 955*5f757f3fSDimitry Andric TemplateParam->getName(), 956*5f757f3fSDimitry Andric DeclarationFragments::FragmentKind::GenericParameter); 957*5f757f3fSDimitry Andric } 958*5f757f3fSDimitry Andric return Fragments; 959*5f757f3fSDimitry Andric } 960*5f757f3fSDimitry Andric 961*5f757f3fSDimitry Andric // Find the name of a template argument from the template's parameters. 962*5f757f3fSDimitry Andric std::string DeclarationFragmentsBuilder::getNameForTemplateArgument( 963*5f757f3fSDimitry Andric const ArrayRef<NamedDecl *> TemplateParameters, std::string TypeParameter) { 964*5f757f3fSDimitry Andric // The arg is a generic parameter from a partial spec, e.g. 965*5f757f3fSDimitry Andric // T in template<typename T> Foo<T, int>. 966*5f757f3fSDimitry Andric // 967*5f757f3fSDimitry Andric // Those names appear as "type-parameter-<index>-<depth>", so we must find its 968*5f757f3fSDimitry Andric // name from the template's parameter list. 969*5f757f3fSDimitry Andric for (unsigned i = 0; i < TemplateParameters.size(); ++i) { 970*5f757f3fSDimitry Andric const auto *Parameter = 971*5f757f3fSDimitry Andric dyn_cast<TemplateTypeParmDecl>(TemplateParameters[i]); 972*5f757f3fSDimitry Andric if (TypeParameter.compare("type-parameter-" + 973*5f757f3fSDimitry Andric std::to_string(Parameter->getDepth()) + "-" + 974*5f757f3fSDimitry Andric std::to_string(Parameter->getIndex())) == 0) 975*5f757f3fSDimitry Andric return std::string(TemplateParameters[i]->getName()); 976*5f757f3fSDimitry Andric } 977*5f757f3fSDimitry Andric llvm_unreachable("Could not find the name of a template argument."); 978*5f757f3fSDimitry Andric } 979*5f757f3fSDimitry Andric 980*5f757f3fSDimitry Andric // Get fragments for template arguments, e.g. int in template<typename T> 981*5f757f3fSDimitry Andric // Foo<int>; 982*5f757f3fSDimitry Andric // 983*5f757f3fSDimitry Andric // Note: TemplateParameters is only necessary if the Decl is a 984*5f757f3fSDimitry Andric // PartialSpecialization, where we need the parameters to deduce the name of the 985*5f757f3fSDimitry Andric // generic arguments. 986*5f757f3fSDimitry Andric DeclarationFragments 987*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForTemplateArguments( 988*5f757f3fSDimitry Andric const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context, 989*5f757f3fSDimitry Andric const std::optional<ArrayRef<NamedDecl *>> TemplateParameters) { 990*5f757f3fSDimitry Andric DeclarationFragments Fragments; 991*5f757f3fSDimitry Andric for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) { 992*5f757f3fSDimitry Andric if (i) 993*5f757f3fSDimitry Andric Fragments.append(",", DeclarationFragments::FragmentKind::Text) 994*5f757f3fSDimitry Andric .appendSpace(); 995*5f757f3fSDimitry Andric 996*5f757f3fSDimitry Andric std::string Type = TemplateArguments[i].getAsType().getAsString(); 997*5f757f3fSDimitry Andric DeclarationFragments After; 998*5f757f3fSDimitry Andric DeclarationFragments ArgumentFragment = 999*5f757f3fSDimitry Andric getFragmentsForType(TemplateArguments[i].getAsType(), Context, After); 1000*5f757f3fSDimitry Andric 1001*5f757f3fSDimitry Andric if (ArgumentFragment.begin()->Spelling.substr(0, 14).compare( 1002*5f757f3fSDimitry Andric "type-parameter") == 0) { 1003*5f757f3fSDimitry Andric std::string ProperArgName = getNameForTemplateArgument( 1004*5f757f3fSDimitry Andric TemplateParameters.value(), ArgumentFragment.begin()->Spelling); 1005*5f757f3fSDimitry Andric ArgumentFragment.begin()->Spelling.swap(ProperArgName); 1006*5f757f3fSDimitry Andric } 1007*5f757f3fSDimitry Andric Fragments.append(std::move(ArgumentFragment)); 1008*5f757f3fSDimitry Andric 1009*5f757f3fSDimitry Andric if (TemplateArguments[i].isPackExpansion()) 1010*5f757f3fSDimitry Andric Fragments.append("...", DeclarationFragments::FragmentKind::Text); 1011*5f757f3fSDimitry Andric } 1012*5f757f3fSDimitry Andric return Fragments; 1013*5f757f3fSDimitry Andric } 1014*5f757f3fSDimitry Andric 1015*5f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept( 1016*5f757f3fSDimitry Andric const ConceptDecl *Concept) { 1017*5f757f3fSDimitry Andric DeclarationFragments Fragments; 1018*5f757f3fSDimitry Andric return Fragments 1019*5f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword) 1020*5f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 1021*5f757f3fSDimitry Andric .append(getFragmentsForTemplateParameters( 1022*5f757f3fSDimitry Andric Concept->getTemplateParameters()->asArray())) 1023*5f757f3fSDimitry Andric .append("> ", DeclarationFragments::FragmentKind::Text) 1024*5f757f3fSDimitry Andric .append("concept", DeclarationFragments::FragmentKind::Keyword) 1025*5f757f3fSDimitry Andric .appendSpace() 1026*5f757f3fSDimitry Andric .append(Concept->getName().str(), 1027*5f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Identifier) 1028*5f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text); 1029*5f757f3fSDimitry Andric } 1030*5f757f3fSDimitry Andric 1031*5f757f3fSDimitry Andric DeclarationFragments 1032*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate( 1033*5f757f3fSDimitry Andric const RedeclarableTemplateDecl *RedeclarableTemplate) { 1034*5f757f3fSDimitry Andric DeclarationFragments Fragments; 1035*5f757f3fSDimitry Andric Fragments.append("template", DeclarationFragments::FragmentKind::Keyword) 1036*5f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 1037*5f757f3fSDimitry Andric .append(getFragmentsForTemplateParameters( 1038*5f757f3fSDimitry Andric RedeclarableTemplate->getTemplateParameters()->asArray())) 1039*5f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 1040*5f757f3fSDimitry Andric .appendSpace(); 1041*5f757f3fSDimitry Andric 1042*5f757f3fSDimitry Andric if (isa<TypeAliasTemplateDecl>(RedeclarableTemplate)) 1043*5f757f3fSDimitry Andric Fragments.appendSpace() 1044*5f757f3fSDimitry Andric .append("using", DeclarationFragments::FragmentKind::Keyword) 1045*5f757f3fSDimitry Andric .appendSpace() 1046*5f757f3fSDimitry Andric .append(RedeclarableTemplate->getName(), 1047*5f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Identifier); 1048*5f757f3fSDimitry Andric // the templated records will be resposbible for injecting their templates 1049*5f757f3fSDimitry Andric return Fragments.appendSpace(); 1050*5f757f3fSDimitry Andric } 1051*5f757f3fSDimitry Andric 1052*5f757f3fSDimitry Andric DeclarationFragments 1053*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization( 1054*5f757f3fSDimitry Andric const ClassTemplateSpecializationDecl *Decl) { 1055*5f757f3fSDimitry Andric DeclarationFragments Fragments; 1056*5f757f3fSDimitry Andric return Fragments 1057*5f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword) 1058*5f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 1059*5f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 1060*5f757f3fSDimitry Andric .appendSpace() 1061*5f757f3fSDimitry Andric .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass( 1062*5f757f3fSDimitry Andric cast<CXXRecordDecl>(Decl))) 1063*5f757f3fSDimitry Andric .pop_back() // there is an extra semicolon now 1064*5f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 1065*5f757f3fSDimitry Andric .append( 1066*5f757f3fSDimitry Andric getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(), 1067*5f757f3fSDimitry Andric Decl->getASTContext(), std::nullopt)) 1068*5f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 1069*5f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text); 1070*5f757f3fSDimitry Andric } 1071*5f757f3fSDimitry Andric 1072*5f757f3fSDimitry Andric DeclarationFragments 1073*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization( 1074*5f757f3fSDimitry Andric const ClassTemplatePartialSpecializationDecl *Decl) { 1075*5f757f3fSDimitry Andric DeclarationFragments Fragments; 1076*5f757f3fSDimitry Andric return Fragments 1077*5f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword) 1078*5f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 1079*5f757f3fSDimitry Andric .append(getFragmentsForTemplateParameters( 1080*5f757f3fSDimitry Andric Decl->getTemplateParameters()->asArray())) 1081*5f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 1082*5f757f3fSDimitry Andric .appendSpace() 1083*5f757f3fSDimitry Andric .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass( 1084*5f757f3fSDimitry Andric cast<CXXRecordDecl>(Decl))) 1085*5f757f3fSDimitry Andric .pop_back() // there is an extra semicolon now 1086*5f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 1087*5f757f3fSDimitry Andric .append(getFragmentsForTemplateArguments( 1088*5f757f3fSDimitry Andric Decl->getTemplateArgs().asArray(), Decl->getASTContext(), 1089*5f757f3fSDimitry Andric Decl->getTemplateParameters()->asArray())) 1090*5f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 1091*5f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text); 1092*5f757f3fSDimitry Andric } 1093*5f757f3fSDimitry Andric 1094*5f757f3fSDimitry Andric DeclarationFragments 1095*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization( 1096*5f757f3fSDimitry Andric const VarTemplateSpecializationDecl *Decl) { 1097*5f757f3fSDimitry Andric DeclarationFragments Fragments; 1098*5f757f3fSDimitry Andric return Fragments 1099*5f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword) 1100*5f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 1101*5f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 1102*5f757f3fSDimitry Andric .appendSpace() 1103*5f757f3fSDimitry Andric .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl)) 1104*5f757f3fSDimitry Andric .pop_back() // there is an extra semicolon now 1105*5f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 1106*5f757f3fSDimitry Andric .append( 1107*5f757f3fSDimitry Andric getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(), 1108*5f757f3fSDimitry Andric Decl->getASTContext(), std::nullopt)) 1109*5f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 1110*5f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text); 1111*5f757f3fSDimitry Andric } 1112*5f757f3fSDimitry Andric 1113*5f757f3fSDimitry Andric DeclarationFragments 1114*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization( 1115*5f757f3fSDimitry Andric const VarTemplatePartialSpecializationDecl *Decl) { 1116*5f757f3fSDimitry Andric DeclarationFragments Fragments; 1117*5f757f3fSDimitry Andric return Fragments 1118*5f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword) 1119*5f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 1120*5f757f3fSDimitry Andric // Partial specs may have new params. 1121*5f757f3fSDimitry Andric .append(getFragmentsForTemplateParameters( 1122*5f757f3fSDimitry Andric Decl->getTemplateParameters()->asArray())) 1123*5f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 1124*5f757f3fSDimitry Andric .appendSpace() 1125*5f757f3fSDimitry Andric .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl)) 1126*5f757f3fSDimitry Andric .pop_back() // there is an extra semicolon now 1127*5f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 1128*5f757f3fSDimitry Andric .append(getFragmentsForTemplateArguments( 1129*5f757f3fSDimitry Andric Decl->getTemplateArgs().asArray(), Decl->getASTContext(), 1130*5f757f3fSDimitry Andric Decl->getTemplateParameters()->asArray())) 1131*5f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 1132*5f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text); 1133*5f757f3fSDimitry Andric } 1134*5f757f3fSDimitry Andric 1135*5f757f3fSDimitry Andric DeclarationFragments 1136*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate( 1137*5f757f3fSDimitry Andric const FunctionTemplateDecl *Decl) { 1138*5f757f3fSDimitry Andric DeclarationFragments Fragments; 1139*5f757f3fSDimitry Andric return Fragments 1140*5f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword) 1141*5f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 1142*5f757f3fSDimitry Andric // Partial specs may have new params. 1143*5f757f3fSDimitry Andric .append(getFragmentsForTemplateParameters( 1144*5f757f3fSDimitry Andric Decl->getTemplateParameters()->asArray())) 1145*5f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 1146*5f757f3fSDimitry Andric .appendSpace() 1147*5f757f3fSDimitry Andric .append(DeclarationFragmentsBuilder::getFragmentsForFunction( 1148*5f757f3fSDimitry Andric Decl->getAsFunction())); 1149*5f757f3fSDimitry Andric } 1150*5f757f3fSDimitry Andric 1151*5f757f3fSDimitry Andric DeclarationFragments 1152*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization( 1153*5f757f3fSDimitry Andric const FunctionDecl *Decl) { 1154*5f757f3fSDimitry Andric DeclarationFragments Fragments; 1155*5f757f3fSDimitry Andric return Fragments 1156*5f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword) 1157*5f757f3fSDimitry Andric .append("<>", DeclarationFragments::FragmentKind::Text) 1158*5f757f3fSDimitry Andric .appendSpace() 1159*5f757f3fSDimitry Andric .append(DeclarationFragmentsBuilder::getFragmentsForFunction(Decl)); 1160*5f757f3fSDimitry Andric } 1161*5f757f3fSDimitry Andric 116281ad6265SDimitry Andric DeclarationFragments 116381ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name, 116481ad6265SDimitry Andric const MacroDirective *MD) { 116581ad6265SDimitry Andric DeclarationFragments Fragments; 116681ad6265SDimitry Andric Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword) 116781ad6265SDimitry Andric .appendSpace(); 116881ad6265SDimitry Andric Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); 116981ad6265SDimitry Andric 117081ad6265SDimitry Andric auto *MI = MD->getMacroInfo(); 117181ad6265SDimitry Andric 117281ad6265SDimitry Andric if (MI->isFunctionLike()) { 117381ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text); 117481ad6265SDimitry Andric unsigned numParameters = MI->getNumParams(); 117581ad6265SDimitry Andric if (MI->isC99Varargs()) 117681ad6265SDimitry Andric --numParameters; 117781ad6265SDimitry Andric for (unsigned i = 0; i < numParameters; ++i) { 117881ad6265SDimitry Andric if (i) 117981ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 118081ad6265SDimitry Andric Fragments.append(MI->params()[i]->getName(), 118181ad6265SDimitry Andric DeclarationFragments::FragmentKind::InternalParam); 118281ad6265SDimitry Andric } 118381ad6265SDimitry Andric if (MI->isVariadic()) { 118481ad6265SDimitry Andric if (numParameters && MI->isC99Varargs()) 118581ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 118681ad6265SDimitry Andric Fragments.append("...", DeclarationFragments::FragmentKind::Text); 118781ad6265SDimitry Andric } 118881ad6265SDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 118981ad6265SDimitry Andric } 119081ad6265SDimitry Andric return Fragments; 119181ad6265SDimitry Andric } 119281ad6265SDimitry Andric 119381ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory( 119481ad6265SDimitry Andric const ObjCCategoryDecl *Category) { 119581ad6265SDimitry Andric DeclarationFragments Fragments; 119681ad6265SDimitry Andric 1197bdd1243dSDimitry Andric auto *Interface = Category->getClassInterface(); 119881ad6265SDimitry Andric SmallString<128> InterfaceUSR; 1199bdd1243dSDimitry Andric index::generateUSRForDecl(Interface, InterfaceUSR); 120081ad6265SDimitry Andric 120181ad6265SDimitry Andric Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) 120281ad6265SDimitry Andric .appendSpace() 120381ad6265SDimitry Andric .append(Category->getClassInterface()->getName(), 1204bdd1243dSDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR, 1205bdd1243dSDimitry Andric Interface) 120681ad6265SDimitry Andric .append(" (", DeclarationFragments::FragmentKind::Text) 120781ad6265SDimitry Andric .append(Category->getName(), 120881ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier) 120981ad6265SDimitry Andric .append(")", DeclarationFragments::FragmentKind::Text); 121081ad6265SDimitry Andric 121181ad6265SDimitry Andric return Fragments; 121281ad6265SDimitry Andric } 121381ad6265SDimitry Andric 121481ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface( 121581ad6265SDimitry Andric const ObjCInterfaceDecl *Interface) { 121681ad6265SDimitry Andric DeclarationFragments Fragments; 121781ad6265SDimitry Andric // Build the base of the Objective-C interface declaration. 121881ad6265SDimitry Andric Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) 121981ad6265SDimitry Andric .appendSpace() 122081ad6265SDimitry Andric .append(Interface->getName(), 122181ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 122281ad6265SDimitry Andric 122381ad6265SDimitry Andric // Build the inheritance part of the declaration. 122481ad6265SDimitry Andric if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) { 122581ad6265SDimitry Andric SmallString<128> SuperUSR; 122681ad6265SDimitry Andric index::generateUSRForDecl(SuperClass, SuperUSR); 122781ad6265SDimitry Andric Fragments.append(" : ", DeclarationFragments::FragmentKind::Text) 122881ad6265SDimitry Andric .append(SuperClass->getName(), 1229bdd1243dSDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR, 1230bdd1243dSDimitry Andric SuperClass); 123181ad6265SDimitry Andric } 123281ad6265SDimitry Andric 123381ad6265SDimitry Andric return Fragments; 123481ad6265SDimitry Andric } 123581ad6265SDimitry Andric 123681ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod( 123781ad6265SDimitry Andric const ObjCMethodDecl *Method) { 123881ad6265SDimitry Andric DeclarationFragments Fragments, After; 123981ad6265SDimitry Andric // Build the instance/class method indicator. 124081ad6265SDimitry Andric if (Method->isClassMethod()) 124181ad6265SDimitry Andric Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); 124281ad6265SDimitry Andric else if (Method->isInstanceMethod()) 124381ad6265SDimitry Andric Fragments.append("- ", DeclarationFragments::FragmentKind::Text); 124481ad6265SDimitry Andric 124581ad6265SDimitry Andric // Build the return type. 124681ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text) 124781ad6265SDimitry Andric .append(getFragmentsForType(Method->getReturnType(), 124881ad6265SDimitry Andric Method->getASTContext(), After)) 124981ad6265SDimitry Andric .append(std::move(After)) 125081ad6265SDimitry Andric .append(")", DeclarationFragments::FragmentKind::Text); 125181ad6265SDimitry Andric 125281ad6265SDimitry Andric // Build the selector part. 125381ad6265SDimitry Andric Selector Selector = Method->getSelector(); 125481ad6265SDimitry Andric if (Selector.getNumArgs() == 0) 125581ad6265SDimitry Andric // For Objective-C methods that don't take arguments, the first (and only) 125681ad6265SDimitry Andric // slot of the selector is the method name. 125781ad6265SDimitry Andric Fragments.appendSpace().append( 125881ad6265SDimitry Andric Selector.getNameForSlot(0), 125981ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 126081ad6265SDimitry Andric 126181ad6265SDimitry Andric // For Objective-C methods that take arguments, build the selector slots. 126281ad6265SDimitry Andric for (unsigned i = 0, end = Method->param_size(); i != end; ++i) { 126381ad6265SDimitry Andric // Objective-C method selector parts are considered as identifiers instead 126481ad6265SDimitry Andric // of "external parameters" as in Swift. This is because Objective-C method 126581ad6265SDimitry Andric // symbols are referenced with the entire selector, instead of just the 126681ad6265SDimitry Andric // method name in Swift. 126781ad6265SDimitry Andric SmallString<32> ParamID(Selector.getNameForSlot(i)); 126881ad6265SDimitry Andric ParamID.append(":"); 126981ad6265SDimitry Andric Fragments.appendSpace().append( 127081ad6265SDimitry Andric ParamID, DeclarationFragments::FragmentKind::Identifier); 127181ad6265SDimitry Andric 127281ad6265SDimitry Andric // Build the internal parameter. 127381ad6265SDimitry Andric const ParmVarDecl *Param = Method->getParamDecl(i); 127481ad6265SDimitry Andric Fragments.append(getFragmentsForParam(Param)); 127581ad6265SDimitry Andric } 127681ad6265SDimitry Andric 127781ad6265SDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 127881ad6265SDimitry Andric } 127981ad6265SDimitry Andric 128081ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty( 128181ad6265SDimitry Andric const ObjCPropertyDecl *Property) { 128281ad6265SDimitry Andric DeclarationFragments Fragments, After; 128381ad6265SDimitry Andric 128481ad6265SDimitry Andric // Build the Objective-C property keyword. 128581ad6265SDimitry Andric Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword); 128681ad6265SDimitry Andric 128706c3fb27SDimitry Andric const auto Attributes = Property->getPropertyAttributesAsWritten(); 128881ad6265SDimitry Andric // Build the attributes if there is any associated with the property. 128981ad6265SDimitry Andric if (Attributes != ObjCPropertyAttribute::kind_noattr) { 129081ad6265SDimitry Andric // No leading comma for the first attribute. 129181ad6265SDimitry Andric bool First = true; 129281ad6265SDimitry Andric Fragments.append(" (", DeclarationFragments::FragmentKind::Text); 129381ad6265SDimitry Andric // Helper function to render the attribute. 129481ad6265SDimitry Andric auto RenderAttribute = 129581ad6265SDimitry Andric [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling, 129681ad6265SDimitry Andric StringRef Arg = "", 129781ad6265SDimitry Andric DeclarationFragments::FragmentKind ArgKind = 129881ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier) { 129981ad6265SDimitry Andric // Check if the `Kind` attribute is set for this property. 130081ad6265SDimitry Andric if ((Attributes & Kind) && !Spelling.empty()) { 130181ad6265SDimitry Andric // Add a leading comma if this is not the first attribute rendered. 130281ad6265SDimitry Andric if (!First) 130381ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 130481ad6265SDimitry Andric // Render the spelling of this attribute `Kind` as a keyword. 130581ad6265SDimitry Andric Fragments.append(Spelling, 130681ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword); 130781ad6265SDimitry Andric // If this attribute takes in arguments (e.g. `getter=getterName`), 130881ad6265SDimitry Andric // render the arguments. 130981ad6265SDimitry Andric if (!Arg.empty()) 131081ad6265SDimitry Andric Fragments.append("=", DeclarationFragments::FragmentKind::Text) 131181ad6265SDimitry Andric .append(Arg, ArgKind); 131281ad6265SDimitry Andric First = false; 131381ad6265SDimitry Andric } 131481ad6265SDimitry Andric }; 131581ad6265SDimitry Andric 131681ad6265SDimitry Andric // Go through all possible Objective-C property attributes and render set 131781ad6265SDimitry Andric // ones. 131881ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_class, "class"); 131981ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct"); 132081ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic"); 132181ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic"); 132281ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign"); 132381ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain"); 132481ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong"); 132581ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy"); 132681ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak"); 132781ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained, 132881ad6265SDimitry Andric "unsafe_unretained"); 132981ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite"); 133081ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly"); 133181ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter", 133281ad6265SDimitry Andric Property->getGetterName().getAsString()); 133381ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter", 133481ad6265SDimitry Andric Property->getSetterName().getAsString()); 133581ad6265SDimitry Andric 133681ad6265SDimitry Andric // Render nullability attributes. 133781ad6265SDimitry Andric if (Attributes & ObjCPropertyAttribute::kind_nullability) { 133881ad6265SDimitry Andric QualType Type = Property->getType(); 133981ad6265SDimitry Andric if (const auto Nullability = 134081ad6265SDimitry Andric AttributedType::stripOuterNullability(Type)) { 134181ad6265SDimitry Andric if (!First) 134281ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 134381ad6265SDimitry Andric if (*Nullability == NullabilityKind::Unspecified && 134481ad6265SDimitry Andric (Attributes & ObjCPropertyAttribute::kind_null_resettable)) 134581ad6265SDimitry Andric Fragments.append("null_resettable", 134681ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword); 134781ad6265SDimitry Andric else 134881ad6265SDimitry Andric Fragments.append( 134981ad6265SDimitry Andric getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true), 135081ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword); 135181ad6265SDimitry Andric First = false; 135281ad6265SDimitry Andric } 135381ad6265SDimitry Andric } 135481ad6265SDimitry Andric 135581ad6265SDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 135681ad6265SDimitry Andric } 135781ad6265SDimitry Andric 1358*5f757f3fSDimitry Andric Fragments.appendSpace(); 1359*5f757f3fSDimitry Andric 1360*5f757f3fSDimitry Andric FunctionTypeLoc BlockLoc; 1361*5f757f3fSDimitry Andric FunctionProtoTypeLoc BlockProtoLoc; 1362*5f757f3fSDimitry Andric findTypeLocForBlockDecl(Property->getTypeSourceInfo(), BlockLoc, 1363*5f757f3fSDimitry Andric BlockProtoLoc); 1364*5f757f3fSDimitry Andric 1365*5f757f3fSDimitry Andric auto PropType = Property->getType(); 1366*5f757f3fSDimitry Andric if (!BlockLoc) 1367*5f757f3fSDimitry Andric Fragments 1368*5f757f3fSDimitry Andric .append(getFragmentsForType(PropType, Property->getASTContext(), After)) 1369*5f757f3fSDimitry Andric .appendSpace(); 1370*5f757f3fSDimitry Andric else 1371*5f757f3fSDimitry Andric Fragments.append( 1372*5f757f3fSDimitry Andric getFragmentsForBlock(Property, BlockLoc, BlockProtoLoc, After)); 1373*5f757f3fSDimitry Andric 1374*5f757f3fSDimitry Andric return Fragments 137581ad6265SDimitry Andric .append(Property->getName(), 137681ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier) 1377*5f757f3fSDimitry Andric .append(std::move(After)) 1378*5f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text); 137981ad6265SDimitry Andric } 138081ad6265SDimitry Andric 138181ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol( 138281ad6265SDimitry Andric const ObjCProtocolDecl *Protocol) { 138381ad6265SDimitry Andric DeclarationFragments Fragments; 138481ad6265SDimitry Andric // Build basic protocol declaration. 138581ad6265SDimitry Andric Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword) 138681ad6265SDimitry Andric .appendSpace() 138781ad6265SDimitry Andric .append(Protocol->getName(), 138881ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 138981ad6265SDimitry Andric 139081ad6265SDimitry Andric // If this protocol conforms to other protocols, build the conformance list. 139181ad6265SDimitry Andric if (!Protocol->protocols().empty()) { 139281ad6265SDimitry Andric Fragments.append(" <", DeclarationFragments::FragmentKind::Text); 139381ad6265SDimitry Andric for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin(); 139481ad6265SDimitry Andric It != Protocol->protocol_end(); It++) { 139581ad6265SDimitry Andric // Add a leading comma if this is not the first protocol rendered. 139681ad6265SDimitry Andric if (It != Protocol->protocol_begin()) 139781ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 139881ad6265SDimitry Andric 139981ad6265SDimitry Andric SmallString<128> USR; 140081ad6265SDimitry Andric index::generateUSRForDecl(*It, USR); 140181ad6265SDimitry Andric Fragments.append((*It)->getName(), 1402bdd1243dSDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, USR, 1403bdd1243dSDimitry Andric *It); 140481ad6265SDimitry Andric } 140581ad6265SDimitry Andric Fragments.append(">", DeclarationFragments::FragmentKind::Text); 140681ad6265SDimitry Andric } 140781ad6265SDimitry Andric 140881ad6265SDimitry Andric return Fragments; 140981ad6265SDimitry Andric } 141081ad6265SDimitry Andric 141181ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef( 141281ad6265SDimitry Andric const TypedefNameDecl *Decl) { 141381ad6265SDimitry Andric DeclarationFragments Fragments, After; 141481ad6265SDimitry Andric Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword) 141581ad6265SDimitry Andric .appendSpace() 141681ad6265SDimitry Andric .append(getFragmentsForType(Decl->getUnderlyingType(), 141781ad6265SDimitry Andric Decl->getASTContext(), After)) 141881ad6265SDimitry Andric .append(std::move(After)) 141981ad6265SDimitry Andric .appendSpace() 142081ad6265SDimitry Andric .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier); 142181ad6265SDimitry Andric 142206c3fb27SDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 142381ad6265SDimitry Andric } 142481ad6265SDimitry Andric 142581ad6265SDimitry Andric // Instantiate template for FunctionDecl. 142681ad6265SDimitry Andric template FunctionSignature 142781ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *); 142881ad6265SDimitry Andric 142981ad6265SDimitry Andric // Instantiate template for ObjCMethodDecl. 143081ad6265SDimitry Andric template FunctionSignature 143181ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *); 143281ad6265SDimitry Andric 143381ad6265SDimitry Andric // Subheading of a symbol defaults to its name. 143481ad6265SDimitry Andric DeclarationFragments 143581ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) { 143681ad6265SDimitry Andric DeclarationFragments Fragments; 1437*5f757f3fSDimitry Andric if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl)) 1438*5f757f3fSDimitry Andric Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(), 1439*5f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Identifier); 1440*5f757f3fSDimitry Andric else if (isa<CXXConversionDecl>(Decl)) { 1441*5f757f3fSDimitry Andric Fragments.append( 1442*5f757f3fSDimitry Andric cast<CXXConversionDecl>(Decl)->getConversionType().getAsString(), 1443*5f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Identifier); 1444*5f757f3fSDimitry Andric } else if (isa<CXXMethodDecl>(Decl) && 1445*5f757f3fSDimitry Andric cast<CXXMethodDecl>(Decl)->isOverloadedOperator()) { 1446*5f757f3fSDimitry Andric Fragments.append(Decl->getNameAsString(), 1447*5f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Identifier); 1448*5f757f3fSDimitry Andric } else if (!Decl->getName().empty()) 144981ad6265SDimitry Andric Fragments.append(Decl->getName(), 145081ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 145181ad6265SDimitry Andric return Fragments; 145281ad6265SDimitry Andric } 145381ad6265SDimitry Andric 145481ad6265SDimitry Andric // Subheading of an Objective-C method is a `+` or `-` sign indicating whether 145581ad6265SDimitry Andric // it's a class method or an instance method, followed by the selector name. 145681ad6265SDimitry Andric DeclarationFragments 145781ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) { 145881ad6265SDimitry Andric DeclarationFragments Fragments; 145981ad6265SDimitry Andric if (Method->isClassMethod()) 146081ad6265SDimitry Andric Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); 146181ad6265SDimitry Andric else if (Method->isInstanceMethod()) 146281ad6265SDimitry Andric Fragments.append("- ", DeclarationFragments::FragmentKind::Text); 146381ad6265SDimitry Andric 146481ad6265SDimitry Andric return Fragments.append(Method->getNameAsString(), 146581ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 146681ad6265SDimitry Andric } 146781ad6265SDimitry Andric 146881ad6265SDimitry Andric // Subheading of a symbol defaults to its name. 146981ad6265SDimitry Andric DeclarationFragments 147081ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) { 147181ad6265SDimitry Andric DeclarationFragments Fragments; 147281ad6265SDimitry Andric Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); 147381ad6265SDimitry Andric return Fragments; 147481ad6265SDimitry Andric } 1475