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