181ad6265SDimitry Andric //===- ExtractAPI/DeclarationFragments.cpp ----------------------*- C++ -*-===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric ///
981ad6265SDimitry Andric /// \file
1081ad6265SDimitry Andric /// This file implements Declaration Fragments related classes.
1181ad6265SDimitry Andric ///
1281ad6265SDimitry Andric //===----------------------------------------------------------------------===//
1381ad6265SDimitry Andric 
1481ad6265SDimitry Andric #include "clang/ExtractAPI/DeclarationFragments.h"
155f757f3fSDimitry Andric #include "clang/AST/Decl.h"
165f757f3fSDimitry Andric #include "clang/AST/DeclCXX.h"
175f757f3fSDimitry Andric #include "clang/AST/QualTypeNames.h"
185f757f3fSDimitry Andric #include "clang/AST/Type.h"
195f757f3fSDimitry Andric #include "clang/AST/TypeLoc.h"
205f757f3fSDimitry Andric #include "clang/Basic/OperatorKinds.h"
2106c3fb27SDimitry Andric #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
2281ad6265SDimitry Andric #include "clang/Index/USRGeneration.h"
2381ad6265SDimitry Andric #include "llvm/ADT/StringSwitch.h"
245f757f3fSDimitry Andric #include <typeinfo>
2581ad6265SDimitry Andric 
2681ad6265SDimitry Andric using namespace clang::extractapi;
2781ad6265SDimitry Andric using namespace llvm;
2881ad6265SDimitry Andric 
295f757f3fSDimitry Andric namespace {
305f757f3fSDimitry Andric 
findTypeLocForBlockDecl(const clang::TypeSourceInfo * TSInfo,clang::FunctionTypeLoc & Block,clang::FunctionProtoTypeLoc & BlockProto)315f757f3fSDimitry Andric void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo,
325f757f3fSDimitry Andric                              clang::FunctionTypeLoc &Block,
335f757f3fSDimitry Andric                              clang::FunctionProtoTypeLoc &BlockProto) {
345f757f3fSDimitry Andric   if (!TSInfo)
355f757f3fSDimitry Andric     return;
365f757f3fSDimitry Andric 
375f757f3fSDimitry Andric   clang::TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
385f757f3fSDimitry Andric   while (true) {
395f757f3fSDimitry Andric     // Look through qualified types
405f757f3fSDimitry Andric     if (auto QualifiedTL = TL.getAs<clang::QualifiedTypeLoc>()) {
415f757f3fSDimitry Andric       TL = QualifiedTL.getUnqualifiedLoc();
425f757f3fSDimitry Andric       continue;
435f757f3fSDimitry Andric     }
445f757f3fSDimitry Andric 
455f757f3fSDimitry Andric     if (auto AttrTL = TL.getAs<clang::AttributedTypeLoc>()) {
465f757f3fSDimitry Andric       TL = AttrTL.getModifiedLoc();
475f757f3fSDimitry Andric       continue;
485f757f3fSDimitry Andric     }
495f757f3fSDimitry Andric 
505f757f3fSDimitry Andric     // Try to get the function prototype behind the block pointer type,
515f757f3fSDimitry Andric     // then we're done.
525f757f3fSDimitry Andric     if (auto BlockPtr = TL.getAs<clang::BlockPointerTypeLoc>()) {
535f757f3fSDimitry Andric       TL = BlockPtr.getPointeeLoc().IgnoreParens();
545f757f3fSDimitry Andric       Block = TL.getAs<clang::FunctionTypeLoc>();
555f757f3fSDimitry Andric       BlockProto = TL.getAs<clang::FunctionProtoTypeLoc>();
565f757f3fSDimitry Andric     }
575f757f3fSDimitry Andric     break;
585f757f3fSDimitry Andric   }
595f757f3fSDimitry Andric }
605f757f3fSDimitry Andric 
615f757f3fSDimitry Andric } // namespace
625f757f3fSDimitry Andric 
appendSpace()6381ad6265SDimitry Andric DeclarationFragments &DeclarationFragments::appendSpace() {
6481ad6265SDimitry Andric   if (!Fragments.empty()) {
6581ad6265SDimitry Andric     Fragment &Last = Fragments.back();
6681ad6265SDimitry Andric     if (Last.Kind == FragmentKind::Text) {
6781ad6265SDimitry Andric       // Merge the extra space into the last fragment if the last fragment is
6881ad6265SDimitry Andric       // also text.
6981ad6265SDimitry Andric       if (Last.Spelling.back() != ' ') { // avoid extra trailing spaces.
7081ad6265SDimitry Andric         Last.Spelling.push_back(' ');
7181ad6265SDimitry Andric       }
7281ad6265SDimitry Andric     } else {
7381ad6265SDimitry Andric       append(" ", FragmentKind::Text);
7481ad6265SDimitry Andric     }
7581ad6265SDimitry Andric   }
7681ad6265SDimitry Andric 
7781ad6265SDimitry Andric   return *this;
7881ad6265SDimitry Andric }
7981ad6265SDimitry Andric 
getFragmentKindString(DeclarationFragments::FragmentKind Kind)8081ad6265SDimitry Andric StringRef DeclarationFragments::getFragmentKindString(
8181ad6265SDimitry Andric     DeclarationFragments::FragmentKind Kind) {
8281ad6265SDimitry Andric   switch (Kind) {
8381ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::None:
8481ad6265SDimitry Andric     return "none";
8581ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::Keyword:
8681ad6265SDimitry Andric     return "keyword";
8781ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::Attribute:
8881ad6265SDimitry Andric     return "attribute";
8981ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::NumberLiteral:
9081ad6265SDimitry Andric     return "number";
9181ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::StringLiteral:
9281ad6265SDimitry Andric     return "string";
9381ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::Identifier:
9481ad6265SDimitry Andric     return "identifier";
9581ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::TypeIdentifier:
9681ad6265SDimitry Andric     return "typeIdentifier";
9781ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::GenericParameter:
9881ad6265SDimitry Andric     return "genericParameter";
9981ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::ExternalParam:
10081ad6265SDimitry Andric     return "externalParam";
10181ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::InternalParam:
10281ad6265SDimitry Andric     return "internalParam";
10381ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::Text:
10481ad6265SDimitry Andric     return "text";
10581ad6265SDimitry Andric   }
10681ad6265SDimitry Andric 
10781ad6265SDimitry Andric   llvm_unreachable("Unhandled FragmentKind");
10881ad6265SDimitry Andric }
10981ad6265SDimitry Andric 
11081ad6265SDimitry Andric DeclarationFragments::FragmentKind
parseFragmentKindFromString(StringRef S)11181ad6265SDimitry Andric DeclarationFragments::parseFragmentKindFromString(StringRef S) {
11281ad6265SDimitry Andric   return llvm::StringSwitch<FragmentKind>(S)
11381ad6265SDimitry Andric       .Case("keyword", DeclarationFragments::FragmentKind::Keyword)
11481ad6265SDimitry Andric       .Case("attribute", DeclarationFragments::FragmentKind::Attribute)
11581ad6265SDimitry Andric       .Case("number", DeclarationFragments::FragmentKind::NumberLiteral)
11681ad6265SDimitry Andric       .Case("string", DeclarationFragments::FragmentKind::StringLiteral)
11781ad6265SDimitry Andric       .Case("identifier", DeclarationFragments::FragmentKind::Identifier)
11881ad6265SDimitry Andric       .Case("typeIdentifier",
11981ad6265SDimitry Andric             DeclarationFragments::FragmentKind::TypeIdentifier)
12081ad6265SDimitry Andric       .Case("genericParameter",
12181ad6265SDimitry Andric             DeclarationFragments::FragmentKind::GenericParameter)
12281ad6265SDimitry Andric       .Case("internalParam", DeclarationFragments::FragmentKind::InternalParam)
12381ad6265SDimitry Andric       .Case("externalParam", DeclarationFragments::FragmentKind::ExternalParam)
12481ad6265SDimitry Andric       .Case("text", DeclarationFragments::FragmentKind::Text)
12581ad6265SDimitry Andric       .Default(DeclarationFragments::FragmentKind::None);
12681ad6265SDimitry Andric }
12781ad6265SDimitry Andric 
getExceptionSpecificationString(ExceptionSpecificationType ExceptionSpec)1285f757f3fSDimitry Andric DeclarationFragments DeclarationFragments::getExceptionSpecificationString(
1295f757f3fSDimitry Andric     ExceptionSpecificationType ExceptionSpec) {
1305f757f3fSDimitry Andric   DeclarationFragments Fragments;
1315f757f3fSDimitry Andric   switch (ExceptionSpec) {
1325f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_None:
1335f757f3fSDimitry Andric     return Fragments;
1345f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_DynamicNone:
1355f757f3fSDimitry Andric     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
1365f757f3fSDimitry Andric         .append("throw", DeclarationFragments::FragmentKind::Keyword)
1375f757f3fSDimitry Andric         .append("(", DeclarationFragments::FragmentKind::Text)
1385f757f3fSDimitry Andric         .append(")", DeclarationFragments::FragmentKind::Text);
1395f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_Dynamic:
1405f757f3fSDimitry Andric     // FIXME: throw(int), get types of inner expression
1415f757f3fSDimitry Andric     return Fragments;
1425f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_BasicNoexcept:
1435f757f3fSDimitry Andric     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
1445f757f3fSDimitry Andric         .append("noexcept", DeclarationFragments::FragmentKind::Keyword);
1455f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_DependentNoexcept:
1465f757f3fSDimitry Andric     // FIXME: throw(conditional-expression), get expression
1475f757f3fSDimitry Andric     break;
1485f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_NoexceptFalse:
1495f757f3fSDimitry Andric     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
1505f757f3fSDimitry Andric         .append("noexcept", DeclarationFragments::FragmentKind::Keyword)
1515f757f3fSDimitry Andric         .append("(", DeclarationFragments::FragmentKind::Text)
1525f757f3fSDimitry Andric         .append("false", DeclarationFragments::FragmentKind::Keyword)
1535f757f3fSDimitry Andric         .append(")", DeclarationFragments::FragmentKind::Text);
1545f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_NoexceptTrue:
1555f757f3fSDimitry Andric     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
1565f757f3fSDimitry Andric         .append("noexcept", DeclarationFragments::FragmentKind::Keyword)
1575f757f3fSDimitry Andric         .append("(", DeclarationFragments::FragmentKind::Text)
1585f757f3fSDimitry Andric         .append("true", DeclarationFragments::FragmentKind::Keyword)
1595f757f3fSDimitry Andric         .append(")", DeclarationFragments::FragmentKind::Text);
1605f757f3fSDimitry Andric   default:
1615f757f3fSDimitry Andric     return Fragments;
1625f757f3fSDimitry Andric   }
1635f757f3fSDimitry Andric 
1645f757f3fSDimitry Andric   llvm_unreachable("Unhandled exception specification");
1655f757f3fSDimitry Andric }
1665f757f3fSDimitry Andric 
1675f757f3fSDimitry Andric DeclarationFragments
getStructureTypeFragment(const RecordDecl * Record)1685f757f3fSDimitry Andric DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) {
1695f757f3fSDimitry Andric   DeclarationFragments Fragments;
1705f757f3fSDimitry Andric   if (Record->isStruct())
1715f757f3fSDimitry Andric     Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);
1725f757f3fSDimitry Andric   else if (Record->isUnion())
1735f757f3fSDimitry Andric     Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);
1745f757f3fSDimitry Andric   else
1755f757f3fSDimitry Andric     Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);
1765f757f3fSDimitry Andric 
1775f757f3fSDimitry Andric   return Fragments;
1785f757f3fSDimitry Andric }
1795f757f3fSDimitry Andric 
18081ad6265SDimitry Andric // NNS stores C++ nested name specifiers, which are prefixes to qualified names.
18181ad6265SDimitry Andric // Build declaration fragments for NNS recursively so that we have the USR for
18281ad6265SDimitry Andric // every part in a qualified name, and also leaves the actual underlying type
18381ad6265SDimitry Andric // cleaner for its own fragment.
18481ad6265SDimitry Andric DeclarationFragments
getFragmentsForNNS(const NestedNameSpecifier * NNS,ASTContext & Context,DeclarationFragments & After)18581ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS,
18681ad6265SDimitry Andric                                                 ASTContext &Context,
18781ad6265SDimitry Andric                                                 DeclarationFragments &After) {
18881ad6265SDimitry Andric   DeclarationFragments Fragments;
18981ad6265SDimitry Andric   if (NNS->getPrefix())
19081ad6265SDimitry Andric     Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After));
19181ad6265SDimitry Andric 
19281ad6265SDimitry Andric   switch (NNS->getKind()) {
19381ad6265SDimitry Andric   case NestedNameSpecifier::Identifier:
19481ad6265SDimitry Andric     Fragments.append(NNS->getAsIdentifier()->getName(),
19581ad6265SDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
19681ad6265SDimitry Andric     break;
19781ad6265SDimitry Andric 
19881ad6265SDimitry Andric   case NestedNameSpecifier::Namespace: {
19981ad6265SDimitry Andric     const NamespaceDecl *NS = NNS->getAsNamespace();
20081ad6265SDimitry Andric     if (NS->isAnonymousNamespace())
20181ad6265SDimitry Andric       return Fragments;
20281ad6265SDimitry Andric     SmallString<128> USR;
20381ad6265SDimitry Andric     index::generateUSRForDecl(NS, USR);
20481ad6265SDimitry Andric     Fragments.append(NS->getName(),
205bdd1243dSDimitry Andric                      DeclarationFragments::FragmentKind::Identifier, USR, NS);
20681ad6265SDimitry Andric     break;
20781ad6265SDimitry Andric   }
20881ad6265SDimitry Andric 
20981ad6265SDimitry Andric   case NestedNameSpecifier::NamespaceAlias: {
21081ad6265SDimitry Andric     const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias();
21181ad6265SDimitry Andric     SmallString<128> USR;
21281ad6265SDimitry Andric     index::generateUSRForDecl(Alias, USR);
21381ad6265SDimitry Andric     Fragments.append(Alias->getName(),
214bdd1243dSDimitry Andric                      DeclarationFragments::FragmentKind::Identifier, USR,
215bdd1243dSDimitry Andric                      Alias);
21681ad6265SDimitry Andric     break;
21781ad6265SDimitry Andric   }
21881ad6265SDimitry Andric 
21981ad6265SDimitry Andric   case NestedNameSpecifier::Global:
22081ad6265SDimitry Andric     // The global specifier `::` at the beginning. No stored value.
22181ad6265SDimitry Andric     break;
22281ad6265SDimitry Andric 
22381ad6265SDimitry Andric   case NestedNameSpecifier::Super:
22481ad6265SDimitry Andric     // Microsoft's `__super` specifier.
22581ad6265SDimitry Andric     Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword);
22681ad6265SDimitry Andric     break;
22781ad6265SDimitry Andric 
22881ad6265SDimitry Andric   case NestedNameSpecifier::TypeSpecWithTemplate:
22981ad6265SDimitry Andric     // A type prefixed by the `template` keyword.
23081ad6265SDimitry Andric     Fragments.append("template", DeclarationFragments::FragmentKind::Keyword);
23181ad6265SDimitry Andric     Fragments.appendSpace();
23281ad6265SDimitry Andric     // Fallthrough after adding the keyword to handle the actual type.
233bdd1243dSDimitry Andric     [[fallthrough]];
23481ad6265SDimitry Andric 
23581ad6265SDimitry Andric   case NestedNameSpecifier::TypeSpec: {
23681ad6265SDimitry Andric     const Type *T = NNS->getAsType();
23781ad6265SDimitry Andric     // FIXME: Handle C++ template specialization type
23881ad6265SDimitry Andric     Fragments.append(getFragmentsForType(T, Context, After));
23981ad6265SDimitry Andric     break;
24081ad6265SDimitry Andric   }
24181ad6265SDimitry Andric   }
24281ad6265SDimitry Andric 
24381ad6265SDimitry Andric   // Add the separator text `::` for this segment.
24481ad6265SDimitry Andric   return Fragments.append("::", DeclarationFragments::FragmentKind::Text);
24581ad6265SDimitry Andric }
24681ad6265SDimitry Andric 
24781ad6265SDimitry Andric // Recursively build the declaration fragments for an underlying `Type` with
24881ad6265SDimitry Andric // qualifiers removed.
getFragmentsForType(const Type * T,ASTContext & Context,DeclarationFragments & After)24981ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
25081ad6265SDimitry Andric     const Type *T, ASTContext &Context, DeclarationFragments &After) {
25181ad6265SDimitry Andric   assert(T && "invalid type");
25281ad6265SDimitry Andric 
25381ad6265SDimitry Andric   DeclarationFragments Fragments;
25481ad6265SDimitry Andric 
255*7a6dacacSDimitry Andric   // An ElaboratedType is a sugar for types that are referred to using an
256*7a6dacacSDimitry Andric   // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a
257*7a6dacacSDimitry Andric   // qualified name, e.g., `N::M::type`, or both.
258*7a6dacacSDimitry Andric   if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) {
259*7a6dacacSDimitry Andric     ElaboratedTypeKeyword Keyword = ET->getKeyword();
260*7a6dacacSDimitry Andric     if (Keyword != ElaboratedTypeKeyword::None) {
261*7a6dacacSDimitry Andric       Fragments
262*7a6dacacSDimitry Andric           .append(ElaboratedType::getKeywordName(Keyword),
263*7a6dacacSDimitry Andric                   DeclarationFragments::FragmentKind::Keyword)
264*7a6dacacSDimitry Andric           .appendSpace();
265*7a6dacacSDimitry Andric     }
266*7a6dacacSDimitry Andric 
267*7a6dacacSDimitry Andric     if (const NestedNameSpecifier *NNS = ET->getQualifier())
268*7a6dacacSDimitry Andric       Fragments.append(getFragmentsForNNS(NNS, Context, After));
269*7a6dacacSDimitry Andric 
270*7a6dacacSDimitry Andric     // After handling the elaborated keyword or qualified name, build
271*7a6dacacSDimitry Andric     // declaration fragments for the desugared underlying type.
272*7a6dacacSDimitry Andric     return Fragments.append(getFragmentsForType(ET->desugar(), Context, After));
273*7a6dacacSDimitry Andric   }
274*7a6dacacSDimitry Andric 
275*7a6dacacSDimitry Andric   // If the type is a typedefed type, get the underlying TypedefNameDecl for a
276*7a6dacacSDimitry Andric   // direct reference to the typedef instead of the wrapped type.
277*7a6dacacSDimitry Andric 
278*7a6dacacSDimitry Andric   // 'id' type is a typedef for an ObjCObjectPointerType
279*7a6dacacSDimitry Andric   //  we treat it as a typedef
280*7a6dacacSDimitry Andric   if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) {
281*7a6dacacSDimitry Andric     const TypedefNameDecl *Decl = TypedefTy->getDecl();
282*7a6dacacSDimitry Andric     TypedefUnderlyingTypeResolver TypedefResolver(Context);
283*7a6dacacSDimitry Andric     std::string USR = TypedefResolver.getUSRForType(QualType(T, 0));
284*7a6dacacSDimitry Andric 
285*7a6dacacSDimitry Andric     if (T->isObjCIdType()) {
286*7a6dacacSDimitry Andric       return Fragments.append(Decl->getName(),
287*7a6dacacSDimitry Andric                               DeclarationFragments::FragmentKind::Keyword);
288*7a6dacacSDimitry Andric     }
289*7a6dacacSDimitry Andric 
290*7a6dacacSDimitry Andric     return Fragments.append(
291*7a6dacacSDimitry Andric         Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier,
292*7a6dacacSDimitry Andric         USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0)));
293*7a6dacacSDimitry Andric   }
294*7a6dacacSDimitry Andric 
29581ad6265SDimitry Andric   // Declaration fragments of a pointer type is the declaration fragments of
29606c3fb27SDimitry Andric   // the pointee type followed by a `*`,
2975f757f3fSDimitry Andric   if (T->isPointerType() && !T->isFunctionPointerType())
29881ad6265SDimitry Andric     return Fragments
29981ad6265SDimitry Andric         .append(getFragmentsForType(T->getPointeeType(), Context, After))
30081ad6265SDimitry Andric         .append(" *", DeclarationFragments::FragmentKind::Text);
30106c3fb27SDimitry Andric 
30206c3fb27SDimitry Andric   // For Objective-C `id` and `Class` pointers
30306c3fb27SDimitry Andric   // we do not spell out the `*`.
30406c3fb27SDimitry Andric   if (T->isObjCObjectPointerType() &&
30506c3fb27SDimitry Andric       !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) {
30606c3fb27SDimitry Andric 
30706c3fb27SDimitry Andric     Fragments.append(getFragmentsForType(T->getPointeeType(), Context, After));
30806c3fb27SDimitry Andric 
30906c3fb27SDimitry Andric     // id<protocol> is an qualified id type
31006c3fb27SDimitry Andric     // id<protocol>* is not an qualified id type
31106c3fb27SDimitry Andric     if (!T->getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) {
31206c3fb27SDimitry Andric       Fragments.append(" *", DeclarationFragments::FragmentKind::Text);
31306c3fb27SDimitry Andric     }
31406c3fb27SDimitry Andric 
31506c3fb27SDimitry Andric     return Fragments;
31681ad6265SDimitry Andric   }
31781ad6265SDimitry Andric 
31881ad6265SDimitry Andric   // Declaration fragments of a lvalue reference type is the declaration
31981ad6265SDimitry Andric   // fragments of the underlying type followed by a `&`.
32081ad6265SDimitry Andric   if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T))
32181ad6265SDimitry Andric     return Fragments
32281ad6265SDimitry Andric         .append(
32381ad6265SDimitry Andric             getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After))
32481ad6265SDimitry Andric         .append(" &", DeclarationFragments::FragmentKind::Text);
32581ad6265SDimitry Andric 
32681ad6265SDimitry Andric   // Declaration fragments of a rvalue reference type is the declaration
32781ad6265SDimitry Andric   // fragments of the underlying type followed by a `&&`.
32881ad6265SDimitry Andric   if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T))
32981ad6265SDimitry Andric     return Fragments
33081ad6265SDimitry Andric         .append(
33181ad6265SDimitry Andric             getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After))
33281ad6265SDimitry Andric         .append(" &&", DeclarationFragments::FragmentKind::Text);
33381ad6265SDimitry Andric 
33481ad6265SDimitry Andric   // Declaration fragments of an array-typed variable have two parts:
33581ad6265SDimitry Andric   // 1. the element type of the array that appears before the variable name;
33681ad6265SDimitry Andric   // 2. array brackets `[(0-9)?]` that appear after the variable name.
33781ad6265SDimitry Andric   if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) {
33881ad6265SDimitry Andric     // Build the "after" part first because the inner element type might also
33981ad6265SDimitry Andric     // be an array-type. For example `int matrix[3][4]` which has a type of
34081ad6265SDimitry Andric     // "(array 3 of (array 4 of ints))."
34181ad6265SDimitry Andric     // Push the array size part first to make sure they are in the right order.
34281ad6265SDimitry Andric     After.append("[", DeclarationFragments::FragmentKind::Text);
34381ad6265SDimitry Andric 
34481ad6265SDimitry Andric     switch (AT->getSizeModifier()) {
3455f757f3fSDimitry Andric     case ArraySizeModifier::Normal:
34681ad6265SDimitry Andric       break;
3475f757f3fSDimitry Andric     case ArraySizeModifier::Static:
34881ad6265SDimitry Andric       Fragments.append("static", DeclarationFragments::FragmentKind::Keyword);
34981ad6265SDimitry Andric       break;
3505f757f3fSDimitry Andric     case ArraySizeModifier::Star:
35181ad6265SDimitry Andric       Fragments.append("*", DeclarationFragments::FragmentKind::Text);
35281ad6265SDimitry Andric       break;
35381ad6265SDimitry Andric     }
35481ad6265SDimitry Andric 
35581ad6265SDimitry Andric     if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
35681ad6265SDimitry Andric       // FIXME: right now this would evaluate any expressions/macros written in
35781ad6265SDimitry Andric       // the original source to concrete values. For example
35881ad6265SDimitry Andric       // `int nums[MAX]` -> `int nums[100]`
35981ad6265SDimitry Andric       // `char *str[5 + 1]` -> `char *str[6]`
36081ad6265SDimitry Andric       SmallString<128> Size;
36181ad6265SDimitry Andric       CAT->getSize().toStringUnsigned(Size);
36281ad6265SDimitry Andric       After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral);
36381ad6265SDimitry Andric     }
36481ad6265SDimitry Andric 
36581ad6265SDimitry Andric     After.append("]", DeclarationFragments::FragmentKind::Text);
36681ad6265SDimitry Andric 
36781ad6265SDimitry Andric     return Fragments.append(
36881ad6265SDimitry Andric         getFragmentsForType(AT->getElementType(), Context, After));
36981ad6265SDimitry Andric   }
37081ad6265SDimitry Andric 
37106c3fb27SDimitry Andric   // Everything we care about has been handled now, reduce to the canonical
37206c3fb27SDimitry Andric   // unqualified base type.
37306c3fb27SDimitry Andric   QualType Base = T->getCanonicalTypeUnqualified();
37406c3fb27SDimitry Andric 
37581ad6265SDimitry Andric   // If the base type is a TagType (struct/interface/union/class/enum), let's
37681ad6265SDimitry Andric   // get the underlying Decl for better names and USRs.
37781ad6265SDimitry Andric   if (const TagType *TagTy = dyn_cast<TagType>(Base)) {
37881ad6265SDimitry Andric     const TagDecl *Decl = TagTy->getDecl();
37981ad6265SDimitry Andric     // Anonymous decl, skip this fragment.
38081ad6265SDimitry Andric     if (Decl->getName().empty())
38181ad6265SDimitry Andric       return Fragments;
38281ad6265SDimitry Andric     SmallString<128> TagUSR;
38381ad6265SDimitry Andric     clang::index::generateUSRForDecl(Decl, TagUSR);
38481ad6265SDimitry Andric     return Fragments.append(Decl->getName(),
38581ad6265SDimitry Andric                             DeclarationFragments::FragmentKind::TypeIdentifier,
386bdd1243dSDimitry Andric                             TagUSR, Decl);
38781ad6265SDimitry Andric   }
38881ad6265SDimitry Andric 
38981ad6265SDimitry Andric   // If the base type is an ObjCInterfaceType, use the underlying
39081ad6265SDimitry Andric   // ObjCInterfaceDecl for the true USR.
39181ad6265SDimitry Andric   if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) {
39281ad6265SDimitry Andric     const auto *Decl = ObjCIT->getDecl();
39381ad6265SDimitry Andric     SmallString<128> USR;
39481ad6265SDimitry Andric     index::generateUSRForDecl(Decl, USR);
39581ad6265SDimitry Andric     return Fragments.append(Decl->getName(),
39681ad6265SDimitry Andric                             DeclarationFragments::FragmentKind::TypeIdentifier,
397bdd1243dSDimitry Andric                             USR, Decl);
39881ad6265SDimitry Andric   }
39981ad6265SDimitry Andric 
40081ad6265SDimitry Andric   // Default fragment builder for other kinds of types (BuiltinType etc.)
40181ad6265SDimitry Andric   SmallString<128> USR;
40281ad6265SDimitry Andric   clang::index::generateUSRForType(Base, Context, USR);
40381ad6265SDimitry Andric   Fragments.append(Base.getAsString(),
40481ad6265SDimitry Andric                    DeclarationFragments::FragmentKind::TypeIdentifier, USR);
40581ad6265SDimitry Andric 
40681ad6265SDimitry Andric   return Fragments;
40781ad6265SDimitry Andric }
40881ad6265SDimitry Andric 
40981ad6265SDimitry Andric DeclarationFragments
getFragmentsForQualifiers(const Qualifiers Quals)41081ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) {
41181ad6265SDimitry Andric   DeclarationFragments Fragments;
41281ad6265SDimitry Andric   if (Quals.hasConst())
41381ad6265SDimitry Andric     Fragments.append("const", DeclarationFragments::FragmentKind::Keyword);
41481ad6265SDimitry Andric   if (Quals.hasVolatile())
41581ad6265SDimitry Andric     Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword);
41681ad6265SDimitry Andric   if (Quals.hasRestrict())
41781ad6265SDimitry Andric     Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword);
41881ad6265SDimitry Andric 
41981ad6265SDimitry Andric   return Fragments;
42081ad6265SDimitry Andric }
42181ad6265SDimitry Andric 
getFragmentsForType(const QualType QT,ASTContext & Context,DeclarationFragments & After)42281ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
42381ad6265SDimitry Andric     const QualType QT, ASTContext &Context, DeclarationFragments &After) {
42481ad6265SDimitry Andric   assert(!QT.isNull() && "invalid type");
42581ad6265SDimitry Andric 
42681ad6265SDimitry Andric   if (const ParenType *PT = dyn_cast<ParenType>(QT)) {
42781ad6265SDimitry Andric     After.append(")", DeclarationFragments::FragmentKind::Text);
42881ad6265SDimitry Andric     return getFragmentsForType(PT->getInnerType(), Context, After)
42981ad6265SDimitry Andric         .append("(", DeclarationFragments::FragmentKind::Text);
43081ad6265SDimitry Andric   }
43181ad6265SDimitry Andric 
43281ad6265SDimitry Andric   const SplitQualType SQT = QT.split();
43381ad6265SDimitry Andric   DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals),
43481ad6265SDimitry Andric                        TypeFragments =
43581ad6265SDimitry Andric                            getFragmentsForType(SQT.Ty, Context, After);
4365f757f3fSDimitry Andric   if (QT.getAsString() == "_Bool")
4375f757f3fSDimitry Andric     TypeFragments.replace("bool", 0);
4385f757f3fSDimitry Andric 
43981ad6265SDimitry Andric   if (QualsFragments.getFragments().empty())
44081ad6265SDimitry Andric     return TypeFragments;
44181ad6265SDimitry Andric 
44281ad6265SDimitry Andric   // Use east qualifier for pointer types
44381ad6265SDimitry Andric   // For example:
44481ad6265SDimitry Andric   // ```
44581ad6265SDimitry Andric   // int *   const
44681ad6265SDimitry Andric   // ^----   ^----
44781ad6265SDimitry Andric   //  type    qualifier
44881ad6265SDimitry Andric   // ^-----------------
44981ad6265SDimitry Andric   //  const pointer to int
45081ad6265SDimitry Andric   // ```
45181ad6265SDimitry Andric   // should not be reconstructed as
45281ad6265SDimitry Andric   // ```
45381ad6265SDimitry Andric   // const       int       *
45481ad6265SDimitry Andric   // ^----       ^--
45581ad6265SDimitry Andric   //  qualifier   type
45681ad6265SDimitry Andric   // ^----------------     ^
45781ad6265SDimitry Andric   //  pointer to const int
45881ad6265SDimitry Andric   // ```
45981ad6265SDimitry Andric   if (SQT.Ty->isAnyPointerType())
46081ad6265SDimitry Andric     return TypeFragments.appendSpace().append(std::move(QualsFragments));
46181ad6265SDimitry Andric 
46281ad6265SDimitry Andric   return QualsFragments.appendSpace().append(std::move(TypeFragments));
46381ad6265SDimitry Andric }
46481ad6265SDimitry Andric 
getFragmentsForNamespace(const NamespaceDecl * Decl)4655f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace(
4665f757f3fSDimitry Andric     const NamespaceDecl *Decl) {
4675f757f3fSDimitry Andric   DeclarationFragments Fragments;
4685f757f3fSDimitry Andric   Fragments.append("namespace", DeclarationFragments::FragmentKind::Keyword);
4695f757f3fSDimitry Andric   if (!Decl->isAnonymousNamespace())
4705f757f3fSDimitry Andric     Fragments.appendSpace().append(
4715f757f3fSDimitry Andric         Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
4725f757f3fSDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
4735f757f3fSDimitry Andric }
4745f757f3fSDimitry Andric 
47581ad6265SDimitry Andric DeclarationFragments
getFragmentsForVar(const VarDecl * Var)47681ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
47781ad6265SDimitry Andric   DeclarationFragments Fragments;
4785f757f3fSDimitry Andric   if (Var->isConstexpr())
4795f757f3fSDimitry Andric     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
4805f757f3fSDimitry Andric         .appendSpace();
4815f757f3fSDimitry Andric 
48281ad6265SDimitry Andric   StorageClass SC = Var->getStorageClass();
48381ad6265SDimitry Andric   if (SC != SC_None)
48481ad6265SDimitry Andric     Fragments
48581ad6265SDimitry Andric         .append(VarDecl::getStorageClassSpecifierString(SC),
48681ad6265SDimitry Andric                 DeclarationFragments::FragmentKind::Keyword)
48781ad6265SDimitry Andric         .appendSpace();
48881ad6265SDimitry Andric 
48981ad6265SDimitry Andric   // Capture potential fragments that needs to be placed after the variable name
49081ad6265SDimitry Andric   // ```
49181ad6265SDimitry Andric   // int nums[5];
49281ad6265SDimitry Andric   // char (*ptr_to_array)[6];
49381ad6265SDimitry Andric   // ```
49481ad6265SDimitry Andric   DeclarationFragments After;
4955f757f3fSDimitry Andric   FunctionTypeLoc BlockLoc;
4965f757f3fSDimitry Andric   FunctionProtoTypeLoc BlockProtoLoc;
4975f757f3fSDimitry Andric   findTypeLocForBlockDecl(Var->getTypeSourceInfo(), BlockLoc, BlockProtoLoc);
4985f757f3fSDimitry Andric 
4995f757f3fSDimitry Andric   if (!BlockLoc) {
5005f757f3fSDimitry Andric     QualType T = Var->getTypeSourceInfo()
5015f757f3fSDimitry Andric                      ? Var->getTypeSourceInfo()->getType()
5025f757f3fSDimitry Andric                      : Var->getASTContext().getUnqualifiedObjCPointerType(
5035f757f3fSDimitry Andric                            Var->getType());
5045f757f3fSDimitry Andric 
5055f757f3fSDimitry Andric     Fragments.append(getFragmentsForType(T, Var->getASTContext(), After))
5065f757f3fSDimitry Andric         .appendSpace();
5075f757f3fSDimitry Andric   } else {
5085f757f3fSDimitry Andric     Fragments.append(getFragmentsForBlock(Var, BlockLoc, BlockProtoLoc, After));
5095f757f3fSDimitry Andric   }
5105f757f3fSDimitry Andric 
5115f757f3fSDimitry Andric   return Fragments
5125f757f3fSDimitry Andric       .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
5135f757f3fSDimitry Andric       .append(std::move(After))
5145f757f3fSDimitry Andric       .append(";", DeclarationFragments::FragmentKind::Text);
5155f757f3fSDimitry Andric }
5165f757f3fSDimitry Andric 
5175f757f3fSDimitry Andric DeclarationFragments
getFragmentsForVarTemplate(const VarDecl * Var)5185f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) {
5195f757f3fSDimitry Andric   DeclarationFragments Fragments;
5205f757f3fSDimitry Andric   if (Var->isConstexpr())
5215f757f3fSDimitry Andric     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
5225f757f3fSDimitry Andric         .appendSpace();
5235f757f3fSDimitry Andric   QualType T =
5245f757f3fSDimitry Andric       Var->getTypeSourceInfo()
5255f757f3fSDimitry Andric           ? Var->getTypeSourceInfo()->getType()
5265f757f3fSDimitry Andric           : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType());
5275f757f3fSDimitry Andric 
5285f757f3fSDimitry Andric   // Might be a member, so might be static.
5295f757f3fSDimitry Andric   if (Var->isStaticDataMember())
5305f757f3fSDimitry Andric     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
5315f757f3fSDimitry Andric         .appendSpace();
5325f757f3fSDimitry Andric 
5335f757f3fSDimitry Andric   DeclarationFragments After;
5345f757f3fSDimitry Andric   DeclarationFragments ArgumentFragment =
5355f757f3fSDimitry Andric       getFragmentsForType(T, Var->getASTContext(), After);
5365f757f3fSDimitry Andric   if (ArgumentFragment.begin()->Spelling.substr(0, 14).compare(
5375f757f3fSDimitry Andric           "type-parameter") == 0) {
5385f757f3fSDimitry Andric     std::string ProperArgName = getNameForTemplateArgument(
5395f757f3fSDimitry Andric         Var->getDescribedVarTemplate()->getTemplateParameters()->asArray(),
5405f757f3fSDimitry Andric         ArgumentFragment.begin()->Spelling);
5415f757f3fSDimitry Andric     ArgumentFragment.begin()->Spelling.swap(ProperArgName);
5425f757f3fSDimitry Andric   }
5435f757f3fSDimitry Andric   Fragments.append(std::move(ArgumentFragment))
54481ad6265SDimitry Andric       .appendSpace()
54581ad6265SDimitry Andric       .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
5465f757f3fSDimitry Andric       .append(";", DeclarationFragments::FragmentKind::Text);
5475f757f3fSDimitry Andric   return Fragments;
54881ad6265SDimitry Andric }
54981ad6265SDimitry Andric 
55081ad6265SDimitry Andric DeclarationFragments
getFragmentsForParam(const ParmVarDecl * Param)55181ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) {
55281ad6265SDimitry Andric   DeclarationFragments Fragments, After;
55381ad6265SDimitry Andric 
5545f757f3fSDimitry Andric   auto *TSInfo = Param->getTypeSourceInfo();
5555f757f3fSDimitry Andric 
5565f757f3fSDimitry Andric   QualType T = TSInfo ? TSInfo->getType()
55781ad6265SDimitry Andric                       : Param->getASTContext().getUnqualifiedObjCPointerType(
55881ad6265SDimitry Andric                             Param->getType());
55981ad6265SDimitry Andric 
5605f757f3fSDimitry Andric   FunctionTypeLoc BlockLoc;
5615f757f3fSDimitry Andric   FunctionProtoTypeLoc BlockProtoLoc;
5625f757f3fSDimitry Andric   findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc);
56381ad6265SDimitry Andric 
5645f757f3fSDimitry Andric   DeclarationFragments TypeFragments;
5655f757f3fSDimitry Andric   if (BlockLoc)
5665f757f3fSDimitry Andric     TypeFragments.append(
5675f757f3fSDimitry Andric         getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After));
5685f757f3fSDimitry Andric   else
5695f757f3fSDimitry Andric     TypeFragments.append(getFragmentsForType(T, Param->getASTContext(), After));
5705f757f3fSDimitry Andric 
5715f757f3fSDimitry Andric   if (TypeFragments.begin()->Spelling.substr(0, 14).compare("type-parameter") ==
5725f757f3fSDimitry Andric       0) {
5735f757f3fSDimitry Andric     std::string ProperArgName = getNameForTemplateArgument(
5745f757f3fSDimitry Andric         dyn_cast<FunctionDecl>(Param->getDeclContext())
5755f757f3fSDimitry Andric             ->getDescribedFunctionTemplate()
5765f757f3fSDimitry Andric             ->getTemplateParameters()
5775f757f3fSDimitry Andric             ->asArray(),
5785f757f3fSDimitry Andric         TypeFragments.begin()->Spelling);
5795f757f3fSDimitry Andric     TypeFragments.begin()->Spelling.swap(ProperArgName);
5805f757f3fSDimitry Andric   }
5815f757f3fSDimitry Andric 
5825f757f3fSDimitry Andric   if (Param->isObjCMethodParameter()) {
58381ad6265SDimitry Andric     Fragments.append("(", DeclarationFragments::FragmentKind::Text)
58481ad6265SDimitry Andric         .append(std::move(TypeFragments))
5855f757f3fSDimitry Andric         .append(std::move(After))
5865f757f3fSDimitry Andric         .append(") ", DeclarationFragments::FragmentKind::Text)
5875f757f3fSDimitry Andric         .append(Param->getName(),
5885f757f3fSDimitry Andric                 DeclarationFragments::FragmentKind::InternalParam);
5895f757f3fSDimitry Andric   } else {
5905f757f3fSDimitry Andric     Fragments.append(std::move(TypeFragments));
5915f757f3fSDimitry Andric     if (!T->isBlockPointerType())
5925f757f3fSDimitry Andric       Fragments.appendSpace();
5935f757f3fSDimitry Andric     Fragments
59481ad6265SDimitry Andric         .append(Param->getName(),
59581ad6265SDimitry Andric                 DeclarationFragments::FragmentKind::InternalParam)
59681ad6265SDimitry Andric         .append(std::move(After));
59781ad6265SDimitry Andric   }
5985f757f3fSDimitry Andric   return Fragments;
5995f757f3fSDimitry Andric }
6005f757f3fSDimitry Andric 
getFragmentsForBlock(const NamedDecl * BlockDecl,FunctionTypeLoc & Block,FunctionProtoTypeLoc & BlockProto,DeclarationFragments & After)6015f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForBlock(
6025f757f3fSDimitry Andric     const NamedDecl *BlockDecl, FunctionTypeLoc &Block,
6035f757f3fSDimitry Andric     FunctionProtoTypeLoc &BlockProto, DeclarationFragments &After) {
6045f757f3fSDimitry Andric   DeclarationFragments Fragments;
6055f757f3fSDimitry Andric 
6065f757f3fSDimitry Andric   DeclarationFragments RetTyAfter;
6075f757f3fSDimitry Andric   auto ReturnValueFragment = getFragmentsForType(
6085f757f3fSDimitry Andric       Block.getTypePtr()->getReturnType(), BlockDecl->getASTContext(), After);
6095f757f3fSDimitry Andric 
6105f757f3fSDimitry Andric   Fragments.append(std::move(ReturnValueFragment))
6115f757f3fSDimitry Andric       .append(std::move(RetTyAfter))
6125f757f3fSDimitry Andric       .appendSpace()
6135f757f3fSDimitry Andric       .append("(^", DeclarationFragments::FragmentKind::Text);
6145f757f3fSDimitry Andric 
6155f757f3fSDimitry Andric   After.append(")", DeclarationFragments::FragmentKind::Text);
6165f757f3fSDimitry Andric   unsigned NumParams = Block.getNumParams();
6175f757f3fSDimitry Andric 
6185f757f3fSDimitry Andric   if (!BlockProto || NumParams == 0) {
6195f757f3fSDimitry Andric     if (BlockProto && BlockProto.getTypePtr()->isVariadic())
6205f757f3fSDimitry Andric       After.append("(...)", DeclarationFragments::FragmentKind::Text);
6215f757f3fSDimitry Andric     else
6225f757f3fSDimitry Andric       After.append("()", DeclarationFragments::FragmentKind::Text);
6235f757f3fSDimitry Andric   } else {
6245f757f3fSDimitry Andric     After.append("(", DeclarationFragments::FragmentKind::Text);
6255f757f3fSDimitry Andric     for (unsigned I = 0; I != NumParams; ++I) {
6265f757f3fSDimitry Andric       if (I)
6275f757f3fSDimitry Andric         After.append(", ", DeclarationFragments::FragmentKind::Text);
6285f757f3fSDimitry Andric       After.append(getFragmentsForParam(Block.getParam(I)));
6295f757f3fSDimitry Andric       if (I == NumParams - 1 && BlockProto.getTypePtr()->isVariadic())
6305f757f3fSDimitry Andric         After.append(", ...", DeclarationFragments::FragmentKind::Text);
6315f757f3fSDimitry Andric     }
6325f757f3fSDimitry Andric     After.append(")", DeclarationFragments::FragmentKind::Text);
6335f757f3fSDimitry Andric   }
6345f757f3fSDimitry Andric 
6355f757f3fSDimitry Andric   return Fragments;
6365f757f3fSDimitry Andric }
63781ad6265SDimitry Andric 
63881ad6265SDimitry Andric DeclarationFragments
getFragmentsForFunction(const FunctionDecl * Func)63981ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
64081ad6265SDimitry Andric   DeclarationFragments Fragments;
64181ad6265SDimitry Andric   // FIXME: Handle template specialization
64281ad6265SDimitry Andric   switch (Func->getStorageClass()) {
64381ad6265SDimitry Andric   case SC_None:
64481ad6265SDimitry Andric   case SC_PrivateExtern:
64581ad6265SDimitry Andric     break;
64681ad6265SDimitry Andric   case SC_Extern:
64781ad6265SDimitry Andric     Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword)
64881ad6265SDimitry Andric         .appendSpace();
64981ad6265SDimitry Andric     break;
65081ad6265SDimitry Andric   case SC_Static:
65181ad6265SDimitry Andric     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
65281ad6265SDimitry Andric         .appendSpace();
65381ad6265SDimitry Andric     break;
65481ad6265SDimitry Andric   case SC_Auto:
65581ad6265SDimitry Andric   case SC_Register:
65681ad6265SDimitry Andric     llvm_unreachable("invalid for functions");
65781ad6265SDimitry Andric   }
6585f757f3fSDimitry Andric   if (Func->isConsteval()) // if consteval, it is also constexpr
6595f757f3fSDimitry Andric     Fragments.append("consteval", DeclarationFragments::FragmentKind::Keyword)
6605f757f3fSDimitry Andric         .appendSpace();
6615f757f3fSDimitry Andric   else if (Func->isConstexpr())
6625f757f3fSDimitry Andric     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
6635f757f3fSDimitry Andric         .appendSpace();
66481ad6265SDimitry Andric 
66581ad6265SDimitry Andric   // FIXME: Is `after` actually needed here?
66681ad6265SDimitry Andric   DeclarationFragments After;
6675f757f3fSDimitry Andric   auto ReturnValueFragment =
6685f757f3fSDimitry Andric       getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After);
6695f757f3fSDimitry Andric   if (ReturnValueFragment.begin()->Spelling.substr(0, 14).compare(
6705f757f3fSDimitry Andric           "type-parameter") == 0) {
6715f757f3fSDimitry Andric     std::string ProperArgName =
6725f757f3fSDimitry Andric         getNameForTemplateArgument(Func->getDescribedFunctionTemplate()
6735f757f3fSDimitry Andric                                        ->getTemplateParameters()
6745f757f3fSDimitry Andric                                        ->asArray(),
6755f757f3fSDimitry Andric                                    ReturnValueFragment.begin()->Spelling);
6765f757f3fSDimitry Andric     ReturnValueFragment.begin()->Spelling.swap(ProperArgName);
6775f757f3fSDimitry Andric   }
6785f757f3fSDimitry Andric 
6795f757f3fSDimitry Andric   Fragments.append(std::move(ReturnValueFragment))
68081ad6265SDimitry Andric       .appendSpace()
6815f757f3fSDimitry Andric       .append(Func->getName(), DeclarationFragments::FragmentKind::Identifier);
6825f757f3fSDimitry Andric 
6835f757f3fSDimitry Andric   if (Func->getTemplateSpecializationInfo()) {
6845f757f3fSDimitry Andric     Fragments.append("<", DeclarationFragments::FragmentKind::Text);
6855f757f3fSDimitry Andric 
6865f757f3fSDimitry Andric     for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) {
6875f757f3fSDimitry Andric       if (i)
6885f757f3fSDimitry Andric         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
6895f757f3fSDimitry Andric       Fragments.append(
6905f757f3fSDimitry Andric           getFragmentsForType(Func->getParamDecl(i)->getType(),
6915f757f3fSDimitry Andric                               Func->getParamDecl(i)->getASTContext(), After));
6925f757f3fSDimitry Andric     }
6935f757f3fSDimitry Andric     Fragments.append(">", DeclarationFragments::FragmentKind::Text);
6945f757f3fSDimitry Andric   }
6955f757f3fSDimitry Andric   Fragments.append(std::move(After));
69681ad6265SDimitry Andric 
69781ad6265SDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
6985f757f3fSDimitry Andric   unsigned NumParams = Func->getNumParams();
6995f757f3fSDimitry Andric   for (unsigned i = 0; i != NumParams; ++i) {
70081ad6265SDimitry Andric     if (i)
70181ad6265SDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
70281ad6265SDimitry Andric     Fragments.append(getFragmentsForParam(Func->getParamDecl(i)));
70381ad6265SDimitry Andric   }
7045f757f3fSDimitry Andric 
7055f757f3fSDimitry Andric   if (Func->isVariadic()) {
7065f757f3fSDimitry Andric     if (NumParams > 0)
7075f757f3fSDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
7085f757f3fSDimitry Andric     Fragments.append("...", DeclarationFragments::FragmentKind::Text);
7095f757f3fSDimitry Andric   }
71081ad6265SDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
71181ad6265SDimitry Andric 
7125f757f3fSDimitry Andric   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
7135f757f3fSDimitry Andric       Func->getExceptionSpecType()));
7145f757f3fSDimitry Andric 
71506c3fb27SDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
71681ad6265SDimitry Andric }
71781ad6265SDimitry Andric 
getFragmentsForEnumConstant(const EnumConstantDecl * EnumConstDecl)71881ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant(
71981ad6265SDimitry Andric     const EnumConstantDecl *EnumConstDecl) {
72081ad6265SDimitry Andric   DeclarationFragments Fragments;
72181ad6265SDimitry Andric   return Fragments.append(EnumConstDecl->getName(),
72281ad6265SDimitry Andric                           DeclarationFragments::FragmentKind::Identifier);
72381ad6265SDimitry Andric }
72481ad6265SDimitry Andric 
72581ad6265SDimitry Andric DeclarationFragments
getFragmentsForEnum(const EnumDecl * EnumDecl)72681ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {
72781ad6265SDimitry Andric   if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl())
72881ad6265SDimitry Andric     return getFragmentsForTypedef(TypedefNameDecl);
72981ad6265SDimitry Andric 
73081ad6265SDimitry Andric   DeclarationFragments Fragments, After;
73181ad6265SDimitry Andric   Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword);
73281ad6265SDimitry Andric 
73381ad6265SDimitry Andric   if (!EnumDecl->getName().empty())
73481ad6265SDimitry Andric     Fragments.appendSpace().append(
73581ad6265SDimitry Andric         EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier);
73681ad6265SDimitry Andric 
73781ad6265SDimitry Andric   QualType IntegerType = EnumDecl->getIntegerType();
73881ad6265SDimitry Andric   if (!IntegerType.isNull())
73981ad6265SDimitry Andric     Fragments.append(": ", DeclarationFragments::FragmentKind::Text)
74081ad6265SDimitry Andric         .append(
74181ad6265SDimitry Andric             getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))
74281ad6265SDimitry Andric         .append(std::move(After));
74381ad6265SDimitry Andric 
74406c3fb27SDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
74581ad6265SDimitry Andric }
74681ad6265SDimitry Andric 
74781ad6265SDimitry Andric DeclarationFragments
getFragmentsForField(const FieldDecl * Field)74881ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) {
74981ad6265SDimitry Andric   DeclarationFragments After;
7505f757f3fSDimitry Andric   DeclarationFragments Fragments;
7515f757f3fSDimitry Andric   if (Field->isMutable())
7525f757f3fSDimitry Andric     Fragments.append("mutable", DeclarationFragments::FragmentKind::Keyword)
7535f757f3fSDimitry Andric         .appendSpace();
7545f757f3fSDimitry Andric   return Fragments
7555f757f3fSDimitry Andric       .append(
7565f757f3fSDimitry Andric           getFragmentsForType(Field->getType(), Field->getASTContext(), After))
75781ad6265SDimitry Andric       .appendSpace()
75881ad6265SDimitry Andric       .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)
7595f757f3fSDimitry Andric       .append(std::move(After))
7605f757f3fSDimitry Andric       .append(";", DeclarationFragments::FragmentKind::Text);
76181ad6265SDimitry Andric }
76281ad6265SDimitry Andric 
getFragmentsForRecordDecl(const RecordDecl * Record)763*7a6dacacSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
764*7a6dacacSDimitry Andric     const RecordDecl *Record) {
76581ad6265SDimitry Andric   if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
76681ad6265SDimitry Andric     return getFragmentsForTypedef(TypedefNameDecl);
76781ad6265SDimitry Andric 
76881ad6265SDimitry Andric   DeclarationFragments Fragments;
769*7a6dacacSDimitry Andric   if (Record->isUnion())
770*7a6dacacSDimitry Andric     Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);
771*7a6dacacSDimitry Andric   else
77281ad6265SDimitry Andric     Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);
77381ad6265SDimitry Andric 
77481ad6265SDimitry Andric   if (!Record->getName().empty())
77581ad6265SDimitry Andric     Fragments.appendSpace().append(
77681ad6265SDimitry Andric         Record->getName(), DeclarationFragments::FragmentKind::Identifier);
77706c3fb27SDimitry Andric 
77806c3fb27SDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
77981ad6265SDimitry Andric }
78081ad6265SDimitry Andric 
getFragmentsForCXXClass(const CXXRecordDecl * Record)7815f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
7825f757f3fSDimitry Andric     const CXXRecordDecl *Record) {
7835f757f3fSDimitry Andric   if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
7845f757f3fSDimitry Andric     return getFragmentsForTypedef(TypedefNameDecl);
7855f757f3fSDimitry Andric 
7865f757f3fSDimitry Andric   DeclarationFragments Fragments;
7875f757f3fSDimitry Andric   Fragments.append(DeclarationFragments::getStructureTypeFragment(Record));
7885f757f3fSDimitry Andric 
7895f757f3fSDimitry Andric   if (!Record->getName().empty())
7905f757f3fSDimitry Andric     Fragments.appendSpace().append(
7915f757f3fSDimitry Andric         Record->getName(), DeclarationFragments::FragmentKind::Identifier);
7925f757f3fSDimitry Andric 
7935f757f3fSDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
7945f757f3fSDimitry Andric }
7955f757f3fSDimitry Andric 
7965f757f3fSDimitry Andric DeclarationFragments
getFragmentsForSpecialCXXMethod(const CXXMethodDecl * Method)7975f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(
7985f757f3fSDimitry Andric     const CXXMethodDecl *Method) {
7995f757f3fSDimitry Andric   DeclarationFragments Fragments;
8005f757f3fSDimitry Andric   std::string Name;
8015f757f3fSDimitry Andric   if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(Method)) {
8025f757f3fSDimitry Andric     Name = Method->getNameAsString();
8035f757f3fSDimitry Andric     if (Constructor->isExplicit())
8045f757f3fSDimitry Andric       Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
8055f757f3fSDimitry Andric           .appendSpace();
8065f757f3fSDimitry Andric   } else if (isa<CXXDestructorDecl>(Method))
8075f757f3fSDimitry Andric     Name = Method->getNameAsString();
8085f757f3fSDimitry Andric 
8095f757f3fSDimitry Andric   DeclarationFragments After;
8105f757f3fSDimitry Andric   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier)
8115f757f3fSDimitry Andric       .append(std::move(After));
8125f757f3fSDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
8135f757f3fSDimitry Andric   for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
8145f757f3fSDimitry Andric     if (i)
8155f757f3fSDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
8165f757f3fSDimitry Andric     Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
8175f757f3fSDimitry Andric   }
8185f757f3fSDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
8195f757f3fSDimitry Andric 
8205f757f3fSDimitry Andric   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
8215f757f3fSDimitry Andric       Method->getExceptionSpecType()));
8225f757f3fSDimitry Andric 
8235f757f3fSDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
8245f757f3fSDimitry Andric }
8255f757f3fSDimitry Andric 
getFragmentsForCXXMethod(const CXXMethodDecl * Method)8265f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
8275f757f3fSDimitry Andric     const CXXMethodDecl *Method) {
8285f757f3fSDimitry Andric   DeclarationFragments Fragments;
8295f757f3fSDimitry Andric   StringRef Name = Method->getName();
8305f757f3fSDimitry Andric   if (Method->isStatic())
8315f757f3fSDimitry Andric     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
8325f757f3fSDimitry Andric         .appendSpace();
8335f757f3fSDimitry Andric   if (Method->isConstexpr())
8345f757f3fSDimitry Andric     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
8355f757f3fSDimitry Andric         .appendSpace();
8365f757f3fSDimitry Andric   if (Method->isVolatile())
8375f757f3fSDimitry Andric     Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword)
8385f757f3fSDimitry Andric         .appendSpace();
8395f757f3fSDimitry Andric 
8405f757f3fSDimitry Andric   // Build return type
8415f757f3fSDimitry Andric   DeclarationFragments After;
8425f757f3fSDimitry Andric   Fragments
8435f757f3fSDimitry Andric       .append(getFragmentsForType(Method->getReturnType(),
8445f757f3fSDimitry Andric                                   Method->getASTContext(), After))
8455f757f3fSDimitry Andric       .appendSpace()
8465f757f3fSDimitry Andric       .append(Name, DeclarationFragments::FragmentKind::Identifier)
8475f757f3fSDimitry Andric       .append(std::move(After));
8485f757f3fSDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
8495f757f3fSDimitry Andric   for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
8505f757f3fSDimitry Andric     if (i)
8515f757f3fSDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
8525f757f3fSDimitry Andric     Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
8535f757f3fSDimitry Andric   }
8545f757f3fSDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
8555f757f3fSDimitry Andric 
8565f757f3fSDimitry Andric   if (Method->isConst())
8575f757f3fSDimitry Andric     Fragments.appendSpace().append("const",
8585f757f3fSDimitry Andric                                    DeclarationFragments::FragmentKind::Keyword);
8595f757f3fSDimitry Andric 
8605f757f3fSDimitry Andric   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
8615f757f3fSDimitry Andric       Method->getExceptionSpecType()));
8625f757f3fSDimitry Andric 
8635f757f3fSDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
8645f757f3fSDimitry Andric }
8655f757f3fSDimitry Andric 
8665f757f3fSDimitry Andric DeclarationFragments
getFragmentsForConversionFunction(const CXXConversionDecl * ConversionFunction)8675f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForConversionFunction(
8685f757f3fSDimitry Andric     const CXXConversionDecl *ConversionFunction) {
8695f757f3fSDimitry Andric   DeclarationFragments Fragments;
8705f757f3fSDimitry Andric 
8715f757f3fSDimitry Andric   if (ConversionFunction->isExplicit())
8725f757f3fSDimitry Andric     Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
8735f757f3fSDimitry Andric         .appendSpace();
8745f757f3fSDimitry Andric 
8755f757f3fSDimitry Andric   Fragments.append("operator", DeclarationFragments::FragmentKind::Keyword)
8765f757f3fSDimitry Andric       .appendSpace();
8775f757f3fSDimitry Andric 
8785f757f3fSDimitry Andric   Fragments
8795f757f3fSDimitry Andric       .append(ConversionFunction->getConversionType().getAsString(),
8805f757f3fSDimitry Andric               DeclarationFragments::FragmentKind::TypeIdentifier)
8815f757f3fSDimitry Andric       .append("(", DeclarationFragments::FragmentKind::Text);
8825f757f3fSDimitry Andric   for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end;
8835f757f3fSDimitry Andric        ++i) {
8845f757f3fSDimitry Andric     if (i)
8855f757f3fSDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
8865f757f3fSDimitry Andric     Fragments.append(getFragmentsForParam(ConversionFunction->getParamDecl(i)));
8875f757f3fSDimitry Andric   }
8885f757f3fSDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
8895f757f3fSDimitry Andric 
8905f757f3fSDimitry Andric   if (ConversionFunction->isConst())
8915f757f3fSDimitry Andric     Fragments.appendSpace().append("const",
8925f757f3fSDimitry Andric                                    DeclarationFragments::FragmentKind::Keyword);
8935f757f3fSDimitry Andric 
8945f757f3fSDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
8955f757f3fSDimitry Andric }
8965f757f3fSDimitry Andric 
8975f757f3fSDimitry Andric DeclarationFragments
getFragmentsForOverloadedOperator(const CXXMethodDecl * Method)8985f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(
8995f757f3fSDimitry Andric     const CXXMethodDecl *Method) {
9005f757f3fSDimitry Andric   DeclarationFragments Fragments;
9015f757f3fSDimitry Andric 
9025f757f3fSDimitry Andric   // Build return type
9035f757f3fSDimitry Andric   DeclarationFragments After;
9045f757f3fSDimitry Andric   Fragments
9055f757f3fSDimitry Andric       .append(getFragmentsForType(Method->getReturnType(),
9065f757f3fSDimitry Andric                                   Method->getASTContext(), After))
9075f757f3fSDimitry Andric       .appendSpace()
9085f757f3fSDimitry Andric       .append(Method->getNameAsString(),
9095f757f3fSDimitry Andric               DeclarationFragments::FragmentKind::Identifier)
9105f757f3fSDimitry Andric       .append(std::move(After));
9115f757f3fSDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
9125f757f3fSDimitry Andric   for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
9135f757f3fSDimitry Andric     if (i)
9145f757f3fSDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
9155f757f3fSDimitry Andric     Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
9165f757f3fSDimitry Andric   }
9175f757f3fSDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
9185f757f3fSDimitry Andric 
9195f757f3fSDimitry Andric   if (Method->isConst())
9205f757f3fSDimitry Andric     Fragments.appendSpace().append("const",
9215f757f3fSDimitry Andric                                    DeclarationFragments::FragmentKind::Keyword);
9225f757f3fSDimitry Andric 
9235f757f3fSDimitry Andric   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
9245f757f3fSDimitry Andric       Method->getExceptionSpecType()));
9255f757f3fSDimitry Andric 
9265f757f3fSDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
9275f757f3fSDimitry Andric }
9285f757f3fSDimitry Andric 
9295f757f3fSDimitry Andric // Get fragments for template parameters, e.g. T in tempalte<typename T> ...
9305f757f3fSDimitry Andric DeclarationFragments
getFragmentsForTemplateParameters(ArrayRef<NamedDecl * > ParameterArray)9315f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForTemplateParameters(
9325f757f3fSDimitry Andric     ArrayRef<NamedDecl *> ParameterArray) {
9335f757f3fSDimitry Andric   DeclarationFragments Fragments;
9345f757f3fSDimitry Andric   for (unsigned i = 0, end = ParameterArray.size(); i != end; ++i) {
9355f757f3fSDimitry Andric     if (i)
9365f757f3fSDimitry Andric       Fragments.append(",", DeclarationFragments::FragmentKind::Text)
9375f757f3fSDimitry Andric           .appendSpace();
9385f757f3fSDimitry Andric 
9395f757f3fSDimitry Andric     const auto *TemplateParam =
9405f757f3fSDimitry Andric         dyn_cast<TemplateTypeParmDecl>(ParameterArray[i]);
9415f757f3fSDimitry Andric     if (!TemplateParam)
9425f757f3fSDimitry Andric       continue;
9435f757f3fSDimitry Andric     if (TemplateParam->hasTypeConstraint())
9445f757f3fSDimitry Andric       Fragments.append(TemplateParam->getTypeConstraint()
9455f757f3fSDimitry Andric                            ->getNamedConcept()
9465f757f3fSDimitry Andric                            ->getName()
9475f757f3fSDimitry Andric                            .str(),
9485f757f3fSDimitry Andric                        DeclarationFragments::FragmentKind::TypeIdentifier);
9495f757f3fSDimitry Andric     else if (TemplateParam->wasDeclaredWithTypename())
9505f757f3fSDimitry Andric       Fragments.append("typename", DeclarationFragments::FragmentKind::Keyword);
9515f757f3fSDimitry Andric     else
9525f757f3fSDimitry Andric       Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);
9535f757f3fSDimitry Andric 
9545f757f3fSDimitry Andric     if (TemplateParam->isParameterPack())
9555f757f3fSDimitry Andric       Fragments.append("...", DeclarationFragments::FragmentKind::Text);
9565f757f3fSDimitry Andric 
9575f757f3fSDimitry Andric     Fragments.appendSpace().append(
9585f757f3fSDimitry Andric         TemplateParam->getName(),
9595f757f3fSDimitry Andric         DeclarationFragments::FragmentKind::GenericParameter);
9605f757f3fSDimitry Andric   }
9615f757f3fSDimitry Andric   return Fragments;
9625f757f3fSDimitry Andric }
9635f757f3fSDimitry Andric 
9645f757f3fSDimitry Andric // Find the name of a template argument from the template's parameters.
getNameForTemplateArgument(const ArrayRef<NamedDecl * > TemplateParameters,std::string TypeParameter)9655f757f3fSDimitry Andric std::string DeclarationFragmentsBuilder::getNameForTemplateArgument(
9665f757f3fSDimitry Andric     const ArrayRef<NamedDecl *> TemplateParameters, std::string TypeParameter) {
9675f757f3fSDimitry Andric   // The arg is a generic parameter from a partial spec, e.g.
9685f757f3fSDimitry Andric   // T in template<typename T> Foo<T, int>.
9695f757f3fSDimitry Andric   //
9705f757f3fSDimitry Andric   // Those names appear as "type-parameter-<index>-<depth>", so we must find its
9715f757f3fSDimitry Andric   // name from the template's parameter list.
9725f757f3fSDimitry Andric   for (unsigned i = 0; i < TemplateParameters.size(); ++i) {
9735f757f3fSDimitry Andric     const auto *Parameter =
9745f757f3fSDimitry Andric         dyn_cast<TemplateTypeParmDecl>(TemplateParameters[i]);
9755f757f3fSDimitry Andric     if (TypeParameter.compare("type-parameter-" +
9765f757f3fSDimitry Andric                               std::to_string(Parameter->getDepth()) + "-" +
9775f757f3fSDimitry Andric                               std::to_string(Parameter->getIndex())) == 0)
9785f757f3fSDimitry Andric       return std::string(TemplateParameters[i]->getName());
9795f757f3fSDimitry Andric   }
9805f757f3fSDimitry Andric   llvm_unreachable("Could not find the name of a template argument.");
9815f757f3fSDimitry Andric }
9825f757f3fSDimitry Andric 
9835f757f3fSDimitry Andric // Get fragments for template arguments, e.g. int in template<typename T>
9845f757f3fSDimitry Andric // Foo<int>;
9855f757f3fSDimitry Andric //
9865f757f3fSDimitry Andric // Note: TemplateParameters is only necessary if the Decl is a
9875f757f3fSDimitry Andric // PartialSpecialization, where we need the parameters to deduce the name of the
9885f757f3fSDimitry Andric // generic arguments.
9895f757f3fSDimitry Andric DeclarationFragments
getFragmentsForTemplateArguments(const ArrayRef<TemplateArgument> TemplateArguments,ASTContext & Context,const std::optional<ArrayRef<NamedDecl * >> TemplateParameters)9905f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForTemplateArguments(
9915f757f3fSDimitry Andric     const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context,
9925f757f3fSDimitry Andric     const std::optional<ArrayRef<NamedDecl *>> TemplateParameters) {
9935f757f3fSDimitry Andric   DeclarationFragments Fragments;
9945f757f3fSDimitry Andric   for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) {
9955f757f3fSDimitry Andric     if (i)
9965f757f3fSDimitry Andric       Fragments.append(",", DeclarationFragments::FragmentKind::Text)
9975f757f3fSDimitry Andric           .appendSpace();
9985f757f3fSDimitry Andric 
9995f757f3fSDimitry Andric     std::string Type = TemplateArguments[i].getAsType().getAsString();
10005f757f3fSDimitry Andric     DeclarationFragments After;
10015f757f3fSDimitry Andric     DeclarationFragments ArgumentFragment =
10025f757f3fSDimitry Andric         getFragmentsForType(TemplateArguments[i].getAsType(), Context, After);
10035f757f3fSDimitry Andric 
10045f757f3fSDimitry Andric     if (ArgumentFragment.begin()->Spelling.substr(0, 14).compare(
10055f757f3fSDimitry Andric             "type-parameter") == 0) {
10065f757f3fSDimitry Andric       std::string ProperArgName = getNameForTemplateArgument(
10075f757f3fSDimitry Andric           TemplateParameters.value(), ArgumentFragment.begin()->Spelling);
10085f757f3fSDimitry Andric       ArgumentFragment.begin()->Spelling.swap(ProperArgName);
10095f757f3fSDimitry Andric     }
10105f757f3fSDimitry Andric     Fragments.append(std::move(ArgumentFragment));
10115f757f3fSDimitry Andric 
10125f757f3fSDimitry Andric     if (TemplateArguments[i].isPackExpansion())
10135f757f3fSDimitry Andric       Fragments.append("...", DeclarationFragments::FragmentKind::Text);
10145f757f3fSDimitry Andric   }
10155f757f3fSDimitry Andric   return Fragments;
10165f757f3fSDimitry Andric }
10175f757f3fSDimitry Andric 
getFragmentsForConcept(const ConceptDecl * Concept)10185f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept(
10195f757f3fSDimitry Andric     const ConceptDecl *Concept) {
10205f757f3fSDimitry Andric   DeclarationFragments Fragments;
10215f757f3fSDimitry Andric   return Fragments
10225f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
10235f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
10245f757f3fSDimitry Andric       .append(getFragmentsForTemplateParameters(
10255f757f3fSDimitry Andric           Concept->getTemplateParameters()->asArray()))
10265f757f3fSDimitry Andric       .append("> ", DeclarationFragments::FragmentKind::Text)
10275f757f3fSDimitry Andric       .append("concept", DeclarationFragments::FragmentKind::Keyword)
10285f757f3fSDimitry Andric       .appendSpace()
10295f757f3fSDimitry Andric       .append(Concept->getName().str(),
10305f757f3fSDimitry Andric               DeclarationFragments::FragmentKind::Identifier)
10315f757f3fSDimitry Andric       .append(";", DeclarationFragments::FragmentKind::Text);
10325f757f3fSDimitry Andric }
10335f757f3fSDimitry Andric 
10345f757f3fSDimitry Andric DeclarationFragments
getFragmentsForRedeclarableTemplate(const RedeclarableTemplateDecl * RedeclarableTemplate)10355f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
10365f757f3fSDimitry Andric     const RedeclarableTemplateDecl *RedeclarableTemplate) {
10375f757f3fSDimitry Andric   DeclarationFragments Fragments;
10385f757f3fSDimitry Andric   Fragments.append("template", DeclarationFragments::FragmentKind::Keyword)
10395f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
10405f757f3fSDimitry Andric       .append(getFragmentsForTemplateParameters(
10415f757f3fSDimitry Andric           RedeclarableTemplate->getTemplateParameters()->asArray()))
10425f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
10435f757f3fSDimitry Andric       .appendSpace();
10445f757f3fSDimitry Andric 
10455f757f3fSDimitry Andric   if (isa<TypeAliasTemplateDecl>(RedeclarableTemplate))
10465f757f3fSDimitry Andric     Fragments.appendSpace()
10475f757f3fSDimitry Andric         .append("using", DeclarationFragments::FragmentKind::Keyword)
10485f757f3fSDimitry Andric         .appendSpace()
10495f757f3fSDimitry Andric         .append(RedeclarableTemplate->getName(),
10505f757f3fSDimitry Andric                 DeclarationFragments::FragmentKind::Identifier);
10515f757f3fSDimitry Andric   // the templated records will be resposbible for injecting their templates
10525f757f3fSDimitry Andric   return Fragments.appendSpace();
10535f757f3fSDimitry Andric }
10545f757f3fSDimitry Andric 
10555f757f3fSDimitry Andric DeclarationFragments
getFragmentsForClassTemplateSpecialization(const ClassTemplateSpecializationDecl * Decl)10565f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization(
10575f757f3fSDimitry Andric     const ClassTemplateSpecializationDecl *Decl) {
10585f757f3fSDimitry Andric   DeclarationFragments Fragments;
10595f757f3fSDimitry Andric   return Fragments
10605f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
10615f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
10625f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
10635f757f3fSDimitry Andric       .appendSpace()
10645f757f3fSDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(
10655f757f3fSDimitry Andric           cast<CXXRecordDecl>(Decl)))
10665f757f3fSDimitry Andric       .pop_back() // there is an extra semicolon now
10675f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
10685f757f3fSDimitry Andric       .append(
10695f757f3fSDimitry Andric           getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(),
10705f757f3fSDimitry Andric                                            Decl->getASTContext(), std::nullopt))
10715f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
10725f757f3fSDimitry Andric       .append(";", DeclarationFragments::FragmentKind::Text);
10735f757f3fSDimitry Andric }
10745f757f3fSDimitry Andric 
10755f757f3fSDimitry Andric DeclarationFragments
getFragmentsForClassTemplatePartialSpecialization(const ClassTemplatePartialSpecializationDecl * Decl)10765f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization(
10775f757f3fSDimitry Andric     const ClassTemplatePartialSpecializationDecl *Decl) {
10785f757f3fSDimitry Andric   DeclarationFragments Fragments;
10795f757f3fSDimitry Andric   return Fragments
10805f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
10815f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
10825f757f3fSDimitry Andric       .append(getFragmentsForTemplateParameters(
10835f757f3fSDimitry Andric           Decl->getTemplateParameters()->asArray()))
10845f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
10855f757f3fSDimitry Andric       .appendSpace()
10865f757f3fSDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(
10875f757f3fSDimitry Andric           cast<CXXRecordDecl>(Decl)))
10885f757f3fSDimitry Andric       .pop_back() // there is an extra semicolon now
10895f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
10905f757f3fSDimitry Andric       .append(getFragmentsForTemplateArguments(
10915f757f3fSDimitry Andric           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
10925f757f3fSDimitry Andric           Decl->getTemplateParameters()->asArray()))
10935f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
10945f757f3fSDimitry Andric       .append(";", DeclarationFragments::FragmentKind::Text);
10955f757f3fSDimitry Andric }
10965f757f3fSDimitry Andric 
10975f757f3fSDimitry Andric DeclarationFragments
getFragmentsForVarTemplateSpecialization(const VarTemplateSpecializationDecl * Decl)10985f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization(
10995f757f3fSDimitry Andric     const VarTemplateSpecializationDecl *Decl) {
11005f757f3fSDimitry Andric   DeclarationFragments Fragments;
11015f757f3fSDimitry Andric   return Fragments
11025f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
11035f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
11045f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
11055f757f3fSDimitry Andric       .appendSpace()
11065f757f3fSDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))
11075f757f3fSDimitry Andric       .pop_back() // there is an extra semicolon now
11085f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
11095f757f3fSDimitry Andric       .append(
11105f757f3fSDimitry Andric           getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(),
11115f757f3fSDimitry Andric                                            Decl->getASTContext(), std::nullopt))
11125f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
11135f757f3fSDimitry Andric       .append(";", DeclarationFragments::FragmentKind::Text);
11145f757f3fSDimitry Andric }
11155f757f3fSDimitry Andric 
11165f757f3fSDimitry Andric DeclarationFragments
getFragmentsForVarTemplatePartialSpecialization(const VarTemplatePartialSpecializationDecl * Decl)11175f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization(
11185f757f3fSDimitry Andric     const VarTemplatePartialSpecializationDecl *Decl) {
11195f757f3fSDimitry Andric   DeclarationFragments Fragments;
11205f757f3fSDimitry Andric   return Fragments
11215f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
11225f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
11235f757f3fSDimitry Andric       // Partial specs may have new params.
11245f757f3fSDimitry Andric       .append(getFragmentsForTemplateParameters(
11255f757f3fSDimitry Andric           Decl->getTemplateParameters()->asArray()))
11265f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
11275f757f3fSDimitry Andric       .appendSpace()
11285f757f3fSDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))
11295f757f3fSDimitry Andric       .pop_back() // there is an extra semicolon now
11305f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
11315f757f3fSDimitry Andric       .append(getFragmentsForTemplateArguments(
11325f757f3fSDimitry Andric           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
11335f757f3fSDimitry Andric           Decl->getTemplateParameters()->asArray()))
11345f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
11355f757f3fSDimitry Andric       .append(";", DeclarationFragments::FragmentKind::Text);
11365f757f3fSDimitry Andric }
11375f757f3fSDimitry Andric 
11385f757f3fSDimitry Andric DeclarationFragments
getFragmentsForFunctionTemplate(const FunctionTemplateDecl * Decl)11395f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(
11405f757f3fSDimitry Andric     const FunctionTemplateDecl *Decl) {
11415f757f3fSDimitry Andric   DeclarationFragments Fragments;
11425f757f3fSDimitry Andric   return Fragments
11435f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
11445f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
11455f757f3fSDimitry Andric       // Partial specs may have new params.
11465f757f3fSDimitry Andric       .append(getFragmentsForTemplateParameters(
11475f757f3fSDimitry Andric           Decl->getTemplateParameters()->asArray()))
11485f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
11495f757f3fSDimitry Andric       .appendSpace()
11505f757f3fSDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForFunction(
11515f757f3fSDimitry Andric           Decl->getAsFunction()));
11525f757f3fSDimitry Andric }
11535f757f3fSDimitry Andric 
11545f757f3fSDimitry Andric DeclarationFragments
getFragmentsForFunctionTemplateSpecialization(const FunctionDecl * Decl)11555f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization(
11565f757f3fSDimitry Andric     const FunctionDecl *Decl) {
11575f757f3fSDimitry Andric   DeclarationFragments Fragments;
11585f757f3fSDimitry Andric   return Fragments
11595f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
11605f757f3fSDimitry Andric       .append("<>", DeclarationFragments::FragmentKind::Text)
11615f757f3fSDimitry Andric       .appendSpace()
11625f757f3fSDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForFunction(Decl));
11635f757f3fSDimitry Andric }
11645f757f3fSDimitry Andric 
116581ad6265SDimitry Andric DeclarationFragments
getFragmentsForMacro(StringRef Name,const MacroDirective * MD)116681ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name,
116781ad6265SDimitry Andric                                                   const MacroDirective *MD) {
116881ad6265SDimitry Andric   DeclarationFragments Fragments;
116981ad6265SDimitry Andric   Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword)
117081ad6265SDimitry Andric       .appendSpace();
117181ad6265SDimitry Andric   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
117281ad6265SDimitry Andric 
117381ad6265SDimitry Andric   auto *MI = MD->getMacroInfo();
117481ad6265SDimitry Andric 
117581ad6265SDimitry Andric   if (MI->isFunctionLike()) {
117681ad6265SDimitry Andric     Fragments.append("(", DeclarationFragments::FragmentKind::Text);
117781ad6265SDimitry Andric     unsigned numParameters = MI->getNumParams();
117881ad6265SDimitry Andric     if (MI->isC99Varargs())
117981ad6265SDimitry Andric       --numParameters;
118081ad6265SDimitry Andric     for (unsigned i = 0; i < numParameters; ++i) {
118181ad6265SDimitry Andric       if (i)
118281ad6265SDimitry Andric         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
118381ad6265SDimitry Andric       Fragments.append(MI->params()[i]->getName(),
118481ad6265SDimitry Andric                        DeclarationFragments::FragmentKind::InternalParam);
118581ad6265SDimitry Andric     }
118681ad6265SDimitry Andric     if (MI->isVariadic()) {
118781ad6265SDimitry Andric       if (numParameters && MI->isC99Varargs())
118881ad6265SDimitry Andric         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
118981ad6265SDimitry Andric       Fragments.append("...", DeclarationFragments::FragmentKind::Text);
119081ad6265SDimitry Andric     }
119181ad6265SDimitry Andric     Fragments.append(")", DeclarationFragments::FragmentKind::Text);
119281ad6265SDimitry Andric   }
119381ad6265SDimitry Andric   return Fragments;
119481ad6265SDimitry Andric }
119581ad6265SDimitry Andric 
getFragmentsForObjCCategory(const ObjCCategoryDecl * Category)119681ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory(
119781ad6265SDimitry Andric     const ObjCCategoryDecl *Category) {
119881ad6265SDimitry Andric   DeclarationFragments Fragments;
119981ad6265SDimitry Andric 
1200bdd1243dSDimitry Andric   auto *Interface = Category->getClassInterface();
120181ad6265SDimitry Andric   SmallString<128> InterfaceUSR;
1202bdd1243dSDimitry Andric   index::generateUSRForDecl(Interface, InterfaceUSR);
120381ad6265SDimitry Andric 
120481ad6265SDimitry Andric   Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
120581ad6265SDimitry Andric       .appendSpace()
120681ad6265SDimitry Andric       .append(Category->getClassInterface()->getName(),
1207bdd1243dSDimitry Andric               DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR,
1208bdd1243dSDimitry Andric               Interface)
120981ad6265SDimitry Andric       .append(" (", DeclarationFragments::FragmentKind::Text)
121081ad6265SDimitry Andric       .append(Category->getName(),
121181ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Identifier)
121281ad6265SDimitry Andric       .append(")", DeclarationFragments::FragmentKind::Text);
121381ad6265SDimitry Andric 
121481ad6265SDimitry Andric   return Fragments;
121581ad6265SDimitry Andric }
121681ad6265SDimitry Andric 
getFragmentsForObjCInterface(const ObjCInterfaceDecl * Interface)121781ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface(
121881ad6265SDimitry Andric     const ObjCInterfaceDecl *Interface) {
121981ad6265SDimitry Andric   DeclarationFragments Fragments;
122081ad6265SDimitry Andric   // Build the base of the Objective-C interface declaration.
122181ad6265SDimitry Andric   Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
122281ad6265SDimitry Andric       .appendSpace()
122381ad6265SDimitry Andric       .append(Interface->getName(),
122481ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Identifier);
122581ad6265SDimitry Andric 
122681ad6265SDimitry Andric   // Build the inheritance part of the declaration.
122781ad6265SDimitry Andric   if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) {
122881ad6265SDimitry Andric     SmallString<128> SuperUSR;
122981ad6265SDimitry Andric     index::generateUSRForDecl(SuperClass, SuperUSR);
123081ad6265SDimitry Andric     Fragments.append(" : ", DeclarationFragments::FragmentKind::Text)
123181ad6265SDimitry Andric         .append(SuperClass->getName(),
1232bdd1243dSDimitry Andric                 DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR,
1233bdd1243dSDimitry Andric                 SuperClass);
123481ad6265SDimitry Andric   }
123581ad6265SDimitry Andric 
123681ad6265SDimitry Andric   return Fragments;
123781ad6265SDimitry Andric }
123881ad6265SDimitry Andric 
getFragmentsForObjCMethod(const ObjCMethodDecl * Method)123981ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod(
124081ad6265SDimitry Andric     const ObjCMethodDecl *Method) {
124181ad6265SDimitry Andric   DeclarationFragments Fragments, After;
124281ad6265SDimitry Andric   // Build the instance/class method indicator.
124381ad6265SDimitry Andric   if (Method->isClassMethod())
124481ad6265SDimitry Andric     Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
124581ad6265SDimitry Andric   else if (Method->isInstanceMethod())
124681ad6265SDimitry Andric     Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
124781ad6265SDimitry Andric 
124881ad6265SDimitry Andric   // Build the return type.
124981ad6265SDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text)
125081ad6265SDimitry Andric       .append(getFragmentsForType(Method->getReturnType(),
125181ad6265SDimitry Andric                                   Method->getASTContext(), After))
125281ad6265SDimitry Andric       .append(std::move(After))
125381ad6265SDimitry Andric       .append(")", DeclarationFragments::FragmentKind::Text);
125481ad6265SDimitry Andric 
125581ad6265SDimitry Andric   // Build the selector part.
125681ad6265SDimitry Andric   Selector Selector = Method->getSelector();
125781ad6265SDimitry Andric   if (Selector.getNumArgs() == 0)
125881ad6265SDimitry Andric     // For Objective-C methods that don't take arguments, the first (and only)
125981ad6265SDimitry Andric     // slot of the selector is the method name.
126081ad6265SDimitry Andric     Fragments.appendSpace().append(
126181ad6265SDimitry Andric         Selector.getNameForSlot(0),
126281ad6265SDimitry Andric         DeclarationFragments::FragmentKind::Identifier);
126381ad6265SDimitry Andric 
126481ad6265SDimitry Andric   // For Objective-C methods that take arguments, build the selector slots.
126581ad6265SDimitry Andric   for (unsigned i = 0, end = Method->param_size(); i != end; ++i) {
126681ad6265SDimitry Andric     // Objective-C method selector parts are considered as identifiers instead
126781ad6265SDimitry Andric     // of "external parameters" as in Swift. This is because Objective-C method
126881ad6265SDimitry Andric     // symbols are referenced with the entire selector, instead of just the
126981ad6265SDimitry Andric     // method name in Swift.
127081ad6265SDimitry Andric     SmallString<32> ParamID(Selector.getNameForSlot(i));
127181ad6265SDimitry Andric     ParamID.append(":");
127281ad6265SDimitry Andric     Fragments.appendSpace().append(
127381ad6265SDimitry Andric         ParamID, DeclarationFragments::FragmentKind::Identifier);
127481ad6265SDimitry Andric 
127581ad6265SDimitry Andric     // Build the internal parameter.
127681ad6265SDimitry Andric     const ParmVarDecl *Param = Method->getParamDecl(i);
127781ad6265SDimitry Andric     Fragments.append(getFragmentsForParam(Param));
127881ad6265SDimitry Andric   }
127981ad6265SDimitry Andric 
128081ad6265SDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
128181ad6265SDimitry Andric }
128281ad6265SDimitry Andric 
getFragmentsForObjCProperty(const ObjCPropertyDecl * Property)128381ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
128481ad6265SDimitry Andric     const ObjCPropertyDecl *Property) {
128581ad6265SDimitry Andric   DeclarationFragments Fragments, After;
128681ad6265SDimitry Andric 
128781ad6265SDimitry Andric   // Build the Objective-C property keyword.
128881ad6265SDimitry Andric   Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword);
128981ad6265SDimitry Andric 
129006c3fb27SDimitry Andric   const auto Attributes = Property->getPropertyAttributesAsWritten();
129181ad6265SDimitry Andric   // Build the attributes if there is any associated with the property.
129281ad6265SDimitry Andric   if (Attributes != ObjCPropertyAttribute::kind_noattr) {
129381ad6265SDimitry Andric     // No leading comma for the first attribute.
129481ad6265SDimitry Andric     bool First = true;
129581ad6265SDimitry Andric     Fragments.append(" (", DeclarationFragments::FragmentKind::Text);
129681ad6265SDimitry Andric     // Helper function to render the attribute.
129781ad6265SDimitry Andric     auto RenderAttribute =
129881ad6265SDimitry Andric         [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling,
129981ad6265SDimitry Andric             StringRef Arg = "",
130081ad6265SDimitry Andric             DeclarationFragments::FragmentKind ArgKind =
130181ad6265SDimitry Andric                 DeclarationFragments::FragmentKind::Identifier) {
130281ad6265SDimitry Andric           // Check if the `Kind` attribute is set for this property.
130381ad6265SDimitry Andric           if ((Attributes & Kind) && !Spelling.empty()) {
130481ad6265SDimitry Andric             // Add a leading comma if this is not the first attribute rendered.
130581ad6265SDimitry Andric             if (!First)
130681ad6265SDimitry Andric               Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
130781ad6265SDimitry Andric             // Render the spelling of this attribute `Kind` as a keyword.
130881ad6265SDimitry Andric             Fragments.append(Spelling,
130981ad6265SDimitry Andric                              DeclarationFragments::FragmentKind::Keyword);
131081ad6265SDimitry Andric             // If this attribute takes in arguments (e.g. `getter=getterName`),
131181ad6265SDimitry Andric             // render the arguments.
131281ad6265SDimitry Andric             if (!Arg.empty())
131381ad6265SDimitry Andric               Fragments.append("=", DeclarationFragments::FragmentKind::Text)
131481ad6265SDimitry Andric                   .append(Arg, ArgKind);
131581ad6265SDimitry Andric             First = false;
131681ad6265SDimitry Andric           }
131781ad6265SDimitry Andric         };
131881ad6265SDimitry Andric 
131981ad6265SDimitry Andric     // Go through all possible Objective-C property attributes and render set
132081ad6265SDimitry Andric     // ones.
132181ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_class, "class");
132281ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct");
132381ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic");
132481ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic");
132581ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign");
132681ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain");
132781ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong");
132881ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy");
132981ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak");
133081ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained,
133181ad6265SDimitry Andric                     "unsafe_unretained");
133281ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite");
133381ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly");
133481ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter",
133581ad6265SDimitry Andric                     Property->getGetterName().getAsString());
133681ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter",
133781ad6265SDimitry Andric                     Property->getSetterName().getAsString());
133881ad6265SDimitry Andric 
133981ad6265SDimitry Andric     // Render nullability attributes.
134081ad6265SDimitry Andric     if (Attributes & ObjCPropertyAttribute::kind_nullability) {
134181ad6265SDimitry Andric       QualType Type = Property->getType();
134281ad6265SDimitry Andric       if (const auto Nullability =
134381ad6265SDimitry Andric               AttributedType::stripOuterNullability(Type)) {
134481ad6265SDimitry Andric         if (!First)
134581ad6265SDimitry Andric           Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
134681ad6265SDimitry Andric         if (*Nullability == NullabilityKind::Unspecified &&
134781ad6265SDimitry Andric             (Attributes & ObjCPropertyAttribute::kind_null_resettable))
134881ad6265SDimitry Andric           Fragments.append("null_resettable",
134981ad6265SDimitry Andric                            DeclarationFragments::FragmentKind::Keyword);
135081ad6265SDimitry Andric         else
135181ad6265SDimitry Andric           Fragments.append(
135281ad6265SDimitry Andric               getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true),
135381ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Keyword);
135481ad6265SDimitry Andric         First = false;
135581ad6265SDimitry Andric       }
135681ad6265SDimitry Andric     }
135781ad6265SDimitry Andric 
135881ad6265SDimitry Andric     Fragments.append(")", DeclarationFragments::FragmentKind::Text);
135981ad6265SDimitry Andric   }
136081ad6265SDimitry Andric 
13615f757f3fSDimitry Andric   Fragments.appendSpace();
13625f757f3fSDimitry Andric 
13635f757f3fSDimitry Andric   FunctionTypeLoc BlockLoc;
13645f757f3fSDimitry Andric   FunctionProtoTypeLoc BlockProtoLoc;
13655f757f3fSDimitry Andric   findTypeLocForBlockDecl(Property->getTypeSourceInfo(), BlockLoc,
13665f757f3fSDimitry Andric                           BlockProtoLoc);
13675f757f3fSDimitry Andric 
13685f757f3fSDimitry Andric   auto PropType = Property->getType();
13695f757f3fSDimitry Andric   if (!BlockLoc)
13705f757f3fSDimitry Andric     Fragments
13715f757f3fSDimitry Andric         .append(getFragmentsForType(PropType, Property->getASTContext(), After))
13725f757f3fSDimitry Andric         .appendSpace();
13735f757f3fSDimitry Andric   else
13745f757f3fSDimitry Andric     Fragments.append(
13755f757f3fSDimitry Andric         getFragmentsForBlock(Property, BlockLoc, BlockProtoLoc, After));
13765f757f3fSDimitry Andric 
13775f757f3fSDimitry Andric   return Fragments
137881ad6265SDimitry Andric       .append(Property->getName(),
137981ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Identifier)
13805f757f3fSDimitry Andric       .append(std::move(After))
13815f757f3fSDimitry Andric       .append(";", DeclarationFragments::FragmentKind::Text);
138281ad6265SDimitry Andric }
138381ad6265SDimitry Andric 
getFragmentsForObjCProtocol(const ObjCProtocolDecl * Protocol)138481ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(
138581ad6265SDimitry Andric     const ObjCProtocolDecl *Protocol) {
138681ad6265SDimitry Andric   DeclarationFragments Fragments;
138781ad6265SDimitry Andric   // Build basic protocol declaration.
138881ad6265SDimitry Andric   Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword)
138981ad6265SDimitry Andric       .appendSpace()
139081ad6265SDimitry Andric       .append(Protocol->getName(),
139181ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Identifier);
139281ad6265SDimitry Andric 
139381ad6265SDimitry Andric   // If this protocol conforms to other protocols, build the conformance list.
139481ad6265SDimitry Andric   if (!Protocol->protocols().empty()) {
139581ad6265SDimitry Andric     Fragments.append(" <", DeclarationFragments::FragmentKind::Text);
139681ad6265SDimitry Andric     for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin();
139781ad6265SDimitry Andric          It != Protocol->protocol_end(); It++) {
139881ad6265SDimitry Andric       // Add a leading comma if this is not the first protocol rendered.
139981ad6265SDimitry Andric       if (It != Protocol->protocol_begin())
140081ad6265SDimitry Andric         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
140181ad6265SDimitry Andric 
140281ad6265SDimitry Andric       SmallString<128> USR;
140381ad6265SDimitry Andric       index::generateUSRForDecl(*It, USR);
140481ad6265SDimitry Andric       Fragments.append((*It)->getName(),
1405bdd1243dSDimitry Andric                        DeclarationFragments::FragmentKind::TypeIdentifier, USR,
1406bdd1243dSDimitry Andric                        *It);
140781ad6265SDimitry Andric     }
140881ad6265SDimitry Andric     Fragments.append(">", DeclarationFragments::FragmentKind::Text);
140981ad6265SDimitry Andric   }
141081ad6265SDimitry Andric 
141181ad6265SDimitry Andric   return Fragments;
141281ad6265SDimitry Andric }
141381ad6265SDimitry Andric 
getFragmentsForTypedef(const TypedefNameDecl * Decl)141481ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(
141581ad6265SDimitry Andric     const TypedefNameDecl *Decl) {
141681ad6265SDimitry Andric   DeclarationFragments Fragments, After;
141781ad6265SDimitry Andric   Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword)
141881ad6265SDimitry Andric       .appendSpace()
141981ad6265SDimitry Andric       .append(getFragmentsForType(Decl->getUnderlyingType(),
142081ad6265SDimitry Andric                                   Decl->getASTContext(), After))
142181ad6265SDimitry Andric       .append(std::move(After))
142281ad6265SDimitry Andric       .appendSpace()
142381ad6265SDimitry Andric       .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
142481ad6265SDimitry Andric 
142506c3fb27SDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
142681ad6265SDimitry Andric }
142781ad6265SDimitry Andric 
142881ad6265SDimitry Andric // Instantiate template for FunctionDecl.
142981ad6265SDimitry Andric template FunctionSignature
143081ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *);
143181ad6265SDimitry Andric 
143281ad6265SDimitry Andric // Instantiate template for ObjCMethodDecl.
143381ad6265SDimitry Andric template FunctionSignature
143481ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *);
143581ad6265SDimitry Andric 
143681ad6265SDimitry Andric // Subheading of a symbol defaults to its name.
143781ad6265SDimitry Andric DeclarationFragments
getSubHeading(const NamedDecl * Decl)143881ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) {
143981ad6265SDimitry Andric   DeclarationFragments Fragments;
14405f757f3fSDimitry Andric   if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl))
14415f757f3fSDimitry Andric     Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(),
14425f757f3fSDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
14435f757f3fSDimitry Andric   else if (isa<CXXConversionDecl>(Decl)) {
14445f757f3fSDimitry Andric     Fragments.append(
14455f757f3fSDimitry Andric         cast<CXXConversionDecl>(Decl)->getConversionType().getAsString(),
14465f757f3fSDimitry Andric         DeclarationFragments::FragmentKind::Identifier);
14475f757f3fSDimitry Andric   } else if (isa<CXXMethodDecl>(Decl) &&
14485f757f3fSDimitry Andric              cast<CXXMethodDecl>(Decl)->isOverloadedOperator()) {
14495f757f3fSDimitry Andric     Fragments.append(Decl->getNameAsString(),
14505f757f3fSDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
14515f757f3fSDimitry Andric   } else if (!Decl->getName().empty())
145281ad6265SDimitry Andric     Fragments.append(Decl->getName(),
145381ad6265SDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
145481ad6265SDimitry Andric   return Fragments;
145581ad6265SDimitry Andric }
145681ad6265SDimitry Andric 
145781ad6265SDimitry Andric // Subheading of an Objective-C method is a `+` or `-` sign indicating whether
145881ad6265SDimitry Andric // it's a class method or an instance method, followed by the selector name.
145981ad6265SDimitry Andric DeclarationFragments
getSubHeading(const ObjCMethodDecl * Method)146081ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) {
146181ad6265SDimitry Andric   DeclarationFragments Fragments;
146281ad6265SDimitry Andric   if (Method->isClassMethod())
146381ad6265SDimitry Andric     Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
146481ad6265SDimitry Andric   else if (Method->isInstanceMethod())
146581ad6265SDimitry Andric     Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
146681ad6265SDimitry Andric 
146781ad6265SDimitry Andric   return Fragments.append(Method->getNameAsString(),
146881ad6265SDimitry Andric                           DeclarationFragments::FragmentKind::Identifier);
146981ad6265SDimitry Andric }
147081ad6265SDimitry Andric 
147181ad6265SDimitry Andric // Subheading of a symbol defaults to its name.
147281ad6265SDimitry Andric DeclarationFragments
getSubHeadingForMacro(StringRef Name)147381ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) {
147481ad6265SDimitry Andric   DeclarationFragments Fragments;
147581ad6265SDimitry Andric   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
147681ad6265SDimitry Andric   return Fragments;
147781ad6265SDimitry Andric }
1478