189f6b26fSZixu Wang //===- ExtractAPI/DeclarationFragments.cpp ----------------------*- C++ -*-===// 289f6b26fSZixu Wang // 389f6b26fSZixu Wang // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 489f6b26fSZixu Wang // See https://llvm.org/LICENSE.txt for license information. 589f6b26fSZixu Wang // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 689f6b26fSZixu Wang // 789f6b26fSZixu Wang //===----------------------------------------------------------------------===// 889f6b26fSZixu Wang /// 989f6b26fSZixu Wang /// \file 1089f6b26fSZixu Wang /// This file implements Declaration Fragments related classes. 1189f6b26fSZixu Wang /// 1289f6b26fSZixu Wang //===----------------------------------------------------------------------===// 1389f6b26fSZixu Wang 1489f6b26fSZixu Wang #include "clang/ExtractAPI/DeclarationFragments.h" 157a674793SDaniel Grumberg #include "clang/AST/ASTFwd.h" 1675f55eb3SErick Velez #include "clang/AST/Decl.h" 1775f55eb3SErick Velez #include "clang/AST/DeclCXX.h" 187a674793SDaniel Grumberg #include "clang/AST/TemplateBase.h" 197a674793SDaniel Grumberg #include "clang/AST/TemplateName.h" 206b89fab8SDaniel Grumberg #include "clang/AST/Type.h" 216b89fab8SDaniel Grumberg #include "clang/AST/TypeLoc.h" 22142c3d9dSDaniel Grumberg #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h" 2389f6b26fSZixu Wang #include "clang/Index/USRGeneration.h" 2489f6b26fSZixu Wang #include "llvm/ADT/StringSwitch.h" 257a674793SDaniel Grumberg #include "llvm/Support/ErrorHandling.h" 267a674793SDaniel Grumberg #include "llvm/Support/raw_ostream.h" 277a674793SDaniel Grumberg #include <optional> 2889f6b26fSZixu Wang 2989f6b26fSZixu Wang using namespace clang::extractapi; 3089f6b26fSZixu Wang using namespace llvm; 3189f6b26fSZixu Wang 326b89fab8SDaniel Grumberg namespace { 336b89fab8SDaniel Grumberg 346b89fab8SDaniel Grumberg void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo, 356b89fab8SDaniel Grumberg clang::FunctionTypeLoc &Block, 366b89fab8SDaniel Grumberg clang::FunctionProtoTypeLoc &BlockProto) { 376b89fab8SDaniel Grumberg if (!TSInfo) 386b89fab8SDaniel Grumberg return; 396b89fab8SDaniel Grumberg 406b89fab8SDaniel Grumberg clang::TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc(); 416b89fab8SDaniel Grumberg while (true) { 426b89fab8SDaniel Grumberg // Look through qualified types 436b89fab8SDaniel Grumberg if (auto QualifiedTL = TL.getAs<clang::QualifiedTypeLoc>()) { 446b89fab8SDaniel Grumberg TL = QualifiedTL.getUnqualifiedLoc(); 456b89fab8SDaniel Grumberg continue; 466b89fab8SDaniel Grumberg } 476b89fab8SDaniel Grumberg 486b89fab8SDaniel Grumberg if (auto AttrTL = TL.getAs<clang::AttributedTypeLoc>()) { 496b89fab8SDaniel Grumberg TL = AttrTL.getModifiedLoc(); 506b89fab8SDaniel Grumberg continue; 516b89fab8SDaniel Grumberg } 526b89fab8SDaniel Grumberg 536b89fab8SDaniel Grumberg // Try to get the function prototype behind the block pointer type, 546b89fab8SDaniel Grumberg // then we're done. 556b89fab8SDaniel Grumberg if (auto BlockPtr = TL.getAs<clang::BlockPointerTypeLoc>()) { 566b89fab8SDaniel Grumberg TL = BlockPtr.getPointeeLoc().IgnoreParens(); 576b89fab8SDaniel Grumberg Block = TL.getAs<clang::FunctionTypeLoc>(); 586b89fab8SDaniel Grumberg BlockProto = TL.getAs<clang::FunctionProtoTypeLoc>(); 596b89fab8SDaniel Grumberg } 606b89fab8SDaniel Grumberg break; 616b89fab8SDaniel Grumberg } 626b89fab8SDaniel Grumberg } 636b89fab8SDaniel Grumberg 646b89fab8SDaniel Grumberg } // namespace 656b89fab8SDaniel Grumberg 66e05c1b46SDaniel Grumberg DeclarationFragments & 67e05c1b46SDaniel Grumberg DeclarationFragments::appendUnduplicatedTextCharacter(char Character) { 6889f6b26fSZixu Wang if (!Fragments.empty()) { 69fe2c77a0SZixu Wang Fragment &Last = Fragments.back(); 7089f6b26fSZixu Wang if (Last.Kind == FragmentKind::Text) { 7189f6b26fSZixu Wang // Merge the extra space into the last fragment if the last fragment is 7289f6b26fSZixu Wang // also text. 73e05c1b46SDaniel Grumberg if (Last.Spelling.back() != Character) { // avoid duplicates at end 74e05c1b46SDaniel Grumberg Last.Spelling.push_back(Character); 7589f6b26fSZixu Wang } 7689f6b26fSZixu Wang } else { 7789f6b26fSZixu Wang append("", FragmentKind::Text); 78e05c1b46SDaniel Grumberg Fragments.back().Spelling.push_back(Character); 7989f6b26fSZixu Wang } 8089f6b26fSZixu Wang } 8189f6b26fSZixu Wang 8289f6b26fSZixu Wang return *this; 8389f6b26fSZixu Wang } 8489f6b26fSZixu Wang 85e05c1b46SDaniel Grumberg DeclarationFragments &DeclarationFragments::appendSpace() { 86e05c1b46SDaniel Grumberg return appendUnduplicatedTextCharacter(' '); 87e05c1b46SDaniel Grumberg } 88e05c1b46SDaniel Grumberg 89e05c1b46SDaniel Grumberg DeclarationFragments &DeclarationFragments::appendSemicolon() { 90e05c1b46SDaniel Grumberg return appendUnduplicatedTextCharacter(';'); 91e05c1b46SDaniel Grumberg } 92e05c1b46SDaniel Grumberg 93e05c1b46SDaniel Grumberg DeclarationFragments &DeclarationFragments::removeTrailingSemicolon() { 94e05c1b46SDaniel Grumberg if (Fragments.empty()) 95e05c1b46SDaniel Grumberg return *this; 96e05c1b46SDaniel Grumberg 97e05c1b46SDaniel Grumberg Fragment &Last = Fragments.back(); 98e05c1b46SDaniel Grumberg if (Last.Kind == FragmentKind::Text && Last.Spelling.back() == ';') 99e05c1b46SDaniel Grumberg Last.Spelling.pop_back(); 100e05c1b46SDaniel Grumberg 101e05c1b46SDaniel Grumberg return *this; 102e05c1b46SDaniel Grumberg } 103e05c1b46SDaniel Grumberg 10489f6b26fSZixu Wang StringRef DeclarationFragments::getFragmentKindString( 10589f6b26fSZixu Wang DeclarationFragments::FragmentKind Kind) { 10689f6b26fSZixu Wang switch (Kind) { 10789f6b26fSZixu Wang case DeclarationFragments::FragmentKind::None: 10889f6b26fSZixu Wang return "none"; 10989f6b26fSZixu Wang case DeclarationFragments::FragmentKind::Keyword: 11089f6b26fSZixu Wang return "keyword"; 11189f6b26fSZixu Wang case DeclarationFragments::FragmentKind::Attribute: 11289f6b26fSZixu Wang return "attribute"; 11389f6b26fSZixu Wang case DeclarationFragments::FragmentKind::NumberLiteral: 11489f6b26fSZixu Wang return "number"; 11589f6b26fSZixu Wang case DeclarationFragments::FragmentKind::StringLiteral: 11689f6b26fSZixu Wang return "string"; 11789f6b26fSZixu Wang case DeclarationFragments::FragmentKind::Identifier: 11889f6b26fSZixu Wang return "identifier"; 11989f6b26fSZixu Wang case DeclarationFragments::FragmentKind::TypeIdentifier: 12089f6b26fSZixu Wang return "typeIdentifier"; 12189f6b26fSZixu Wang case DeclarationFragments::FragmentKind::GenericParameter: 12289f6b26fSZixu Wang return "genericParameter"; 12389f6b26fSZixu Wang case DeclarationFragments::FragmentKind::ExternalParam: 12489f6b26fSZixu Wang return "externalParam"; 12589f6b26fSZixu Wang case DeclarationFragments::FragmentKind::InternalParam: 12689f6b26fSZixu Wang return "internalParam"; 12789f6b26fSZixu Wang case DeclarationFragments::FragmentKind::Text: 12889f6b26fSZixu Wang return "text"; 12989f6b26fSZixu Wang } 13089f6b26fSZixu Wang 13189f6b26fSZixu Wang llvm_unreachable("Unhandled FragmentKind"); 13289f6b26fSZixu Wang } 13389f6b26fSZixu Wang 13489f6b26fSZixu Wang DeclarationFragments::FragmentKind 13589f6b26fSZixu Wang DeclarationFragments::parseFragmentKindFromString(StringRef S) { 13689f6b26fSZixu Wang return llvm::StringSwitch<FragmentKind>(S) 13789f6b26fSZixu Wang .Case("keyword", DeclarationFragments::FragmentKind::Keyword) 13889f6b26fSZixu Wang .Case("attribute", DeclarationFragments::FragmentKind::Attribute) 13989f6b26fSZixu Wang .Case("number", DeclarationFragments::FragmentKind::NumberLiteral) 14089f6b26fSZixu Wang .Case("string", DeclarationFragments::FragmentKind::StringLiteral) 14189f6b26fSZixu Wang .Case("identifier", DeclarationFragments::FragmentKind::Identifier) 14289f6b26fSZixu Wang .Case("typeIdentifier", 14389f6b26fSZixu Wang DeclarationFragments::FragmentKind::TypeIdentifier) 14489f6b26fSZixu Wang .Case("genericParameter", 14589f6b26fSZixu Wang DeclarationFragments::FragmentKind::GenericParameter) 14689f6b26fSZixu Wang .Case("internalParam", DeclarationFragments::FragmentKind::InternalParam) 14789f6b26fSZixu Wang .Case("externalParam", DeclarationFragments::FragmentKind::ExternalParam) 14889f6b26fSZixu Wang .Case("text", DeclarationFragments::FragmentKind::Text) 14989f6b26fSZixu Wang .Default(DeclarationFragments::FragmentKind::None); 15089f6b26fSZixu Wang } 15189f6b26fSZixu Wang 15275f55eb3SErick Velez DeclarationFragments DeclarationFragments::getExceptionSpecificationString( 15375f55eb3SErick Velez ExceptionSpecificationType ExceptionSpec) { 15475f55eb3SErick Velez DeclarationFragments Fragments; 15575f55eb3SErick Velez switch (ExceptionSpec) { 15675f55eb3SErick Velez case ExceptionSpecificationType::EST_None: 15775f55eb3SErick Velez return Fragments; 15875f55eb3SErick Velez case ExceptionSpecificationType::EST_DynamicNone: 15975f55eb3SErick Velez return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) 16075f55eb3SErick Velez .append("throw", DeclarationFragments::FragmentKind::Keyword) 16175f55eb3SErick Velez .append("(", DeclarationFragments::FragmentKind::Text) 16275f55eb3SErick Velez .append(")", DeclarationFragments::FragmentKind::Text); 16375f55eb3SErick Velez case ExceptionSpecificationType::EST_Dynamic: 16475f55eb3SErick Velez // FIXME: throw(int), get types of inner expression 16575f55eb3SErick Velez return Fragments; 16675f55eb3SErick Velez case ExceptionSpecificationType::EST_BasicNoexcept: 16775f55eb3SErick Velez return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) 16875f55eb3SErick Velez .append("noexcept", DeclarationFragments::FragmentKind::Keyword); 16975f55eb3SErick Velez case ExceptionSpecificationType::EST_DependentNoexcept: 17075f55eb3SErick Velez // FIXME: throw(conditional-expression), get expression 17175f55eb3SErick Velez break; 17275f55eb3SErick Velez case ExceptionSpecificationType::EST_NoexceptFalse: 17375f55eb3SErick Velez return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) 17475f55eb3SErick Velez .append("noexcept", DeclarationFragments::FragmentKind::Keyword) 17575f55eb3SErick Velez .append("(", DeclarationFragments::FragmentKind::Text) 17675f55eb3SErick Velez .append("false", DeclarationFragments::FragmentKind::Keyword) 17775f55eb3SErick Velez .append(")", DeclarationFragments::FragmentKind::Text); 17875f55eb3SErick Velez case ExceptionSpecificationType::EST_NoexceptTrue: 17975f55eb3SErick Velez return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) 18075f55eb3SErick Velez .append("noexcept", DeclarationFragments::FragmentKind::Keyword) 18175f55eb3SErick Velez .append("(", DeclarationFragments::FragmentKind::Text) 18275f55eb3SErick Velez .append("true", DeclarationFragments::FragmentKind::Keyword) 18375f55eb3SErick Velez .append(")", DeclarationFragments::FragmentKind::Text); 18475f55eb3SErick Velez default: 18575f55eb3SErick Velez return Fragments; 18675f55eb3SErick Velez } 18775f55eb3SErick Velez 18875f55eb3SErick Velez llvm_unreachable("Unhandled exception specification"); 18975f55eb3SErick Velez } 19075f55eb3SErick Velez 19175f55eb3SErick Velez DeclarationFragments 19275f55eb3SErick Velez DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) { 19375f55eb3SErick Velez DeclarationFragments Fragments; 19475f55eb3SErick Velez if (Record->isStruct()) 19575f55eb3SErick Velez Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword); 19675f55eb3SErick Velez else if (Record->isUnion()) 19775f55eb3SErick Velez Fragments.append("union", DeclarationFragments::FragmentKind::Keyword); 19875f55eb3SErick Velez else 19975f55eb3SErick Velez Fragments.append("class", DeclarationFragments::FragmentKind::Keyword); 20075f55eb3SErick Velez 20175f55eb3SErick Velez return Fragments; 20275f55eb3SErick Velez } 20375f55eb3SErick Velez 20489f6b26fSZixu Wang // NNS stores C++ nested name specifiers, which are prefixes to qualified names. 20589f6b26fSZixu Wang // Build declaration fragments for NNS recursively so that we have the USR for 20689f6b26fSZixu Wang // every part in a qualified name, and also leaves the actual underlying type 20789f6b26fSZixu Wang // cleaner for its own fragment. 20889f6b26fSZixu Wang DeclarationFragments 20989f6b26fSZixu Wang DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS, 21089f6b26fSZixu Wang ASTContext &Context, 21189f6b26fSZixu Wang DeclarationFragments &After) { 21289f6b26fSZixu Wang DeclarationFragments Fragments; 21389f6b26fSZixu Wang if (NNS->getPrefix()) 21489f6b26fSZixu Wang Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After)); 21589f6b26fSZixu Wang 21689f6b26fSZixu Wang switch (NNS->getKind()) { 21789f6b26fSZixu Wang case NestedNameSpecifier::Identifier: 21889f6b26fSZixu Wang Fragments.append(NNS->getAsIdentifier()->getName(), 21989f6b26fSZixu Wang DeclarationFragments::FragmentKind::Identifier); 22089f6b26fSZixu Wang break; 22189f6b26fSZixu Wang 22289f6b26fSZixu Wang case NestedNameSpecifier::Namespace: { 22389f6b26fSZixu Wang const NamespaceDecl *NS = NNS->getAsNamespace(); 22489f6b26fSZixu Wang if (NS->isAnonymousNamespace()) 22589f6b26fSZixu Wang return Fragments; 22689f6b26fSZixu Wang SmallString<128> USR; 22789f6b26fSZixu Wang index::generateUSRForDecl(NS, USR); 22889f6b26fSZixu Wang Fragments.append(NS->getName(), 2297a851921SDaniel Grumberg DeclarationFragments::FragmentKind::Identifier, USR, NS); 23089f6b26fSZixu Wang break; 23189f6b26fSZixu Wang } 23289f6b26fSZixu Wang 23389f6b26fSZixu Wang case NestedNameSpecifier::NamespaceAlias: { 23489f6b26fSZixu Wang const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias(); 23589f6b26fSZixu Wang SmallString<128> USR; 23689f6b26fSZixu Wang index::generateUSRForDecl(Alias, USR); 23789f6b26fSZixu Wang Fragments.append(Alias->getName(), 2387a851921SDaniel Grumberg DeclarationFragments::FragmentKind::Identifier, USR, 2397a851921SDaniel Grumberg Alias); 24089f6b26fSZixu Wang break; 24189f6b26fSZixu Wang } 24289f6b26fSZixu Wang 24389f6b26fSZixu Wang case NestedNameSpecifier::Global: 24489f6b26fSZixu Wang // The global specifier `::` at the beginning. No stored value. 24589f6b26fSZixu Wang break; 24689f6b26fSZixu Wang 24789f6b26fSZixu Wang case NestedNameSpecifier::Super: 24889f6b26fSZixu Wang // Microsoft's `__super` specifier. 24989f6b26fSZixu Wang Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword); 25089f6b26fSZixu Wang break; 25189f6b26fSZixu Wang 25289f6b26fSZixu Wang case NestedNameSpecifier::TypeSpecWithTemplate: 25389f6b26fSZixu Wang // A type prefixed by the `template` keyword. 25489f6b26fSZixu Wang Fragments.append("template", DeclarationFragments::FragmentKind::Keyword); 25589f6b26fSZixu Wang Fragments.appendSpace(); 25689f6b26fSZixu Wang // Fallthrough after adding the keyword to handle the actual type. 2573f18f7c0SFangrui Song [[fallthrough]]; 25889f6b26fSZixu Wang 25989f6b26fSZixu Wang case NestedNameSpecifier::TypeSpec: { 26089f6b26fSZixu Wang const Type *T = NNS->getAsType(); 26189f6b26fSZixu Wang // FIXME: Handle C++ template specialization type 26289f6b26fSZixu Wang Fragments.append(getFragmentsForType(T, Context, After)); 26389f6b26fSZixu Wang break; 26489f6b26fSZixu Wang } 26589f6b26fSZixu Wang } 26689f6b26fSZixu Wang 26789f6b26fSZixu Wang // Add the separator text `::` for this segment. 26889f6b26fSZixu Wang return Fragments.append("::", DeclarationFragments::FragmentKind::Text); 26989f6b26fSZixu Wang } 27089f6b26fSZixu Wang 27189f6b26fSZixu Wang // Recursively build the declaration fragments for an underlying `Type` with 27289f6b26fSZixu Wang // qualifiers removed. 27389f6b26fSZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( 27489f6b26fSZixu Wang const Type *T, ASTContext &Context, DeclarationFragments &After) { 27589f6b26fSZixu Wang assert(T && "invalid type"); 27689f6b26fSZixu Wang 27789f6b26fSZixu Wang DeclarationFragments Fragments; 27889f6b26fSZixu Wang 279cf1ad281SDaniel Grumberg if (const MacroQualifiedType *MQT = dyn_cast<MacroQualifiedType>(T)) { 280cf1ad281SDaniel Grumberg Fragments.append( 281cf1ad281SDaniel Grumberg getFragmentsForType(MQT->getUnderlyingType(), Context, After)); 282cf1ad281SDaniel Grumberg return Fragments; 283cf1ad281SDaniel Grumberg } 284cf1ad281SDaniel Grumberg 285cf1ad281SDaniel Grumberg if (const AttributedType *AT = dyn_cast<AttributedType>(T)) { 286cf1ad281SDaniel Grumberg // FIXME: Serialize Attributes correctly 287cf1ad281SDaniel Grumberg Fragments.append( 288cf1ad281SDaniel Grumberg getFragmentsForType(AT->getModifiedType(), Context, After)); 289cf1ad281SDaniel Grumberg return Fragments; 290cf1ad281SDaniel Grumberg } 291cf1ad281SDaniel Grumberg 292c5532124SDaniel Grumberg // An ElaboratedType is a sugar for types that are referred to using an 293c5532124SDaniel Grumberg // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a 294c5532124SDaniel Grumberg // qualified name, e.g., `N::M::type`, or both. 295c5532124SDaniel Grumberg if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) { 296c5532124SDaniel Grumberg ElaboratedTypeKeyword Keyword = ET->getKeyword(); 297c5532124SDaniel Grumberg if (Keyword != ElaboratedTypeKeyword::None) { 298c5532124SDaniel Grumberg Fragments 299c5532124SDaniel Grumberg .append(ElaboratedType::getKeywordName(Keyword), 300c5532124SDaniel Grumberg DeclarationFragments::FragmentKind::Keyword) 301c5532124SDaniel Grumberg .appendSpace(); 302c5532124SDaniel Grumberg } 303c5532124SDaniel Grumberg 304c5532124SDaniel Grumberg if (const NestedNameSpecifier *NNS = ET->getQualifier()) 305c5532124SDaniel Grumberg Fragments.append(getFragmentsForNNS(NNS, Context, After)); 306c5532124SDaniel Grumberg 307c5532124SDaniel Grumberg // After handling the elaborated keyword or qualified name, build 308c5532124SDaniel Grumberg // declaration fragments for the desugared underlying type. 309c5532124SDaniel Grumberg return Fragments.append(getFragmentsForType(ET->desugar(), Context, After)); 310c5532124SDaniel Grumberg } 311c5532124SDaniel Grumberg 312c5532124SDaniel Grumberg // If the type is a typedefed type, get the underlying TypedefNameDecl for a 313c5532124SDaniel Grumberg // direct reference to the typedef instead of the wrapped type. 314c5532124SDaniel Grumberg 315c5532124SDaniel Grumberg // 'id' type is a typedef for an ObjCObjectPointerType 316c5532124SDaniel Grumberg // we treat it as a typedef 317c5532124SDaniel Grumberg if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) { 318c5532124SDaniel Grumberg const TypedefNameDecl *Decl = TypedefTy->getDecl(); 319c5532124SDaniel Grumberg TypedefUnderlyingTypeResolver TypedefResolver(Context); 320c5532124SDaniel Grumberg std::string USR = TypedefResolver.getUSRForType(QualType(T, 0)); 321c5532124SDaniel Grumberg 322c5532124SDaniel Grumberg if (T->isObjCIdType()) { 323c5532124SDaniel Grumberg return Fragments.append(Decl->getName(), 324c5532124SDaniel Grumberg DeclarationFragments::FragmentKind::Keyword); 325c5532124SDaniel Grumberg } 326c5532124SDaniel Grumberg 327c5532124SDaniel Grumberg return Fragments.append( 328c5532124SDaniel Grumberg Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier, 329c5532124SDaniel Grumberg USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0))); 330c5532124SDaniel Grumberg } 331c5532124SDaniel Grumberg 33289f6b26fSZixu Wang // Declaration fragments of a pointer type is the declaration fragments of 333a590d863SNagaChaitanya Vellanki // the pointee type followed by a `*`, 3346b89fab8SDaniel Grumberg if (T->isPointerType() && !T->isFunctionPointerType()) 33589f6b26fSZixu Wang return Fragments 33689f6b26fSZixu Wang .append(getFragmentsForType(T->getPointeeType(), Context, After)) 33789f6b26fSZixu Wang .append(" *", DeclarationFragments::FragmentKind::Text); 338a590d863SNagaChaitanya Vellanki 339a590d863SNagaChaitanya Vellanki // For Objective-C `id` and `Class` pointers 340a590d863SNagaChaitanya Vellanki // we do not spell out the `*`. 341a590d863SNagaChaitanya Vellanki if (T->isObjCObjectPointerType() && 342a590d863SNagaChaitanya Vellanki !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) { 343a590d863SNagaChaitanya Vellanki 344a590d863SNagaChaitanya Vellanki Fragments.append(getFragmentsForType(T->getPointeeType(), Context, After)); 345a590d863SNagaChaitanya Vellanki 346a590d863SNagaChaitanya Vellanki // id<protocol> is an qualified id type 347a590d863SNagaChaitanya Vellanki // id<protocol>* is not an qualified id type 348a590d863SNagaChaitanya Vellanki if (!T->getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) { 349a590d863SNagaChaitanya Vellanki Fragments.append(" *", DeclarationFragments::FragmentKind::Text); 350a590d863SNagaChaitanya Vellanki } 351a590d863SNagaChaitanya Vellanki 352a590d863SNagaChaitanya Vellanki return Fragments; 35389f6b26fSZixu Wang } 35489f6b26fSZixu Wang 35589f6b26fSZixu Wang // Declaration fragments of a lvalue reference type is the declaration 35689f6b26fSZixu Wang // fragments of the underlying type followed by a `&`. 35789f6b26fSZixu Wang if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T)) 35889f6b26fSZixu Wang return Fragments 35989f6b26fSZixu Wang .append( 36089f6b26fSZixu Wang getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After)) 36189f6b26fSZixu Wang .append(" &", DeclarationFragments::FragmentKind::Text); 36289f6b26fSZixu Wang 36389f6b26fSZixu Wang // Declaration fragments of a rvalue reference type is the declaration 36489f6b26fSZixu Wang // fragments of the underlying type followed by a `&&`. 36589f6b26fSZixu Wang if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T)) 36689f6b26fSZixu Wang return Fragments 36789f6b26fSZixu Wang .append( 36889f6b26fSZixu Wang getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After)) 36989f6b26fSZixu Wang .append(" &&", DeclarationFragments::FragmentKind::Text); 37089f6b26fSZixu Wang 37189f6b26fSZixu Wang // Declaration fragments of an array-typed variable have two parts: 37289f6b26fSZixu Wang // 1. the element type of the array that appears before the variable name; 37389f6b26fSZixu Wang // 2. array brackets `[(0-9)?]` that appear after the variable name. 37489f6b26fSZixu Wang if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) { 37589f6b26fSZixu Wang // Build the "after" part first because the inner element type might also 37689f6b26fSZixu Wang // be an array-type. For example `int matrix[3][4]` which has a type of 37789f6b26fSZixu Wang // "(array 3 of (array 4 of ints))." 37889f6b26fSZixu Wang // Push the array size part first to make sure they are in the right order. 37989f6b26fSZixu Wang After.append("[", DeclarationFragments::FragmentKind::Text); 38089f6b26fSZixu Wang 38189f6b26fSZixu Wang switch (AT->getSizeModifier()) { 38249fd28d9SVlad Serebrennikov case ArraySizeModifier::Normal: 38389f6b26fSZixu Wang break; 38449fd28d9SVlad Serebrennikov case ArraySizeModifier::Static: 38589f6b26fSZixu Wang Fragments.append("static", DeclarationFragments::FragmentKind::Keyword); 38689f6b26fSZixu Wang break; 38749fd28d9SVlad Serebrennikov case ArraySizeModifier::Star: 38889f6b26fSZixu Wang Fragments.append("*", DeclarationFragments::FragmentKind::Text); 38989f6b26fSZixu Wang break; 39089f6b26fSZixu Wang } 39189f6b26fSZixu Wang 39289f6b26fSZixu Wang if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) { 39389f6b26fSZixu Wang // FIXME: right now this would evaluate any expressions/macros written in 39489f6b26fSZixu Wang // the original source to concrete values. For example 39589f6b26fSZixu Wang // `int nums[MAX]` -> `int nums[100]` 39689f6b26fSZixu Wang // `char *str[5 + 1]` -> `char *str[6]` 39789f6b26fSZixu Wang SmallString<128> Size; 39889f6b26fSZixu Wang CAT->getSize().toStringUnsigned(Size); 39989f6b26fSZixu Wang After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral); 40089f6b26fSZixu Wang } 40189f6b26fSZixu Wang 40289f6b26fSZixu Wang After.append("]", DeclarationFragments::FragmentKind::Text); 40389f6b26fSZixu Wang 40489f6b26fSZixu Wang return Fragments.append( 40589f6b26fSZixu Wang getFragmentsForType(AT->getElementType(), Context, After)); 40689f6b26fSZixu Wang } 40789f6b26fSZixu Wang 4087a674793SDaniel Grumberg if (const TemplateSpecializationType *TemplSpecTy = 4097a674793SDaniel Grumberg dyn_cast<TemplateSpecializationType>(T)) { 4107a674793SDaniel Grumberg const auto TemplName = TemplSpecTy->getTemplateName(); 4117a674793SDaniel Grumberg std::string Str; 4127a674793SDaniel Grumberg raw_string_ostream Stream(Str); 4137a674793SDaniel Grumberg TemplName.print(Stream, Context.getPrintingPolicy(), 4147a674793SDaniel Grumberg TemplateName::Qualified::AsWritten); 4157a674793SDaniel Grumberg SmallString<64> USR(""); 4167a674793SDaniel Grumberg if (const auto *TemplDecl = TemplName.getAsTemplateDecl()) 4177a674793SDaniel Grumberg index::generateUSRForDecl(TemplDecl, USR); 4187a674793SDaniel Grumberg 4197a674793SDaniel Grumberg return Fragments 4207a674793SDaniel Grumberg .append(Str, DeclarationFragments::FragmentKind::TypeIdentifier, USR) 4217a674793SDaniel Grumberg .append("<", DeclarationFragments::FragmentKind::Text) 4227a674793SDaniel Grumberg .append(getFragmentsForTemplateArguments( 4237a674793SDaniel Grumberg TemplSpecTy->template_arguments(), Context, std::nullopt)) 4247a674793SDaniel Grumberg .append(">", DeclarationFragments::FragmentKind::Text); 4257a674793SDaniel Grumberg } 4267a674793SDaniel Grumberg 427c13ccf1fSNagaChaitanya Vellanki // Everything we care about has been handled now, reduce to the canonical 428c13ccf1fSNagaChaitanya Vellanki // unqualified base type. 429c13ccf1fSNagaChaitanya Vellanki QualType Base = T->getCanonicalTypeUnqualified(); 430c13ccf1fSNagaChaitanya Vellanki 4319fc45ca0SDaniel Grumberg // If the base type is a TagType (struct/interface/union/class/enum), let's 4329fc45ca0SDaniel Grumberg // get the underlying Decl for better names and USRs. 4339fc45ca0SDaniel Grumberg if (const TagType *TagTy = dyn_cast<TagType>(Base)) { 4349fc45ca0SDaniel Grumberg const TagDecl *Decl = TagTy->getDecl(); 4359fc45ca0SDaniel Grumberg // Anonymous decl, skip this fragment. 4369fc45ca0SDaniel Grumberg if (Decl->getName().empty()) 4372bcbe40fSDaniel Grumberg return Fragments.append("{ ... }", 4382bcbe40fSDaniel Grumberg DeclarationFragments::FragmentKind::Text); 4399fc45ca0SDaniel Grumberg SmallString<128> TagUSR; 4409fc45ca0SDaniel Grumberg clang::index::generateUSRForDecl(Decl, TagUSR); 4419fc45ca0SDaniel Grumberg return Fragments.append(Decl->getName(), 4429fc45ca0SDaniel Grumberg DeclarationFragments::FragmentKind::TypeIdentifier, 4437a851921SDaniel Grumberg TagUSR, Decl); 4449fc45ca0SDaniel Grumberg } 4459fc45ca0SDaniel Grumberg 4469b36e126SZixu Wang // If the base type is an ObjCInterfaceType, use the underlying 4479b36e126SZixu Wang // ObjCInterfaceDecl for the true USR. 4489b36e126SZixu Wang if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) { 4499b36e126SZixu Wang const auto *Decl = ObjCIT->getDecl(); 4509b36e126SZixu Wang SmallString<128> USR; 4519b36e126SZixu Wang index::generateUSRForDecl(Decl, USR); 4529b36e126SZixu Wang return Fragments.append(Decl->getName(), 4539b36e126SZixu Wang DeclarationFragments::FragmentKind::TypeIdentifier, 4547a851921SDaniel Grumberg USR, Decl); 4559b36e126SZixu Wang } 4569b36e126SZixu Wang 45789f6b26fSZixu Wang // Default fragment builder for other kinds of types (BuiltinType etc.) 45889f6b26fSZixu Wang SmallString<128> USR; 45989f6b26fSZixu Wang clang::index::generateUSRForType(Base, Context, USR); 46089f6b26fSZixu Wang Fragments.append(Base.getAsString(), 46189f6b26fSZixu Wang DeclarationFragments::FragmentKind::TypeIdentifier, USR); 46289f6b26fSZixu Wang 46389f6b26fSZixu Wang return Fragments; 46489f6b26fSZixu Wang } 46589f6b26fSZixu Wang 46689f6b26fSZixu Wang DeclarationFragments 46789f6b26fSZixu Wang DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) { 46889f6b26fSZixu Wang DeclarationFragments Fragments; 46989f6b26fSZixu Wang if (Quals.hasConst()) 47089f6b26fSZixu Wang Fragments.append("const", DeclarationFragments::FragmentKind::Keyword); 47189f6b26fSZixu Wang if (Quals.hasVolatile()) 47289f6b26fSZixu Wang Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword); 47389f6b26fSZixu Wang if (Quals.hasRestrict()) 47489f6b26fSZixu Wang Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword); 47589f6b26fSZixu Wang 47689f6b26fSZixu Wang return Fragments; 47789f6b26fSZixu Wang } 47889f6b26fSZixu Wang 47989f6b26fSZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( 48089f6b26fSZixu Wang const QualType QT, ASTContext &Context, DeclarationFragments &After) { 48189f6b26fSZixu Wang assert(!QT.isNull() && "invalid type"); 48289f6b26fSZixu Wang 48389f6b26fSZixu Wang if (const ParenType *PT = dyn_cast<ParenType>(QT)) { 48489f6b26fSZixu Wang After.append(")", DeclarationFragments::FragmentKind::Text); 48589f6b26fSZixu Wang return getFragmentsForType(PT->getInnerType(), Context, After) 48689f6b26fSZixu Wang .append("(", DeclarationFragments::FragmentKind::Text); 48789f6b26fSZixu Wang } 48889f6b26fSZixu Wang 48989f6b26fSZixu Wang const SplitQualType SQT = QT.split(); 49089f6b26fSZixu Wang DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals), 49189f6b26fSZixu Wang TypeFragments = 49289f6b26fSZixu Wang getFragmentsForType(SQT.Ty, Context, After); 493e8174456SErick Velez if (QT.getAsString() == "_Bool") 494e8174456SErick Velez TypeFragments.replace("bool", 0); 495e8174456SErick Velez 49689f6b26fSZixu Wang if (QualsFragments.getFragments().empty()) 49789f6b26fSZixu Wang return TypeFragments; 49889f6b26fSZixu Wang 49989f6b26fSZixu Wang // Use east qualifier for pointer types 50089f6b26fSZixu Wang // For example: 50189f6b26fSZixu Wang // ``` 50289f6b26fSZixu Wang // int * const 50389f6b26fSZixu Wang // ^---- ^---- 50489f6b26fSZixu Wang // type qualifier 50589f6b26fSZixu Wang // ^----------------- 50689f6b26fSZixu Wang // const pointer to int 50789f6b26fSZixu Wang // ``` 50889f6b26fSZixu Wang // should not be reconstructed as 50989f6b26fSZixu Wang // ``` 51089f6b26fSZixu Wang // const int * 51189f6b26fSZixu Wang // ^---- ^-- 51289f6b26fSZixu Wang // qualifier type 51389f6b26fSZixu Wang // ^---------------- ^ 51489f6b26fSZixu Wang // pointer to const int 51589f6b26fSZixu Wang // ``` 51689f6b26fSZixu Wang if (SQT.Ty->isAnyPointerType()) 51789f6b26fSZixu Wang return TypeFragments.appendSpace().append(std::move(QualsFragments)); 51889f6b26fSZixu Wang 51989f6b26fSZixu Wang return QualsFragments.appendSpace().append(std::move(TypeFragments)); 52089f6b26fSZixu Wang } 52189f6b26fSZixu Wang 52208f034f9SErick Velez DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace( 52308f034f9SErick Velez const NamespaceDecl *Decl) { 52408f034f9SErick Velez DeclarationFragments Fragments; 52508f034f9SErick Velez Fragments.append("namespace", DeclarationFragments::FragmentKind::Keyword); 52608f034f9SErick Velez if (!Decl->isAnonymousNamespace()) 52708f034f9SErick Velez Fragments.appendSpace().append( 52808f034f9SErick Velez Decl->getName(), DeclarationFragments::FragmentKind::Identifier); 529e05c1b46SDaniel Grumberg return Fragments.appendSemicolon(); 53008f034f9SErick Velez } 53108f034f9SErick Velez 53289f6b26fSZixu Wang DeclarationFragments 53389f6b26fSZixu Wang DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) { 53489f6b26fSZixu Wang DeclarationFragments Fragments; 53575f55eb3SErick Velez if (Var->isConstexpr()) 53675f55eb3SErick Velez Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 53775f55eb3SErick Velez .appendSpace(); 53875f55eb3SErick Velez 53989f6b26fSZixu Wang StorageClass SC = Var->getStorageClass(); 54089f6b26fSZixu Wang if (SC != SC_None) 54189f6b26fSZixu Wang Fragments 54289f6b26fSZixu Wang .append(VarDecl::getStorageClassSpecifierString(SC), 54389f6b26fSZixu Wang DeclarationFragments::FragmentKind::Keyword) 54489f6b26fSZixu Wang .appendSpace(); 54589f6b26fSZixu Wang 54689f6b26fSZixu Wang // Capture potential fragments that needs to be placed after the variable name 54789f6b26fSZixu Wang // ``` 54889f6b26fSZixu Wang // int nums[5]; 54989f6b26fSZixu Wang // char (*ptr_to_array)[6]; 55089f6b26fSZixu Wang // ``` 55189f6b26fSZixu Wang DeclarationFragments After; 5526b89fab8SDaniel Grumberg FunctionTypeLoc BlockLoc; 5536b89fab8SDaniel Grumberg FunctionProtoTypeLoc BlockProtoLoc; 5546b89fab8SDaniel Grumberg findTypeLocForBlockDecl(Var->getTypeSourceInfo(), BlockLoc, BlockProtoLoc); 5556b89fab8SDaniel Grumberg 5566b89fab8SDaniel Grumberg if (!BlockLoc) { 5576b89fab8SDaniel Grumberg QualType T = Var->getTypeSourceInfo() 5586b89fab8SDaniel Grumberg ? Var->getTypeSourceInfo()->getType() 5596b89fab8SDaniel Grumberg : Var->getASTContext().getUnqualifiedObjCPointerType( 5606b89fab8SDaniel Grumberg Var->getType()); 5616b89fab8SDaniel Grumberg 5626b89fab8SDaniel Grumberg Fragments.append(getFragmentsForType(T, Var->getASTContext(), After)) 5636b89fab8SDaniel Grumberg .appendSpace(); 5646b89fab8SDaniel Grumberg } else { 5656b89fab8SDaniel Grumberg Fragments.append(getFragmentsForBlock(Var, BlockLoc, BlockProtoLoc, After)); 5666b89fab8SDaniel Grumberg } 5676b89fab8SDaniel Grumberg 5686b89fab8SDaniel Grumberg return Fragments 56989f6b26fSZixu Wang .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) 570422bcd10SErick Velez .append(std::move(After)) 571e05c1b46SDaniel Grumberg .appendSemicolon(); 57289f6b26fSZixu Wang } 57389f6b26fSZixu Wang 57489f6b26fSZixu Wang DeclarationFragments 5758d8c8981SErick Velez DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) { 5768d8c8981SErick Velez DeclarationFragments Fragments; 5778d8c8981SErick Velez if (Var->isConstexpr()) 5788d8c8981SErick Velez Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 5798d8c8981SErick Velez .appendSpace(); 5808d8c8981SErick Velez QualType T = 5818d8c8981SErick Velez Var->getTypeSourceInfo() 5828d8c8981SErick Velez ? Var->getTypeSourceInfo()->getType() 5838d8c8981SErick Velez : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType()); 5848d8c8981SErick Velez 585634b2fd2SErick Velez // Might be a member, so might be static. 586634b2fd2SErick Velez if (Var->isStaticDataMember()) 587634b2fd2SErick Velez Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) 588634b2fd2SErick Velez .appendSpace(); 589634b2fd2SErick Velez 5908d8c8981SErick Velez DeclarationFragments After; 5918d8c8981SErick Velez DeclarationFragments ArgumentFragment = 5928d8c8981SErick Velez getFragmentsForType(T, Var->getASTContext(), After); 59326648daeSKazu Hirata if (StringRef(ArgumentFragment.begin()->Spelling) 59426648daeSKazu Hirata .starts_with("type-parameter")) { 5952b6c038eSErick Velez std::string ProperArgName = T.getAsString(); 5968d8c8981SErick Velez ArgumentFragment.begin()->Spelling.swap(ProperArgName); 5978d8c8981SErick Velez } 5988d8c8981SErick Velez Fragments.append(std::move(ArgumentFragment)) 5998d8c8981SErick Velez .appendSpace() 6008d8c8981SErick Velez .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) 601e05c1b46SDaniel Grumberg .appendSemicolon(); 6028d8c8981SErick Velez return Fragments; 6038d8c8981SErick Velez } 6048d8c8981SErick Velez 6058d8c8981SErick Velez DeclarationFragments 60689f6b26fSZixu Wang DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) { 60789f6b26fSZixu Wang DeclarationFragments Fragments, After; 60889f6b26fSZixu Wang 6096b89fab8SDaniel Grumberg auto *TSInfo = Param->getTypeSourceInfo(); 6106b89fab8SDaniel Grumberg 6116b89fab8SDaniel Grumberg QualType T = TSInfo ? TSInfo->getType() 61289f6b26fSZixu Wang : Param->getASTContext().getUnqualifiedObjCPointerType( 61389f6b26fSZixu Wang Param->getType()); 61489f6b26fSZixu Wang 6156b89fab8SDaniel Grumberg FunctionTypeLoc BlockLoc; 6166b89fab8SDaniel Grumberg FunctionProtoTypeLoc BlockProtoLoc; 6176b89fab8SDaniel Grumberg findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc); 6186b89fab8SDaniel Grumberg 6196b89fab8SDaniel Grumberg DeclarationFragments TypeFragments; 6206b89fab8SDaniel Grumberg if (BlockLoc) 6216b89fab8SDaniel Grumberg TypeFragments.append( 6226b89fab8SDaniel Grumberg getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After)); 6236b89fab8SDaniel Grumberg else 6246b89fab8SDaniel Grumberg TypeFragments.append(getFragmentsForType(T, Param->getASTContext(), After)); 6256b89fab8SDaniel Grumberg 62626648daeSKazu Hirata if (StringRef(TypeFragments.begin()->Spelling) 62726648daeSKazu Hirata .starts_with("type-parameter")) { 6282b6c038eSErick Velez std::string ProperArgName = Param->getOriginalType().getAsString(); 62980b787e8SErick Velez TypeFragments.begin()->Spelling.swap(ProperArgName); 63080b787e8SErick Velez } 63189f6b26fSZixu Wang 6326b89fab8SDaniel Grumberg if (Param->isObjCMethodParameter()) { 63389f6b26fSZixu Wang Fragments.append("(", DeclarationFragments::FragmentKind::Text) 63489f6b26fSZixu Wang .append(std::move(TypeFragments)) 6356b89fab8SDaniel Grumberg .append(std::move(After)) 6366b89fab8SDaniel Grumberg .append(") ", DeclarationFragments::FragmentKind::Text) 6376b89fab8SDaniel Grumberg .append(Param->getName(), 6386b89fab8SDaniel Grumberg DeclarationFragments::FragmentKind::InternalParam); 6396b89fab8SDaniel Grumberg } else { 6406b89fab8SDaniel Grumberg Fragments.append(std::move(TypeFragments)); 6416b89fab8SDaniel Grumberg if (!T->isBlockPointerType()) 6426b89fab8SDaniel Grumberg Fragments.appendSpace(); 6436b89fab8SDaniel Grumberg Fragments 64489f6b26fSZixu Wang .append(Param->getName(), 64589f6b26fSZixu Wang DeclarationFragments::FragmentKind::InternalParam) 64689f6b26fSZixu Wang .append(std::move(After)); 64789f6b26fSZixu Wang } 6486b89fab8SDaniel Grumberg return Fragments; 6496b89fab8SDaniel Grumberg } 6506b89fab8SDaniel Grumberg 6516b89fab8SDaniel Grumberg DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForBlock( 6526b89fab8SDaniel Grumberg const NamedDecl *BlockDecl, FunctionTypeLoc &Block, 6536b89fab8SDaniel Grumberg FunctionProtoTypeLoc &BlockProto, DeclarationFragments &After) { 6546b89fab8SDaniel Grumberg DeclarationFragments Fragments; 6556b89fab8SDaniel Grumberg 6566b89fab8SDaniel Grumberg DeclarationFragments RetTyAfter; 6576b89fab8SDaniel Grumberg auto ReturnValueFragment = getFragmentsForType( 6586b89fab8SDaniel Grumberg Block.getTypePtr()->getReturnType(), BlockDecl->getASTContext(), After); 6596b89fab8SDaniel Grumberg 6606b89fab8SDaniel Grumberg Fragments.append(std::move(ReturnValueFragment)) 6616b89fab8SDaniel Grumberg .append(std::move(RetTyAfter)) 6626b89fab8SDaniel Grumberg .appendSpace() 6636b89fab8SDaniel Grumberg .append("(^", DeclarationFragments::FragmentKind::Text); 6646b89fab8SDaniel Grumberg 6656b89fab8SDaniel Grumberg After.append(")", DeclarationFragments::FragmentKind::Text); 6666b89fab8SDaniel Grumberg unsigned NumParams = Block.getNumParams(); 6676b89fab8SDaniel Grumberg 6686b89fab8SDaniel Grumberg if (!BlockProto || NumParams == 0) { 6696b89fab8SDaniel Grumberg if (BlockProto && BlockProto.getTypePtr()->isVariadic()) 6706b89fab8SDaniel Grumberg After.append("(...)", DeclarationFragments::FragmentKind::Text); 6716b89fab8SDaniel Grumberg else 6726b89fab8SDaniel Grumberg After.append("()", DeclarationFragments::FragmentKind::Text); 6736b89fab8SDaniel Grumberg } else { 6746b89fab8SDaniel Grumberg After.append("(", DeclarationFragments::FragmentKind::Text); 6756b89fab8SDaniel Grumberg for (unsigned I = 0; I != NumParams; ++I) { 6766b89fab8SDaniel Grumberg if (I) 6776b89fab8SDaniel Grumberg After.append(", ", DeclarationFragments::FragmentKind::Text); 6786b89fab8SDaniel Grumberg After.append(getFragmentsForParam(Block.getParam(I))); 6796b89fab8SDaniel Grumberg if (I == NumParams - 1 && BlockProto.getTypePtr()->isVariadic()) 6806b89fab8SDaniel Grumberg After.append(", ...", DeclarationFragments::FragmentKind::Text); 6816b89fab8SDaniel Grumberg } 6826b89fab8SDaniel Grumberg After.append(")", DeclarationFragments::FragmentKind::Text); 6836b89fab8SDaniel Grumberg } 6846b89fab8SDaniel Grumberg 6856b89fab8SDaniel Grumberg return Fragments; 6866b89fab8SDaniel Grumberg } 68789f6b26fSZixu Wang 68889f6b26fSZixu Wang DeclarationFragments 68989f6b26fSZixu Wang DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) { 69089f6b26fSZixu Wang DeclarationFragments Fragments; 69189f6b26fSZixu Wang switch (Func->getStorageClass()) { 69289f6b26fSZixu Wang case SC_None: 69389f6b26fSZixu Wang case SC_PrivateExtern: 69489f6b26fSZixu Wang break; 69589f6b26fSZixu Wang case SC_Extern: 69689f6b26fSZixu Wang Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword) 69789f6b26fSZixu Wang .appendSpace(); 69889f6b26fSZixu Wang break; 69989f6b26fSZixu Wang case SC_Static: 70089f6b26fSZixu Wang Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) 70189f6b26fSZixu Wang .appendSpace(); 70289f6b26fSZixu Wang break; 70389f6b26fSZixu Wang case SC_Auto: 70489f6b26fSZixu Wang case SC_Register: 70589f6b26fSZixu Wang llvm_unreachable("invalid for functions"); 70689f6b26fSZixu Wang } 70775f55eb3SErick Velez if (Func->isConsteval()) // if consteval, it is also constexpr 70875f55eb3SErick Velez Fragments.append("consteval", DeclarationFragments::FragmentKind::Keyword) 70975f55eb3SErick Velez .appendSpace(); 71075f55eb3SErick Velez else if (Func->isConstexpr()) 71175f55eb3SErick Velez Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 71275f55eb3SErick Velez .appendSpace(); 71389f6b26fSZixu Wang 71489f6b26fSZixu Wang // FIXME: Is `after` actually needed here? 71589f6b26fSZixu Wang DeclarationFragments After; 71680b787e8SErick Velez auto ReturnValueFragment = 71780b787e8SErick Velez getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After); 71826648daeSKazu Hirata if (StringRef(ReturnValueFragment.begin()->Spelling) 71926648daeSKazu Hirata .starts_with("type-parameter")) { 7202b6c038eSErick Velez std::string ProperArgName = Func->getReturnType().getAsString(); 72180b787e8SErick Velez ReturnValueFragment.begin()->Spelling.swap(ProperArgName); 72280b787e8SErick Velez } 72380b787e8SErick Velez 72480b787e8SErick Velez Fragments.append(std::move(ReturnValueFragment)) 72589f6b26fSZixu Wang .appendSpace() 7262c13194eSDaniel Grumberg .append(Func->getNameAsString(), 7272c13194eSDaniel Grumberg DeclarationFragments::FragmentKind::Identifier); 72880b787e8SErick Velez 72980b787e8SErick Velez if (Func->getTemplateSpecializationInfo()) { 73080b787e8SErick Velez Fragments.append("<", DeclarationFragments::FragmentKind::Text); 73180b787e8SErick Velez 73280b787e8SErick Velez for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) { 73380b787e8SErick Velez if (i) 73480b787e8SErick Velez Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 73580b787e8SErick Velez Fragments.append( 73680b787e8SErick Velez getFragmentsForType(Func->getParamDecl(i)->getType(), 73780b787e8SErick Velez Func->getParamDecl(i)->getASTContext(), After)); 73880b787e8SErick Velez } 73980b787e8SErick Velez Fragments.append(">", DeclarationFragments::FragmentKind::Text); 74080b787e8SErick Velez } 74180b787e8SErick Velez Fragments.append(std::move(After)); 74289f6b26fSZixu Wang 74389f6b26fSZixu Wang Fragments.append("(", DeclarationFragments::FragmentKind::Text); 7446b89fab8SDaniel Grumberg unsigned NumParams = Func->getNumParams(); 7456b89fab8SDaniel Grumberg for (unsigned i = 0; i != NumParams; ++i) { 74689f6b26fSZixu Wang if (i) 74789f6b26fSZixu Wang Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 74889f6b26fSZixu Wang Fragments.append(getFragmentsForParam(Func->getParamDecl(i))); 74989f6b26fSZixu Wang } 7506b89fab8SDaniel Grumberg 7516b89fab8SDaniel Grumberg if (Func->isVariadic()) { 7526b89fab8SDaniel Grumberg if (NumParams > 0) 7536b89fab8SDaniel Grumberg Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 7546b89fab8SDaniel Grumberg Fragments.append("...", DeclarationFragments::FragmentKind::Text); 7556b89fab8SDaniel Grumberg } 75689f6b26fSZixu Wang Fragments.append(")", DeclarationFragments::FragmentKind::Text); 75789f6b26fSZixu Wang 75875f55eb3SErick Velez Fragments.append(DeclarationFragments::getExceptionSpecificationString( 75975f55eb3SErick Velez Func->getExceptionSpecType())); 76075f55eb3SErick Velez 761e05c1b46SDaniel Grumberg return Fragments.appendSemicolon(); 76289f6b26fSZixu Wang } 76389f6b26fSZixu Wang 76471b4c226SZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant( 76571b4c226SZixu Wang const EnumConstantDecl *EnumConstDecl) { 76671b4c226SZixu Wang DeclarationFragments Fragments; 76771b4c226SZixu Wang return Fragments.append(EnumConstDecl->getName(), 76871b4c226SZixu Wang DeclarationFragments::FragmentKind::Identifier); 76971b4c226SZixu Wang } 77071b4c226SZixu Wang 77171b4c226SZixu Wang DeclarationFragments 77271b4c226SZixu Wang DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) { 7739fc45ca0SDaniel Grumberg if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl()) 7749fc45ca0SDaniel Grumberg return getFragmentsForTypedef(TypedefNameDecl); 77571b4c226SZixu Wang 77671b4c226SZixu Wang DeclarationFragments Fragments, After; 77771b4c226SZixu Wang Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword); 77871b4c226SZixu Wang 77971b4c226SZixu Wang if (!EnumDecl->getName().empty()) 78071b4c226SZixu Wang Fragments.appendSpace().append( 78171b4c226SZixu Wang EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier); 78271b4c226SZixu Wang 78371b4c226SZixu Wang QualType IntegerType = EnumDecl->getIntegerType(); 78471b4c226SZixu Wang if (!IntegerType.isNull()) 7852bcbe40fSDaniel Grumberg Fragments.appendSpace() 7862bcbe40fSDaniel Grumberg .append(": ", DeclarationFragments::FragmentKind::Text) 78771b4c226SZixu Wang .append( 78871b4c226SZixu Wang getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After)) 78971b4c226SZixu Wang .append(std::move(After)); 79071b4c226SZixu Wang 7912bcbe40fSDaniel Grumberg if (EnumDecl->getName().empty()) 7922bcbe40fSDaniel Grumberg Fragments.appendSpace().append("{ ... }", 7932bcbe40fSDaniel Grumberg DeclarationFragments::FragmentKind::Text); 7942bcbe40fSDaniel Grumberg 795e05c1b46SDaniel Grumberg return Fragments.appendSemicolon(); 79671b4c226SZixu Wang } 79771b4c226SZixu Wang 7985bb5704cSZixu Wang DeclarationFragments 7995bb5704cSZixu Wang DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) { 8005bb5704cSZixu Wang DeclarationFragments After; 80175f55eb3SErick Velez DeclarationFragments Fragments; 80275f55eb3SErick Velez if (Field->isMutable()) 80375f55eb3SErick Velez Fragments.append("mutable", DeclarationFragments::FragmentKind::Keyword) 80475f55eb3SErick Velez .appendSpace(); 80575f55eb3SErick Velez return Fragments 80675f55eb3SErick Velez .append( 80775f55eb3SErick Velez getFragmentsForType(Field->getType(), Field->getASTContext(), After)) 8085bb5704cSZixu Wang .appendSpace() 8095bb5704cSZixu Wang .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier) 810422bcd10SErick Velez .append(std::move(After)) 811e05c1b46SDaniel Grumberg .appendSemicolon(); 8125bb5704cSZixu Wang } 8135bb5704cSZixu Wang 81469fedaf8SDaniel Grumberg DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl( 81569fedaf8SDaniel Grumberg const RecordDecl *Record) { 8169fc45ca0SDaniel Grumberg if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl()) 8179fc45ca0SDaniel Grumberg return getFragmentsForTypedef(TypedefNameDecl); 8185bb5704cSZixu Wang 8195bb5704cSZixu Wang DeclarationFragments Fragments; 82069fedaf8SDaniel Grumberg if (Record->isUnion()) 82169fedaf8SDaniel Grumberg Fragments.append("union", DeclarationFragments::FragmentKind::Keyword); 82269fedaf8SDaniel Grumberg else 8235bb5704cSZixu Wang Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword); 8245bb5704cSZixu Wang 8252bcbe40fSDaniel Grumberg Fragments.appendSpace(); 8265bb5704cSZixu Wang if (!Record->getName().empty()) 8272bcbe40fSDaniel Grumberg Fragments.append(Record->getName(), 8282bcbe40fSDaniel Grumberg DeclarationFragments::FragmentKind::Identifier); 8292bcbe40fSDaniel Grumberg else 8302bcbe40fSDaniel Grumberg Fragments.append("{ ... }", DeclarationFragments::FragmentKind::Text); 831afce10c5SNagaChaitanya Vellanki 832e05c1b46SDaniel Grumberg return Fragments.appendSemicolon(); 833529a0570SDaniel Grumberg } 8345bb5704cSZixu Wang 83575f55eb3SErick Velez DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass( 83675f55eb3SErick Velez const CXXRecordDecl *Record) { 83775f55eb3SErick Velez if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl()) 83875f55eb3SErick Velez return getFragmentsForTypedef(TypedefNameDecl); 83975f55eb3SErick Velez 84075f55eb3SErick Velez DeclarationFragments Fragments; 84175f55eb3SErick Velez Fragments.append(DeclarationFragments::getStructureTypeFragment(Record)); 84275f55eb3SErick Velez 84375f55eb3SErick Velez if (!Record->getName().empty()) 84475f55eb3SErick Velez Fragments.appendSpace().append( 84575f55eb3SErick Velez Record->getName(), DeclarationFragments::FragmentKind::Identifier); 84675f55eb3SErick Velez 847e05c1b46SDaniel Grumberg return Fragments.appendSemicolon(); 84875f55eb3SErick Velez } 84975f55eb3SErick Velez 85075f55eb3SErick Velez DeclarationFragments 85175f55eb3SErick Velez DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod( 85275f55eb3SErick Velez const CXXMethodDecl *Method) { 85375f55eb3SErick Velez DeclarationFragments Fragments; 85475f55eb3SErick Velez std::string Name; 855847186ebSElizabeth Andrews if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(Method)) { 85675f55eb3SErick Velez Name = Method->getNameAsString(); 857847186ebSElizabeth Andrews if (Constructor->isExplicit()) 85875f55eb3SErick Velez Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword) 85975f55eb3SErick Velez .appendSpace(); 86075f55eb3SErick Velez } else if (isa<CXXDestructorDecl>(Method)) 86175f55eb3SErick Velez Name = Method->getNameAsString(); 86275f55eb3SErick Velez 86375f55eb3SErick Velez DeclarationFragments After; 86475f55eb3SErick Velez Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier) 86575f55eb3SErick Velez .append(std::move(After)); 86675f55eb3SErick Velez Fragments.append("(", DeclarationFragments::FragmentKind::Text); 86775f55eb3SErick Velez for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) { 86875f55eb3SErick Velez if (i) 86975f55eb3SErick Velez Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 87075f55eb3SErick Velez Fragments.append(getFragmentsForParam(Method->getParamDecl(i))); 87175f55eb3SErick Velez } 87275f55eb3SErick Velez Fragments.append(")", DeclarationFragments::FragmentKind::Text); 87375f55eb3SErick Velez 87475f55eb3SErick Velez Fragments.append(DeclarationFragments::getExceptionSpecificationString( 87575f55eb3SErick Velez Method->getExceptionSpecType())); 87675f55eb3SErick Velez 877e05c1b46SDaniel Grumberg return Fragments.appendSemicolon(); 87875f55eb3SErick Velez } 87975f55eb3SErick Velez 88075f55eb3SErick Velez DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod( 88175f55eb3SErick Velez const CXXMethodDecl *Method) { 88275f55eb3SErick Velez DeclarationFragments Fragments; 88375f55eb3SErick Velez StringRef Name = Method->getName(); 88475f55eb3SErick Velez if (Method->isStatic()) 88575f55eb3SErick Velez Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) 88675f55eb3SErick Velez .appendSpace(); 88775f55eb3SErick Velez if (Method->isConstexpr()) 88875f55eb3SErick Velez Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) 88975f55eb3SErick Velez .appendSpace(); 89075f55eb3SErick Velez if (Method->isVolatile()) 89175f55eb3SErick Velez Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword) 89275f55eb3SErick Velez .appendSpace(); 89375f55eb3SErick Velez 89475f55eb3SErick Velez // Build return type 89575f55eb3SErick Velez DeclarationFragments After; 89675f55eb3SErick Velez Fragments 89775f55eb3SErick Velez .append(getFragmentsForType(Method->getReturnType(), 89875f55eb3SErick Velez Method->getASTContext(), After)) 89975f55eb3SErick Velez .appendSpace() 90075f55eb3SErick Velez .append(Name, DeclarationFragments::FragmentKind::Identifier) 90175f55eb3SErick Velez .append(std::move(After)); 90275f55eb3SErick Velez Fragments.append("(", DeclarationFragments::FragmentKind::Text); 90375f55eb3SErick Velez for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) { 90475f55eb3SErick Velez if (i) 90575f55eb3SErick Velez Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 90675f55eb3SErick Velez Fragments.append(getFragmentsForParam(Method->getParamDecl(i))); 90775f55eb3SErick Velez } 90875f55eb3SErick Velez Fragments.append(")", DeclarationFragments::FragmentKind::Text); 90975f55eb3SErick Velez 91075f55eb3SErick Velez if (Method->isConst()) 91175f55eb3SErick Velez Fragments.appendSpace().append("const", 91275f55eb3SErick Velez DeclarationFragments::FragmentKind::Keyword); 91375f55eb3SErick Velez 91475f55eb3SErick Velez Fragments.append(DeclarationFragments::getExceptionSpecificationString( 91575f55eb3SErick Velez Method->getExceptionSpecType())); 91675f55eb3SErick Velez 917e05c1b46SDaniel Grumberg return Fragments.appendSemicolon(); 91875f55eb3SErick Velez } 91975f55eb3SErick Velez 92075f55eb3SErick Velez DeclarationFragments 92175f55eb3SErick Velez DeclarationFragmentsBuilder::getFragmentsForConversionFunction( 92275f55eb3SErick Velez const CXXConversionDecl *ConversionFunction) { 92375f55eb3SErick Velez DeclarationFragments Fragments; 92475f55eb3SErick Velez 92575f55eb3SErick Velez if (ConversionFunction->isExplicit()) 92675f55eb3SErick Velez Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword) 92775f55eb3SErick Velez .appendSpace(); 92875f55eb3SErick Velez 92975f55eb3SErick Velez Fragments.append("operator", DeclarationFragments::FragmentKind::Keyword) 93075f55eb3SErick Velez .appendSpace(); 93175f55eb3SErick Velez 93275f55eb3SErick Velez Fragments 93375f55eb3SErick Velez .append(ConversionFunction->getConversionType().getAsString(), 93475f55eb3SErick Velez DeclarationFragments::FragmentKind::TypeIdentifier) 93575f55eb3SErick Velez .append("(", DeclarationFragments::FragmentKind::Text); 93675f55eb3SErick Velez for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end; 93775f55eb3SErick Velez ++i) { 93875f55eb3SErick Velez if (i) 93975f55eb3SErick Velez Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 94075f55eb3SErick Velez Fragments.append(getFragmentsForParam(ConversionFunction->getParamDecl(i))); 94175f55eb3SErick Velez } 94275f55eb3SErick Velez Fragments.append(")", DeclarationFragments::FragmentKind::Text); 94375f55eb3SErick Velez 94475f55eb3SErick Velez if (ConversionFunction->isConst()) 94575f55eb3SErick Velez Fragments.appendSpace().append("const", 94675f55eb3SErick Velez DeclarationFragments::FragmentKind::Keyword); 94775f55eb3SErick Velez 948e05c1b46SDaniel Grumberg return Fragments.appendSemicolon(); 94975f55eb3SErick Velez } 95075f55eb3SErick Velez 95175f55eb3SErick Velez DeclarationFragments 95275f55eb3SErick Velez DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator( 95375f55eb3SErick Velez const CXXMethodDecl *Method) { 95475f55eb3SErick Velez DeclarationFragments Fragments; 95575f55eb3SErick Velez 95675f55eb3SErick Velez // Build return type 95775f55eb3SErick Velez DeclarationFragments After; 95875f55eb3SErick Velez Fragments 95975f55eb3SErick Velez .append(getFragmentsForType(Method->getReturnType(), 96075f55eb3SErick Velez Method->getASTContext(), After)) 96175f55eb3SErick Velez .appendSpace() 96275f55eb3SErick Velez .append(Method->getNameAsString(), 96375f55eb3SErick Velez DeclarationFragments::FragmentKind::Identifier) 96475f55eb3SErick Velez .append(std::move(After)); 96575f55eb3SErick Velez Fragments.append("(", DeclarationFragments::FragmentKind::Text); 96675f55eb3SErick Velez for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) { 96775f55eb3SErick Velez if (i) 96875f55eb3SErick Velez Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 96975f55eb3SErick Velez Fragments.append(getFragmentsForParam(Method->getParamDecl(i))); 97075f55eb3SErick Velez } 97175f55eb3SErick Velez Fragments.append(")", DeclarationFragments::FragmentKind::Text); 97275f55eb3SErick Velez 97375f55eb3SErick Velez if (Method->isConst()) 97475f55eb3SErick Velez Fragments.appendSpace().append("const", 97575f55eb3SErick Velez DeclarationFragments::FragmentKind::Keyword); 97675f55eb3SErick Velez 97775f55eb3SErick Velez Fragments.append(DeclarationFragments::getExceptionSpecificationString( 97875f55eb3SErick Velez Method->getExceptionSpecType())); 97975f55eb3SErick Velez 980e05c1b46SDaniel Grumberg return Fragments.appendSemicolon(); 98175f55eb3SErick Velez } 98275f55eb3SErick Velez 9837ba37f4eSErick Velez // Get fragments for template parameters, e.g. T in tempalte<typename T> ... 9847ba37f4eSErick Velez DeclarationFragments 9857ba37f4eSErick Velez DeclarationFragmentsBuilder::getFragmentsForTemplateParameters( 9867ba37f4eSErick Velez ArrayRef<NamedDecl *> ParameterArray) { 9877ba37f4eSErick Velez DeclarationFragments Fragments; 9887ba37f4eSErick Velez for (unsigned i = 0, end = ParameterArray.size(); i != end; ++i) { 9897ba37f4eSErick Velez if (i) 9907ba37f4eSErick Velez Fragments.append(",", DeclarationFragments::FragmentKind::Text) 9917ba37f4eSErick Velez .appendSpace(); 9927ba37f4eSErick Velez 9937a674793SDaniel Grumberg if (const auto *TemplateParam = 9947a674793SDaniel Grumberg dyn_cast<TemplateTypeParmDecl>(ParameterArray[i])) { 9957ba37f4eSErick Velez if (TemplateParam->hasTypeConstraint()) 9967ba37f4eSErick Velez Fragments.append(TemplateParam->getTypeConstraint() 9977ba37f4eSErick Velez ->getNamedConcept() 9987ba37f4eSErick Velez ->getName() 9997ba37f4eSErick Velez .str(), 10007ba37f4eSErick Velez DeclarationFragments::FragmentKind::TypeIdentifier); 10017ba37f4eSErick Velez else if (TemplateParam->wasDeclaredWithTypename()) 10027a674793SDaniel Grumberg Fragments.append("typename", 10037a674793SDaniel Grumberg DeclarationFragments::FragmentKind::Keyword); 10047ba37f4eSErick Velez else 10057ba37f4eSErick Velez Fragments.append("class", DeclarationFragments::FragmentKind::Keyword); 10067ba37f4eSErick Velez 10077ba37f4eSErick Velez if (TemplateParam->isParameterPack()) 10087ba37f4eSErick Velez Fragments.append("...", DeclarationFragments::FragmentKind::Text); 10097ba37f4eSErick Velez 10107a674793SDaniel Grumberg if (!TemplateParam->getName().empty()) 10117ba37f4eSErick Velez Fragments.appendSpace().append( 10127ba37f4eSErick Velez TemplateParam->getName(), 10137ba37f4eSErick Velez DeclarationFragments::FragmentKind::GenericParameter); 10147a674793SDaniel Grumberg 10157a674793SDaniel Grumberg if (TemplateParam->hasDefaultArgument()) { 1016e42b799bSMatheus Izvekov const auto Default = TemplateParam->getDefaultArgument(); 10177a674793SDaniel Grumberg Fragments.append(" = ", DeclarationFragments::FragmentKind::Text) 1018e42b799bSMatheus Izvekov .append(getFragmentsForTemplateArguments( 1019e42b799bSMatheus Izvekov {Default.getArgument()}, TemplateParam->getASTContext(), 1020e42b799bSMatheus Izvekov {Default})); 10217a674793SDaniel Grumberg } 10227a674793SDaniel Grumberg } else if (const auto *NTP = 10237a674793SDaniel Grumberg dyn_cast<NonTypeTemplateParmDecl>(ParameterArray[i])) { 10247a674793SDaniel Grumberg DeclarationFragments After; 10257a674793SDaniel Grumberg const auto TyFragments = 10267a674793SDaniel Grumberg getFragmentsForType(NTP->getType(), NTP->getASTContext(), After); 10277a674793SDaniel Grumberg Fragments.append(std::move(TyFragments)).append(std::move(After)); 10287a674793SDaniel Grumberg 10297a674793SDaniel Grumberg if (NTP->isParameterPack()) 10307a674793SDaniel Grumberg Fragments.append("...", DeclarationFragments::FragmentKind::Text); 10317a674793SDaniel Grumberg 10327a674793SDaniel Grumberg if (!NTP->getName().empty()) 10337a674793SDaniel Grumberg Fragments.appendSpace().append( 10347a674793SDaniel Grumberg NTP->getName(), 10357a674793SDaniel Grumberg DeclarationFragments::FragmentKind::GenericParameter); 10367a674793SDaniel Grumberg 10377a674793SDaniel Grumberg if (NTP->hasDefaultArgument()) { 10387a674793SDaniel Grumberg SmallString<8> ExprStr; 10397a674793SDaniel Grumberg raw_svector_ostream Output(ExprStr); 10402bde13cdSMatheus Izvekov NTP->getDefaultArgument().getArgument().print( 10412bde13cdSMatheus Izvekov NTP->getASTContext().getPrintingPolicy(), Output, 10422bde13cdSMatheus Izvekov /*IncludeType=*/false); 10437a674793SDaniel Grumberg Fragments.append(" = ", DeclarationFragments::FragmentKind::Text) 10447a674793SDaniel Grumberg .append(ExprStr, DeclarationFragments::FragmentKind::Text); 10457a674793SDaniel Grumberg } 10467a674793SDaniel Grumberg } else if (const auto *TTP = 10477a674793SDaniel Grumberg dyn_cast<TemplateTemplateParmDecl>(ParameterArray[i])) { 10487a674793SDaniel Grumberg Fragments.append("template", DeclarationFragments::FragmentKind::Keyword) 10497a674793SDaniel Grumberg .appendSpace() 10507a674793SDaniel Grumberg .append("<", DeclarationFragments::FragmentKind::Text) 10517a674793SDaniel Grumberg .append(getFragmentsForTemplateParameters( 10527a674793SDaniel Grumberg TTP->getTemplateParameters()->asArray())) 10537a674793SDaniel Grumberg .append(">", DeclarationFragments::FragmentKind::Text) 10547a674793SDaniel Grumberg .appendSpace() 10557a674793SDaniel Grumberg .append(TTP->wasDeclaredWithTypename() ? "typename" : "class", 10567a674793SDaniel Grumberg DeclarationFragments::FragmentKind::Keyword); 10577a674793SDaniel Grumberg 10587a674793SDaniel Grumberg if (TTP->isParameterPack()) 10597a674793SDaniel Grumberg Fragments.append("...", DeclarationFragments::FragmentKind::Text); 10607a674793SDaniel Grumberg 10617a674793SDaniel Grumberg if (!TTP->getName().empty()) 10627a674793SDaniel Grumberg Fragments.appendSpace().append( 10637a674793SDaniel Grumberg TTP->getName(), 10647a674793SDaniel Grumberg DeclarationFragments::FragmentKind::GenericParameter); 10657a674793SDaniel Grumberg if (TTP->hasDefaultArgument()) { 10667a674793SDaniel Grumberg const auto Default = TTP->getDefaultArgument(); 10677a674793SDaniel Grumberg Fragments.append(" = ", DeclarationFragments::FragmentKind::Text) 10687a674793SDaniel Grumberg .append(getFragmentsForTemplateArguments( 10697a674793SDaniel Grumberg {Default.getArgument()}, TTP->getASTContext(), {Default})); 10707a674793SDaniel Grumberg } 10717a674793SDaniel Grumberg } 10727ba37f4eSErick Velez } 10737ba37f4eSErick Velez return Fragments; 10747ba37f4eSErick Velez } 10757ba37f4eSErick Velez 10767ba37f4eSErick Velez // Get fragments for template arguments, e.g. int in template<typename T> 10777ba37f4eSErick Velez // Foo<int>; 10787ba37f4eSErick Velez // 10797ba37f4eSErick Velez // Note: TemplateParameters is only necessary if the Decl is a 10807ba37f4eSErick Velez // PartialSpecialization, where we need the parameters to deduce the name of the 10817ba37f4eSErick Velez // generic arguments. 10827ba37f4eSErick Velez DeclarationFragments 10837ba37f4eSErick Velez DeclarationFragmentsBuilder::getFragmentsForTemplateArguments( 10847ba37f4eSErick Velez const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context, 10852b6c038eSErick Velez const std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs) { 10867ba37f4eSErick Velez DeclarationFragments Fragments; 10877ba37f4eSErick Velez for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) { 10887ba37f4eSErick Velez if (i) 10897ba37f4eSErick Velez Fragments.append(",", DeclarationFragments::FragmentKind::Text) 10907ba37f4eSErick Velez .appendSpace(); 10917ba37f4eSErick Velez 10927a674793SDaniel Grumberg const auto &CTA = TemplateArguments[i]; 10937a674793SDaniel Grumberg switch (CTA.getKind()) { 10947a674793SDaniel Grumberg case TemplateArgument::Type: { 10957ba37f4eSErick Velez DeclarationFragments After; 10967ba37f4eSErick Velez DeclarationFragments ArgumentFragment = 10977a674793SDaniel Grumberg getFragmentsForType(CTA.getAsType(), Context, After); 10987ba37f4eSErick Velez 109926648daeSKazu Hirata if (StringRef(ArgumentFragment.begin()->Spelling) 110026648daeSKazu Hirata .starts_with("type-parameter")) { 1101ab7e6b66SDaniel Grumberg if (TemplateArgumentLocs.has_value() && 1102ab7e6b66SDaniel Grumberg TemplateArgumentLocs->size() > i) { 11032b6c038eSErick Velez std::string ProperArgName = TemplateArgumentLocs.value()[i] 11042b6c038eSErick Velez .getTypeSourceInfo() 11052b6c038eSErick Velez ->getType() 11062b6c038eSErick Velez .getAsString(); 11077ba37f4eSErick Velez ArgumentFragment.begin()->Spelling.swap(ProperArgName); 1108ab7e6b66SDaniel Grumberg } else { 1109ab7e6b66SDaniel Grumberg auto &Spelling = ArgumentFragment.begin()->Spelling; 1110ab7e6b66SDaniel Grumberg Spelling.clear(); 1111ab7e6b66SDaniel Grumberg raw_string_ostream OutStream(Spelling); 1112ab7e6b66SDaniel Grumberg CTA.print(Context.getPrintingPolicy(), OutStream, false); 11137ba37f4eSErick Velez } 1114ab7e6b66SDaniel Grumberg } 1115ab7e6b66SDaniel Grumberg 11167ba37f4eSErick Velez Fragments.append(std::move(ArgumentFragment)); 11177a674793SDaniel Grumberg break; 11187a674793SDaniel Grumberg } 11197a674793SDaniel Grumberg case TemplateArgument::Declaration: { 11207a674793SDaniel Grumberg const auto *VD = CTA.getAsDecl(); 11217a674793SDaniel Grumberg SmallString<128> USR; 11227a674793SDaniel Grumberg index::generateUSRForDecl(VD, USR); 11237a674793SDaniel Grumberg Fragments.append(VD->getNameAsString(), 11247a674793SDaniel Grumberg DeclarationFragments::FragmentKind::Identifier, USR); 11257a674793SDaniel Grumberg break; 11267a674793SDaniel Grumberg } 11277a674793SDaniel Grumberg case TemplateArgument::NullPtr: 11287a674793SDaniel Grumberg Fragments.append("nullptr", DeclarationFragments::FragmentKind::Keyword); 11297a674793SDaniel Grumberg break; 11307ba37f4eSErick Velez 11317a674793SDaniel Grumberg case TemplateArgument::Integral: { 11327a674793SDaniel Grumberg SmallString<4> Str; 11337a674793SDaniel Grumberg CTA.getAsIntegral().toString(Str); 11347a674793SDaniel Grumberg Fragments.append(Str, DeclarationFragments::FragmentKind::Text); 11357a674793SDaniel Grumberg break; 11367a674793SDaniel Grumberg } 11377a674793SDaniel Grumberg 11387a674793SDaniel Grumberg case TemplateArgument::StructuralValue: { 11397a674793SDaniel Grumberg const auto SVTy = CTA.getStructuralValueType(); 11407a674793SDaniel Grumberg Fragments.append(CTA.getAsStructuralValue().getAsString(Context, SVTy), 11417a674793SDaniel Grumberg DeclarationFragments::FragmentKind::Text); 11427a674793SDaniel Grumberg break; 11437a674793SDaniel Grumberg } 11447a674793SDaniel Grumberg 11457a674793SDaniel Grumberg case TemplateArgument::TemplateExpansion: 11467a674793SDaniel Grumberg case TemplateArgument::Template: { 11477a674793SDaniel Grumberg std::string Str; 11487a674793SDaniel Grumberg raw_string_ostream Stream(Str); 11497a674793SDaniel Grumberg CTA.getAsTemplate().print(Stream, Context.getPrintingPolicy()); 11507a674793SDaniel Grumberg SmallString<64> USR(""); 11517a674793SDaniel Grumberg if (const auto *TemplDecl = 11527a674793SDaniel Grumberg CTA.getAsTemplateOrTemplatePattern().getAsTemplateDecl()) 11537a674793SDaniel Grumberg index::generateUSRForDecl(TemplDecl, USR); 11547a674793SDaniel Grumberg Fragments.append(Str, DeclarationFragments::FragmentKind::TypeIdentifier, 11557a674793SDaniel Grumberg USR); 11567a674793SDaniel Grumberg if (CTA.getKind() == TemplateArgument::TemplateExpansion) 11577ba37f4eSErick Velez Fragments.append("...", DeclarationFragments::FragmentKind::Text); 11587a674793SDaniel Grumberg break; 11597a674793SDaniel Grumberg } 11607a674793SDaniel Grumberg 11617a674793SDaniel Grumberg case TemplateArgument::Pack: 11627a674793SDaniel Grumberg Fragments.append("<", DeclarationFragments::FragmentKind::Text) 11637a674793SDaniel Grumberg .append(getFragmentsForTemplateArguments(CTA.pack_elements(), Context, 11647a674793SDaniel Grumberg {})) 11657a674793SDaniel Grumberg .append(">", DeclarationFragments::FragmentKind::Text); 11667a674793SDaniel Grumberg break; 11677a674793SDaniel Grumberg 11687a674793SDaniel Grumberg case TemplateArgument::Expression: { 11697a674793SDaniel Grumberg SmallString<8> ExprStr; 11707a674793SDaniel Grumberg raw_svector_ostream Output(ExprStr); 11717a674793SDaniel Grumberg CTA.getAsExpr()->printPretty(Output, nullptr, 11727a674793SDaniel Grumberg Context.getPrintingPolicy()); 11737a674793SDaniel Grumberg Fragments.append(ExprStr, DeclarationFragments::FragmentKind::Text); 11747a674793SDaniel Grumberg break; 11757a674793SDaniel Grumberg } 11767a674793SDaniel Grumberg 11777a674793SDaniel Grumberg case TemplateArgument::Null: 11787a674793SDaniel Grumberg break; 11797a674793SDaniel Grumberg } 11807ba37f4eSErick Velez } 11817ba37f4eSErick Velez return Fragments; 11827ba37f4eSErick Velez } 11837ba37f4eSErick Velez 11847ba37f4eSErick Velez DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept( 11857ba37f4eSErick Velez const ConceptDecl *Concept) { 11867ba37f4eSErick Velez DeclarationFragments Fragments; 11877ba37f4eSErick Velez return Fragments 11887ba37f4eSErick Velez .append("template", DeclarationFragments::FragmentKind::Keyword) 11897a674793SDaniel Grumberg .appendSpace() 11907ba37f4eSErick Velez .append("<", DeclarationFragments::FragmentKind::Text) 11917ba37f4eSErick Velez .append(getFragmentsForTemplateParameters( 11927ba37f4eSErick Velez Concept->getTemplateParameters()->asArray())) 11937ba37f4eSErick Velez .append("> ", DeclarationFragments::FragmentKind::Text) 11947a674793SDaniel Grumberg .appendSpace() 11957ba37f4eSErick Velez .append("concept", DeclarationFragments::FragmentKind::Keyword) 11967ba37f4eSErick Velez .appendSpace() 11977ba37f4eSErick Velez .append(Concept->getName().str(), 11987ba37f4eSErick Velez DeclarationFragments::FragmentKind::Identifier) 1199e05c1b46SDaniel Grumberg .appendSemicolon(); 12007ba37f4eSErick Velez } 12017ba37f4eSErick Velez 12027ba37f4eSErick Velez DeclarationFragments 12037ba37f4eSErick Velez DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate( 12047ba37f4eSErick Velez const RedeclarableTemplateDecl *RedeclarableTemplate) { 12057ba37f4eSErick Velez DeclarationFragments Fragments; 12067ba37f4eSErick Velez Fragments.append("template", DeclarationFragments::FragmentKind::Keyword) 12077a674793SDaniel Grumberg .appendSpace() 12087ba37f4eSErick Velez .append("<", DeclarationFragments::FragmentKind::Text) 12097ba37f4eSErick Velez .append(getFragmentsForTemplateParameters( 12107ba37f4eSErick Velez RedeclarableTemplate->getTemplateParameters()->asArray())) 12117ba37f4eSErick Velez .append(">", DeclarationFragments::FragmentKind::Text) 12127ba37f4eSErick Velez .appendSpace(); 12137ba37f4eSErick Velez 12147ba37f4eSErick Velez if (isa<TypeAliasTemplateDecl>(RedeclarableTemplate)) 12157ba37f4eSErick Velez Fragments.appendSpace() 12167ba37f4eSErick Velez .append("using", DeclarationFragments::FragmentKind::Keyword) 12177ba37f4eSErick Velez .appendSpace() 12187ba37f4eSErick Velez .append(RedeclarableTemplate->getName(), 12197ba37f4eSErick Velez DeclarationFragments::FragmentKind::Identifier); 12207ba37f4eSErick Velez // the templated records will be resposbible for injecting their templates 12217ba37f4eSErick Velez return Fragments.appendSpace(); 12227ba37f4eSErick Velez } 12237ba37f4eSErick Velez 12247ba37f4eSErick Velez DeclarationFragments 12257ba37f4eSErick Velez DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization( 12267ba37f4eSErick Velez const ClassTemplateSpecializationDecl *Decl) { 12277ba37f4eSErick Velez DeclarationFragments Fragments; 12287ba37f4eSErick Velez return Fragments 12297ba37f4eSErick Velez .append("template", DeclarationFragments::FragmentKind::Keyword) 12307a674793SDaniel Grumberg .appendSpace() 12317ba37f4eSErick Velez .append("<", DeclarationFragments::FragmentKind::Text) 12327ba37f4eSErick Velez .append(">", DeclarationFragments::FragmentKind::Text) 12337ba37f4eSErick Velez .appendSpace() 12347ba37f4eSErick Velez .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass( 12357ba37f4eSErick Velez cast<CXXRecordDecl>(Decl))) 12367ba37f4eSErick Velez .pop_back() // there is an extra semicolon now 12377ba37f4eSErick Velez .append("<", DeclarationFragments::FragmentKind::Text) 1238ab7e6b66SDaniel Grumberg .append(getFragmentsForTemplateArguments( 1239ab7e6b66SDaniel Grumberg Decl->getTemplateArgs().asArray(), Decl->getASTContext(), 1240ab7e6b66SDaniel Grumberg Decl->getTemplateArgsAsWritten()->arguments())) 12417ba37f4eSErick Velez .append(">", DeclarationFragments::FragmentKind::Text) 1242e05c1b46SDaniel Grumberg .appendSemicolon(); 12437ba37f4eSErick Velez } 12447ba37f4eSErick Velez 12457ba37f4eSErick Velez DeclarationFragments 12467ba37f4eSErick Velez DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization( 12477ba37f4eSErick Velez const ClassTemplatePartialSpecializationDecl *Decl) { 12487ba37f4eSErick Velez DeclarationFragments Fragments; 12497ba37f4eSErick Velez return Fragments 12507ba37f4eSErick Velez .append("template", DeclarationFragments::FragmentKind::Keyword) 12517a674793SDaniel Grumberg .appendSpace() 12527ba37f4eSErick Velez .append("<", DeclarationFragments::FragmentKind::Text) 12537ba37f4eSErick Velez .append(getFragmentsForTemplateParameters( 12547ba37f4eSErick Velez Decl->getTemplateParameters()->asArray())) 12557ba37f4eSErick Velez .append(">", DeclarationFragments::FragmentKind::Text) 12567ba37f4eSErick Velez .appendSpace() 12577ba37f4eSErick Velez .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass( 12587ba37f4eSErick Velez cast<CXXRecordDecl>(Decl))) 12597ba37f4eSErick Velez .pop_back() // there is an extra semicolon now 12607ba37f4eSErick Velez .append("<", DeclarationFragments::FragmentKind::Text) 12617ba37f4eSErick Velez .append(getFragmentsForTemplateArguments( 12627ba37f4eSErick Velez Decl->getTemplateArgs().asArray(), Decl->getASTContext(), 12632b6c038eSErick Velez Decl->getTemplateArgsAsWritten()->arguments())) 12647ba37f4eSErick Velez .append(">", DeclarationFragments::FragmentKind::Text) 1265e05c1b46SDaniel Grumberg .appendSemicolon(); 12667ba37f4eSErick Velez } 12677ba37f4eSErick Velez 1268529a0570SDaniel Grumberg DeclarationFragments 12698d8c8981SErick Velez DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization( 12708d8c8981SErick Velez const VarTemplateSpecializationDecl *Decl) { 12718d8c8981SErick Velez DeclarationFragments Fragments; 12728d8c8981SErick Velez return Fragments 12738d8c8981SErick Velez .append("template", DeclarationFragments::FragmentKind::Keyword) 12747a674793SDaniel Grumberg .appendSpace() 12758d8c8981SErick Velez .append("<", DeclarationFragments::FragmentKind::Text) 12768d8c8981SErick Velez .append(">", DeclarationFragments::FragmentKind::Text) 12778d8c8981SErick Velez .appendSpace() 12788d8c8981SErick Velez .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl)) 12798d8c8981SErick Velez .pop_back() // there is an extra semicolon now 12808d8c8981SErick Velez .append("<", DeclarationFragments::FragmentKind::Text) 1281ab7e6b66SDaniel Grumberg .append(getFragmentsForTemplateArguments( 1282ab7e6b66SDaniel Grumberg Decl->getTemplateArgs().asArray(), Decl->getASTContext(), 1283ab7e6b66SDaniel Grumberg Decl->getTemplateArgsAsWritten()->arguments())) 12848d8c8981SErick Velez .append(">", DeclarationFragments::FragmentKind::Text) 1285e05c1b46SDaniel Grumberg .appendSemicolon(); 12868d8c8981SErick Velez } 12878d8c8981SErick Velez 12888d8c8981SErick Velez DeclarationFragments 12898d8c8981SErick Velez DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization( 12908d8c8981SErick Velez const VarTemplatePartialSpecializationDecl *Decl) { 12918d8c8981SErick Velez DeclarationFragments Fragments; 12928d8c8981SErick Velez return Fragments 12938d8c8981SErick Velez .append("template", DeclarationFragments::FragmentKind::Keyword) 12947a674793SDaniel Grumberg .appendSpace() 12958d8c8981SErick Velez .append("<", DeclarationFragments::FragmentKind::Text) 12968d8c8981SErick Velez // Partial specs may have new params. 12978d8c8981SErick Velez .append(getFragmentsForTemplateParameters( 12988d8c8981SErick Velez Decl->getTemplateParameters()->asArray())) 12998d8c8981SErick Velez .append(">", DeclarationFragments::FragmentKind::Text) 13008d8c8981SErick Velez .appendSpace() 13018d8c8981SErick Velez .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl)) 13028d8c8981SErick Velez .pop_back() // there is an extra semicolon now 13038d8c8981SErick Velez .append("<", DeclarationFragments::FragmentKind::Text) 13048d8c8981SErick Velez .append(getFragmentsForTemplateArguments( 13058d8c8981SErick Velez Decl->getTemplateArgs().asArray(), Decl->getASTContext(), 13062b6c038eSErick Velez Decl->getTemplateArgsAsWritten()->arguments())) 13078d8c8981SErick Velez .append(">", DeclarationFragments::FragmentKind::Text) 1308e05c1b46SDaniel Grumberg .appendSemicolon(); 13098d8c8981SErick Velez } 13108d8c8981SErick Velez 13118d8c8981SErick Velez DeclarationFragments 131280b787e8SErick Velez DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate( 131380b787e8SErick Velez const FunctionTemplateDecl *Decl) { 131480b787e8SErick Velez DeclarationFragments Fragments; 131580b787e8SErick Velez return Fragments 131680b787e8SErick Velez .append("template", DeclarationFragments::FragmentKind::Keyword) 13177a674793SDaniel Grumberg .appendSpace() 131880b787e8SErick Velez .append("<", DeclarationFragments::FragmentKind::Text) 131980b787e8SErick Velez // Partial specs may have new params. 132080b787e8SErick Velez .append(getFragmentsForTemplateParameters( 132180b787e8SErick Velez Decl->getTemplateParameters()->asArray())) 132280b787e8SErick Velez .append(">", DeclarationFragments::FragmentKind::Text) 132380b787e8SErick Velez .appendSpace() 132480b787e8SErick Velez .append(DeclarationFragmentsBuilder::getFragmentsForFunction( 132580b787e8SErick Velez Decl->getAsFunction())); 132680b787e8SErick Velez } 132780b787e8SErick Velez 132880b787e8SErick Velez DeclarationFragments 132980b787e8SErick Velez DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization( 133080b787e8SErick Velez const FunctionDecl *Decl) { 133180b787e8SErick Velez DeclarationFragments Fragments; 133280b787e8SErick Velez return Fragments 133380b787e8SErick Velez .append("template", DeclarationFragments::FragmentKind::Keyword) 13347a674793SDaniel Grumberg .appendSpace() 133580b787e8SErick Velez .append("<>", DeclarationFragments::FragmentKind::Text) 133680b787e8SErick Velez .appendSpace() 133780b787e8SErick Velez .append(DeclarationFragmentsBuilder::getFragmentsForFunction(Decl)); 133880b787e8SErick Velez } 133980b787e8SErick Velez 134080b787e8SErick Velez DeclarationFragments 1341529a0570SDaniel Grumberg DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name, 1342b1b24d75SDaniel Grumberg const MacroInfo *MI) { 1343529a0570SDaniel Grumberg DeclarationFragments Fragments; 1344529a0570SDaniel Grumberg Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword) 1345529a0570SDaniel Grumberg .appendSpace(); 1346529a0570SDaniel Grumberg Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); 1347529a0570SDaniel Grumberg 1348529a0570SDaniel Grumberg if (MI->isFunctionLike()) { 1349529a0570SDaniel Grumberg Fragments.append("(", DeclarationFragments::FragmentKind::Text); 1350529a0570SDaniel Grumberg unsigned numParameters = MI->getNumParams(); 1351529a0570SDaniel Grumberg if (MI->isC99Varargs()) 1352529a0570SDaniel Grumberg --numParameters; 1353529a0570SDaniel Grumberg for (unsigned i = 0; i < numParameters; ++i) { 1354529a0570SDaniel Grumberg if (i) 1355529a0570SDaniel Grumberg Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 1356529a0570SDaniel Grumberg Fragments.append(MI->params()[i]->getName(), 1357529a0570SDaniel Grumberg DeclarationFragments::FragmentKind::InternalParam); 1358529a0570SDaniel Grumberg } 1359529a0570SDaniel Grumberg if (MI->isVariadic()) { 1360529a0570SDaniel Grumberg if (numParameters && MI->isC99Varargs()) 1361529a0570SDaniel Grumberg Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 1362529a0570SDaniel Grumberg Fragments.append("...", DeclarationFragments::FragmentKind::Text); 1363529a0570SDaniel Grumberg } 1364529a0570SDaniel Grumberg Fragments.append(")", DeclarationFragments::FragmentKind::Text); 1365529a0570SDaniel Grumberg } 13665bb5704cSZixu Wang return Fragments; 13675bb5704cSZixu Wang } 13685bb5704cSZixu Wang 1369178aad9bSZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory( 1370178aad9bSZixu Wang const ObjCCategoryDecl *Category) { 1371178aad9bSZixu Wang DeclarationFragments Fragments; 1372178aad9bSZixu Wang 13737a851921SDaniel Grumberg auto *Interface = Category->getClassInterface(); 1374178aad9bSZixu Wang SmallString<128> InterfaceUSR; 13757a851921SDaniel Grumberg index::generateUSRForDecl(Interface, InterfaceUSR); 1376178aad9bSZixu Wang 1377178aad9bSZixu Wang Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) 1378178aad9bSZixu Wang .appendSpace() 1379e05c1b46SDaniel Grumberg .append(Interface->getName(), 13807a851921SDaniel Grumberg DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR, 13817a851921SDaniel Grumberg Interface) 1382178aad9bSZixu Wang .append(" (", DeclarationFragments::FragmentKind::Text) 1383178aad9bSZixu Wang .append(Category->getName(), 1384178aad9bSZixu Wang DeclarationFragments::FragmentKind::Identifier) 1385178aad9bSZixu Wang .append(")", DeclarationFragments::FragmentKind::Text); 1386178aad9bSZixu Wang 1387178aad9bSZixu Wang return Fragments; 1388178aad9bSZixu Wang } 1389178aad9bSZixu Wang 13909b36e126SZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface( 13919b36e126SZixu Wang const ObjCInterfaceDecl *Interface) { 13929b36e126SZixu Wang DeclarationFragments Fragments; 13939b36e126SZixu Wang // Build the base of the Objective-C interface declaration. 13949b36e126SZixu Wang Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) 13959b36e126SZixu Wang .appendSpace() 13969b36e126SZixu Wang .append(Interface->getName(), 13979b36e126SZixu Wang DeclarationFragments::FragmentKind::Identifier); 139889f6b26fSZixu Wang 13999b36e126SZixu Wang // Build the inheritance part of the declaration. 14009b36e126SZixu Wang if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) { 14019b36e126SZixu Wang SmallString<128> SuperUSR; 14029b36e126SZixu Wang index::generateUSRForDecl(SuperClass, SuperUSR); 14039b36e126SZixu Wang Fragments.append(" : ", DeclarationFragments::FragmentKind::Text) 14049b36e126SZixu Wang .append(SuperClass->getName(), 14057a851921SDaniel Grumberg DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR, 14067a851921SDaniel Grumberg SuperClass); 140789f6b26fSZixu Wang } 140889f6b26fSZixu Wang 14099b36e126SZixu Wang return Fragments; 14109b36e126SZixu Wang } 141189f6b26fSZixu Wang 14129b36e126SZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod( 14139b36e126SZixu Wang const ObjCMethodDecl *Method) { 14149b36e126SZixu Wang DeclarationFragments Fragments, After; 14159b36e126SZixu Wang // Build the instance/class method indicator. 14169b36e126SZixu Wang if (Method->isClassMethod()) 14179b36e126SZixu Wang Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); 14189b36e126SZixu Wang else if (Method->isInstanceMethod()) 14199b36e126SZixu Wang Fragments.append("- ", DeclarationFragments::FragmentKind::Text); 14209b36e126SZixu Wang 14219b36e126SZixu Wang // Build the return type. 14229b36e126SZixu Wang Fragments.append("(", DeclarationFragments::FragmentKind::Text) 14239b36e126SZixu Wang .append(getFragmentsForType(Method->getReturnType(), 14249b36e126SZixu Wang Method->getASTContext(), After)) 14259b36e126SZixu Wang .append(std::move(After)) 14269b36e126SZixu Wang .append(")", DeclarationFragments::FragmentKind::Text); 14279b36e126SZixu Wang 14289b36e126SZixu Wang // Build the selector part. 14299b36e126SZixu Wang Selector Selector = Method->getSelector(); 14309b36e126SZixu Wang if (Selector.getNumArgs() == 0) 14319b36e126SZixu Wang // For Objective-C methods that don't take arguments, the first (and only) 14329b36e126SZixu Wang // slot of the selector is the method name. 14339b36e126SZixu Wang Fragments.appendSpace().append( 14349b36e126SZixu Wang Selector.getNameForSlot(0), 14359b36e126SZixu Wang DeclarationFragments::FragmentKind::Identifier); 14369b36e126SZixu Wang 14379b36e126SZixu Wang // For Objective-C methods that take arguments, build the selector slots. 14389b36e126SZixu Wang for (unsigned i = 0, end = Method->param_size(); i != end; ++i) { 14394048aad8SZixu Wang // Objective-C method selector parts are considered as identifiers instead 14404048aad8SZixu Wang // of "external parameters" as in Swift. This is because Objective-C method 14414048aad8SZixu Wang // symbols are referenced with the entire selector, instead of just the 14424048aad8SZixu Wang // method name in Swift. 14434048aad8SZixu Wang SmallString<32> ParamID(Selector.getNameForSlot(i)); 14444048aad8SZixu Wang ParamID.append(":"); 14454048aad8SZixu Wang Fragments.appendSpace().append( 14464048aad8SZixu Wang ParamID, DeclarationFragments::FragmentKind::Identifier); 14479b36e126SZixu Wang 14489b36e126SZixu Wang // Build the internal parameter. 14499b36e126SZixu Wang const ParmVarDecl *Param = Method->getParamDecl(i); 14509b36e126SZixu Wang Fragments.append(getFragmentsForParam(Param)); 14519b36e126SZixu Wang } 14529b36e126SZixu Wang 1453e05c1b46SDaniel Grumberg return Fragments.appendSemicolon(); 14549b36e126SZixu Wang } 14559b36e126SZixu Wang 14569b36e126SZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty( 14579b36e126SZixu Wang const ObjCPropertyDecl *Property) { 14589b36e126SZixu Wang DeclarationFragments Fragments, After; 14599b36e126SZixu Wang 14609b36e126SZixu Wang // Build the Objective-C property keyword. 14619b36e126SZixu Wang Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword); 14629b36e126SZixu Wang 146332b53cf9SUsman Akinyemi const auto Attributes = Property->getPropertyAttributesAsWritten(); 14649b36e126SZixu Wang // Build the attributes if there is any associated with the property. 14659b36e126SZixu Wang if (Attributes != ObjCPropertyAttribute::kind_noattr) { 14669b36e126SZixu Wang // No leading comma for the first attribute. 14679b36e126SZixu Wang bool First = true; 14689b36e126SZixu Wang Fragments.append(" (", DeclarationFragments::FragmentKind::Text); 14699b36e126SZixu Wang // Helper function to render the attribute. 14709b36e126SZixu Wang auto RenderAttribute = 14719b36e126SZixu Wang [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling, 14729b36e126SZixu Wang StringRef Arg = "", 14739b36e126SZixu Wang DeclarationFragments::FragmentKind ArgKind = 14749b36e126SZixu Wang DeclarationFragments::FragmentKind::Identifier) { 14759b36e126SZixu Wang // Check if the `Kind` attribute is set for this property. 14769b36e126SZixu Wang if ((Attributes & Kind) && !Spelling.empty()) { 14779b36e126SZixu Wang // Add a leading comma if this is not the first attribute rendered. 14789b36e126SZixu Wang if (!First) 14799b36e126SZixu Wang Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 14809b36e126SZixu Wang // Render the spelling of this attribute `Kind` as a keyword. 14819b36e126SZixu Wang Fragments.append(Spelling, 14829b36e126SZixu Wang DeclarationFragments::FragmentKind::Keyword); 14839b36e126SZixu Wang // If this attribute takes in arguments (e.g. `getter=getterName`), 14849b36e126SZixu Wang // render the arguments. 14859b36e126SZixu Wang if (!Arg.empty()) 14869b36e126SZixu Wang Fragments.append("=", DeclarationFragments::FragmentKind::Text) 14879b36e126SZixu Wang .append(Arg, ArgKind); 14889b36e126SZixu Wang First = false; 14899b36e126SZixu Wang } 14909b36e126SZixu Wang }; 14919b36e126SZixu Wang 14929b36e126SZixu Wang // Go through all possible Objective-C property attributes and render set 14939b36e126SZixu Wang // ones. 14949b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_class, "class"); 14959b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct"); 14969b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic"); 14979b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic"); 14989b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign"); 14999b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain"); 15009b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong"); 15019b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy"); 15029b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak"); 15039b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained, 15049b36e126SZixu Wang "unsafe_unretained"); 15059b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite"); 15069b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly"); 15079b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter", 15089b36e126SZixu Wang Property->getGetterName().getAsString()); 15099b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter", 15109b36e126SZixu Wang Property->getSetterName().getAsString()); 15119b36e126SZixu Wang 15129b36e126SZixu Wang // Render nullability attributes. 15139b36e126SZixu Wang if (Attributes & ObjCPropertyAttribute::kind_nullability) { 15149b36e126SZixu Wang QualType Type = Property->getType(); 15159b36e126SZixu Wang if (const auto Nullability = 15169b36e126SZixu Wang AttributedType::stripOuterNullability(Type)) { 15179b36e126SZixu Wang if (!First) 15189b36e126SZixu Wang Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 15199b36e126SZixu Wang if (*Nullability == NullabilityKind::Unspecified && 15209b36e126SZixu Wang (Attributes & ObjCPropertyAttribute::kind_null_resettable)) 15219b36e126SZixu Wang Fragments.append("null_resettable", 15229b36e126SZixu Wang DeclarationFragments::FragmentKind::Keyword); 15239b36e126SZixu Wang else 15249b36e126SZixu Wang Fragments.append( 15259b36e126SZixu Wang getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true), 15269b36e126SZixu Wang DeclarationFragments::FragmentKind::Keyword); 15279b36e126SZixu Wang First = false; 15289b36e126SZixu Wang } 15299b36e126SZixu Wang } 15309b36e126SZixu Wang 15319b36e126SZixu Wang Fragments.append(")", DeclarationFragments::FragmentKind::Text); 15329b36e126SZixu Wang } 15339b36e126SZixu Wang 15346b89fab8SDaniel Grumberg Fragments.appendSpace(); 15356b89fab8SDaniel Grumberg 15366b89fab8SDaniel Grumberg FunctionTypeLoc BlockLoc; 15376b89fab8SDaniel Grumberg FunctionProtoTypeLoc BlockProtoLoc; 15386b89fab8SDaniel Grumberg findTypeLocForBlockDecl(Property->getTypeSourceInfo(), BlockLoc, 15396b89fab8SDaniel Grumberg BlockProtoLoc); 15406b89fab8SDaniel Grumberg 15416b89fab8SDaniel Grumberg auto PropType = Property->getType(); 15426b89fab8SDaniel Grumberg if (!BlockLoc) 15436b89fab8SDaniel Grumberg Fragments 15446b89fab8SDaniel Grumberg .append(getFragmentsForType(PropType, Property->getASTContext(), After)) 15456b89fab8SDaniel Grumberg .appendSpace(); 15466b89fab8SDaniel Grumberg else 15476b89fab8SDaniel Grumberg Fragments.append( 15486b89fab8SDaniel Grumberg getFragmentsForBlock(Property, BlockLoc, BlockProtoLoc, After)); 15496b89fab8SDaniel Grumberg 15506b89fab8SDaniel Grumberg return Fragments 15519b36e126SZixu Wang .append(Property->getName(), 15529b36e126SZixu Wang DeclarationFragments::FragmentKind::Identifier) 15536b89fab8SDaniel Grumberg .append(std::move(After)) 1554e05c1b46SDaniel Grumberg .appendSemicolon(); 15559b36e126SZixu Wang } 15569b36e126SZixu Wang 1557d1d34bafSZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol( 1558d1d34bafSZixu Wang const ObjCProtocolDecl *Protocol) { 1559d1d34bafSZixu Wang DeclarationFragments Fragments; 1560d1d34bafSZixu Wang // Build basic protocol declaration. 1561d1d34bafSZixu Wang Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword) 1562d1d34bafSZixu Wang .appendSpace() 1563d1d34bafSZixu Wang .append(Protocol->getName(), 1564d1d34bafSZixu Wang DeclarationFragments::FragmentKind::Identifier); 1565d1d34bafSZixu Wang 1566d1d34bafSZixu Wang // If this protocol conforms to other protocols, build the conformance list. 1567d1d34bafSZixu Wang if (!Protocol->protocols().empty()) { 1568d1d34bafSZixu Wang Fragments.append(" <", DeclarationFragments::FragmentKind::Text); 1569d1d34bafSZixu Wang for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin(); 1570d1d34bafSZixu Wang It != Protocol->protocol_end(); It++) { 1571d1d34bafSZixu Wang // Add a leading comma if this is not the first protocol rendered. 1572d1d34bafSZixu Wang if (It != Protocol->protocol_begin()) 1573d1d34bafSZixu Wang Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 1574d1d34bafSZixu Wang 1575d1d34bafSZixu Wang SmallString<128> USR; 1576d1d34bafSZixu Wang index::generateUSRForDecl(*It, USR); 1577d1d34bafSZixu Wang Fragments.append((*It)->getName(), 15787a851921SDaniel Grumberg DeclarationFragments::FragmentKind::TypeIdentifier, USR, 15797a851921SDaniel Grumberg *It); 1580d1d34bafSZixu Wang } 1581d1d34bafSZixu Wang Fragments.append(">", DeclarationFragments::FragmentKind::Text); 1582d1d34bafSZixu Wang } 1583d1d34bafSZixu Wang 1584d1d34bafSZixu Wang return Fragments; 1585d1d34bafSZixu Wang } 1586d1d34bafSZixu Wang 15879fc45ca0SDaniel Grumberg DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef( 15889fc45ca0SDaniel Grumberg const TypedefNameDecl *Decl) { 15899fc45ca0SDaniel Grumberg DeclarationFragments Fragments, After; 15909fc45ca0SDaniel Grumberg Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword) 15919fc45ca0SDaniel Grumberg .appendSpace() 15929fc45ca0SDaniel Grumberg .append(getFragmentsForType(Decl->getUnderlyingType(), 15939fc45ca0SDaniel Grumberg Decl->getASTContext(), After)) 15949fc45ca0SDaniel Grumberg .append(std::move(After)) 15959fc45ca0SDaniel Grumberg .appendSpace() 15969fc45ca0SDaniel Grumberg .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier); 15979fc45ca0SDaniel Grumberg 1598e05c1b46SDaniel Grumberg return Fragments.appendSemicolon(); 15999fc45ca0SDaniel Grumberg } 16009fc45ca0SDaniel Grumberg 16019b36e126SZixu Wang // Instantiate template for FunctionDecl. 16029b36e126SZixu Wang template FunctionSignature 16039b36e126SZixu Wang DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *); 16049b36e126SZixu Wang 16059b36e126SZixu Wang // Instantiate template for ObjCMethodDecl. 16069b36e126SZixu Wang template FunctionSignature 16079b36e126SZixu Wang DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *); 16089b36e126SZixu Wang 160989f6b26fSZixu Wang // Subheading of a symbol defaults to its name. 161089f6b26fSZixu Wang DeclarationFragments 161189f6b26fSZixu Wang DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) { 161289f6b26fSZixu Wang DeclarationFragments Fragments; 161375f55eb3SErick Velez if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl)) 161475f55eb3SErick Velez Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(), 161575f55eb3SErick Velez DeclarationFragments::FragmentKind::Identifier); 161675f55eb3SErick Velez else if (isa<CXXConversionDecl>(Decl)) { 161775f55eb3SErick Velez Fragments.append( 161875f55eb3SErick Velez cast<CXXConversionDecl>(Decl)->getConversionType().getAsString(), 161975f55eb3SErick Velez DeclarationFragments::FragmentKind::Identifier); 162075f55eb3SErick Velez } else if (isa<CXXMethodDecl>(Decl) && 162175f55eb3SErick Velez cast<CXXMethodDecl>(Decl)->isOverloadedOperator()) { 162275f55eb3SErick Velez Fragments.append(Decl->getNameAsString(), 162375f55eb3SErick Velez DeclarationFragments::FragmentKind::Identifier); 1624*33fa40ccSDaniel Grumberg } else if (isa<TagDecl>(Decl) && 1625*33fa40ccSDaniel Grumberg cast<TagDecl>(Decl)->getTypedefNameForAnonDecl()) { 1626*33fa40ccSDaniel Grumberg return getSubHeading(cast<TagDecl>(Decl)->getTypedefNameForAnonDecl()); 16272c13194eSDaniel Grumberg } else if (Decl->getIdentifier()) { 162889f6b26fSZixu Wang Fragments.append(Decl->getName(), 162989f6b26fSZixu Wang DeclarationFragments::FragmentKind::Identifier); 16302c13194eSDaniel Grumberg } else 16312c13194eSDaniel Grumberg Fragments.append(Decl->getDeclName().getAsString(), 16322c13194eSDaniel Grumberg DeclarationFragments::FragmentKind::Identifier); 163389f6b26fSZixu Wang return Fragments; 163489f6b26fSZixu Wang } 16359b36e126SZixu Wang 16369b36e126SZixu Wang // Subheading of an Objective-C method is a `+` or `-` sign indicating whether 16379b36e126SZixu Wang // it's a class method or an instance method, followed by the selector name. 16389b36e126SZixu Wang DeclarationFragments 16399b36e126SZixu Wang DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) { 16409b36e126SZixu Wang DeclarationFragments Fragments; 16419b36e126SZixu Wang if (Method->isClassMethod()) 16429b36e126SZixu Wang Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); 16439b36e126SZixu Wang else if (Method->isInstanceMethod()) 16449b36e126SZixu Wang Fragments.append("- ", DeclarationFragments::FragmentKind::Text); 16459b36e126SZixu Wang 16469b36e126SZixu Wang return Fragments.append(Method->getNameAsString(), 16479b36e126SZixu Wang DeclarationFragments::FragmentKind::Identifier); 16489b36e126SZixu Wang } 1649529a0570SDaniel Grumberg 1650529a0570SDaniel Grumberg // Subheading of a symbol defaults to its name. 1651529a0570SDaniel Grumberg DeclarationFragments 1652529a0570SDaniel Grumberg DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) { 1653529a0570SDaniel Grumberg DeclarationFragments Fragments; 1654529a0570SDaniel Grumberg Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); 1655529a0570SDaniel Grumberg return Fragments; 1656529a0570SDaniel Grumberg } 1657