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 DeclarationFragmentsBuilder::getFragmentsForNamespace( 427 const NamespaceDecl *Decl) { 428 DeclarationFragments Fragments; 429 Fragments.append("namespace", DeclarationFragments::FragmentKind::Keyword); 430 if (!Decl->isAnonymousNamespace()) 431 Fragments.appendSpace().append( 432 Decl->getName(), DeclarationFragments::FragmentKind::Identifier); 433 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 434 } 435 436 DeclarationFragments 437 DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) { 438 DeclarationFragments Fragments; 439 if (Var->isConstexpr()) 440 Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 441 .appendSpace(); 442 443 StorageClass SC = Var->getStorageClass(); 444 if (SC != SC_None) 445 Fragments 446 .append(VarDecl::getStorageClassSpecifierString(SC), 447 DeclarationFragments::FragmentKind::Keyword) 448 .appendSpace(); 449 QualType T = 450 Var->getTypeSourceInfo() 451 ? Var->getTypeSourceInfo()->getType() 452 : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType()); 453 454 // Capture potential fragments that needs to be placed after the variable name 455 // ``` 456 // int nums[5]; 457 // char (*ptr_to_array)[6]; 458 // ``` 459 DeclarationFragments After; 460 return Fragments.append(getFragmentsForType(T, Var->getASTContext(), After)) 461 .appendSpace() 462 .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) 463 .append(std::move(After)) 464 .append(";", DeclarationFragments::FragmentKind::Text); 465 } 466 467 DeclarationFragments 468 DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) { 469 DeclarationFragments Fragments; 470 if (Var->isConstexpr()) 471 Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 472 .appendSpace(); 473 QualType T = 474 Var->getTypeSourceInfo() 475 ? Var->getTypeSourceInfo()->getType() 476 : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType()); 477 478 // Might be a member, so might be static. 479 if (Var->isStaticDataMember()) 480 Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) 481 .appendSpace(); 482 483 DeclarationFragments After; 484 DeclarationFragments ArgumentFragment = 485 getFragmentsForType(T, Var->getASTContext(), After); 486 if (ArgumentFragment.begin()->Spelling.substr(0, 14).compare( 487 "type-parameter") == 0) { 488 std::string ProperArgName = getNameForTemplateArgument( 489 Var->getDescribedVarTemplate()->getTemplateParameters()->asArray(), 490 ArgumentFragment.begin()->Spelling); 491 ArgumentFragment.begin()->Spelling.swap(ProperArgName); 492 } 493 Fragments.append(std::move(ArgumentFragment)) 494 .appendSpace() 495 .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) 496 .append(";", DeclarationFragments::FragmentKind::Text); 497 return Fragments; 498 } 499 500 DeclarationFragments 501 DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) { 502 DeclarationFragments Fragments, After; 503 504 QualType T = Param->getTypeSourceInfo() 505 ? Param->getTypeSourceInfo()->getType() 506 : Param->getASTContext().getUnqualifiedObjCPointerType( 507 Param->getType()); 508 509 DeclarationFragments TypeFragments = 510 getFragmentsForType(T, Param->getASTContext(), After); 511 if (TypeFragments.begin()->Spelling.substr(0, 14).compare("type-parameter") == 512 0) { 513 std::string ProperArgName = getNameForTemplateArgument( 514 dyn_cast<FunctionDecl>(Param->getDeclContext()) 515 ->getDescribedFunctionTemplate() 516 ->getTemplateParameters() 517 ->asArray(), 518 TypeFragments.begin()->Spelling); 519 TypeFragments.begin()->Spelling.swap(ProperArgName); 520 } 521 522 if (Param->isObjCMethodParameter()) 523 Fragments.append("(", DeclarationFragments::FragmentKind::Text) 524 .append(std::move(TypeFragments)) 525 .append(") ", DeclarationFragments::FragmentKind::Text); 526 else 527 Fragments.append(std::move(TypeFragments)).appendSpace(); 528 529 return Fragments 530 .append(Param->getName(), 531 DeclarationFragments::FragmentKind::InternalParam) 532 .append(std::move(After)); 533 } 534 535 DeclarationFragments 536 DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) { 537 DeclarationFragments Fragments; 538 // FIXME: Handle template specialization 539 switch (Func->getStorageClass()) { 540 case SC_None: 541 case SC_PrivateExtern: 542 break; 543 case SC_Extern: 544 Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword) 545 .appendSpace(); 546 break; 547 case SC_Static: 548 Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) 549 .appendSpace(); 550 break; 551 case SC_Auto: 552 case SC_Register: 553 llvm_unreachable("invalid for functions"); 554 } 555 if (Func->isConsteval()) // if consteval, it is also constexpr 556 Fragments.append("consteval", DeclarationFragments::FragmentKind::Keyword) 557 .appendSpace(); 558 else if (Func->isConstexpr()) 559 Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 560 .appendSpace(); 561 562 // FIXME: Is `after` actually needed here? 563 DeclarationFragments After; 564 auto ReturnValueFragment = 565 getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After); 566 if (ReturnValueFragment.begin()->Spelling.substr(0, 14).compare( 567 "type-parameter") == 0) { 568 std::string ProperArgName = 569 getNameForTemplateArgument(Func->getDescribedFunctionTemplate() 570 ->getTemplateParameters() 571 ->asArray(), 572 ReturnValueFragment.begin()->Spelling); 573 ReturnValueFragment.begin()->Spelling.swap(ProperArgName); 574 } 575 576 Fragments.append(std::move(ReturnValueFragment)) 577 .appendSpace() 578 .append(Func->getName(), DeclarationFragments::FragmentKind::Identifier); 579 580 if (Func->getTemplateSpecializationInfo()) { 581 Fragments.append("<", DeclarationFragments::FragmentKind::Text); 582 583 for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) { 584 if (i) 585 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 586 Fragments.append( 587 getFragmentsForType(Func->getParamDecl(i)->getType(), 588 Func->getParamDecl(i)->getASTContext(), After)); 589 } 590 Fragments.append(">", DeclarationFragments::FragmentKind::Text); 591 } 592 Fragments.append(std::move(After)); 593 594 Fragments.append("(", DeclarationFragments::FragmentKind::Text); 595 for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) { 596 if (i) 597 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 598 Fragments.append(getFragmentsForParam(Func->getParamDecl(i))); 599 } 600 Fragments.append(")", DeclarationFragments::FragmentKind::Text); 601 602 Fragments.append(DeclarationFragments::getExceptionSpecificationString( 603 Func->getExceptionSpecType())); 604 605 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 606 } 607 608 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant( 609 const EnumConstantDecl *EnumConstDecl) { 610 DeclarationFragments Fragments; 611 return Fragments.append(EnumConstDecl->getName(), 612 DeclarationFragments::FragmentKind::Identifier); 613 } 614 615 DeclarationFragments 616 DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) { 617 if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl()) 618 return getFragmentsForTypedef(TypedefNameDecl); 619 620 DeclarationFragments Fragments, After; 621 Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword); 622 623 if (!EnumDecl->getName().empty()) 624 Fragments.appendSpace().append( 625 EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier); 626 627 QualType IntegerType = EnumDecl->getIntegerType(); 628 if (!IntegerType.isNull()) 629 Fragments.append(": ", DeclarationFragments::FragmentKind::Text) 630 .append( 631 getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After)) 632 .append(std::move(After)); 633 634 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 635 } 636 637 DeclarationFragments 638 DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) { 639 DeclarationFragments After; 640 DeclarationFragments Fragments; 641 if (Field->isMutable()) 642 Fragments.append("mutable", DeclarationFragments::FragmentKind::Keyword) 643 .appendSpace(); 644 return Fragments 645 .append( 646 getFragmentsForType(Field->getType(), Field->getASTContext(), After)) 647 .appendSpace() 648 .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier) 649 .append(std::move(After)) 650 .append(";", DeclarationFragments::FragmentKind::Text); 651 } 652 653 DeclarationFragments 654 DeclarationFragmentsBuilder::getFragmentsForStruct(const RecordDecl *Record) { 655 if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl()) 656 return getFragmentsForTypedef(TypedefNameDecl); 657 658 DeclarationFragments Fragments; 659 Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword); 660 661 if (!Record->getName().empty()) 662 Fragments.appendSpace().append( 663 Record->getName(), DeclarationFragments::FragmentKind::Identifier); 664 665 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 666 } 667 668 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass( 669 const CXXRecordDecl *Record) { 670 if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl()) 671 return getFragmentsForTypedef(TypedefNameDecl); 672 673 DeclarationFragments Fragments; 674 Fragments.append(DeclarationFragments::getStructureTypeFragment(Record)); 675 676 if (!Record->getName().empty()) 677 Fragments.appendSpace().append( 678 Record->getName(), DeclarationFragments::FragmentKind::Identifier); 679 680 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 681 } 682 683 DeclarationFragments 684 DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod( 685 const CXXMethodDecl *Method) { 686 DeclarationFragments Fragments; 687 std::string Name; 688 if (isa<CXXConstructorDecl>(Method)) { 689 Name = Method->getNameAsString(); 690 if (dyn_cast<CXXConstructorDecl>(Method)->isExplicit()) 691 Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword) 692 .appendSpace(); 693 } else if (isa<CXXDestructorDecl>(Method)) 694 Name = Method->getNameAsString(); 695 696 DeclarationFragments After; 697 Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier) 698 .append(std::move(After)); 699 Fragments.append("(", DeclarationFragments::FragmentKind::Text); 700 for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) { 701 if (i) 702 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 703 Fragments.append(getFragmentsForParam(Method->getParamDecl(i))); 704 } 705 Fragments.append(")", DeclarationFragments::FragmentKind::Text); 706 707 Fragments.append(DeclarationFragments::getExceptionSpecificationString( 708 Method->getExceptionSpecType())); 709 710 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 711 } 712 713 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod( 714 const CXXMethodDecl *Method) { 715 DeclarationFragments Fragments; 716 StringRef Name = Method->getName(); 717 if (Method->isStatic()) 718 Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) 719 .appendSpace(); 720 if (Method->isConstexpr()) 721 Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 722 .appendSpace(); 723 if (Method->isVolatile()) 724 Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword) 725 .appendSpace(); 726 727 // Build return type 728 DeclarationFragments After; 729 Fragments 730 .append(getFragmentsForType(Method->getReturnType(), 731 Method->getASTContext(), After)) 732 .appendSpace() 733 .append(Name, DeclarationFragments::FragmentKind::Identifier) 734 .append(std::move(After)); 735 Fragments.append("(", DeclarationFragments::FragmentKind::Text); 736 for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) { 737 if (i) 738 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 739 Fragments.append(getFragmentsForParam(Method->getParamDecl(i))); 740 } 741 Fragments.append(")", DeclarationFragments::FragmentKind::Text); 742 743 if (Method->isConst()) 744 Fragments.appendSpace().append("const", 745 DeclarationFragments::FragmentKind::Keyword); 746 747 Fragments.append(DeclarationFragments::getExceptionSpecificationString( 748 Method->getExceptionSpecType())); 749 750 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 751 } 752 753 DeclarationFragments 754 DeclarationFragmentsBuilder::getFragmentsForConversionFunction( 755 const CXXConversionDecl *ConversionFunction) { 756 DeclarationFragments Fragments; 757 758 if (ConversionFunction->isExplicit()) 759 Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword) 760 .appendSpace(); 761 762 Fragments.append("operator", DeclarationFragments::FragmentKind::Keyword) 763 .appendSpace(); 764 765 Fragments 766 .append(ConversionFunction->getConversionType().getAsString(), 767 DeclarationFragments::FragmentKind::TypeIdentifier) 768 .append("(", DeclarationFragments::FragmentKind::Text); 769 for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end; 770 ++i) { 771 if (i) 772 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 773 Fragments.append(getFragmentsForParam(ConversionFunction->getParamDecl(i))); 774 } 775 Fragments.append(")", DeclarationFragments::FragmentKind::Text); 776 777 if (ConversionFunction->isConst()) 778 Fragments.appendSpace().append("const", 779 DeclarationFragments::FragmentKind::Keyword); 780 781 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 782 } 783 784 DeclarationFragments 785 DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator( 786 const CXXMethodDecl *Method) { 787 DeclarationFragments Fragments; 788 789 // Build return type 790 DeclarationFragments After; 791 Fragments 792 .append(getFragmentsForType(Method->getReturnType(), 793 Method->getASTContext(), After)) 794 .appendSpace() 795 .append(Method->getNameAsString(), 796 DeclarationFragments::FragmentKind::Identifier) 797 .append(std::move(After)); 798 Fragments.append("(", DeclarationFragments::FragmentKind::Text); 799 for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) { 800 if (i) 801 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 802 Fragments.append(getFragmentsForParam(Method->getParamDecl(i))); 803 } 804 Fragments.append(")", DeclarationFragments::FragmentKind::Text); 805 806 if (Method->isConst()) 807 Fragments.appendSpace().append("const", 808 DeclarationFragments::FragmentKind::Keyword); 809 810 Fragments.append(DeclarationFragments::getExceptionSpecificationString( 811 Method->getExceptionSpecType())); 812 813 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 814 } 815 816 // Get fragments for template parameters, e.g. T in tempalte<typename T> ... 817 DeclarationFragments 818 DeclarationFragmentsBuilder::getFragmentsForTemplateParameters( 819 ArrayRef<NamedDecl *> ParameterArray) { 820 DeclarationFragments Fragments; 821 for (unsigned i = 0, end = ParameterArray.size(); i != end; ++i) { 822 if (i) 823 Fragments.append(",", DeclarationFragments::FragmentKind::Text) 824 .appendSpace(); 825 826 const auto *TemplateParam = 827 dyn_cast<TemplateTypeParmDecl>(ParameterArray[i]); 828 if (!TemplateParam) 829 continue; 830 if (TemplateParam->hasTypeConstraint()) 831 Fragments.append(TemplateParam->getTypeConstraint() 832 ->getNamedConcept() 833 ->getName() 834 .str(), 835 DeclarationFragments::FragmentKind::TypeIdentifier); 836 else if (TemplateParam->wasDeclaredWithTypename()) 837 Fragments.append("typename", DeclarationFragments::FragmentKind::Keyword); 838 else 839 Fragments.append("class", DeclarationFragments::FragmentKind::Keyword); 840 841 if (TemplateParam->isParameterPack()) 842 Fragments.append("...", DeclarationFragments::FragmentKind::Text); 843 844 Fragments.appendSpace().append( 845 TemplateParam->getName(), 846 DeclarationFragments::FragmentKind::GenericParameter); 847 } 848 return Fragments; 849 } 850 851 // Find the name of a template argument from the template's parameters. 852 std::string DeclarationFragmentsBuilder::getNameForTemplateArgument( 853 const ArrayRef<NamedDecl *> TemplateParameters, std::string TypeParameter) { 854 // The arg is a generic parameter from a partial spec, e.g. 855 // T in template<typename T> Foo<T, int>. 856 // 857 // Those names appear as "type-parameter-<index>-<depth>", so we must find its 858 // name from the template's parameter list. 859 for (unsigned i = 0; i < TemplateParameters.size(); ++i) { 860 const auto *Parameter = 861 dyn_cast<TemplateTypeParmDecl>(TemplateParameters[i]); 862 if (TypeParameter.compare("type-parameter-" + 863 std::to_string(Parameter->getDepth()) + "-" + 864 std::to_string(Parameter->getIndex())) == 0) 865 return std::string(TemplateParameters[i]->getName()); 866 } 867 llvm_unreachable("Could not find the name of a template argument."); 868 } 869 870 // Get fragments for template arguments, e.g. int in template<typename T> 871 // Foo<int>; 872 // 873 // Note: TemplateParameters is only necessary if the Decl is a 874 // PartialSpecialization, where we need the parameters to deduce the name of the 875 // generic arguments. 876 DeclarationFragments 877 DeclarationFragmentsBuilder::getFragmentsForTemplateArguments( 878 const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context, 879 const std::optional<ArrayRef<NamedDecl *>> TemplateParameters) { 880 DeclarationFragments Fragments; 881 for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) { 882 if (i) 883 Fragments.append(",", DeclarationFragments::FragmentKind::Text) 884 .appendSpace(); 885 886 std::string Type = TemplateArguments[i].getAsType().getAsString(); 887 DeclarationFragments After; 888 DeclarationFragments ArgumentFragment = 889 getFragmentsForType(TemplateArguments[i].getAsType(), Context, After); 890 891 if (ArgumentFragment.begin()->Spelling.substr(0, 14).compare( 892 "type-parameter") == 0) { 893 std::string ProperArgName = getNameForTemplateArgument( 894 TemplateParameters.value(), ArgumentFragment.begin()->Spelling); 895 ArgumentFragment.begin()->Spelling.swap(ProperArgName); 896 } 897 Fragments.append(std::move(ArgumentFragment)); 898 899 if (TemplateArguments[i].isPackExpansion()) 900 Fragments.append("...", DeclarationFragments::FragmentKind::Text); 901 } 902 return Fragments; 903 } 904 905 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept( 906 const ConceptDecl *Concept) { 907 DeclarationFragments Fragments; 908 return Fragments 909 .append("template", DeclarationFragments::FragmentKind::Keyword) 910 .append("<", DeclarationFragments::FragmentKind::Text) 911 .append(getFragmentsForTemplateParameters( 912 Concept->getTemplateParameters()->asArray())) 913 .append("> ", DeclarationFragments::FragmentKind::Text) 914 .append("concept", DeclarationFragments::FragmentKind::Keyword) 915 .appendSpace() 916 .append(Concept->getName().str(), 917 DeclarationFragments::FragmentKind::Identifier) 918 .append(";", DeclarationFragments::FragmentKind::Text); 919 } 920 921 DeclarationFragments 922 DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate( 923 const RedeclarableTemplateDecl *RedeclarableTemplate) { 924 DeclarationFragments Fragments; 925 Fragments.append("template", DeclarationFragments::FragmentKind::Keyword) 926 .append("<", DeclarationFragments::FragmentKind::Text) 927 .append(getFragmentsForTemplateParameters( 928 RedeclarableTemplate->getTemplateParameters()->asArray())) 929 .append(">", DeclarationFragments::FragmentKind::Text) 930 .appendSpace(); 931 932 if (isa<TypeAliasTemplateDecl>(RedeclarableTemplate)) 933 Fragments.appendSpace() 934 .append("using", DeclarationFragments::FragmentKind::Keyword) 935 .appendSpace() 936 .append(RedeclarableTemplate->getName(), 937 DeclarationFragments::FragmentKind::Identifier); 938 // the templated records will be resposbible for injecting their templates 939 return Fragments.appendSpace(); 940 } 941 942 DeclarationFragments 943 DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization( 944 const ClassTemplateSpecializationDecl *Decl) { 945 DeclarationFragments Fragments; 946 return Fragments 947 .append("template", DeclarationFragments::FragmentKind::Keyword) 948 .append("<", DeclarationFragments::FragmentKind::Text) 949 .append(">", DeclarationFragments::FragmentKind::Text) 950 .appendSpace() 951 .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass( 952 cast<CXXRecordDecl>(Decl))) 953 .pop_back() // there is an extra semicolon now 954 .append("<", DeclarationFragments::FragmentKind::Text) 955 .append( 956 getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(), 957 Decl->getASTContext(), std::nullopt)) 958 .append(">", DeclarationFragments::FragmentKind::Text) 959 .append(";", DeclarationFragments::FragmentKind::Text); 960 } 961 962 DeclarationFragments 963 DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization( 964 const ClassTemplatePartialSpecializationDecl *Decl) { 965 DeclarationFragments Fragments; 966 return Fragments 967 .append("template", DeclarationFragments::FragmentKind::Keyword) 968 .append("<", DeclarationFragments::FragmentKind::Text) 969 .append(getFragmentsForTemplateParameters( 970 Decl->getTemplateParameters()->asArray())) 971 .append(">", DeclarationFragments::FragmentKind::Text) 972 .appendSpace() 973 .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass( 974 cast<CXXRecordDecl>(Decl))) 975 .pop_back() // there is an extra semicolon now 976 .append("<", DeclarationFragments::FragmentKind::Text) 977 .append(getFragmentsForTemplateArguments( 978 Decl->getTemplateArgs().asArray(), Decl->getASTContext(), 979 Decl->getTemplateParameters()->asArray())) 980 .append(">", DeclarationFragments::FragmentKind::Text) 981 .append(";", DeclarationFragments::FragmentKind::Text); 982 } 983 984 DeclarationFragments 985 DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization( 986 const VarTemplateSpecializationDecl *Decl) { 987 DeclarationFragments Fragments; 988 return Fragments 989 .append("template", DeclarationFragments::FragmentKind::Keyword) 990 .append("<", DeclarationFragments::FragmentKind::Text) 991 .append(">", DeclarationFragments::FragmentKind::Text) 992 .appendSpace() 993 .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl)) 994 .pop_back() // there is an extra semicolon now 995 .append("<", DeclarationFragments::FragmentKind::Text) 996 .append( 997 getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(), 998 Decl->getASTContext(), std::nullopt)) 999 .append(">", DeclarationFragments::FragmentKind::Text) 1000 .append(";", DeclarationFragments::FragmentKind::Text); 1001 } 1002 1003 DeclarationFragments 1004 DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization( 1005 const VarTemplatePartialSpecializationDecl *Decl) { 1006 DeclarationFragments Fragments; 1007 return Fragments 1008 .append("template", DeclarationFragments::FragmentKind::Keyword) 1009 .append("<", DeclarationFragments::FragmentKind::Text) 1010 // Partial specs may have new params. 1011 .append(getFragmentsForTemplateParameters( 1012 Decl->getTemplateParameters()->asArray())) 1013 .append(">", DeclarationFragments::FragmentKind::Text) 1014 .appendSpace() 1015 .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl)) 1016 .pop_back() // there is an extra semicolon now 1017 .append("<", DeclarationFragments::FragmentKind::Text) 1018 .append(getFragmentsForTemplateArguments( 1019 Decl->getTemplateArgs().asArray(), Decl->getASTContext(), 1020 Decl->getTemplateParameters()->asArray())) 1021 .append(">", DeclarationFragments::FragmentKind::Text) 1022 .append(";", DeclarationFragments::FragmentKind::Text); 1023 } 1024 1025 DeclarationFragments 1026 DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate( 1027 const FunctionTemplateDecl *Decl) { 1028 DeclarationFragments Fragments; 1029 return Fragments 1030 .append("template", DeclarationFragments::FragmentKind::Keyword) 1031 .append("<", DeclarationFragments::FragmentKind::Text) 1032 // Partial specs may have new params. 1033 .append(getFragmentsForTemplateParameters( 1034 Decl->getTemplateParameters()->asArray())) 1035 .append(">", DeclarationFragments::FragmentKind::Text) 1036 .appendSpace() 1037 .append(DeclarationFragmentsBuilder::getFragmentsForFunction( 1038 Decl->getAsFunction())); 1039 } 1040 1041 DeclarationFragments 1042 DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization( 1043 const FunctionDecl *Decl) { 1044 DeclarationFragments Fragments; 1045 return Fragments 1046 .append("template", DeclarationFragments::FragmentKind::Keyword) 1047 .append("<>", DeclarationFragments::FragmentKind::Text) 1048 .appendSpace() 1049 .append(DeclarationFragmentsBuilder::getFragmentsForFunction(Decl)); 1050 } 1051 1052 DeclarationFragments 1053 DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name, 1054 const MacroDirective *MD) { 1055 DeclarationFragments Fragments; 1056 Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword) 1057 .appendSpace(); 1058 Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); 1059 1060 auto *MI = MD->getMacroInfo(); 1061 1062 if (MI->isFunctionLike()) { 1063 Fragments.append("(", DeclarationFragments::FragmentKind::Text); 1064 unsigned numParameters = MI->getNumParams(); 1065 if (MI->isC99Varargs()) 1066 --numParameters; 1067 for (unsigned i = 0; i < numParameters; ++i) { 1068 if (i) 1069 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 1070 Fragments.append(MI->params()[i]->getName(), 1071 DeclarationFragments::FragmentKind::InternalParam); 1072 } 1073 if (MI->isVariadic()) { 1074 if (numParameters && MI->isC99Varargs()) 1075 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 1076 Fragments.append("...", DeclarationFragments::FragmentKind::Text); 1077 } 1078 Fragments.append(")", DeclarationFragments::FragmentKind::Text); 1079 } 1080 return Fragments; 1081 } 1082 1083 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory( 1084 const ObjCCategoryDecl *Category) { 1085 DeclarationFragments Fragments; 1086 1087 auto *Interface = Category->getClassInterface(); 1088 SmallString<128> InterfaceUSR; 1089 index::generateUSRForDecl(Interface, InterfaceUSR); 1090 1091 Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) 1092 .appendSpace() 1093 .append(Category->getClassInterface()->getName(), 1094 DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR, 1095 Interface) 1096 .append(" (", DeclarationFragments::FragmentKind::Text) 1097 .append(Category->getName(), 1098 DeclarationFragments::FragmentKind::Identifier) 1099 .append(")", DeclarationFragments::FragmentKind::Text); 1100 1101 return Fragments; 1102 } 1103 1104 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface( 1105 const ObjCInterfaceDecl *Interface) { 1106 DeclarationFragments Fragments; 1107 // Build the base of the Objective-C interface declaration. 1108 Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) 1109 .appendSpace() 1110 .append(Interface->getName(), 1111 DeclarationFragments::FragmentKind::Identifier); 1112 1113 // Build the inheritance part of the declaration. 1114 if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) { 1115 SmallString<128> SuperUSR; 1116 index::generateUSRForDecl(SuperClass, SuperUSR); 1117 Fragments.append(" : ", DeclarationFragments::FragmentKind::Text) 1118 .append(SuperClass->getName(), 1119 DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR, 1120 SuperClass); 1121 } 1122 1123 return Fragments; 1124 } 1125 1126 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod( 1127 const ObjCMethodDecl *Method) { 1128 DeclarationFragments Fragments, After; 1129 // Build the instance/class method indicator. 1130 if (Method->isClassMethod()) 1131 Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); 1132 else if (Method->isInstanceMethod()) 1133 Fragments.append("- ", DeclarationFragments::FragmentKind::Text); 1134 1135 // Build the return type. 1136 Fragments.append("(", DeclarationFragments::FragmentKind::Text) 1137 .append(getFragmentsForType(Method->getReturnType(), 1138 Method->getASTContext(), After)) 1139 .append(std::move(After)) 1140 .append(")", DeclarationFragments::FragmentKind::Text); 1141 1142 // Build the selector part. 1143 Selector Selector = Method->getSelector(); 1144 if (Selector.getNumArgs() == 0) 1145 // For Objective-C methods that don't take arguments, the first (and only) 1146 // slot of the selector is the method name. 1147 Fragments.appendSpace().append( 1148 Selector.getNameForSlot(0), 1149 DeclarationFragments::FragmentKind::Identifier); 1150 1151 // For Objective-C methods that take arguments, build the selector slots. 1152 for (unsigned i = 0, end = Method->param_size(); i != end; ++i) { 1153 // Objective-C method selector parts are considered as identifiers instead 1154 // of "external parameters" as in Swift. This is because Objective-C method 1155 // symbols are referenced with the entire selector, instead of just the 1156 // method name in Swift. 1157 SmallString<32> ParamID(Selector.getNameForSlot(i)); 1158 ParamID.append(":"); 1159 Fragments.appendSpace().append( 1160 ParamID, DeclarationFragments::FragmentKind::Identifier); 1161 1162 // Build the internal parameter. 1163 const ParmVarDecl *Param = Method->getParamDecl(i); 1164 Fragments.append(getFragmentsForParam(Param)); 1165 } 1166 1167 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 1168 } 1169 1170 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty( 1171 const ObjCPropertyDecl *Property) { 1172 DeclarationFragments Fragments, After; 1173 1174 // Build the Objective-C property keyword. 1175 Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword); 1176 1177 const auto Attributes = Property->getPropertyAttributesAsWritten(); 1178 // Build the attributes if there is any associated with the property. 1179 if (Attributes != ObjCPropertyAttribute::kind_noattr) { 1180 // No leading comma for the first attribute. 1181 bool First = true; 1182 Fragments.append(" (", DeclarationFragments::FragmentKind::Text); 1183 // Helper function to render the attribute. 1184 auto RenderAttribute = 1185 [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling, 1186 StringRef Arg = "", 1187 DeclarationFragments::FragmentKind ArgKind = 1188 DeclarationFragments::FragmentKind::Identifier) { 1189 // Check if the `Kind` attribute is set for this property. 1190 if ((Attributes & Kind) && !Spelling.empty()) { 1191 // Add a leading comma if this is not the first attribute rendered. 1192 if (!First) 1193 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 1194 // Render the spelling of this attribute `Kind` as a keyword. 1195 Fragments.append(Spelling, 1196 DeclarationFragments::FragmentKind::Keyword); 1197 // If this attribute takes in arguments (e.g. `getter=getterName`), 1198 // render the arguments. 1199 if (!Arg.empty()) 1200 Fragments.append("=", DeclarationFragments::FragmentKind::Text) 1201 .append(Arg, ArgKind); 1202 First = false; 1203 } 1204 }; 1205 1206 // Go through all possible Objective-C property attributes and render set 1207 // ones. 1208 RenderAttribute(ObjCPropertyAttribute::kind_class, "class"); 1209 RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct"); 1210 RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic"); 1211 RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic"); 1212 RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign"); 1213 RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain"); 1214 RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong"); 1215 RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy"); 1216 RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak"); 1217 RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained, 1218 "unsafe_unretained"); 1219 RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite"); 1220 RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly"); 1221 RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter", 1222 Property->getGetterName().getAsString()); 1223 RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter", 1224 Property->getSetterName().getAsString()); 1225 1226 // Render nullability attributes. 1227 if (Attributes & ObjCPropertyAttribute::kind_nullability) { 1228 QualType Type = Property->getType(); 1229 if (const auto Nullability = 1230 AttributedType::stripOuterNullability(Type)) { 1231 if (!First) 1232 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 1233 if (*Nullability == NullabilityKind::Unspecified && 1234 (Attributes & ObjCPropertyAttribute::kind_null_resettable)) 1235 Fragments.append("null_resettable", 1236 DeclarationFragments::FragmentKind::Keyword); 1237 else 1238 Fragments.append( 1239 getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true), 1240 DeclarationFragments::FragmentKind::Keyword); 1241 First = false; 1242 } 1243 } 1244 1245 Fragments.append(")", DeclarationFragments::FragmentKind::Text); 1246 } 1247 1248 // Build the property type and name, and return the completed fragments. 1249 return Fragments.appendSpace() 1250 .append(getFragmentsForType(Property->getType(), 1251 Property->getASTContext(), After)) 1252 .appendSpace() 1253 .append(Property->getName(), 1254 DeclarationFragments::FragmentKind::Identifier) 1255 .append(std::move(After)); 1256 } 1257 1258 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol( 1259 const ObjCProtocolDecl *Protocol) { 1260 DeclarationFragments Fragments; 1261 // Build basic protocol declaration. 1262 Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword) 1263 .appendSpace() 1264 .append(Protocol->getName(), 1265 DeclarationFragments::FragmentKind::Identifier); 1266 1267 // If this protocol conforms to other protocols, build the conformance list. 1268 if (!Protocol->protocols().empty()) { 1269 Fragments.append(" <", DeclarationFragments::FragmentKind::Text); 1270 for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin(); 1271 It != Protocol->protocol_end(); It++) { 1272 // Add a leading comma if this is not the first protocol rendered. 1273 if (It != Protocol->protocol_begin()) 1274 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 1275 1276 SmallString<128> USR; 1277 index::generateUSRForDecl(*It, USR); 1278 Fragments.append((*It)->getName(), 1279 DeclarationFragments::FragmentKind::TypeIdentifier, USR, 1280 *It); 1281 } 1282 Fragments.append(">", DeclarationFragments::FragmentKind::Text); 1283 } 1284 1285 return Fragments; 1286 } 1287 1288 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef( 1289 const TypedefNameDecl *Decl) { 1290 DeclarationFragments Fragments, After; 1291 Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword) 1292 .appendSpace() 1293 .append(getFragmentsForType(Decl->getUnderlyingType(), 1294 Decl->getASTContext(), After)) 1295 .append(std::move(After)) 1296 .appendSpace() 1297 .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier); 1298 1299 return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 1300 } 1301 1302 // Instantiate template for FunctionDecl. 1303 template FunctionSignature 1304 DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *); 1305 1306 // Instantiate template for ObjCMethodDecl. 1307 template FunctionSignature 1308 DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *); 1309 1310 // Subheading of a symbol defaults to its name. 1311 DeclarationFragments 1312 DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) { 1313 DeclarationFragments Fragments; 1314 if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl)) 1315 Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(), 1316 DeclarationFragments::FragmentKind::Identifier); 1317 else if (isa<CXXConversionDecl>(Decl)) { 1318 Fragments.append( 1319 cast<CXXConversionDecl>(Decl)->getConversionType().getAsString(), 1320 DeclarationFragments::FragmentKind::Identifier); 1321 } else if (isa<CXXMethodDecl>(Decl) && 1322 cast<CXXMethodDecl>(Decl)->isOverloadedOperator()) { 1323 Fragments.append(Decl->getNameAsString(), 1324 DeclarationFragments::FragmentKind::Identifier); 1325 } else if (!Decl->getName().empty()) 1326 Fragments.append(Decl->getName(), 1327 DeclarationFragments::FragmentKind::Identifier); 1328 return Fragments; 1329 } 1330 1331 // Subheading of an Objective-C method is a `+` or `-` sign indicating whether 1332 // it's a class method or an instance method, followed by the selector name. 1333 DeclarationFragments 1334 DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) { 1335 DeclarationFragments Fragments; 1336 if (Method->isClassMethod()) 1337 Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); 1338 else if (Method->isInstanceMethod()) 1339 Fragments.append("- ", DeclarationFragments::FragmentKind::Text); 1340 1341 return Fragments.append(Method->getNameAsString(), 1342 DeclarationFragments::FragmentKind::Identifier); 1343 } 1344 1345 // Subheading of a symbol defaults to its name. 1346 DeclarationFragments 1347 DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) { 1348 DeclarationFragments Fragments; 1349 Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); 1350 return Fragments; 1351 } 1352