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