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" 155f757f3fSDimitry Andric #include "clang/AST/Decl.h" 165f757f3fSDimitry Andric #include "clang/AST/DeclCXX.h" 175f757f3fSDimitry Andric #include "clang/AST/QualTypeNames.h" 185f757f3fSDimitry Andric #include "clang/AST/Type.h" 195f757f3fSDimitry Andric #include "clang/AST/TypeLoc.h" 205f757f3fSDimitry 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" 245f757f3fSDimitry Andric #include <typeinfo> 2581ad6265SDimitry Andric 2681ad6265SDimitry Andric using namespace clang::extractapi; 2781ad6265SDimitry Andric using namespace llvm; 2881ad6265SDimitry Andric 295f757f3fSDimitry Andric namespace { 305f757f3fSDimitry Andric 315f757f3fSDimitry Andric void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo, 325f757f3fSDimitry Andric clang::FunctionTypeLoc &Block, 335f757f3fSDimitry Andric clang::FunctionProtoTypeLoc &BlockProto) { 345f757f3fSDimitry Andric if (!TSInfo) 355f757f3fSDimitry Andric return; 365f757f3fSDimitry Andric 375f757f3fSDimitry Andric clang::TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc(); 385f757f3fSDimitry Andric while (true) { 395f757f3fSDimitry Andric // Look through qualified types 405f757f3fSDimitry Andric if (auto QualifiedTL = TL.getAs<clang::QualifiedTypeLoc>()) { 415f757f3fSDimitry Andric TL = QualifiedTL.getUnqualifiedLoc(); 425f757f3fSDimitry Andric continue; 435f757f3fSDimitry Andric } 445f757f3fSDimitry Andric 455f757f3fSDimitry Andric if (auto AttrTL = TL.getAs<clang::AttributedTypeLoc>()) { 465f757f3fSDimitry Andric TL = AttrTL.getModifiedLoc(); 475f757f3fSDimitry Andric continue; 485f757f3fSDimitry Andric } 495f757f3fSDimitry Andric 505f757f3fSDimitry Andric // Try to get the function prototype behind the block pointer type, 515f757f3fSDimitry Andric // then we're done. 525f757f3fSDimitry Andric if (auto BlockPtr = TL.getAs<clang::BlockPointerTypeLoc>()) { 535f757f3fSDimitry Andric TL = BlockPtr.getPointeeLoc().IgnoreParens(); 545f757f3fSDimitry Andric Block = TL.getAs<clang::FunctionTypeLoc>(); 555f757f3fSDimitry Andric BlockProto = TL.getAs<clang::FunctionProtoTypeLoc>(); 565f757f3fSDimitry Andric } 575f757f3fSDimitry Andric break; 585f757f3fSDimitry Andric } 595f757f3fSDimitry Andric } 605f757f3fSDimitry Andric 615f757f3fSDimitry Andric } // namespace 625f757f3fSDimitry 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 1285f757f3fSDimitry Andric DeclarationFragments DeclarationFragments::getExceptionSpecificationString( 1295f757f3fSDimitry Andric ExceptionSpecificationType ExceptionSpec) { 1305f757f3fSDimitry Andric DeclarationFragments Fragments; 1315f757f3fSDimitry Andric switch (ExceptionSpec) { 1325f757f3fSDimitry Andric case ExceptionSpecificationType::EST_None: 1335f757f3fSDimitry Andric return Fragments; 1345f757f3fSDimitry Andric case ExceptionSpecificationType::EST_DynamicNone: 1355f757f3fSDimitry Andric return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) 1365f757f3fSDimitry Andric .append("throw", DeclarationFragments::FragmentKind::Keyword) 1375f757f3fSDimitry Andric .append("(", DeclarationFragments::FragmentKind::Text) 1385f757f3fSDimitry Andric .append(")", DeclarationFragments::FragmentKind::Text); 1395f757f3fSDimitry Andric case ExceptionSpecificationType::EST_Dynamic: 1405f757f3fSDimitry Andric // FIXME: throw(int), get types of inner expression 1415f757f3fSDimitry Andric return Fragments; 1425f757f3fSDimitry Andric case ExceptionSpecificationType::EST_BasicNoexcept: 1435f757f3fSDimitry Andric return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) 1445f757f3fSDimitry Andric .append("noexcept", DeclarationFragments::FragmentKind::Keyword); 1455f757f3fSDimitry Andric case ExceptionSpecificationType::EST_DependentNoexcept: 1465f757f3fSDimitry Andric // FIXME: throw(conditional-expression), get expression 1475f757f3fSDimitry Andric break; 1485f757f3fSDimitry Andric case ExceptionSpecificationType::EST_NoexceptFalse: 1495f757f3fSDimitry Andric return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) 1505f757f3fSDimitry Andric .append("noexcept", DeclarationFragments::FragmentKind::Keyword) 1515f757f3fSDimitry Andric .append("(", DeclarationFragments::FragmentKind::Text) 1525f757f3fSDimitry Andric .append("false", DeclarationFragments::FragmentKind::Keyword) 1535f757f3fSDimitry Andric .append(")", DeclarationFragments::FragmentKind::Text); 1545f757f3fSDimitry Andric case ExceptionSpecificationType::EST_NoexceptTrue: 1555f757f3fSDimitry Andric return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) 1565f757f3fSDimitry Andric .append("noexcept", DeclarationFragments::FragmentKind::Keyword) 1575f757f3fSDimitry Andric .append("(", DeclarationFragments::FragmentKind::Text) 1585f757f3fSDimitry Andric .append("true", DeclarationFragments::FragmentKind::Keyword) 1595f757f3fSDimitry Andric .append(")", DeclarationFragments::FragmentKind::Text); 1605f757f3fSDimitry Andric default: 1615f757f3fSDimitry Andric return Fragments; 1625f757f3fSDimitry Andric } 1635f757f3fSDimitry Andric 1645f757f3fSDimitry Andric llvm_unreachable("Unhandled exception specification"); 1655f757f3fSDimitry Andric } 1665f757f3fSDimitry Andric 1675f757f3fSDimitry Andric DeclarationFragments 1685f757f3fSDimitry Andric DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) { 1695f757f3fSDimitry Andric DeclarationFragments Fragments; 1705f757f3fSDimitry Andric if (Record->isStruct()) 1715f757f3fSDimitry Andric Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword); 1725f757f3fSDimitry Andric else if (Record->isUnion()) 1735f757f3fSDimitry Andric Fragments.append("union", DeclarationFragments::FragmentKind::Keyword); 1745f757f3fSDimitry Andric else 1755f757f3fSDimitry Andric Fragments.append("class", DeclarationFragments::FragmentKind::Keyword); 1765f757f3fSDimitry Andric 1775f757f3fSDimitry Andric return Fragments; 1785f757f3fSDimitry Andric } 1795f757f3fSDimitry 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 255*7a6dacacSDimitry Andric // An ElaboratedType is a sugar for types that are referred to using an 256*7a6dacacSDimitry Andric // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a 257*7a6dacacSDimitry Andric // qualified name, e.g., `N::M::type`, or both. 258*7a6dacacSDimitry Andric if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) { 259*7a6dacacSDimitry Andric ElaboratedTypeKeyword Keyword = ET->getKeyword(); 260*7a6dacacSDimitry Andric if (Keyword != ElaboratedTypeKeyword::None) { 261*7a6dacacSDimitry Andric Fragments 262*7a6dacacSDimitry Andric .append(ElaboratedType::getKeywordName(Keyword), 263*7a6dacacSDimitry Andric DeclarationFragments::FragmentKind::Keyword) 264*7a6dacacSDimitry Andric .appendSpace(); 265*7a6dacacSDimitry Andric } 266*7a6dacacSDimitry Andric 267*7a6dacacSDimitry Andric if (const NestedNameSpecifier *NNS = ET->getQualifier()) 268*7a6dacacSDimitry Andric Fragments.append(getFragmentsForNNS(NNS, Context, After)); 269*7a6dacacSDimitry Andric 270*7a6dacacSDimitry Andric // After handling the elaborated keyword or qualified name, build 271*7a6dacacSDimitry Andric // declaration fragments for the desugared underlying type. 272*7a6dacacSDimitry Andric return Fragments.append(getFragmentsForType(ET->desugar(), Context, After)); 273*7a6dacacSDimitry Andric } 274*7a6dacacSDimitry Andric 275*7a6dacacSDimitry Andric // If the type is a typedefed type, get the underlying TypedefNameDecl for a 276*7a6dacacSDimitry Andric // direct reference to the typedef instead of the wrapped type. 277*7a6dacacSDimitry Andric 278*7a6dacacSDimitry Andric // 'id' type is a typedef for an ObjCObjectPointerType 279*7a6dacacSDimitry Andric // we treat it as a typedef 280*7a6dacacSDimitry Andric if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) { 281*7a6dacacSDimitry Andric const TypedefNameDecl *Decl = TypedefTy->getDecl(); 282*7a6dacacSDimitry Andric TypedefUnderlyingTypeResolver TypedefResolver(Context); 283*7a6dacacSDimitry Andric std::string USR = TypedefResolver.getUSRForType(QualType(T, 0)); 284*7a6dacacSDimitry Andric 285*7a6dacacSDimitry Andric if (T->isObjCIdType()) { 286*7a6dacacSDimitry Andric return Fragments.append(Decl->getName(), 287*7a6dacacSDimitry Andric DeclarationFragments::FragmentKind::Keyword); 288*7a6dacacSDimitry Andric } 289*7a6dacacSDimitry Andric 290*7a6dacacSDimitry Andric return Fragments.append( 291*7a6dacacSDimitry Andric Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier, 292*7a6dacacSDimitry Andric USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0))); 293*7a6dacacSDimitry Andric } 294*7a6dacacSDimitry Andric 29581ad6265SDimitry Andric // Declaration fragments of a pointer type is the declaration fragments of 29606c3fb27SDimitry Andric // the pointee type followed by a `*`, 2975f757f3fSDimitry Andric if (T->isPointerType() && !T->isFunctionPointerType()) 29881ad6265SDimitry Andric return Fragments 29981ad6265SDimitry Andric .append(getFragmentsForType(T->getPointeeType(), Context, After)) 30081ad6265SDimitry Andric .append(" *", DeclarationFragments::FragmentKind::Text); 30106c3fb27SDimitry Andric 30206c3fb27SDimitry Andric // For Objective-C `id` and `Class` pointers 30306c3fb27SDimitry Andric // we do not spell out the `*`. 30406c3fb27SDimitry Andric if (T->isObjCObjectPointerType() && 30506c3fb27SDimitry Andric !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) { 30606c3fb27SDimitry Andric 30706c3fb27SDimitry Andric Fragments.append(getFragmentsForType(T->getPointeeType(), Context, After)); 30806c3fb27SDimitry Andric 30906c3fb27SDimitry Andric // id<protocol> is an qualified id type 31006c3fb27SDimitry Andric // id<protocol>* is not an qualified id type 31106c3fb27SDimitry Andric if (!T->getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) { 31206c3fb27SDimitry Andric Fragments.append(" *", DeclarationFragments::FragmentKind::Text); 31306c3fb27SDimitry Andric } 31406c3fb27SDimitry Andric 31506c3fb27SDimitry Andric return Fragments; 31681ad6265SDimitry Andric } 31781ad6265SDimitry Andric 31881ad6265SDimitry Andric // Declaration fragments of a lvalue reference type is the declaration 31981ad6265SDimitry Andric // fragments of the underlying type followed by a `&`. 32081ad6265SDimitry Andric if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T)) 32181ad6265SDimitry Andric return Fragments 32281ad6265SDimitry Andric .append( 32381ad6265SDimitry Andric getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After)) 32481ad6265SDimitry Andric .append(" &", DeclarationFragments::FragmentKind::Text); 32581ad6265SDimitry Andric 32681ad6265SDimitry Andric // Declaration fragments of a rvalue reference type is the declaration 32781ad6265SDimitry Andric // fragments of the underlying type followed by a `&&`. 32881ad6265SDimitry Andric if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T)) 32981ad6265SDimitry Andric return Fragments 33081ad6265SDimitry Andric .append( 33181ad6265SDimitry Andric getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After)) 33281ad6265SDimitry Andric .append(" &&", DeclarationFragments::FragmentKind::Text); 33381ad6265SDimitry Andric 33481ad6265SDimitry Andric // Declaration fragments of an array-typed variable have two parts: 33581ad6265SDimitry Andric // 1. the element type of the array that appears before the variable name; 33681ad6265SDimitry Andric // 2. array brackets `[(0-9)?]` that appear after the variable name. 33781ad6265SDimitry Andric if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) { 33881ad6265SDimitry Andric // Build the "after" part first because the inner element type might also 33981ad6265SDimitry Andric // be an array-type. For example `int matrix[3][4]` which has a type of 34081ad6265SDimitry Andric // "(array 3 of (array 4 of ints))." 34181ad6265SDimitry Andric // Push the array size part first to make sure they are in the right order. 34281ad6265SDimitry Andric After.append("[", DeclarationFragments::FragmentKind::Text); 34381ad6265SDimitry Andric 34481ad6265SDimitry Andric switch (AT->getSizeModifier()) { 3455f757f3fSDimitry Andric case ArraySizeModifier::Normal: 34681ad6265SDimitry Andric break; 3475f757f3fSDimitry Andric case ArraySizeModifier::Static: 34881ad6265SDimitry Andric Fragments.append("static", DeclarationFragments::FragmentKind::Keyword); 34981ad6265SDimitry Andric break; 3505f757f3fSDimitry Andric case ArraySizeModifier::Star: 35181ad6265SDimitry Andric Fragments.append("*", DeclarationFragments::FragmentKind::Text); 35281ad6265SDimitry Andric break; 35381ad6265SDimitry Andric } 35481ad6265SDimitry Andric 35581ad6265SDimitry Andric if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) { 35681ad6265SDimitry Andric // FIXME: right now this would evaluate any expressions/macros written in 35781ad6265SDimitry Andric // the original source to concrete values. For example 35881ad6265SDimitry Andric // `int nums[MAX]` -> `int nums[100]` 35981ad6265SDimitry Andric // `char *str[5 + 1]` -> `char *str[6]` 36081ad6265SDimitry Andric SmallString<128> Size; 36181ad6265SDimitry Andric CAT->getSize().toStringUnsigned(Size); 36281ad6265SDimitry Andric After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral); 36381ad6265SDimitry Andric } 36481ad6265SDimitry Andric 36581ad6265SDimitry Andric After.append("]", DeclarationFragments::FragmentKind::Text); 36681ad6265SDimitry Andric 36781ad6265SDimitry Andric return Fragments.append( 36881ad6265SDimitry Andric getFragmentsForType(AT->getElementType(), Context, After)); 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); 4365f757f3fSDimitry Andric if (QT.getAsString() == "_Bool") 4375f757f3fSDimitry Andric TypeFragments.replace("bool", 0); 4385f757f3fSDimitry 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 4655f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace( 4665f757f3fSDimitry Andric const NamespaceDecl *Decl) { 4675f757f3fSDimitry Andric DeclarationFragments Fragments; 4685f757f3fSDimitry Andric Fragments.append("namespace", DeclarationFragments::FragmentKind::Keyword); 4695f757f3fSDimitry Andric if (!Decl->isAnonymousNamespace()) 4705f757f3fSDimitry Andric Fragments.appendSpace().append( 4715f757f3fSDimitry Andric Decl->getName(), DeclarationFragments::FragmentKind::Identifier); 4725f757f3fSDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 4735f757f3fSDimitry Andric } 4745f757f3fSDimitry Andric 47581ad6265SDimitry Andric DeclarationFragments 47681ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) { 47781ad6265SDimitry Andric DeclarationFragments Fragments; 4785f757f3fSDimitry Andric if (Var->isConstexpr()) 4795f757f3fSDimitry Andric Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 4805f757f3fSDimitry Andric .appendSpace(); 4815f757f3fSDimitry 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; 4955f757f3fSDimitry Andric FunctionTypeLoc BlockLoc; 4965f757f3fSDimitry Andric FunctionProtoTypeLoc BlockProtoLoc; 4975f757f3fSDimitry Andric findTypeLocForBlockDecl(Var->getTypeSourceInfo(), BlockLoc, BlockProtoLoc); 4985f757f3fSDimitry Andric 4995f757f3fSDimitry Andric if (!BlockLoc) { 5005f757f3fSDimitry Andric QualType T = Var->getTypeSourceInfo() 5015f757f3fSDimitry Andric ? Var->getTypeSourceInfo()->getType() 5025f757f3fSDimitry Andric : Var->getASTContext().getUnqualifiedObjCPointerType( 5035f757f3fSDimitry Andric Var->getType()); 5045f757f3fSDimitry Andric 5055f757f3fSDimitry Andric Fragments.append(getFragmentsForType(T, Var->getASTContext(), After)) 5065f757f3fSDimitry Andric .appendSpace(); 5075f757f3fSDimitry Andric } else { 5085f757f3fSDimitry Andric Fragments.append(getFragmentsForBlock(Var, BlockLoc, BlockProtoLoc, After)); 5095f757f3fSDimitry Andric } 5105f757f3fSDimitry Andric 5115f757f3fSDimitry Andric return Fragments 5125f757f3fSDimitry Andric .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) 5135f757f3fSDimitry Andric .append(std::move(After)) 5145f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text); 5155f757f3fSDimitry Andric } 5165f757f3fSDimitry Andric 5175f757f3fSDimitry Andric DeclarationFragments 5185f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) { 5195f757f3fSDimitry Andric DeclarationFragments Fragments; 5205f757f3fSDimitry Andric if (Var->isConstexpr()) 5215f757f3fSDimitry Andric Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 5225f757f3fSDimitry Andric .appendSpace(); 5235f757f3fSDimitry Andric QualType T = 5245f757f3fSDimitry Andric Var->getTypeSourceInfo() 5255f757f3fSDimitry Andric ? Var->getTypeSourceInfo()->getType() 5265f757f3fSDimitry Andric : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType()); 5275f757f3fSDimitry Andric 5285f757f3fSDimitry Andric // Might be a member, so might be static. 5295f757f3fSDimitry Andric if (Var->isStaticDataMember()) 5305f757f3fSDimitry Andric Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) 5315f757f3fSDimitry Andric .appendSpace(); 5325f757f3fSDimitry Andric 5335f757f3fSDimitry Andric DeclarationFragments After; 5345f757f3fSDimitry Andric DeclarationFragments ArgumentFragment = 5355f757f3fSDimitry Andric getFragmentsForType(T, Var->getASTContext(), After); 5365f757f3fSDimitry Andric if (ArgumentFragment.begin()->Spelling.substr(0, 14).compare( 5375f757f3fSDimitry Andric "type-parameter") == 0) { 5385f757f3fSDimitry Andric std::string ProperArgName = getNameForTemplateArgument( 5395f757f3fSDimitry Andric Var->getDescribedVarTemplate()->getTemplateParameters()->asArray(), 5405f757f3fSDimitry Andric ArgumentFragment.begin()->Spelling); 5415f757f3fSDimitry Andric ArgumentFragment.begin()->Spelling.swap(ProperArgName); 5425f757f3fSDimitry Andric } 5435f757f3fSDimitry Andric Fragments.append(std::move(ArgumentFragment)) 54481ad6265SDimitry Andric .appendSpace() 54581ad6265SDimitry Andric .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) 5465f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text); 5475f757f3fSDimitry Andric return Fragments; 54881ad6265SDimitry Andric } 54981ad6265SDimitry Andric 55081ad6265SDimitry Andric DeclarationFragments 55181ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) { 55281ad6265SDimitry Andric DeclarationFragments Fragments, After; 55381ad6265SDimitry Andric 5545f757f3fSDimitry Andric auto *TSInfo = Param->getTypeSourceInfo(); 5555f757f3fSDimitry Andric 5565f757f3fSDimitry Andric QualType T = TSInfo ? TSInfo->getType() 55781ad6265SDimitry Andric : Param->getASTContext().getUnqualifiedObjCPointerType( 55881ad6265SDimitry Andric Param->getType()); 55981ad6265SDimitry Andric 5605f757f3fSDimitry Andric FunctionTypeLoc BlockLoc; 5615f757f3fSDimitry Andric FunctionProtoTypeLoc BlockProtoLoc; 5625f757f3fSDimitry Andric findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc); 56381ad6265SDimitry Andric 5645f757f3fSDimitry Andric DeclarationFragments TypeFragments; 5655f757f3fSDimitry Andric if (BlockLoc) 5665f757f3fSDimitry Andric TypeFragments.append( 5675f757f3fSDimitry Andric getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After)); 5685f757f3fSDimitry Andric else 5695f757f3fSDimitry Andric TypeFragments.append(getFragmentsForType(T, Param->getASTContext(), After)); 5705f757f3fSDimitry Andric 5715f757f3fSDimitry Andric if (TypeFragments.begin()->Spelling.substr(0, 14).compare("type-parameter") == 5725f757f3fSDimitry Andric 0) { 5735f757f3fSDimitry Andric std::string ProperArgName = getNameForTemplateArgument( 5745f757f3fSDimitry Andric dyn_cast<FunctionDecl>(Param->getDeclContext()) 5755f757f3fSDimitry Andric ->getDescribedFunctionTemplate() 5765f757f3fSDimitry Andric ->getTemplateParameters() 5775f757f3fSDimitry Andric ->asArray(), 5785f757f3fSDimitry Andric TypeFragments.begin()->Spelling); 5795f757f3fSDimitry Andric TypeFragments.begin()->Spelling.swap(ProperArgName); 5805f757f3fSDimitry Andric } 5815f757f3fSDimitry Andric 5825f757f3fSDimitry Andric if (Param->isObjCMethodParameter()) { 58381ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text) 58481ad6265SDimitry Andric .append(std::move(TypeFragments)) 5855f757f3fSDimitry Andric .append(std::move(After)) 5865f757f3fSDimitry Andric .append(") ", DeclarationFragments::FragmentKind::Text) 5875f757f3fSDimitry Andric .append(Param->getName(), 5885f757f3fSDimitry Andric DeclarationFragments::FragmentKind::InternalParam); 5895f757f3fSDimitry Andric } else { 5905f757f3fSDimitry Andric Fragments.append(std::move(TypeFragments)); 5915f757f3fSDimitry Andric if (!T->isBlockPointerType()) 5925f757f3fSDimitry Andric Fragments.appendSpace(); 5935f757f3fSDimitry Andric Fragments 59481ad6265SDimitry Andric .append(Param->getName(), 59581ad6265SDimitry Andric DeclarationFragments::FragmentKind::InternalParam) 59681ad6265SDimitry Andric .append(std::move(After)); 59781ad6265SDimitry Andric } 5985f757f3fSDimitry Andric return Fragments; 5995f757f3fSDimitry Andric } 6005f757f3fSDimitry Andric 6015f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForBlock( 6025f757f3fSDimitry Andric const NamedDecl *BlockDecl, FunctionTypeLoc &Block, 6035f757f3fSDimitry Andric FunctionProtoTypeLoc &BlockProto, DeclarationFragments &After) { 6045f757f3fSDimitry Andric DeclarationFragments Fragments; 6055f757f3fSDimitry Andric 6065f757f3fSDimitry Andric DeclarationFragments RetTyAfter; 6075f757f3fSDimitry Andric auto ReturnValueFragment = getFragmentsForType( 6085f757f3fSDimitry Andric Block.getTypePtr()->getReturnType(), BlockDecl->getASTContext(), After); 6095f757f3fSDimitry Andric 6105f757f3fSDimitry Andric Fragments.append(std::move(ReturnValueFragment)) 6115f757f3fSDimitry Andric .append(std::move(RetTyAfter)) 6125f757f3fSDimitry Andric .appendSpace() 6135f757f3fSDimitry Andric .append("(^", DeclarationFragments::FragmentKind::Text); 6145f757f3fSDimitry Andric 6155f757f3fSDimitry Andric After.append(")", DeclarationFragments::FragmentKind::Text); 6165f757f3fSDimitry Andric unsigned NumParams = Block.getNumParams(); 6175f757f3fSDimitry Andric 6185f757f3fSDimitry Andric if (!BlockProto || NumParams == 0) { 6195f757f3fSDimitry Andric if (BlockProto && BlockProto.getTypePtr()->isVariadic()) 6205f757f3fSDimitry Andric After.append("(...)", DeclarationFragments::FragmentKind::Text); 6215f757f3fSDimitry Andric else 6225f757f3fSDimitry Andric After.append("()", DeclarationFragments::FragmentKind::Text); 6235f757f3fSDimitry Andric } else { 6245f757f3fSDimitry Andric After.append("(", DeclarationFragments::FragmentKind::Text); 6255f757f3fSDimitry Andric for (unsigned I = 0; I != NumParams; ++I) { 6265f757f3fSDimitry Andric if (I) 6275f757f3fSDimitry Andric After.append(", ", DeclarationFragments::FragmentKind::Text); 6285f757f3fSDimitry Andric After.append(getFragmentsForParam(Block.getParam(I))); 6295f757f3fSDimitry Andric if (I == NumParams - 1 && BlockProto.getTypePtr()->isVariadic()) 6305f757f3fSDimitry Andric After.append(", ...", DeclarationFragments::FragmentKind::Text); 6315f757f3fSDimitry Andric } 6325f757f3fSDimitry Andric After.append(")", DeclarationFragments::FragmentKind::Text); 6335f757f3fSDimitry Andric } 6345f757f3fSDimitry Andric 6355f757f3fSDimitry Andric return Fragments; 6365f757f3fSDimitry 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 } 6585f757f3fSDimitry Andric if (Func->isConsteval()) // if consteval, it is also constexpr 6595f757f3fSDimitry Andric Fragments.append("consteval", DeclarationFragments::FragmentKind::Keyword) 6605f757f3fSDimitry Andric .appendSpace(); 6615f757f3fSDimitry Andric else if (Func->isConstexpr()) 6625f757f3fSDimitry Andric Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 6635f757f3fSDimitry Andric .appendSpace(); 66481ad6265SDimitry Andric 66581ad6265SDimitry Andric // FIXME: Is `after` actually needed here? 66681ad6265SDimitry Andric DeclarationFragments After; 6675f757f3fSDimitry Andric auto ReturnValueFragment = 6685f757f3fSDimitry Andric getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After); 6695f757f3fSDimitry Andric if (ReturnValueFragment.begin()->Spelling.substr(0, 14).compare( 6705f757f3fSDimitry Andric "type-parameter") == 0) { 6715f757f3fSDimitry Andric std::string ProperArgName = 6725f757f3fSDimitry Andric getNameForTemplateArgument(Func->getDescribedFunctionTemplate() 6735f757f3fSDimitry Andric ->getTemplateParameters() 6745f757f3fSDimitry Andric ->asArray(), 6755f757f3fSDimitry Andric ReturnValueFragment.begin()->Spelling); 6765f757f3fSDimitry Andric ReturnValueFragment.begin()->Spelling.swap(ProperArgName); 6775f757f3fSDimitry Andric } 6785f757f3fSDimitry Andric 6795f757f3fSDimitry Andric Fragments.append(std::move(ReturnValueFragment)) 68081ad6265SDimitry Andric .appendSpace() 6815f757f3fSDimitry Andric .append(Func->getName(), DeclarationFragments::FragmentKind::Identifier); 6825f757f3fSDimitry Andric 6835f757f3fSDimitry Andric if (Func->getTemplateSpecializationInfo()) { 6845f757f3fSDimitry Andric Fragments.append("<", DeclarationFragments::FragmentKind::Text); 6855f757f3fSDimitry Andric 6865f757f3fSDimitry Andric for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) { 6875f757f3fSDimitry Andric if (i) 6885f757f3fSDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 6895f757f3fSDimitry Andric Fragments.append( 6905f757f3fSDimitry Andric getFragmentsForType(Func->getParamDecl(i)->getType(), 6915f757f3fSDimitry Andric Func->getParamDecl(i)->getASTContext(), After)); 6925f757f3fSDimitry Andric } 6935f757f3fSDimitry Andric Fragments.append(">", DeclarationFragments::FragmentKind::Text); 6945f757f3fSDimitry Andric } 6955f757f3fSDimitry Andric Fragments.append(std::move(After)); 69681ad6265SDimitry Andric 69781ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text); 6985f757f3fSDimitry Andric unsigned NumParams = Func->getNumParams(); 6995f757f3fSDimitry 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 } 7045f757f3fSDimitry Andric 7055f757f3fSDimitry Andric if (Func->isVariadic()) { 7065f757f3fSDimitry Andric if (NumParams > 0) 7075f757f3fSDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 7085f757f3fSDimitry Andric Fragments.append("...", DeclarationFragments::FragmentKind::Text); 7095f757f3fSDimitry Andric } 71081ad6265SDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 71181ad6265SDimitry Andric 7125f757f3fSDimitry Andric Fragments.append(DeclarationFragments::getExceptionSpecificationString( 7135f757f3fSDimitry Andric Func->getExceptionSpecType())); 7145f757f3fSDimitry 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; 7505f757f3fSDimitry Andric DeclarationFragments Fragments; 7515f757f3fSDimitry Andric if (Field->isMutable()) 7525f757f3fSDimitry Andric Fragments.append("mutable", DeclarationFragments::FragmentKind::Keyword) 7535f757f3fSDimitry Andric .appendSpace(); 7545f757f3fSDimitry Andric return Fragments 7555f757f3fSDimitry Andric .append( 7565f757f3fSDimitry Andric getFragmentsForType(Field->getType(), Field->getASTContext(), After)) 75781ad6265SDimitry Andric .appendSpace() 75881ad6265SDimitry Andric .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier) 7595f757f3fSDimitry Andric .append(std::move(After)) 7605f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text); 76181ad6265SDimitry Andric } 76281ad6265SDimitry Andric 763*7a6dacacSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl( 764*7a6dacacSDimitry Andric const RecordDecl *Record) { 76581ad6265SDimitry Andric if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl()) 76681ad6265SDimitry Andric return getFragmentsForTypedef(TypedefNameDecl); 76781ad6265SDimitry Andric 76881ad6265SDimitry Andric DeclarationFragments Fragments; 769*7a6dacacSDimitry Andric if (Record->isUnion()) 770*7a6dacacSDimitry Andric Fragments.append("union", DeclarationFragments::FragmentKind::Keyword); 771*7a6dacacSDimitry Andric else 77281ad6265SDimitry Andric Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword); 77381ad6265SDimitry Andric 77481ad6265SDimitry Andric if (!Record->getName().empty()) 77581ad6265SDimitry Andric Fragments.appendSpace().append( 77681ad6265SDimitry Andric Record->getName(), DeclarationFragments::FragmentKind::Identifier); 77706c3fb27SDimitry Andric 77806c3fb27SDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 77981ad6265SDimitry Andric } 78081ad6265SDimitry Andric 7815f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass( 7825f757f3fSDimitry Andric const CXXRecordDecl *Record) { 7835f757f3fSDimitry Andric if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl()) 7845f757f3fSDimitry Andric return getFragmentsForTypedef(TypedefNameDecl); 7855f757f3fSDimitry Andric 7865f757f3fSDimitry Andric DeclarationFragments Fragments; 7875f757f3fSDimitry Andric Fragments.append(DeclarationFragments::getStructureTypeFragment(Record)); 7885f757f3fSDimitry Andric 7895f757f3fSDimitry Andric if (!Record->getName().empty()) 7905f757f3fSDimitry Andric Fragments.appendSpace().append( 7915f757f3fSDimitry Andric Record->getName(), DeclarationFragments::FragmentKind::Identifier); 7925f757f3fSDimitry Andric 7935f757f3fSDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 7945f757f3fSDimitry Andric } 7955f757f3fSDimitry Andric 7965f757f3fSDimitry Andric DeclarationFragments 7975f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod( 7985f757f3fSDimitry Andric const CXXMethodDecl *Method) { 7995f757f3fSDimitry Andric DeclarationFragments Fragments; 8005f757f3fSDimitry Andric std::string Name; 8015f757f3fSDimitry Andric if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(Method)) { 8025f757f3fSDimitry Andric Name = Method->getNameAsString(); 8035f757f3fSDimitry Andric if (Constructor->isExplicit()) 8045f757f3fSDimitry Andric Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword) 8055f757f3fSDimitry Andric .appendSpace(); 8065f757f3fSDimitry Andric } else if (isa<CXXDestructorDecl>(Method)) 8075f757f3fSDimitry Andric Name = Method->getNameAsString(); 8085f757f3fSDimitry Andric 8095f757f3fSDimitry Andric DeclarationFragments After; 8105f757f3fSDimitry Andric Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier) 8115f757f3fSDimitry Andric .append(std::move(After)); 8125f757f3fSDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text); 8135f757f3fSDimitry Andric for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) { 8145f757f3fSDimitry Andric if (i) 8155f757f3fSDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 8165f757f3fSDimitry Andric Fragments.append(getFragmentsForParam(Method->getParamDecl(i))); 8175f757f3fSDimitry Andric } 8185f757f3fSDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 8195f757f3fSDimitry Andric 8205f757f3fSDimitry Andric Fragments.append(DeclarationFragments::getExceptionSpecificationString( 8215f757f3fSDimitry Andric Method->getExceptionSpecType())); 8225f757f3fSDimitry Andric 8235f757f3fSDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 8245f757f3fSDimitry Andric } 8255f757f3fSDimitry Andric 8265f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod( 8275f757f3fSDimitry Andric const CXXMethodDecl *Method) { 8285f757f3fSDimitry Andric DeclarationFragments Fragments; 8295f757f3fSDimitry Andric StringRef Name = Method->getName(); 8305f757f3fSDimitry Andric if (Method->isStatic()) 8315f757f3fSDimitry Andric Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) 8325f757f3fSDimitry Andric .appendSpace(); 8335f757f3fSDimitry Andric if (Method->isConstexpr()) 8345f757f3fSDimitry Andric Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 8355f757f3fSDimitry Andric .appendSpace(); 8365f757f3fSDimitry Andric if (Method->isVolatile()) 8375f757f3fSDimitry Andric Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword) 8385f757f3fSDimitry Andric .appendSpace(); 8395f757f3fSDimitry Andric 8405f757f3fSDimitry Andric // Build return type 8415f757f3fSDimitry Andric DeclarationFragments After; 8425f757f3fSDimitry Andric Fragments 8435f757f3fSDimitry Andric .append(getFragmentsForType(Method->getReturnType(), 8445f757f3fSDimitry Andric Method->getASTContext(), After)) 8455f757f3fSDimitry Andric .appendSpace() 8465f757f3fSDimitry Andric .append(Name, DeclarationFragments::FragmentKind::Identifier) 8475f757f3fSDimitry Andric .append(std::move(After)); 8485f757f3fSDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text); 8495f757f3fSDimitry Andric for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) { 8505f757f3fSDimitry Andric if (i) 8515f757f3fSDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 8525f757f3fSDimitry Andric Fragments.append(getFragmentsForParam(Method->getParamDecl(i))); 8535f757f3fSDimitry Andric } 8545f757f3fSDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 8555f757f3fSDimitry Andric 8565f757f3fSDimitry Andric if (Method->isConst()) 8575f757f3fSDimitry Andric Fragments.appendSpace().append("const", 8585f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Keyword); 8595f757f3fSDimitry Andric 8605f757f3fSDimitry Andric Fragments.append(DeclarationFragments::getExceptionSpecificationString( 8615f757f3fSDimitry Andric Method->getExceptionSpecType())); 8625f757f3fSDimitry Andric 8635f757f3fSDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 8645f757f3fSDimitry Andric } 8655f757f3fSDimitry Andric 8665f757f3fSDimitry Andric DeclarationFragments 8675f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForConversionFunction( 8685f757f3fSDimitry Andric const CXXConversionDecl *ConversionFunction) { 8695f757f3fSDimitry Andric DeclarationFragments Fragments; 8705f757f3fSDimitry Andric 8715f757f3fSDimitry Andric if (ConversionFunction->isExplicit()) 8725f757f3fSDimitry Andric Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword) 8735f757f3fSDimitry Andric .appendSpace(); 8745f757f3fSDimitry Andric 8755f757f3fSDimitry Andric Fragments.append("operator", DeclarationFragments::FragmentKind::Keyword) 8765f757f3fSDimitry Andric .appendSpace(); 8775f757f3fSDimitry Andric 8785f757f3fSDimitry Andric Fragments 8795f757f3fSDimitry Andric .append(ConversionFunction->getConversionType().getAsString(), 8805f757f3fSDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier) 8815f757f3fSDimitry Andric .append("(", DeclarationFragments::FragmentKind::Text); 8825f757f3fSDimitry Andric for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end; 8835f757f3fSDimitry Andric ++i) { 8845f757f3fSDimitry Andric if (i) 8855f757f3fSDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 8865f757f3fSDimitry Andric Fragments.append(getFragmentsForParam(ConversionFunction->getParamDecl(i))); 8875f757f3fSDimitry Andric } 8885f757f3fSDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 8895f757f3fSDimitry Andric 8905f757f3fSDimitry Andric if (ConversionFunction->isConst()) 8915f757f3fSDimitry Andric Fragments.appendSpace().append("const", 8925f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Keyword); 8935f757f3fSDimitry Andric 8945f757f3fSDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 8955f757f3fSDimitry Andric } 8965f757f3fSDimitry Andric 8975f757f3fSDimitry Andric DeclarationFragments 8985f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator( 8995f757f3fSDimitry Andric const CXXMethodDecl *Method) { 9005f757f3fSDimitry Andric DeclarationFragments Fragments; 9015f757f3fSDimitry Andric 9025f757f3fSDimitry Andric // Build return type 9035f757f3fSDimitry Andric DeclarationFragments After; 9045f757f3fSDimitry Andric Fragments 9055f757f3fSDimitry Andric .append(getFragmentsForType(Method->getReturnType(), 9065f757f3fSDimitry Andric Method->getASTContext(), After)) 9075f757f3fSDimitry Andric .appendSpace() 9085f757f3fSDimitry Andric .append(Method->getNameAsString(), 9095f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Identifier) 9105f757f3fSDimitry Andric .append(std::move(After)); 9115f757f3fSDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text); 9125f757f3fSDimitry Andric for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) { 9135f757f3fSDimitry Andric if (i) 9145f757f3fSDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 9155f757f3fSDimitry Andric Fragments.append(getFragmentsForParam(Method->getParamDecl(i))); 9165f757f3fSDimitry Andric } 9175f757f3fSDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 9185f757f3fSDimitry Andric 9195f757f3fSDimitry Andric if (Method->isConst()) 9205f757f3fSDimitry Andric Fragments.appendSpace().append("const", 9215f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Keyword); 9225f757f3fSDimitry Andric 9235f757f3fSDimitry Andric Fragments.append(DeclarationFragments::getExceptionSpecificationString( 9245f757f3fSDimitry Andric Method->getExceptionSpecType())); 9255f757f3fSDimitry Andric 9265f757f3fSDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 9275f757f3fSDimitry Andric } 9285f757f3fSDimitry Andric 9295f757f3fSDimitry Andric // Get fragments for template parameters, e.g. T in tempalte<typename T> ... 9305f757f3fSDimitry Andric DeclarationFragments 9315f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForTemplateParameters( 9325f757f3fSDimitry Andric ArrayRef<NamedDecl *> ParameterArray) { 9335f757f3fSDimitry Andric DeclarationFragments Fragments; 9345f757f3fSDimitry Andric for (unsigned i = 0, end = ParameterArray.size(); i != end; ++i) { 9355f757f3fSDimitry Andric if (i) 9365f757f3fSDimitry Andric Fragments.append(",", DeclarationFragments::FragmentKind::Text) 9375f757f3fSDimitry Andric .appendSpace(); 9385f757f3fSDimitry Andric 9395f757f3fSDimitry Andric const auto *TemplateParam = 9405f757f3fSDimitry Andric dyn_cast<TemplateTypeParmDecl>(ParameterArray[i]); 9415f757f3fSDimitry Andric if (!TemplateParam) 9425f757f3fSDimitry Andric continue; 9435f757f3fSDimitry Andric if (TemplateParam->hasTypeConstraint()) 9445f757f3fSDimitry Andric Fragments.append(TemplateParam->getTypeConstraint() 9455f757f3fSDimitry Andric ->getNamedConcept() 9465f757f3fSDimitry Andric ->getName() 9475f757f3fSDimitry Andric .str(), 9485f757f3fSDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier); 9495f757f3fSDimitry Andric else if (TemplateParam->wasDeclaredWithTypename()) 9505f757f3fSDimitry Andric Fragments.append("typename", DeclarationFragments::FragmentKind::Keyword); 9515f757f3fSDimitry Andric else 9525f757f3fSDimitry Andric Fragments.append("class", DeclarationFragments::FragmentKind::Keyword); 9535f757f3fSDimitry Andric 9545f757f3fSDimitry Andric if (TemplateParam->isParameterPack()) 9555f757f3fSDimitry Andric Fragments.append("...", DeclarationFragments::FragmentKind::Text); 9565f757f3fSDimitry Andric 9575f757f3fSDimitry Andric Fragments.appendSpace().append( 9585f757f3fSDimitry Andric TemplateParam->getName(), 9595f757f3fSDimitry Andric DeclarationFragments::FragmentKind::GenericParameter); 9605f757f3fSDimitry Andric } 9615f757f3fSDimitry Andric return Fragments; 9625f757f3fSDimitry Andric } 9635f757f3fSDimitry Andric 9645f757f3fSDimitry Andric // Find the name of a template argument from the template's parameters. 9655f757f3fSDimitry Andric std::string DeclarationFragmentsBuilder::getNameForTemplateArgument( 9665f757f3fSDimitry Andric const ArrayRef<NamedDecl *> TemplateParameters, std::string TypeParameter) { 9675f757f3fSDimitry Andric // The arg is a generic parameter from a partial spec, e.g. 9685f757f3fSDimitry Andric // T in template<typename T> Foo<T, int>. 9695f757f3fSDimitry Andric // 9705f757f3fSDimitry Andric // Those names appear as "type-parameter-<index>-<depth>", so we must find its 9715f757f3fSDimitry Andric // name from the template's parameter list. 9725f757f3fSDimitry Andric for (unsigned i = 0; i < TemplateParameters.size(); ++i) { 9735f757f3fSDimitry Andric const auto *Parameter = 9745f757f3fSDimitry Andric dyn_cast<TemplateTypeParmDecl>(TemplateParameters[i]); 9755f757f3fSDimitry Andric if (TypeParameter.compare("type-parameter-" + 9765f757f3fSDimitry Andric std::to_string(Parameter->getDepth()) + "-" + 9775f757f3fSDimitry Andric std::to_string(Parameter->getIndex())) == 0) 9785f757f3fSDimitry Andric return std::string(TemplateParameters[i]->getName()); 9795f757f3fSDimitry Andric } 9805f757f3fSDimitry Andric llvm_unreachable("Could not find the name of a template argument."); 9815f757f3fSDimitry Andric } 9825f757f3fSDimitry Andric 9835f757f3fSDimitry Andric // Get fragments for template arguments, e.g. int in template<typename T> 9845f757f3fSDimitry Andric // Foo<int>; 9855f757f3fSDimitry Andric // 9865f757f3fSDimitry Andric // Note: TemplateParameters is only necessary if the Decl is a 9875f757f3fSDimitry Andric // PartialSpecialization, where we need the parameters to deduce the name of the 9885f757f3fSDimitry Andric // generic arguments. 9895f757f3fSDimitry Andric DeclarationFragments 9905f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForTemplateArguments( 9915f757f3fSDimitry Andric const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context, 9925f757f3fSDimitry Andric const std::optional<ArrayRef<NamedDecl *>> TemplateParameters) { 9935f757f3fSDimitry Andric DeclarationFragments Fragments; 9945f757f3fSDimitry Andric for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) { 9955f757f3fSDimitry Andric if (i) 9965f757f3fSDimitry Andric Fragments.append(",", DeclarationFragments::FragmentKind::Text) 9975f757f3fSDimitry Andric .appendSpace(); 9985f757f3fSDimitry Andric 9995f757f3fSDimitry Andric std::string Type = TemplateArguments[i].getAsType().getAsString(); 10005f757f3fSDimitry Andric DeclarationFragments After; 10015f757f3fSDimitry Andric DeclarationFragments ArgumentFragment = 10025f757f3fSDimitry Andric getFragmentsForType(TemplateArguments[i].getAsType(), Context, After); 10035f757f3fSDimitry Andric 10045f757f3fSDimitry Andric if (ArgumentFragment.begin()->Spelling.substr(0, 14).compare( 10055f757f3fSDimitry Andric "type-parameter") == 0) { 10065f757f3fSDimitry Andric std::string ProperArgName = getNameForTemplateArgument( 10075f757f3fSDimitry Andric TemplateParameters.value(), ArgumentFragment.begin()->Spelling); 10085f757f3fSDimitry Andric ArgumentFragment.begin()->Spelling.swap(ProperArgName); 10095f757f3fSDimitry Andric } 10105f757f3fSDimitry Andric Fragments.append(std::move(ArgumentFragment)); 10115f757f3fSDimitry Andric 10125f757f3fSDimitry Andric if (TemplateArguments[i].isPackExpansion()) 10135f757f3fSDimitry Andric Fragments.append("...", DeclarationFragments::FragmentKind::Text); 10145f757f3fSDimitry Andric } 10155f757f3fSDimitry Andric return Fragments; 10165f757f3fSDimitry Andric } 10175f757f3fSDimitry Andric 10185f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept( 10195f757f3fSDimitry Andric const ConceptDecl *Concept) { 10205f757f3fSDimitry Andric DeclarationFragments Fragments; 10215f757f3fSDimitry Andric return Fragments 10225f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword) 10235f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 10245f757f3fSDimitry Andric .append(getFragmentsForTemplateParameters( 10255f757f3fSDimitry Andric Concept->getTemplateParameters()->asArray())) 10265f757f3fSDimitry Andric .append("> ", DeclarationFragments::FragmentKind::Text) 10275f757f3fSDimitry Andric .append("concept", DeclarationFragments::FragmentKind::Keyword) 10285f757f3fSDimitry Andric .appendSpace() 10295f757f3fSDimitry Andric .append(Concept->getName().str(), 10305f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Identifier) 10315f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text); 10325f757f3fSDimitry Andric } 10335f757f3fSDimitry Andric 10345f757f3fSDimitry Andric DeclarationFragments 10355f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate( 10365f757f3fSDimitry Andric const RedeclarableTemplateDecl *RedeclarableTemplate) { 10375f757f3fSDimitry Andric DeclarationFragments Fragments; 10385f757f3fSDimitry Andric Fragments.append("template", DeclarationFragments::FragmentKind::Keyword) 10395f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 10405f757f3fSDimitry Andric .append(getFragmentsForTemplateParameters( 10415f757f3fSDimitry Andric RedeclarableTemplate->getTemplateParameters()->asArray())) 10425f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 10435f757f3fSDimitry Andric .appendSpace(); 10445f757f3fSDimitry Andric 10455f757f3fSDimitry Andric if (isa<TypeAliasTemplateDecl>(RedeclarableTemplate)) 10465f757f3fSDimitry Andric Fragments.appendSpace() 10475f757f3fSDimitry Andric .append("using", DeclarationFragments::FragmentKind::Keyword) 10485f757f3fSDimitry Andric .appendSpace() 10495f757f3fSDimitry Andric .append(RedeclarableTemplate->getName(), 10505f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Identifier); 10515f757f3fSDimitry Andric // the templated records will be resposbible for injecting their templates 10525f757f3fSDimitry Andric return Fragments.appendSpace(); 10535f757f3fSDimitry Andric } 10545f757f3fSDimitry Andric 10555f757f3fSDimitry Andric DeclarationFragments 10565f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization( 10575f757f3fSDimitry Andric const ClassTemplateSpecializationDecl *Decl) { 10585f757f3fSDimitry Andric DeclarationFragments Fragments; 10595f757f3fSDimitry Andric return Fragments 10605f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword) 10615f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 10625f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 10635f757f3fSDimitry Andric .appendSpace() 10645f757f3fSDimitry Andric .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass( 10655f757f3fSDimitry Andric cast<CXXRecordDecl>(Decl))) 10665f757f3fSDimitry Andric .pop_back() // there is an extra semicolon now 10675f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 10685f757f3fSDimitry Andric .append( 10695f757f3fSDimitry Andric getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(), 10705f757f3fSDimitry Andric Decl->getASTContext(), std::nullopt)) 10715f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 10725f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text); 10735f757f3fSDimitry Andric } 10745f757f3fSDimitry Andric 10755f757f3fSDimitry Andric DeclarationFragments 10765f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization( 10775f757f3fSDimitry Andric const ClassTemplatePartialSpecializationDecl *Decl) { 10785f757f3fSDimitry Andric DeclarationFragments Fragments; 10795f757f3fSDimitry Andric return Fragments 10805f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword) 10815f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 10825f757f3fSDimitry Andric .append(getFragmentsForTemplateParameters( 10835f757f3fSDimitry Andric Decl->getTemplateParameters()->asArray())) 10845f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 10855f757f3fSDimitry Andric .appendSpace() 10865f757f3fSDimitry Andric .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass( 10875f757f3fSDimitry Andric cast<CXXRecordDecl>(Decl))) 10885f757f3fSDimitry Andric .pop_back() // there is an extra semicolon now 10895f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 10905f757f3fSDimitry Andric .append(getFragmentsForTemplateArguments( 10915f757f3fSDimitry Andric Decl->getTemplateArgs().asArray(), Decl->getASTContext(), 10925f757f3fSDimitry Andric Decl->getTemplateParameters()->asArray())) 10935f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 10945f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text); 10955f757f3fSDimitry Andric } 10965f757f3fSDimitry Andric 10975f757f3fSDimitry Andric DeclarationFragments 10985f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization( 10995f757f3fSDimitry Andric const VarTemplateSpecializationDecl *Decl) { 11005f757f3fSDimitry Andric DeclarationFragments Fragments; 11015f757f3fSDimitry Andric return Fragments 11025f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword) 11035f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 11045f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 11055f757f3fSDimitry Andric .appendSpace() 11065f757f3fSDimitry Andric .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl)) 11075f757f3fSDimitry Andric .pop_back() // there is an extra semicolon now 11085f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 11095f757f3fSDimitry Andric .append( 11105f757f3fSDimitry Andric getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(), 11115f757f3fSDimitry Andric Decl->getASTContext(), std::nullopt)) 11125f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 11135f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text); 11145f757f3fSDimitry Andric } 11155f757f3fSDimitry Andric 11165f757f3fSDimitry Andric DeclarationFragments 11175f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization( 11185f757f3fSDimitry Andric const VarTemplatePartialSpecializationDecl *Decl) { 11195f757f3fSDimitry Andric DeclarationFragments Fragments; 11205f757f3fSDimitry Andric return Fragments 11215f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword) 11225f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 11235f757f3fSDimitry Andric // Partial specs may have new params. 11245f757f3fSDimitry Andric .append(getFragmentsForTemplateParameters( 11255f757f3fSDimitry Andric Decl->getTemplateParameters()->asArray())) 11265f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 11275f757f3fSDimitry Andric .appendSpace() 11285f757f3fSDimitry Andric .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl)) 11295f757f3fSDimitry Andric .pop_back() // there is an extra semicolon now 11305f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 11315f757f3fSDimitry Andric .append(getFragmentsForTemplateArguments( 11325f757f3fSDimitry Andric Decl->getTemplateArgs().asArray(), Decl->getASTContext(), 11335f757f3fSDimitry Andric Decl->getTemplateParameters()->asArray())) 11345f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 11355f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text); 11365f757f3fSDimitry Andric } 11375f757f3fSDimitry Andric 11385f757f3fSDimitry Andric DeclarationFragments 11395f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate( 11405f757f3fSDimitry Andric const FunctionTemplateDecl *Decl) { 11415f757f3fSDimitry Andric DeclarationFragments Fragments; 11425f757f3fSDimitry Andric return Fragments 11435f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword) 11445f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text) 11455f757f3fSDimitry Andric // Partial specs may have new params. 11465f757f3fSDimitry Andric .append(getFragmentsForTemplateParameters( 11475f757f3fSDimitry Andric Decl->getTemplateParameters()->asArray())) 11485f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text) 11495f757f3fSDimitry Andric .appendSpace() 11505f757f3fSDimitry Andric .append(DeclarationFragmentsBuilder::getFragmentsForFunction( 11515f757f3fSDimitry Andric Decl->getAsFunction())); 11525f757f3fSDimitry Andric } 11535f757f3fSDimitry Andric 11545f757f3fSDimitry Andric DeclarationFragments 11555f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization( 11565f757f3fSDimitry Andric const FunctionDecl *Decl) { 11575f757f3fSDimitry Andric DeclarationFragments Fragments; 11585f757f3fSDimitry Andric return Fragments 11595f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword) 11605f757f3fSDimitry Andric .append("<>", DeclarationFragments::FragmentKind::Text) 11615f757f3fSDimitry Andric .appendSpace() 11625f757f3fSDimitry Andric .append(DeclarationFragmentsBuilder::getFragmentsForFunction(Decl)); 11635f757f3fSDimitry Andric } 11645f757f3fSDimitry Andric 116581ad6265SDimitry Andric DeclarationFragments 116681ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name, 116781ad6265SDimitry Andric const MacroDirective *MD) { 116881ad6265SDimitry Andric DeclarationFragments Fragments; 116981ad6265SDimitry Andric Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword) 117081ad6265SDimitry Andric .appendSpace(); 117181ad6265SDimitry Andric Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); 117281ad6265SDimitry Andric 117381ad6265SDimitry Andric auto *MI = MD->getMacroInfo(); 117481ad6265SDimitry Andric 117581ad6265SDimitry Andric if (MI->isFunctionLike()) { 117681ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text); 117781ad6265SDimitry Andric unsigned numParameters = MI->getNumParams(); 117881ad6265SDimitry Andric if (MI->isC99Varargs()) 117981ad6265SDimitry Andric --numParameters; 118081ad6265SDimitry Andric for (unsigned i = 0; i < numParameters; ++i) { 118181ad6265SDimitry Andric if (i) 118281ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 118381ad6265SDimitry Andric Fragments.append(MI->params()[i]->getName(), 118481ad6265SDimitry Andric DeclarationFragments::FragmentKind::InternalParam); 118581ad6265SDimitry Andric } 118681ad6265SDimitry Andric if (MI->isVariadic()) { 118781ad6265SDimitry Andric if (numParameters && MI->isC99Varargs()) 118881ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 118981ad6265SDimitry Andric Fragments.append("...", DeclarationFragments::FragmentKind::Text); 119081ad6265SDimitry Andric } 119181ad6265SDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 119281ad6265SDimitry Andric } 119381ad6265SDimitry Andric return Fragments; 119481ad6265SDimitry Andric } 119581ad6265SDimitry Andric 119681ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory( 119781ad6265SDimitry Andric const ObjCCategoryDecl *Category) { 119881ad6265SDimitry Andric DeclarationFragments Fragments; 119981ad6265SDimitry Andric 1200bdd1243dSDimitry Andric auto *Interface = Category->getClassInterface(); 120181ad6265SDimitry Andric SmallString<128> InterfaceUSR; 1202bdd1243dSDimitry Andric index::generateUSRForDecl(Interface, InterfaceUSR); 120381ad6265SDimitry Andric 120481ad6265SDimitry Andric Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) 120581ad6265SDimitry Andric .appendSpace() 120681ad6265SDimitry Andric .append(Category->getClassInterface()->getName(), 1207bdd1243dSDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR, 1208bdd1243dSDimitry Andric Interface) 120981ad6265SDimitry Andric .append(" (", DeclarationFragments::FragmentKind::Text) 121081ad6265SDimitry Andric .append(Category->getName(), 121181ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier) 121281ad6265SDimitry Andric .append(")", DeclarationFragments::FragmentKind::Text); 121381ad6265SDimitry Andric 121481ad6265SDimitry Andric return Fragments; 121581ad6265SDimitry Andric } 121681ad6265SDimitry Andric 121781ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface( 121881ad6265SDimitry Andric const ObjCInterfaceDecl *Interface) { 121981ad6265SDimitry Andric DeclarationFragments Fragments; 122081ad6265SDimitry Andric // Build the base of the Objective-C interface declaration. 122181ad6265SDimitry Andric Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) 122281ad6265SDimitry Andric .appendSpace() 122381ad6265SDimitry Andric .append(Interface->getName(), 122481ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 122581ad6265SDimitry Andric 122681ad6265SDimitry Andric // Build the inheritance part of the declaration. 122781ad6265SDimitry Andric if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) { 122881ad6265SDimitry Andric SmallString<128> SuperUSR; 122981ad6265SDimitry Andric index::generateUSRForDecl(SuperClass, SuperUSR); 123081ad6265SDimitry Andric Fragments.append(" : ", DeclarationFragments::FragmentKind::Text) 123181ad6265SDimitry Andric .append(SuperClass->getName(), 1232bdd1243dSDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR, 1233bdd1243dSDimitry Andric SuperClass); 123481ad6265SDimitry Andric } 123581ad6265SDimitry Andric 123681ad6265SDimitry Andric return Fragments; 123781ad6265SDimitry Andric } 123881ad6265SDimitry Andric 123981ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod( 124081ad6265SDimitry Andric const ObjCMethodDecl *Method) { 124181ad6265SDimitry Andric DeclarationFragments Fragments, After; 124281ad6265SDimitry Andric // Build the instance/class method indicator. 124381ad6265SDimitry Andric if (Method->isClassMethod()) 124481ad6265SDimitry Andric Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); 124581ad6265SDimitry Andric else if (Method->isInstanceMethod()) 124681ad6265SDimitry Andric Fragments.append("- ", DeclarationFragments::FragmentKind::Text); 124781ad6265SDimitry Andric 124881ad6265SDimitry Andric // Build the return type. 124981ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text) 125081ad6265SDimitry Andric .append(getFragmentsForType(Method->getReturnType(), 125181ad6265SDimitry Andric Method->getASTContext(), After)) 125281ad6265SDimitry Andric .append(std::move(After)) 125381ad6265SDimitry Andric .append(")", DeclarationFragments::FragmentKind::Text); 125481ad6265SDimitry Andric 125581ad6265SDimitry Andric // Build the selector part. 125681ad6265SDimitry Andric Selector Selector = Method->getSelector(); 125781ad6265SDimitry Andric if (Selector.getNumArgs() == 0) 125881ad6265SDimitry Andric // For Objective-C methods that don't take arguments, the first (and only) 125981ad6265SDimitry Andric // slot of the selector is the method name. 126081ad6265SDimitry Andric Fragments.appendSpace().append( 126181ad6265SDimitry Andric Selector.getNameForSlot(0), 126281ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 126381ad6265SDimitry Andric 126481ad6265SDimitry Andric // For Objective-C methods that take arguments, build the selector slots. 126581ad6265SDimitry Andric for (unsigned i = 0, end = Method->param_size(); i != end; ++i) { 126681ad6265SDimitry Andric // Objective-C method selector parts are considered as identifiers instead 126781ad6265SDimitry Andric // of "external parameters" as in Swift. This is because Objective-C method 126881ad6265SDimitry Andric // symbols are referenced with the entire selector, instead of just the 126981ad6265SDimitry Andric // method name in Swift. 127081ad6265SDimitry Andric SmallString<32> ParamID(Selector.getNameForSlot(i)); 127181ad6265SDimitry Andric ParamID.append(":"); 127281ad6265SDimitry Andric Fragments.appendSpace().append( 127381ad6265SDimitry Andric ParamID, DeclarationFragments::FragmentKind::Identifier); 127481ad6265SDimitry Andric 127581ad6265SDimitry Andric // Build the internal parameter. 127681ad6265SDimitry Andric const ParmVarDecl *Param = Method->getParamDecl(i); 127781ad6265SDimitry Andric Fragments.append(getFragmentsForParam(Param)); 127881ad6265SDimitry Andric } 127981ad6265SDimitry Andric 128081ad6265SDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 128181ad6265SDimitry Andric } 128281ad6265SDimitry Andric 128381ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty( 128481ad6265SDimitry Andric const ObjCPropertyDecl *Property) { 128581ad6265SDimitry Andric DeclarationFragments Fragments, After; 128681ad6265SDimitry Andric 128781ad6265SDimitry Andric // Build the Objective-C property keyword. 128881ad6265SDimitry Andric Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword); 128981ad6265SDimitry Andric 129006c3fb27SDimitry Andric const auto Attributes = Property->getPropertyAttributesAsWritten(); 129181ad6265SDimitry Andric // Build the attributes if there is any associated with the property. 129281ad6265SDimitry Andric if (Attributes != ObjCPropertyAttribute::kind_noattr) { 129381ad6265SDimitry Andric // No leading comma for the first attribute. 129481ad6265SDimitry Andric bool First = true; 129581ad6265SDimitry Andric Fragments.append(" (", DeclarationFragments::FragmentKind::Text); 129681ad6265SDimitry Andric // Helper function to render the attribute. 129781ad6265SDimitry Andric auto RenderAttribute = 129881ad6265SDimitry Andric [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling, 129981ad6265SDimitry Andric StringRef Arg = "", 130081ad6265SDimitry Andric DeclarationFragments::FragmentKind ArgKind = 130181ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier) { 130281ad6265SDimitry Andric // Check if the `Kind` attribute is set for this property. 130381ad6265SDimitry Andric if ((Attributes & Kind) && !Spelling.empty()) { 130481ad6265SDimitry Andric // Add a leading comma if this is not the first attribute rendered. 130581ad6265SDimitry Andric if (!First) 130681ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 130781ad6265SDimitry Andric // Render the spelling of this attribute `Kind` as a keyword. 130881ad6265SDimitry Andric Fragments.append(Spelling, 130981ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword); 131081ad6265SDimitry Andric // If this attribute takes in arguments (e.g. `getter=getterName`), 131181ad6265SDimitry Andric // render the arguments. 131281ad6265SDimitry Andric if (!Arg.empty()) 131381ad6265SDimitry Andric Fragments.append("=", DeclarationFragments::FragmentKind::Text) 131481ad6265SDimitry Andric .append(Arg, ArgKind); 131581ad6265SDimitry Andric First = false; 131681ad6265SDimitry Andric } 131781ad6265SDimitry Andric }; 131881ad6265SDimitry Andric 131981ad6265SDimitry Andric // Go through all possible Objective-C property attributes and render set 132081ad6265SDimitry Andric // ones. 132181ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_class, "class"); 132281ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct"); 132381ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic"); 132481ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic"); 132581ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign"); 132681ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain"); 132781ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong"); 132881ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy"); 132981ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak"); 133081ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained, 133181ad6265SDimitry Andric "unsafe_unretained"); 133281ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite"); 133381ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly"); 133481ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter", 133581ad6265SDimitry Andric Property->getGetterName().getAsString()); 133681ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter", 133781ad6265SDimitry Andric Property->getSetterName().getAsString()); 133881ad6265SDimitry Andric 133981ad6265SDimitry Andric // Render nullability attributes. 134081ad6265SDimitry Andric if (Attributes & ObjCPropertyAttribute::kind_nullability) { 134181ad6265SDimitry Andric QualType Type = Property->getType(); 134281ad6265SDimitry Andric if (const auto Nullability = 134381ad6265SDimitry Andric AttributedType::stripOuterNullability(Type)) { 134481ad6265SDimitry Andric if (!First) 134581ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 134681ad6265SDimitry Andric if (*Nullability == NullabilityKind::Unspecified && 134781ad6265SDimitry Andric (Attributes & ObjCPropertyAttribute::kind_null_resettable)) 134881ad6265SDimitry Andric Fragments.append("null_resettable", 134981ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword); 135081ad6265SDimitry Andric else 135181ad6265SDimitry Andric Fragments.append( 135281ad6265SDimitry Andric getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true), 135381ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword); 135481ad6265SDimitry Andric First = false; 135581ad6265SDimitry Andric } 135681ad6265SDimitry Andric } 135781ad6265SDimitry Andric 135881ad6265SDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 135981ad6265SDimitry Andric } 136081ad6265SDimitry Andric 13615f757f3fSDimitry Andric Fragments.appendSpace(); 13625f757f3fSDimitry Andric 13635f757f3fSDimitry Andric FunctionTypeLoc BlockLoc; 13645f757f3fSDimitry Andric FunctionProtoTypeLoc BlockProtoLoc; 13655f757f3fSDimitry Andric findTypeLocForBlockDecl(Property->getTypeSourceInfo(), BlockLoc, 13665f757f3fSDimitry Andric BlockProtoLoc); 13675f757f3fSDimitry Andric 13685f757f3fSDimitry Andric auto PropType = Property->getType(); 13695f757f3fSDimitry Andric if (!BlockLoc) 13705f757f3fSDimitry Andric Fragments 13715f757f3fSDimitry Andric .append(getFragmentsForType(PropType, Property->getASTContext(), After)) 13725f757f3fSDimitry Andric .appendSpace(); 13735f757f3fSDimitry Andric else 13745f757f3fSDimitry Andric Fragments.append( 13755f757f3fSDimitry Andric getFragmentsForBlock(Property, BlockLoc, BlockProtoLoc, After)); 13765f757f3fSDimitry Andric 13775f757f3fSDimitry Andric return Fragments 137881ad6265SDimitry Andric .append(Property->getName(), 137981ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier) 13805f757f3fSDimitry Andric .append(std::move(After)) 13815f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text); 138281ad6265SDimitry Andric } 138381ad6265SDimitry Andric 138481ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol( 138581ad6265SDimitry Andric const ObjCProtocolDecl *Protocol) { 138681ad6265SDimitry Andric DeclarationFragments Fragments; 138781ad6265SDimitry Andric // Build basic protocol declaration. 138881ad6265SDimitry Andric Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword) 138981ad6265SDimitry Andric .appendSpace() 139081ad6265SDimitry Andric .append(Protocol->getName(), 139181ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 139281ad6265SDimitry Andric 139381ad6265SDimitry Andric // If this protocol conforms to other protocols, build the conformance list. 139481ad6265SDimitry Andric if (!Protocol->protocols().empty()) { 139581ad6265SDimitry Andric Fragments.append(" <", DeclarationFragments::FragmentKind::Text); 139681ad6265SDimitry Andric for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin(); 139781ad6265SDimitry Andric It != Protocol->protocol_end(); It++) { 139881ad6265SDimitry Andric // Add a leading comma if this is not the first protocol rendered. 139981ad6265SDimitry Andric if (It != Protocol->protocol_begin()) 140081ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 140181ad6265SDimitry Andric 140281ad6265SDimitry Andric SmallString<128> USR; 140381ad6265SDimitry Andric index::generateUSRForDecl(*It, USR); 140481ad6265SDimitry Andric Fragments.append((*It)->getName(), 1405bdd1243dSDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, USR, 1406bdd1243dSDimitry Andric *It); 140781ad6265SDimitry Andric } 140881ad6265SDimitry Andric Fragments.append(">", DeclarationFragments::FragmentKind::Text); 140981ad6265SDimitry Andric } 141081ad6265SDimitry Andric 141181ad6265SDimitry Andric return Fragments; 141281ad6265SDimitry Andric } 141381ad6265SDimitry Andric 141481ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef( 141581ad6265SDimitry Andric const TypedefNameDecl *Decl) { 141681ad6265SDimitry Andric DeclarationFragments Fragments, After; 141781ad6265SDimitry Andric Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword) 141881ad6265SDimitry Andric .appendSpace() 141981ad6265SDimitry Andric .append(getFragmentsForType(Decl->getUnderlyingType(), 142081ad6265SDimitry Andric Decl->getASTContext(), After)) 142181ad6265SDimitry Andric .append(std::move(After)) 142281ad6265SDimitry Andric .appendSpace() 142381ad6265SDimitry Andric .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier); 142481ad6265SDimitry Andric 142506c3fb27SDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 142681ad6265SDimitry Andric } 142781ad6265SDimitry Andric 142881ad6265SDimitry Andric // Instantiate template for FunctionDecl. 142981ad6265SDimitry Andric template FunctionSignature 143081ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *); 143181ad6265SDimitry Andric 143281ad6265SDimitry Andric // Instantiate template for ObjCMethodDecl. 143381ad6265SDimitry Andric template FunctionSignature 143481ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *); 143581ad6265SDimitry Andric 143681ad6265SDimitry Andric // Subheading of a symbol defaults to its name. 143781ad6265SDimitry Andric DeclarationFragments 143881ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) { 143981ad6265SDimitry Andric DeclarationFragments Fragments; 14405f757f3fSDimitry Andric if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl)) 14415f757f3fSDimitry Andric Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(), 14425f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Identifier); 14435f757f3fSDimitry Andric else if (isa<CXXConversionDecl>(Decl)) { 14445f757f3fSDimitry Andric Fragments.append( 14455f757f3fSDimitry Andric cast<CXXConversionDecl>(Decl)->getConversionType().getAsString(), 14465f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Identifier); 14475f757f3fSDimitry Andric } else if (isa<CXXMethodDecl>(Decl) && 14485f757f3fSDimitry Andric cast<CXXMethodDecl>(Decl)->isOverloadedOperator()) { 14495f757f3fSDimitry Andric Fragments.append(Decl->getNameAsString(), 14505f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Identifier); 14515f757f3fSDimitry Andric } else if (!Decl->getName().empty()) 145281ad6265SDimitry Andric Fragments.append(Decl->getName(), 145381ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 145481ad6265SDimitry Andric return Fragments; 145581ad6265SDimitry Andric } 145681ad6265SDimitry Andric 145781ad6265SDimitry Andric // Subheading of an Objective-C method is a `+` or `-` sign indicating whether 145881ad6265SDimitry Andric // it's a class method or an instance method, followed by the selector name. 145981ad6265SDimitry Andric DeclarationFragments 146081ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) { 146181ad6265SDimitry Andric DeclarationFragments Fragments; 146281ad6265SDimitry Andric if (Method->isClassMethod()) 146381ad6265SDimitry Andric Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); 146481ad6265SDimitry Andric else if (Method->isInstanceMethod()) 146581ad6265SDimitry Andric Fragments.append("- ", DeclarationFragments::FragmentKind::Text); 146681ad6265SDimitry Andric 146781ad6265SDimitry Andric return Fragments.append(Method->getNameAsString(), 146881ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 146981ad6265SDimitry Andric } 147081ad6265SDimitry Andric 147181ad6265SDimitry Andric // Subheading of a symbol defaults to its name. 147281ad6265SDimitry Andric DeclarationFragments 147381ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) { 147481ad6265SDimitry Andric DeclarationFragments Fragments; 147581ad6265SDimitry Andric Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); 147681ad6265SDimitry Andric return Fragments; 147781ad6265SDimitry Andric } 1478