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" 15*9fc45ca0SDaniel Grumberg #include "TypedefUnderlyingTypeResolver.h" 1689f6b26fSZixu Wang #include "clang/Index/USRGeneration.h" 1789f6b26fSZixu Wang #include "llvm/ADT/StringSwitch.h" 1889f6b26fSZixu Wang 1989f6b26fSZixu Wang using namespace clang::extractapi; 2089f6b26fSZixu Wang using namespace llvm; 2189f6b26fSZixu Wang 2289f6b26fSZixu Wang DeclarationFragments &DeclarationFragments::appendSpace() { 2389f6b26fSZixu Wang if (!Fragments.empty()) { 2489f6b26fSZixu Wang Fragment Last = Fragments.back(); 2589f6b26fSZixu Wang if (Last.Kind == FragmentKind::Text) { 2689f6b26fSZixu Wang // Merge the extra space into the last fragment if the last fragment is 2789f6b26fSZixu Wang // also text. 2889f6b26fSZixu Wang if (Last.Spelling.back() != ' ') { // avoid extra trailing spaces. 2989f6b26fSZixu Wang Last.Spelling.push_back(' '); 3089f6b26fSZixu Wang } 3189f6b26fSZixu Wang } else { 3289f6b26fSZixu Wang append(" ", FragmentKind::Text); 3389f6b26fSZixu Wang } 3489f6b26fSZixu Wang } 3589f6b26fSZixu Wang 3689f6b26fSZixu Wang return *this; 3789f6b26fSZixu Wang } 3889f6b26fSZixu Wang 3989f6b26fSZixu Wang StringRef DeclarationFragments::getFragmentKindString( 4089f6b26fSZixu Wang DeclarationFragments::FragmentKind Kind) { 4189f6b26fSZixu Wang switch (Kind) { 4289f6b26fSZixu Wang case DeclarationFragments::FragmentKind::None: 4389f6b26fSZixu Wang return "none"; 4489f6b26fSZixu Wang case DeclarationFragments::FragmentKind::Keyword: 4589f6b26fSZixu Wang return "keyword"; 4689f6b26fSZixu Wang case DeclarationFragments::FragmentKind::Attribute: 4789f6b26fSZixu Wang return "attribute"; 4889f6b26fSZixu Wang case DeclarationFragments::FragmentKind::NumberLiteral: 4989f6b26fSZixu Wang return "number"; 5089f6b26fSZixu Wang case DeclarationFragments::FragmentKind::StringLiteral: 5189f6b26fSZixu Wang return "string"; 5289f6b26fSZixu Wang case DeclarationFragments::FragmentKind::Identifier: 5389f6b26fSZixu Wang return "identifier"; 5489f6b26fSZixu Wang case DeclarationFragments::FragmentKind::TypeIdentifier: 5589f6b26fSZixu Wang return "typeIdentifier"; 5689f6b26fSZixu Wang case DeclarationFragments::FragmentKind::GenericParameter: 5789f6b26fSZixu Wang return "genericParameter"; 5889f6b26fSZixu Wang case DeclarationFragments::FragmentKind::ExternalParam: 5989f6b26fSZixu Wang return "externalParam"; 6089f6b26fSZixu Wang case DeclarationFragments::FragmentKind::InternalParam: 6189f6b26fSZixu Wang return "internalParam"; 6289f6b26fSZixu Wang case DeclarationFragments::FragmentKind::Text: 6389f6b26fSZixu Wang return "text"; 6489f6b26fSZixu Wang } 6589f6b26fSZixu Wang 6689f6b26fSZixu Wang llvm_unreachable("Unhandled FragmentKind"); 6789f6b26fSZixu Wang } 6889f6b26fSZixu Wang 6989f6b26fSZixu Wang DeclarationFragments::FragmentKind 7089f6b26fSZixu Wang DeclarationFragments::parseFragmentKindFromString(StringRef S) { 7189f6b26fSZixu Wang return llvm::StringSwitch<FragmentKind>(S) 7289f6b26fSZixu Wang .Case("keyword", DeclarationFragments::FragmentKind::Keyword) 7389f6b26fSZixu Wang .Case("attribute", DeclarationFragments::FragmentKind::Attribute) 7489f6b26fSZixu Wang .Case("number", DeclarationFragments::FragmentKind::NumberLiteral) 7589f6b26fSZixu Wang .Case("string", DeclarationFragments::FragmentKind::StringLiteral) 7689f6b26fSZixu Wang .Case("identifier", DeclarationFragments::FragmentKind::Identifier) 7789f6b26fSZixu Wang .Case("typeIdentifier", 7889f6b26fSZixu Wang DeclarationFragments::FragmentKind::TypeIdentifier) 7989f6b26fSZixu Wang .Case("genericParameter", 8089f6b26fSZixu Wang DeclarationFragments::FragmentKind::GenericParameter) 8189f6b26fSZixu Wang .Case("internalParam", DeclarationFragments::FragmentKind::InternalParam) 8289f6b26fSZixu Wang .Case("externalParam", DeclarationFragments::FragmentKind::ExternalParam) 8389f6b26fSZixu Wang .Case("text", DeclarationFragments::FragmentKind::Text) 8489f6b26fSZixu Wang .Default(DeclarationFragments::FragmentKind::None); 8589f6b26fSZixu Wang } 8689f6b26fSZixu Wang 8789f6b26fSZixu Wang // NNS stores C++ nested name specifiers, which are prefixes to qualified names. 8889f6b26fSZixu Wang // Build declaration fragments for NNS recursively so that we have the USR for 8989f6b26fSZixu Wang // every part in a qualified name, and also leaves the actual underlying type 9089f6b26fSZixu Wang // cleaner for its own fragment. 9189f6b26fSZixu Wang DeclarationFragments 9289f6b26fSZixu Wang DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS, 9389f6b26fSZixu Wang ASTContext &Context, 9489f6b26fSZixu Wang DeclarationFragments &After) { 9589f6b26fSZixu Wang DeclarationFragments Fragments; 9689f6b26fSZixu Wang if (NNS->getPrefix()) 9789f6b26fSZixu Wang Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After)); 9889f6b26fSZixu Wang 9989f6b26fSZixu Wang switch (NNS->getKind()) { 10089f6b26fSZixu Wang case NestedNameSpecifier::Identifier: 10189f6b26fSZixu Wang Fragments.append(NNS->getAsIdentifier()->getName(), 10289f6b26fSZixu Wang DeclarationFragments::FragmentKind::Identifier); 10389f6b26fSZixu Wang break; 10489f6b26fSZixu Wang 10589f6b26fSZixu Wang case NestedNameSpecifier::Namespace: { 10689f6b26fSZixu Wang const NamespaceDecl *NS = NNS->getAsNamespace(); 10789f6b26fSZixu Wang if (NS->isAnonymousNamespace()) 10889f6b26fSZixu Wang return Fragments; 10989f6b26fSZixu Wang SmallString<128> USR; 11089f6b26fSZixu Wang index::generateUSRForDecl(NS, USR); 11189f6b26fSZixu Wang Fragments.append(NS->getName(), 11289f6b26fSZixu Wang DeclarationFragments::FragmentKind::Identifier, USR); 11389f6b26fSZixu Wang break; 11489f6b26fSZixu Wang } 11589f6b26fSZixu Wang 11689f6b26fSZixu Wang case NestedNameSpecifier::NamespaceAlias: { 11789f6b26fSZixu Wang const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias(); 11889f6b26fSZixu Wang SmallString<128> USR; 11989f6b26fSZixu Wang index::generateUSRForDecl(Alias, USR); 12089f6b26fSZixu Wang Fragments.append(Alias->getName(), 12189f6b26fSZixu Wang DeclarationFragments::FragmentKind::Identifier, USR); 12289f6b26fSZixu Wang break; 12389f6b26fSZixu Wang } 12489f6b26fSZixu Wang 12589f6b26fSZixu Wang case NestedNameSpecifier::Global: 12689f6b26fSZixu Wang // The global specifier `::` at the beginning. No stored value. 12789f6b26fSZixu Wang break; 12889f6b26fSZixu Wang 12989f6b26fSZixu Wang case NestedNameSpecifier::Super: 13089f6b26fSZixu Wang // Microsoft's `__super` specifier. 13189f6b26fSZixu Wang Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword); 13289f6b26fSZixu Wang break; 13389f6b26fSZixu Wang 13489f6b26fSZixu Wang case NestedNameSpecifier::TypeSpecWithTemplate: 13589f6b26fSZixu Wang // A type prefixed by the `template` keyword. 13689f6b26fSZixu Wang Fragments.append("template", DeclarationFragments::FragmentKind::Keyword); 13789f6b26fSZixu Wang Fragments.appendSpace(); 13889f6b26fSZixu Wang // Fallthrough after adding the keyword to handle the actual type. 13989f6b26fSZixu Wang LLVM_FALLTHROUGH; 14089f6b26fSZixu Wang 14189f6b26fSZixu Wang case NestedNameSpecifier::TypeSpec: { 14289f6b26fSZixu Wang const Type *T = NNS->getAsType(); 14389f6b26fSZixu Wang // FIXME: Handle C++ template specialization type 14489f6b26fSZixu Wang Fragments.append(getFragmentsForType(T, Context, After)); 14589f6b26fSZixu Wang break; 14689f6b26fSZixu Wang } 14789f6b26fSZixu Wang } 14889f6b26fSZixu Wang 14989f6b26fSZixu Wang // Add the separator text `::` for this segment. 15089f6b26fSZixu Wang return Fragments.append("::", DeclarationFragments::FragmentKind::Text); 15189f6b26fSZixu Wang } 15289f6b26fSZixu Wang 15389f6b26fSZixu Wang // Recursively build the declaration fragments for an underlying `Type` with 15489f6b26fSZixu Wang // qualifiers removed. 15589f6b26fSZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( 15689f6b26fSZixu Wang const Type *T, ASTContext &Context, DeclarationFragments &After) { 15789f6b26fSZixu Wang assert(T && "invalid type"); 15889f6b26fSZixu Wang 15989f6b26fSZixu Wang DeclarationFragments Fragments; 16089f6b26fSZixu Wang 16189f6b26fSZixu Wang // Declaration fragments of a pointer type is the declaration fragments of 16289f6b26fSZixu Wang // the pointee type followed by a `*`, except for Objective-C `id` and `Class` 16389f6b26fSZixu Wang // pointers, where we do not spell out the `*`. 16489f6b26fSZixu Wang if (T->isPointerType() || 16589f6b26fSZixu Wang (T->isObjCObjectPointerType() && 16689f6b26fSZixu Wang !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType())) { 16789f6b26fSZixu Wang return Fragments 16889f6b26fSZixu Wang .append(getFragmentsForType(T->getPointeeType(), Context, After)) 16989f6b26fSZixu Wang .append(" *", DeclarationFragments::FragmentKind::Text); 17089f6b26fSZixu Wang } 17189f6b26fSZixu Wang 17289f6b26fSZixu Wang // Declaration fragments of a lvalue reference type is the declaration 17389f6b26fSZixu Wang // fragments of the underlying type followed by a `&`. 17489f6b26fSZixu Wang if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T)) 17589f6b26fSZixu Wang return Fragments 17689f6b26fSZixu Wang .append( 17789f6b26fSZixu Wang getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After)) 17889f6b26fSZixu Wang .append(" &", DeclarationFragments::FragmentKind::Text); 17989f6b26fSZixu Wang 18089f6b26fSZixu Wang // Declaration fragments of a rvalue reference type is the declaration 18189f6b26fSZixu Wang // fragments of the underlying type followed by a `&&`. 18289f6b26fSZixu Wang if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T)) 18389f6b26fSZixu Wang return Fragments 18489f6b26fSZixu Wang .append( 18589f6b26fSZixu Wang getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After)) 18689f6b26fSZixu Wang .append(" &&", DeclarationFragments::FragmentKind::Text); 18789f6b26fSZixu Wang 18889f6b26fSZixu Wang // Declaration fragments of an array-typed variable have two parts: 18989f6b26fSZixu Wang // 1. the element type of the array that appears before the variable name; 19089f6b26fSZixu Wang // 2. array brackets `[(0-9)?]` that appear after the variable name. 19189f6b26fSZixu Wang if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) { 19289f6b26fSZixu Wang // Build the "after" part first because the inner element type might also 19389f6b26fSZixu Wang // be an array-type. For example `int matrix[3][4]` which has a type of 19489f6b26fSZixu Wang // "(array 3 of (array 4 of ints))." 19589f6b26fSZixu Wang // Push the array size part first to make sure they are in the right order. 19689f6b26fSZixu Wang After.append("[", DeclarationFragments::FragmentKind::Text); 19789f6b26fSZixu Wang 19889f6b26fSZixu Wang switch (AT->getSizeModifier()) { 19989f6b26fSZixu Wang case ArrayType::Normal: 20089f6b26fSZixu Wang break; 20189f6b26fSZixu Wang case ArrayType::Static: 20289f6b26fSZixu Wang Fragments.append("static", DeclarationFragments::FragmentKind::Keyword); 20389f6b26fSZixu Wang break; 20489f6b26fSZixu Wang case ArrayType::Star: 20589f6b26fSZixu Wang Fragments.append("*", DeclarationFragments::FragmentKind::Text); 20689f6b26fSZixu Wang break; 20789f6b26fSZixu Wang } 20889f6b26fSZixu Wang 20989f6b26fSZixu Wang if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) { 21089f6b26fSZixu Wang // FIXME: right now this would evaluate any expressions/macros written in 21189f6b26fSZixu Wang // the original source to concrete values. For example 21289f6b26fSZixu Wang // `int nums[MAX]` -> `int nums[100]` 21389f6b26fSZixu Wang // `char *str[5 + 1]` -> `char *str[6]` 21489f6b26fSZixu Wang SmallString<128> Size; 21589f6b26fSZixu Wang CAT->getSize().toStringUnsigned(Size); 21689f6b26fSZixu Wang After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral); 21789f6b26fSZixu Wang } 21889f6b26fSZixu Wang 21989f6b26fSZixu Wang After.append("]", DeclarationFragments::FragmentKind::Text); 22089f6b26fSZixu Wang 22189f6b26fSZixu Wang return Fragments.append( 22289f6b26fSZixu Wang getFragmentsForType(AT->getElementType(), Context, After)); 22389f6b26fSZixu Wang } 22489f6b26fSZixu Wang 22589f6b26fSZixu Wang // An ElaboratedType is a sugar for types that are referred to using an 22689f6b26fSZixu Wang // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a 22789f6b26fSZixu Wang // qualified name, e.g., `N::M::type`, or both. 22889f6b26fSZixu Wang if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) { 22989f6b26fSZixu Wang ElaboratedTypeKeyword Keyword = ET->getKeyword(); 23089f6b26fSZixu Wang if (Keyword != ETK_None) { 23189f6b26fSZixu Wang Fragments 23289f6b26fSZixu Wang .append(ElaboratedType::getKeywordName(Keyword), 23389f6b26fSZixu Wang DeclarationFragments::FragmentKind::Keyword) 23489f6b26fSZixu Wang .appendSpace(); 23589f6b26fSZixu Wang } 23689f6b26fSZixu Wang 23789f6b26fSZixu Wang if (const NestedNameSpecifier *NNS = ET->getQualifier()) 23889f6b26fSZixu Wang Fragments.append(getFragmentsForNNS(NNS, Context, After)); 23989f6b26fSZixu Wang 24089f6b26fSZixu Wang // After handling the elaborated keyword or qualified name, build 24189f6b26fSZixu Wang // declaration fragments for the desugared underlying type. 24289f6b26fSZixu Wang return Fragments.append(getFragmentsForType(ET->desugar(), Context, After)); 24389f6b26fSZixu Wang } 24489f6b26fSZixu Wang 24589f6b26fSZixu Wang // Everything we care about has been handled now, reduce to the canonical 24689f6b26fSZixu Wang // unqualified base type. 24789f6b26fSZixu Wang QualType Base = T->getCanonicalTypeUnqualified(); 24889f6b26fSZixu Wang 2499b36e126SZixu Wang // Render Objective-C `id`/`instancetype` as keywords. 2509b36e126SZixu Wang if (T->isObjCIdType()) 2519b36e126SZixu Wang return Fragments.append(Base.getAsString(), 2529b36e126SZixu Wang DeclarationFragments::FragmentKind::Keyword); 2539b36e126SZixu Wang 254*9fc45ca0SDaniel Grumberg // If the type is a typedefed type, get the underlying TypedefNameDecl for a 255*9fc45ca0SDaniel Grumberg // direct reference to the typedef instead of the wrapped type. 256*9fc45ca0SDaniel Grumberg if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) { 257*9fc45ca0SDaniel Grumberg const TypedefNameDecl *Decl = TypedefTy->getDecl(); 258*9fc45ca0SDaniel Grumberg std::string USR = 259*9fc45ca0SDaniel Grumberg TypedefUnderlyingTypeResolver(Context).getUSRForType(QualType(T, 0)); 260*9fc45ca0SDaniel Grumberg return Fragments.append(Decl->getName(), 261*9fc45ca0SDaniel Grumberg DeclarationFragments::FragmentKind::TypeIdentifier, 262*9fc45ca0SDaniel Grumberg USR); 263*9fc45ca0SDaniel Grumberg } 264*9fc45ca0SDaniel Grumberg 265*9fc45ca0SDaniel Grumberg // If the base type is a TagType (struct/interface/union/class/enum), let's 266*9fc45ca0SDaniel Grumberg // get the underlying Decl for better names and USRs. 267*9fc45ca0SDaniel Grumberg if (const TagType *TagTy = dyn_cast<TagType>(Base)) { 268*9fc45ca0SDaniel Grumberg const TagDecl *Decl = TagTy->getDecl(); 269*9fc45ca0SDaniel Grumberg // Anonymous decl, skip this fragment. 270*9fc45ca0SDaniel Grumberg if (Decl->getName().empty()) 271*9fc45ca0SDaniel Grumberg return Fragments; 272*9fc45ca0SDaniel Grumberg SmallString<128> TagUSR; 273*9fc45ca0SDaniel Grumberg clang::index::generateUSRForDecl(Decl, TagUSR); 274*9fc45ca0SDaniel Grumberg return Fragments.append(Decl->getName(), 275*9fc45ca0SDaniel Grumberg DeclarationFragments::FragmentKind::TypeIdentifier, 276*9fc45ca0SDaniel Grumberg TagUSR); 277*9fc45ca0SDaniel Grumberg } 278*9fc45ca0SDaniel Grumberg 2799b36e126SZixu Wang // If the base type is an ObjCInterfaceType, use the underlying 2809b36e126SZixu Wang // ObjCInterfaceDecl for the true USR. 2819b36e126SZixu Wang if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) { 2829b36e126SZixu Wang const auto *Decl = ObjCIT->getDecl(); 2839b36e126SZixu Wang SmallString<128> USR; 2849b36e126SZixu Wang index::generateUSRForDecl(Decl, USR); 2859b36e126SZixu Wang return Fragments.append(Decl->getName(), 2869b36e126SZixu Wang DeclarationFragments::FragmentKind::TypeIdentifier, 2879b36e126SZixu Wang USR); 2889b36e126SZixu Wang } 2899b36e126SZixu Wang 29089f6b26fSZixu Wang // Default fragment builder for other kinds of types (BuiltinType etc.) 29189f6b26fSZixu Wang SmallString<128> USR; 29289f6b26fSZixu Wang clang::index::generateUSRForType(Base, Context, USR); 29389f6b26fSZixu Wang Fragments.append(Base.getAsString(), 29489f6b26fSZixu Wang DeclarationFragments::FragmentKind::TypeIdentifier, USR); 29589f6b26fSZixu Wang 29689f6b26fSZixu Wang return Fragments; 29789f6b26fSZixu Wang } 29889f6b26fSZixu Wang 29989f6b26fSZixu Wang DeclarationFragments 30089f6b26fSZixu Wang DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) { 30189f6b26fSZixu Wang DeclarationFragments Fragments; 30289f6b26fSZixu Wang if (Quals.hasConst()) 30389f6b26fSZixu Wang Fragments.append("const", DeclarationFragments::FragmentKind::Keyword); 30489f6b26fSZixu Wang if (Quals.hasVolatile()) 30589f6b26fSZixu Wang Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword); 30689f6b26fSZixu Wang if (Quals.hasRestrict()) 30789f6b26fSZixu Wang Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword); 30889f6b26fSZixu Wang 30989f6b26fSZixu Wang return Fragments; 31089f6b26fSZixu Wang } 31189f6b26fSZixu Wang 31289f6b26fSZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( 31389f6b26fSZixu Wang const QualType QT, ASTContext &Context, DeclarationFragments &After) { 31489f6b26fSZixu Wang assert(!QT.isNull() && "invalid type"); 31589f6b26fSZixu Wang 31689f6b26fSZixu Wang if (const ParenType *PT = dyn_cast<ParenType>(QT)) { 31789f6b26fSZixu Wang After.append(")", DeclarationFragments::FragmentKind::Text); 31889f6b26fSZixu Wang return getFragmentsForType(PT->getInnerType(), Context, After) 31989f6b26fSZixu Wang .append("(", DeclarationFragments::FragmentKind::Text); 32089f6b26fSZixu Wang } 32189f6b26fSZixu Wang 32289f6b26fSZixu Wang const SplitQualType SQT = QT.split(); 32389f6b26fSZixu Wang DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals), 32489f6b26fSZixu Wang TypeFragments = 32589f6b26fSZixu Wang getFragmentsForType(SQT.Ty, Context, After); 32689f6b26fSZixu Wang if (QualsFragments.getFragments().empty()) 32789f6b26fSZixu Wang return TypeFragments; 32889f6b26fSZixu Wang 32989f6b26fSZixu Wang // Use east qualifier for pointer types 33089f6b26fSZixu Wang // For example: 33189f6b26fSZixu Wang // ``` 33289f6b26fSZixu Wang // int * const 33389f6b26fSZixu Wang // ^---- ^---- 33489f6b26fSZixu Wang // type qualifier 33589f6b26fSZixu Wang // ^----------------- 33689f6b26fSZixu Wang // const pointer to int 33789f6b26fSZixu Wang // ``` 33889f6b26fSZixu Wang // should not be reconstructed as 33989f6b26fSZixu Wang // ``` 34089f6b26fSZixu Wang // const int * 34189f6b26fSZixu Wang // ^---- ^-- 34289f6b26fSZixu Wang // qualifier type 34389f6b26fSZixu Wang // ^---------------- ^ 34489f6b26fSZixu Wang // pointer to const int 34589f6b26fSZixu Wang // ``` 34689f6b26fSZixu Wang if (SQT.Ty->isAnyPointerType()) 34789f6b26fSZixu Wang return TypeFragments.appendSpace().append(std::move(QualsFragments)); 34889f6b26fSZixu Wang 34989f6b26fSZixu Wang return QualsFragments.appendSpace().append(std::move(TypeFragments)); 35089f6b26fSZixu Wang } 35189f6b26fSZixu Wang 35289f6b26fSZixu Wang DeclarationFragments 35389f6b26fSZixu Wang DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) { 35489f6b26fSZixu Wang DeclarationFragments Fragments; 35589f6b26fSZixu Wang StorageClass SC = Var->getStorageClass(); 35689f6b26fSZixu Wang if (SC != SC_None) 35789f6b26fSZixu Wang Fragments 35889f6b26fSZixu Wang .append(VarDecl::getStorageClassSpecifierString(SC), 35989f6b26fSZixu Wang DeclarationFragments::FragmentKind::Keyword) 36089f6b26fSZixu Wang .appendSpace(); 36189f6b26fSZixu Wang QualType T = 36289f6b26fSZixu Wang Var->getTypeSourceInfo() 36389f6b26fSZixu Wang ? Var->getTypeSourceInfo()->getType() 36489f6b26fSZixu Wang : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType()); 36589f6b26fSZixu Wang 36689f6b26fSZixu Wang // Capture potential fragments that needs to be placed after the variable name 36789f6b26fSZixu Wang // ``` 36889f6b26fSZixu Wang // int nums[5]; 36989f6b26fSZixu Wang // char (*ptr_to_array)[6]; 37089f6b26fSZixu Wang // ``` 37189f6b26fSZixu Wang DeclarationFragments After; 37289f6b26fSZixu Wang return Fragments.append(getFragmentsForType(T, Var->getASTContext(), After)) 37389f6b26fSZixu Wang .appendSpace() 37489f6b26fSZixu Wang .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) 37589f6b26fSZixu Wang .append(std::move(After)); 37689f6b26fSZixu Wang } 37789f6b26fSZixu Wang 37889f6b26fSZixu Wang DeclarationFragments 37989f6b26fSZixu Wang DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) { 38089f6b26fSZixu Wang DeclarationFragments Fragments, After; 38189f6b26fSZixu Wang 38289f6b26fSZixu Wang QualType T = Param->getTypeSourceInfo() 38389f6b26fSZixu Wang ? Param->getTypeSourceInfo()->getType() 38489f6b26fSZixu Wang : Param->getASTContext().getUnqualifiedObjCPointerType( 38589f6b26fSZixu Wang Param->getType()); 38689f6b26fSZixu Wang 38789f6b26fSZixu Wang DeclarationFragments TypeFragments = 38889f6b26fSZixu Wang getFragmentsForType(T, Param->getASTContext(), After); 38989f6b26fSZixu Wang 39089f6b26fSZixu Wang if (Param->isObjCMethodParameter()) 39189f6b26fSZixu Wang Fragments.append("(", DeclarationFragments::FragmentKind::Text) 39289f6b26fSZixu Wang .append(std::move(TypeFragments)) 39389f6b26fSZixu Wang .append(")", DeclarationFragments::FragmentKind::Text); 39489f6b26fSZixu Wang else 39589f6b26fSZixu Wang Fragments.append(std::move(TypeFragments)).appendSpace(); 39689f6b26fSZixu Wang 39789f6b26fSZixu Wang return Fragments 39889f6b26fSZixu Wang .append(Param->getName(), 39989f6b26fSZixu Wang DeclarationFragments::FragmentKind::InternalParam) 40089f6b26fSZixu Wang .append(std::move(After)); 40189f6b26fSZixu Wang } 40289f6b26fSZixu Wang 40389f6b26fSZixu Wang DeclarationFragments 40489f6b26fSZixu Wang DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) { 40589f6b26fSZixu Wang DeclarationFragments Fragments; 40689f6b26fSZixu Wang // FIXME: Handle template specialization 40789f6b26fSZixu Wang switch (Func->getStorageClass()) { 40889f6b26fSZixu Wang case SC_None: 40989f6b26fSZixu Wang case SC_PrivateExtern: 41089f6b26fSZixu Wang break; 41189f6b26fSZixu Wang case SC_Extern: 41289f6b26fSZixu Wang Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword) 41389f6b26fSZixu Wang .appendSpace(); 41489f6b26fSZixu Wang break; 41589f6b26fSZixu Wang case SC_Static: 41689f6b26fSZixu Wang Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) 41789f6b26fSZixu Wang .appendSpace(); 41889f6b26fSZixu Wang break; 41989f6b26fSZixu Wang case SC_Auto: 42089f6b26fSZixu Wang case SC_Register: 42189f6b26fSZixu Wang llvm_unreachable("invalid for functions"); 42289f6b26fSZixu Wang } 42389f6b26fSZixu Wang // FIXME: Handle C++ function specifiers: constexpr, consteval, explicit, etc. 42489f6b26fSZixu Wang 42589f6b26fSZixu Wang // FIXME: Is `after` actually needed here? 42689f6b26fSZixu Wang DeclarationFragments After; 42789f6b26fSZixu Wang Fragments 42889f6b26fSZixu Wang .append(getFragmentsForType(Func->getReturnType(), Func->getASTContext(), 42989f6b26fSZixu Wang After)) 43089f6b26fSZixu Wang .appendSpace() 43189f6b26fSZixu Wang .append(Func->getName(), DeclarationFragments::FragmentKind::Identifier) 43289f6b26fSZixu Wang .append(std::move(After)); 43389f6b26fSZixu Wang 43489f6b26fSZixu Wang Fragments.append("(", DeclarationFragments::FragmentKind::Text); 43589f6b26fSZixu Wang for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) { 43689f6b26fSZixu Wang if (i) 43789f6b26fSZixu Wang Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 43889f6b26fSZixu Wang Fragments.append(getFragmentsForParam(Func->getParamDecl(i))); 43989f6b26fSZixu Wang } 44089f6b26fSZixu Wang Fragments.append(")", DeclarationFragments::FragmentKind::Text); 44189f6b26fSZixu Wang 44289f6b26fSZixu Wang // FIXME: Handle exception specifiers: throw, noexcept 44389f6b26fSZixu Wang return Fragments; 44489f6b26fSZixu Wang } 44589f6b26fSZixu Wang 44671b4c226SZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant( 44771b4c226SZixu Wang const EnumConstantDecl *EnumConstDecl) { 44871b4c226SZixu Wang DeclarationFragments Fragments; 44971b4c226SZixu Wang return Fragments.append(EnumConstDecl->getName(), 45071b4c226SZixu Wang DeclarationFragments::FragmentKind::Identifier); 45171b4c226SZixu Wang } 45271b4c226SZixu Wang 45371b4c226SZixu Wang DeclarationFragments 45471b4c226SZixu Wang DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) { 455*9fc45ca0SDaniel Grumberg if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl()) 456*9fc45ca0SDaniel Grumberg return getFragmentsForTypedef(TypedefNameDecl); 45771b4c226SZixu Wang 45871b4c226SZixu Wang DeclarationFragments Fragments, After; 45971b4c226SZixu Wang Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword); 46071b4c226SZixu Wang 46171b4c226SZixu Wang if (!EnumDecl->getName().empty()) 46271b4c226SZixu Wang Fragments.appendSpace().append( 46371b4c226SZixu Wang EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier); 46471b4c226SZixu Wang 46571b4c226SZixu Wang QualType IntegerType = EnumDecl->getIntegerType(); 46671b4c226SZixu Wang if (!IntegerType.isNull()) 46771b4c226SZixu Wang Fragments.append(": ", DeclarationFragments::FragmentKind::Text) 46871b4c226SZixu Wang .append( 46971b4c226SZixu Wang getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After)) 47071b4c226SZixu Wang .append(std::move(After)); 47171b4c226SZixu Wang 47271b4c226SZixu Wang return Fragments; 47371b4c226SZixu Wang } 47471b4c226SZixu Wang 4755bb5704cSZixu Wang DeclarationFragments 4765bb5704cSZixu Wang DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) { 4775bb5704cSZixu Wang DeclarationFragments After; 4785bb5704cSZixu Wang return getFragmentsForType(Field->getType(), Field->getASTContext(), After) 4795bb5704cSZixu Wang .appendSpace() 4805bb5704cSZixu Wang .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier) 4815bb5704cSZixu Wang .append(std::move(After)); 4825bb5704cSZixu Wang } 4835bb5704cSZixu Wang 4845bb5704cSZixu Wang DeclarationFragments 4855bb5704cSZixu Wang DeclarationFragmentsBuilder::getFragmentsForStruct(const RecordDecl *Record) { 486*9fc45ca0SDaniel Grumberg if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl()) 487*9fc45ca0SDaniel Grumberg return getFragmentsForTypedef(TypedefNameDecl); 4885bb5704cSZixu Wang 4895bb5704cSZixu Wang DeclarationFragments Fragments; 4905bb5704cSZixu Wang Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword); 4915bb5704cSZixu Wang 4925bb5704cSZixu Wang if (!Record->getName().empty()) 4935bb5704cSZixu Wang Fragments.appendSpace().append( 4945bb5704cSZixu Wang Record->getName(), DeclarationFragments::FragmentKind::Identifier); 495529a0570SDaniel Grumberg return Fragments; 496529a0570SDaniel Grumberg } 4975bb5704cSZixu Wang 498529a0570SDaniel Grumberg DeclarationFragments 499529a0570SDaniel Grumberg DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name, 500529a0570SDaniel Grumberg const MacroDirective *MD) { 501529a0570SDaniel Grumberg DeclarationFragments Fragments; 502529a0570SDaniel Grumberg Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword) 503529a0570SDaniel Grumberg .appendSpace(); 504529a0570SDaniel Grumberg Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); 505529a0570SDaniel Grumberg 506529a0570SDaniel Grumberg auto *MI = MD->getMacroInfo(); 507529a0570SDaniel Grumberg 508529a0570SDaniel Grumberg if (MI->isFunctionLike()) { 509529a0570SDaniel Grumberg Fragments.append("(", DeclarationFragments::FragmentKind::Text); 510529a0570SDaniel Grumberg unsigned numParameters = MI->getNumParams(); 511529a0570SDaniel Grumberg if (MI->isC99Varargs()) 512529a0570SDaniel Grumberg --numParameters; 513529a0570SDaniel Grumberg for (unsigned i = 0; i < numParameters; ++i) { 514529a0570SDaniel Grumberg if (i) 515529a0570SDaniel Grumberg Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 516529a0570SDaniel Grumberg Fragments.append(MI->params()[i]->getName(), 517529a0570SDaniel Grumberg DeclarationFragments::FragmentKind::InternalParam); 518529a0570SDaniel Grumberg } 519529a0570SDaniel Grumberg if (MI->isVariadic()) { 520529a0570SDaniel Grumberg if (numParameters && MI->isC99Varargs()) 521529a0570SDaniel Grumberg Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 522529a0570SDaniel Grumberg Fragments.append("...", DeclarationFragments::FragmentKind::Text); 523529a0570SDaniel Grumberg } 524529a0570SDaniel Grumberg Fragments.append(")", DeclarationFragments::FragmentKind::Text); 525529a0570SDaniel Grumberg } 5265bb5704cSZixu Wang return Fragments; 5275bb5704cSZixu Wang } 5285bb5704cSZixu Wang 5299b36e126SZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface( 5309b36e126SZixu Wang const ObjCInterfaceDecl *Interface) { 5319b36e126SZixu Wang DeclarationFragments Fragments; 5329b36e126SZixu Wang // Build the base of the Objective-C interface declaration. 5339b36e126SZixu Wang Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) 5349b36e126SZixu Wang .appendSpace() 5359b36e126SZixu Wang .append(Interface->getName(), 5369b36e126SZixu Wang DeclarationFragments::FragmentKind::Identifier); 53789f6b26fSZixu Wang 5389b36e126SZixu Wang // Build the inheritance part of the declaration. 5399b36e126SZixu Wang if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) { 5409b36e126SZixu Wang SmallString<128> SuperUSR; 5419b36e126SZixu Wang index::generateUSRForDecl(SuperClass, SuperUSR); 5429b36e126SZixu Wang Fragments.append(" : ", DeclarationFragments::FragmentKind::Text) 5439b36e126SZixu Wang .append(SuperClass->getName(), 5449b36e126SZixu Wang DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR); 54589f6b26fSZixu Wang } 54689f6b26fSZixu Wang 5479b36e126SZixu Wang return Fragments; 5489b36e126SZixu Wang } 54989f6b26fSZixu Wang 5509b36e126SZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod( 5519b36e126SZixu Wang const ObjCMethodDecl *Method) { 5529b36e126SZixu Wang DeclarationFragments Fragments, After; 5539b36e126SZixu Wang // Build the instance/class method indicator. 5549b36e126SZixu Wang if (Method->isClassMethod()) 5559b36e126SZixu Wang Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); 5569b36e126SZixu Wang else if (Method->isInstanceMethod()) 5579b36e126SZixu Wang Fragments.append("- ", DeclarationFragments::FragmentKind::Text); 5589b36e126SZixu Wang 5599b36e126SZixu Wang // Build the return type. 5609b36e126SZixu Wang Fragments.append("(", DeclarationFragments::FragmentKind::Text) 5619b36e126SZixu Wang .append(getFragmentsForType(Method->getReturnType(), 5629b36e126SZixu Wang Method->getASTContext(), After)) 5639b36e126SZixu Wang .append(std::move(After)) 5649b36e126SZixu Wang .append(")", DeclarationFragments::FragmentKind::Text); 5659b36e126SZixu Wang 5669b36e126SZixu Wang // Build the selector part. 5679b36e126SZixu Wang Selector Selector = Method->getSelector(); 5689b36e126SZixu Wang if (Selector.getNumArgs() == 0) 5699b36e126SZixu Wang // For Objective-C methods that don't take arguments, the first (and only) 5709b36e126SZixu Wang // slot of the selector is the method name. 5719b36e126SZixu Wang Fragments.appendSpace().append( 5729b36e126SZixu Wang Selector.getNameForSlot(0), 5739b36e126SZixu Wang DeclarationFragments::FragmentKind::Identifier); 5749b36e126SZixu Wang 5759b36e126SZixu Wang // For Objective-C methods that take arguments, build the selector slots. 5769b36e126SZixu Wang for (unsigned i = 0, end = Method->param_size(); i != end; ++i) { 5779b36e126SZixu Wang Fragments.appendSpace() 5789b36e126SZixu Wang .append(Selector.getNameForSlot(i), 5799b36e126SZixu Wang // The first slot is the name of the method, record as an 5809b36e126SZixu Wang // identifier, otherwise as exteranl parameters. 5819b36e126SZixu Wang i == 0 ? DeclarationFragments::FragmentKind::Identifier 5829b36e126SZixu Wang : DeclarationFragments::FragmentKind::ExternalParam) 5839b36e126SZixu Wang .append(":", DeclarationFragments::FragmentKind::Text); 5849b36e126SZixu Wang 5859b36e126SZixu Wang // Build the internal parameter. 5869b36e126SZixu Wang const ParmVarDecl *Param = Method->getParamDecl(i); 5879b36e126SZixu Wang Fragments.append(getFragmentsForParam(Param)); 5889b36e126SZixu Wang } 5899b36e126SZixu Wang 5909b36e126SZixu Wang return Fragments; 5919b36e126SZixu Wang } 5929b36e126SZixu Wang 5939b36e126SZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty( 5949b36e126SZixu Wang const ObjCPropertyDecl *Property) { 5959b36e126SZixu Wang DeclarationFragments Fragments, After; 5969b36e126SZixu Wang 5979b36e126SZixu Wang // Build the Objective-C property keyword. 5989b36e126SZixu Wang Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword); 5999b36e126SZixu Wang 6009b36e126SZixu Wang const auto Attributes = Property->getPropertyAttributes(); 6019b36e126SZixu Wang // Build the attributes if there is any associated with the property. 6029b36e126SZixu Wang if (Attributes != ObjCPropertyAttribute::kind_noattr) { 6039b36e126SZixu Wang // No leading comma for the first attribute. 6049b36e126SZixu Wang bool First = true; 6059b36e126SZixu Wang Fragments.append(" (", DeclarationFragments::FragmentKind::Text); 6069b36e126SZixu Wang // Helper function to render the attribute. 6079b36e126SZixu Wang auto RenderAttribute = 6089b36e126SZixu Wang [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling, 6099b36e126SZixu Wang StringRef Arg = "", 6109b36e126SZixu Wang DeclarationFragments::FragmentKind ArgKind = 6119b36e126SZixu Wang DeclarationFragments::FragmentKind::Identifier) { 6129b36e126SZixu Wang // Check if the `Kind` attribute is set for this property. 6139b36e126SZixu Wang if ((Attributes & Kind) && !Spelling.empty()) { 6149b36e126SZixu Wang // Add a leading comma if this is not the first attribute rendered. 6159b36e126SZixu Wang if (!First) 6169b36e126SZixu Wang Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 6179b36e126SZixu Wang // Render the spelling of this attribute `Kind` as a keyword. 6189b36e126SZixu Wang Fragments.append(Spelling, 6199b36e126SZixu Wang DeclarationFragments::FragmentKind::Keyword); 6209b36e126SZixu Wang // If this attribute takes in arguments (e.g. `getter=getterName`), 6219b36e126SZixu Wang // render the arguments. 6229b36e126SZixu Wang if (!Arg.empty()) 6239b36e126SZixu Wang Fragments.append("=", DeclarationFragments::FragmentKind::Text) 6249b36e126SZixu Wang .append(Arg, ArgKind); 6259b36e126SZixu Wang First = false; 6269b36e126SZixu Wang } 6279b36e126SZixu Wang }; 6289b36e126SZixu Wang 6299b36e126SZixu Wang // Go through all possible Objective-C property attributes and render set 6309b36e126SZixu Wang // ones. 6319b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_class, "class"); 6329b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct"); 6339b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic"); 6349b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic"); 6359b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign"); 6369b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain"); 6379b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong"); 6389b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy"); 6399b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak"); 6409b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained, 6419b36e126SZixu Wang "unsafe_unretained"); 6429b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite"); 6439b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly"); 6449b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter", 6459b36e126SZixu Wang Property->getGetterName().getAsString()); 6469b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter", 6479b36e126SZixu Wang Property->getSetterName().getAsString()); 6489b36e126SZixu Wang 6499b36e126SZixu Wang // Render nullability attributes. 6509b36e126SZixu Wang if (Attributes & ObjCPropertyAttribute::kind_nullability) { 6519b36e126SZixu Wang QualType Type = Property->getType(); 6529b36e126SZixu Wang if (const auto Nullability = 6539b36e126SZixu Wang AttributedType::stripOuterNullability(Type)) { 6549b36e126SZixu Wang if (!First) 6559b36e126SZixu Wang Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 6569b36e126SZixu Wang if (*Nullability == NullabilityKind::Unspecified && 6579b36e126SZixu Wang (Attributes & ObjCPropertyAttribute::kind_null_resettable)) 6589b36e126SZixu Wang Fragments.append("null_resettable", 6599b36e126SZixu Wang DeclarationFragments::FragmentKind::Keyword); 6609b36e126SZixu Wang else 6619b36e126SZixu Wang Fragments.append( 6629b36e126SZixu Wang getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true), 6639b36e126SZixu Wang DeclarationFragments::FragmentKind::Keyword); 6649b36e126SZixu Wang First = false; 6659b36e126SZixu Wang } 6669b36e126SZixu Wang } 6679b36e126SZixu Wang 6689b36e126SZixu Wang Fragments.append(")", DeclarationFragments::FragmentKind::Text); 6699b36e126SZixu Wang } 6709b36e126SZixu Wang 6719b36e126SZixu Wang // Build the property type and name, and return the completed fragments. 6729b36e126SZixu Wang return Fragments.appendSpace() 6739b36e126SZixu Wang .append(getFragmentsForType(Property->getType(), 6749b36e126SZixu Wang Property->getASTContext(), After)) 6759b36e126SZixu Wang .append(Property->getName(), 6769b36e126SZixu Wang DeclarationFragments::FragmentKind::Identifier) 6779b36e126SZixu Wang .append(std::move(After)); 6789b36e126SZixu Wang } 6799b36e126SZixu Wang 680d1d34bafSZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol( 681d1d34bafSZixu Wang const ObjCProtocolDecl *Protocol) { 682d1d34bafSZixu Wang DeclarationFragments Fragments; 683d1d34bafSZixu Wang // Build basic protocol declaration. 684d1d34bafSZixu Wang Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword) 685d1d34bafSZixu Wang .appendSpace() 686d1d34bafSZixu Wang .append(Protocol->getName(), 687d1d34bafSZixu Wang DeclarationFragments::FragmentKind::Identifier); 688d1d34bafSZixu Wang 689d1d34bafSZixu Wang // If this protocol conforms to other protocols, build the conformance list. 690d1d34bafSZixu Wang if (!Protocol->protocols().empty()) { 691d1d34bafSZixu Wang Fragments.append(" <", DeclarationFragments::FragmentKind::Text); 692d1d34bafSZixu Wang for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin(); 693d1d34bafSZixu Wang It != Protocol->protocol_end(); It++) { 694d1d34bafSZixu Wang // Add a leading comma if this is not the first protocol rendered. 695d1d34bafSZixu Wang if (It != Protocol->protocol_begin()) 696d1d34bafSZixu Wang Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 697d1d34bafSZixu Wang 698d1d34bafSZixu Wang SmallString<128> USR; 699d1d34bafSZixu Wang index::generateUSRForDecl(*It, USR); 700d1d34bafSZixu Wang Fragments.append((*It)->getName(), 701d1d34bafSZixu Wang DeclarationFragments::FragmentKind::TypeIdentifier, USR); 702d1d34bafSZixu Wang } 703d1d34bafSZixu Wang Fragments.append(">", DeclarationFragments::FragmentKind::Text); 704d1d34bafSZixu Wang } 705d1d34bafSZixu Wang 706d1d34bafSZixu Wang return Fragments; 707d1d34bafSZixu Wang } 708d1d34bafSZixu Wang 709*9fc45ca0SDaniel Grumberg DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef( 710*9fc45ca0SDaniel Grumberg const TypedefNameDecl *Decl) { 711*9fc45ca0SDaniel Grumberg DeclarationFragments Fragments, After; 712*9fc45ca0SDaniel Grumberg Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword) 713*9fc45ca0SDaniel Grumberg .appendSpace() 714*9fc45ca0SDaniel Grumberg .append(getFragmentsForType(Decl->getUnderlyingType(), 715*9fc45ca0SDaniel Grumberg Decl->getASTContext(), After)) 716*9fc45ca0SDaniel Grumberg .append(std::move(After)) 717*9fc45ca0SDaniel Grumberg .appendSpace() 718*9fc45ca0SDaniel Grumberg .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier); 719*9fc45ca0SDaniel Grumberg 720*9fc45ca0SDaniel Grumberg return Fragments; 721*9fc45ca0SDaniel Grumberg } 722*9fc45ca0SDaniel Grumberg 7239b36e126SZixu Wang template <typename FunctionT> 7249b36e126SZixu Wang FunctionSignature 7259b36e126SZixu Wang DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) { 7269b36e126SZixu Wang FunctionSignature Signature; 7279b36e126SZixu Wang 7289b36e126SZixu Wang DeclarationFragments ReturnType, After; 7299b36e126SZixu Wang ReturnType 7309b36e126SZixu Wang .append(getFragmentsForType(Function->getReturnType(), 7319b36e126SZixu Wang Function->getASTContext(), After)) 7329b36e126SZixu Wang .append(std::move(After)); 7339b36e126SZixu Wang Signature.setReturnType(ReturnType); 7349b36e126SZixu Wang 7359b36e126SZixu Wang for (const auto *Param : Function->parameters()) 7369b36e126SZixu Wang Signature.addParameter(Param->getName(), getFragmentsForParam(Param)); 73789f6b26fSZixu Wang 73889f6b26fSZixu Wang return Signature; 73989f6b26fSZixu Wang } 74089f6b26fSZixu Wang 7419b36e126SZixu Wang // Instantiate template for FunctionDecl. 7429b36e126SZixu Wang template FunctionSignature 7439b36e126SZixu Wang DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *); 7449b36e126SZixu Wang 7459b36e126SZixu Wang // Instantiate template for ObjCMethodDecl. 7469b36e126SZixu Wang template FunctionSignature 7479b36e126SZixu Wang DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *); 7489b36e126SZixu Wang 74989f6b26fSZixu Wang // Subheading of a symbol defaults to its name. 75089f6b26fSZixu Wang DeclarationFragments 75189f6b26fSZixu Wang DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) { 75289f6b26fSZixu Wang DeclarationFragments Fragments; 75389f6b26fSZixu Wang if (!Decl->getName().empty()) 75489f6b26fSZixu Wang Fragments.append(Decl->getName(), 75589f6b26fSZixu Wang DeclarationFragments::FragmentKind::Identifier); 75689f6b26fSZixu Wang return Fragments; 75789f6b26fSZixu Wang } 7589b36e126SZixu Wang 7599b36e126SZixu Wang // Subheading of an Objective-C method is a `+` or `-` sign indicating whether 7609b36e126SZixu Wang // it's a class method or an instance method, followed by the selector name. 7619b36e126SZixu Wang DeclarationFragments 7629b36e126SZixu Wang DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) { 7639b36e126SZixu Wang DeclarationFragments Fragments; 7649b36e126SZixu Wang if (Method->isClassMethod()) 7659b36e126SZixu Wang Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); 7669b36e126SZixu Wang else if (Method->isInstanceMethod()) 7679b36e126SZixu Wang Fragments.append("- ", DeclarationFragments::FragmentKind::Text); 7689b36e126SZixu Wang 7699b36e126SZixu Wang return Fragments.append(Method->getNameAsString(), 7709b36e126SZixu Wang DeclarationFragments::FragmentKind::Identifier); 7719b36e126SZixu Wang } 772529a0570SDaniel Grumberg 773529a0570SDaniel Grumberg // Subheading of a symbol defaults to its name. 774529a0570SDaniel Grumberg DeclarationFragments 775529a0570SDaniel Grumberg DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) { 776529a0570SDaniel Grumberg DeclarationFragments Fragments; 777529a0570SDaniel Grumberg Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); 778529a0570SDaniel Grumberg return Fragments; 779529a0570SDaniel Grumberg } 780