Path: blob/main/contrib/llvm-project/clang/lib/ExtractAPI/DeclarationFragments.cpp
35233 views
//===- ExtractAPI/DeclarationFragments.cpp ----------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7///8/// \file9/// This file implements Declaration Fragments related classes.10///11//===----------------------------------------------------------------------===//1213#include "clang/ExtractAPI/DeclarationFragments.h"14#include "clang/AST/ASTFwd.h"15#include "clang/AST/Decl.h"16#include "clang/AST/DeclCXX.h"17#include "clang/AST/TemplateBase.h"18#include "clang/AST/TemplateName.h"19#include "clang/AST/Type.h"20#include "clang/AST/TypeLoc.h"21#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"22#include "clang/Index/USRGeneration.h"23#include "llvm/ADT/StringSwitch.h"24#include "llvm/Support/ErrorHandling.h"25#include "llvm/Support/raw_ostream.h"26#include <optional>2728using namespace clang::extractapi;29using namespace llvm;3031namespace {3233void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo,34clang::FunctionTypeLoc &Block,35clang::FunctionProtoTypeLoc &BlockProto) {36if (!TSInfo)37return;3839clang::TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();40while (true) {41// Look through qualified types42if (auto QualifiedTL = TL.getAs<clang::QualifiedTypeLoc>()) {43TL = QualifiedTL.getUnqualifiedLoc();44continue;45}4647if (auto AttrTL = TL.getAs<clang::AttributedTypeLoc>()) {48TL = AttrTL.getModifiedLoc();49continue;50}5152// Try to get the function prototype behind the block pointer type,53// then we're done.54if (auto BlockPtr = TL.getAs<clang::BlockPointerTypeLoc>()) {55TL = BlockPtr.getPointeeLoc().IgnoreParens();56Block = TL.getAs<clang::FunctionTypeLoc>();57BlockProto = TL.getAs<clang::FunctionProtoTypeLoc>();58}59break;60}61}6263} // namespace6465DeclarationFragments &66DeclarationFragments::appendUnduplicatedTextCharacter(char Character) {67if (!Fragments.empty()) {68Fragment &Last = Fragments.back();69if (Last.Kind == FragmentKind::Text) {70// Merge the extra space into the last fragment if the last fragment is71// also text.72if (Last.Spelling.back() != Character) { // avoid duplicates at end73Last.Spelling.push_back(Character);74}75} else {76append("", FragmentKind::Text);77Fragments.back().Spelling.push_back(Character);78}79}8081return *this;82}8384DeclarationFragments &DeclarationFragments::appendSpace() {85return appendUnduplicatedTextCharacter(' ');86}8788DeclarationFragments &DeclarationFragments::appendSemicolon() {89return appendUnduplicatedTextCharacter(';');90}9192DeclarationFragments &DeclarationFragments::removeTrailingSemicolon() {93if (Fragments.empty())94return *this;9596Fragment &Last = Fragments.back();97if (Last.Kind == FragmentKind::Text && Last.Spelling.back() == ';')98Last.Spelling.pop_back();99100return *this;101}102103StringRef DeclarationFragments::getFragmentKindString(104DeclarationFragments::FragmentKind Kind) {105switch (Kind) {106case DeclarationFragments::FragmentKind::None:107return "none";108case DeclarationFragments::FragmentKind::Keyword:109return "keyword";110case DeclarationFragments::FragmentKind::Attribute:111return "attribute";112case DeclarationFragments::FragmentKind::NumberLiteral:113return "number";114case DeclarationFragments::FragmentKind::StringLiteral:115return "string";116case DeclarationFragments::FragmentKind::Identifier:117return "identifier";118case DeclarationFragments::FragmentKind::TypeIdentifier:119return "typeIdentifier";120case DeclarationFragments::FragmentKind::GenericParameter:121return "genericParameter";122case DeclarationFragments::FragmentKind::ExternalParam:123return "externalParam";124case DeclarationFragments::FragmentKind::InternalParam:125return "internalParam";126case DeclarationFragments::FragmentKind::Text:127return "text";128}129130llvm_unreachable("Unhandled FragmentKind");131}132133DeclarationFragments::FragmentKind134DeclarationFragments::parseFragmentKindFromString(StringRef S) {135return llvm::StringSwitch<FragmentKind>(S)136.Case("keyword", DeclarationFragments::FragmentKind::Keyword)137.Case("attribute", DeclarationFragments::FragmentKind::Attribute)138.Case("number", DeclarationFragments::FragmentKind::NumberLiteral)139.Case("string", DeclarationFragments::FragmentKind::StringLiteral)140.Case("identifier", DeclarationFragments::FragmentKind::Identifier)141.Case("typeIdentifier",142DeclarationFragments::FragmentKind::TypeIdentifier)143.Case("genericParameter",144DeclarationFragments::FragmentKind::GenericParameter)145.Case("internalParam", DeclarationFragments::FragmentKind::InternalParam)146.Case("externalParam", DeclarationFragments::FragmentKind::ExternalParam)147.Case("text", DeclarationFragments::FragmentKind::Text)148.Default(DeclarationFragments::FragmentKind::None);149}150151DeclarationFragments DeclarationFragments::getExceptionSpecificationString(152ExceptionSpecificationType ExceptionSpec) {153DeclarationFragments Fragments;154switch (ExceptionSpec) {155case ExceptionSpecificationType::EST_None:156return Fragments;157case ExceptionSpecificationType::EST_DynamicNone:158return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)159.append("throw", DeclarationFragments::FragmentKind::Keyword)160.append("(", DeclarationFragments::FragmentKind::Text)161.append(")", DeclarationFragments::FragmentKind::Text);162case ExceptionSpecificationType::EST_Dynamic:163// FIXME: throw(int), get types of inner expression164return Fragments;165case ExceptionSpecificationType::EST_BasicNoexcept:166return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)167.append("noexcept", DeclarationFragments::FragmentKind::Keyword);168case ExceptionSpecificationType::EST_DependentNoexcept:169// FIXME: throw(conditional-expression), get expression170break;171case ExceptionSpecificationType::EST_NoexceptFalse:172return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)173.append("noexcept", DeclarationFragments::FragmentKind::Keyword)174.append("(", DeclarationFragments::FragmentKind::Text)175.append("false", DeclarationFragments::FragmentKind::Keyword)176.append(")", DeclarationFragments::FragmentKind::Text);177case ExceptionSpecificationType::EST_NoexceptTrue:178return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)179.append("noexcept", DeclarationFragments::FragmentKind::Keyword)180.append("(", DeclarationFragments::FragmentKind::Text)181.append("true", DeclarationFragments::FragmentKind::Keyword)182.append(")", DeclarationFragments::FragmentKind::Text);183default:184return Fragments;185}186187llvm_unreachable("Unhandled exception specification");188}189190DeclarationFragments191DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) {192DeclarationFragments Fragments;193if (Record->isStruct())194Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);195else if (Record->isUnion())196Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);197else198Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);199200return Fragments;201}202203// NNS stores C++ nested name specifiers, which are prefixes to qualified names.204// Build declaration fragments for NNS recursively so that we have the USR for205// every part in a qualified name, and also leaves the actual underlying type206// cleaner for its own fragment.207DeclarationFragments208DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS,209ASTContext &Context,210DeclarationFragments &After) {211DeclarationFragments Fragments;212if (NNS->getPrefix())213Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After));214215switch (NNS->getKind()) {216case NestedNameSpecifier::Identifier:217Fragments.append(NNS->getAsIdentifier()->getName(),218DeclarationFragments::FragmentKind::Identifier);219break;220221case NestedNameSpecifier::Namespace: {222const NamespaceDecl *NS = NNS->getAsNamespace();223if (NS->isAnonymousNamespace())224return Fragments;225SmallString<128> USR;226index::generateUSRForDecl(NS, USR);227Fragments.append(NS->getName(),228DeclarationFragments::FragmentKind::Identifier, USR, NS);229break;230}231232case NestedNameSpecifier::NamespaceAlias: {233const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias();234SmallString<128> USR;235index::generateUSRForDecl(Alias, USR);236Fragments.append(Alias->getName(),237DeclarationFragments::FragmentKind::Identifier, USR,238Alias);239break;240}241242case NestedNameSpecifier::Global:243// The global specifier `::` at the beginning. No stored value.244break;245246case NestedNameSpecifier::Super:247// Microsoft's `__super` specifier.248Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword);249break;250251case NestedNameSpecifier::TypeSpecWithTemplate:252// A type prefixed by the `template` keyword.253Fragments.append("template", DeclarationFragments::FragmentKind::Keyword);254Fragments.appendSpace();255// Fallthrough after adding the keyword to handle the actual type.256[[fallthrough]];257258case NestedNameSpecifier::TypeSpec: {259const Type *T = NNS->getAsType();260// FIXME: Handle C++ template specialization type261Fragments.append(getFragmentsForType(T, Context, After));262break;263}264}265266// Add the separator text `::` for this segment.267return Fragments.append("::", DeclarationFragments::FragmentKind::Text);268}269270// Recursively build the declaration fragments for an underlying `Type` with271// qualifiers removed.272DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(273const Type *T, ASTContext &Context, DeclarationFragments &After) {274assert(T && "invalid type");275276DeclarationFragments Fragments;277278// An ElaboratedType is a sugar for types that are referred to using an279// elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a280// qualified name, e.g., `N::M::type`, or both.281if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) {282ElaboratedTypeKeyword Keyword = ET->getKeyword();283if (Keyword != ElaboratedTypeKeyword::None) {284Fragments285.append(ElaboratedType::getKeywordName(Keyword),286DeclarationFragments::FragmentKind::Keyword)287.appendSpace();288}289290if (const NestedNameSpecifier *NNS = ET->getQualifier())291Fragments.append(getFragmentsForNNS(NNS, Context, After));292293// After handling the elaborated keyword or qualified name, build294// declaration fragments for the desugared underlying type.295return Fragments.append(getFragmentsForType(ET->desugar(), Context, After));296}297298// If the type is a typedefed type, get the underlying TypedefNameDecl for a299// direct reference to the typedef instead of the wrapped type.300301// 'id' type is a typedef for an ObjCObjectPointerType302// we treat it as a typedef303if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) {304const TypedefNameDecl *Decl = TypedefTy->getDecl();305TypedefUnderlyingTypeResolver TypedefResolver(Context);306std::string USR = TypedefResolver.getUSRForType(QualType(T, 0));307308if (T->isObjCIdType()) {309return Fragments.append(Decl->getName(),310DeclarationFragments::FragmentKind::Keyword);311}312313return Fragments.append(314Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier,315USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0)));316}317318// Declaration fragments of a pointer type is the declaration fragments of319// the pointee type followed by a `*`,320if (T->isPointerType() && !T->isFunctionPointerType())321return Fragments322.append(getFragmentsForType(T->getPointeeType(), Context, After))323.append(" *", DeclarationFragments::FragmentKind::Text);324325// For Objective-C `id` and `Class` pointers326// we do not spell out the `*`.327if (T->isObjCObjectPointerType() &&328!T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) {329330Fragments.append(getFragmentsForType(T->getPointeeType(), Context, After));331332// id<protocol> is an qualified id type333// id<protocol>* is not an qualified id type334if (!T->getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) {335Fragments.append(" *", DeclarationFragments::FragmentKind::Text);336}337338return Fragments;339}340341// Declaration fragments of a lvalue reference type is the declaration342// fragments of the underlying type followed by a `&`.343if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T))344return Fragments345.append(346getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After))347.append(" &", DeclarationFragments::FragmentKind::Text);348349// Declaration fragments of a rvalue reference type is the declaration350// fragments of the underlying type followed by a `&&`.351if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T))352return Fragments353.append(354getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After))355.append(" &&", DeclarationFragments::FragmentKind::Text);356357// Declaration fragments of an array-typed variable have two parts:358// 1. the element type of the array that appears before the variable name;359// 2. array brackets `[(0-9)?]` that appear after the variable name.360if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) {361// Build the "after" part first because the inner element type might also362// be an array-type. For example `int matrix[3][4]` which has a type of363// "(array 3 of (array 4 of ints))."364// Push the array size part first to make sure they are in the right order.365After.append("[", DeclarationFragments::FragmentKind::Text);366367switch (AT->getSizeModifier()) {368case ArraySizeModifier::Normal:369break;370case ArraySizeModifier::Static:371Fragments.append("static", DeclarationFragments::FragmentKind::Keyword);372break;373case ArraySizeModifier::Star:374Fragments.append("*", DeclarationFragments::FragmentKind::Text);375break;376}377378if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {379// FIXME: right now this would evaluate any expressions/macros written in380// the original source to concrete values. For example381// `int nums[MAX]` -> `int nums[100]`382// `char *str[5 + 1]` -> `char *str[6]`383SmallString<128> Size;384CAT->getSize().toStringUnsigned(Size);385After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral);386}387388After.append("]", DeclarationFragments::FragmentKind::Text);389390return Fragments.append(391getFragmentsForType(AT->getElementType(), Context, After));392}393394if (const TemplateSpecializationType *TemplSpecTy =395dyn_cast<TemplateSpecializationType>(T)) {396const auto TemplName = TemplSpecTy->getTemplateName();397std::string Str;398raw_string_ostream Stream(Str);399TemplName.print(Stream, Context.getPrintingPolicy(),400TemplateName::Qualified::AsWritten);401SmallString<64> USR("");402if (const auto *TemplDecl = TemplName.getAsTemplateDecl())403index::generateUSRForDecl(TemplDecl, USR);404405return Fragments406.append(Str, DeclarationFragments::FragmentKind::TypeIdentifier, USR)407.append("<", DeclarationFragments::FragmentKind::Text)408.append(getFragmentsForTemplateArguments(409TemplSpecTy->template_arguments(), Context, std::nullopt))410.append(">", DeclarationFragments::FragmentKind::Text);411}412413// Everything we care about has been handled now, reduce to the canonical414// unqualified base type.415QualType Base = T->getCanonicalTypeUnqualified();416417// If the base type is a TagType (struct/interface/union/class/enum), let's418// get the underlying Decl for better names and USRs.419if (const TagType *TagTy = dyn_cast<TagType>(Base)) {420const TagDecl *Decl = TagTy->getDecl();421// Anonymous decl, skip this fragment.422if (Decl->getName().empty())423return Fragments.append("{ ... }",424DeclarationFragments::FragmentKind::Text);425SmallString<128> TagUSR;426clang::index::generateUSRForDecl(Decl, TagUSR);427return Fragments.append(Decl->getName(),428DeclarationFragments::FragmentKind::TypeIdentifier,429TagUSR, Decl);430}431432// If the base type is an ObjCInterfaceType, use the underlying433// ObjCInterfaceDecl for the true USR.434if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) {435const auto *Decl = ObjCIT->getDecl();436SmallString<128> USR;437index::generateUSRForDecl(Decl, USR);438return Fragments.append(Decl->getName(),439DeclarationFragments::FragmentKind::TypeIdentifier,440USR, Decl);441}442443// Default fragment builder for other kinds of types (BuiltinType etc.)444SmallString<128> USR;445clang::index::generateUSRForType(Base, Context, USR);446Fragments.append(Base.getAsString(),447DeclarationFragments::FragmentKind::TypeIdentifier, USR);448449return Fragments;450}451452DeclarationFragments453DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) {454DeclarationFragments Fragments;455if (Quals.hasConst())456Fragments.append("const", DeclarationFragments::FragmentKind::Keyword);457if (Quals.hasVolatile())458Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword);459if (Quals.hasRestrict())460Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword);461462return Fragments;463}464465DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(466const QualType QT, ASTContext &Context, DeclarationFragments &After) {467assert(!QT.isNull() && "invalid type");468469if (const ParenType *PT = dyn_cast<ParenType>(QT)) {470After.append(")", DeclarationFragments::FragmentKind::Text);471return getFragmentsForType(PT->getInnerType(), Context, After)472.append("(", DeclarationFragments::FragmentKind::Text);473}474475const SplitQualType SQT = QT.split();476DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals),477TypeFragments =478getFragmentsForType(SQT.Ty, Context, After);479if (QT.getAsString() == "_Bool")480TypeFragments.replace("bool", 0);481482if (QualsFragments.getFragments().empty())483return TypeFragments;484485// Use east qualifier for pointer types486// For example:487// ```488// int * const489// ^---- ^----490// type qualifier491// ^-----------------492// const pointer to int493// ```494// should not be reconstructed as495// ```496// const int *497// ^---- ^--498// qualifier type499// ^---------------- ^500// pointer to const int501// ```502if (SQT.Ty->isAnyPointerType())503return TypeFragments.appendSpace().append(std::move(QualsFragments));504505return QualsFragments.appendSpace().append(std::move(TypeFragments));506}507508DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace(509const NamespaceDecl *Decl) {510DeclarationFragments Fragments;511Fragments.append("namespace", DeclarationFragments::FragmentKind::Keyword);512if (!Decl->isAnonymousNamespace())513Fragments.appendSpace().append(514Decl->getName(), DeclarationFragments::FragmentKind::Identifier);515return Fragments.appendSemicolon();516}517518DeclarationFragments519DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {520DeclarationFragments Fragments;521if (Var->isConstexpr())522Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)523.appendSpace();524525StorageClass SC = Var->getStorageClass();526if (SC != SC_None)527Fragments528.append(VarDecl::getStorageClassSpecifierString(SC),529DeclarationFragments::FragmentKind::Keyword)530.appendSpace();531532// Capture potential fragments that needs to be placed after the variable name533// ```534// int nums[5];535// char (*ptr_to_array)[6];536// ```537DeclarationFragments After;538FunctionTypeLoc BlockLoc;539FunctionProtoTypeLoc BlockProtoLoc;540findTypeLocForBlockDecl(Var->getTypeSourceInfo(), BlockLoc, BlockProtoLoc);541542if (!BlockLoc) {543QualType T = Var->getTypeSourceInfo()544? Var->getTypeSourceInfo()->getType()545: Var->getASTContext().getUnqualifiedObjCPointerType(546Var->getType());547548Fragments.append(getFragmentsForType(T, Var->getASTContext(), After))549.appendSpace();550} else {551Fragments.append(getFragmentsForBlock(Var, BlockLoc, BlockProtoLoc, After));552}553554return Fragments555.append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)556.append(std::move(After))557.appendSemicolon();558}559560DeclarationFragments561DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) {562DeclarationFragments Fragments;563if (Var->isConstexpr())564Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)565.appendSpace();566QualType T =567Var->getTypeSourceInfo()568? Var->getTypeSourceInfo()->getType()569: Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType());570571// Might be a member, so might be static.572if (Var->isStaticDataMember())573Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)574.appendSpace();575576DeclarationFragments After;577DeclarationFragments ArgumentFragment =578getFragmentsForType(T, Var->getASTContext(), After);579if (StringRef(ArgumentFragment.begin()->Spelling)580.starts_with("type-parameter")) {581std::string ProperArgName = T.getAsString();582ArgumentFragment.begin()->Spelling.swap(ProperArgName);583}584Fragments.append(std::move(ArgumentFragment))585.appendSpace()586.append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)587.appendSemicolon();588return Fragments;589}590591DeclarationFragments592DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) {593DeclarationFragments Fragments, After;594595auto *TSInfo = Param->getTypeSourceInfo();596597QualType T = TSInfo ? TSInfo->getType()598: Param->getASTContext().getUnqualifiedObjCPointerType(599Param->getType());600601FunctionTypeLoc BlockLoc;602FunctionProtoTypeLoc BlockProtoLoc;603findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc);604605DeclarationFragments TypeFragments;606if (BlockLoc)607TypeFragments.append(608getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After));609else610TypeFragments.append(getFragmentsForType(T, Param->getASTContext(), After));611612if (StringRef(TypeFragments.begin()->Spelling)613.starts_with("type-parameter")) {614std::string ProperArgName = Param->getOriginalType().getAsString();615TypeFragments.begin()->Spelling.swap(ProperArgName);616}617618if (Param->isObjCMethodParameter()) {619Fragments.append("(", DeclarationFragments::FragmentKind::Text)620.append(std::move(TypeFragments))621.append(std::move(After))622.append(") ", DeclarationFragments::FragmentKind::Text)623.append(Param->getName(),624DeclarationFragments::FragmentKind::InternalParam);625} else {626Fragments.append(std::move(TypeFragments));627if (!T->isBlockPointerType())628Fragments.appendSpace();629Fragments630.append(Param->getName(),631DeclarationFragments::FragmentKind::InternalParam)632.append(std::move(After));633}634return Fragments;635}636637DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForBlock(638const NamedDecl *BlockDecl, FunctionTypeLoc &Block,639FunctionProtoTypeLoc &BlockProto, DeclarationFragments &After) {640DeclarationFragments Fragments;641642DeclarationFragments RetTyAfter;643auto ReturnValueFragment = getFragmentsForType(644Block.getTypePtr()->getReturnType(), BlockDecl->getASTContext(), After);645646Fragments.append(std::move(ReturnValueFragment))647.append(std::move(RetTyAfter))648.appendSpace()649.append("(^", DeclarationFragments::FragmentKind::Text);650651After.append(")", DeclarationFragments::FragmentKind::Text);652unsigned NumParams = Block.getNumParams();653654if (!BlockProto || NumParams == 0) {655if (BlockProto && BlockProto.getTypePtr()->isVariadic())656After.append("(...)", DeclarationFragments::FragmentKind::Text);657else658After.append("()", DeclarationFragments::FragmentKind::Text);659} else {660After.append("(", DeclarationFragments::FragmentKind::Text);661for (unsigned I = 0; I != NumParams; ++I) {662if (I)663After.append(", ", DeclarationFragments::FragmentKind::Text);664After.append(getFragmentsForParam(Block.getParam(I)));665if (I == NumParams - 1 && BlockProto.getTypePtr()->isVariadic())666After.append(", ...", DeclarationFragments::FragmentKind::Text);667}668After.append(")", DeclarationFragments::FragmentKind::Text);669}670671return Fragments;672}673674DeclarationFragments675DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {676DeclarationFragments Fragments;677switch (Func->getStorageClass()) {678case SC_None:679case SC_PrivateExtern:680break;681case SC_Extern:682Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword)683.appendSpace();684break;685case SC_Static:686Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)687.appendSpace();688break;689case SC_Auto:690case SC_Register:691llvm_unreachable("invalid for functions");692}693if (Func->isConsteval()) // if consteval, it is also constexpr694Fragments.append("consteval", DeclarationFragments::FragmentKind::Keyword)695.appendSpace();696else if (Func->isConstexpr())697Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)698.appendSpace();699700// FIXME: Is `after` actually needed here?701DeclarationFragments After;702auto ReturnValueFragment =703getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After);704if (StringRef(ReturnValueFragment.begin()->Spelling)705.starts_with("type-parameter")) {706std::string ProperArgName = Func->getReturnType().getAsString();707ReturnValueFragment.begin()->Spelling.swap(ProperArgName);708}709710Fragments.append(std::move(ReturnValueFragment))711.appendSpace()712.append(Func->getNameAsString(),713DeclarationFragments::FragmentKind::Identifier);714715if (Func->getTemplateSpecializationInfo()) {716Fragments.append("<", DeclarationFragments::FragmentKind::Text);717718for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) {719if (i)720Fragments.append(", ", DeclarationFragments::FragmentKind::Text);721Fragments.append(722getFragmentsForType(Func->getParamDecl(i)->getType(),723Func->getParamDecl(i)->getASTContext(), After));724}725Fragments.append(">", DeclarationFragments::FragmentKind::Text);726}727Fragments.append(std::move(After));728729Fragments.append("(", DeclarationFragments::FragmentKind::Text);730unsigned NumParams = Func->getNumParams();731for (unsigned i = 0; i != NumParams; ++i) {732if (i)733Fragments.append(", ", DeclarationFragments::FragmentKind::Text);734Fragments.append(getFragmentsForParam(Func->getParamDecl(i)));735}736737if (Func->isVariadic()) {738if (NumParams > 0)739Fragments.append(", ", DeclarationFragments::FragmentKind::Text);740Fragments.append("...", DeclarationFragments::FragmentKind::Text);741}742Fragments.append(")", DeclarationFragments::FragmentKind::Text);743744Fragments.append(DeclarationFragments::getExceptionSpecificationString(745Func->getExceptionSpecType()));746747return Fragments.appendSemicolon();748}749750DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant(751const EnumConstantDecl *EnumConstDecl) {752DeclarationFragments Fragments;753return Fragments.append(EnumConstDecl->getName(),754DeclarationFragments::FragmentKind::Identifier);755}756757DeclarationFragments758DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {759if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl())760return getFragmentsForTypedef(TypedefNameDecl);761762DeclarationFragments Fragments, After;763Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword);764765if (!EnumDecl->getName().empty())766Fragments.appendSpace().append(767EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier);768769QualType IntegerType = EnumDecl->getIntegerType();770if (!IntegerType.isNull())771Fragments.appendSpace()772.append(": ", DeclarationFragments::FragmentKind::Text)773.append(774getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))775.append(std::move(After));776777if (EnumDecl->getName().empty())778Fragments.appendSpace().append("{ ... }",779DeclarationFragments::FragmentKind::Text);780781return Fragments.appendSemicolon();782}783784DeclarationFragments785DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) {786DeclarationFragments After;787DeclarationFragments Fragments;788if (Field->isMutable())789Fragments.append("mutable", DeclarationFragments::FragmentKind::Keyword)790.appendSpace();791return Fragments792.append(793getFragmentsForType(Field->getType(), Field->getASTContext(), After))794.appendSpace()795.append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)796.append(std::move(After))797.appendSemicolon();798}799800DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(801const RecordDecl *Record) {802if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())803return getFragmentsForTypedef(TypedefNameDecl);804805DeclarationFragments Fragments;806if (Record->isUnion())807Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);808else809Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);810811Fragments.appendSpace();812if (!Record->getName().empty())813Fragments.append(Record->getName(),814DeclarationFragments::FragmentKind::Identifier);815else816Fragments.append("{ ... }", DeclarationFragments::FragmentKind::Text);817818return Fragments.appendSemicolon();819}820821DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(822const CXXRecordDecl *Record) {823if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())824return getFragmentsForTypedef(TypedefNameDecl);825826DeclarationFragments Fragments;827Fragments.append(DeclarationFragments::getStructureTypeFragment(Record));828829if (!Record->getName().empty())830Fragments.appendSpace().append(831Record->getName(), DeclarationFragments::FragmentKind::Identifier);832833return Fragments.appendSemicolon();834}835836DeclarationFragments837DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(838const CXXMethodDecl *Method) {839DeclarationFragments Fragments;840std::string Name;841if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(Method)) {842Name = Method->getNameAsString();843if (Constructor->isExplicit())844Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)845.appendSpace();846} else if (isa<CXXDestructorDecl>(Method))847Name = Method->getNameAsString();848849DeclarationFragments After;850Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier)851.append(std::move(After));852Fragments.append("(", DeclarationFragments::FragmentKind::Text);853for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {854if (i)855Fragments.append(", ", DeclarationFragments::FragmentKind::Text);856Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));857}858Fragments.append(")", DeclarationFragments::FragmentKind::Text);859860Fragments.append(DeclarationFragments::getExceptionSpecificationString(861Method->getExceptionSpecType()));862863return Fragments.appendSemicolon();864}865866DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(867const CXXMethodDecl *Method) {868DeclarationFragments Fragments;869StringRef Name = Method->getName();870if (Method->isStatic())871Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)872.appendSpace();873if (Method->isConstexpr())874Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)875.appendSpace();876if (Method->isVolatile())877Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword)878.appendSpace();879880// Build return type881DeclarationFragments After;882Fragments883.append(getFragmentsForType(Method->getReturnType(),884Method->getASTContext(), After))885.appendSpace()886.append(Name, DeclarationFragments::FragmentKind::Identifier)887.append(std::move(After));888Fragments.append("(", DeclarationFragments::FragmentKind::Text);889for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {890if (i)891Fragments.append(", ", DeclarationFragments::FragmentKind::Text);892Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));893}894Fragments.append(")", DeclarationFragments::FragmentKind::Text);895896if (Method->isConst())897Fragments.appendSpace().append("const",898DeclarationFragments::FragmentKind::Keyword);899900Fragments.append(DeclarationFragments::getExceptionSpecificationString(901Method->getExceptionSpecType()));902903return Fragments.appendSemicolon();904}905906DeclarationFragments907DeclarationFragmentsBuilder::getFragmentsForConversionFunction(908const CXXConversionDecl *ConversionFunction) {909DeclarationFragments Fragments;910911if (ConversionFunction->isExplicit())912Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)913.appendSpace();914915Fragments.append("operator", DeclarationFragments::FragmentKind::Keyword)916.appendSpace();917918Fragments919.append(ConversionFunction->getConversionType().getAsString(),920DeclarationFragments::FragmentKind::TypeIdentifier)921.append("(", DeclarationFragments::FragmentKind::Text);922for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end;923++i) {924if (i)925Fragments.append(", ", DeclarationFragments::FragmentKind::Text);926Fragments.append(getFragmentsForParam(ConversionFunction->getParamDecl(i)));927}928Fragments.append(")", DeclarationFragments::FragmentKind::Text);929930if (ConversionFunction->isConst())931Fragments.appendSpace().append("const",932DeclarationFragments::FragmentKind::Keyword);933934return Fragments.appendSemicolon();935}936937DeclarationFragments938DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(939const CXXMethodDecl *Method) {940DeclarationFragments Fragments;941942// Build return type943DeclarationFragments After;944Fragments945.append(getFragmentsForType(Method->getReturnType(),946Method->getASTContext(), After))947.appendSpace()948.append(Method->getNameAsString(),949DeclarationFragments::FragmentKind::Identifier)950.append(std::move(After));951Fragments.append("(", DeclarationFragments::FragmentKind::Text);952for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {953if (i)954Fragments.append(", ", DeclarationFragments::FragmentKind::Text);955Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));956}957Fragments.append(")", DeclarationFragments::FragmentKind::Text);958959if (Method->isConst())960Fragments.appendSpace().append("const",961DeclarationFragments::FragmentKind::Keyword);962963Fragments.append(DeclarationFragments::getExceptionSpecificationString(964Method->getExceptionSpecType()));965966return Fragments.appendSemicolon();967}968969// Get fragments for template parameters, e.g. T in tempalte<typename T> ...970DeclarationFragments971DeclarationFragmentsBuilder::getFragmentsForTemplateParameters(972ArrayRef<NamedDecl *> ParameterArray) {973DeclarationFragments Fragments;974for (unsigned i = 0, end = ParameterArray.size(); i != end; ++i) {975if (i)976Fragments.append(",", DeclarationFragments::FragmentKind::Text)977.appendSpace();978979if (const auto *TemplateParam =980dyn_cast<TemplateTypeParmDecl>(ParameterArray[i])) {981if (TemplateParam->hasTypeConstraint())982Fragments.append(TemplateParam->getTypeConstraint()983->getNamedConcept()984->getName()985.str(),986DeclarationFragments::FragmentKind::TypeIdentifier);987else if (TemplateParam->wasDeclaredWithTypename())988Fragments.append("typename",989DeclarationFragments::FragmentKind::Keyword);990else991Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);992993if (TemplateParam->isParameterPack())994Fragments.append("...", DeclarationFragments::FragmentKind::Text);995996if (!TemplateParam->getName().empty())997Fragments.appendSpace().append(998TemplateParam->getName(),999DeclarationFragments::FragmentKind::GenericParameter);10001001if (TemplateParam->hasDefaultArgument()) {1002const auto Default = TemplateParam->getDefaultArgument();1003Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)1004.append(getFragmentsForTemplateArguments(1005{Default.getArgument()}, TemplateParam->getASTContext(),1006{Default}));1007}1008} else if (const auto *NTP =1009dyn_cast<NonTypeTemplateParmDecl>(ParameterArray[i])) {1010DeclarationFragments After;1011const auto TyFragments =1012getFragmentsForType(NTP->getType(), NTP->getASTContext(), After);1013Fragments.append(std::move(TyFragments)).append(std::move(After));10141015if (NTP->isParameterPack())1016Fragments.append("...", DeclarationFragments::FragmentKind::Text);10171018if (!NTP->getName().empty())1019Fragments.appendSpace().append(1020NTP->getName(),1021DeclarationFragments::FragmentKind::GenericParameter);10221023if (NTP->hasDefaultArgument()) {1024SmallString<8> ExprStr;1025raw_svector_ostream Output(ExprStr);1026NTP->getDefaultArgument().getArgument().print(1027NTP->getASTContext().getPrintingPolicy(), Output,1028/*IncludeType=*/false);1029Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)1030.append(ExprStr, DeclarationFragments::FragmentKind::Text);1031}1032} else if (const auto *TTP =1033dyn_cast<TemplateTemplateParmDecl>(ParameterArray[i])) {1034Fragments.append("template", DeclarationFragments::FragmentKind::Keyword)1035.appendSpace()1036.append("<", DeclarationFragments::FragmentKind::Text)1037.append(getFragmentsForTemplateParameters(1038TTP->getTemplateParameters()->asArray()))1039.append(">", DeclarationFragments::FragmentKind::Text)1040.appendSpace()1041.append(TTP->wasDeclaredWithTypename() ? "typename" : "class",1042DeclarationFragments::FragmentKind::Keyword);10431044if (TTP->isParameterPack())1045Fragments.append("...", DeclarationFragments::FragmentKind::Text);10461047if (!TTP->getName().empty())1048Fragments.appendSpace().append(1049TTP->getName(),1050DeclarationFragments::FragmentKind::GenericParameter);1051if (TTP->hasDefaultArgument()) {1052const auto Default = TTP->getDefaultArgument();1053Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)1054.append(getFragmentsForTemplateArguments(1055{Default.getArgument()}, TTP->getASTContext(), {Default}));1056}1057}1058}1059return Fragments;1060}10611062// Get fragments for template arguments, e.g. int in template<typename T>1063// Foo<int>;1064//1065// Note: TemplateParameters is only necessary if the Decl is a1066// PartialSpecialization, where we need the parameters to deduce the name of the1067// generic arguments.1068DeclarationFragments1069DeclarationFragmentsBuilder::getFragmentsForTemplateArguments(1070const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context,1071const std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs) {1072DeclarationFragments Fragments;1073for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) {1074if (i)1075Fragments.append(",", DeclarationFragments::FragmentKind::Text)1076.appendSpace();10771078const auto &CTA = TemplateArguments[i];1079switch (CTA.getKind()) {1080case TemplateArgument::Type: {1081DeclarationFragments After;1082DeclarationFragments ArgumentFragment =1083getFragmentsForType(CTA.getAsType(), Context, After);10841085if (StringRef(ArgumentFragment.begin()->Spelling)1086.starts_with("type-parameter")) {1087if (TemplateArgumentLocs.has_value() &&1088TemplateArgumentLocs->size() > i) {1089std::string ProperArgName = TemplateArgumentLocs.value()[i]1090.getTypeSourceInfo()1091->getType()1092.getAsString();1093ArgumentFragment.begin()->Spelling.swap(ProperArgName);1094} else {1095auto &Spelling = ArgumentFragment.begin()->Spelling;1096Spelling.clear();1097raw_string_ostream OutStream(Spelling);1098CTA.print(Context.getPrintingPolicy(), OutStream, false);1099OutStream.flush();1100}1101}11021103Fragments.append(std::move(ArgumentFragment));1104break;1105}1106case TemplateArgument::Declaration: {1107const auto *VD = CTA.getAsDecl();1108SmallString<128> USR;1109index::generateUSRForDecl(VD, USR);1110Fragments.append(VD->getNameAsString(),1111DeclarationFragments::FragmentKind::Identifier, USR);1112break;1113}1114case TemplateArgument::NullPtr:1115Fragments.append("nullptr", DeclarationFragments::FragmentKind::Keyword);1116break;11171118case TemplateArgument::Integral: {1119SmallString<4> Str;1120CTA.getAsIntegral().toString(Str);1121Fragments.append(Str, DeclarationFragments::FragmentKind::Text);1122break;1123}11241125case TemplateArgument::StructuralValue: {1126const auto SVTy = CTA.getStructuralValueType();1127Fragments.append(CTA.getAsStructuralValue().getAsString(Context, SVTy),1128DeclarationFragments::FragmentKind::Text);1129break;1130}11311132case TemplateArgument::TemplateExpansion:1133case TemplateArgument::Template: {1134std::string Str;1135raw_string_ostream Stream(Str);1136CTA.getAsTemplate().print(Stream, Context.getPrintingPolicy());1137SmallString<64> USR("");1138if (const auto *TemplDecl =1139CTA.getAsTemplateOrTemplatePattern().getAsTemplateDecl())1140index::generateUSRForDecl(TemplDecl, USR);1141Fragments.append(Str, DeclarationFragments::FragmentKind::TypeIdentifier,1142USR);1143if (CTA.getKind() == TemplateArgument::TemplateExpansion)1144Fragments.append("...", DeclarationFragments::FragmentKind::Text);1145break;1146}11471148case TemplateArgument::Pack:1149Fragments.append("<", DeclarationFragments::FragmentKind::Text)1150.append(getFragmentsForTemplateArguments(CTA.pack_elements(), Context,1151{}))1152.append(">", DeclarationFragments::FragmentKind::Text);1153break;11541155case TemplateArgument::Expression: {1156SmallString<8> ExprStr;1157raw_svector_ostream Output(ExprStr);1158CTA.getAsExpr()->printPretty(Output, nullptr,1159Context.getPrintingPolicy());1160Fragments.append(ExprStr, DeclarationFragments::FragmentKind::Text);1161break;1162}11631164case TemplateArgument::Null:1165break;1166}1167}1168return Fragments;1169}11701171DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept(1172const ConceptDecl *Concept) {1173DeclarationFragments Fragments;1174return Fragments1175.append("template", DeclarationFragments::FragmentKind::Keyword)1176.appendSpace()1177.append("<", DeclarationFragments::FragmentKind::Text)1178.append(getFragmentsForTemplateParameters(1179Concept->getTemplateParameters()->asArray()))1180.append("> ", DeclarationFragments::FragmentKind::Text)1181.appendSpace()1182.append("concept", DeclarationFragments::FragmentKind::Keyword)1183.appendSpace()1184.append(Concept->getName().str(),1185DeclarationFragments::FragmentKind::Identifier)1186.appendSemicolon();1187}11881189DeclarationFragments1190DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(1191const RedeclarableTemplateDecl *RedeclarableTemplate) {1192DeclarationFragments Fragments;1193Fragments.append("template", DeclarationFragments::FragmentKind::Keyword)1194.appendSpace()1195.append("<", DeclarationFragments::FragmentKind::Text)1196.append(getFragmentsForTemplateParameters(1197RedeclarableTemplate->getTemplateParameters()->asArray()))1198.append(">", DeclarationFragments::FragmentKind::Text)1199.appendSpace();12001201if (isa<TypeAliasTemplateDecl>(RedeclarableTemplate))1202Fragments.appendSpace()1203.append("using", DeclarationFragments::FragmentKind::Keyword)1204.appendSpace()1205.append(RedeclarableTemplate->getName(),1206DeclarationFragments::FragmentKind::Identifier);1207// the templated records will be resposbible for injecting their templates1208return Fragments.appendSpace();1209}12101211DeclarationFragments1212DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization(1213const ClassTemplateSpecializationDecl *Decl) {1214DeclarationFragments Fragments;1215return Fragments1216.append("template", DeclarationFragments::FragmentKind::Keyword)1217.appendSpace()1218.append("<", DeclarationFragments::FragmentKind::Text)1219.append(">", DeclarationFragments::FragmentKind::Text)1220.appendSpace()1221.append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(1222cast<CXXRecordDecl>(Decl)))1223.pop_back() // there is an extra semicolon now1224.append("<", DeclarationFragments::FragmentKind::Text)1225.append(getFragmentsForTemplateArguments(1226Decl->getTemplateArgs().asArray(), Decl->getASTContext(),1227Decl->getTemplateArgsAsWritten()->arguments()))1228.append(">", DeclarationFragments::FragmentKind::Text)1229.appendSemicolon();1230}12311232DeclarationFragments1233DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization(1234const ClassTemplatePartialSpecializationDecl *Decl) {1235DeclarationFragments Fragments;1236return Fragments1237.append("template", DeclarationFragments::FragmentKind::Keyword)1238.appendSpace()1239.append("<", DeclarationFragments::FragmentKind::Text)1240.append(getFragmentsForTemplateParameters(1241Decl->getTemplateParameters()->asArray()))1242.append(">", DeclarationFragments::FragmentKind::Text)1243.appendSpace()1244.append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(1245cast<CXXRecordDecl>(Decl)))1246.pop_back() // there is an extra semicolon now1247.append("<", DeclarationFragments::FragmentKind::Text)1248.append(getFragmentsForTemplateArguments(1249Decl->getTemplateArgs().asArray(), Decl->getASTContext(),1250Decl->getTemplateArgsAsWritten()->arguments()))1251.append(">", DeclarationFragments::FragmentKind::Text)1252.appendSemicolon();1253}12541255DeclarationFragments1256DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization(1257const VarTemplateSpecializationDecl *Decl) {1258DeclarationFragments Fragments;1259return Fragments1260.append("template", DeclarationFragments::FragmentKind::Keyword)1261.appendSpace()1262.append("<", DeclarationFragments::FragmentKind::Text)1263.append(">", DeclarationFragments::FragmentKind::Text)1264.appendSpace()1265.append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))1266.pop_back() // there is an extra semicolon now1267.append("<", DeclarationFragments::FragmentKind::Text)1268.append(getFragmentsForTemplateArguments(1269Decl->getTemplateArgs().asArray(), Decl->getASTContext(),1270Decl->getTemplateArgsAsWritten()->arguments()))1271.append(">", DeclarationFragments::FragmentKind::Text)1272.appendSemicolon();1273}12741275DeclarationFragments1276DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization(1277const VarTemplatePartialSpecializationDecl *Decl) {1278DeclarationFragments Fragments;1279return Fragments1280.append("template", DeclarationFragments::FragmentKind::Keyword)1281.appendSpace()1282.append("<", DeclarationFragments::FragmentKind::Text)1283// Partial specs may have new params.1284.append(getFragmentsForTemplateParameters(1285Decl->getTemplateParameters()->asArray()))1286.append(">", DeclarationFragments::FragmentKind::Text)1287.appendSpace()1288.append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))1289.pop_back() // there is an extra semicolon now1290.append("<", DeclarationFragments::FragmentKind::Text)1291.append(getFragmentsForTemplateArguments(1292Decl->getTemplateArgs().asArray(), Decl->getASTContext(),1293Decl->getTemplateArgsAsWritten()->arguments()))1294.append(">", DeclarationFragments::FragmentKind::Text)1295.appendSemicolon();1296}12971298DeclarationFragments1299DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(1300const FunctionTemplateDecl *Decl) {1301DeclarationFragments Fragments;1302return Fragments1303.append("template", DeclarationFragments::FragmentKind::Keyword)1304.appendSpace()1305.append("<", DeclarationFragments::FragmentKind::Text)1306// Partial specs may have new params.1307.append(getFragmentsForTemplateParameters(1308Decl->getTemplateParameters()->asArray()))1309.append(">", DeclarationFragments::FragmentKind::Text)1310.appendSpace()1311.append(DeclarationFragmentsBuilder::getFragmentsForFunction(1312Decl->getAsFunction()));1313}13141315DeclarationFragments1316DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization(1317const FunctionDecl *Decl) {1318DeclarationFragments Fragments;1319return Fragments1320.append("template", DeclarationFragments::FragmentKind::Keyword)1321.appendSpace()1322.append("<>", DeclarationFragments::FragmentKind::Text)1323.appendSpace()1324.append(DeclarationFragmentsBuilder::getFragmentsForFunction(Decl));1325}13261327DeclarationFragments1328DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name,1329const MacroDirective *MD) {1330DeclarationFragments Fragments;1331Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword)1332.appendSpace();1333Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);13341335auto *MI = MD->getMacroInfo();13361337if (MI->isFunctionLike()) {1338Fragments.append("(", DeclarationFragments::FragmentKind::Text);1339unsigned numParameters = MI->getNumParams();1340if (MI->isC99Varargs())1341--numParameters;1342for (unsigned i = 0; i < numParameters; ++i) {1343if (i)1344Fragments.append(", ", DeclarationFragments::FragmentKind::Text);1345Fragments.append(MI->params()[i]->getName(),1346DeclarationFragments::FragmentKind::InternalParam);1347}1348if (MI->isVariadic()) {1349if (numParameters && MI->isC99Varargs())1350Fragments.append(", ", DeclarationFragments::FragmentKind::Text);1351Fragments.append("...", DeclarationFragments::FragmentKind::Text);1352}1353Fragments.append(")", DeclarationFragments::FragmentKind::Text);1354}1355return Fragments;1356}13571358DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory(1359const ObjCCategoryDecl *Category) {1360DeclarationFragments Fragments;13611362auto *Interface = Category->getClassInterface();1363SmallString<128> InterfaceUSR;1364index::generateUSRForDecl(Interface, InterfaceUSR);13651366Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)1367.appendSpace()1368.append(Interface->getName(),1369DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR,1370Interface)1371.append(" (", DeclarationFragments::FragmentKind::Text)1372.append(Category->getName(),1373DeclarationFragments::FragmentKind::Identifier)1374.append(")", DeclarationFragments::FragmentKind::Text);13751376return Fragments;1377}13781379DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface(1380const ObjCInterfaceDecl *Interface) {1381DeclarationFragments Fragments;1382// Build the base of the Objective-C interface declaration.1383Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)1384.appendSpace()1385.append(Interface->getName(),1386DeclarationFragments::FragmentKind::Identifier);13871388// Build the inheritance part of the declaration.1389if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) {1390SmallString<128> SuperUSR;1391index::generateUSRForDecl(SuperClass, SuperUSR);1392Fragments.append(" : ", DeclarationFragments::FragmentKind::Text)1393.append(SuperClass->getName(),1394DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR,1395SuperClass);1396}13971398return Fragments;1399}14001401DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod(1402const ObjCMethodDecl *Method) {1403DeclarationFragments Fragments, After;1404// Build the instance/class method indicator.1405if (Method->isClassMethod())1406Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);1407else if (Method->isInstanceMethod())1408Fragments.append("- ", DeclarationFragments::FragmentKind::Text);14091410// Build the return type.1411Fragments.append("(", DeclarationFragments::FragmentKind::Text)1412.append(getFragmentsForType(Method->getReturnType(),1413Method->getASTContext(), After))1414.append(std::move(After))1415.append(")", DeclarationFragments::FragmentKind::Text);14161417// Build the selector part.1418Selector Selector = Method->getSelector();1419if (Selector.getNumArgs() == 0)1420// For Objective-C methods that don't take arguments, the first (and only)1421// slot of the selector is the method name.1422Fragments.appendSpace().append(1423Selector.getNameForSlot(0),1424DeclarationFragments::FragmentKind::Identifier);14251426// For Objective-C methods that take arguments, build the selector slots.1427for (unsigned i = 0, end = Method->param_size(); i != end; ++i) {1428// Objective-C method selector parts are considered as identifiers instead1429// of "external parameters" as in Swift. This is because Objective-C method1430// symbols are referenced with the entire selector, instead of just the1431// method name in Swift.1432SmallString<32> ParamID(Selector.getNameForSlot(i));1433ParamID.append(":");1434Fragments.appendSpace().append(1435ParamID, DeclarationFragments::FragmentKind::Identifier);14361437// Build the internal parameter.1438const ParmVarDecl *Param = Method->getParamDecl(i);1439Fragments.append(getFragmentsForParam(Param));1440}14411442return Fragments.appendSemicolon();1443}14441445DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(1446const ObjCPropertyDecl *Property) {1447DeclarationFragments Fragments, After;14481449// Build the Objective-C property keyword.1450Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword);14511452const auto Attributes = Property->getPropertyAttributesAsWritten();1453// Build the attributes if there is any associated with the property.1454if (Attributes != ObjCPropertyAttribute::kind_noattr) {1455// No leading comma for the first attribute.1456bool First = true;1457Fragments.append(" (", DeclarationFragments::FragmentKind::Text);1458// Helper function to render the attribute.1459auto RenderAttribute =1460[&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling,1461StringRef Arg = "",1462DeclarationFragments::FragmentKind ArgKind =1463DeclarationFragments::FragmentKind::Identifier) {1464// Check if the `Kind` attribute is set for this property.1465if ((Attributes & Kind) && !Spelling.empty()) {1466// Add a leading comma if this is not the first attribute rendered.1467if (!First)1468Fragments.append(", ", DeclarationFragments::FragmentKind::Text);1469// Render the spelling of this attribute `Kind` as a keyword.1470Fragments.append(Spelling,1471DeclarationFragments::FragmentKind::Keyword);1472// If this attribute takes in arguments (e.g. `getter=getterName`),1473// render the arguments.1474if (!Arg.empty())1475Fragments.append("=", DeclarationFragments::FragmentKind::Text)1476.append(Arg, ArgKind);1477First = false;1478}1479};14801481// Go through all possible Objective-C property attributes and render set1482// ones.1483RenderAttribute(ObjCPropertyAttribute::kind_class, "class");1484RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct");1485RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic");1486RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic");1487RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign");1488RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain");1489RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong");1490RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy");1491RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak");1492RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained,1493"unsafe_unretained");1494RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite");1495RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly");1496RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter",1497Property->getGetterName().getAsString());1498RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter",1499Property->getSetterName().getAsString());15001501// Render nullability attributes.1502if (Attributes & ObjCPropertyAttribute::kind_nullability) {1503QualType Type = Property->getType();1504if (const auto Nullability =1505AttributedType::stripOuterNullability(Type)) {1506if (!First)1507Fragments.append(", ", DeclarationFragments::FragmentKind::Text);1508if (*Nullability == NullabilityKind::Unspecified &&1509(Attributes & ObjCPropertyAttribute::kind_null_resettable))1510Fragments.append("null_resettable",1511DeclarationFragments::FragmentKind::Keyword);1512else1513Fragments.append(1514getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true),1515DeclarationFragments::FragmentKind::Keyword);1516First = false;1517}1518}15191520Fragments.append(")", DeclarationFragments::FragmentKind::Text);1521}15221523Fragments.appendSpace();15241525FunctionTypeLoc BlockLoc;1526FunctionProtoTypeLoc BlockProtoLoc;1527findTypeLocForBlockDecl(Property->getTypeSourceInfo(), BlockLoc,1528BlockProtoLoc);15291530auto PropType = Property->getType();1531if (!BlockLoc)1532Fragments1533.append(getFragmentsForType(PropType, Property->getASTContext(), After))1534.appendSpace();1535else1536Fragments.append(1537getFragmentsForBlock(Property, BlockLoc, BlockProtoLoc, After));15381539return Fragments1540.append(Property->getName(),1541DeclarationFragments::FragmentKind::Identifier)1542.append(std::move(After))1543.appendSemicolon();1544}15451546DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(1547const ObjCProtocolDecl *Protocol) {1548DeclarationFragments Fragments;1549// Build basic protocol declaration.1550Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword)1551.appendSpace()1552.append(Protocol->getName(),1553DeclarationFragments::FragmentKind::Identifier);15541555// If this protocol conforms to other protocols, build the conformance list.1556if (!Protocol->protocols().empty()) {1557Fragments.append(" <", DeclarationFragments::FragmentKind::Text);1558for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin();1559It != Protocol->protocol_end(); It++) {1560// Add a leading comma if this is not the first protocol rendered.1561if (It != Protocol->protocol_begin())1562Fragments.append(", ", DeclarationFragments::FragmentKind::Text);15631564SmallString<128> USR;1565index::generateUSRForDecl(*It, USR);1566Fragments.append((*It)->getName(),1567DeclarationFragments::FragmentKind::TypeIdentifier, USR,1568*It);1569}1570Fragments.append(">", DeclarationFragments::FragmentKind::Text);1571}15721573return Fragments;1574}15751576DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(1577const TypedefNameDecl *Decl) {1578DeclarationFragments Fragments, After;1579Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword)1580.appendSpace()1581.append(getFragmentsForType(Decl->getUnderlyingType(),1582Decl->getASTContext(), After))1583.append(std::move(After))1584.appendSpace()1585.append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier);15861587return Fragments.appendSemicolon();1588}15891590// Instantiate template for FunctionDecl.1591template FunctionSignature1592DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *);15931594// Instantiate template for ObjCMethodDecl.1595template FunctionSignature1596DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *);15971598// Subheading of a symbol defaults to its name.1599DeclarationFragments1600DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) {1601DeclarationFragments Fragments;1602if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl))1603Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(),1604DeclarationFragments::FragmentKind::Identifier);1605else if (isa<CXXConversionDecl>(Decl)) {1606Fragments.append(1607cast<CXXConversionDecl>(Decl)->getConversionType().getAsString(),1608DeclarationFragments::FragmentKind::Identifier);1609} else if (isa<CXXMethodDecl>(Decl) &&1610cast<CXXMethodDecl>(Decl)->isOverloadedOperator()) {1611Fragments.append(Decl->getNameAsString(),1612DeclarationFragments::FragmentKind::Identifier);1613} else if (Decl->getIdentifier()) {1614Fragments.append(Decl->getName(),1615DeclarationFragments::FragmentKind::Identifier);1616} else1617Fragments.append(Decl->getDeclName().getAsString(),1618DeclarationFragments::FragmentKind::Identifier);1619return Fragments;1620}16211622// Subheading of an Objective-C method is a `+` or `-` sign indicating whether1623// it's a class method or an instance method, followed by the selector name.1624DeclarationFragments1625DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) {1626DeclarationFragments Fragments;1627if (Method->isClassMethod())1628Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);1629else if (Method->isInstanceMethod())1630Fragments.append("- ", DeclarationFragments::FragmentKind::Text);16311632return Fragments.append(Method->getNameAsString(),1633DeclarationFragments::FragmentKind::Identifier);1634}16351636// Subheading of a symbol defaults to its name.1637DeclarationFragments1638DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) {1639DeclarationFragments Fragments;1640Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);1641return Fragments;1642}164316441645