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