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