181ad6265SDimitry Andric //===- ExtractAPI/DeclarationFragments.cpp ----------------------*- C++ -*-===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric /// 981ad6265SDimitry Andric /// \file 1081ad6265SDimitry Andric /// This file implements Declaration Fragments related classes. 1181ad6265SDimitry Andric /// 1281ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1381ad6265SDimitry Andric 1481ad6265SDimitry Andric #include "clang/ExtractAPI/DeclarationFragments.h" 1581ad6265SDimitry Andric #include "TypedefUnderlyingTypeResolver.h" 1681ad6265SDimitry Andric #include "clang/Index/USRGeneration.h" 1781ad6265SDimitry Andric #include "llvm/ADT/StringSwitch.h" 1881ad6265SDimitry Andric 1981ad6265SDimitry Andric using namespace clang::extractapi; 2081ad6265SDimitry Andric using namespace llvm; 2181ad6265SDimitry Andric 2281ad6265SDimitry Andric DeclarationFragments &DeclarationFragments::appendSpace() { 2381ad6265SDimitry Andric if (!Fragments.empty()) { 2481ad6265SDimitry Andric Fragment &Last = Fragments.back(); 2581ad6265SDimitry Andric if (Last.Kind == FragmentKind::Text) { 2681ad6265SDimitry Andric // Merge the extra space into the last fragment if the last fragment is 2781ad6265SDimitry Andric // also text. 2881ad6265SDimitry Andric if (Last.Spelling.back() != ' ') { // avoid extra trailing spaces. 2981ad6265SDimitry Andric Last.Spelling.push_back(' '); 3081ad6265SDimitry Andric } 3181ad6265SDimitry Andric } else { 3281ad6265SDimitry Andric append(" ", FragmentKind::Text); 3381ad6265SDimitry Andric } 3481ad6265SDimitry Andric } 3581ad6265SDimitry Andric 3681ad6265SDimitry Andric return *this; 3781ad6265SDimitry Andric } 3881ad6265SDimitry Andric 3981ad6265SDimitry Andric StringRef DeclarationFragments::getFragmentKindString( 4081ad6265SDimitry Andric DeclarationFragments::FragmentKind Kind) { 4181ad6265SDimitry Andric switch (Kind) { 4281ad6265SDimitry Andric case DeclarationFragments::FragmentKind::None: 4381ad6265SDimitry Andric return "none"; 4481ad6265SDimitry Andric case DeclarationFragments::FragmentKind::Keyword: 4581ad6265SDimitry Andric return "keyword"; 4681ad6265SDimitry Andric case DeclarationFragments::FragmentKind::Attribute: 4781ad6265SDimitry Andric return "attribute"; 4881ad6265SDimitry Andric case DeclarationFragments::FragmentKind::NumberLiteral: 4981ad6265SDimitry Andric return "number"; 5081ad6265SDimitry Andric case DeclarationFragments::FragmentKind::StringLiteral: 5181ad6265SDimitry Andric return "string"; 5281ad6265SDimitry Andric case DeclarationFragments::FragmentKind::Identifier: 5381ad6265SDimitry Andric return "identifier"; 5481ad6265SDimitry Andric case DeclarationFragments::FragmentKind::TypeIdentifier: 5581ad6265SDimitry Andric return "typeIdentifier"; 5681ad6265SDimitry Andric case DeclarationFragments::FragmentKind::GenericParameter: 5781ad6265SDimitry Andric return "genericParameter"; 5881ad6265SDimitry Andric case DeclarationFragments::FragmentKind::ExternalParam: 5981ad6265SDimitry Andric return "externalParam"; 6081ad6265SDimitry Andric case DeclarationFragments::FragmentKind::InternalParam: 6181ad6265SDimitry Andric return "internalParam"; 6281ad6265SDimitry Andric case DeclarationFragments::FragmentKind::Text: 6381ad6265SDimitry Andric return "text"; 6481ad6265SDimitry Andric } 6581ad6265SDimitry Andric 6681ad6265SDimitry Andric llvm_unreachable("Unhandled FragmentKind"); 6781ad6265SDimitry Andric } 6881ad6265SDimitry Andric 6981ad6265SDimitry Andric DeclarationFragments::FragmentKind 7081ad6265SDimitry Andric DeclarationFragments::parseFragmentKindFromString(StringRef S) { 7181ad6265SDimitry Andric return llvm::StringSwitch<FragmentKind>(S) 7281ad6265SDimitry Andric .Case("keyword", DeclarationFragments::FragmentKind::Keyword) 7381ad6265SDimitry Andric .Case("attribute", DeclarationFragments::FragmentKind::Attribute) 7481ad6265SDimitry Andric .Case("number", DeclarationFragments::FragmentKind::NumberLiteral) 7581ad6265SDimitry Andric .Case("string", DeclarationFragments::FragmentKind::StringLiteral) 7681ad6265SDimitry Andric .Case("identifier", DeclarationFragments::FragmentKind::Identifier) 7781ad6265SDimitry Andric .Case("typeIdentifier", 7881ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier) 7981ad6265SDimitry Andric .Case("genericParameter", 8081ad6265SDimitry Andric DeclarationFragments::FragmentKind::GenericParameter) 8181ad6265SDimitry Andric .Case("internalParam", DeclarationFragments::FragmentKind::InternalParam) 8281ad6265SDimitry Andric .Case("externalParam", DeclarationFragments::FragmentKind::ExternalParam) 8381ad6265SDimitry Andric .Case("text", DeclarationFragments::FragmentKind::Text) 8481ad6265SDimitry Andric .Default(DeclarationFragments::FragmentKind::None); 8581ad6265SDimitry Andric } 8681ad6265SDimitry Andric 8781ad6265SDimitry Andric // NNS stores C++ nested name specifiers, which are prefixes to qualified names. 8881ad6265SDimitry Andric // Build declaration fragments for NNS recursively so that we have the USR for 8981ad6265SDimitry Andric // every part in a qualified name, and also leaves the actual underlying type 9081ad6265SDimitry Andric // cleaner for its own fragment. 9181ad6265SDimitry Andric DeclarationFragments 9281ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS, 9381ad6265SDimitry Andric ASTContext &Context, 9481ad6265SDimitry Andric DeclarationFragments &After) { 9581ad6265SDimitry Andric DeclarationFragments Fragments; 9681ad6265SDimitry Andric if (NNS->getPrefix()) 9781ad6265SDimitry Andric Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After)); 9881ad6265SDimitry Andric 9981ad6265SDimitry Andric switch (NNS->getKind()) { 10081ad6265SDimitry Andric case NestedNameSpecifier::Identifier: 10181ad6265SDimitry Andric Fragments.append(NNS->getAsIdentifier()->getName(), 10281ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 10381ad6265SDimitry Andric break; 10481ad6265SDimitry Andric 10581ad6265SDimitry Andric case NestedNameSpecifier::Namespace: { 10681ad6265SDimitry Andric const NamespaceDecl *NS = NNS->getAsNamespace(); 10781ad6265SDimitry Andric if (NS->isAnonymousNamespace()) 10881ad6265SDimitry Andric return Fragments; 10981ad6265SDimitry Andric SmallString<128> USR; 11081ad6265SDimitry Andric index::generateUSRForDecl(NS, USR); 11181ad6265SDimitry Andric Fragments.append(NS->getName(), 112*bdd1243dSDimitry Andric DeclarationFragments::FragmentKind::Identifier, USR, NS); 11381ad6265SDimitry Andric break; 11481ad6265SDimitry Andric } 11581ad6265SDimitry Andric 11681ad6265SDimitry Andric case NestedNameSpecifier::NamespaceAlias: { 11781ad6265SDimitry Andric const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias(); 11881ad6265SDimitry Andric SmallString<128> USR; 11981ad6265SDimitry Andric index::generateUSRForDecl(Alias, USR); 12081ad6265SDimitry Andric Fragments.append(Alias->getName(), 121*bdd1243dSDimitry Andric DeclarationFragments::FragmentKind::Identifier, USR, 122*bdd1243dSDimitry Andric Alias); 12381ad6265SDimitry Andric break; 12481ad6265SDimitry Andric } 12581ad6265SDimitry Andric 12681ad6265SDimitry Andric case NestedNameSpecifier::Global: 12781ad6265SDimitry Andric // The global specifier `::` at the beginning. No stored value. 12881ad6265SDimitry Andric break; 12981ad6265SDimitry Andric 13081ad6265SDimitry Andric case NestedNameSpecifier::Super: 13181ad6265SDimitry Andric // Microsoft's `__super` specifier. 13281ad6265SDimitry Andric Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword); 13381ad6265SDimitry Andric break; 13481ad6265SDimitry Andric 13581ad6265SDimitry Andric case NestedNameSpecifier::TypeSpecWithTemplate: 13681ad6265SDimitry Andric // A type prefixed by the `template` keyword. 13781ad6265SDimitry Andric Fragments.append("template", DeclarationFragments::FragmentKind::Keyword); 13881ad6265SDimitry Andric Fragments.appendSpace(); 13981ad6265SDimitry Andric // Fallthrough after adding the keyword to handle the actual type. 140*bdd1243dSDimitry Andric [[fallthrough]]; 14181ad6265SDimitry Andric 14281ad6265SDimitry Andric case NestedNameSpecifier::TypeSpec: { 14381ad6265SDimitry Andric const Type *T = NNS->getAsType(); 14481ad6265SDimitry Andric // FIXME: Handle C++ template specialization type 14581ad6265SDimitry Andric Fragments.append(getFragmentsForType(T, Context, After)); 14681ad6265SDimitry Andric break; 14781ad6265SDimitry Andric } 14881ad6265SDimitry Andric } 14981ad6265SDimitry Andric 15081ad6265SDimitry Andric // Add the separator text `::` for this segment. 15181ad6265SDimitry Andric return Fragments.append("::", DeclarationFragments::FragmentKind::Text); 15281ad6265SDimitry Andric } 15381ad6265SDimitry Andric 15481ad6265SDimitry Andric // Recursively build the declaration fragments for an underlying `Type` with 15581ad6265SDimitry Andric // qualifiers removed. 15681ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( 15781ad6265SDimitry Andric const Type *T, ASTContext &Context, DeclarationFragments &After) { 15881ad6265SDimitry Andric assert(T && "invalid type"); 15981ad6265SDimitry Andric 16081ad6265SDimitry Andric DeclarationFragments Fragments; 16181ad6265SDimitry Andric 16281ad6265SDimitry Andric // Declaration fragments of a pointer type is the declaration fragments of 16381ad6265SDimitry Andric // the pointee type followed by a `*`, except for Objective-C `id` and `Class` 16481ad6265SDimitry Andric // pointers, where we do not spell out the `*`. 16581ad6265SDimitry Andric if (T->isPointerType() || 16681ad6265SDimitry Andric (T->isObjCObjectPointerType() && 16781ad6265SDimitry Andric !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType())) { 16881ad6265SDimitry Andric return Fragments 16981ad6265SDimitry Andric .append(getFragmentsForType(T->getPointeeType(), Context, After)) 17081ad6265SDimitry Andric .append(" *", DeclarationFragments::FragmentKind::Text); 17181ad6265SDimitry Andric } 17281ad6265SDimitry Andric 17381ad6265SDimitry Andric // Declaration fragments of a lvalue reference type is the declaration 17481ad6265SDimitry Andric // fragments of the underlying type followed by a `&`. 17581ad6265SDimitry Andric if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T)) 17681ad6265SDimitry Andric return Fragments 17781ad6265SDimitry Andric .append( 17881ad6265SDimitry Andric getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After)) 17981ad6265SDimitry Andric .append(" &", DeclarationFragments::FragmentKind::Text); 18081ad6265SDimitry Andric 18181ad6265SDimitry Andric // Declaration fragments of a rvalue reference type is the declaration 18281ad6265SDimitry Andric // fragments of the underlying type followed by a `&&`. 18381ad6265SDimitry Andric if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T)) 18481ad6265SDimitry Andric return Fragments 18581ad6265SDimitry Andric .append( 18681ad6265SDimitry Andric getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After)) 18781ad6265SDimitry Andric .append(" &&", DeclarationFragments::FragmentKind::Text); 18881ad6265SDimitry Andric 18981ad6265SDimitry Andric // Declaration fragments of an array-typed variable have two parts: 19081ad6265SDimitry Andric // 1. the element type of the array that appears before the variable name; 19181ad6265SDimitry Andric // 2. array brackets `[(0-9)?]` that appear after the variable name. 19281ad6265SDimitry Andric if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) { 19381ad6265SDimitry Andric // Build the "after" part first because the inner element type might also 19481ad6265SDimitry Andric // be an array-type. For example `int matrix[3][4]` which has a type of 19581ad6265SDimitry Andric // "(array 3 of (array 4 of ints))." 19681ad6265SDimitry Andric // Push the array size part first to make sure they are in the right order. 19781ad6265SDimitry Andric After.append("[", DeclarationFragments::FragmentKind::Text); 19881ad6265SDimitry Andric 19981ad6265SDimitry Andric switch (AT->getSizeModifier()) { 20081ad6265SDimitry Andric case ArrayType::Normal: 20181ad6265SDimitry Andric break; 20281ad6265SDimitry Andric case ArrayType::Static: 20381ad6265SDimitry Andric Fragments.append("static", DeclarationFragments::FragmentKind::Keyword); 20481ad6265SDimitry Andric break; 20581ad6265SDimitry Andric case ArrayType::Star: 20681ad6265SDimitry Andric Fragments.append("*", DeclarationFragments::FragmentKind::Text); 20781ad6265SDimitry Andric break; 20881ad6265SDimitry Andric } 20981ad6265SDimitry Andric 21081ad6265SDimitry Andric if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) { 21181ad6265SDimitry Andric // FIXME: right now this would evaluate any expressions/macros written in 21281ad6265SDimitry Andric // the original source to concrete values. For example 21381ad6265SDimitry Andric // `int nums[MAX]` -> `int nums[100]` 21481ad6265SDimitry Andric // `char *str[5 + 1]` -> `char *str[6]` 21581ad6265SDimitry Andric SmallString<128> Size; 21681ad6265SDimitry Andric CAT->getSize().toStringUnsigned(Size); 21781ad6265SDimitry Andric After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral); 21881ad6265SDimitry Andric } 21981ad6265SDimitry Andric 22081ad6265SDimitry Andric After.append("]", DeclarationFragments::FragmentKind::Text); 22181ad6265SDimitry Andric 22281ad6265SDimitry Andric return Fragments.append( 22381ad6265SDimitry Andric getFragmentsForType(AT->getElementType(), Context, After)); 22481ad6265SDimitry Andric } 22581ad6265SDimitry Andric 22681ad6265SDimitry Andric // An ElaboratedType is a sugar for types that are referred to using an 22781ad6265SDimitry Andric // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a 22881ad6265SDimitry Andric // qualified name, e.g., `N::M::type`, or both. 22981ad6265SDimitry Andric if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) { 23081ad6265SDimitry Andric ElaboratedTypeKeyword Keyword = ET->getKeyword(); 23181ad6265SDimitry Andric if (Keyword != ETK_None) { 23281ad6265SDimitry Andric Fragments 23381ad6265SDimitry Andric .append(ElaboratedType::getKeywordName(Keyword), 23481ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword) 23581ad6265SDimitry Andric .appendSpace(); 23681ad6265SDimitry Andric } 23781ad6265SDimitry Andric 23881ad6265SDimitry Andric if (const NestedNameSpecifier *NNS = ET->getQualifier()) 23981ad6265SDimitry Andric Fragments.append(getFragmentsForNNS(NNS, Context, After)); 24081ad6265SDimitry Andric 24181ad6265SDimitry Andric // After handling the elaborated keyword or qualified name, build 24281ad6265SDimitry Andric // declaration fragments for the desugared underlying type. 24381ad6265SDimitry Andric return Fragments.append(getFragmentsForType(ET->desugar(), Context, After)); 24481ad6265SDimitry Andric } 24581ad6265SDimitry Andric 24681ad6265SDimitry Andric // Everything we care about has been handled now, reduce to the canonical 24781ad6265SDimitry Andric // unqualified base type. 24881ad6265SDimitry Andric QualType Base = T->getCanonicalTypeUnqualified(); 24981ad6265SDimitry Andric 25081ad6265SDimitry Andric // Render Objective-C `id`/`instancetype` as keywords. 25181ad6265SDimitry Andric if (T->isObjCIdType()) 25281ad6265SDimitry Andric return Fragments.append(Base.getAsString(), 25381ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword); 25481ad6265SDimitry Andric 25581ad6265SDimitry Andric // If the type is a typedefed type, get the underlying TypedefNameDecl for a 25681ad6265SDimitry Andric // direct reference to the typedef instead of the wrapped type. 25781ad6265SDimitry Andric if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) { 25881ad6265SDimitry Andric const TypedefNameDecl *Decl = TypedefTy->getDecl(); 259*bdd1243dSDimitry Andric TypedefUnderlyingTypeResolver TypedefResolver(Context); 260*bdd1243dSDimitry Andric std::string USR = TypedefResolver.getUSRForType(QualType(T, 0)); 261*bdd1243dSDimitry Andric return Fragments.append( 262*bdd1243dSDimitry Andric Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier, 263*bdd1243dSDimitry Andric USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0))); 26481ad6265SDimitry Andric } 26581ad6265SDimitry Andric 26681ad6265SDimitry Andric // If the base type is a TagType (struct/interface/union/class/enum), let's 26781ad6265SDimitry Andric // get the underlying Decl for better names and USRs. 26881ad6265SDimitry Andric if (const TagType *TagTy = dyn_cast<TagType>(Base)) { 26981ad6265SDimitry Andric const TagDecl *Decl = TagTy->getDecl(); 27081ad6265SDimitry Andric // Anonymous decl, skip this fragment. 27181ad6265SDimitry Andric if (Decl->getName().empty()) 27281ad6265SDimitry Andric return Fragments; 27381ad6265SDimitry Andric SmallString<128> TagUSR; 27481ad6265SDimitry Andric clang::index::generateUSRForDecl(Decl, TagUSR); 27581ad6265SDimitry Andric return Fragments.append(Decl->getName(), 27681ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, 277*bdd1243dSDimitry Andric TagUSR, Decl); 27881ad6265SDimitry Andric } 27981ad6265SDimitry Andric 28081ad6265SDimitry Andric // If the base type is an ObjCInterfaceType, use the underlying 28181ad6265SDimitry Andric // ObjCInterfaceDecl for the true USR. 28281ad6265SDimitry Andric if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) { 28381ad6265SDimitry Andric const auto *Decl = ObjCIT->getDecl(); 28481ad6265SDimitry Andric SmallString<128> USR; 28581ad6265SDimitry Andric index::generateUSRForDecl(Decl, USR); 28681ad6265SDimitry Andric return Fragments.append(Decl->getName(), 28781ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, 288*bdd1243dSDimitry Andric USR, Decl); 28981ad6265SDimitry Andric } 29081ad6265SDimitry Andric 29181ad6265SDimitry Andric // Default fragment builder for other kinds of types (BuiltinType etc.) 29281ad6265SDimitry Andric SmallString<128> USR; 29381ad6265SDimitry Andric clang::index::generateUSRForType(Base, Context, USR); 29481ad6265SDimitry Andric Fragments.append(Base.getAsString(), 29581ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, USR); 29681ad6265SDimitry Andric 29781ad6265SDimitry Andric return Fragments; 29881ad6265SDimitry Andric } 29981ad6265SDimitry Andric 30081ad6265SDimitry Andric DeclarationFragments 30181ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) { 30281ad6265SDimitry Andric DeclarationFragments Fragments; 30381ad6265SDimitry Andric if (Quals.hasConst()) 30481ad6265SDimitry Andric Fragments.append("const", DeclarationFragments::FragmentKind::Keyword); 30581ad6265SDimitry Andric if (Quals.hasVolatile()) 30681ad6265SDimitry Andric Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword); 30781ad6265SDimitry Andric if (Quals.hasRestrict()) 30881ad6265SDimitry Andric Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword); 30981ad6265SDimitry Andric 31081ad6265SDimitry Andric return Fragments; 31181ad6265SDimitry Andric } 31281ad6265SDimitry Andric 31381ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( 31481ad6265SDimitry Andric const QualType QT, ASTContext &Context, DeclarationFragments &After) { 31581ad6265SDimitry Andric assert(!QT.isNull() && "invalid type"); 31681ad6265SDimitry Andric 31781ad6265SDimitry Andric if (const ParenType *PT = dyn_cast<ParenType>(QT)) { 31881ad6265SDimitry Andric After.append(")", DeclarationFragments::FragmentKind::Text); 31981ad6265SDimitry Andric return getFragmentsForType(PT->getInnerType(), Context, After) 32081ad6265SDimitry Andric .append("(", DeclarationFragments::FragmentKind::Text); 32181ad6265SDimitry Andric } 32281ad6265SDimitry Andric 32381ad6265SDimitry Andric const SplitQualType SQT = QT.split(); 32481ad6265SDimitry Andric DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals), 32581ad6265SDimitry Andric TypeFragments = 32681ad6265SDimitry Andric getFragmentsForType(SQT.Ty, Context, After); 32781ad6265SDimitry Andric if (QualsFragments.getFragments().empty()) 32881ad6265SDimitry Andric return TypeFragments; 32981ad6265SDimitry Andric 33081ad6265SDimitry Andric // Use east qualifier for pointer types 33181ad6265SDimitry Andric // For example: 33281ad6265SDimitry Andric // ``` 33381ad6265SDimitry Andric // int * const 33481ad6265SDimitry Andric // ^---- ^---- 33581ad6265SDimitry Andric // type qualifier 33681ad6265SDimitry Andric // ^----------------- 33781ad6265SDimitry Andric // const pointer to int 33881ad6265SDimitry Andric // ``` 33981ad6265SDimitry Andric // should not be reconstructed as 34081ad6265SDimitry Andric // ``` 34181ad6265SDimitry Andric // const int * 34281ad6265SDimitry Andric // ^---- ^-- 34381ad6265SDimitry Andric // qualifier type 34481ad6265SDimitry Andric // ^---------------- ^ 34581ad6265SDimitry Andric // pointer to const int 34681ad6265SDimitry Andric // ``` 34781ad6265SDimitry Andric if (SQT.Ty->isAnyPointerType()) 34881ad6265SDimitry Andric return TypeFragments.appendSpace().append(std::move(QualsFragments)); 34981ad6265SDimitry Andric 35081ad6265SDimitry Andric return QualsFragments.appendSpace().append(std::move(TypeFragments)); 35181ad6265SDimitry Andric } 35281ad6265SDimitry Andric 35381ad6265SDimitry Andric DeclarationFragments 35481ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) { 35581ad6265SDimitry Andric DeclarationFragments Fragments; 35681ad6265SDimitry Andric StorageClass SC = Var->getStorageClass(); 35781ad6265SDimitry Andric if (SC != SC_None) 35881ad6265SDimitry Andric Fragments 35981ad6265SDimitry Andric .append(VarDecl::getStorageClassSpecifierString(SC), 36081ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword) 36181ad6265SDimitry Andric .appendSpace(); 36281ad6265SDimitry Andric QualType T = 36381ad6265SDimitry Andric Var->getTypeSourceInfo() 36481ad6265SDimitry Andric ? Var->getTypeSourceInfo()->getType() 36581ad6265SDimitry Andric : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType()); 36681ad6265SDimitry Andric 36781ad6265SDimitry Andric // Capture potential fragments that needs to be placed after the variable name 36881ad6265SDimitry Andric // ``` 36981ad6265SDimitry Andric // int nums[5]; 37081ad6265SDimitry Andric // char (*ptr_to_array)[6]; 37181ad6265SDimitry Andric // ``` 37281ad6265SDimitry Andric DeclarationFragments After; 37381ad6265SDimitry Andric return Fragments.append(getFragmentsForType(T, Var->getASTContext(), After)) 37481ad6265SDimitry Andric .appendSpace() 37581ad6265SDimitry Andric .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) 37681ad6265SDimitry Andric .append(std::move(After)); 37781ad6265SDimitry Andric } 37881ad6265SDimitry Andric 37981ad6265SDimitry Andric DeclarationFragments 38081ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) { 38181ad6265SDimitry Andric DeclarationFragments Fragments, After; 38281ad6265SDimitry Andric 38381ad6265SDimitry Andric QualType T = Param->getTypeSourceInfo() 38481ad6265SDimitry Andric ? Param->getTypeSourceInfo()->getType() 38581ad6265SDimitry Andric : Param->getASTContext().getUnqualifiedObjCPointerType( 38681ad6265SDimitry Andric Param->getType()); 38781ad6265SDimitry Andric 38881ad6265SDimitry Andric DeclarationFragments TypeFragments = 38981ad6265SDimitry Andric getFragmentsForType(T, Param->getASTContext(), After); 39081ad6265SDimitry Andric 39181ad6265SDimitry Andric if (Param->isObjCMethodParameter()) 39281ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text) 39381ad6265SDimitry Andric .append(std::move(TypeFragments)) 39481ad6265SDimitry Andric .append(") ", DeclarationFragments::FragmentKind::Text); 39581ad6265SDimitry Andric else 39681ad6265SDimitry Andric Fragments.append(std::move(TypeFragments)).appendSpace(); 39781ad6265SDimitry Andric 39881ad6265SDimitry Andric return Fragments 39981ad6265SDimitry Andric .append(Param->getName(), 40081ad6265SDimitry Andric DeclarationFragments::FragmentKind::InternalParam) 40181ad6265SDimitry Andric .append(std::move(After)); 40281ad6265SDimitry Andric } 40381ad6265SDimitry Andric 40481ad6265SDimitry Andric DeclarationFragments 40581ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) { 40681ad6265SDimitry Andric DeclarationFragments Fragments; 40781ad6265SDimitry Andric // FIXME: Handle template specialization 40881ad6265SDimitry Andric switch (Func->getStorageClass()) { 40981ad6265SDimitry Andric case SC_None: 41081ad6265SDimitry Andric case SC_PrivateExtern: 41181ad6265SDimitry Andric break; 41281ad6265SDimitry Andric case SC_Extern: 41381ad6265SDimitry Andric Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword) 41481ad6265SDimitry Andric .appendSpace(); 41581ad6265SDimitry Andric break; 41681ad6265SDimitry Andric case SC_Static: 41781ad6265SDimitry Andric Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) 41881ad6265SDimitry Andric .appendSpace(); 41981ad6265SDimitry Andric break; 42081ad6265SDimitry Andric case SC_Auto: 42181ad6265SDimitry Andric case SC_Register: 42281ad6265SDimitry Andric llvm_unreachable("invalid for functions"); 42381ad6265SDimitry Andric } 42481ad6265SDimitry Andric // FIXME: Handle C++ function specifiers: constexpr, consteval, explicit, etc. 42581ad6265SDimitry Andric 42681ad6265SDimitry Andric // FIXME: Is `after` actually needed here? 42781ad6265SDimitry Andric DeclarationFragments After; 42881ad6265SDimitry Andric Fragments 42981ad6265SDimitry Andric .append(getFragmentsForType(Func->getReturnType(), Func->getASTContext(), 43081ad6265SDimitry Andric After)) 43181ad6265SDimitry Andric .appendSpace() 43281ad6265SDimitry Andric .append(Func->getName(), DeclarationFragments::FragmentKind::Identifier) 43381ad6265SDimitry Andric .append(std::move(After)); 43481ad6265SDimitry Andric 43581ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text); 43681ad6265SDimitry Andric for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) { 43781ad6265SDimitry Andric if (i) 43881ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 43981ad6265SDimitry Andric Fragments.append(getFragmentsForParam(Func->getParamDecl(i))); 44081ad6265SDimitry Andric } 44181ad6265SDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 44281ad6265SDimitry Andric 44381ad6265SDimitry Andric // FIXME: Handle exception specifiers: throw, noexcept 44481ad6265SDimitry Andric return Fragments; 44581ad6265SDimitry Andric } 44681ad6265SDimitry Andric 44781ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant( 44881ad6265SDimitry Andric const EnumConstantDecl *EnumConstDecl) { 44981ad6265SDimitry Andric DeclarationFragments Fragments; 45081ad6265SDimitry Andric return Fragments.append(EnumConstDecl->getName(), 45181ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 45281ad6265SDimitry Andric } 45381ad6265SDimitry Andric 45481ad6265SDimitry Andric DeclarationFragments 45581ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) { 45681ad6265SDimitry Andric if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl()) 45781ad6265SDimitry Andric return getFragmentsForTypedef(TypedefNameDecl); 45881ad6265SDimitry Andric 45981ad6265SDimitry Andric DeclarationFragments Fragments, After; 46081ad6265SDimitry Andric Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword); 46181ad6265SDimitry Andric 46281ad6265SDimitry Andric if (!EnumDecl->getName().empty()) 46381ad6265SDimitry Andric Fragments.appendSpace().append( 46481ad6265SDimitry Andric EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier); 46581ad6265SDimitry Andric 46681ad6265SDimitry Andric QualType IntegerType = EnumDecl->getIntegerType(); 46781ad6265SDimitry Andric if (!IntegerType.isNull()) 46881ad6265SDimitry Andric Fragments.append(": ", DeclarationFragments::FragmentKind::Text) 46981ad6265SDimitry Andric .append( 47081ad6265SDimitry Andric getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After)) 47181ad6265SDimitry Andric .append(std::move(After)); 47281ad6265SDimitry Andric 47381ad6265SDimitry Andric return Fragments; 47481ad6265SDimitry Andric } 47581ad6265SDimitry Andric 47681ad6265SDimitry Andric DeclarationFragments 47781ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) { 47881ad6265SDimitry Andric DeclarationFragments After; 47981ad6265SDimitry Andric return getFragmentsForType(Field->getType(), Field->getASTContext(), After) 48081ad6265SDimitry Andric .appendSpace() 48181ad6265SDimitry Andric .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier) 48281ad6265SDimitry Andric .append(std::move(After)); 48381ad6265SDimitry Andric } 48481ad6265SDimitry Andric 48581ad6265SDimitry Andric DeclarationFragments 48681ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForStruct(const RecordDecl *Record) { 48781ad6265SDimitry Andric if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl()) 48881ad6265SDimitry Andric return getFragmentsForTypedef(TypedefNameDecl); 48981ad6265SDimitry Andric 49081ad6265SDimitry Andric DeclarationFragments Fragments; 49181ad6265SDimitry Andric Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword); 49281ad6265SDimitry Andric 49381ad6265SDimitry Andric if (!Record->getName().empty()) 49481ad6265SDimitry Andric Fragments.appendSpace().append( 49581ad6265SDimitry Andric Record->getName(), DeclarationFragments::FragmentKind::Identifier); 49681ad6265SDimitry Andric return Fragments; 49781ad6265SDimitry Andric } 49881ad6265SDimitry Andric 49981ad6265SDimitry Andric DeclarationFragments 50081ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name, 50181ad6265SDimitry Andric const MacroDirective *MD) { 50281ad6265SDimitry Andric DeclarationFragments Fragments; 50381ad6265SDimitry Andric Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword) 50481ad6265SDimitry Andric .appendSpace(); 50581ad6265SDimitry Andric Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); 50681ad6265SDimitry Andric 50781ad6265SDimitry Andric auto *MI = MD->getMacroInfo(); 50881ad6265SDimitry Andric 50981ad6265SDimitry Andric if (MI->isFunctionLike()) { 51081ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text); 51181ad6265SDimitry Andric unsigned numParameters = MI->getNumParams(); 51281ad6265SDimitry Andric if (MI->isC99Varargs()) 51381ad6265SDimitry Andric --numParameters; 51481ad6265SDimitry Andric for (unsigned i = 0; i < numParameters; ++i) { 51581ad6265SDimitry Andric if (i) 51681ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 51781ad6265SDimitry Andric Fragments.append(MI->params()[i]->getName(), 51881ad6265SDimitry Andric DeclarationFragments::FragmentKind::InternalParam); 51981ad6265SDimitry Andric } 52081ad6265SDimitry Andric if (MI->isVariadic()) { 52181ad6265SDimitry Andric if (numParameters && MI->isC99Varargs()) 52281ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 52381ad6265SDimitry Andric Fragments.append("...", DeclarationFragments::FragmentKind::Text); 52481ad6265SDimitry Andric } 52581ad6265SDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 52681ad6265SDimitry Andric } 52781ad6265SDimitry Andric return Fragments; 52881ad6265SDimitry Andric } 52981ad6265SDimitry Andric 53081ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory( 53181ad6265SDimitry Andric const ObjCCategoryDecl *Category) { 53281ad6265SDimitry Andric DeclarationFragments Fragments; 53381ad6265SDimitry Andric 534*bdd1243dSDimitry Andric auto *Interface = Category->getClassInterface(); 53581ad6265SDimitry Andric SmallString<128> InterfaceUSR; 536*bdd1243dSDimitry Andric index::generateUSRForDecl(Interface, InterfaceUSR); 53781ad6265SDimitry Andric 53881ad6265SDimitry Andric Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) 53981ad6265SDimitry Andric .appendSpace() 54081ad6265SDimitry Andric .append(Category->getClassInterface()->getName(), 541*bdd1243dSDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR, 542*bdd1243dSDimitry Andric Interface) 54381ad6265SDimitry Andric .append(" (", DeclarationFragments::FragmentKind::Text) 54481ad6265SDimitry Andric .append(Category->getName(), 54581ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier) 54681ad6265SDimitry Andric .append(")", DeclarationFragments::FragmentKind::Text); 54781ad6265SDimitry Andric 54881ad6265SDimitry Andric return Fragments; 54981ad6265SDimitry Andric } 55081ad6265SDimitry Andric 55181ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface( 55281ad6265SDimitry Andric const ObjCInterfaceDecl *Interface) { 55381ad6265SDimitry Andric DeclarationFragments Fragments; 55481ad6265SDimitry Andric // Build the base of the Objective-C interface declaration. 55581ad6265SDimitry Andric Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) 55681ad6265SDimitry Andric .appendSpace() 55781ad6265SDimitry Andric .append(Interface->getName(), 55881ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 55981ad6265SDimitry Andric 56081ad6265SDimitry Andric // Build the inheritance part of the declaration. 56181ad6265SDimitry Andric if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) { 56281ad6265SDimitry Andric SmallString<128> SuperUSR; 56381ad6265SDimitry Andric index::generateUSRForDecl(SuperClass, SuperUSR); 56481ad6265SDimitry Andric Fragments.append(" : ", DeclarationFragments::FragmentKind::Text) 56581ad6265SDimitry Andric .append(SuperClass->getName(), 566*bdd1243dSDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR, 567*bdd1243dSDimitry Andric SuperClass); 56881ad6265SDimitry Andric } 56981ad6265SDimitry Andric 57081ad6265SDimitry Andric return Fragments; 57181ad6265SDimitry Andric } 57281ad6265SDimitry Andric 57381ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod( 57481ad6265SDimitry Andric const ObjCMethodDecl *Method) { 57581ad6265SDimitry Andric DeclarationFragments Fragments, After; 57681ad6265SDimitry Andric // Build the instance/class method indicator. 57781ad6265SDimitry Andric if (Method->isClassMethod()) 57881ad6265SDimitry Andric Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); 57981ad6265SDimitry Andric else if (Method->isInstanceMethod()) 58081ad6265SDimitry Andric Fragments.append("- ", DeclarationFragments::FragmentKind::Text); 58181ad6265SDimitry Andric 58281ad6265SDimitry Andric // Build the return type. 58381ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text) 58481ad6265SDimitry Andric .append(getFragmentsForType(Method->getReturnType(), 58581ad6265SDimitry Andric Method->getASTContext(), After)) 58681ad6265SDimitry Andric .append(std::move(After)) 58781ad6265SDimitry Andric .append(")", DeclarationFragments::FragmentKind::Text); 58881ad6265SDimitry Andric 58981ad6265SDimitry Andric // Build the selector part. 59081ad6265SDimitry Andric Selector Selector = Method->getSelector(); 59181ad6265SDimitry Andric if (Selector.getNumArgs() == 0) 59281ad6265SDimitry Andric // For Objective-C methods that don't take arguments, the first (and only) 59381ad6265SDimitry Andric // slot of the selector is the method name. 59481ad6265SDimitry Andric Fragments.appendSpace().append( 59581ad6265SDimitry Andric Selector.getNameForSlot(0), 59681ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 59781ad6265SDimitry Andric 59881ad6265SDimitry Andric // For Objective-C methods that take arguments, build the selector slots. 59981ad6265SDimitry Andric for (unsigned i = 0, end = Method->param_size(); i != end; ++i) { 60081ad6265SDimitry Andric // Objective-C method selector parts are considered as identifiers instead 60181ad6265SDimitry Andric // of "external parameters" as in Swift. This is because Objective-C method 60281ad6265SDimitry Andric // symbols are referenced with the entire selector, instead of just the 60381ad6265SDimitry Andric // method name in Swift. 60481ad6265SDimitry Andric SmallString<32> ParamID(Selector.getNameForSlot(i)); 60581ad6265SDimitry Andric ParamID.append(":"); 60681ad6265SDimitry Andric Fragments.appendSpace().append( 60781ad6265SDimitry Andric ParamID, DeclarationFragments::FragmentKind::Identifier); 60881ad6265SDimitry Andric 60981ad6265SDimitry Andric // Build the internal parameter. 61081ad6265SDimitry Andric const ParmVarDecl *Param = Method->getParamDecl(i); 61181ad6265SDimitry Andric Fragments.append(getFragmentsForParam(Param)); 61281ad6265SDimitry Andric } 61381ad6265SDimitry Andric 61481ad6265SDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 61581ad6265SDimitry Andric } 61681ad6265SDimitry Andric 61781ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty( 61881ad6265SDimitry Andric const ObjCPropertyDecl *Property) { 61981ad6265SDimitry Andric DeclarationFragments Fragments, After; 62081ad6265SDimitry Andric 62181ad6265SDimitry Andric // Build the Objective-C property keyword. 62281ad6265SDimitry Andric Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword); 62381ad6265SDimitry Andric 62481ad6265SDimitry Andric const auto Attributes = Property->getPropertyAttributes(); 62581ad6265SDimitry Andric // Build the attributes if there is any associated with the property. 62681ad6265SDimitry Andric if (Attributes != ObjCPropertyAttribute::kind_noattr) { 62781ad6265SDimitry Andric // No leading comma for the first attribute. 62881ad6265SDimitry Andric bool First = true; 62981ad6265SDimitry Andric Fragments.append(" (", DeclarationFragments::FragmentKind::Text); 63081ad6265SDimitry Andric // Helper function to render the attribute. 63181ad6265SDimitry Andric auto RenderAttribute = 63281ad6265SDimitry Andric [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling, 63381ad6265SDimitry Andric StringRef Arg = "", 63481ad6265SDimitry Andric DeclarationFragments::FragmentKind ArgKind = 63581ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier) { 63681ad6265SDimitry Andric // Check if the `Kind` attribute is set for this property. 63781ad6265SDimitry Andric if ((Attributes & Kind) && !Spelling.empty()) { 63881ad6265SDimitry Andric // Add a leading comma if this is not the first attribute rendered. 63981ad6265SDimitry Andric if (!First) 64081ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 64181ad6265SDimitry Andric // Render the spelling of this attribute `Kind` as a keyword. 64281ad6265SDimitry Andric Fragments.append(Spelling, 64381ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword); 64481ad6265SDimitry Andric // If this attribute takes in arguments (e.g. `getter=getterName`), 64581ad6265SDimitry Andric // render the arguments. 64681ad6265SDimitry Andric if (!Arg.empty()) 64781ad6265SDimitry Andric Fragments.append("=", DeclarationFragments::FragmentKind::Text) 64881ad6265SDimitry Andric .append(Arg, ArgKind); 64981ad6265SDimitry Andric First = false; 65081ad6265SDimitry Andric } 65181ad6265SDimitry Andric }; 65281ad6265SDimitry Andric 65381ad6265SDimitry Andric // Go through all possible Objective-C property attributes and render set 65481ad6265SDimitry Andric // ones. 65581ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_class, "class"); 65681ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct"); 65781ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic"); 65881ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic"); 65981ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign"); 66081ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain"); 66181ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong"); 66281ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy"); 66381ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak"); 66481ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained, 66581ad6265SDimitry Andric "unsafe_unretained"); 66681ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite"); 66781ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly"); 66881ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter", 66981ad6265SDimitry Andric Property->getGetterName().getAsString()); 67081ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter", 67181ad6265SDimitry Andric Property->getSetterName().getAsString()); 67281ad6265SDimitry Andric 67381ad6265SDimitry Andric // Render nullability attributes. 67481ad6265SDimitry Andric if (Attributes & ObjCPropertyAttribute::kind_nullability) { 67581ad6265SDimitry Andric QualType Type = Property->getType(); 67681ad6265SDimitry Andric if (const auto Nullability = 67781ad6265SDimitry Andric AttributedType::stripOuterNullability(Type)) { 67881ad6265SDimitry Andric if (!First) 67981ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 68081ad6265SDimitry Andric if (*Nullability == NullabilityKind::Unspecified && 68181ad6265SDimitry Andric (Attributes & ObjCPropertyAttribute::kind_null_resettable)) 68281ad6265SDimitry Andric Fragments.append("null_resettable", 68381ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword); 68481ad6265SDimitry Andric else 68581ad6265SDimitry Andric Fragments.append( 68681ad6265SDimitry Andric getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true), 68781ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword); 68881ad6265SDimitry Andric First = false; 68981ad6265SDimitry Andric } 69081ad6265SDimitry Andric } 69181ad6265SDimitry Andric 69281ad6265SDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 69381ad6265SDimitry Andric } 69481ad6265SDimitry Andric 69581ad6265SDimitry Andric // Build the property type and name, and return the completed fragments. 69681ad6265SDimitry Andric return Fragments.appendSpace() 69781ad6265SDimitry Andric .append(getFragmentsForType(Property->getType(), 69881ad6265SDimitry Andric Property->getASTContext(), After)) 699*bdd1243dSDimitry Andric .appendSpace() 70081ad6265SDimitry Andric .append(Property->getName(), 70181ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier) 70281ad6265SDimitry Andric .append(std::move(After)); 70381ad6265SDimitry Andric } 70481ad6265SDimitry Andric 70581ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol( 70681ad6265SDimitry Andric const ObjCProtocolDecl *Protocol) { 70781ad6265SDimitry Andric DeclarationFragments Fragments; 70881ad6265SDimitry Andric // Build basic protocol declaration. 70981ad6265SDimitry Andric Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword) 71081ad6265SDimitry Andric .appendSpace() 71181ad6265SDimitry Andric .append(Protocol->getName(), 71281ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 71381ad6265SDimitry Andric 71481ad6265SDimitry Andric // If this protocol conforms to other protocols, build the conformance list. 71581ad6265SDimitry Andric if (!Protocol->protocols().empty()) { 71681ad6265SDimitry Andric Fragments.append(" <", DeclarationFragments::FragmentKind::Text); 71781ad6265SDimitry Andric for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin(); 71881ad6265SDimitry Andric It != Protocol->protocol_end(); It++) { 71981ad6265SDimitry Andric // Add a leading comma if this is not the first protocol rendered. 72081ad6265SDimitry Andric if (It != Protocol->protocol_begin()) 72181ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 72281ad6265SDimitry Andric 72381ad6265SDimitry Andric SmallString<128> USR; 72481ad6265SDimitry Andric index::generateUSRForDecl(*It, USR); 72581ad6265SDimitry Andric Fragments.append((*It)->getName(), 726*bdd1243dSDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, USR, 727*bdd1243dSDimitry Andric *It); 72881ad6265SDimitry Andric } 72981ad6265SDimitry Andric Fragments.append(">", DeclarationFragments::FragmentKind::Text); 73081ad6265SDimitry Andric } 73181ad6265SDimitry Andric 73281ad6265SDimitry Andric return Fragments; 73381ad6265SDimitry Andric } 73481ad6265SDimitry Andric 73581ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef( 73681ad6265SDimitry Andric const TypedefNameDecl *Decl) { 73781ad6265SDimitry Andric DeclarationFragments Fragments, After; 73881ad6265SDimitry Andric Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword) 73981ad6265SDimitry Andric .appendSpace() 74081ad6265SDimitry Andric .append(getFragmentsForType(Decl->getUnderlyingType(), 74181ad6265SDimitry Andric Decl->getASTContext(), After)) 74281ad6265SDimitry Andric .append(std::move(After)) 74381ad6265SDimitry Andric .appendSpace() 74481ad6265SDimitry Andric .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier); 74581ad6265SDimitry Andric 74681ad6265SDimitry Andric return Fragments; 74781ad6265SDimitry Andric } 74881ad6265SDimitry Andric 74981ad6265SDimitry Andric template <typename FunctionT> 75081ad6265SDimitry Andric FunctionSignature 75181ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) { 75281ad6265SDimitry Andric FunctionSignature Signature; 75381ad6265SDimitry Andric 75481ad6265SDimitry Andric DeclarationFragments ReturnType, After; 75581ad6265SDimitry Andric ReturnType 75681ad6265SDimitry Andric .append(getFragmentsForType(Function->getReturnType(), 75781ad6265SDimitry Andric Function->getASTContext(), After)) 75881ad6265SDimitry Andric .append(std::move(After)); 75981ad6265SDimitry Andric Signature.setReturnType(ReturnType); 76081ad6265SDimitry Andric 76181ad6265SDimitry Andric for (const auto *Param : Function->parameters()) 76281ad6265SDimitry Andric Signature.addParameter(Param->getName(), getFragmentsForParam(Param)); 76381ad6265SDimitry Andric 76481ad6265SDimitry Andric return Signature; 76581ad6265SDimitry Andric } 76681ad6265SDimitry Andric 76781ad6265SDimitry Andric // Instantiate template for FunctionDecl. 76881ad6265SDimitry Andric template FunctionSignature 76981ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *); 77081ad6265SDimitry Andric 77181ad6265SDimitry Andric // Instantiate template for ObjCMethodDecl. 77281ad6265SDimitry Andric template FunctionSignature 77381ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *); 77481ad6265SDimitry Andric 77581ad6265SDimitry Andric // Subheading of a symbol defaults to its name. 77681ad6265SDimitry Andric DeclarationFragments 77781ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) { 77881ad6265SDimitry Andric DeclarationFragments Fragments; 77981ad6265SDimitry Andric if (!Decl->getName().empty()) 78081ad6265SDimitry Andric Fragments.append(Decl->getName(), 78181ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 78281ad6265SDimitry Andric return Fragments; 78381ad6265SDimitry Andric } 78481ad6265SDimitry Andric 78581ad6265SDimitry Andric // Subheading of an Objective-C method is a `+` or `-` sign indicating whether 78681ad6265SDimitry Andric // it's a class method or an instance method, followed by the selector name. 78781ad6265SDimitry Andric DeclarationFragments 78881ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) { 78981ad6265SDimitry Andric DeclarationFragments Fragments; 79081ad6265SDimitry Andric if (Method->isClassMethod()) 79181ad6265SDimitry Andric Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); 79281ad6265SDimitry Andric else if (Method->isInstanceMethod()) 79381ad6265SDimitry Andric Fragments.append("- ", DeclarationFragments::FragmentKind::Text); 79481ad6265SDimitry Andric 79581ad6265SDimitry Andric return Fragments.append(Method->getNameAsString(), 79681ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 79781ad6265SDimitry Andric } 79881ad6265SDimitry Andric 79981ad6265SDimitry Andric // Subheading of a symbol defaults to its name. 80081ad6265SDimitry Andric DeclarationFragments 80181ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) { 80281ad6265SDimitry Andric DeclarationFragments Fragments; 80381ad6265SDimitry Andric Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); 80481ad6265SDimitry Andric return Fragments; 80581ad6265SDimitry Andric } 806