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" 15*06c3fb27SDimitry Andric #include "clang/ExtractAPI/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(), 112bdd1243dSDimitry 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(), 121bdd1243dSDimitry Andric DeclarationFragments::FragmentKind::Identifier, USR, 122bdd1243dSDimitry 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. 140bdd1243dSDimitry 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 163*06c3fb27SDimitry Andric // the pointee type followed by a `*`, 164*06c3fb27SDimitry Andric if (T->isPointerType()) 16581ad6265SDimitry Andric return Fragments 16681ad6265SDimitry Andric .append(getFragmentsForType(T->getPointeeType(), Context, After)) 16781ad6265SDimitry Andric .append(" *", DeclarationFragments::FragmentKind::Text); 168*06c3fb27SDimitry Andric 169*06c3fb27SDimitry Andric // For Objective-C `id` and `Class` pointers 170*06c3fb27SDimitry Andric // we do not spell out the `*`. 171*06c3fb27SDimitry Andric if (T->isObjCObjectPointerType() && 172*06c3fb27SDimitry Andric !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) { 173*06c3fb27SDimitry Andric 174*06c3fb27SDimitry Andric Fragments.append(getFragmentsForType(T->getPointeeType(), Context, After)); 175*06c3fb27SDimitry Andric 176*06c3fb27SDimitry Andric // id<protocol> is an qualified id type 177*06c3fb27SDimitry Andric // id<protocol>* is not an qualified id type 178*06c3fb27SDimitry Andric if (!T->getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) { 179*06c3fb27SDimitry Andric Fragments.append(" *", DeclarationFragments::FragmentKind::Text); 180*06c3fb27SDimitry Andric } 181*06c3fb27SDimitry Andric 182*06c3fb27SDimitry Andric return Fragments; 18381ad6265SDimitry Andric } 18481ad6265SDimitry Andric 18581ad6265SDimitry Andric // Declaration fragments of a lvalue reference type is the declaration 18681ad6265SDimitry Andric // fragments of the underlying type followed by a `&`. 18781ad6265SDimitry Andric if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T)) 18881ad6265SDimitry Andric return Fragments 18981ad6265SDimitry Andric .append( 19081ad6265SDimitry Andric getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After)) 19181ad6265SDimitry Andric .append(" &", DeclarationFragments::FragmentKind::Text); 19281ad6265SDimitry Andric 19381ad6265SDimitry Andric // Declaration fragments of a rvalue reference type is the declaration 19481ad6265SDimitry Andric // fragments of the underlying type followed by a `&&`. 19581ad6265SDimitry Andric if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T)) 19681ad6265SDimitry Andric return Fragments 19781ad6265SDimitry Andric .append( 19881ad6265SDimitry Andric getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After)) 19981ad6265SDimitry Andric .append(" &&", DeclarationFragments::FragmentKind::Text); 20081ad6265SDimitry Andric 20181ad6265SDimitry Andric // Declaration fragments of an array-typed variable have two parts: 20281ad6265SDimitry Andric // 1. the element type of the array that appears before the variable name; 20381ad6265SDimitry Andric // 2. array brackets `[(0-9)?]` that appear after the variable name. 20481ad6265SDimitry Andric if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) { 20581ad6265SDimitry Andric // Build the "after" part first because the inner element type might also 20681ad6265SDimitry Andric // be an array-type. For example `int matrix[3][4]` which has a type of 20781ad6265SDimitry Andric // "(array 3 of (array 4 of ints))." 20881ad6265SDimitry Andric // Push the array size part first to make sure they are in the right order. 20981ad6265SDimitry Andric After.append("[", DeclarationFragments::FragmentKind::Text); 21081ad6265SDimitry Andric 21181ad6265SDimitry Andric switch (AT->getSizeModifier()) { 21281ad6265SDimitry Andric case ArrayType::Normal: 21381ad6265SDimitry Andric break; 21481ad6265SDimitry Andric case ArrayType::Static: 21581ad6265SDimitry Andric Fragments.append("static", DeclarationFragments::FragmentKind::Keyword); 21681ad6265SDimitry Andric break; 21781ad6265SDimitry Andric case ArrayType::Star: 21881ad6265SDimitry Andric Fragments.append("*", DeclarationFragments::FragmentKind::Text); 21981ad6265SDimitry Andric break; 22081ad6265SDimitry Andric } 22181ad6265SDimitry Andric 22281ad6265SDimitry Andric if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) { 22381ad6265SDimitry Andric // FIXME: right now this would evaluate any expressions/macros written in 22481ad6265SDimitry Andric // the original source to concrete values. For example 22581ad6265SDimitry Andric // `int nums[MAX]` -> `int nums[100]` 22681ad6265SDimitry Andric // `char *str[5 + 1]` -> `char *str[6]` 22781ad6265SDimitry Andric SmallString<128> Size; 22881ad6265SDimitry Andric CAT->getSize().toStringUnsigned(Size); 22981ad6265SDimitry Andric After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral); 23081ad6265SDimitry Andric } 23181ad6265SDimitry Andric 23281ad6265SDimitry Andric After.append("]", DeclarationFragments::FragmentKind::Text); 23381ad6265SDimitry Andric 23481ad6265SDimitry Andric return Fragments.append( 23581ad6265SDimitry Andric getFragmentsForType(AT->getElementType(), Context, After)); 23681ad6265SDimitry Andric } 23781ad6265SDimitry Andric 23881ad6265SDimitry Andric // An ElaboratedType is a sugar for types that are referred to using an 23981ad6265SDimitry Andric // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a 24081ad6265SDimitry Andric // qualified name, e.g., `N::M::type`, or both. 24181ad6265SDimitry Andric if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) { 24281ad6265SDimitry Andric ElaboratedTypeKeyword Keyword = ET->getKeyword(); 24381ad6265SDimitry Andric if (Keyword != ETK_None) { 24481ad6265SDimitry Andric Fragments 24581ad6265SDimitry Andric .append(ElaboratedType::getKeywordName(Keyword), 24681ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword) 24781ad6265SDimitry Andric .appendSpace(); 24881ad6265SDimitry Andric } 24981ad6265SDimitry Andric 25081ad6265SDimitry Andric if (const NestedNameSpecifier *NNS = ET->getQualifier()) 25181ad6265SDimitry Andric Fragments.append(getFragmentsForNNS(NNS, Context, After)); 25281ad6265SDimitry Andric 25381ad6265SDimitry Andric // After handling the elaborated keyword or qualified name, build 25481ad6265SDimitry Andric // declaration fragments for the desugared underlying type. 25581ad6265SDimitry Andric return Fragments.append(getFragmentsForType(ET->desugar(), Context, After)); 25681ad6265SDimitry Andric } 25781ad6265SDimitry Andric 25881ad6265SDimitry Andric // If the type is a typedefed type, get the underlying TypedefNameDecl for a 25981ad6265SDimitry Andric // direct reference to the typedef instead of the wrapped type. 260*06c3fb27SDimitry Andric 261*06c3fb27SDimitry Andric // 'id' type is a typedef for an ObjCObjectPointerType 262*06c3fb27SDimitry Andric // we treat it as a typedef 26381ad6265SDimitry Andric if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) { 26481ad6265SDimitry Andric const TypedefNameDecl *Decl = TypedefTy->getDecl(); 265bdd1243dSDimitry Andric TypedefUnderlyingTypeResolver TypedefResolver(Context); 266bdd1243dSDimitry Andric std::string USR = TypedefResolver.getUSRForType(QualType(T, 0)); 267*06c3fb27SDimitry Andric 268*06c3fb27SDimitry Andric if (T->isObjCIdType()) { 269*06c3fb27SDimitry Andric return Fragments.append(Decl->getName(), 270*06c3fb27SDimitry Andric DeclarationFragments::FragmentKind::Keyword); 271*06c3fb27SDimitry Andric } 272*06c3fb27SDimitry Andric 273bdd1243dSDimitry Andric return Fragments.append( 274bdd1243dSDimitry Andric Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier, 275bdd1243dSDimitry Andric USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0))); 27681ad6265SDimitry Andric } 27781ad6265SDimitry Andric 278*06c3fb27SDimitry Andric // Everything we care about has been handled now, reduce to the canonical 279*06c3fb27SDimitry Andric // unqualified base type. 280*06c3fb27SDimitry Andric QualType Base = T->getCanonicalTypeUnqualified(); 281*06c3fb27SDimitry Andric 28281ad6265SDimitry Andric // If the base type is a TagType (struct/interface/union/class/enum), let's 28381ad6265SDimitry Andric // get the underlying Decl for better names and USRs. 28481ad6265SDimitry Andric if (const TagType *TagTy = dyn_cast<TagType>(Base)) { 28581ad6265SDimitry Andric const TagDecl *Decl = TagTy->getDecl(); 28681ad6265SDimitry Andric // Anonymous decl, skip this fragment. 28781ad6265SDimitry Andric if (Decl->getName().empty()) 28881ad6265SDimitry Andric return Fragments; 28981ad6265SDimitry Andric SmallString<128> TagUSR; 29081ad6265SDimitry Andric clang::index::generateUSRForDecl(Decl, TagUSR); 29181ad6265SDimitry Andric return Fragments.append(Decl->getName(), 29281ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, 293bdd1243dSDimitry Andric TagUSR, Decl); 29481ad6265SDimitry Andric } 29581ad6265SDimitry Andric 29681ad6265SDimitry Andric // If the base type is an ObjCInterfaceType, use the underlying 29781ad6265SDimitry Andric // ObjCInterfaceDecl for the true USR. 29881ad6265SDimitry Andric if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) { 29981ad6265SDimitry Andric const auto *Decl = ObjCIT->getDecl(); 30081ad6265SDimitry Andric SmallString<128> USR; 30181ad6265SDimitry Andric index::generateUSRForDecl(Decl, USR); 30281ad6265SDimitry Andric return Fragments.append(Decl->getName(), 30381ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, 304bdd1243dSDimitry Andric USR, Decl); 30581ad6265SDimitry Andric } 30681ad6265SDimitry Andric 30781ad6265SDimitry Andric // Default fragment builder for other kinds of types (BuiltinType etc.) 30881ad6265SDimitry Andric SmallString<128> USR; 30981ad6265SDimitry Andric clang::index::generateUSRForType(Base, Context, USR); 31081ad6265SDimitry Andric Fragments.append(Base.getAsString(), 31181ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, USR); 31281ad6265SDimitry Andric 31381ad6265SDimitry Andric return Fragments; 31481ad6265SDimitry Andric } 31581ad6265SDimitry Andric 31681ad6265SDimitry Andric DeclarationFragments 31781ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) { 31881ad6265SDimitry Andric DeclarationFragments Fragments; 31981ad6265SDimitry Andric if (Quals.hasConst()) 32081ad6265SDimitry Andric Fragments.append("const", DeclarationFragments::FragmentKind::Keyword); 32181ad6265SDimitry Andric if (Quals.hasVolatile()) 32281ad6265SDimitry Andric Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword); 32381ad6265SDimitry Andric if (Quals.hasRestrict()) 32481ad6265SDimitry Andric Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword); 32581ad6265SDimitry Andric 32681ad6265SDimitry Andric return Fragments; 32781ad6265SDimitry Andric } 32881ad6265SDimitry Andric 32981ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( 33081ad6265SDimitry Andric const QualType QT, ASTContext &Context, DeclarationFragments &After) { 33181ad6265SDimitry Andric assert(!QT.isNull() && "invalid type"); 33281ad6265SDimitry Andric 33381ad6265SDimitry Andric if (const ParenType *PT = dyn_cast<ParenType>(QT)) { 33481ad6265SDimitry Andric After.append(")", DeclarationFragments::FragmentKind::Text); 33581ad6265SDimitry Andric return getFragmentsForType(PT->getInnerType(), Context, After) 33681ad6265SDimitry Andric .append("(", DeclarationFragments::FragmentKind::Text); 33781ad6265SDimitry Andric } 33881ad6265SDimitry Andric 33981ad6265SDimitry Andric const SplitQualType SQT = QT.split(); 34081ad6265SDimitry Andric DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals), 34181ad6265SDimitry Andric TypeFragments = 34281ad6265SDimitry Andric getFragmentsForType(SQT.Ty, Context, After); 34381ad6265SDimitry Andric if (QualsFragments.getFragments().empty()) 34481ad6265SDimitry Andric return TypeFragments; 34581ad6265SDimitry Andric 34681ad6265SDimitry Andric // Use east qualifier for pointer types 34781ad6265SDimitry Andric // For example: 34881ad6265SDimitry Andric // ``` 34981ad6265SDimitry Andric // int * const 35081ad6265SDimitry Andric // ^---- ^---- 35181ad6265SDimitry Andric // type qualifier 35281ad6265SDimitry Andric // ^----------------- 35381ad6265SDimitry Andric // const pointer to int 35481ad6265SDimitry Andric // ``` 35581ad6265SDimitry Andric // should not be reconstructed as 35681ad6265SDimitry Andric // ``` 35781ad6265SDimitry Andric // const int * 35881ad6265SDimitry Andric // ^---- ^-- 35981ad6265SDimitry Andric // qualifier type 36081ad6265SDimitry Andric // ^---------------- ^ 36181ad6265SDimitry Andric // pointer to const int 36281ad6265SDimitry Andric // ``` 36381ad6265SDimitry Andric if (SQT.Ty->isAnyPointerType()) 36481ad6265SDimitry Andric return TypeFragments.appendSpace().append(std::move(QualsFragments)); 36581ad6265SDimitry Andric 36681ad6265SDimitry Andric return QualsFragments.appendSpace().append(std::move(TypeFragments)); 36781ad6265SDimitry Andric } 36881ad6265SDimitry Andric 36981ad6265SDimitry Andric DeclarationFragments 37081ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) { 37181ad6265SDimitry Andric DeclarationFragments Fragments; 37281ad6265SDimitry Andric StorageClass SC = Var->getStorageClass(); 37381ad6265SDimitry Andric if (SC != SC_None) 37481ad6265SDimitry Andric Fragments 37581ad6265SDimitry Andric .append(VarDecl::getStorageClassSpecifierString(SC), 37681ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword) 37781ad6265SDimitry Andric .appendSpace(); 37881ad6265SDimitry Andric QualType T = 37981ad6265SDimitry Andric Var->getTypeSourceInfo() 38081ad6265SDimitry Andric ? Var->getTypeSourceInfo()->getType() 38181ad6265SDimitry Andric : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType()); 38281ad6265SDimitry Andric 38381ad6265SDimitry Andric // Capture potential fragments that needs to be placed after the variable name 38481ad6265SDimitry Andric // ``` 38581ad6265SDimitry Andric // int nums[5]; 38681ad6265SDimitry Andric // char (*ptr_to_array)[6]; 38781ad6265SDimitry Andric // ``` 38881ad6265SDimitry Andric DeclarationFragments After; 38981ad6265SDimitry Andric return Fragments.append(getFragmentsForType(T, Var->getASTContext(), After)) 39081ad6265SDimitry Andric .appendSpace() 39181ad6265SDimitry Andric .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) 39281ad6265SDimitry Andric .append(std::move(After)); 39381ad6265SDimitry Andric } 39481ad6265SDimitry Andric 39581ad6265SDimitry Andric DeclarationFragments 39681ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) { 39781ad6265SDimitry Andric DeclarationFragments Fragments, After; 39881ad6265SDimitry Andric 39981ad6265SDimitry Andric QualType T = Param->getTypeSourceInfo() 40081ad6265SDimitry Andric ? Param->getTypeSourceInfo()->getType() 40181ad6265SDimitry Andric : Param->getASTContext().getUnqualifiedObjCPointerType( 40281ad6265SDimitry Andric Param->getType()); 40381ad6265SDimitry Andric 40481ad6265SDimitry Andric DeclarationFragments TypeFragments = 40581ad6265SDimitry Andric getFragmentsForType(T, Param->getASTContext(), After); 40681ad6265SDimitry Andric 40781ad6265SDimitry Andric if (Param->isObjCMethodParameter()) 40881ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text) 40981ad6265SDimitry Andric .append(std::move(TypeFragments)) 41081ad6265SDimitry Andric .append(") ", DeclarationFragments::FragmentKind::Text); 41181ad6265SDimitry Andric else 41281ad6265SDimitry Andric Fragments.append(std::move(TypeFragments)).appendSpace(); 41381ad6265SDimitry Andric 41481ad6265SDimitry Andric return Fragments 41581ad6265SDimitry Andric .append(Param->getName(), 41681ad6265SDimitry Andric DeclarationFragments::FragmentKind::InternalParam) 41781ad6265SDimitry Andric .append(std::move(After)); 41881ad6265SDimitry Andric } 41981ad6265SDimitry Andric 42081ad6265SDimitry Andric DeclarationFragments 42181ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) { 42281ad6265SDimitry Andric DeclarationFragments Fragments; 42381ad6265SDimitry Andric // FIXME: Handle template specialization 42481ad6265SDimitry Andric switch (Func->getStorageClass()) { 42581ad6265SDimitry Andric case SC_None: 42681ad6265SDimitry Andric case SC_PrivateExtern: 42781ad6265SDimitry Andric break; 42881ad6265SDimitry Andric case SC_Extern: 42981ad6265SDimitry Andric Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword) 43081ad6265SDimitry Andric .appendSpace(); 43181ad6265SDimitry Andric break; 43281ad6265SDimitry Andric case SC_Static: 43381ad6265SDimitry Andric Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) 43481ad6265SDimitry Andric .appendSpace(); 43581ad6265SDimitry Andric break; 43681ad6265SDimitry Andric case SC_Auto: 43781ad6265SDimitry Andric case SC_Register: 43881ad6265SDimitry Andric llvm_unreachable("invalid for functions"); 43981ad6265SDimitry Andric } 44081ad6265SDimitry Andric // FIXME: Handle C++ function specifiers: constexpr, consteval, explicit, etc. 44181ad6265SDimitry Andric 44281ad6265SDimitry Andric // FIXME: Is `after` actually needed here? 44381ad6265SDimitry Andric DeclarationFragments After; 44481ad6265SDimitry Andric Fragments 44581ad6265SDimitry Andric .append(getFragmentsForType(Func->getReturnType(), Func->getASTContext(), 44681ad6265SDimitry Andric After)) 44781ad6265SDimitry Andric .appendSpace() 44881ad6265SDimitry Andric .append(Func->getName(), DeclarationFragments::FragmentKind::Identifier) 44981ad6265SDimitry Andric .append(std::move(After)); 45081ad6265SDimitry Andric 45181ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text); 45281ad6265SDimitry Andric for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) { 45381ad6265SDimitry Andric if (i) 45481ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 45581ad6265SDimitry Andric Fragments.append(getFragmentsForParam(Func->getParamDecl(i))); 45681ad6265SDimitry Andric } 45781ad6265SDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 45881ad6265SDimitry Andric 45981ad6265SDimitry Andric // FIXME: Handle exception specifiers: throw, noexcept 460*06c3fb27SDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 46181ad6265SDimitry Andric } 46281ad6265SDimitry Andric 46381ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant( 46481ad6265SDimitry Andric const EnumConstantDecl *EnumConstDecl) { 46581ad6265SDimitry Andric DeclarationFragments Fragments; 46681ad6265SDimitry Andric return Fragments.append(EnumConstDecl->getName(), 46781ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 46881ad6265SDimitry Andric } 46981ad6265SDimitry Andric 47081ad6265SDimitry Andric DeclarationFragments 47181ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) { 47281ad6265SDimitry Andric if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl()) 47381ad6265SDimitry Andric return getFragmentsForTypedef(TypedefNameDecl); 47481ad6265SDimitry Andric 47581ad6265SDimitry Andric DeclarationFragments Fragments, After; 47681ad6265SDimitry Andric Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword); 47781ad6265SDimitry Andric 47881ad6265SDimitry Andric if (!EnumDecl->getName().empty()) 47981ad6265SDimitry Andric Fragments.appendSpace().append( 48081ad6265SDimitry Andric EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier); 48181ad6265SDimitry Andric 48281ad6265SDimitry Andric QualType IntegerType = EnumDecl->getIntegerType(); 48381ad6265SDimitry Andric if (!IntegerType.isNull()) 48481ad6265SDimitry Andric Fragments.append(": ", DeclarationFragments::FragmentKind::Text) 48581ad6265SDimitry Andric .append( 48681ad6265SDimitry Andric getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After)) 48781ad6265SDimitry Andric .append(std::move(After)); 48881ad6265SDimitry Andric 489*06c3fb27SDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 49081ad6265SDimitry Andric } 49181ad6265SDimitry Andric 49281ad6265SDimitry Andric DeclarationFragments 49381ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) { 49481ad6265SDimitry Andric DeclarationFragments After; 49581ad6265SDimitry Andric return getFragmentsForType(Field->getType(), Field->getASTContext(), After) 49681ad6265SDimitry Andric .appendSpace() 49781ad6265SDimitry Andric .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier) 49881ad6265SDimitry Andric .append(std::move(After)); 49981ad6265SDimitry Andric } 50081ad6265SDimitry Andric 50181ad6265SDimitry Andric DeclarationFragments 50281ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForStruct(const RecordDecl *Record) { 50381ad6265SDimitry Andric if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl()) 50481ad6265SDimitry Andric return getFragmentsForTypedef(TypedefNameDecl); 50581ad6265SDimitry Andric 50681ad6265SDimitry Andric DeclarationFragments Fragments; 50781ad6265SDimitry Andric Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword); 50881ad6265SDimitry Andric 50981ad6265SDimitry Andric if (!Record->getName().empty()) 51081ad6265SDimitry Andric Fragments.appendSpace().append( 51181ad6265SDimitry Andric Record->getName(), DeclarationFragments::FragmentKind::Identifier); 512*06c3fb27SDimitry Andric 513*06c3fb27SDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 51481ad6265SDimitry Andric } 51581ad6265SDimitry Andric 51681ad6265SDimitry Andric DeclarationFragments 51781ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name, 51881ad6265SDimitry Andric const MacroDirective *MD) { 51981ad6265SDimitry Andric DeclarationFragments Fragments; 52081ad6265SDimitry Andric Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword) 52181ad6265SDimitry Andric .appendSpace(); 52281ad6265SDimitry Andric Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); 52381ad6265SDimitry Andric 52481ad6265SDimitry Andric auto *MI = MD->getMacroInfo(); 52581ad6265SDimitry Andric 52681ad6265SDimitry Andric if (MI->isFunctionLike()) { 52781ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text); 52881ad6265SDimitry Andric unsigned numParameters = MI->getNumParams(); 52981ad6265SDimitry Andric if (MI->isC99Varargs()) 53081ad6265SDimitry Andric --numParameters; 53181ad6265SDimitry Andric for (unsigned i = 0; i < numParameters; ++i) { 53281ad6265SDimitry Andric if (i) 53381ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 53481ad6265SDimitry Andric Fragments.append(MI->params()[i]->getName(), 53581ad6265SDimitry Andric DeclarationFragments::FragmentKind::InternalParam); 53681ad6265SDimitry Andric } 53781ad6265SDimitry Andric if (MI->isVariadic()) { 53881ad6265SDimitry Andric if (numParameters && MI->isC99Varargs()) 53981ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 54081ad6265SDimitry Andric Fragments.append("...", DeclarationFragments::FragmentKind::Text); 54181ad6265SDimitry Andric } 54281ad6265SDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 54381ad6265SDimitry Andric } 54481ad6265SDimitry Andric return Fragments; 54581ad6265SDimitry Andric } 54681ad6265SDimitry Andric 54781ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory( 54881ad6265SDimitry Andric const ObjCCategoryDecl *Category) { 54981ad6265SDimitry Andric DeclarationFragments Fragments; 55081ad6265SDimitry Andric 551bdd1243dSDimitry Andric auto *Interface = Category->getClassInterface(); 55281ad6265SDimitry Andric SmallString<128> InterfaceUSR; 553bdd1243dSDimitry Andric index::generateUSRForDecl(Interface, InterfaceUSR); 55481ad6265SDimitry Andric 55581ad6265SDimitry Andric Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) 55681ad6265SDimitry Andric .appendSpace() 55781ad6265SDimitry Andric .append(Category->getClassInterface()->getName(), 558bdd1243dSDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR, 559bdd1243dSDimitry Andric Interface) 56081ad6265SDimitry Andric .append(" (", DeclarationFragments::FragmentKind::Text) 56181ad6265SDimitry Andric .append(Category->getName(), 56281ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier) 56381ad6265SDimitry Andric .append(")", DeclarationFragments::FragmentKind::Text); 56481ad6265SDimitry Andric 56581ad6265SDimitry Andric return Fragments; 56681ad6265SDimitry Andric } 56781ad6265SDimitry Andric 56881ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface( 56981ad6265SDimitry Andric const ObjCInterfaceDecl *Interface) { 57081ad6265SDimitry Andric DeclarationFragments Fragments; 57181ad6265SDimitry Andric // Build the base of the Objective-C interface declaration. 57281ad6265SDimitry Andric Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) 57381ad6265SDimitry Andric .appendSpace() 57481ad6265SDimitry Andric .append(Interface->getName(), 57581ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 57681ad6265SDimitry Andric 57781ad6265SDimitry Andric // Build the inheritance part of the declaration. 57881ad6265SDimitry Andric if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) { 57981ad6265SDimitry Andric SmallString<128> SuperUSR; 58081ad6265SDimitry Andric index::generateUSRForDecl(SuperClass, SuperUSR); 58181ad6265SDimitry Andric Fragments.append(" : ", DeclarationFragments::FragmentKind::Text) 58281ad6265SDimitry Andric .append(SuperClass->getName(), 583bdd1243dSDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR, 584bdd1243dSDimitry Andric SuperClass); 58581ad6265SDimitry Andric } 58681ad6265SDimitry Andric 58781ad6265SDimitry Andric return Fragments; 58881ad6265SDimitry Andric } 58981ad6265SDimitry Andric 59081ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod( 59181ad6265SDimitry Andric const ObjCMethodDecl *Method) { 59281ad6265SDimitry Andric DeclarationFragments Fragments, After; 59381ad6265SDimitry Andric // Build the instance/class method indicator. 59481ad6265SDimitry Andric if (Method->isClassMethod()) 59581ad6265SDimitry Andric Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); 59681ad6265SDimitry Andric else if (Method->isInstanceMethod()) 59781ad6265SDimitry Andric Fragments.append("- ", DeclarationFragments::FragmentKind::Text); 59881ad6265SDimitry Andric 59981ad6265SDimitry Andric // Build the return type. 60081ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text) 60181ad6265SDimitry Andric .append(getFragmentsForType(Method->getReturnType(), 60281ad6265SDimitry Andric Method->getASTContext(), After)) 60381ad6265SDimitry Andric .append(std::move(After)) 60481ad6265SDimitry Andric .append(")", DeclarationFragments::FragmentKind::Text); 60581ad6265SDimitry Andric 60681ad6265SDimitry Andric // Build the selector part. 60781ad6265SDimitry Andric Selector Selector = Method->getSelector(); 60881ad6265SDimitry Andric if (Selector.getNumArgs() == 0) 60981ad6265SDimitry Andric // For Objective-C methods that don't take arguments, the first (and only) 61081ad6265SDimitry Andric // slot of the selector is the method name. 61181ad6265SDimitry Andric Fragments.appendSpace().append( 61281ad6265SDimitry Andric Selector.getNameForSlot(0), 61381ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 61481ad6265SDimitry Andric 61581ad6265SDimitry Andric // For Objective-C methods that take arguments, build the selector slots. 61681ad6265SDimitry Andric for (unsigned i = 0, end = Method->param_size(); i != end; ++i) { 61781ad6265SDimitry Andric // Objective-C method selector parts are considered as identifiers instead 61881ad6265SDimitry Andric // of "external parameters" as in Swift. This is because Objective-C method 61981ad6265SDimitry Andric // symbols are referenced with the entire selector, instead of just the 62081ad6265SDimitry Andric // method name in Swift. 62181ad6265SDimitry Andric SmallString<32> ParamID(Selector.getNameForSlot(i)); 62281ad6265SDimitry Andric ParamID.append(":"); 62381ad6265SDimitry Andric Fragments.appendSpace().append( 62481ad6265SDimitry Andric ParamID, DeclarationFragments::FragmentKind::Identifier); 62581ad6265SDimitry Andric 62681ad6265SDimitry Andric // Build the internal parameter. 62781ad6265SDimitry Andric const ParmVarDecl *Param = Method->getParamDecl(i); 62881ad6265SDimitry Andric Fragments.append(getFragmentsForParam(Param)); 62981ad6265SDimitry Andric } 63081ad6265SDimitry Andric 63181ad6265SDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 63281ad6265SDimitry Andric } 63381ad6265SDimitry Andric 63481ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty( 63581ad6265SDimitry Andric const ObjCPropertyDecl *Property) { 63681ad6265SDimitry Andric DeclarationFragments Fragments, After; 63781ad6265SDimitry Andric 63881ad6265SDimitry Andric // Build the Objective-C property keyword. 63981ad6265SDimitry Andric Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword); 64081ad6265SDimitry Andric 641*06c3fb27SDimitry Andric const auto Attributes = Property->getPropertyAttributesAsWritten(); 64281ad6265SDimitry Andric // Build the attributes if there is any associated with the property. 64381ad6265SDimitry Andric if (Attributes != ObjCPropertyAttribute::kind_noattr) { 64481ad6265SDimitry Andric // No leading comma for the first attribute. 64581ad6265SDimitry Andric bool First = true; 64681ad6265SDimitry Andric Fragments.append(" (", DeclarationFragments::FragmentKind::Text); 64781ad6265SDimitry Andric // Helper function to render the attribute. 64881ad6265SDimitry Andric auto RenderAttribute = 64981ad6265SDimitry Andric [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling, 65081ad6265SDimitry Andric StringRef Arg = "", 65181ad6265SDimitry Andric DeclarationFragments::FragmentKind ArgKind = 65281ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier) { 65381ad6265SDimitry Andric // Check if the `Kind` attribute is set for this property. 65481ad6265SDimitry Andric if ((Attributes & Kind) && !Spelling.empty()) { 65581ad6265SDimitry Andric // Add a leading comma if this is not the first attribute rendered. 65681ad6265SDimitry Andric if (!First) 65781ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 65881ad6265SDimitry Andric // Render the spelling of this attribute `Kind` as a keyword. 65981ad6265SDimitry Andric Fragments.append(Spelling, 66081ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword); 66181ad6265SDimitry Andric // If this attribute takes in arguments (e.g. `getter=getterName`), 66281ad6265SDimitry Andric // render the arguments. 66381ad6265SDimitry Andric if (!Arg.empty()) 66481ad6265SDimitry Andric Fragments.append("=", DeclarationFragments::FragmentKind::Text) 66581ad6265SDimitry Andric .append(Arg, ArgKind); 66681ad6265SDimitry Andric First = false; 66781ad6265SDimitry Andric } 66881ad6265SDimitry Andric }; 66981ad6265SDimitry Andric 67081ad6265SDimitry Andric // Go through all possible Objective-C property attributes and render set 67181ad6265SDimitry Andric // ones. 67281ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_class, "class"); 67381ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct"); 67481ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic"); 67581ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic"); 67681ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign"); 67781ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain"); 67881ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong"); 67981ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy"); 68081ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak"); 68181ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained, 68281ad6265SDimitry Andric "unsafe_unretained"); 68381ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite"); 68481ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly"); 68581ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter", 68681ad6265SDimitry Andric Property->getGetterName().getAsString()); 68781ad6265SDimitry Andric RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter", 68881ad6265SDimitry Andric Property->getSetterName().getAsString()); 68981ad6265SDimitry Andric 69081ad6265SDimitry Andric // Render nullability attributes. 69181ad6265SDimitry Andric if (Attributes & ObjCPropertyAttribute::kind_nullability) { 69281ad6265SDimitry Andric QualType Type = Property->getType(); 69381ad6265SDimitry Andric if (const auto Nullability = 69481ad6265SDimitry Andric AttributedType::stripOuterNullability(Type)) { 69581ad6265SDimitry Andric if (!First) 69681ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 69781ad6265SDimitry Andric if (*Nullability == NullabilityKind::Unspecified && 69881ad6265SDimitry Andric (Attributes & ObjCPropertyAttribute::kind_null_resettable)) 69981ad6265SDimitry Andric Fragments.append("null_resettable", 70081ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword); 70181ad6265SDimitry Andric else 70281ad6265SDimitry Andric Fragments.append( 70381ad6265SDimitry Andric getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true), 70481ad6265SDimitry Andric DeclarationFragments::FragmentKind::Keyword); 70581ad6265SDimitry Andric First = false; 70681ad6265SDimitry Andric } 70781ad6265SDimitry Andric } 70881ad6265SDimitry Andric 70981ad6265SDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text); 71081ad6265SDimitry Andric } 71181ad6265SDimitry Andric 71281ad6265SDimitry Andric // Build the property type and name, and return the completed fragments. 71381ad6265SDimitry Andric return Fragments.appendSpace() 71481ad6265SDimitry Andric .append(getFragmentsForType(Property->getType(), 71581ad6265SDimitry Andric Property->getASTContext(), After)) 716bdd1243dSDimitry Andric .appendSpace() 71781ad6265SDimitry Andric .append(Property->getName(), 71881ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier) 71981ad6265SDimitry Andric .append(std::move(After)); 72081ad6265SDimitry Andric } 72181ad6265SDimitry Andric 72281ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol( 72381ad6265SDimitry Andric const ObjCProtocolDecl *Protocol) { 72481ad6265SDimitry Andric DeclarationFragments Fragments; 72581ad6265SDimitry Andric // Build basic protocol declaration. 72681ad6265SDimitry Andric Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword) 72781ad6265SDimitry Andric .appendSpace() 72881ad6265SDimitry Andric .append(Protocol->getName(), 72981ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 73081ad6265SDimitry Andric 73181ad6265SDimitry Andric // If this protocol conforms to other protocols, build the conformance list. 73281ad6265SDimitry Andric if (!Protocol->protocols().empty()) { 73381ad6265SDimitry Andric Fragments.append(" <", DeclarationFragments::FragmentKind::Text); 73481ad6265SDimitry Andric for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin(); 73581ad6265SDimitry Andric It != Protocol->protocol_end(); It++) { 73681ad6265SDimitry Andric // Add a leading comma if this is not the first protocol rendered. 73781ad6265SDimitry Andric if (It != Protocol->protocol_begin()) 73881ad6265SDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 73981ad6265SDimitry Andric 74081ad6265SDimitry Andric SmallString<128> USR; 74181ad6265SDimitry Andric index::generateUSRForDecl(*It, USR); 74281ad6265SDimitry Andric Fragments.append((*It)->getName(), 743bdd1243dSDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, USR, 744bdd1243dSDimitry Andric *It); 74581ad6265SDimitry Andric } 74681ad6265SDimitry Andric Fragments.append(">", DeclarationFragments::FragmentKind::Text); 74781ad6265SDimitry Andric } 74881ad6265SDimitry Andric 74981ad6265SDimitry Andric return Fragments; 75081ad6265SDimitry Andric } 75181ad6265SDimitry Andric 75281ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef( 75381ad6265SDimitry Andric const TypedefNameDecl *Decl) { 75481ad6265SDimitry Andric DeclarationFragments Fragments, After; 75581ad6265SDimitry Andric Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword) 75681ad6265SDimitry Andric .appendSpace() 75781ad6265SDimitry Andric .append(getFragmentsForType(Decl->getUnderlyingType(), 75881ad6265SDimitry Andric Decl->getASTContext(), After)) 75981ad6265SDimitry Andric .append(std::move(After)) 76081ad6265SDimitry Andric .appendSpace() 76181ad6265SDimitry Andric .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier); 76281ad6265SDimitry Andric 763*06c3fb27SDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text); 76481ad6265SDimitry Andric } 76581ad6265SDimitry Andric 76681ad6265SDimitry Andric template <typename FunctionT> 76781ad6265SDimitry Andric FunctionSignature 76881ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) { 76981ad6265SDimitry Andric FunctionSignature Signature; 77081ad6265SDimitry Andric 77181ad6265SDimitry Andric DeclarationFragments ReturnType, After; 77281ad6265SDimitry Andric ReturnType 77381ad6265SDimitry Andric .append(getFragmentsForType(Function->getReturnType(), 77481ad6265SDimitry Andric Function->getASTContext(), After)) 77581ad6265SDimitry Andric .append(std::move(After)); 77681ad6265SDimitry Andric Signature.setReturnType(ReturnType); 77781ad6265SDimitry Andric 77881ad6265SDimitry Andric for (const auto *Param : Function->parameters()) 77981ad6265SDimitry Andric Signature.addParameter(Param->getName(), getFragmentsForParam(Param)); 78081ad6265SDimitry Andric 78181ad6265SDimitry Andric return Signature; 78281ad6265SDimitry Andric } 78381ad6265SDimitry Andric 78481ad6265SDimitry Andric // Instantiate template for FunctionDecl. 78581ad6265SDimitry Andric template FunctionSignature 78681ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *); 78781ad6265SDimitry Andric 78881ad6265SDimitry Andric // Instantiate template for ObjCMethodDecl. 78981ad6265SDimitry Andric template FunctionSignature 79081ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *); 79181ad6265SDimitry Andric 79281ad6265SDimitry Andric // Subheading of a symbol defaults to its name. 79381ad6265SDimitry Andric DeclarationFragments 79481ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) { 79581ad6265SDimitry Andric DeclarationFragments Fragments; 79681ad6265SDimitry Andric if (!Decl->getName().empty()) 79781ad6265SDimitry Andric Fragments.append(Decl->getName(), 79881ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 79981ad6265SDimitry Andric return Fragments; 80081ad6265SDimitry Andric } 80181ad6265SDimitry Andric 80281ad6265SDimitry Andric // Subheading of an Objective-C method is a `+` or `-` sign indicating whether 80381ad6265SDimitry Andric // it's a class method or an instance method, followed by the selector name. 80481ad6265SDimitry Andric DeclarationFragments 80581ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) { 80681ad6265SDimitry Andric DeclarationFragments Fragments; 80781ad6265SDimitry Andric if (Method->isClassMethod()) 80881ad6265SDimitry Andric Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); 80981ad6265SDimitry Andric else if (Method->isInstanceMethod()) 81081ad6265SDimitry Andric Fragments.append("- ", DeclarationFragments::FragmentKind::Text); 81181ad6265SDimitry Andric 81281ad6265SDimitry Andric return Fragments.append(Method->getNameAsString(), 81381ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier); 81481ad6265SDimitry Andric } 81581ad6265SDimitry Andric 81681ad6265SDimitry Andric // Subheading of a symbol defaults to its name. 81781ad6265SDimitry Andric DeclarationFragments 81881ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) { 81981ad6265SDimitry Andric DeclarationFragments Fragments; 82081ad6265SDimitry Andric Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); 82181ad6265SDimitry Andric return Fragments; 82281ad6265SDimitry Andric } 823