brintos

brintos / llvm-project-archived public Read only

0
0
Text · 63.9 KiB · e5eda46 Raw
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