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"
159fc45ca0SDaniel 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
appendSpace()2289f6b26fSZixu Wang DeclarationFragments &DeclarationFragments::appendSpace() {
2389f6b26fSZixu Wang if (!Fragments.empty()) {
24fe2c77a0SZixu 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
getFragmentKindString(DeclarationFragments::FragmentKind Kind)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
parseFragmentKindFromString(StringRef S)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
getFragmentsForNNS(const NestedNameSpecifier * NNS,ASTContext & Context,DeclarationFragments & After)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.
getFragmentsForType(const Type * T,ASTContext & Context,DeclarationFragments & After)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
2549fc45ca0SDaniel Grumberg // If the type is a typedefed type, get the underlying TypedefNameDecl for a
2559fc45ca0SDaniel Grumberg // direct reference to the typedef instead of the wrapped type.
2569fc45ca0SDaniel Grumberg if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) {
2579fc45ca0SDaniel Grumberg const TypedefNameDecl *Decl = TypedefTy->getDecl();
2589fc45ca0SDaniel Grumberg std::string USR =
2599fc45ca0SDaniel Grumberg TypedefUnderlyingTypeResolver(Context).getUSRForType(QualType(T, 0));
2609fc45ca0SDaniel Grumberg return Fragments.append(Decl->getName(),
2619fc45ca0SDaniel Grumberg DeclarationFragments::FragmentKind::TypeIdentifier,
2629fc45ca0SDaniel Grumberg USR);
2639fc45ca0SDaniel Grumberg }
2649fc45ca0SDaniel Grumberg
2659fc45ca0SDaniel Grumberg // If the base type is a TagType (struct/interface/union/class/enum), let's
2669fc45ca0SDaniel Grumberg // get the underlying Decl for better names and USRs.
2679fc45ca0SDaniel Grumberg if (const TagType *TagTy = dyn_cast<TagType>(Base)) {
2689fc45ca0SDaniel Grumberg const TagDecl *Decl = TagTy->getDecl();
2699fc45ca0SDaniel Grumberg // Anonymous decl, skip this fragment.
2709fc45ca0SDaniel Grumberg if (Decl->getName().empty())
2719fc45ca0SDaniel Grumberg return Fragments;
2729fc45ca0SDaniel Grumberg SmallString<128> TagUSR;
2739fc45ca0SDaniel Grumberg clang::index::generateUSRForDecl(Decl, TagUSR);
2749fc45ca0SDaniel Grumberg return Fragments.append(Decl->getName(),
2759fc45ca0SDaniel Grumberg DeclarationFragments::FragmentKind::TypeIdentifier,
2769fc45ca0SDaniel Grumberg TagUSR);
2779fc45ca0SDaniel Grumberg }
2789fc45ca0SDaniel 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
getFragmentsForQualifiers(const Qualifiers Quals)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
getFragmentsForType(const QualType QT,ASTContext & Context,DeclarationFragments & After)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
getFragmentsForVar(const VarDecl * Var)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
getFragmentsForParam(const ParmVarDecl * Param)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
getFragmentsForFunction(const FunctionDecl * Func)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
getFragmentsForEnumConstant(const EnumConstantDecl * EnumConstDecl)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
getFragmentsForEnum(const EnumDecl * EnumDecl)45471b4c226SZixu Wang DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {
4559fc45ca0SDaniel Grumberg if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl())
4569fc45ca0SDaniel 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
getFragmentsForField(const FieldDecl * Field)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
getFragmentsForStruct(const RecordDecl * Record)4855bb5704cSZixu Wang DeclarationFragmentsBuilder::getFragmentsForStruct(const RecordDecl *Record) {
4869fc45ca0SDaniel Grumberg if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
4879fc45ca0SDaniel 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
getFragmentsForMacro(StringRef Name,const MacroDirective * MD)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
getFragmentsForObjCCategory(const ObjCCategoryDecl * Category)529178aad9bSZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory(
530178aad9bSZixu Wang const ObjCCategoryDecl *Category) {
531178aad9bSZixu Wang DeclarationFragments Fragments;
532178aad9bSZixu Wang
533178aad9bSZixu Wang SmallString<128> InterfaceUSR;
534178aad9bSZixu Wang index::generateUSRForDecl(Category->getClassInterface(), InterfaceUSR);
535178aad9bSZixu Wang
536178aad9bSZixu Wang Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
537178aad9bSZixu Wang .appendSpace()
538178aad9bSZixu Wang .append(Category->getClassInterface()->getName(),
539178aad9bSZixu Wang DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR)
540178aad9bSZixu Wang .append(" (", DeclarationFragments::FragmentKind::Text)
541178aad9bSZixu Wang .append(Category->getName(),
542178aad9bSZixu Wang DeclarationFragments::FragmentKind::Identifier)
543178aad9bSZixu Wang .append(")", DeclarationFragments::FragmentKind::Text);
544178aad9bSZixu Wang
545178aad9bSZixu Wang return Fragments;
546178aad9bSZixu Wang }
547178aad9bSZixu Wang
getFragmentsForObjCInterface(const ObjCInterfaceDecl * Interface)5489b36e126SZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface(
5499b36e126SZixu Wang const ObjCInterfaceDecl *Interface) {
5509b36e126SZixu Wang DeclarationFragments Fragments;
5519b36e126SZixu Wang // Build the base of the Objective-C interface declaration.
5529b36e126SZixu Wang Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
5539b36e126SZixu Wang .appendSpace()
5549b36e126SZixu Wang .append(Interface->getName(),
5559b36e126SZixu Wang DeclarationFragments::FragmentKind::Identifier);
55689f6b26fSZixu Wang
5579b36e126SZixu Wang // Build the inheritance part of the declaration.
5589b36e126SZixu Wang if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) {
5599b36e126SZixu Wang SmallString<128> SuperUSR;
5609b36e126SZixu Wang index::generateUSRForDecl(SuperClass, SuperUSR);
5619b36e126SZixu Wang Fragments.append(" : ", DeclarationFragments::FragmentKind::Text)
5629b36e126SZixu Wang .append(SuperClass->getName(),
5639b36e126SZixu Wang DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR);
56489f6b26fSZixu Wang }
56589f6b26fSZixu Wang
5669b36e126SZixu Wang return Fragments;
5679b36e126SZixu Wang }
56889f6b26fSZixu Wang
getFragmentsForObjCMethod(const ObjCMethodDecl * Method)5699b36e126SZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod(
5709b36e126SZixu Wang const ObjCMethodDecl *Method) {
5719b36e126SZixu Wang DeclarationFragments Fragments, After;
5729b36e126SZixu Wang // Build the instance/class method indicator.
5739b36e126SZixu Wang if (Method->isClassMethod())
5749b36e126SZixu Wang Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
5759b36e126SZixu Wang else if (Method->isInstanceMethod())
5769b36e126SZixu Wang Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
5779b36e126SZixu Wang
5789b36e126SZixu Wang // Build the return type.
5799b36e126SZixu Wang Fragments.append("(", DeclarationFragments::FragmentKind::Text)
5809b36e126SZixu Wang .append(getFragmentsForType(Method->getReturnType(),
5819b36e126SZixu Wang Method->getASTContext(), After))
5829b36e126SZixu Wang .append(std::move(After))
5839b36e126SZixu Wang .append(")", DeclarationFragments::FragmentKind::Text);
5849b36e126SZixu Wang
5859b36e126SZixu Wang // Build the selector part.
5869b36e126SZixu Wang Selector Selector = Method->getSelector();
5879b36e126SZixu Wang if (Selector.getNumArgs() == 0)
5889b36e126SZixu Wang // For Objective-C methods that don't take arguments, the first (and only)
5899b36e126SZixu Wang // slot of the selector is the method name.
5909b36e126SZixu Wang Fragments.appendSpace().append(
5919b36e126SZixu Wang Selector.getNameForSlot(0),
5929b36e126SZixu Wang DeclarationFragments::FragmentKind::Identifier);
5939b36e126SZixu Wang
5949b36e126SZixu Wang // For Objective-C methods that take arguments, build the selector slots.
5959b36e126SZixu Wang for (unsigned i = 0, end = Method->param_size(); i != end; ++i) {
596*4048aad8SZixu Wang // Objective-C method selector parts are considered as identifiers instead
597*4048aad8SZixu Wang // of "external parameters" as in Swift. This is because Objective-C method
598*4048aad8SZixu Wang // symbols are referenced with the entire selector, instead of just the
599*4048aad8SZixu Wang // method name in Swift.
600*4048aad8SZixu Wang SmallString<32> ParamID(Selector.getNameForSlot(i));
601*4048aad8SZixu Wang ParamID.append(":");
602*4048aad8SZixu Wang Fragments.appendSpace().append(
603*4048aad8SZixu Wang ParamID, DeclarationFragments::FragmentKind::Identifier);
6049b36e126SZixu Wang
6059b36e126SZixu Wang // Build the internal parameter.
6069b36e126SZixu Wang const ParmVarDecl *Param = Method->getParamDecl(i);
6079b36e126SZixu Wang Fragments.append(getFragmentsForParam(Param));
6089b36e126SZixu Wang }
6099b36e126SZixu Wang
610*4048aad8SZixu Wang return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
6119b36e126SZixu Wang }
6129b36e126SZixu Wang
getFragmentsForObjCProperty(const ObjCPropertyDecl * Property)6139b36e126SZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
6149b36e126SZixu Wang const ObjCPropertyDecl *Property) {
6159b36e126SZixu Wang DeclarationFragments Fragments, After;
6169b36e126SZixu Wang
6179b36e126SZixu Wang // Build the Objective-C property keyword.
6189b36e126SZixu Wang Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword);
6199b36e126SZixu Wang
6209b36e126SZixu Wang const auto Attributes = Property->getPropertyAttributes();
6219b36e126SZixu Wang // Build the attributes if there is any associated with the property.
6229b36e126SZixu Wang if (Attributes != ObjCPropertyAttribute::kind_noattr) {
6239b36e126SZixu Wang // No leading comma for the first attribute.
6249b36e126SZixu Wang bool First = true;
6259b36e126SZixu Wang Fragments.append(" (", DeclarationFragments::FragmentKind::Text);
6269b36e126SZixu Wang // Helper function to render the attribute.
6279b36e126SZixu Wang auto RenderAttribute =
6289b36e126SZixu Wang [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling,
6299b36e126SZixu Wang StringRef Arg = "",
6309b36e126SZixu Wang DeclarationFragments::FragmentKind ArgKind =
6319b36e126SZixu Wang DeclarationFragments::FragmentKind::Identifier) {
6329b36e126SZixu Wang // Check if the `Kind` attribute is set for this property.
6339b36e126SZixu Wang if ((Attributes & Kind) && !Spelling.empty()) {
6349b36e126SZixu Wang // Add a leading comma if this is not the first attribute rendered.
6359b36e126SZixu Wang if (!First)
6369b36e126SZixu Wang Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
6379b36e126SZixu Wang // Render the spelling of this attribute `Kind` as a keyword.
6389b36e126SZixu Wang Fragments.append(Spelling,
6399b36e126SZixu Wang DeclarationFragments::FragmentKind::Keyword);
6409b36e126SZixu Wang // If this attribute takes in arguments (e.g. `getter=getterName`),
6419b36e126SZixu Wang // render the arguments.
6429b36e126SZixu Wang if (!Arg.empty())
6439b36e126SZixu Wang Fragments.append("=", DeclarationFragments::FragmentKind::Text)
6449b36e126SZixu Wang .append(Arg, ArgKind);
6459b36e126SZixu Wang First = false;
6469b36e126SZixu Wang }
6479b36e126SZixu Wang };
6489b36e126SZixu Wang
6499b36e126SZixu Wang // Go through all possible Objective-C property attributes and render set
6509b36e126SZixu Wang // ones.
6519b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_class, "class");
6529b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct");
6539b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic");
6549b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic");
6559b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign");
6569b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain");
6579b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong");
6589b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy");
6599b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak");
6609b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained,
6619b36e126SZixu Wang "unsafe_unretained");
6629b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite");
6639b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly");
6649b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter",
6659b36e126SZixu Wang Property->getGetterName().getAsString());
6669b36e126SZixu Wang RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter",
6679b36e126SZixu Wang Property->getSetterName().getAsString());
6689b36e126SZixu Wang
6699b36e126SZixu Wang // Render nullability attributes.
6709b36e126SZixu Wang if (Attributes & ObjCPropertyAttribute::kind_nullability) {
6719b36e126SZixu Wang QualType Type = Property->getType();
6729b36e126SZixu Wang if (const auto Nullability =
6739b36e126SZixu Wang AttributedType::stripOuterNullability(Type)) {
6749b36e126SZixu Wang if (!First)
6759b36e126SZixu Wang Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
6769b36e126SZixu Wang if (*Nullability == NullabilityKind::Unspecified &&
6779b36e126SZixu Wang (Attributes & ObjCPropertyAttribute::kind_null_resettable))
6789b36e126SZixu Wang Fragments.append("null_resettable",
6799b36e126SZixu Wang DeclarationFragments::FragmentKind::Keyword);
6809b36e126SZixu Wang else
6819b36e126SZixu Wang Fragments.append(
6829b36e126SZixu Wang getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true),
6839b36e126SZixu Wang DeclarationFragments::FragmentKind::Keyword);
6849b36e126SZixu Wang First = false;
6859b36e126SZixu Wang }
6869b36e126SZixu Wang }
6879b36e126SZixu Wang
6889b36e126SZixu Wang Fragments.append(")", DeclarationFragments::FragmentKind::Text);
6899b36e126SZixu Wang }
6909b36e126SZixu Wang
6919b36e126SZixu Wang // Build the property type and name, and return the completed fragments.
6929b36e126SZixu Wang return Fragments.appendSpace()
6939b36e126SZixu Wang .append(getFragmentsForType(Property->getType(),
6949b36e126SZixu Wang Property->getASTContext(), After))
6959b36e126SZixu Wang .append(Property->getName(),
6969b36e126SZixu Wang DeclarationFragments::FragmentKind::Identifier)
6979b36e126SZixu Wang .append(std::move(After));
6989b36e126SZixu Wang }
6999b36e126SZixu Wang
getFragmentsForObjCProtocol(const ObjCProtocolDecl * Protocol)700d1d34bafSZixu Wang DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(
701d1d34bafSZixu Wang const ObjCProtocolDecl *Protocol) {
702d1d34bafSZixu Wang DeclarationFragments Fragments;
703d1d34bafSZixu Wang // Build basic protocol declaration.
704d1d34bafSZixu Wang Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword)
705d1d34bafSZixu Wang .appendSpace()
706d1d34bafSZixu Wang .append(Protocol->getName(),
707d1d34bafSZixu Wang DeclarationFragments::FragmentKind::Identifier);
708d1d34bafSZixu Wang
709d1d34bafSZixu Wang // If this protocol conforms to other protocols, build the conformance list.
710d1d34bafSZixu Wang if (!Protocol->protocols().empty()) {
711d1d34bafSZixu Wang Fragments.append(" <", DeclarationFragments::FragmentKind::Text);
712d1d34bafSZixu Wang for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin();
713d1d34bafSZixu Wang It != Protocol->protocol_end(); It++) {
714d1d34bafSZixu Wang // Add a leading comma if this is not the first protocol rendered.
715d1d34bafSZixu Wang if (It != Protocol->protocol_begin())
716d1d34bafSZixu Wang Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
717d1d34bafSZixu Wang
718d1d34bafSZixu Wang SmallString<128> USR;
719d1d34bafSZixu Wang index::generateUSRForDecl(*It, USR);
720d1d34bafSZixu Wang Fragments.append((*It)->getName(),
721d1d34bafSZixu Wang DeclarationFragments::FragmentKind::TypeIdentifier, USR);
722d1d34bafSZixu Wang }
723d1d34bafSZixu Wang Fragments.append(">", DeclarationFragments::FragmentKind::Text);
724d1d34bafSZixu Wang }
725d1d34bafSZixu Wang
726d1d34bafSZixu Wang return Fragments;
727d1d34bafSZixu Wang }
728d1d34bafSZixu Wang
getFragmentsForTypedef(const TypedefNameDecl * Decl)7299fc45ca0SDaniel Grumberg DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(
7309fc45ca0SDaniel Grumberg const TypedefNameDecl *Decl) {
7319fc45ca0SDaniel Grumberg DeclarationFragments Fragments, After;
7329fc45ca0SDaniel Grumberg Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword)
7339fc45ca0SDaniel Grumberg .appendSpace()
7349fc45ca0SDaniel Grumberg .append(getFragmentsForType(Decl->getUnderlyingType(),
7359fc45ca0SDaniel Grumberg Decl->getASTContext(), After))
7369fc45ca0SDaniel Grumberg .append(std::move(After))
7379fc45ca0SDaniel Grumberg .appendSpace()
7389fc45ca0SDaniel Grumberg .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
7399fc45ca0SDaniel Grumberg
7409fc45ca0SDaniel Grumberg return Fragments;
7419fc45ca0SDaniel Grumberg }
7429fc45ca0SDaniel Grumberg
7439b36e126SZixu Wang template <typename FunctionT>
7449b36e126SZixu Wang FunctionSignature
getFunctionSignature(const FunctionT * Function)7459b36e126SZixu Wang DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) {
7469b36e126SZixu Wang FunctionSignature Signature;
7479b36e126SZixu Wang
7489b36e126SZixu Wang DeclarationFragments ReturnType, After;
7499b36e126SZixu Wang ReturnType
7509b36e126SZixu Wang .append(getFragmentsForType(Function->getReturnType(),
7519b36e126SZixu Wang Function->getASTContext(), After))
7529b36e126SZixu Wang .append(std::move(After));
7539b36e126SZixu Wang Signature.setReturnType(ReturnType);
7549b36e126SZixu Wang
7559b36e126SZixu Wang for (const auto *Param : Function->parameters())
7569b36e126SZixu Wang Signature.addParameter(Param->getName(), getFragmentsForParam(Param));
75789f6b26fSZixu Wang
75889f6b26fSZixu Wang return Signature;
75989f6b26fSZixu Wang }
76089f6b26fSZixu Wang
7619b36e126SZixu Wang // Instantiate template for FunctionDecl.
7629b36e126SZixu Wang template FunctionSignature
7639b36e126SZixu Wang DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *);
7649b36e126SZixu Wang
7659b36e126SZixu Wang // Instantiate template for ObjCMethodDecl.
7669b36e126SZixu Wang template FunctionSignature
7679b36e126SZixu Wang DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *);
7689b36e126SZixu Wang
76989f6b26fSZixu Wang // Subheading of a symbol defaults to its name.
77089f6b26fSZixu Wang DeclarationFragments
getSubHeading(const NamedDecl * Decl)77189f6b26fSZixu Wang DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) {
77289f6b26fSZixu Wang DeclarationFragments Fragments;
77389f6b26fSZixu Wang if (!Decl->getName().empty())
77489f6b26fSZixu Wang Fragments.append(Decl->getName(),
77589f6b26fSZixu Wang DeclarationFragments::FragmentKind::Identifier);
77689f6b26fSZixu Wang return Fragments;
77789f6b26fSZixu Wang }
7789b36e126SZixu Wang
7799b36e126SZixu Wang // Subheading of an Objective-C method is a `+` or `-` sign indicating whether
7809b36e126SZixu Wang // it's a class method or an instance method, followed by the selector name.
7819b36e126SZixu Wang DeclarationFragments
getSubHeading(const ObjCMethodDecl * Method)7829b36e126SZixu Wang DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) {
7839b36e126SZixu Wang DeclarationFragments Fragments;
7849b36e126SZixu Wang if (Method->isClassMethod())
7859b36e126SZixu Wang Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
7869b36e126SZixu Wang else if (Method->isInstanceMethod())
7879b36e126SZixu Wang Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
7889b36e126SZixu Wang
7899b36e126SZixu Wang return Fragments.append(Method->getNameAsString(),
7909b36e126SZixu Wang DeclarationFragments::FragmentKind::Identifier);
7919b36e126SZixu Wang }
792529a0570SDaniel Grumberg
793529a0570SDaniel Grumberg // Subheading of a symbol defaults to its name.
794529a0570SDaniel Grumberg DeclarationFragments
getSubHeadingForMacro(StringRef Name)795529a0570SDaniel Grumberg DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) {
796529a0570SDaniel Grumberg DeclarationFragments Fragments;
797529a0570SDaniel Grumberg Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
798529a0570SDaniel Grumberg return Fragments;
799529a0570SDaniel Grumberg }
800