1666 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file implements Declaration Fragments related classes.11///12//===----------------------------------------------------------------------===//13 14#include "clang/ExtractAPI/DeclarationFragments.h"15#include "clang/AST/ASTFwd.h"16#include "clang/AST/Decl.h"17#include "clang/AST/DeclCXX.h"18#include "clang/AST/TemplateBase.h"19#include "clang/AST/TemplateName.h"20#include "clang/AST/Type.h"21#include "clang/AST/TypeLoc.h"22#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"23#include "clang/Index/USRGeneration.h"24#include "llvm/ADT/StringSwitch.h"25#include "llvm/Support/ErrorHandling.h"26#include "llvm/Support/raw_ostream.h"27#include <optional>28 29using namespace clang::extractapi;30using namespace llvm;31 32namespace {33 34void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo,35 clang::FunctionTypeLoc &Block,36 clang::FunctionProtoTypeLoc &BlockProto) {37 if (!TSInfo)38 return;39 40 clang::TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();41 while (true) {42 // Look through qualified types43 if (auto QualifiedTL = TL.getAs<clang::QualifiedTypeLoc>()) {44 TL = QualifiedTL.getUnqualifiedLoc();45 continue;46 }47 48 if (auto AttrTL = TL.getAs<clang::AttributedTypeLoc>()) {49 TL = AttrTL.getModifiedLoc();50 continue;51 }52 53 // Try to get the function prototype behind the block pointer type,54 // then we're done.55 if (auto BlockPtr = TL.getAs<clang::BlockPointerTypeLoc>()) {56 TL = BlockPtr.getPointeeLoc().IgnoreParens();57 Block = TL.getAs<clang::FunctionTypeLoc>();58 BlockProto = TL.getAs<clang::FunctionProtoTypeLoc>();59 }60 break;61 }62}63 64} // namespace65 66DeclarationFragments &67DeclarationFragments::appendUnduplicatedTextCharacter(char Character) {68 if (!Fragments.empty()) {69 Fragment &Last = Fragments.back();70 if (Last.Kind == FragmentKind::Text) {71 // Merge the extra space into the last fragment if the last fragment is72 // also text.73 if (Last.Spelling.back() != Character) { // avoid duplicates at end74 Last.Spelling.push_back(Character);75 }76 } else {77 append("", FragmentKind::Text);78 Fragments.back().Spelling.push_back(Character);79 }80 }81 82 return *this;83}84 85DeclarationFragments &DeclarationFragments::appendSpace() {86 return appendUnduplicatedTextCharacter(' ');87}88 89DeclarationFragments &DeclarationFragments::appendSemicolon() {90 return appendUnduplicatedTextCharacter(';');91}92 93DeclarationFragments &DeclarationFragments::removeTrailingSemicolon() {94 if (Fragments.empty())95 return *this;96 97 Fragment &Last = Fragments.back();98 if (Last.Kind == FragmentKind::Text && Last.Spelling.back() == ';')99 Last.Spelling.pop_back();100 101 return *this;102}103 104StringRef DeclarationFragments::getFragmentKindString(105 DeclarationFragments::FragmentKind Kind) {106 switch (Kind) {107 case DeclarationFragments::FragmentKind::None:108 return "none";109 case DeclarationFragments::FragmentKind::Keyword:110 return "keyword";111 case DeclarationFragments::FragmentKind::Attribute:112 return "attribute";113 case DeclarationFragments::FragmentKind::NumberLiteral:114 return "number";115 case DeclarationFragments::FragmentKind::StringLiteral:116 return "string";117 case DeclarationFragments::FragmentKind::Identifier:118 return "identifier";119 case DeclarationFragments::FragmentKind::TypeIdentifier:120 return "typeIdentifier";121 case DeclarationFragments::FragmentKind::GenericParameter:122 return "genericParameter";123 case DeclarationFragments::FragmentKind::ExternalParam:124 return "externalParam";125 case DeclarationFragments::FragmentKind::InternalParam:126 return "internalParam";127 case DeclarationFragments::FragmentKind::Text:128 return "text";129 }130 131 llvm_unreachable("Unhandled FragmentKind");132}133 134DeclarationFragments::FragmentKind135DeclarationFragments::parseFragmentKindFromString(StringRef S) {136 return llvm::StringSwitch<FragmentKind>(S)137 .Case("keyword", DeclarationFragments::FragmentKind::Keyword)138 .Case("attribute", DeclarationFragments::FragmentKind::Attribute)139 .Case("number", DeclarationFragments::FragmentKind::NumberLiteral)140 .Case("string", DeclarationFragments::FragmentKind::StringLiteral)141 .Case("identifier", DeclarationFragments::FragmentKind::Identifier)142 .Case("typeIdentifier",143 DeclarationFragments::FragmentKind::TypeIdentifier)144 .Case("genericParameter",145 DeclarationFragments::FragmentKind::GenericParameter)146 .Case("internalParam", DeclarationFragments::FragmentKind::InternalParam)147 .Case("externalParam", DeclarationFragments::FragmentKind::ExternalParam)148 .Case("text", DeclarationFragments::FragmentKind::Text)149 .Default(DeclarationFragments::FragmentKind::None);150}151 152DeclarationFragments DeclarationFragments::getExceptionSpecificationString(153 ExceptionSpecificationType ExceptionSpec) {154 DeclarationFragments Fragments;155 switch (ExceptionSpec) {156 case ExceptionSpecificationType::EST_None:157 return Fragments;158 case ExceptionSpecificationType::EST_DynamicNone:159 return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)160 .append("throw", DeclarationFragments::FragmentKind::Keyword)161 .append("(", DeclarationFragments::FragmentKind::Text)162 .append(")", DeclarationFragments::FragmentKind::Text);163 case ExceptionSpecificationType::EST_Dynamic:164 // FIXME: throw(int), get types of inner expression165 return Fragments;166 case ExceptionSpecificationType::EST_BasicNoexcept:167 return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)168 .append("noexcept", DeclarationFragments::FragmentKind::Keyword);169 case ExceptionSpecificationType::EST_DependentNoexcept:170 // FIXME: throw(conditional-expression), get expression171 break;172 case ExceptionSpecificationType::EST_NoexceptFalse:173 return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)174 .append("noexcept", DeclarationFragments::FragmentKind::Keyword)175 .append("(", DeclarationFragments::FragmentKind::Text)176 .append("false", DeclarationFragments::FragmentKind::Keyword)177 .append(")", DeclarationFragments::FragmentKind::Text);178 case ExceptionSpecificationType::EST_NoexceptTrue:179 return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)180 .append("noexcept", DeclarationFragments::FragmentKind::Keyword)181 .append("(", DeclarationFragments::FragmentKind::Text)182 .append("true", DeclarationFragments::FragmentKind::Keyword)183 .append(")", DeclarationFragments::FragmentKind::Text);184 default:185 return Fragments;186 }187 188 llvm_unreachable("Unhandled exception specification");189}190 191DeclarationFragments192DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) {193 DeclarationFragments Fragments;194 if (Record->isStruct())195 Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);196 else if (Record->isUnion())197 Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);198 else199 Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);200 201 return Fragments;202}203 204// NNS stores C++ nested name specifiers, which are prefixes to qualified names.205// Build declaration fragments for NNS recursively so that we have the USR for206// every part in a qualified name, and also leaves the actual underlying type207// cleaner for its own fragment.208DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNNS(209 NestedNameSpecifier NNS, ASTContext &Context, DeclarationFragments &After) {210 DeclarationFragments Fragments;211 switch (NNS.getKind()) {212 case NestedNameSpecifier::Kind::Null:213 return Fragments;214 215 case NestedNameSpecifier::Kind::Namespace: {216 auto [Namespace, Prefix] = NNS.getAsNamespaceAndPrefix();217 Fragments.append(getFragmentsForNNS(Prefix, Context, After));218 if (const auto *NS = dyn_cast<NamespaceDecl>(Namespace);219 NS && NS->isAnonymousNamespace())220 return Fragments;221 SmallString<128> USR;222 index::generateUSRForDecl(Namespace, USR);223 Fragments.append(Namespace->getName(),224 DeclarationFragments::FragmentKind::Identifier, USR,225 Namespace);226 break;227 }228 229 case NestedNameSpecifier::Kind::Global:230 // The global specifier `::` at the beginning. No stored value.231 break;232 233 case NestedNameSpecifier::Kind::MicrosoftSuper:234 // Microsoft's `__super` specifier.235 Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword);236 break;237 238 case NestedNameSpecifier::Kind::Type: {239 // FIXME: Handle C++ template specialization type240 Fragments.append(getFragmentsForType(NNS.getAsType(), Context, After));241 break;242 }243 }244 245 // Add the separator text `::` for this segment.246 return Fragments.append("::", DeclarationFragments::FragmentKind::Text);247}248 249// Recursively build the declaration fragments for an underlying `Type` with250// qualifiers removed.251DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(252 const Type *T, ASTContext &Context, DeclarationFragments &After) {253 assert(T && "invalid type");254 255 DeclarationFragments Fragments;256 257 if (const MacroQualifiedType *MQT = dyn_cast<MacroQualifiedType>(T)) {258 Fragments.append(259 getFragmentsForType(MQT->getUnderlyingType(), Context, After));260 return Fragments;261 }262 263 if (const AttributedType *AT = dyn_cast<AttributedType>(T)) {264 // FIXME: Serialize Attributes correctly265 Fragments.append(266 getFragmentsForType(AT->getModifiedType(), Context, After));267 return Fragments;268 }269 270 // If the type is a typedefed type, get the underlying TypedefNameDecl for a271 // direct reference to the typedef instead of the wrapped type.272 273 // 'id' type is a typedef for an ObjCObjectPointerType274 // we treat it as a typedef275 if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) {276 const TypedefNameDecl *Decl = TypedefTy->getDecl();277 TypedefUnderlyingTypeResolver TypedefResolver(Context);278 std::string USR = TypedefResolver.getUSRForType(QualType(T, 0));279 280 if (ElaboratedTypeKeyword Keyword = TypedefTy->getKeyword();281 Keyword != ElaboratedTypeKeyword::None) {282 Fragments283 .append(KeywordHelpers::getKeywordName(Keyword),284 DeclarationFragments::FragmentKind::Keyword)285 .appendSpace();286 }287 288 Fragments.append(289 getFragmentsForNNS(TypedefTy->getQualifier(), Context, After));290 291 if (TypedefTy->isObjCIdType()) {292 return Fragments.append(Decl->getName(),293 DeclarationFragments::FragmentKind::Keyword);294 }295 296 return Fragments.append(297 Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier,298 USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0)));299 }300 301 // Declaration fragments of a pointer type is the declaration fragments of302 // the pointee type followed by a `*`,303 if (T->isPointerType() && !T->isFunctionPointerType()) {304 QualType PointeeT = T->getPointeeType();305 Fragments.append(getFragmentsForType(PointeeT, Context, After));306 // If the pointee is itself a pointer, we do not want to insert a space307 // before the `*` as the preceding character in the type name is a `*`.308 if (!PointeeT->isAnyPointerType())309 Fragments.appendSpace();310 return Fragments.append("*", DeclarationFragments::FragmentKind::Text);311 }312 313 // For Objective-C `id` and `Class` pointers314 // we do not spell out the `*`.315 if (T->isObjCObjectPointerType() &&316 !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) {317 318 Fragments.append(getFragmentsForType(T->getPointeeType(), Context, After));319 320 // id<protocol> is an qualified id type321 // id<protocol>* is not an qualified id type322 if (!T->getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) {323 Fragments.append(" *", DeclarationFragments::FragmentKind::Text);324 }325 326 return Fragments;327 }328 329 // Declaration fragments of a lvalue reference type is the declaration330 // fragments of the underlying type followed by a `&`.331 if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T))332 return Fragments333 .append(334 getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After))335 .append(" &", DeclarationFragments::FragmentKind::Text);336 337 // Declaration fragments of a rvalue reference type is the declaration338 // fragments of the underlying type followed by a `&&`.339 if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T))340 return Fragments341 .append(342 getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After))343 .append(" &&", DeclarationFragments::FragmentKind::Text);344 345 // Declaration fragments of an array-typed variable have two parts:346 // 1. the element type of the array that appears before the variable name;347 // 2. array brackets `[(0-9)?]` that appear after the variable name.348 if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) {349 // Build the "after" part first because the inner element type might also350 // be an array-type. For example `int matrix[3][4]` which has a type of351 // "(array 3 of (array 4 of ints))."352 // Push the array size part first to make sure they are in the right order.353 After.append("[", DeclarationFragments::FragmentKind::Text);354 355 switch (AT->getSizeModifier()) {356 case ArraySizeModifier::Normal:357 break;358 case ArraySizeModifier::Static:359 Fragments.append("static", DeclarationFragments::FragmentKind::Keyword);360 break;361 case ArraySizeModifier::Star:362 Fragments.append("*", DeclarationFragments::FragmentKind::Text);363 break;364 }365 366 if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {367 // FIXME: right now this would evaluate any expressions/macros written in368 // the original source to concrete values. For example369 // `int nums[MAX]` -> `int nums[100]`370 // `char *str[5 + 1]` -> `char *str[6]`371 SmallString<128> Size;372 CAT->getSize().toStringUnsigned(Size);373 After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral);374 }375 376 After.append("]", DeclarationFragments::FragmentKind::Text);377 378 return Fragments.append(379 getFragmentsForType(AT->getElementType(), Context, After));380 }381 382 if (const TemplateSpecializationType *TemplSpecTy =383 dyn_cast<TemplateSpecializationType>(T)) {384 if (ElaboratedTypeKeyword Keyword = TemplSpecTy->getKeyword();385 Keyword != ElaboratedTypeKeyword::None)386 Fragments387 .append(KeywordHelpers::getKeywordName(Keyword),388 DeclarationFragments::FragmentKind::Keyword)389 .appendSpace();390 391 auto TemplName = TemplSpecTy->getTemplateName();392 std::string Str;393 raw_string_ostream Stream(Str);394 TemplName.print(Stream, Context.getPrintingPolicy(),395 TemplateName::Qualified::AsWritten);396 SmallString<64> USR("");397 if (const auto *QTN = TemplName.getAsQualifiedTemplateName()) {398 Fragments.append(getFragmentsForNNS(QTN->getQualifier(), Context, After));399 TemplName = QTN->getUnderlyingTemplate();400 }401 if (const auto *TemplDecl = TemplName.getAsTemplateDecl())402 index::generateUSRForDecl(TemplDecl, USR);403 // FIXME: Handle other kinds of TemplateNames.404 405 return Fragments406 .append(Str, DeclarationFragments::FragmentKind::TypeIdentifier, USR)407 .append("<", DeclarationFragments::FragmentKind::Text)408 .append(getFragmentsForTemplateArguments(409 TemplSpecTy->template_arguments(), Context, std::nullopt))410 .append(">", DeclarationFragments::FragmentKind::Text);411 }412 413 // If the base type is a TagType (struct/interface/union/class/enum), let's414 // get the underlying Decl for better names and USRs.415 if (const TagType *TagTy = dyn_cast<TagType>(T)) {416 if (ElaboratedTypeKeyword Keyword = TagTy->getKeyword();417 Keyword != ElaboratedTypeKeyword::None)418 Fragments419 .append(KeywordHelpers::getKeywordName(Keyword),420 DeclarationFragments::FragmentKind::Keyword)421 .appendSpace();422 423 Fragments.append(getFragmentsForNNS(TagTy->getQualifier(), Context, After));424 425 const TagDecl *Decl = TagTy->getDecl();426 // Anonymous decl, skip this fragment.427 if (Decl->getName().empty())428 return Fragments.append("{ ... }",429 DeclarationFragments::FragmentKind::Text);430 SmallString<128> TagUSR;431 clang::index::generateUSRForDecl(Decl, TagUSR);432 return Fragments.append(Decl->getName(),433 DeclarationFragments::FragmentKind::TypeIdentifier,434 TagUSR, Decl);435 }436 437 // Everything we care about has been handled now, reduce to the canonical438 // unqualified base type.439 QualType Base = T->getCanonicalTypeUnqualified();440 441 // If the base type is an ObjCInterfaceType, use the underlying442 // ObjCInterfaceDecl for the true USR.443 if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) {444 const auto *Decl = ObjCIT->getDecl();445 SmallString<128> USR;446 index::generateUSRForDecl(Decl, USR);447 return Fragments.append(Decl->getName(),448 DeclarationFragments::FragmentKind::TypeIdentifier,449 USR, Decl);450 }451 452 // Default fragment builder for other kinds of types (BuiltinType etc.)453 SmallString<128> USR;454 clang::index::generateUSRForType(Base, Context, USR);455 Fragments.append(Base.getAsString(),456 DeclarationFragments::FragmentKind::TypeIdentifier, USR);457 458 return Fragments;459}460 461DeclarationFragments462DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) {463 DeclarationFragments Fragments;464 if (Quals.hasConst())465 Fragments.append("const", DeclarationFragments::FragmentKind::Keyword);466 if (Quals.hasVolatile())467 Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword);468 if (Quals.hasRestrict())469 Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword);470 471 return Fragments;472}473 474DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(475 const QualType QT, ASTContext &Context, DeclarationFragments &After) {476 assert(!QT.isNull() && "invalid type");477 478 if (const ParenType *PT = dyn_cast<ParenType>(QT)) {479 After.append(")", DeclarationFragments::FragmentKind::Text);480 return getFragmentsForType(PT->getInnerType(), Context, After)481 .append("(", DeclarationFragments::FragmentKind::Text);482 }483 484 const SplitQualType SQT = QT.split();485 DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals),486 TypeFragments =487 getFragmentsForType(SQT.Ty, Context, After);488 if (QT.getAsString() == "_Bool")489 TypeFragments.replace("bool", 0);490 491 if (QualsFragments.getFragments().empty())492 return TypeFragments;493 494 // Use east qualifier for pointer types495 // For example:496 // ```497 // int * const498 // ^---- ^----499 // type qualifier500 // ^-----------------501 // const pointer to int502 // ```503 // should not be reconstructed as504 // ```505 // const int *506 // ^---- ^--507 // qualifier type508 // ^---------------- ^509 // pointer to const int510 // ```511 if (SQT.Ty->isAnyPointerType())512 return TypeFragments.appendSpace().append(std::move(QualsFragments));513 514 return QualsFragments.appendSpace().append(std::move(TypeFragments));515}516 517DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace(518 const NamespaceDecl *Decl) {519 DeclarationFragments Fragments;520 Fragments.append("namespace", DeclarationFragments::FragmentKind::Keyword);521 if (!Decl->isAnonymousNamespace())522 Fragments.appendSpace().append(523 Decl->getName(), DeclarationFragments::FragmentKind::Identifier);524 return Fragments.appendSemicolon();525}526 527DeclarationFragments528DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {529 DeclarationFragments Fragments;530 if (Var->isConstexpr())531 Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)532 .appendSpace();533 534 StorageClass SC = Var->getStorageClass();535 if (SC != SC_None)536 Fragments537 .append(VarDecl::getStorageClassSpecifierString(SC),538 DeclarationFragments::FragmentKind::Keyword)539 .appendSpace();540 541 // Capture potential fragments that needs to be placed after the variable name542 // ```543 // int nums[5];544 // char (*ptr_to_array)[6];545 // ```546 DeclarationFragments After;547 FunctionTypeLoc BlockLoc;548 FunctionProtoTypeLoc BlockProtoLoc;549 findTypeLocForBlockDecl(Var->getTypeSourceInfo(), BlockLoc, BlockProtoLoc);550 551 if (!BlockLoc) {552 QualType T = Var->getTypeSourceInfo()553 ? Var->getTypeSourceInfo()->getType()554 : Var->getASTContext().getUnqualifiedObjCPointerType(555 Var->getType());556 557 Fragments.append(getFragmentsForType(T, Var->getASTContext(), After))558 .appendSpace();559 } else {560 Fragments.append(getFragmentsForBlock(Var, BlockLoc, BlockProtoLoc, After));561 }562 563 return Fragments564 .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)565 .append(std::move(After))566 .appendSemicolon();567}568 569DeclarationFragments570DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) {571 DeclarationFragments Fragments;572 if (Var->isConstexpr())573 Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)574 .appendSpace();575 QualType T =576 Var->getTypeSourceInfo()577 ? Var->getTypeSourceInfo()->getType()578 : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType());579 580 // Might be a member, so might be static.581 if (Var->isStaticDataMember())582 Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)583 .appendSpace();584 585 DeclarationFragments After;586 DeclarationFragments ArgumentFragment =587 getFragmentsForType(T, Var->getASTContext(), After);588 if (StringRef(ArgumentFragment.begin()->Spelling)589 .starts_with("type-parameter")) {590 std::string ProperArgName = T.getAsString();591 ArgumentFragment.begin()->Spelling.swap(ProperArgName);592 }593 Fragments.append(std::move(ArgumentFragment))594 .appendSpace()595 .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)596 .appendSemicolon();597 return Fragments;598}599 600DeclarationFragments601DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) {602 DeclarationFragments Fragments, After;603 604 auto *TSInfo = Param->getTypeSourceInfo();605 606 QualType T = TSInfo ? TSInfo->getType()607 : Param->getASTContext().getUnqualifiedObjCPointerType(608 Param->getType());609 610 FunctionTypeLoc BlockLoc;611 FunctionProtoTypeLoc BlockProtoLoc;612 findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc);613 614 DeclarationFragments TypeFragments;615 if (BlockLoc)616 TypeFragments.append(617 getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After));618 else619 TypeFragments.append(getFragmentsForType(T, Param->getASTContext(), After));620 621 if (StringRef(TypeFragments.begin()->Spelling)622 .starts_with("type-parameter")) {623 std::string ProperArgName = Param->getOriginalType().getAsString();624 TypeFragments.begin()->Spelling.swap(ProperArgName);625 }626 627 if (Param->isObjCMethodParameter()) {628 Fragments.append("(", DeclarationFragments::FragmentKind::Text)629 .append(std::move(TypeFragments))630 .append(std::move(After))631 .append(") ", DeclarationFragments::FragmentKind::Text)632 .append(Param->getName(),633 DeclarationFragments::FragmentKind::InternalParam);634 } else {635 Fragments.append(std::move(TypeFragments));636 if (!T->isAnyPointerType() && !T->isBlockPointerType())637 Fragments.appendSpace();638 Fragments639 .append(Param->getName(),640 DeclarationFragments::FragmentKind::InternalParam)641 .append(std::move(After));642 }643 return Fragments;644}645 646DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForBlock(647 const NamedDecl *BlockDecl, FunctionTypeLoc &Block,648 FunctionProtoTypeLoc &BlockProto, DeclarationFragments &After) {649 DeclarationFragments Fragments;650 651 DeclarationFragments RetTyAfter;652 auto ReturnValueFragment = getFragmentsForType(653 Block.getTypePtr()->getReturnType(), BlockDecl->getASTContext(), After);654 655 Fragments.append(std::move(ReturnValueFragment))656 .append(std::move(RetTyAfter))657 .appendSpace()658 .append("(^", DeclarationFragments::FragmentKind::Text);659 660 After.append(")", DeclarationFragments::FragmentKind::Text);661 unsigned NumParams = Block.getNumParams();662 663 if (!BlockProto || NumParams == 0) {664 if (BlockProto && BlockProto.getTypePtr()->isVariadic())665 After.append("(...)", DeclarationFragments::FragmentKind::Text);666 else667 After.append("()", DeclarationFragments::FragmentKind::Text);668 } else {669 After.append("(", DeclarationFragments::FragmentKind::Text);670 for (unsigned I = 0; I != NumParams; ++I) {671 if (I)672 After.append(", ", DeclarationFragments::FragmentKind::Text);673 After.append(getFragmentsForParam(Block.getParam(I)));674 if (I == NumParams - 1 && BlockProto.getTypePtr()->isVariadic())675 After.append(", ...", DeclarationFragments::FragmentKind::Text);676 }677 After.append(")", DeclarationFragments::FragmentKind::Text);678 }679 680 return Fragments;681}682 683DeclarationFragments684DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {685 DeclarationFragments Fragments;686 switch (Func->getStorageClass()) {687 case SC_None:688 case SC_PrivateExtern:689 break;690 case SC_Extern:691 Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword)692 .appendSpace();693 break;694 case SC_Static:695 Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)696 .appendSpace();697 break;698 case SC_Auto:699 case SC_Register:700 llvm_unreachable("invalid for functions");701 }702 if (Func->isConsteval()) // if consteval, it is also constexpr703 Fragments.append("consteval", DeclarationFragments::FragmentKind::Keyword)704 .appendSpace();705 else if (Func->isConstexpr())706 Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)707 .appendSpace();708 709 // FIXME: Is `after` actually needed here?710 DeclarationFragments After;711 QualType ReturnType = Func->getReturnType();712 auto ReturnValueFragment =713 getFragmentsForType(ReturnType, Func->getASTContext(), After);714 if (StringRef(ReturnValueFragment.begin()->Spelling)715 .starts_with("type-parameter")) {716 std::string ProperArgName = ReturnType.getAsString();717 ReturnValueFragment.begin()->Spelling.swap(ProperArgName);718 }719 720 Fragments.append(std::move(ReturnValueFragment));721 if (!ReturnType->isAnyPointerType())722 Fragments.appendSpace();723 Fragments.append(Func->getNameAsString(),724 DeclarationFragments::FragmentKind::Identifier);725 726 if (Func->getTemplateSpecializationInfo()) {727 Fragments.append("<", DeclarationFragments::FragmentKind::Text);728 729 for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) {730 if (i)731 Fragments.append(", ", DeclarationFragments::FragmentKind::Text);732 Fragments.append(733 getFragmentsForType(Func->getParamDecl(i)->getType(),734 Func->getParamDecl(i)->getASTContext(), After));735 }736 Fragments.append(">", DeclarationFragments::FragmentKind::Text);737 }738 Fragments.append(std::move(After));739 740 Fragments.append("(", DeclarationFragments::FragmentKind::Text);741 unsigned NumParams = Func->getNumParams();742 for (unsigned i = 0; i != NumParams; ++i) {743 if (i)744 Fragments.append(", ", DeclarationFragments::FragmentKind::Text);745 Fragments.append(getFragmentsForParam(Func->getParamDecl(i)));746 }747 748 if (Func->isVariadic()) {749 if (NumParams > 0)750 Fragments.append(", ", DeclarationFragments::FragmentKind::Text);751 Fragments.append("...", DeclarationFragments::FragmentKind::Text);752 }753 Fragments.append(")", DeclarationFragments::FragmentKind::Text);754 755 Fragments.append(DeclarationFragments::getExceptionSpecificationString(756 Func->getExceptionSpecType()));757 758 return Fragments.appendSemicolon();759}760 761DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant(762 const EnumConstantDecl *EnumConstDecl) {763 DeclarationFragments Fragments;764 return Fragments.append(EnumConstDecl->getName(),765 DeclarationFragments::FragmentKind::Identifier);766}767 768DeclarationFragments769DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {770 if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl())771 return getFragmentsForTypedef(TypedefNameDecl);772 773 DeclarationFragments Fragments, After;774 Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword);775 776 if (!EnumDecl->getName().empty())777 Fragments.appendSpace().append(778 EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier);779 780 QualType IntegerType = EnumDecl->getIntegerType();781 if (!IntegerType.isNull())782 Fragments.appendSpace()783 .append(": ", DeclarationFragments::FragmentKind::Text)784 .append(785 getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))786 .append(std::move(After));787 788 if (EnumDecl->getName().empty())789 Fragments.appendSpace().append("{ ... }",790 DeclarationFragments::FragmentKind::Text);791 792 return Fragments.appendSemicolon();793}794 795DeclarationFragments796DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) {797 DeclarationFragments After;798 DeclarationFragments Fragments;799 if (Field->isMutable())800 Fragments.append("mutable", DeclarationFragments::FragmentKind::Keyword)801 .appendSpace();802 return Fragments803 .append(804 getFragmentsForType(Field->getType(), Field->getASTContext(), After))805 .appendSpace()806 .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)807 .append(std::move(After))808 .appendSemicolon();809}810 811DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(812 const RecordDecl *Record) {813 if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())814 return getFragmentsForTypedef(TypedefNameDecl);815 816 DeclarationFragments Fragments;817 if (Record->isUnion())818 Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);819 else820 Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);821 822 Fragments.appendSpace();823 if (!Record->getName().empty())824 Fragments.append(Record->getName(),825 DeclarationFragments::FragmentKind::Identifier);826 else827 Fragments.append("{ ... }", DeclarationFragments::FragmentKind::Text);828 829 return Fragments.appendSemicolon();830}831 832DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(833 const CXXRecordDecl *Record) {834 if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())835 return getFragmentsForTypedef(TypedefNameDecl);836 837 DeclarationFragments Fragments;838 Fragments.append(DeclarationFragments::getStructureTypeFragment(Record));839 840 if (!Record->getName().empty())841 Fragments.appendSpace().append(842 Record->getName(), DeclarationFragments::FragmentKind::Identifier);843 844 return Fragments.appendSemicolon();845}846 847DeclarationFragments848DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(849 const CXXMethodDecl *Method) {850 DeclarationFragments Fragments;851 std::string Name;852 if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(Method)) {853 Name = Method->getNameAsString();854 if (Constructor->isExplicit())855 Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)856 .appendSpace();857 } else if (isa<CXXDestructorDecl>(Method))858 Name = Method->getNameAsString();859 860 DeclarationFragments After;861 Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier)862 .append(std::move(After));863 Fragments.append("(", DeclarationFragments::FragmentKind::Text);864 for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {865 if (i)866 Fragments.append(", ", DeclarationFragments::FragmentKind::Text);867 Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));868 }869 Fragments.append(")", DeclarationFragments::FragmentKind::Text);870 871 Fragments.append(DeclarationFragments::getExceptionSpecificationString(872 Method->getExceptionSpecType()));873 874 return Fragments.appendSemicolon();875}876 877DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(878 const CXXMethodDecl *Method) {879 DeclarationFragments Fragments;880 StringRef Name = Method->getName();881 if (Method->isStatic())882 Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)883 .appendSpace();884 if (Method->isConstexpr())885 Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)886 .appendSpace();887 if (Method->isVolatile())888 Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword)889 .appendSpace();890 if (Method->isVirtual())891 Fragments.append("virtual", DeclarationFragments::FragmentKind::Keyword)892 .appendSpace();893 894 // Build return type895 DeclarationFragments After;896 Fragments897 .append(getFragmentsForType(Method->getReturnType(),898 Method->getASTContext(), After))899 .appendSpace()900 .append(Name, DeclarationFragments::FragmentKind::Identifier)901 .append(std::move(After));902 Fragments.append("(", DeclarationFragments::FragmentKind::Text);903 for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {904 if (i)905 Fragments.append(", ", DeclarationFragments::FragmentKind::Text);906 Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));907 }908 Fragments.append(")", DeclarationFragments::FragmentKind::Text);909 910 if (Method->isConst())911 Fragments.appendSpace().append("const",912 DeclarationFragments::FragmentKind::Keyword);913 914 Fragments.append(DeclarationFragments::getExceptionSpecificationString(915 Method->getExceptionSpecType()));916 917 return Fragments.appendSemicolon();918}919 920DeclarationFragments921DeclarationFragmentsBuilder::getFragmentsForConversionFunction(922 const CXXConversionDecl *ConversionFunction) {923 DeclarationFragments Fragments;924 925 if (ConversionFunction->isExplicit())926 Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)927 .appendSpace();928 929 Fragments.append("operator", DeclarationFragments::FragmentKind::Keyword)930 .appendSpace();931 932 Fragments933 .append(ConversionFunction->getConversionType().getAsString(),934 DeclarationFragments::FragmentKind::TypeIdentifier)935 .append("(", DeclarationFragments::FragmentKind::Text);936 for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end;937 ++i) {938 if (i)939 Fragments.append(", ", DeclarationFragments::FragmentKind::Text);940 Fragments.append(getFragmentsForParam(ConversionFunction->getParamDecl(i)));941 }942 Fragments.append(")", DeclarationFragments::FragmentKind::Text);943 944 if (ConversionFunction->isConst())945 Fragments.appendSpace().append("const",946 DeclarationFragments::FragmentKind::Keyword);947 948 return Fragments.appendSemicolon();949}950 951DeclarationFragments952DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(953 const CXXMethodDecl *Method) {954 DeclarationFragments Fragments;955 956 // Build return type957 DeclarationFragments After;958 Fragments959 .append(getFragmentsForType(Method->getReturnType(),960 Method->getASTContext(), After))961 .appendSpace()962 .append(Method->getNameAsString(),963 DeclarationFragments::FragmentKind::Identifier)964 .append(std::move(After));965 Fragments.append("(", DeclarationFragments::FragmentKind::Text);966 for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {967 if (i)968 Fragments.append(", ", DeclarationFragments::FragmentKind::Text);969 Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));970 }971 Fragments.append(")", DeclarationFragments::FragmentKind::Text);972 973 if (Method->isConst())974 Fragments.appendSpace().append("const",975 DeclarationFragments::FragmentKind::Keyword);976 977 Fragments.append(DeclarationFragments::getExceptionSpecificationString(978 Method->getExceptionSpecType()));979 980 return Fragments.appendSemicolon();981}982 983// Get fragments for template parameters, e.g. T in tempalte<typename T> ...984DeclarationFragments985DeclarationFragmentsBuilder::getFragmentsForTemplateParameters(986 ArrayRef<NamedDecl *> ParameterArray) {987 DeclarationFragments Fragments;988 for (unsigned i = 0, end = ParameterArray.size(); i != end; ++i) {989 if (i)990 Fragments.append(",", DeclarationFragments::FragmentKind::Text)991 .appendSpace();992 993 if (const auto *TemplateParam =994 dyn_cast<TemplateTypeParmDecl>(ParameterArray[i])) {995 if (TemplateParam->hasTypeConstraint())996 Fragments.append(TemplateParam->getTypeConstraint()997 ->getNamedConcept()998 ->getName()999 .str(),1000 DeclarationFragments::FragmentKind::TypeIdentifier);1001 else if (TemplateParam->wasDeclaredWithTypename())1002 Fragments.append("typename",1003 DeclarationFragments::FragmentKind::Keyword);1004 else1005 Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);1006 1007 if (TemplateParam->isParameterPack())1008 Fragments.append("...", DeclarationFragments::FragmentKind::Text);1009 1010 if (!TemplateParam->getName().empty())1011 Fragments.appendSpace().append(1012 TemplateParam->getName(),1013 DeclarationFragments::FragmentKind::GenericParameter);1014 1015 if (TemplateParam->hasDefaultArgument()) {1016 const auto Default = TemplateParam->getDefaultArgument();1017 Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)1018 .append(getFragmentsForTemplateArguments(1019 {Default.getArgument()}, TemplateParam->getASTContext(),1020 {Default}));1021 }1022 } else if (const auto *NTP =1023 dyn_cast<NonTypeTemplateParmDecl>(ParameterArray[i])) {1024 DeclarationFragments After;1025 const auto TyFragments =1026 getFragmentsForType(NTP->getType(), NTP->getASTContext(), After);1027 Fragments.append(std::move(TyFragments)).append(std::move(After));1028 1029 if (NTP->isParameterPack())1030 Fragments.append("...", DeclarationFragments::FragmentKind::Text);1031 1032 if (!NTP->getName().empty())1033 Fragments.appendSpace().append(1034 NTP->getName(),1035 DeclarationFragments::FragmentKind::GenericParameter);1036 1037 if (NTP->hasDefaultArgument()) {1038 SmallString<8> ExprStr;1039 raw_svector_ostream Output(ExprStr);1040 NTP->getDefaultArgument().getArgument().print(1041 NTP->getASTContext().getPrintingPolicy(), Output,1042 /*IncludeType=*/false);1043 Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)1044 .append(ExprStr, DeclarationFragments::FragmentKind::Text);1045 }1046 } else if (const auto *TTP =1047 dyn_cast<TemplateTemplateParmDecl>(ParameterArray[i])) {1048 Fragments.append("template", DeclarationFragments::FragmentKind::Keyword)1049 .appendSpace()1050 .append("<", DeclarationFragments::FragmentKind::Text)1051 .append(getFragmentsForTemplateParameters(1052 TTP->getTemplateParameters()->asArray()))1053 .append(">", DeclarationFragments::FragmentKind::Text)1054 .appendSpace()1055 .append(TTP->wasDeclaredWithTypename() ? "typename" : "class",1056 DeclarationFragments::FragmentKind::Keyword);1057 1058 if (TTP->isParameterPack())1059 Fragments.append("...", DeclarationFragments::FragmentKind::Text);1060 1061 if (!TTP->getName().empty())1062 Fragments.appendSpace().append(1063 TTP->getName(),1064 DeclarationFragments::FragmentKind::GenericParameter);1065 if (TTP->hasDefaultArgument()) {1066 const auto Default = TTP->getDefaultArgument();1067 Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)1068 .append(getFragmentsForTemplateArguments(1069 {Default.getArgument()}, TTP->getASTContext(), {Default}));1070 }1071 }1072 }1073 return Fragments;1074}1075 1076// Get fragments for template arguments, e.g. int in template<typename T>1077// Foo<int>;1078//1079// Note: TemplateParameters is only necessary if the Decl is a1080// PartialSpecialization, where we need the parameters to deduce the name of the1081// generic arguments.1082DeclarationFragments1083DeclarationFragmentsBuilder::getFragmentsForTemplateArguments(1084 const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context,1085 const std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs) {1086 DeclarationFragments Fragments;1087 for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) {1088 if (i)1089 Fragments.append(",", DeclarationFragments::FragmentKind::Text)1090 .appendSpace();1091 1092 const auto &CTA = TemplateArguments[i];1093 switch (CTA.getKind()) {1094 case TemplateArgument::Type: {1095 DeclarationFragments After;1096 DeclarationFragments ArgumentFragment =1097 getFragmentsForType(CTA.getAsType(), Context, After);1098 1099 if (StringRef(ArgumentFragment.begin()->Spelling)1100 .starts_with("type-parameter")) {1101 if (TemplateArgumentLocs.has_value() &&1102 TemplateArgumentLocs->size() > i) {1103 std::string ProperArgName = TemplateArgumentLocs.value()[i]1104 .getTypeSourceInfo()1105 ->getType()1106 .getAsString();1107 ArgumentFragment.begin()->Spelling.swap(ProperArgName);1108 } else {1109 auto &Spelling = ArgumentFragment.begin()->Spelling;1110 Spelling.clear();1111 raw_string_ostream OutStream(Spelling);1112 CTA.print(Context.getPrintingPolicy(), OutStream, false);1113 }1114 }1115 1116 Fragments.append(std::move(ArgumentFragment));1117 break;1118 }1119 case TemplateArgument::Declaration: {1120 const auto *VD = CTA.getAsDecl();1121 SmallString<128> USR;1122 index::generateUSRForDecl(VD, USR);1123 Fragments.append(VD->getNameAsString(),1124 DeclarationFragments::FragmentKind::Identifier, USR);1125 break;1126 }1127 case TemplateArgument::NullPtr:1128 Fragments.append("nullptr", DeclarationFragments::FragmentKind::Keyword);1129 break;1130 1131 case TemplateArgument::Integral: {1132 SmallString<4> Str;1133 CTA.getAsIntegral().toString(Str);1134 Fragments.append(Str, DeclarationFragments::FragmentKind::Text);1135 break;1136 }1137 1138 case TemplateArgument::StructuralValue: {1139 const auto SVTy = CTA.getStructuralValueType();1140 Fragments.append(CTA.getAsStructuralValue().getAsString(Context, SVTy),1141 DeclarationFragments::FragmentKind::Text);1142 break;1143 }1144 1145 case TemplateArgument::TemplateExpansion:1146 case TemplateArgument::Template: {1147 std::string Str;1148 raw_string_ostream Stream(Str);1149 CTA.getAsTemplate().print(Stream, Context.getPrintingPolicy());1150 SmallString<64> USR("");1151 if (const auto *TemplDecl =1152 CTA.getAsTemplateOrTemplatePattern().getAsTemplateDecl())1153 index::generateUSRForDecl(TemplDecl, USR);1154 Fragments.append(Str, DeclarationFragments::FragmentKind::TypeIdentifier,1155 USR);1156 if (CTA.getKind() == TemplateArgument::TemplateExpansion)1157 Fragments.append("...", DeclarationFragments::FragmentKind::Text);1158 break;1159 }1160 1161 case TemplateArgument::Pack:1162 Fragments.append("<", DeclarationFragments::FragmentKind::Text)1163 .append(getFragmentsForTemplateArguments(CTA.pack_elements(), Context,1164 {}))1165 .append(">", DeclarationFragments::FragmentKind::Text);1166 break;1167 1168 case TemplateArgument::Expression: {1169 SmallString<8> ExprStr;1170 raw_svector_ostream Output(ExprStr);1171 CTA.getAsExpr()->printPretty(Output, nullptr,1172 Context.getPrintingPolicy());1173 Fragments.append(ExprStr, DeclarationFragments::FragmentKind::Text);1174 break;1175 }1176 1177 case TemplateArgument::Null:1178 break;1179 }1180 }1181 return Fragments;1182}1183 1184DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept(1185 const ConceptDecl *Concept) {1186 DeclarationFragments Fragments;1187 return Fragments1188 .append("template", DeclarationFragments::FragmentKind::Keyword)1189 .appendSpace()1190 .append("<", DeclarationFragments::FragmentKind::Text)1191 .append(getFragmentsForTemplateParameters(1192 Concept->getTemplateParameters()->asArray()))1193 .append("> ", DeclarationFragments::FragmentKind::Text)1194 .appendSpace()1195 .append("concept", DeclarationFragments::FragmentKind::Keyword)1196 .appendSpace()1197 .append(Concept->getName().str(),1198 DeclarationFragments::FragmentKind::Identifier)1199 .appendSemicolon();1200}1201 1202DeclarationFragments1203DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(1204 const RedeclarableTemplateDecl *RedeclarableTemplate) {1205 DeclarationFragments Fragments;1206 Fragments.append("template", DeclarationFragments::FragmentKind::Keyword)1207 .appendSpace()1208 .append("<", DeclarationFragments::FragmentKind::Text)1209 .append(getFragmentsForTemplateParameters(1210 RedeclarableTemplate->getTemplateParameters()->asArray()))1211 .append(">", DeclarationFragments::FragmentKind::Text)1212 .appendSpace();1213 1214 if (isa<TypeAliasTemplateDecl>(RedeclarableTemplate))1215 Fragments.appendSpace()1216 .append("using", DeclarationFragments::FragmentKind::Keyword)1217 .appendSpace()1218 .append(RedeclarableTemplate->getName(),1219 DeclarationFragments::FragmentKind::Identifier);1220 // the templated records will be resposbible for injecting their templates1221 return Fragments.appendSpace();1222}1223 1224DeclarationFragments1225DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization(1226 const ClassTemplateSpecializationDecl *Decl) {1227 DeclarationFragments Fragments;1228 std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs = {};1229 if (auto *TemplateArgs = Decl->getTemplateArgsAsWritten()) {1230 TemplateArgumentLocs = TemplateArgs->arguments();1231 }1232 return Fragments1233 .append("template", DeclarationFragments::FragmentKind::Keyword)1234 .appendSpace()1235 .append("<", DeclarationFragments::FragmentKind::Text)1236 .append(">", DeclarationFragments::FragmentKind::Text)1237 .appendSpace()1238 .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(1239 cast<CXXRecordDecl>(Decl)))1240 .pop_back() // there is an extra semicolon now1241 .append("<", DeclarationFragments::FragmentKind::Text)1242 .append(getFragmentsForTemplateArguments(1243 Decl->getTemplateArgs().asArray(), Decl->getASTContext(),1244 TemplateArgumentLocs))1245 .append(">", DeclarationFragments::FragmentKind::Text)1246 .appendSemicolon();1247}1248 1249DeclarationFragments1250DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization(1251 const ClassTemplatePartialSpecializationDecl *Decl) {1252 DeclarationFragments Fragments;1253 return Fragments1254 .append("template", DeclarationFragments::FragmentKind::Keyword)1255 .appendSpace()1256 .append("<", DeclarationFragments::FragmentKind::Text)1257 .append(getFragmentsForTemplateParameters(1258 Decl->getTemplateParameters()->asArray()))1259 .append(">", DeclarationFragments::FragmentKind::Text)1260 .appendSpace()1261 .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(1262 cast<CXXRecordDecl>(Decl)))1263 .pop_back() // there is an extra semicolon now1264 .append("<", DeclarationFragments::FragmentKind::Text)1265 .append(getFragmentsForTemplateArguments(1266 Decl->getTemplateArgs().asArray(), Decl->getASTContext(),1267 Decl->getTemplateArgsAsWritten()->arguments()))1268 .append(">", DeclarationFragments::FragmentKind::Text)1269 .appendSemicolon();1270}1271 1272DeclarationFragments1273DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization(1274 const VarTemplateSpecializationDecl *Decl) {1275 DeclarationFragments Fragments;1276 return Fragments1277 .append("template", DeclarationFragments::FragmentKind::Keyword)1278 .appendSpace()1279 .append("<", DeclarationFragments::FragmentKind::Text)1280 .append(">", DeclarationFragments::FragmentKind::Text)1281 .appendSpace()1282 .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))1283 .pop_back() // there is an extra semicolon now1284 .append("<", DeclarationFragments::FragmentKind::Text)1285 .append(getFragmentsForTemplateArguments(1286 Decl->getTemplateArgs().asArray(), Decl->getASTContext(),1287 Decl->getTemplateArgsAsWritten()->arguments()))1288 .append(">", DeclarationFragments::FragmentKind::Text)1289 .appendSemicolon();1290}1291 1292DeclarationFragments1293DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization(1294 const VarTemplatePartialSpecializationDecl *Decl) {1295 DeclarationFragments Fragments;1296 return Fragments1297 .append("template", DeclarationFragments::FragmentKind::Keyword)1298 .appendSpace()1299 .append("<", DeclarationFragments::FragmentKind::Text)1300 // Partial specs may have new params.1301 .append(getFragmentsForTemplateParameters(1302 Decl->getTemplateParameters()->asArray()))1303 .append(">", DeclarationFragments::FragmentKind::Text)1304 .appendSpace()1305 .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))1306 .pop_back() // there is an extra semicolon now1307 .append("<", DeclarationFragments::FragmentKind::Text)1308 .append(getFragmentsForTemplateArguments(1309 Decl->getTemplateArgs().asArray(), Decl->getASTContext(),1310 Decl->getTemplateArgsAsWritten()->arguments()))1311 .append(">", DeclarationFragments::FragmentKind::Text)1312 .appendSemicolon();1313}1314 1315DeclarationFragments1316DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(1317 const FunctionTemplateDecl *Decl) {1318 DeclarationFragments Fragments;1319 return Fragments1320 .append("template", DeclarationFragments::FragmentKind::Keyword)1321 .appendSpace()1322 .append("<", DeclarationFragments::FragmentKind::Text)1323 // Partial specs may have new params.1324 .append(getFragmentsForTemplateParameters(1325 Decl->getTemplateParameters()->asArray()))1326 .append(">", DeclarationFragments::FragmentKind::Text)1327 .appendSpace()1328 .append(DeclarationFragmentsBuilder::getFragmentsForFunction(1329 Decl->getAsFunction()));1330}1331 1332DeclarationFragments1333DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization(1334 const FunctionDecl *Decl) {1335 DeclarationFragments Fragments;1336 return Fragments1337 .append("template", DeclarationFragments::FragmentKind::Keyword)1338 .appendSpace()1339 .append("<>", DeclarationFragments::FragmentKind::Text)1340 .appendSpace()1341 .append(DeclarationFragmentsBuilder::getFragmentsForFunction(Decl));1342}1343 1344DeclarationFragments1345DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name,1346 const MacroInfo *MI) {1347 DeclarationFragments Fragments;1348 Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword)1349 .appendSpace();1350 Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);1351 1352 if (MI->isFunctionLike()) {1353 Fragments.append("(", DeclarationFragments::FragmentKind::Text);1354 unsigned numParameters = MI->getNumParams();1355 if (MI->isC99Varargs())1356 --numParameters;1357 for (unsigned i = 0; i < numParameters; ++i) {1358 if (i)1359 Fragments.append(", ", DeclarationFragments::FragmentKind::Text);1360 Fragments.append(MI->params()[i]->getName(),1361 DeclarationFragments::FragmentKind::InternalParam);1362 }1363 if (MI->isVariadic()) {1364 if (numParameters && MI->isC99Varargs())1365 Fragments.append(", ", DeclarationFragments::FragmentKind::Text);1366 Fragments.append("...", DeclarationFragments::FragmentKind::Text);1367 }1368 Fragments.append(")", DeclarationFragments::FragmentKind::Text);1369 }1370 return Fragments;1371}1372 1373DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory(1374 const ObjCCategoryDecl *Category) {1375 DeclarationFragments Fragments;1376 1377 auto *Interface = Category->getClassInterface();1378 SmallString<128> InterfaceUSR;1379 index::generateUSRForDecl(Interface, InterfaceUSR);1380 1381 Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)1382 .appendSpace()1383 .append(Interface->getName(),1384 DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR,1385 Interface)1386 .append(" (", DeclarationFragments::FragmentKind::Text)1387 .append(Category->getName(),1388 DeclarationFragments::FragmentKind::Identifier)1389 .append(")", DeclarationFragments::FragmentKind::Text);1390 1391 return Fragments;1392}1393 1394DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface(1395 const ObjCInterfaceDecl *Interface) {1396 DeclarationFragments Fragments;1397 // Build the base of the Objective-C interface declaration.1398 Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)1399 .appendSpace()1400 .append(Interface->getName(),1401 DeclarationFragments::FragmentKind::Identifier);1402 1403 // Build the inheritance part of the declaration.1404 if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) {1405 SmallString<128> SuperUSR;1406 index::generateUSRForDecl(SuperClass, SuperUSR);1407 Fragments.append(" : ", DeclarationFragments::FragmentKind::Text)1408 .append(SuperClass->getName(),1409 DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR,1410 SuperClass);1411 }1412 1413 return Fragments;1414}1415 1416DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod(1417 const ObjCMethodDecl *Method) {1418 DeclarationFragments Fragments, After;1419 // Build the instance/class method indicator.1420 if (Method->isClassMethod())1421 Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);1422 else if (Method->isInstanceMethod())1423 Fragments.append("- ", DeclarationFragments::FragmentKind::Text);1424 1425 // Build the return type.1426 Fragments.append("(", DeclarationFragments::FragmentKind::Text)1427 .append(getFragmentsForType(Method->getReturnType(),1428 Method->getASTContext(), After))1429 .append(std::move(After))1430 .append(")", DeclarationFragments::FragmentKind::Text);1431 1432 // Build the selector part.1433 Selector Selector = Method->getSelector();1434 if (Selector.getNumArgs() == 0)1435 // For Objective-C methods that don't take arguments, the first (and only)1436 // slot of the selector is the method name.1437 Fragments.appendSpace().append(1438 Selector.getNameForSlot(0),1439 DeclarationFragments::FragmentKind::Identifier);1440 1441 // For Objective-C methods that take arguments, build the selector slots.1442 for (unsigned i = 0, end = Method->param_size(); i != end; ++i) {1443 // Objective-C method selector parts are considered as identifiers instead1444 // of "external parameters" as in Swift. This is because Objective-C method1445 // symbols are referenced with the entire selector, instead of just the1446 // method name in Swift.1447 SmallString<32> ParamID(Selector.getNameForSlot(i));1448 ParamID.append(":");1449 Fragments.appendSpace().append(1450 ParamID, DeclarationFragments::FragmentKind::Identifier);1451 1452 // Build the internal parameter.1453 const ParmVarDecl *Param = Method->getParamDecl(i);1454 Fragments.append(getFragmentsForParam(Param));1455 }1456 1457 return Fragments.appendSemicolon();1458}1459 1460DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(1461 const ObjCPropertyDecl *Property) {1462 DeclarationFragments Fragments, After;1463 1464 // Build the Objective-C property keyword.1465 Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword);1466 1467 const auto Attributes = Property->getPropertyAttributesAsWritten();1468 // Build the attributes if there is any associated with the property.1469 if (Attributes != ObjCPropertyAttribute::kind_noattr) {1470 // No leading comma for the first attribute.1471 bool First = true;1472 Fragments.append(" (", DeclarationFragments::FragmentKind::Text);1473 // Helper function to render the attribute.1474 auto RenderAttribute =1475 [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling,1476 StringRef Arg = "",1477 DeclarationFragments::FragmentKind ArgKind =1478 DeclarationFragments::FragmentKind::Identifier) {1479 // Check if the `Kind` attribute is set for this property.1480 if ((Attributes & Kind) && !Spelling.empty()) {1481 // Add a leading comma if this is not the first attribute rendered.1482 if (!First)1483 Fragments.append(", ", DeclarationFragments::FragmentKind::Text);1484 // Render the spelling of this attribute `Kind` as a keyword.1485 Fragments.append(Spelling,1486 DeclarationFragments::FragmentKind::Keyword);1487 // If this attribute takes in arguments (e.g. `getter=getterName`),1488 // render the arguments.1489 if (!Arg.empty())1490 Fragments.append("=", DeclarationFragments::FragmentKind::Text)1491 .append(Arg, ArgKind);1492 First = false;1493 }1494 };1495 1496 // Go through all possible Objective-C property attributes and render set1497 // ones.1498 RenderAttribute(ObjCPropertyAttribute::kind_class, "class");1499 RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct");1500 RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic");1501 RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic");1502 RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign");1503 RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain");1504 RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong");1505 RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy");1506 RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak");1507 RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained,1508 "unsafe_unretained");1509 RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite");1510 RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly");1511 RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter",1512 Property->getGetterName().getAsString());1513 RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter",1514 Property->getSetterName().getAsString());1515 1516 // Render nullability attributes.1517 if (Attributes & ObjCPropertyAttribute::kind_nullability) {1518 QualType Type = Property->getType();1519 if (const auto Nullability =1520 AttributedType::stripOuterNullability(Type)) {1521 if (!First)1522 Fragments.append(", ", DeclarationFragments::FragmentKind::Text);1523 if (*Nullability == NullabilityKind::Unspecified &&1524 (Attributes & ObjCPropertyAttribute::kind_null_resettable))1525 Fragments.append("null_resettable",1526 DeclarationFragments::FragmentKind::Keyword);1527 else1528 Fragments.append(1529 getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true),1530 DeclarationFragments::FragmentKind::Keyword);1531 First = false;1532 }1533 }1534 1535 Fragments.append(")", DeclarationFragments::FragmentKind::Text);1536 }1537 1538 Fragments.appendSpace();1539 1540 FunctionTypeLoc BlockLoc;1541 FunctionProtoTypeLoc BlockProtoLoc;1542 findTypeLocForBlockDecl(Property->getTypeSourceInfo(), BlockLoc,1543 BlockProtoLoc);1544 1545 auto PropType = Property->getType();1546 if (!BlockLoc)1547 Fragments1548 .append(getFragmentsForType(PropType, Property->getASTContext(), After))1549 .appendSpace();1550 else1551 Fragments.append(1552 getFragmentsForBlock(Property, BlockLoc, BlockProtoLoc, After));1553 1554 return Fragments1555 .append(Property->getName(),1556 DeclarationFragments::FragmentKind::Identifier)1557 .append(std::move(After))1558 .appendSemicolon();1559}1560 1561DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(1562 const ObjCProtocolDecl *Protocol) {1563 DeclarationFragments Fragments;1564 // Build basic protocol declaration.1565 Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword)1566 .appendSpace()1567 .append(Protocol->getName(),1568 DeclarationFragments::FragmentKind::Identifier);1569 1570 // If this protocol conforms to other protocols, build the conformance list.1571 if (!Protocol->protocols().empty()) {1572 Fragments.append(" <", DeclarationFragments::FragmentKind::Text);1573 for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin();1574 It != Protocol->protocol_end(); It++) {1575 // Add a leading comma if this is not the first protocol rendered.1576 if (It != Protocol->protocol_begin())1577 Fragments.append(", ", DeclarationFragments::FragmentKind::Text);1578 1579 SmallString<128> USR;1580 index::generateUSRForDecl(*It, USR);1581 Fragments.append((*It)->getName(),1582 DeclarationFragments::FragmentKind::TypeIdentifier, USR,1583 *It);1584 }1585 Fragments.append(">", DeclarationFragments::FragmentKind::Text);1586 }1587 1588 return Fragments;1589}1590 1591DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(1592 const TypedefNameDecl *Decl) {1593 DeclarationFragments Fragments, After;1594 Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword)1595 .appendSpace()1596 .append(getFragmentsForType(Decl->getUnderlyingType(),1597 Decl->getASTContext(), After))1598 .append(std::move(After))1599 .appendSpace()1600 .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier);1601 1602 return Fragments.appendSemicolon();1603}1604 1605// Instantiate template for FunctionDecl.1606template FunctionSignature1607DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *);1608 1609// Instantiate template for ObjCMethodDecl.1610template FunctionSignature1611DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *);1612 1613// Subheading of a symbol defaults to its name.1614DeclarationFragments1615DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) {1616 DeclarationFragments Fragments;1617 if (isa<CXXConstructorDecl>(Decl)) {1618 Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(),1619 DeclarationFragments::FragmentKind::Identifier);1620 } else if (isa<CXXDestructorDecl>(Decl)) {1621 Fragments.append(cast<CXXDestructorDecl>(Decl)->getNameAsString(),1622 DeclarationFragments::FragmentKind::Identifier);1623 } else if (isa<CXXConversionDecl>(Decl)) {1624 Fragments.append(1625 cast<CXXConversionDecl>(Decl)->getConversionType().getAsString(),1626 DeclarationFragments::FragmentKind::Identifier);1627 } else if (isa<CXXMethodDecl>(Decl) &&1628 cast<CXXMethodDecl>(Decl)->isOverloadedOperator()) {1629 Fragments.append(Decl->getNameAsString(),1630 DeclarationFragments::FragmentKind::Identifier);1631 } else if (isa<TagDecl>(Decl) &&1632 cast<TagDecl>(Decl)->getTypedefNameForAnonDecl()) {1633 return getSubHeading(cast<TagDecl>(Decl)->getTypedefNameForAnonDecl());1634 } else if (Decl->getIdentifier()) {1635 Fragments.append(Decl->getName(),1636 DeclarationFragments::FragmentKind::Identifier);1637 } else {1638 Fragments.append(Decl->getDeclName().getAsString(),1639 DeclarationFragments::FragmentKind::Identifier);1640 }1641 1642 return Fragments;1643}1644 1645// Subheading of an Objective-C method is a `+` or `-` sign indicating whether1646// it's a class method or an instance method, followed by the selector name.1647DeclarationFragments1648DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) {1649 DeclarationFragments Fragments;1650 if (Method->isClassMethod())1651 Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);1652 else if (Method->isInstanceMethod())1653 Fragments.append("- ", DeclarationFragments::FragmentKind::Text);1654 1655 return Fragments.append(Method->getNameAsString(),1656 DeclarationFragments::FragmentKind::Identifier);1657}1658 1659// Subheading of a symbol defaults to its name.1660DeclarationFragments1661DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) {1662 DeclarationFragments Fragments;1663 Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);1664 return Fragments;1665}1666