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/AST/Decl.h" 16 #include "clang/AST/DeclCXX.h" 17 #include "clang/AST/QualTypeNames.h" 18 #include "clang/Basic/OperatorKinds.h" 19 #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h" 20 #include "clang/Index/USRGeneration.h" 21 #include "llvm/ADT/StringSwitch.h" 22 #include <typeinfo> 23 24 using namespace clang::extractapi; 25 using namespace llvm; 26 27 DeclarationFragments &DeclarationFragments::appendSpace() { 28 if (!Fragments.empty()) { 29 Fragment &Last = Fragments.back(); 30 if (Last.Kind == FragmentKind::Text) { 31 // Merge the extra space into the last fragment if the last fragment is 32 // also text. 33 if (Last.Spelling.back() != ' ') { // avoid extra trailing spaces. 34 Last.Spelling.push_back(' '); 35 } 36 } else { 37 append(" ", FragmentKind::Text); 38 } 39 } 40 41 return *this; 42 } 43 44 StringRef DeclarationFragments::getFragmentKindString( 45 DeclarationFragments::FragmentKind Kind) { 46 switch (Kind) { 47 case DeclarationFragments::FragmentKind::None: 48 return "none"; 49 case DeclarationFragments::FragmentKind::Keyword: 50 return "keyword"; 51 case DeclarationFragments::FragmentKind::Attribute: 52 return "attribute"; 53 case DeclarationFragments::FragmentKind::NumberLiteral: 54 return "number"; 55 case DeclarationFragments::FragmentKind::StringLiteral: 56 return "string"; 57 case DeclarationFragments::FragmentKind::Identifier: 58 return "identifier"; 59 case DeclarationFragments::FragmentKind::TypeIdentifier: 60 return "typeIdentifier"; 61 case DeclarationFragments::FragmentKind::GenericParameter: 62 return "genericParameter"; 63 case DeclarationFragments::FragmentKind::ExternalParam: 64 return "externalParam"; 65 case DeclarationFragments::FragmentKind::InternalParam: 66 return "internalParam"; 67 case DeclarationFragments::FragmentKind::Text: 68 return "text"; 69 } 70 71 llvm_unreachable("Unhandled FragmentKind"); 72 } 73 74 DeclarationFragments::FragmentKind 75 DeclarationFragments::parseFragmentKindFromString(StringRef S) { 76 return llvm::StringSwitch<FragmentKind>(S) 77 .Case("keyword", DeclarationFragments::FragmentKind::Keyword) 78 .Case("attribute", DeclarationFragments::FragmentKind::Attribute) 79 .Case("number", DeclarationFragments::FragmentKind::NumberLiteral) 80 .Case("string", DeclarationFragments::FragmentKind::StringLiteral) 81 .Case("identifier", DeclarationFragments::FragmentKind::Identifier) 82 .Case("typeIdentifier", 83 DeclarationFragments::FragmentKind::TypeIdentifier) 84 .Case("genericParameter", 85 DeclarationFragments::FragmentKind::GenericParameter) 86 .Case("internalParam", DeclarationFragments::FragmentKind::InternalParam) 87 .Case("externalParam", DeclarationFragments::FragmentKind::ExternalParam) 88 .Case("text", DeclarationFragments::FragmentKind::Text) 89 .Default(DeclarationFragments::FragmentKind::None); 90 } 91 92 DeclarationFragments DeclarationFragments::getExceptionSpecificationString( 93 ExceptionSpecificationType ExceptionSpec) { 94 DeclarationFragments Fragments; 95 switch (ExceptionSpec) { 96 case ExceptionSpecificationType::EST_None: 97 return Fragments; 98 case ExceptionSpecificationType::EST_DynamicNone: 99 return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) 100 .append("throw", DeclarationFragments::FragmentKind::Keyword) 101 .append("(", DeclarationFragments::FragmentKind::Text) 102 .append(")", DeclarationFragments::FragmentKind::Text); 103 case ExceptionSpecificationType::EST_Dynamic: 104 // FIXME: throw(int), get types of inner expression 105 return Fragments; 106 case ExceptionSpecificationType::EST_BasicNoexcept: 107 return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) 108 .append("noexcept", DeclarationFragments::FragmentKind::Keyword); 109 case ExceptionSpecificationType::EST_DependentNoexcept: 110 // FIXME: throw(conditional-expression), get expression 111 break; 112 case ExceptionSpecificationType::EST_NoexceptFalse: 113 return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) 114 .append("noexcept", DeclarationFragments::FragmentKind::Keyword) 115 .append("(", DeclarationFragments::FragmentKind::Text) 116 .append("false", DeclarationFragments::FragmentKind::Keyword) 117 .append(")", DeclarationFragments::FragmentKind::Text); 118 case ExceptionSpecificationType::EST_NoexceptTrue: 119 return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) 120 .append("noexcept", DeclarationFragments::FragmentKind::Keyword) 121 .append("(", DeclarationFragments::FragmentKind::Text) 122 .append("true", DeclarationFragments::FragmentKind::Keyword) 123 .append(")", DeclarationFragments::FragmentKind::Text); 124 default: 125 return Fragments; 126 } 127 128 llvm_unreachable("Unhandled exception specification"); 129 } 130 131 DeclarationFragments 132 DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) { 133 DeclarationFragments Fragments; 134 if (Record->isStruct()) 135 Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword); 136 else if (Record->isUnion()) 137 Fragments.append("union", DeclarationFragments::FragmentKind::Keyword); 138 else 139 Fragments.append("class", DeclarationFragments::FragmentKind::Keyword); 140 141 return Fragments; 142 } 143 144 // NNS stores C++ nested name specifiers, which are prefixes to qualified names. 145 // Build declaration fragments for NNS recursively so that we have the USR for 146 // every part in a qualified name, and also leaves the actual underlying type 147 // cleaner for its own fragment. 148 DeclarationFragments 149 DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS, 150 ASTContext &Context, 151 DeclarationFragments &After) { 152 DeclarationFragments Fragments; 153 if (NNS->getPrefix()) 154 Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After)); 155 156 switch (NNS->getKind()) { 157 case NestedNameSpecifier::Identifier: 158 Fragments.append(NNS->getAsIdentifier()->getName(), 159 DeclarationFragments::FragmentKind::Identifier); 160 break; 161 162 case NestedNameSpecifier::Namespace: { 163 const NamespaceDecl *NS = NNS->getAsNamespace(); 164 if (NS->isAnonymousNamespace()) 165 return Fragments; 166 SmallString<128> USR; 167 index::generateUSRForDecl(NS, USR); 168 Fragments.append(NS->getName(), 169 DeclarationFragments::FragmentKind::Identifier, USR, NS); 170 break; 171 } 172 173 case NestedNameSpecifier::NamespaceAlias: { 174 const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias(); 175 SmallString<128> USR; 176 index::generateUSRForDecl(Alias, USR); 177 Fragments.append(Alias->getName(), 178 DeclarationFragments::FragmentKind::Identifier, USR, 179 Alias); 180 break; 181 } 182 183 case NestedNameSpecifier::Global: 184 // The global specifier `::` at the beginning. No stored value. 185 break; 186 187 case NestedNameSpecifier::Super: 188 // Microsoft's `__super` specifier. 189 Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword); 190 break; 191 192 case NestedNameSpecifier::TypeSpecWithTemplate: 193 // A type prefixed by the `template` keyword. 194 Fragments.append("template", DeclarationFragments::FragmentKind::Keyword); 195 Fragments.appendSpace(); 196 // Fallthrough after adding the keyword to handle the actual type. 197 [[fallthrough]]; 198 199 case NestedNameSpecifier::TypeSpec: { 200 const Type *T = NNS->getAsType(); 201 // FIXME: Handle C++ template specialization type 202 Fragments.append(getFragmentsForType(T, Context, After)); 203 break; 204 } 205 } 206 207 // Add the separator text `::` for this segment. 208 return Fragments.append("::", DeclarationFragments::FragmentKind::Text); 209 } 210 211 // Recursively build the declaration fragments for an underlying `Type` with 212 // qualifiers removed. 213 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( 214 const Type *T, ASTContext &Context, DeclarationFragments &After) { 215 assert(T && "invalid type"); 216 217 DeclarationFragments Fragments; 218 219 // Declaration fragments of a pointer type is the declaration fragments of 220 // the pointee type followed by a `*`, 221 if (T->isPointerType()) 222 return Fragments 223 .append(getFragmentsForType(T->getPointeeType(), Context, After)) 224 .append(" *", DeclarationFragments::FragmentKind::Text); 225 226 // For Objective-C `id` and `Class` pointers 227 // we do not spell out the `*`. 228 if (T->isObjCObjectPointerType() && 229 !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) { 230 231 Fragments.append(getFragmentsForType(T->getPointeeType(), Context, After)); 232 233 // id<protocol> is an qualified id type 234 // id<protocol>* is not an qualified id type 235 if (!T->getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) { 236 Fragments.append(" *", DeclarationFragments::FragmentKind::Text); 237 } 238 239 return Fragments; 240 } 241 242 // Declaration fragments of a lvalue reference type is the declaration 243 // fragments of the underlying type followed by a `&`. 244 if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T)) 245 return Fragments 246 .append( 247 getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After)) 248 .append(" &", DeclarationFragments::FragmentKind::Text); 249 250 // Declaration fragments of a rvalue reference type is the declaration 251 // fragments of the underlying type followed by a `&&`. 252 if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T)) 253 return Fragments 254 .append( 255 getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After)) 256 .append(" &&", DeclarationFragments::FragmentKind::Text); 257 258 // Declaration fragments of an array-typed variable have two parts: 259 // 1. the element type of the array that appears before the variable name; 260 // 2. array brackets `[(0-9)?]` that appear after the variable name. 261 if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) { 262 // Build the "after" part first because the inner element type might also 263 // be an array-type. For example `int matrix[3][4]` which has a type of 264 // "(array 3 of (array 4 of ints))." 265 // Push the array size part first to make sure they are in the right order. 266 After.append("[", DeclarationFragments::FragmentKind::Text); 267 268 switch (AT->getSizeModifier()) { 269 case ArrayType::Normal: 270 break; 271 case ArrayType::Static: 272 Fragments.append("static", DeclarationFragments::FragmentKind::Keyword); 273 break; 274 case ArrayType::Star: 275 Fragments.append("*", DeclarationFragments::FragmentKind::Text); 276 break; 277 } 278 279 if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) { 280 // FIXME: right now this would evaluate any expressions/macros written in 281 // the original source to concrete values. For example 282 // `int nums[MAX]` -> `int nums[100]` 283 // `char *str[5 + 1]` -> `char *str[6]` 284 SmallString<128> Size; 285 CAT->getSize().toStringUnsigned(Size); 286 After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral); 287 } 288 289 After.append("]", DeclarationFragments::FragmentKind::Text); 290 291 return Fragments.append( 292 getFragmentsForType(AT->getElementType(), Context, After)); 293 } 294 295 // An ElaboratedType is a sugar for types that are referred to using an 296 // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a 297 // qualified name, e.g., `N::M::type`, or both. 298 if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) { 299 ElaboratedTypeKeyword Keyword = ET->getKeyword(); 300 if (Keyword != ETK_None) { 301 Fragments 302 .append(ElaboratedType::getKeywordName(Keyword), 303 DeclarationFragments::FragmentKind::Keyword) 304 .appendSpace(); 305 } 306 307 if (const NestedNameSpecifier *NNS = ET->getQualifier()) 308 Fragments.append(getFragmentsForNNS(NNS, Context, After)); 309 310 // After handling the elaborated keyword or qualified name, build 311 // declaration fragments for the desugared underlying type. 312 return Fragments.append(getFragmentsForType(ET->desugar(), Context, After)); 313 } 314 315 // If the type is a typedefed type, get the underlying TypedefNameDecl for a 316 // direct reference to the typedef instead of the wrapped type. 317 318 // 'id' type is a typedef for an ObjCObjectPointerType 319 // we treat it as a typedef 320 if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) { 321 const TypedefNameDecl *Decl = TypedefTy->getDecl(); 322 TypedefUnderlyingTypeResolver TypedefResolver(Context); 323 std::string USR = TypedefResolver.getUSRForType(QualType(T, 0)); 324 325 if (T->isObjCIdType()) { 326 return Fragments.append(Decl->getName(), 327 DeclarationFragments::FragmentKind::Keyword); 328 } 329 330 return Fragments.append( 331 Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier, 332 USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0))); 333 } 334 335 // Everything we care about has been handled now, reduce to the canonical 336 // unqualified base type. 337 QualType Base = T->getCanonicalTypeUnqualified(); 338 339 // If the base type is a TagType (struct/interface/union/class/enum), let's 340 // get the underlying Decl for better names and USRs. 341 if (const TagType *TagTy = dyn_cast<TagType>(Base)) { 342 const TagDecl *Decl = TagTy->getDecl(); 343 // Anonymous decl, skip this fragment. 344 if (Decl->getName().empty()) 345 return Fragments; 346 SmallString<128> TagUSR; 347 clang::index::generateUSRForDecl(Decl, TagUSR); 348 return Fragments.append(Decl->getName(), 349 DeclarationFragments::FragmentKind::TypeIdentifier, 350 TagUSR, Decl); 351 } 352 353 // If the base type is an ObjCInterfaceType, use the underlying 354 // ObjCInterfaceDecl for the true USR. 355 if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) { 356 const auto *Decl = ObjCIT->getDecl(); 357 SmallString<128> USR; 358 index::generateUSRForDecl(Decl, USR); 359 return Fragments.append(Decl->getName(), 360 DeclarationFragments::FragmentKind::TypeIdentifier, 361 USR, Decl); 362 } 363 364 // Default fragment builder for other kinds of types (BuiltinType etc.) 365 SmallString<128> USR; 366 clang::index::generateUSRForType(Base, Context, USR); 367 Fragments.append(Base.getAsString(), 368 DeclarationFragments::FragmentKind::TypeIdentifier, USR); 369 370 return Fragments; 371 } 372 373 DeclarationFragments 374 DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) { 375 DeclarationFragments Fragments; 376 if (Quals.hasConst()) 377 Fragments.append("const", DeclarationFragments::FragmentKind::Keyword); 378 if (Quals.hasVolatile()) 379 Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword); 380 if (Quals.hasRestrict()) 381 Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword); 382 383 return Fragments; 384 } 385 386 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( 387 const QualType QT, ASTContext &Context, DeclarationFragments &After) { 388 assert(!QT.isNull() && "invalid type"); 389 390 if (const ParenType *PT = dyn_cast<ParenType>(QT)) { 391 After.append(")", DeclarationFragments::FragmentKind::Text); 392 return getFragmentsForType(PT->getInnerType(), Context, After) 393 .append("(", DeclarationFragments::FragmentKind::Text); 394 } 395 396 const SplitQualType SQT = QT.split(); 397 DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals), 398 TypeFragments = 399 getFragmentsForType(SQT.Ty, Context, After); 400 if (QualsFragments.getFragments().empty()) 401 return TypeFragments; 402 403 // Use east qualifier for pointer types 404 // For example: 405 // ``` 406 // int * const 407 // ^---- ^---- 408 // type qualifier 409 // ^----------------- 410 // const pointer to int 411 // ``` 412 // should not be reconstructed as 413 // ``` 414 // const int * 415 // ^---- ^-- 416 // qualifier type 417 // ^---------------- ^ 418 // pointer to const int 419 // ``` 420 if (SQT.Ty->isAnyPointerType()) 421 return TypeFragments.appendSpace().append(std::move(QualsFragments)); 422 423 return QualsFragments.appendSpace().append(std::move(TypeFragments)); 424 } 425 426 DeclarationFragments 427 DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) { 428 DeclarationFragments Fragments; 429 if (Var->isConstexpr()) 430 Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 431 .appendSpace(); 432 433 StorageClass SC = Var->getStorageClass(); 434 if (SC != SC_None) 435 Fragments 436 .append(VarDecl::getStorageClassSpecifierString(SC), 437 DeclarationFragments::FragmentKind::Keyword) 438 .appendSpace(); 439 QualType T = 440 Var->getTypeSourceInfo() 441 ? Var->getTypeSourceInfo()->getType() 442 : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType()); 443 444 // Capture potential fragments that needs to be placed after the variable name 445 // ``` 446 // int nums[5]; 447 // char (*ptr_to_array)[6]; 448 // ``` 449 DeclarationFragments After; 450 return Fragments.append(getFragmentsForType(T, Var->getASTContext(), After)) 451 .appendSpace() 452 .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) 453 .append(std::move(After)) 454 .append(";", DeclarationFragments::FragmentKind::Text); 455 } 456 457 DeclarationFragments 458 DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) { 459 DeclarationFragments Fragments; 460 if (Var->isConstexpr()) 461 Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 462 .appendSpace(); 463 QualType T = 464 Var->getTypeSourceInfo() 465 ? Var->getTypeSourceInfo()->getType() 466 : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType()); 467 468 // Might be a member, so might be static. 469 if (Var->isStaticDataMember()) 470 Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) 471 .appendSpace(); 472 473 DeclarationFragments After; 474 DeclarationFragments ArgumentFragment = 475 getFragmentsForType(T, Var->getASTContext(), After); 476 if (ArgumentFragment.begin()->Spelling.substr(0, 14).compare( 477 "type-parameter") == 0) { 478 std::string ProperArgName = getNameForTemplateArgument( 479 Var->getDescribedVarTemplate()->getTemplateParameters()->asArray(), 480 ArgumentFragment.begin()->Spelling); 481 ArgumentFragment.begin()->Spelling.swap(ProperArgName); 482 } 483 Fragments.append(std::move(ArgumentFragment)) 484 .appendSpace() 485 .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) 486 .append(";", DeclarationFragments::FragmentKind::Text); 487 return Fragments; 488 } 489 490 DeclarationFragments 491 DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) { 492 DeclarationFragments Fragments, After; 493 494 QualType T = Param->getTypeSourceInfo() 495 ? Param->getTypeSourceInfo()->getType() 496 : Param->getASTContext().getUnqualifiedObjCPointerType( 497 Param->getType()); 498 499 DeclarationFragments TypeFragments = 500 getFragmentsForType(T, Param->getASTContext(), After); 501 if (TypeFragments.begin()->Spelling.substr(0, 14).compare("type-parameter") == 502 0) { 503 std::string ProperArgName = getNameForTemplateArgument( 504 dyn_cast<FunctionDecl>(Param->getDeclContext()) 505 ->getDescribedFunctionTemplate() 506 ->getTemplateParameters() 507 ->asArray(), 508 TypeFragments.begin()->Spelling); 509 TypeFragments.begin()->Spelling.swap(ProperArgName); 510 } 511 512 if (Param->isObjCMethodParameter()) 513 Fragments.append("(", DeclarationFragments::FragmentKind::Text) 514 .append(std::move(TypeFragments)) 515 .append(") ", DeclarationFragments::FragmentKind::Text); 516 else 517 Fragments.append(std::move(TypeFragments)).appendSpace(); 518 519 return Fragments 520 .append(Param->getName(), 521 DeclarationFragments::FragmentKind::InternalParam) 522 .append(std::move(After)); 523 } 524 525 DeclarationFragments 526 DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) { 527 DeclarationFragments Fragments; 528 // FIXME: Handle template specialization 529 switch (Func->getStorageClass()) { 530 case SC_None: 531 case SC_PrivateExtern: 532 break; 533 case SC_Extern: 534 Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword) 535 .appendSpace(); 536 break; 537 case SC_Static: 538 Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) 539 .appendSpace(); 540 break; 541 case SC_Auto: 542 case SC_Register: 543 llvm_unreachable("invalid for functions"); 544 } 545 if (Func->isConsteval()) // if consteval, it is also constexpr 546 Fragments.append("consteval", DeclarationFragments::FragmentKind::Keyword) 547 .appendSpace(); 548 else if (Func->isConstexpr()) 549 Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 550 .appendSpace(); 551 552 // FIXME: Is `after` actually needed here? 553 DeclarationFragments After; 554 auto ReturnValueFragment = 555 getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After); 556 if (ReturnValueFragment.begin()->Spelling.substr(0, 14).compare( 557 "type-parameter") == 0) { 558 std::string ProperArgName = 559 getNameForTemplateArgument(Func->getDescribedFunctionTemplate() 560 ->getTemplateParameters() 561 ->asArray(), 562 ReturnValueFragment.begin()->Spelling); 563 ReturnValueFragment.begin()->Spelling.swap(ProperArgName); 564 } 565 566 Fragments.append(std::move(ReturnValueFragment)) 567 .appendSpace() 568 .append(Func->getName(), DeclarationFragments::FragmentKind::Identifier); 569 570 if (Func->getTemplateSpecializationInfo()) { 571 Fragments.append("<", DeclarationFragments::FragmentKind::Text); 572 573 for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) { 574 if (i) 575 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 576 Fragments.append( 577 getFragmentsForType(Func->getParamDecl(i)->getType(), 578 Func->getParamDecl(i)->getASTContext(), After)); 579 } 580 Fragments.append(">", DeclarationFragments::FragmentKind::Text); 581 } 582 Fragments.append(std::move(After)); 583 584 Fragments.append("(", DeclarationFragments::FragmentKind::Text); 585 for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) { 586 if (i) 587 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 588 Fragments.append(getFragmentsForParam(Func->getParamDecl(i))); 589 } 590 Fragments.append(")", DeclarationFragments::FragmentKind::Text); 591 592 Fragments.append(DeclarationFragments::getExceptionSpecificationString( 593 Func->getExceptionSpecType())); 594 595 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 596 } 597 598 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant( 599 const EnumConstantDecl *EnumConstDecl) { 600 DeclarationFragments Fragments; 601 return Fragments.append(EnumConstDecl->getName(), 602 DeclarationFragments::FragmentKind::Identifier); 603 } 604 605 DeclarationFragments 606 DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) { 607 if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl()) 608 return getFragmentsForTypedef(TypedefNameDecl); 609 610 DeclarationFragments Fragments, After; 611 Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword); 612 613 if (!EnumDecl->getName().empty()) 614 Fragments.appendSpace().append( 615 EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier); 616 617 QualType IntegerType = EnumDecl->getIntegerType(); 618 if (!IntegerType.isNull()) 619 Fragments.append(": ", DeclarationFragments::FragmentKind::Text) 620 .append( 621 getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After)) 622 .append(std::move(After)); 623 624 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 625 } 626 627 DeclarationFragments 628 DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) { 629 DeclarationFragments After; 630 DeclarationFragments Fragments; 631 if (Field->isMutable()) 632 Fragments.append("mutable", DeclarationFragments::FragmentKind::Keyword) 633 .appendSpace(); 634 return Fragments 635 .append( 636 getFragmentsForType(Field->getType(), Field->getASTContext(), After)) 637 .appendSpace() 638 .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier) 639 .append(std::move(After)) 640 .append(";", DeclarationFragments::FragmentKind::Text); 641 } 642 643 DeclarationFragments 644 DeclarationFragmentsBuilder::getFragmentsForStruct(const RecordDecl *Record) { 645 if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl()) 646 return getFragmentsForTypedef(TypedefNameDecl); 647 648 DeclarationFragments Fragments; 649 Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword); 650 651 if (!Record->getName().empty()) 652 Fragments.appendSpace().append( 653 Record->getName(), DeclarationFragments::FragmentKind::Identifier); 654 655 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 656 } 657 658 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass( 659 const CXXRecordDecl *Record) { 660 if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl()) 661 return getFragmentsForTypedef(TypedefNameDecl); 662 663 DeclarationFragments Fragments; 664 Fragments.append(DeclarationFragments::getStructureTypeFragment(Record)); 665 666 if (!Record->getName().empty()) 667 Fragments.appendSpace().append( 668 Record->getName(), DeclarationFragments::FragmentKind::Identifier); 669 670 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 671 } 672 673 DeclarationFragments 674 DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod( 675 const CXXMethodDecl *Method) { 676 DeclarationFragments Fragments; 677 std::string Name; 678 if (isa<CXXConstructorDecl>(Method)) { 679 Name = Method->getNameAsString(); 680 if (dyn_cast<CXXConstructorDecl>(Method)->isExplicit()) 681 Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword) 682 .appendSpace(); 683 } else if (isa<CXXDestructorDecl>(Method)) 684 Name = Method->getNameAsString(); 685 686 DeclarationFragments After; 687 Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier) 688 .append(std::move(After)); 689 Fragments.append("(", DeclarationFragments::FragmentKind::Text); 690 for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) { 691 if (i) 692 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 693 Fragments.append(getFragmentsForParam(Method->getParamDecl(i))); 694 } 695 Fragments.append(")", DeclarationFragments::FragmentKind::Text); 696 697 Fragments.append(DeclarationFragments::getExceptionSpecificationString( 698 Method->getExceptionSpecType())); 699 700 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 701 } 702 703 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod( 704 const CXXMethodDecl *Method) { 705 DeclarationFragments Fragments; 706 StringRef Name = Method->getName(); 707 if (Method->isStatic()) 708 Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) 709 .appendSpace(); 710 if (Method->isConstexpr()) 711 Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 712 .appendSpace(); 713 if (Method->isVolatile()) 714 Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword) 715 .appendSpace(); 716 717 // Build return type 718 DeclarationFragments After; 719 Fragments 720 .append(getFragmentsForType(Method->getReturnType(), 721 Method->getASTContext(), After)) 722 .appendSpace() 723 .append(Name, DeclarationFragments::FragmentKind::Identifier) 724 .append(std::move(After)); 725 Fragments.append("(", DeclarationFragments::FragmentKind::Text); 726 for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) { 727 if (i) 728 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 729 Fragments.append(getFragmentsForParam(Method->getParamDecl(i))); 730 } 731 Fragments.append(")", DeclarationFragments::FragmentKind::Text); 732 733 if (Method->isConst()) 734 Fragments.appendSpace().append("const", 735 DeclarationFragments::FragmentKind::Keyword); 736 737 Fragments.append(DeclarationFragments::getExceptionSpecificationString( 738 Method->getExceptionSpecType())); 739 740 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 741 } 742 743 DeclarationFragments 744 DeclarationFragmentsBuilder::getFragmentsForConversionFunction( 745 const CXXConversionDecl *ConversionFunction) { 746 DeclarationFragments Fragments; 747 748 if (ConversionFunction->isExplicit()) 749 Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword) 750 .appendSpace(); 751 752 Fragments.append("operator", DeclarationFragments::FragmentKind::Keyword) 753 .appendSpace(); 754 755 Fragments 756 .append(ConversionFunction->getConversionType().getAsString(), 757 DeclarationFragments::FragmentKind::TypeIdentifier) 758 .append("(", DeclarationFragments::FragmentKind::Text); 759 for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end; 760 ++i) { 761 if (i) 762 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 763 Fragments.append(getFragmentsForParam(ConversionFunction->getParamDecl(i))); 764 } 765 Fragments.append(")", DeclarationFragments::FragmentKind::Text); 766 767 if (ConversionFunction->isConst()) 768 Fragments.appendSpace().append("const", 769 DeclarationFragments::FragmentKind::Keyword); 770 771 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 772 } 773 774 DeclarationFragments 775 DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator( 776 const CXXMethodDecl *Method) { 777 DeclarationFragments Fragments; 778 779 // Build return type 780 DeclarationFragments After; 781 Fragments 782 .append(getFragmentsForType(Method->getReturnType(), 783 Method->getASTContext(), After)) 784 .appendSpace() 785 .append(Method->getNameAsString(), 786 DeclarationFragments::FragmentKind::Identifier) 787 .append(std::move(After)); 788 Fragments.append("(", DeclarationFragments::FragmentKind::Text); 789 for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) { 790 if (i) 791 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 792 Fragments.append(getFragmentsForParam(Method->getParamDecl(i))); 793 } 794 Fragments.append(")", DeclarationFragments::FragmentKind::Text); 795 796 if (Method->isConst()) 797 Fragments.appendSpace().append("const", 798 DeclarationFragments::FragmentKind::Keyword); 799 800 Fragments.append(DeclarationFragments::getExceptionSpecificationString( 801 Method->getExceptionSpecType())); 802 803 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 804 } 805 806 // Get fragments for template parameters, e.g. T in tempalte<typename T> ... 807 DeclarationFragments 808 DeclarationFragmentsBuilder::getFragmentsForTemplateParameters( 809 ArrayRef<NamedDecl *> ParameterArray) { 810 DeclarationFragments Fragments; 811 for (unsigned i = 0, end = ParameterArray.size(); i != end; ++i) { 812 if (i) 813 Fragments.append(",", DeclarationFragments::FragmentKind::Text) 814 .appendSpace(); 815 816 const auto *TemplateParam = 817 dyn_cast<TemplateTypeParmDecl>(ParameterArray[i]); 818 if (!TemplateParam) 819 continue; 820 if (TemplateParam->hasTypeConstraint()) 821 Fragments.append(TemplateParam->getTypeConstraint() 822 ->getNamedConcept() 823 ->getName() 824 .str(), 825 DeclarationFragments::FragmentKind::TypeIdentifier); 826 else if (TemplateParam->wasDeclaredWithTypename()) 827 Fragments.append("typename", DeclarationFragments::FragmentKind::Keyword); 828 else 829 Fragments.append("class", DeclarationFragments::FragmentKind::Keyword); 830 831 if (TemplateParam->isParameterPack()) 832 Fragments.append("...", DeclarationFragments::FragmentKind::Text); 833 834 Fragments.appendSpace().append( 835 TemplateParam->getName(), 836 DeclarationFragments::FragmentKind::GenericParameter); 837 } 838 return Fragments; 839 } 840 841 // Find the name of a template argument from the template's parameters. 842 std::string DeclarationFragmentsBuilder::getNameForTemplateArgument( 843 const ArrayRef<NamedDecl *> TemplateParameters, std::string TypeParameter) { 844 // The arg is a generic parameter from a partial spec, e.g. 845 // T in template<typename T> Foo<T, int>. 846 // 847 // Those names appear as "type-parameter-<index>-<depth>", so we must find its 848 // name from the template's parameter list. 849 for (unsigned i = 0; i < TemplateParameters.size(); ++i) { 850 const auto *Parameter = 851 dyn_cast<TemplateTypeParmDecl>(TemplateParameters[i]); 852 if (TypeParameter.compare("type-parameter-" + 853 std::to_string(Parameter->getDepth()) + "-" + 854 std::to_string(Parameter->getIndex())) == 0) 855 return std::string(TemplateParameters[i]->getName()); 856 } 857 llvm_unreachable("Could not find the name of a template argument."); 858 } 859 860 // Get fragments for template arguments, e.g. int in template<typename T> 861 // Foo<int>; 862 // 863 // Note: TemplateParameters is only necessary if the Decl is a 864 // PartialSpecialization, where we need the parameters to deduce the name of the 865 // generic arguments. 866 DeclarationFragments 867 DeclarationFragmentsBuilder::getFragmentsForTemplateArguments( 868 const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context, 869 const std::optional<ArrayRef<NamedDecl *>> TemplateParameters) { 870 DeclarationFragments Fragments; 871 for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) { 872 if (i) 873 Fragments.append(",", DeclarationFragments::FragmentKind::Text) 874 .appendSpace(); 875 876 std::string Type = TemplateArguments[i].getAsType().getAsString(); 877 DeclarationFragments After; 878 DeclarationFragments ArgumentFragment = 879 getFragmentsForType(TemplateArguments[i].getAsType(), Context, After); 880 881 if (ArgumentFragment.begin()->Spelling.substr(0, 14).compare( 882 "type-parameter") == 0) { 883 std::string ProperArgName = getNameForTemplateArgument( 884 TemplateParameters.value(), ArgumentFragment.begin()->Spelling); 885 ArgumentFragment.begin()->Spelling.swap(ProperArgName); 886 } 887 Fragments.append(std::move(ArgumentFragment)); 888 889 if (TemplateArguments[i].isPackExpansion()) 890 Fragments.append("...", DeclarationFragments::FragmentKind::Text); 891 } 892 return Fragments; 893 } 894 895 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept( 896 const ConceptDecl *Concept) { 897 DeclarationFragments Fragments; 898 return Fragments 899 .append("template", DeclarationFragments::FragmentKind::Keyword) 900 .append("<", DeclarationFragments::FragmentKind::Text) 901 .append(getFragmentsForTemplateParameters( 902 Concept->getTemplateParameters()->asArray())) 903 .append("> ", DeclarationFragments::FragmentKind::Text) 904 .append("concept", DeclarationFragments::FragmentKind::Keyword) 905 .appendSpace() 906 .append(Concept->getName().str(), 907 DeclarationFragments::FragmentKind::Identifier) 908 .append(";", DeclarationFragments::FragmentKind::Text); 909 } 910 911 DeclarationFragments 912 DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate( 913 const RedeclarableTemplateDecl *RedeclarableTemplate) { 914 DeclarationFragments Fragments; 915 Fragments.append("template", DeclarationFragments::FragmentKind::Keyword) 916 .append("<", DeclarationFragments::FragmentKind::Text) 917 .append(getFragmentsForTemplateParameters( 918 RedeclarableTemplate->getTemplateParameters()->asArray())) 919 .append(">", DeclarationFragments::FragmentKind::Text) 920 .appendSpace(); 921 922 if (isa<TypeAliasTemplateDecl>(RedeclarableTemplate)) 923 Fragments.appendSpace() 924 .append("using", DeclarationFragments::FragmentKind::Keyword) 925 .appendSpace() 926 .append(RedeclarableTemplate->getName(), 927 DeclarationFragments::FragmentKind::Identifier); 928 // the templated records will be resposbible for injecting their templates 929 return Fragments.appendSpace(); 930 } 931 932 DeclarationFragments 933 DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization( 934 const ClassTemplateSpecializationDecl *Decl) { 935 DeclarationFragments Fragments; 936 return Fragments 937 .append("template", DeclarationFragments::FragmentKind::Keyword) 938 .append("<", DeclarationFragments::FragmentKind::Text) 939 .append(">", DeclarationFragments::FragmentKind::Text) 940 .appendSpace() 941 .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass( 942 cast<CXXRecordDecl>(Decl))) 943 .pop_back() // there is an extra semicolon now 944 .append("<", DeclarationFragments::FragmentKind::Text) 945 .append( 946 getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(), 947 Decl->getASTContext(), std::nullopt)) 948 .append(">", DeclarationFragments::FragmentKind::Text) 949 .append(";", DeclarationFragments::FragmentKind::Text); 950 } 951 952 DeclarationFragments 953 DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization( 954 const ClassTemplatePartialSpecializationDecl *Decl) { 955 DeclarationFragments Fragments; 956 return Fragments 957 .append("template", DeclarationFragments::FragmentKind::Keyword) 958 .append("<", DeclarationFragments::FragmentKind::Text) 959 .append(getFragmentsForTemplateParameters( 960 Decl->getTemplateParameters()->asArray())) 961 .append(">", DeclarationFragments::FragmentKind::Text) 962 .appendSpace() 963 .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass( 964 cast<CXXRecordDecl>(Decl))) 965 .pop_back() // there is an extra semicolon now 966 .append("<", DeclarationFragments::FragmentKind::Text) 967 .append(getFragmentsForTemplateArguments( 968 Decl->getTemplateArgs().asArray(), Decl->getASTContext(), 969 Decl->getTemplateParameters()->asArray())) 970 .append(">", DeclarationFragments::FragmentKind::Text) 971 .append(";", DeclarationFragments::FragmentKind::Text); 972 } 973 974 DeclarationFragments 975 DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization( 976 const VarTemplateSpecializationDecl *Decl) { 977 DeclarationFragments Fragments; 978 return Fragments 979 .append("template", DeclarationFragments::FragmentKind::Keyword) 980 .append("<", DeclarationFragments::FragmentKind::Text) 981 .append(">", DeclarationFragments::FragmentKind::Text) 982 .appendSpace() 983 .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl)) 984 .pop_back() // there is an extra semicolon now 985 .append("<", DeclarationFragments::FragmentKind::Text) 986 .append( 987 getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(), 988 Decl->getASTContext(), std::nullopt)) 989 .append(">", DeclarationFragments::FragmentKind::Text) 990 .append(";", DeclarationFragments::FragmentKind::Text); 991 } 992 993 DeclarationFragments 994 DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization( 995 const VarTemplatePartialSpecializationDecl *Decl) { 996 DeclarationFragments Fragments; 997 return Fragments 998 .append("template", DeclarationFragments::FragmentKind::Keyword) 999 .append("<", DeclarationFragments::FragmentKind::Text) 1000 // Partial specs may have new params. 1001 .append(getFragmentsForTemplateParameters( 1002 Decl->getTemplateParameters()->asArray())) 1003 .append(">", DeclarationFragments::FragmentKind::Text) 1004 .appendSpace() 1005 .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl)) 1006 .pop_back() // there is an extra semicolon now 1007 .append("<", DeclarationFragments::FragmentKind::Text) 1008 .append(getFragmentsForTemplateArguments( 1009 Decl->getTemplateArgs().asArray(), Decl->getASTContext(), 1010 Decl->getTemplateParameters()->asArray())) 1011 .append(">", DeclarationFragments::FragmentKind::Text) 1012 .append(";", DeclarationFragments::FragmentKind::Text); 1013 } 1014 1015 DeclarationFragments 1016 DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate( 1017 const FunctionTemplateDecl *Decl) { 1018 DeclarationFragments Fragments; 1019 return Fragments 1020 .append("template", DeclarationFragments::FragmentKind::Keyword) 1021 .append("<", DeclarationFragments::FragmentKind::Text) 1022 // Partial specs may have new params. 1023 .append(getFragmentsForTemplateParameters( 1024 Decl->getTemplateParameters()->asArray())) 1025 .append(">", DeclarationFragments::FragmentKind::Text) 1026 .appendSpace() 1027 .append(DeclarationFragmentsBuilder::getFragmentsForFunction( 1028 Decl->getAsFunction())); 1029 } 1030 1031 DeclarationFragments 1032 DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization( 1033 const FunctionDecl *Decl) { 1034 DeclarationFragments Fragments; 1035 return Fragments 1036 .append("template", DeclarationFragments::FragmentKind::Keyword) 1037 .append("<>", DeclarationFragments::FragmentKind::Text) 1038 .appendSpace() 1039 .append(DeclarationFragmentsBuilder::getFragmentsForFunction(Decl)); 1040 } 1041 1042 DeclarationFragments 1043 DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name, 1044 const MacroDirective *MD) { 1045 DeclarationFragments Fragments; 1046 Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword) 1047 .appendSpace(); 1048 Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); 1049 1050 auto *MI = MD->getMacroInfo(); 1051 1052 if (MI->isFunctionLike()) { 1053 Fragments.append("(", DeclarationFragments::FragmentKind::Text); 1054 unsigned numParameters = MI->getNumParams(); 1055 if (MI->isC99Varargs()) 1056 --numParameters; 1057 for (unsigned i = 0; i < numParameters; ++i) { 1058 if (i) 1059 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 1060 Fragments.append(MI->params()[i]->getName(), 1061 DeclarationFragments::FragmentKind::InternalParam); 1062 } 1063 if (MI->isVariadic()) { 1064 if (numParameters && MI->isC99Varargs()) 1065 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 1066 Fragments.append("...", DeclarationFragments::FragmentKind::Text); 1067 } 1068 Fragments.append(")", DeclarationFragments::FragmentKind::Text); 1069 } 1070 return Fragments; 1071 } 1072 1073 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory( 1074 const ObjCCategoryDecl *Category) { 1075 DeclarationFragments Fragments; 1076 1077 auto *Interface = Category->getClassInterface(); 1078 SmallString<128> InterfaceUSR; 1079 index::generateUSRForDecl(Interface, InterfaceUSR); 1080 1081 Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) 1082 .appendSpace() 1083 .append(Category->getClassInterface()->getName(), 1084 DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR, 1085 Interface) 1086 .append(" (", DeclarationFragments::FragmentKind::Text) 1087 .append(Category->getName(), 1088 DeclarationFragments::FragmentKind::Identifier) 1089 .append(")", DeclarationFragments::FragmentKind::Text); 1090 1091 return Fragments; 1092 } 1093 1094 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface( 1095 const ObjCInterfaceDecl *Interface) { 1096 DeclarationFragments Fragments; 1097 // Build the base of the Objective-C interface declaration. 1098 Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) 1099 .appendSpace() 1100 .append(Interface->getName(), 1101 DeclarationFragments::FragmentKind::Identifier); 1102 1103 // Build the inheritance part of the declaration. 1104 if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) { 1105 SmallString<128> SuperUSR; 1106 index::generateUSRForDecl(SuperClass, SuperUSR); 1107 Fragments.append(" : ", DeclarationFragments::FragmentKind::Text) 1108 .append(SuperClass->getName(), 1109 DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR, 1110 SuperClass); 1111 } 1112 1113 return Fragments; 1114 } 1115 1116 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod( 1117 const ObjCMethodDecl *Method) { 1118 DeclarationFragments Fragments, After; 1119 // Build the instance/class method indicator. 1120 if (Method->isClassMethod()) 1121 Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); 1122 else if (Method->isInstanceMethod()) 1123 Fragments.append("- ", DeclarationFragments::FragmentKind::Text); 1124 1125 // Build the return type. 1126 Fragments.append("(", DeclarationFragments::FragmentKind::Text) 1127 .append(getFragmentsForType(Method->getReturnType(), 1128 Method->getASTContext(), After)) 1129 .append(std::move(After)) 1130 .append(")", DeclarationFragments::FragmentKind::Text); 1131 1132 // Build the selector part. 1133 Selector Selector = Method->getSelector(); 1134 if (Selector.getNumArgs() == 0) 1135 // For Objective-C methods that don't take arguments, the first (and only) 1136 // slot of the selector is the method name. 1137 Fragments.appendSpace().append( 1138 Selector.getNameForSlot(0), 1139 DeclarationFragments::FragmentKind::Identifier); 1140 1141 // For Objective-C methods that take arguments, build the selector slots. 1142 for (unsigned i = 0, end = Method->param_size(); i != end; ++i) { 1143 // Objective-C method selector parts are considered as identifiers instead 1144 // of "external parameters" as in Swift. This is because Objective-C method 1145 // symbols are referenced with the entire selector, instead of just the 1146 // method name in Swift. 1147 SmallString<32> ParamID(Selector.getNameForSlot(i)); 1148 ParamID.append(":"); 1149 Fragments.appendSpace().append( 1150 ParamID, DeclarationFragments::FragmentKind::Identifier); 1151 1152 // Build the internal parameter. 1153 const ParmVarDecl *Param = Method->getParamDecl(i); 1154 Fragments.append(getFragmentsForParam(Param)); 1155 } 1156 1157 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 1158 } 1159 1160 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty( 1161 const ObjCPropertyDecl *Property) { 1162 DeclarationFragments Fragments, After; 1163 1164 // Build the Objective-C property keyword. 1165 Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword); 1166 1167 const auto Attributes = Property->getPropertyAttributesAsWritten(); 1168 // Build the attributes if there is any associated with the property. 1169 if (Attributes != ObjCPropertyAttribute::kind_noattr) { 1170 // No leading comma for the first attribute. 1171 bool First = true; 1172 Fragments.append(" (", DeclarationFragments::FragmentKind::Text); 1173 // Helper function to render the attribute. 1174 auto RenderAttribute = 1175 [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling, 1176 StringRef Arg = "", 1177 DeclarationFragments::FragmentKind ArgKind = 1178 DeclarationFragments::FragmentKind::Identifier) { 1179 // Check if the `Kind` attribute is set for this property. 1180 if ((Attributes & Kind) && !Spelling.empty()) { 1181 // Add a leading comma if this is not the first attribute rendered. 1182 if (!First) 1183 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 1184 // Render the spelling of this attribute `Kind` as a keyword. 1185 Fragments.append(Spelling, 1186 DeclarationFragments::FragmentKind::Keyword); 1187 // If this attribute takes in arguments (e.g. `getter=getterName`), 1188 // render the arguments. 1189 if (!Arg.empty()) 1190 Fragments.append("=", DeclarationFragments::FragmentKind::Text) 1191 .append(Arg, ArgKind); 1192 First = false; 1193 } 1194 }; 1195 1196 // Go through all possible Objective-C property attributes and render set 1197 // ones. 1198 RenderAttribute(ObjCPropertyAttribute::kind_class, "class"); 1199 RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct"); 1200 RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic"); 1201 RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic"); 1202 RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign"); 1203 RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain"); 1204 RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong"); 1205 RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy"); 1206 RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak"); 1207 RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained, 1208 "unsafe_unretained"); 1209 RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite"); 1210 RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly"); 1211 RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter", 1212 Property->getGetterName().getAsString()); 1213 RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter", 1214 Property->getSetterName().getAsString()); 1215 1216 // Render nullability attributes. 1217 if (Attributes & ObjCPropertyAttribute::kind_nullability) { 1218 QualType Type = Property->getType(); 1219 if (const auto Nullability = 1220 AttributedType::stripOuterNullability(Type)) { 1221 if (!First) 1222 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 1223 if (*Nullability == NullabilityKind::Unspecified && 1224 (Attributes & ObjCPropertyAttribute::kind_null_resettable)) 1225 Fragments.append("null_resettable", 1226 DeclarationFragments::FragmentKind::Keyword); 1227 else 1228 Fragments.append( 1229 getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true), 1230 DeclarationFragments::FragmentKind::Keyword); 1231 First = false; 1232 } 1233 } 1234 1235 Fragments.append(")", DeclarationFragments::FragmentKind::Text); 1236 } 1237 1238 // Build the property type and name, and return the completed fragments. 1239 return Fragments.appendSpace() 1240 .append(getFragmentsForType(Property->getType(), 1241 Property->getASTContext(), After)) 1242 .appendSpace() 1243 .append(Property->getName(), 1244 DeclarationFragments::FragmentKind::Identifier) 1245 .append(std::move(After)); 1246 } 1247 1248 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol( 1249 const ObjCProtocolDecl *Protocol) { 1250 DeclarationFragments Fragments; 1251 // Build basic protocol declaration. 1252 Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword) 1253 .appendSpace() 1254 .append(Protocol->getName(), 1255 DeclarationFragments::FragmentKind::Identifier); 1256 1257 // If this protocol conforms to other protocols, build the conformance list. 1258 if (!Protocol->protocols().empty()) { 1259 Fragments.append(" <", DeclarationFragments::FragmentKind::Text); 1260 for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin(); 1261 It != Protocol->protocol_end(); It++) { 1262 // Add a leading comma if this is not the first protocol rendered. 1263 if (It != Protocol->protocol_begin()) 1264 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 1265 1266 SmallString<128> USR; 1267 index::generateUSRForDecl(*It, USR); 1268 Fragments.append((*It)->getName(), 1269 DeclarationFragments::FragmentKind::TypeIdentifier, USR, 1270 *It); 1271 } 1272 Fragments.append(">", DeclarationFragments::FragmentKind::Text); 1273 } 1274 1275 return Fragments; 1276 } 1277 1278 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef( 1279 const TypedefNameDecl *Decl) { 1280 DeclarationFragments Fragments, After; 1281 Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword) 1282 .appendSpace() 1283 .append(getFragmentsForType(Decl->getUnderlyingType(), 1284 Decl->getASTContext(), After)) 1285 .append(std::move(After)) 1286 .appendSpace() 1287 .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier); 1288 1289 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 1290 } 1291 1292 // Instantiate template for FunctionDecl. 1293 template FunctionSignature 1294 DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *); 1295 1296 // Instantiate template for ObjCMethodDecl. 1297 template FunctionSignature 1298 DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *); 1299 1300 // Subheading of a symbol defaults to its name. 1301 DeclarationFragments 1302 DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) { 1303 DeclarationFragments Fragments; 1304 if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl)) 1305 Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(), 1306 DeclarationFragments::FragmentKind::Identifier); 1307 else if (isa<CXXConversionDecl>(Decl)) { 1308 Fragments.append( 1309 cast<CXXConversionDecl>(Decl)->getConversionType().getAsString(), 1310 DeclarationFragments::FragmentKind::Identifier); 1311 } else if (isa<CXXMethodDecl>(Decl) && 1312 cast<CXXMethodDecl>(Decl)->isOverloadedOperator()) { 1313 Fragments.append(Decl->getNameAsString(), 1314 DeclarationFragments::FragmentKind::Identifier); 1315 } else if (!Decl->getName().empty()) 1316 Fragments.append(Decl->getName(), 1317 DeclarationFragments::FragmentKind::Identifier); 1318 return Fragments; 1319 } 1320 1321 // Subheading of an Objective-C method is a `+` or `-` sign indicating whether 1322 // it's a class method or an instance method, followed by the selector name. 1323 DeclarationFragments 1324 DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) { 1325 DeclarationFragments Fragments; 1326 if (Method->isClassMethod()) 1327 Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); 1328 else if (Method->isInstanceMethod()) 1329 Fragments.append("- ", DeclarationFragments::FragmentKind::Text); 1330 1331 return Fragments.append(Method->getNameAsString(), 1332 DeclarationFragments::FragmentKind::Identifier); 1333 } 1334 1335 // Subheading of a symbol defaults to its name. 1336 DeclarationFragments 1337 DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) { 1338 DeclarationFragments Fragments; 1339 Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); 1340 return Fragments; 1341 } 1342