1*81ad6265SDimitry Andric //===- ExtractAPI/DeclarationFragments.cpp ----------------------*- C++ -*-===// 2*81ad6265SDimitry Andric // 3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*81ad6265SDimitry Andric // 7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 8*81ad6265SDimitry Andric /// 9*81ad6265SDimitry Andric /// \file 10*81ad6265SDimitry Andric /// This file implements Declaration Fragments related classes. 11*81ad6265SDimitry Andric /// 12*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 13*81ad6265SDimitry Andric 14*81ad6265SDimitry Andric #include "clang/ExtractAPI/DeclarationFragments.h" 15*81ad6265SDimitry Andric #include "TypedefUnderlyingTypeResolver.h" 16*81ad6265SDimitry Andric #include "clang/Index/USRGeneration.h" 17*81ad6265SDimitry Andric #include "llvm/ADT/StringSwitch.h" 18*81ad6265SDimitry Andric 19*81ad6265SDimitry Andric using namespace clang::extractapi; 20*81ad6265SDimitry Andric using namespace llvm; 21*81ad6265SDimitry Andric 22*81ad6265SDimitry Andric DeclarationFragments &DeclarationFragments::appendSpace() { 23*81ad6265SDimitry Andric if (!Fragments.empty()) { 24*81ad6265SDimitry Andric Fragment &Last = Fragments.back(); 25*81ad6265SDimitry Andric if (Last.Kind == FragmentKind::Text) { 26*81ad6265SDimitry Andric // Merge the extra space into the last fragment if the last fragment is 27*81ad6265SDimitry Andric // also text. 28*81ad6265SDimitry Andric if (Last.Spelling.back() != ' ') { // avoid extra trailing spaces. 29*81ad6265SDimitry Andric Last.Spelling.push_back(' '); 30*81ad6265SDimitry Andric } 31*81ad6265SDimitry Andric } else { 32*81ad6265SDimitry Andric append(" ", FragmentKind::Text); 33*81ad6265SDimitry Andric } 34*81ad6265SDimitry Andric } 35*81ad6265SDimitry Andric 36*81ad6265SDimitry Andric return *this; 37*81ad6265SDimitry Andric } 38*81ad6265SDimitry Andric 39*81ad6265SDimitry Andric StringRef DeclarationFragments::getFragmentKindString( 40*81ad6265SDimitry Andric DeclarationFragments::FragmentKind Kind) { 41*81ad6265SDimitry Andric switch (Kind) { 42*81ad6265SDimitry Andric case DeclarationFragments::FragmentKind::None: 43*81ad6265SDimitry Andric return "none"; 44*81ad6265SDimitry Andric case DeclarationFragments::FragmentKind::Keyword: 45*81ad6265SDimitry Andric return "keyword"; 46*81ad6265SDimitry Andric case DeclarationFragments::FragmentKind::Attribute: 47*81ad6265SDimitry Andric return "attribute"; 48*81ad6265SDimitry Andric case DeclarationFragments::FragmentKind::NumberLiteral: 49*81ad6265SDimitry Andric return "number"; 50*81ad6265SDimitry Andric case DeclarationFragments::FragmentKind::StringLiteral: 51*81ad6265SDimitry Andric return "string"; 52*81ad6265SDimitry Andric case DeclarationFragments::FragmentKind::Identifier: 53*81ad6265SDimitry Andric return "identifier"; 54*81ad6265SDimitry Andric case DeclarationFragments::FragmentKind::TypeIdentifier: 55*81ad6265SDimitry Andric return "typeIdentifier"; 56*81ad6265SDimitry Andric case DeclarationFragments::FragmentKind::GenericParameter: 57*81ad6265SDimitry Andric return "genericParameter"; 58*81ad6265SDimitry Andric case DeclarationFragments::FragmentKind::ExternalParam: 59*81ad6265SDimitry Andric return "externalParam"; 60*81ad6265SDimitry Andric case DeclarationFragments::FragmentKind::InternalParam: 61*81ad6265SDimitry Andric return "internalParam"; 62*81ad6265SDimitry Andric case DeclarationFragments::FragmentKind::Text: 63*81ad6265SDimitry Andric return "text"; 64*81ad6265SDimitry Andric } 65*81ad6265SDimitry Andric 66*81ad6265SDimitry Andric llvm_unreachable("Unhandled FragmentKind"); 67*81ad6265SDimitry Andric } 68*81ad6265SDimitry Andric 69*81ad6265SDimitry Andric DeclarationFragments::FragmentKind 70*81ad6265SDimitry Andric DeclarationFragments::parseFragmentKindFromString(StringRef S) { 71*81ad6265SDimitry Andric return llvm::StringSwitch<FragmentKind>(S) 72*81ad6265SDimitry Andric .Case("keyword", DeclarationFragments::FragmentKind::Keyword) 73*81ad6265SDimitry Andric .Case("attribute", DeclarationFragments::FragmentKind::Attribute) 74*81ad6265SDimitry Andric .Case("number", DeclarationFragments::FragmentKind::NumberLiteral) 75*81ad6265SDimitry Andric .Case("string", DeclarationFragments::FragmentKind::StringLiteral) 76*81ad6265SDimitry Andric .Case("identifier", DeclarationFragments::FragmentKind::Identifier) 77*81ad6265SDimitry Andric .Case("typeIdentifier", 78*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier) 79*81ad6265SDimitry Andric .Case("genericParameter", 80*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::GenericParameter) 81*81ad6265SDimitry Andric .Case("internalParam", DeclarationFragments::FragmentKind::InternalParam) 82*81ad6265SDimitry Andric .Case("externalParam", DeclarationFragments::FragmentKind::ExternalParam) 83*81ad6265SDimitry Andric .Case("text", DeclarationFragments::FragmentKind::Text) 84*81ad6265SDimitry Andric .Default(DeclarationFragments::FragmentKind::None); 85*81ad6265SDimitry Andric } 86*81ad6265SDimitry Andric 87*81ad6265SDimitry Andric // NNS stores C++ nested name specifiers, which are prefixes to qualified names. 88*81ad6265SDimitry Andric // Build declaration fragments for NNS recursively so that we have the USR for 89*81ad6265SDimitry Andric // every part in a qualified name, and also leaves the actual underlying type 90*81ad6265SDimitry Andric // cleaner for its own fragment. 91*81ad6265SDimitry Andric DeclarationFragments 92*81ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS, 93*81ad6265SDimitry Andric ASTContext &Context, 94*81ad6265SDimitry Andric DeclarationFragments &After) { 95*81ad6265SDimitry Andric DeclarationFragments Fragments; 96*81ad6265SDimitry Andric if (NNS->getPrefix()) 97*81ad6265SDimitry Andric Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After)); 98*81ad6265SDimitry Andric 99*81ad6265SDimitry Andric switch (NNS->getKind()) { 100*81ad6265SDimitry Andric case NestedNameSpecifier::Identifier: 101*81ad6265SDimitry Andric Fragments.append(NNS->getAsIdentifier()->getName(), 102*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 103*81ad6265SDimitry Andric break; 104*81ad6265SDimitry Andric 105*81ad6265SDimitry Andric case NestedNameSpecifier::Namespace: { 106*81ad6265SDimitry Andric const NamespaceDecl *NS = NNS->getAsNamespace(); 107*81ad6265SDimitry Andric if (NS->isAnonymousNamespace()) 108*81ad6265SDimitry Andric return Fragments; 109*81ad6265SDimitry Andric SmallString<128> USR; 110*81ad6265SDimitry Andric index::generateUSRForDecl(NS, USR); 111*81ad6265SDimitry Andric Fragments.append(NS->getName(), 112*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier, USR); 113*81ad6265SDimitry Andric break; 114*81ad6265SDimitry Andric } 115*81ad6265SDimitry Andric 116*81ad6265SDimitry Andric case NestedNameSpecifier::NamespaceAlias: { 117*81ad6265SDimitry Andric const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias(); 118*81ad6265SDimitry Andric SmallString<128> USR; 119*81ad6265SDimitry Andric index::generateUSRForDecl(Alias, USR); 120*81ad6265SDimitry Andric Fragments.append(Alias->getName(), 121*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier, USR); 122*81ad6265SDimitry Andric break; 123*81ad6265SDimitry Andric } 124*81ad6265SDimitry Andric 125*81ad6265SDimitry Andric case NestedNameSpecifier::Global: 126*81ad6265SDimitry Andric // The global specifier `::` at the beginning. No stored value. 127*81ad6265SDimitry Andric break; 128*81ad6265SDimitry Andric 129*81ad6265SDimitry Andric case NestedNameSpecifier::Super: 130*81ad6265SDimitry Andric // Microsoft's `__super` specifier. 131*81ad6265SDimitry Andric Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword); 132*81ad6265SDimitry Andric break; 133*81ad6265SDimitry Andric 134*81ad6265SDimitry Andric case NestedNameSpecifier::TypeSpecWithTemplate: 135*81ad6265SDimitry Andric // A type prefixed by the `template` keyword. 136*81ad6265SDimitry Andric Fragments.append("template", DeclarationFragments::FragmentKind::Keyword); 137*81ad6265SDimitry Andric Fragments.appendSpace(); 138*81ad6265SDimitry Andric // Fallthrough after adding the keyword to handle the actual type. 139*81ad6265SDimitry Andric LLVM_FALLTHROUGH; 140*81ad6265SDimitry Andric 141*81ad6265SDimitry Andric case NestedNameSpecifier::TypeSpec: { 142*81ad6265SDimitry Andric const Type *T = NNS->getAsType(); 143*81ad6265SDimitry Andric // FIXME: Handle C++ template specialization type 144*81ad6265SDimitry Andric Fragments.append(getFragmentsForType(T, Context, After)); 145*81ad6265SDimitry Andric break; 146*81ad6265SDimitry Andric } 147*81ad6265SDimitry Andric } 148*81ad6265SDimitry Andric 149*81ad6265SDimitry Andric // Add the separator text `::` for this segment. 150*81ad6265SDimitry Andric return Fragments.append("::", DeclarationFragments::FragmentKind::Text); 151*81ad6265SDimitry Andric } 152*81ad6265SDimitry Andric 153*81ad6265SDimitry Andric // Recursively build the declaration fragments for an underlying `Type` with 154*81ad6265SDimitry Andric // qualifiers removed. 155*81ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( 156*81ad6265SDimitry Andric const Type *T, ASTContext &Context, DeclarationFragments &After) { 157*81ad6265SDimitry Andric assert(T && "invalid type"); 158*81ad6265SDimitry Andric 159*81ad6265SDimitry Andric DeclarationFragments Fragments; 160*81ad6265SDimitry Andric 161*81ad6265SDimitry Andric // Declaration fragments of a pointer type is the declaration fragments of 162*81ad6265SDimitry Andric // the pointee type followed by a `*`, except for Objective-C `id` and `Class` 163*81ad6265SDimitry Andric // pointers, where we do not spell out the `*`. 164*81ad6265SDimitry Andric if (T->isPointerType() || 165*81ad6265SDimitry Andric (T->isObjCObjectPointerType() && 166*81ad6265SDimitry Andric !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType())) { 167*81ad6265SDimitry Andric return Fragments 168*81ad6265SDimitry Andric .append(getFragmentsForType(T->getPointeeType(), Context, After)) 169*81ad6265SDimitry Andric .append(" *", DeclarationFragments::FragmentKind::Text); 170*81ad6265SDimitry Andric } 171*81ad6265SDimitry Andric 172*81ad6265SDimitry Andric // Declaration fragments of a lvalue reference type is the declaration 173*81ad6265SDimitry Andric // fragments of the underlying type followed by a `&`. 174*81ad6265SDimitry Andric if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T)) 175*81ad6265SDimitry Andric return Fragments 176*81ad6265SDimitry Andric .append( 177*81ad6265SDimitry Andric getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After)) 178*81ad6265SDimitry Andric .append(" &", DeclarationFragments::FragmentKind::Text); 179*81ad6265SDimitry Andric 180*81ad6265SDimitry Andric // Declaration fragments of a rvalue reference type is the declaration 181*81ad6265SDimitry Andric // fragments of the underlying type followed by a `&&`. 182*81ad6265SDimitry Andric if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T)) 183*81ad6265SDimitry Andric return Fragments 184*81ad6265SDimitry Andric .append( 185*81ad6265SDimitry Andric getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After)) 186*81ad6265SDimitry Andric .append(" &&", DeclarationFragments::FragmentKind::Text); 187*81ad6265SDimitry Andric 188*81ad6265SDimitry Andric // Declaration fragments of an array-typed variable have two parts: 189*81ad6265SDimitry Andric // 1. the element type of the array that appears before the variable name; 190*81ad6265SDimitry Andric // 2. array brackets `[(0-9)?]` that appear after the variable name. 191*81ad6265SDimitry Andric if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) { 192*81ad6265SDimitry Andric // Build the "after" part first because the inner element type might also 193*81ad6265SDimitry Andric // be an array-type. For example `int matrix[3][4]` which has a type of 194*81ad6265SDimitry Andric // "(array 3 of (array 4 of ints))." 195*81ad6265SDimitry Andric // Push the array size part first to make sure they are in the right order. 196*81ad6265SDimitry Andric After.append("[", DeclarationFragments::FragmentKind::Text); 197*81ad6265SDimitry Andric 198*81ad6265SDimitry Andric switch (AT->getSizeModifier()) { 199*81ad6265SDimitry Andric case ArrayType::Normal: 200*81ad6265SDimitry Andric break; 201*81ad6265SDimitry Andric case ArrayType::Static: 202*81ad6265SDimitry Andric Fragments.append("static", DeclarationFragments::FragmentKind::Keyword); 203*81ad6265SDimitry Andric break; 204*81ad6265SDimitry Andric case ArrayType::Star: 205*81ad6265SDimitry Andric Fragments.append("*", DeclarationFragments::FragmentKind::Text); 206*81ad6265SDimitry Andric break; 207*81ad6265SDimitry Andric } 208*81ad6265SDimitry Andric 209*81ad6265SDimitry Andric if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) { 210*81ad6265SDimitry Andric // FIXME: right now this would evaluate any expressions/macros written in 211*81ad6265SDimitry Andric // the original source to concrete values. For example 212*81ad6265SDimitry Andric // `int nums[MAX]` -> `int nums[100]` 213*81ad6265SDimitry Andric // `char *str[5 + 1]` -> `char *str[6]` 214*81ad6265SDimitry Andric SmallString<128> Size; 215*81ad6265SDimitry Andric CAT->getSize().toStringUnsigned(Size); 216*81ad6265SDimitry Andric After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral); 217*81ad6265SDimitry Andric } 218*81ad6265SDimitry Andric 219*81ad6265SDimitry Andric After.append("]", DeclarationFragments::FragmentKind::Text); 220*81ad6265SDimitry Andric 221*81ad6265SDimitry Andric return Fragments.append( 222*81ad6265SDimitry Andric getFragmentsForType(AT->getElementType(), Context, After)); 223*81ad6265SDimitry Andric } 224*81ad6265SDimitry Andric 225*81ad6265SDimitry Andric // An ElaboratedType is a sugar for types that are referred to using an 226*81ad6265SDimitry Andric // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a 227*81ad6265SDimitry Andric // qualified name, e.g., `N::M::type`, or both. 228*81ad6265SDimitry Andric if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) { 229*81ad6265SDimitry Andric ElaboratedTypeKeyword Keyword = ET->getKeyword(); 230*81ad6265SDimitry Andric if (Keyword != ETK_None) { 231*81ad6265SDimitry Andric Fragments 232*81ad6265SDimitry Andric .append(ElaboratedType::getKeywordName(Keyword), 233*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword) 234*81ad6265SDimitry Andric .appendSpace(); 235*81ad6265SDimitry Andric } 236*81ad6265SDimitry Andric 237*81ad6265SDimitry Andric if (const NestedNameSpecifier *NNS = ET->getQualifier()) 238*81ad6265SDimitry Andric Fragments.append(getFragmentsForNNS(NNS, Context, After)); 239*81ad6265SDimitry Andric 240*81ad6265SDimitry Andric // After handling the elaborated keyword or qualified name, build 241*81ad6265SDimitry Andric // declaration fragments for the desugared underlying type. 242*81ad6265SDimitry Andric return Fragments.append(getFragmentsForType(ET->desugar(), Context, After)); 243*81ad6265SDimitry Andric } 244*81ad6265SDimitry Andric 245*81ad6265SDimitry Andric // Everything we care about has been handled now, reduce to the canonical 246*81ad6265SDimitry Andric // unqualified base type. 247*81ad6265SDimitry Andric QualType Base = T->getCanonicalTypeUnqualified(); 248*81ad6265SDimitry Andric 249*81ad6265SDimitry Andric // Render Objective-C `id`/`instancetype` as keywords. 250*81ad6265SDimitry Andric if (T->isObjCIdType()) 251*81ad6265SDimitry Andric return Fragments.append(Base.getAsString(), 252*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword); 253*81ad6265SDimitry Andric 254*81ad6265SDimitry Andric // If the type is a typedefed type, get the underlying TypedefNameDecl for a 255*81ad6265SDimitry Andric // direct reference to the typedef instead of the wrapped type. 256*81ad6265SDimitry Andric if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) { 257*81ad6265SDimitry Andric const TypedefNameDecl *Decl = TypedefTy->getDecl(); 258*81ad6265SDimitry Andric std::string USR = 259*81ad6265SDimitry Andric TypedefUnderlyingTypeResolver(Context).getUSRForType(QualType(T, 0)); 260*81ad6265SDimitry Andric return Fragments.append(Decl->getName(), 261*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, 262*81ad6265SDimitry Andric USR); 263*81ad6265SDimitry Andric } 264*81ad6265SDimitry Andric 265*81ad6265SDimitry Andric // If the base type is a TagType (struct/interface/union/class/enum), let's 266*81ad6265SDimitry Andric // get the underlying Decl for better names and USRs. 267*81ad6265SDimitry Andric if (const TagType *TagTy = dyn_cast<TagType>(Base)) { 268*81ad6265SDimitry Andric const TagDecl *Decl = TagTy->getDecl(); 269*81ad6265SDimitry Andric // Anonymous decl, skip this fragment. 270*81ad6265SDimitry Andric if (Decl->getName().empty()) 271*81ad6265SDimitry Andric return Fragments; 272*81ad6265SDimitry Andric SmallString<128> TagUSR; 273*81ad6265SDimitry Andric clang::index::generateUSRForDecl(Decl, TagUSR); 274*81ad6265SDimitry Andric return Fragments.append(Decl->getName(), 275*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, 276*81ad6265SDimitry Andric TagUSR); 277*81ad6265SDimitry Andric } 278*81ad6265SDimitry Andric 279*81ad6265SDimitry Andric // If the base type is an ObjCInterfaceType, use the underlying 280*81ad6265SDimitry Andric // ObjCInterfaceDecl for the true USR. 281*81ad6265SDimitry Andric if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) { 282*81ad6265SDimitry Andric const auto *Decl = ObjCIT->getDecl(); 283*81ad6265SDimitry Andric SmallString<128> USR; 284*81ad6265SDimitry Andric index::generateUSRForDecl(Decl, USR); 285*81ad6265SDimitry Andric return Fragments.append(Decl->getName(), 286*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, 287*81ad6265SDimitry Andric USR); 288*81ad6265SDimitry Andric } 289*81ad6265SDimitry Andric 290*81ad6265SDimitry Andric // Default fragment builder for other kinds of types (BuiltinType etc.) 291*81ad6265SDimitry Andric SmallString<128> USR; 292*81ad6265SDimitry Andric clang::index::generateUSRForType(Base, Context, USR); 293*81ad6265SDimitry Andric Fragments.append(Base.getAsString(), 294*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, USR); 295*81ad6265SDimitry Andric 296*81ad6265SDimitry Andric return Fragments; 297*81ad6265SDimitry Andric } 298*81ad6265SDimitry Andric 299*81ad6265SDimitry Andric DeclarationFragments 300*81ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) { 301*81ad6265SDimitry Andric DeclarationFragments Fragments; 302*81ad6265SDimitry Andric if (Quals.hasConst()) 303*81ad6265SDimitry Andric Fragments.append("const", DeclarationFragments::FragmentKind::Keyword); 304*81ad6265SDimitry Andric if (Quals.hasVolatile()) 305*81ad6265SDimitry Andric Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword); 306*81ad6265SDimitry Andric if (Quals.hasRestrict()) 307*81ad6265SDimitry Andric Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword); 308*81ad6265SDimitry Andric 309*81ad6265SDimitry Andric return Fragments; 310*81ad6265SDimitry Andric } 311*81ad6265SDimitry Andric 312*81ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( 313*81ad6265SDimitry Andric const QualType QT, ASTContext &Context, DeclarationFragments &After) { 314*81ad6265SDimitry Andric assert(!QT.isNull() && "invalid type"); 315*81ad6265SDimitry Andric 316*81ad6265SDimitry Andric if (const ParenType *PT = dyn_cast<ParenType>(QT)) { 317*81ad6265SDimitry Andric After.append(")", DeclarationFragments::FragmentKind::Text); 318*81ad6265SDimitry Andric return getFragmentsForType(PT->getInnerType(), Context, After) 319*81ad6265SDimitry Andric .append("(", DeclarationFragments::FragmentKind::Text); 320*81ad6265SDimitry Andric } 321*81ad6265SDimitry Andric 322*81ad6265SDimitry Andric const SplitQualType SQT = QT.split(); 323*81ad6265SDimitry Andric DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals), 324*81ad6265SDimitry Andric TypeFragments = 325*81ad6265SDimitry Andric getFragmentsForType(SQT.Ty, Context, After); 326*81ad6265SDimitry Andric if (QualsFragments.getFragments().empty()) 327*81ad6265SDimitry Andric return TypeFragments; 328*81ad6265SDimitry Andric 329*81ad6265SDimitry Andric // Use east qualifier for pointer types 330*81ad6265SDimitry Andric // For example: 331*81ad6265SDimitry Andric // ``` 332*81ad6265SDimitry Andric // int * const 333*81ad6265SDimitry Andric // ^---- ^---- 334*81ad6265SDimitry Andric // type qualifier 335*81ad6265SDimitry Andric // ^----------------- 336*81ad6265SDimitry Andric // const pointer to int 337*81ad6265SDimitry Andric // ``` 338*81ad6265SDimitry Andric // should not be reconstructed as 339*81ad6265SDimitry Andric // ``` 340*81ad6265SDimitry Andric // const int * 341*81ad6265SDimitry Andric // ^---- ^-- 342*81ad6265SDimitry Andric // qualifier type 343*81ad6265SDimitry Andric // ^---------------- ^ 344*81ad6265SDimitry Andric // pointer to const int 345*81ad6265SDimitry Andric // ``` 346*81ad6265SDimitry Andric if (SQT.Ty->isAnyPointerType()) 347*81ad6265SDimitry Andric return TypeFragments.appendSpace().append(std::move(QualsFragments)); 348*81ad6265SDimitry Andric 349*81ad6265SDimitry Andric return QualsFragments.appendSpace().append(std::move(TypeFragments)); 350*81ad6265SDimitry Andric } 351*81ad6265SDimitry Andric 352*81ad6265SDimitry Andric DeclarationFragments 353*81ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) { 354*81ad6265SDimitry Andric DeclarationFragments Fragments; 355*81ad6265SDimitry Andric StorageClass SC = Var->getStorageClass(); 356*81ad6265SDimitry Andric if (SC != SC_None) 357*81ad6265SDimitry Andric Fragments 358*81ad6265SDimitry Andric .append(VarDecl::getStorageClassSpecifierString(SC), 359*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword) 360*81ad6265SDimitry Andric .appendSpace(); 361*81ad6265SDimitry Andric QualType T = 362*81ad6265SDimitry Andric Var->getTypeSourceInfo() 363*81ad6265SDimitry Andric ? Var->getTypeSourceInfo()->getType() 364*81ad6265SDimitry Andric : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType()); 365*81ad6265SDimitry Andric 366*81ad6265SDimitry Andric // Capture potential fragments that needs to be placed after the variable name 367*81ad6265SDimitry Andric // ``` 368*81ad6265SDimitry Andric // int nums[5]; 369*81ad6265SDimitry Andric // char (*ptr_to_array)[6]; 370*81ad6265SDimitry Andric // ``` 371*81ad6265SDimitry Andric DeclarationFragments After; 372*81ad6265SDimitry Andric return Fragments.append(getFragmentsForType(T, Var->getASTContext(), After)) 373*81ad6265SDimitry Andric .appendSpace() 374*81ad6265SDimitry Andric .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) 375*81ad6265SDimitry Andric .append(std::move(After)); 376*81ad6265SDimitry Andric } 377*81ad6265SDimitry Andric 378*81ad6265SDimitry Andric DeclarationFragments 379*81ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) { 380*81ad6265SDimitry Andric DeclarationFragments Fragments, After; 381*81ad6265SDimitry Andric 382*81ad6265SDimitry Andric QualType T = Param->getTypeSourceInfo() 383*81ad6265SDimitry Andric ? Param->getTypeSourceInfo()->getType() 384*81ad6265SDimitry Andric : Param->getASTContext().getUnqualifiedObjCPointerType( 385*81ad6265SDimitry Andric Param->getType()); 386*81ad6265SDimitry Andric 387*81ad6265SDimitry Andric DeclarationFragments TypeFragments = 388*81ad6265SDimitry Andric getFragmentsForType(T, Param->getASTContext(), After); 389*81ad6265SDimitry Andric 390*81ad6265SDimitry Andric if (Param->isObjCMethodParameter()) 391*81ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text) 392*81ad6265SDimitry Andric .append(std::move(TypeFragments)) 393*81ad6265SDimitry Andric .append(") ", DeclarationFragments::FragmentKind::Text); 394*81ad6265SDimitry Andric else 395*81ad6265SDimitry Andric Fragments.append(std::move(TypeFragments)).appendSpace(); 396*81ad6265SDimitry Andric 397*81ad6265SDimitry Andric return Fragments 398*81ad6265SDimitry Andric .append(Param->getName(), 399*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::InternalParam) 400*81ad6265SDimitry Andric .append(std::move(After)); 401*81ad6265SDimitry Andric } 402*81ad6265SDimitry Andric 403*81ad6265SDimitry Andric DeclarationFragments 404*81ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) { 405*81ad6265SDimitry Andric DeclarationFragments Fragments; 406*81ad6265SDimitry Andric // FIXME: Handle template specialization 407*81ad6265SDimitry Andric switch (Func->getStorageClass()) { 408*81ad6265SDimitry Andric case SC_None: 409*81ad6265SDimitry Andric case SC_PrivateExtern: 410*81ad6265SDimitry Andric break; 411*81ad6265SDimitry Andric case SC_Extern: 412*81ad6265SDimitry Andric Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword) 413*81ad6265SDimitry Andric .appendSpace(); 414*81ad6265SDimitry Andric break; 415*81ad6265SDimitry Andric case SC_Static: 416*81ad6265SDimitry Andric Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) 417*81ad6265SDimitry Andric .appendSpace(); 418*81ad6265SDimitry Andric break; 419*81ad6265SDimitry Andric case SC_Auto: 420*81ad6265SDimitry Andric case SC_Register: 421*81ad6265SDimitry Andric llvm_unreachable("invalid for functions"); 422*81ad6265SDimitry Andric } 423*81ad6265SDimitry Andric // FIXME: Handle C++ function specifiers: constexpr, consteval, explicit, etc. 424*81ad6265SDimitry Andric 425*81ad6265SDimitry Andric // FIXME: Is `after` actually needed here? 426*81ad6265SDimitry Andric DeclarationFragments After; 427*81ad6265SDimitry Andric Fragments 428*81ad6265SDimitry Andric .append(getFragmentsForType(Func->getReturnType(), Func->getASTContext(), 429*81ad6265SDimitry Andric After)) 430*81ad6265SDimitry Andric .appendSpace() 431*81ad6265SDimitry Andric .append(Func->getName(), DeclarationFragments::FragmentKind::Identifier) 432*81ad6265SDimitry Andric .append(std::move(After)); 433*81ad6265SDimitry Andric 434*81ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text); 435*81ad6265SDimitry Andric for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) { 436*81ad6265SDimitry Andric if (i) 437*81ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 438*81ad6265SDimitry Andric Fragments.append(getFragmentsForParam(Func->getParamDecl(i))); 439*81ad6265SDimitry Andric } 440*81ad6265SDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 441*81ad6265SDimitry Andric 442*81ad6265SDimitry Andric // FIXME: Handle exception specifiers: throw, noexcept 443*81ad6265SDimitry Andric return Fragments; 444*81ad6265SDimitry Andric } 445*81ad6265SDimitry Andric 446*81ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant( 447*81ad6265SDimitry Andric const EnumConstantDecl *EnumConstDecl) { 448*81ad6265SDimitry Andric DeclarationFragments Fragments; 449*81ad6265SDimitry Andric return Fragments.append(EnumConstDecl->getName(), 450*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 451*81ad6265SDimitry Andric } 452*81ad6265SDimitry Andric 453*81ad6265SDimitry Andric DeclarationFragments 454*81ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) { 455*81ad6265SDimitry Andric if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl()) 456*81ad6265SDimitry Andric return getFragmentsForTypedef(TypedefNameDecl); 457*81ad6265SDimitry Andric 458*81ad6265SDimitry Andric DeclarationFragments Fragments, After; 459*81ad6265SDimitry Andric Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword); 460*81ad6265SDimitry Andric 461*81ad6265SDimitry Andric if (!EnumDecl->getName().empty()) 462*81ad6265SDimitry Andric Fragments.appendSpace().append( 463*81ad6265SDimitry Andric EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier); 464*81ad6265SDimitry Andric 465*81ad6265SDimitry Andric QualType IntegerType = EnumDecl->getIntegerType(); 466*81ad6265SDimitry Andric if (!IntegerType.isNull()) 467*81ad6265SDimitry Andric Fragments.append(": ", DeclarationFragments::FragmentKind::Text) 468*81ad6265SDimitry Andric .append( 469*81ad6265SDimitry Andric getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After)) 470*81ad6265SDimitry Andric .append(std::move(After)); 471*81ad6265SDimitry Andric 472*81ad6265SDimitry Andric return Fragments; 473*81ad6265SDimitry Andric } 474*81ad6265SDimitry Andric 475*81ad6265SDimitry Andric DeclarationFragments 476*81ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) { 477*81ad6265SDimitry Andric DeclarationFragments After; 478*81ad6265SDimitry Andric return getFragmentsForType(Field->getType(), Field->getASTContext(), After) 479*81ad6265SDimitry Andric .appendSpace() 480*81ad6265SDimitry Andric .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier) 481*81ad6265SDimitry Andric .append(std::move(After)); 482*81ad6265SDimitry Andric } 483*81ad6265SDimitry Andric 484*81ad6265SDimitry Andric DeclarationFragments 485*81ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForStruct(const RecordDecl *Record) { 486*81ad6265SDimitry Andric if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl()) 487*81ad6265SDimitry Andric return getFragmentsForTypedef(TypedefNameDecl); 488*81ad6265SDimitry Andric 489*81ad6265SDimitry Andric DeclarationFragments Fragments; 490*81ad6265SDimitry Andric Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword); 491*81ad6265SDimitry Andric 492*81ad6265SDimitry Andric if (!Record->getName().empty()) 493*81ad6265SDimitry Andric Fragments.appendSpace().append( 494*81ad6265SDimitry Andric Record->getName(), DeclarationFragments::FragmentKind::Identifier); 495*81ad6265SDimitry Andric return Fragments; 496*81ad6265SDimitry Andric } 497*81ad6265SDimitry Andric 498*81ad6265SDimitry Andric DeclarationFragments 499*81ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name, 500*81ad6265SDimitry Andric const MacroDirective *MD) { 501*81ad6265SDimitry Andric DeclarationFragments Fragments; 502*81ad6265SDimitry Andric Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword) 503*81ad6265SDimitry Andric .appendSpace(); 504*81ad6265SDimitry Andric Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); 505*81ad6265SDimitry Andric 506*81ad6265SDimitry Andric auto *MI = MD->getMacroInfo(); 507*81ad6265SDimitry Andric 508*81ad6265SDimitry Andric if (MI->isFunctionLike()) { 509*81ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text); 510*81ad6265SDimitry Andric unsigned numParameters = MI->getNumParams(); 511*81ad6265SDimitry Andric if (MI->isC99Varargs()) 512*81ad6265SDimitry Andric --numParameters; 513*81ad6265SDimitry Andric for (unsigned i = 0; i < numParameters; ++i) { 514*81ad6265SDimitry Andric if (i) 515*81ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 516*81ad6265SDimitry Andric Fragments.append(MI->params()[i]->getName(), 517*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::InternalParam); 518*81ad6265SDimitry Andric } 519*81ad6265SDimitry Andric if (MI->isVariadic()) { 520*81ad6265SDimitry Andric if (numParameters && MI->isC99Varargs()) 521*81ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 522*81ad6265SDimitry Andric Fragments.append("...", DeclarationFragments::FragmentKind::Text); 523*81ad6265SDimitry Andric } 524*81ad6265SDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 525*81ad6265SDimitry Andric } 526*81ad6265SDimitry Andric return Fragments; 527*81ad6265SDimitry Andric } 528*81ad6265SDimitry Andric 529*81ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory( 530*81ad6265SDimitry Andric const ObjCCategoryDecl *Category) { 531*81ad6265SDimitry Andric DeclarationFragments Fragments; 532*81ad6265SDimitry Andric 533*81ad6265SDimitry Andric SmallString<128> InterfaceUSR; 534*81ad6265SDimitry Andric index::generateUSRForDecl(Category->getClassInterface(), InterfaceUSR); 535*81ad6265SDimitry Andric 536*81ad6265SDimitry Andric Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) 537*81ad6265SDimitry Andric .appendSpace() 538*81ad6265SDimitry Andric .append(Category->getClassInterface()->getName(), 539*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR) 540*81ad6265SDimitry Andric .append(" (", DeclarationFragments::FragmentKind::Text) 541*81ad6265SDimitry Andric .append(Category->getName(), 542*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier) 543*81ad6265SDimitry Andric .append(")", DeclarationFragments::FragmentKind::Text); 544*81ad6265SDimitry Andric 545*81ad6265SDimitry Andric return Fragments; 546*81ad6265SDimitry Andric } 547*81ad6265SDimitry Andric 548*81ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface( 549*81ad6265SDimitry Andric const ObjCInterfaceDecl *Interface) { 550*81ad6265SDimitry Andric DeclarationFragments Fragments; 551*81ad6265SDimitry Andric // Build the base of the Objective-C interface declaration. 552*81ad6265SDimitry Andric Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) 553*81ad6265SDimitry Andric .appendSpace() 554*81ad6265SDimitry Andric .append(Interface->getName(), 555*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 556*81ad6265SDimitry Andric 557*81ad6265SDimitry Andric // Build the inheritance part of the declaration. 558*81ad6265SDimitry Andric if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) { 559*81ad6265SDimitry Andric SmallString<128> SuperUSR; 560*81ad6265SDimitry Andric index::generateUSRForDecl(SuperClass, SuperUSR); 561*81ad6265SDimitry Andric Fragments.append(" : ", DeclarationFragments::FragmentKind::Text) 562*81ad6265SDimitry Andric .append(SuperClass->getName(), 563*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR); 564*81ad6265SDimitry Andric } 565*81ad6265SDimitry Andric 566*81ad6265SDimitry Andric return Fragments; 567*81ad6265SDimitry Andric } 568*81ad6265SDimitry Andric 569*81ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod( 570*81ad6265SDimitry Andric const ObjCMethodDecl *Method) { 571*81ad6265SDimitry Andric DeclarationFragments Fragments, After; 572*81ad6265SDimitry Andric // Build the instance/class method indicator. 573*81ad6265SDimitry Andric if (Method->isClassMethod()) 574*81ad6265SDimitry Andric Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); 575*81ad6265SDimitry Andric else if (Method->isInstanceMethod()) 576*81ad6265SDimitry Andric Fragments.append("- ", DeclarationFragments::FragmentKind::Text); 577*81ad6265SDimitry Andric 578*81ad6265SDimitry Andric // Build the return type. 579*81ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text) 580*81ad6265SDimitry Andric .append(getFragmentsForType(Method->getReturnType(), 581*81ad6265SDimitry Andric Method->getASTContext(), After)) 582*81ad6265SDimitry Andric .append(std::move(After)) 583*81ad6265SDimitry Andric .append(")", DeclarationFragments::FragmentKind::Text); 584*81ad6265SDimitry Andric 585*81ad6265SDimitry Andric // Build the selector part. 586*81ad6265SDimitry Andric Selector Selector = Method->getSelector(); 587*81ad6265SDimitry Andric if (Selector.getNumArgs() == 0) 588*81ad6265SDimitry Andric // For Objective-C methods that don't take arguments, the first (and only) 589*81ad6265SDimitry Andric // slot of the selector is the method name. 590*81ad6265SDimitry Andric Fragments.appendSpace().append( 591*81ad6265SDimitry Andric Selector.getNameForSlot(0), 592*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 593*81ad6265SDimitry Andric 594*81ad6265SDimitry Andric // For Objective-C methods that take arguments, build the selector slots. 595*81ad6265SDimitry Andric for (unsigned i = 0, end = Method->param_size(); i != end; ++i) { 596*81ad6265SDimitry Andric // Objective-C method selector parts are considered as identifiers instead 597*81ad6265SDimitry Andric // of "external parameters" as in Swift. This is because Objective-C method 598*81ad6265SDimitry Andric // symbols are referenced with the entire selector, instead of just the 599*81ad6265SDimitry Andric // method name in Swift. 600*81ad6265SDimitry Andric SmallString<32> ParamID(Selector.getNameForSlot(i)); 601*81ad6265SDimitry Andric ParamID.append(":"); 602*81ad6265SDimitry Andric Fragments.appendSpace().append( 603*81ad6265SDimitry Andric ParamID, DeclarationFragments::FragmentKind::Identifier); 604*81ad6265SDimitry Andric 605*81ad6265SDimitry Andric // Build the internal parameter. 606*81ad6265SDimitry Andric const ParmVarDecl *Param = Method->getParamDecl(i); 607*81ad6265SDimitry Andric Fragments.append(getFragmentsForParam(Param)); 608*81ad6265SDimitry Andric } 609*81ad6265SDimitry Andric 610*81ad6265SDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 611*81ad6265SDimitry Andric } 612*81ad6265SDimitry Andric 613*81ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty( 614*81ad6265SDimitry Andric const ObjCPropertyDecl *Property) { 615*81ad6265SDimitry Andric DeclarationFragments Fragments, After; 616*81ad6265SDimitry Andric 617*81ad6265SDimitry Andric // Build the Objective-C property keyword. 618*81ad6265SDimitry Andric Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword); 619*81ad6265SDimitry Andric 620*81ad6265SDimitry Andric const auto Attributes = Property->getPropertyAttributes(); 621*81ad6265SDimitry Andric // Build the attributes if there is any associated with the property. 622*81ad6265SDimitry Andric if (Attributes != ObjCPropertyAttribute::kind_noattr) { 623*81ad6265SDimitry Andric // No leading comma for the first attribute. 624*81ad6265SDimitry Andric bool First = true; 625*81ad6265SDimitry Andric Fragments.append(" (", DeclarationFragments::FragmentKind::Text); 626*81ad6265SDimitry Andric // Helper function to render the attribute. 627*81ad6265SDimitry Andric auto RenderAttribute = 628*81ad6265SDimitry Andric [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling, 629*81ad6265SDimitry Andric StringRef Arg = "", 630*81ad6265SDimitry Andric DeclarationFragments::FragmentKind ArgKind = 631*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier) { 632*81ad6265SDimitry Andric // Check if the `Kind` attribute is set for this property. 633*81ad6265SDimitry Andric if ((Attributes & Kind) && !Spelling.empty()) { 634*81ad6265SDimitry Andric // Add a leading comma if this is not the first attribute rendered. 635*81ad6265SDimitry Andric if (!First) 636*81ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 637*81ad6265SDimitry Andric // Render the spelling of this attribute `Kind` as a keyword. 638*81ad6265SDimitry Andric Fragments.append(Spelling, 639*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword); 640*81ad6265SDimitry Andric // If this attribute takes in arguments (e.g. `getter=getterName`), 641*81ad6265SDimitry Andric // render the arguments. 642*81ad6265SDimitry Andric if (!Arg.empty()) 643*81ad6265SDimitry Andric Fragments.append("=", DeclarationFragments::FragmentKind::Text) 644*81ad6265SDimitry Andric .append(Arg, ArgKind); 645*81ad6265SDimitry Andric First = false; 646*81ad6265SDimitry Andric } 647*81ad6265SDimitry Andric }; 648*81ad6265SDimitry Andric 649*81ad6265SDimitry Andric // Go through all possible Objective-C property attributes and render set 650*81ad6265SDimitry Andric // ones. 651*81ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_class, "class"); 652*81ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct"); 653*81ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic"); 654*81ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic"); 655*81ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign"); 656*81ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain"); 657*81ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong"); 658*81ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy"); 659*81ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak"); 660*81ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained, 661*81ad6265SDimitry Andric "unsafe_unretained"); 662*81ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite"); 663*81ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly"); 664*81ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter", 665*81ad6265SDimitry Andric Property->getGetterName().getAsString()); 666*81ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter", 667*81ad6265SDimitry Andric Property->getSetterName().getAsString()); 668*81ad6265SDimitry Andric 669*81ad6265SDimitry Andric // Render nullability attributes. 670*81ad6265SDimitry Andric if (Attributes & ObjCPropertyAttribute::kind_nullability) { 671*81ad6265SDimitry Andric QualType Type = Property->getType(); 672*81ad6265SDimitry Andric if (const auto Nullability = 673*81ad6265SDimitry Andric AttributedType::stripOuterNullability(Type)) { 674*81ad6265SDimitry Andric if (!First) 675*81ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 676*81ad6265SDimitry Andric if (*Nullability == NullabilityKind::Unspecified && 677*81ad6265SDimitry Andric (Attributes & ObjCPropertyAttribute::kind_null_resettable)) 678*81ad6265SDimitry Andric Fragments.append("null_resettable", 679*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword); 680*81ad6265SDimitry Andric else 681*81ad6265SDimitry Andric Fragments.append( 682*81ad6265SDimitry Andric getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true), 683*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword); 684*81ad6265SDimitry Andric First = false; 685*81ad6265SDimitry Andric } 686*81ad6265SDimitry Andric } 687*81ad6265SDimitry Andric 688*81ad6265SDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 689*81ad6265SDimitry Andric } 690*81ad6265SDimitry Andric 691*81ad6265SDimitry Andric // Build the property type and name, and return the completed fragments. 692*81ad6265SDimitry Andric return Fragments.appendSpace() 693*81ad6265SDimitry Andric .append(getFragmentsForType(Property->getType(), 694*81ad6265SDimitry Andric Property->getASTContext(), After)) 695*81ad6265SDimitry Andric .append(Property->getName(), 696*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier) 697*81ad6265SDimitry Andric .append(std::move(After)); 698*81ad6265SDimitry Andric } 699*81ad6265SDimitry Andric 700*81ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol( 701*81ad6265SDimitry Andric const ObjCProtocolDecl *Protocol) { 702*81ad6265SDimitry Andric DeclarationFragments Fragments; 703*81ad6265SDimitry Andric // Build basic protocol declaration. 704*81ad6265SDimitry Andric Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword) 705*81ad6265SDimitry Andric .appendSpace() 706*81ad6265SDimitry Andric .append(Protocol->getName(), 707*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 708*81ad6265SDimitry Andric 709*81ad6265SDimitry Andric // If this protocol conforms to other protocols, build the conformance list. 710*81ad6265SDimitry Andric if (!Protocol->protocols().empty()) { 711*81ad6265SDimitry Andric Fragments.append(" <", DeclarationFragments::FragmentKind::Text); 712*81ad6265SDimitry Andric for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin(); 713*81ad6265SDimitry Andric It != Protocol->protocol_end(); It++) { 714*81ad6265SDimitry Andric // Add a leading comma if this is not the first protocol rendered. 715*81ad6265SDimitry Andric if (It != Protocol->protocol_begin()) 716*81ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 717*81ad6265SDimitry Andric 718*81ad6265SDimitry Andric SmallString<128> USR; 719*81ad6265SDimitry Andric index::generateUSRForDecl(*It, USR); 720*81ad6265SDimitry Andric Fragments.append((*It)->getName(), 721*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, USR); 722*81ad6265SDimitry Andric } 723*81ad6265SDimitry Andric Fragments.append(">", DeclarationFragments::FragmentKind::Text); 724*81ad6265SDimitry Andric } 725*81ad6265SDimitry Andric 726*81ad6265SDimitry Andric return Fragments; 727*81ad6265SDimitry Andric } 728*81ad6265SDimitry Andric 729*81ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef( 730*81ad6265SDimitry Andric const TypedefNameDecl *Decl) { 731*81ad6265SDimitry Andric DeclarationFragments Fragments, After; 732*81ad6265SDimitry Andric Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword) 733*81ad6265SDimitry Andric .appendSpace() 734*81ad6265SDimitry Andric .append(getFragmentsForType(Decl->getUnderlyingType(), 735*81ad6265SDimitry Andric Decl->getASTContext(), After)) 736*81ad6265SDimitry Andric .append(std::move(After)) 737*81ad6265SDimitry Andric .appendSpace() 738*81ad6265SDimitry Andric .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier); 739*81ad6265SDimitry Andric 740*81ad6265SDimitry Andric return Fragments; 741*81ad6265SDimitry Andric } 742*81ad6265SDimitry Andric 743*81ad6265SDimitry Andric template <typename FunctionT> 744*81ad6265SDimitry Andric FunctionSignature 745*81ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) { 746*81ad6265SDimitry Andric FunctionSignature Signature; 747*81ad6265SDimitry Andric 748*81ad6265SDimitry Andric DeclarationFragments ReturnType, After; 749*81ad6265SDimitry Andric ReturnType 750*81ad6265SDimitry Andric .append(getFragmentsForType(Function->getReturnType(), 751*81ad6265SDimitry Andric Function->getASTContext(), After)) 752*81ad6265SDimitry Andric .append(std::move(After)); 753*81ad6265SDimitry Andric Signature.setReturnType(ReturnType); 754*81ad6265SDimitry Andric 755*81ad6265SDimitry Andric for (const auto *Param : Function->parameters()) 756*81ad6265SDimitry Andric Signature.addParameter(Param->getName(), getFragmentsForParam(Param)); 757*81ad6265SDimitry Andric 758*81ad6265SDimitry Andric return Signature; 759*81ad6265SDimitry Andric } 760*81ad6265SDimitry Andric 761*81ad6265SDimitry Andric // Instantiate template for FunctionDecl. 762*81ad6265SDimitry Andric template FunctionSignature 763*81ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *); 764*81ad6265SDimitry Andric 765*81ad6265SDimitry Andric // Instantiate template for ObjCMethodDecl. 766*81ad6265SDimitry Andric template FunctionSignature 767*81ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *); 768*81ad6265SDimitry Andric 769*81ad6265SDimitry Andric // Subheading of a symbol defaults to its name. 770*81ad6265SDimitry Andric DeclarationFragments 771*81ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) { 772*81ad6265SDimitry Andric DeclarationFragments Fragments; 773*81ad6265SDimitry Andric if (!Decl->getName().empty()) 774*81ad6265SDimitry Andric Fragments.append(Decl->getName(), 775*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 776*81ad6265SDimitry Andric return Fragments; 777*81ad6265SDimitry Andric } 778*81ad6265SDimitry Andric 779*81ad6265SDimitry Andric // Subheading of an Objective-C method is a `+` or `-` sign indicating whether 780*81ad6265SDimitry Andric // it's a class method or an instance method, followed by the selector name. 781*81ad6265SDimitry Andric DeclarationFragments 782*81ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) { 783*81ad6265SDimitry Andric DeclarationFragments Fragments; 784*81ad6265SDimitry Andric if (Method->isClassMethod()) 785*81ad6265SDimitry Andric Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); 786*81ad6265SDimitry Andric else if (Method->isInstanceMethod()) 787*81ad6265SDimitry Andric Fragments.append("- ", DeclarationFragments::FragmentKind::Text); 788*81ad6265SDimitry Andric 789*81ad6265SDimitry Andric return Fragments.append(Method->getNameAsString(), 790*81ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 791*81ad6265SDimitry Andric } 792*81ad6265SDimitry Andric 793*81ad6265SDimitry Andric // Subheading of a symbol defaults to its name. 794*81ad6265SDimitry Andric DeclarationFragments 795*81ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) { 796*81ad6265SDimitry Andric DeclarationFragments Fragments; 797*81ad6265SDimitry Andric Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); 798*81ad6265SDimitry Andric return Fragments; 799*81ad6265SDimitry Andric } 800