//===- ExtractAPI/DeclarationFragments.cpp ----------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file implements Declaration Fragments related classes.
///
//===----------------------------------------------------------------------===//

#include "clang/ExtractAPI/DeclarationFragments.h"
#include "clang/AST/ASTFwd.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
#include "clang/Index/USRGeneration.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <optional>

using namespace clang::extractapi;
using namespace llvm;

namespace {

void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo,
                             clang::FunctionTypeLoc &Block,
                             clang::FunctionProtoTypeLoc &BlockProto) {
  if (!TSInfo)
    return;

  clang::TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
  while (true) {
    // Look through qualified types
    if (auto QualifiedTL = TL.getAs<clang::QualifiedTypeLoc>()) {
      TL = QualifiedTL.getUnqualifiedLoc();
      continue;
    }

    if (auto AttrTL = TL.getAs<clang::AttributedTypeLoc>()) {
      TL = AttrTL.getModifiedLoc();
      continue;
    }

    // Try to get the function prototype behind the block pointer type,
    // then we're done.
    if (auto BlockPtr = TL.getAs<clang::BlockPointerTypeLoc>()) {
      TL = BlockPtr.getPointeeLoc().IgnoreParens();
      Block = TL.getAs<clang::FunctionTypeLoc>();
      BlockProto = TL.getAs<clang::FunctionProtoTypeLoc>();
    }
    break;
  }
}

} // namespace

DeclarationFragments &
DeclarationFragments::appendUnduplicatedTextCharacter(char Character) {
  if (!Fragments.empty()) {
    Fragment &Last = Fragments.back();
    if (Last.Kind == FragmentKind::Text) {
      // Merge the extra space into the last fragment if the last fragment is
      // also text.
      if (Last.Spelling.back() != Character) { // avoid duplicates at end
        Last.Spelling.push_back(Character);
      }
    } else {
      append("", FragmentKind::Text);
      Fragments.back().Spelling.push_back(Character);
    }
  }

  return *this;
}

DeclarationFragments &DeclarationFragments::appendSpace() {
  return appendUnduplicatedTextCharacter(' ');
}

DeclarationFragments &DeclarationFragments::appendSemicolon() {
  return appendUnduplicatedTextCharacter(';');
}

DeclarationFragments &DeclarationFragments::removeTrailingSemicolon() {
  if (Fragments.empty())
    return *this;

  Fragment &Last = Fragments.back();
  if (Last.Kind == FragmentKind::Text && Last.Spelling.back() == ';')
    Last.Spelling.pop_back();

  return *this;
}

StringRef DeclarationFragments::getFragmentKindString(
    DeclarationFragments::FragmentKind Kind) {
  switch (Kind) {
  case DeclarationFragments::FragmentKind::None:
    return "none";
  case DeclarationFragments::FragmentKind::Keyword:
    return "keyword";
  case DeclarationFragments::FragmentKind::Attribute:
    return "attribute";
  case DeclarationFragments::FragmentKind::NumberLiteral:
    return "number";
  case DeclarationFragments::FragmentKind::StringLiteral:
    return "string";
  case DeclarationFragments::FragmentKind::Identifier:
    return "identifier";
  case DeclarationFragments::FragmentKind::TypeIdentifier:
    return "typeIdentifier";
  case DeclarationFragments::FragmentKind::GenericParameter:
    return "genericParameter";
  case DeclarationFragments::FragmentKind::ExternalParam:
    return "externalParam";
  case DeclarationFragments::FragmentKind::InternalParam:
    return "internalParam";
  case DeclarationFragments::FragmentKind::Text:
    return "text";
  }

  llvm_unreachable("Unhandled FragmentKind");
}

DeclarationFragments::FragmentKind
DeclarationFragments::parseFragmentKindFromString(StringRef S) {
  return llvm::StringSwitch<FragmentKind>(S)
      .Case("keyword", DeclarationFragments::FragmentKind::Keyword)
      .Case("attribute", DeclarationFragments::FragmentKind::Attribute)
      .Case("number", DeclarationFragments::FragmentKind::NumberLiteral)
      .Case("string", DeclarationFragments::FragmentKind::StringLiteral)
      .Case("identifier", DeclarationFragments::FragmentKind::Identifier)
      .Case("typeIdentifier",
            DeclarationFragments::FragmentKind::TypeIdentifier)
      .Case("genericParameter",
            DeclarationFragments::FragmentKind::GenericParameter)
      .Case("internalParam", DeclarationFragments::FragmentKind::InternalParam)
      .Case("externalParam", DeclarationFragments::FragmentKind::ExternalParam)
      .Case("text", DeclarationFragments::FragmentKind::Text)
      .Default(DeclarationFragments::FragmentKind::None);
}

DeclarationFragments DeclarationFragments::getExceptionSpecificationString(
    ExceptionSpecificationType ExceptionSpec) {
  DeclarationFragments Fragments;
  switch (ExceptionSpec) {
  case ExceptionSpecificationType::EST_None:
    return Fragments;
  case ExceptionSpecificationType::EST_DynamicNone:
    return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
        .append("throw", DeclarationFragments::FragmentKind::Keyword)
        .append("(", DeclarationFragments::FragmentKind::Text)
        .append(")", DeclarationFragments::FragmentKind::Text);
  case ExceptionSpecificationType::EST_Dynamic:
    // FIXME: throw(int), get types of inner expression
    return Fragments;
  case ExceptionSpecificationType::EST_BasicNoexcept:
    return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
        .append("noexcept", DeclarationFragments::FragmentKind::Keyword);
  case ExceptionSpecificationType::EST_DependentNoexcept:
    // FIXME: throw(conditional-expression), get expression
    break;
  case ExceptionSpecificationType::EST_NoexceptFalse:
    return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
        .append("noexcept", DeclarationFragments::FragmentKind::Keyword)
        .append("(", DeclarationFragments::FragmentKind::Text)
        .append("false", DeclarationFragments::FragmentKind::Keyword)
        .append(")", DeclarationFragments::FragmentKind::Text);
  case ExceptionSpecificationType::EST_NoexceptTrue:
    return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
        .append("noexcept", DeclarationFragments::FragmentKind::Keyword)
        .append("(", DeclarationFragments::FragmentKind::Text)
        .append("true", DeclarationFragments::FragmentKind::Keyword)
        .append(")", DeclarationFragments::FragmentKind::Text);
  default:
    return Fragments;
  }

  llvm_unreachable("Unhandled exception specification");
}

DeclarationFragments
DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) {
  DeclarationFragments Fragments;
  if (Record->isStruct())
    Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);
  else if (Record->isUnion())
    Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);
  else
    Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);

  return Fragments;
}

// NNS stores C++ nested name specifiers, which are prefixes to qualified names.
// Build declaration fragments for NNS recursively so that we have the USR for
// every part in a qualified name, and also leaves the actual underlying type
// cleaner for its own fragment.
DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS,
                                                ASTContext &Context,
                                                DeclarationFragments &After) {
  DeclarationFragments Fragments;
  if (NNS->getPrefix())
    Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After));

  switch (NNS->getKind()) {
  case NestedNameSpecifier::Identifier:
    Fragments.append(NNS->getAsIdentifier()->getName(),
                     DeclarationFragments::FragmentKind::Identifier);
    break;

  case NestedNameSpecifier::Namespace: {
    const NamespaceDecl *NS = NNS->getAsNamespace();
    if (NS->isAnonymousNamespace())
      return Fragments;
    SmallString<128> USR;
    index::generateUSRForDecl(NS, USR);
    Fragments.append(NS->getName(),
                     DeclarationFragments::FragmentKind::Identifier, USR, NS);
    break;
  }

  case NestedNameSpecifier::NamespaceAlias: {
    const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias();
    SmallString<128> USR;
    index::generateUSRForDecl(Alias, USR);
    Fragments.append(Alias->getName(),
                     DeclarationFragments::FragmentKind::Identifier, USR,
                     Alias);
    break;
  }

  case NestedNameSpecifier::Global:
    // The global specifier `::` at the beginning. No stored value.
    break;

  case NestedNameSpecifier::Super:
    // Microsoft's `__super` specifier.
    Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword);
    break;

  case NestedNameSpecifier::TypeSpec: {
    const Type *T = NNS->getAsType();
    // FIXME: Handle C++ template specialization type
    Fragments.append(getFragmentsForType(T, Context, After));
    break;
  }
  }

  // Add the separator text `::` for this segment.
  return Fragments.append("::", DeclarationFragments::FragmentKind::Text);
}

// Recursively build the declaration fragments for an underlying `Type` with
// qualifiers removed.
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
    const Type *T, ASTContext &Context, DeclarationFragments &After) {
  assert(T && "invalid type");

  DeclarationFragments Fragments;

  if (const MacroQualifiedType *MQT = dyn_cast<MacroQualifiedType>(T)) {
    Fragments.append(
        getFragmentsForType(MQT->getUnderlyingType(), Context, After));
    return Fragments;
  }

  if (const AttributedType *AT = dyn_cast<AttributedType>(T)) {
    // FIXME: Serialize Attributes correctly
    Fragments.append(
        getFragmentsForType(AT->getModifiedType(), Context, After));
    return Fragments;
  }

  // An ElaboratedType is a sugar for types that are referred to using an
  // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a
  // qualified name, e.g., `N::M::type`, or both.
  if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) {
    ElaboratedTypeKeyword Keyword = ET->getKeyword();
    if (Keyword != ElaboratedTypeKeyword::None) {
      Fragments
          .append(ElaboratedType::getKeywordName(Keyword),
                  DeclarationFragments::FragmentKind::Keyword)
          .appendSpace();
    }

    if (const NestedNameSpecifier *NNS = ET->getQualifier())
      Fragments.append(getFragmentsForNNS(NNS, Context, After));

    // After handling the elaborated keyword or qualified name, build
    // declaration fragments for the desugared underlying type.
    return Fragments.append(getFragmentsForType(ET->desugar(), Context, After));
  }

  // If the type is a typedefed type, get the underlying TypedefNameDecl for a
  // direct reference to the typedef instead of the wrapped type.

  // 'id' type is a typedef for an ObjCObjectPointerType
  //  we treat it as a typedef
  if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) {
    const TypedefNameDecl *Decl = TypedefTy->getDecl();
    TypedefUnderlyingTypeResolver TypedefResolver(Context);
    std::string USR = TypedefResolver.getUSRForType(QualType(T, 0));

    if (T->isObjCIdType()) {
      return Fragments.append(Decl->getName(),
                              DeclarationFragments::FragmentKind::Keyword);
    }

    return Fragments.append(
        Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier,
        USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0)));
  }

  // Declaration fragments of a pointer type is the declaration fragments of
  // the pointee type followed by a `*`,
  if (T->isPointerType() && !T->isFunctionPointerType())
    return Fragments
        .append(getFragmentsForType(T->getPointeeType(), Context, After))
        .append(" *", DeclarationFragments::FragmentKind::Text);

  // For Objective-C `id` and `Class` pointers
  // we do not spell out the `*`.
  if (T->isObjCObjectPointerType() &&
      !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) {

    Fragments.append(getFragmentsForType(T->getPointeeType(), Context, After));

    // id<protocol> is an qualified id type
    // id<protocol>* is not an qualified id type
    if (!T->getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) {
      Fragments.append(" *", DeclarationFragments::FragmentKind::Text);
    }

    return Fragments;
  }

  // Declaration fragments of a lvalue reference type is the declaration
  // fragments of the underlying type followed by a `&`.
  if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T))
    return Fragments
        .append(
            getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After))
        .append(" &", DeclarationFragments::FragmentKind::Text);

  // Declaration fragments of a rvalue reference type is the declaration
  // fragments of the underlying type followed by a `&&`.
  if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T))
    return Fragments
        .append(
            getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After))
        .append(" &&", DeclarationFragments::FragmentKind::Text);

  // Declaration fragments of an array-typed variable have two parts:
  // 1. the element type of the array that appears before the variable name;
  // 2. array brackets `[(0-9)?]` that appear after the variable name.
  if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) {
    // Build the "after" part first because the inner element type might also
    // be an array-type. For example `int matrix[3][4]` which has a type of
    // "(array 3 of (array 4 of ints))."
    // Push the array size part first to make sure they are in the right order.
    After.append("[", DeclarationFragments::FragmentKind::Text);

    switch (AT->getSizeModifier()) {
    case ArraySizeModifier::Normal:
      break;
    case ArraySizeModifier::Static:
      Fragments.append("static", DeclarationFragments::FragmentKind::Keyword);
      break;
    case ArraySizeModifier::Star:
      Fragments.append("*", DeclarationFragments::FragmentKind::Text);
      break;
    }

    if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
      // FIXME: right now this would evaluate any expressions/macros written in
      // the original source to concrete values. For example
      // `int nums[MAX]` -> `int nums[100]`
      // `char *str[5 + 1]` -> `char *str[6]`
      SmallString<128> Size;
      CAT->getSize().toStringUnsigned(Size);
      After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral);
    }

    After.append("]", DeclarationFragments::FragmentKind::Text);

    return Fragments.append(
        getFragmentsForType(AT->getElementType(), Context, After));
  }

  if (const TemplateSpecializationType *TemplSpecTy =
          dyn_cast<TemplateSpecializationType>(T)) {
    const auto TemplName = TemplSpecTy->getTemplateName();
    std::string Str;
    raw_string_ostream Stream(Str);
    TemplName.print(Stream, Context.getPrintingPolicy(),
                    TemplateName::Qualified::AsWritten);
    SmallString<64> USR("");
    if (const auto *TemplDecl = TemplName.getAsTemplateDecl())
      index::generateUSRForDecl(TemplDecl, USR);

    return Fragments
        .append(Str, DeclarationFragments::FragmentKind::TypeIdentifier, USR)
        .append("<", DeclarationFragments::FragmentKind::Text)
        .append(getFragmentsForTemplateArguments(
            TemplSpecTy->template_arguments(), Context, std::nullopt))
        .append(">", DeclarationFragments::FragmentKind::Text);
  }

  // Everything we care about has been handled now, reduce to the canonical
  // unqualified base type.
  QualType Base = T->getCanonicalTypeUnqualified();

  // If the base type is a TagType (struct/interface/union/class/enum), let's
  // get the underlying Decl for better names and USRs.
  if (const TagType *TagTy = dyn_cast<TagType>(Base)) {
    const TagDecl *Decl = TagTy->getDecl();
    // Anonymous decl, skip this fragment.
    if (Decl->getName().empty())
      return Fragments.append("{ ... }",
                              DeclarationFragments::FragmentKind::Text);
    SmallString<128> TagUSR;
    clang::index::generateUSRForDecl(Decl, TagUSR);
    return Fragments.append(Decl->getName(),
                            DeclarationFragments::FragmentKind::TypeIdentifier,
                            TagUSR, Decl);
  }

  // If the base type is an ObjCInterfaceType, use the underlying
  // ObjCInterfaceDecl for the true USR.
  if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) {
    const auto *Decl = ObjCIT->getDecl();
    SmallString<128> USR;
    index::generateUSRForDecl(Decl, USR);
    return Fragments.append(Decl->getName(),
                            DeclarationFragments::FragmentKind::TypeIdentifier,
                            USR, Decl);
  }

  // Default fragment builder for other kinds of types (BuiltinType etc.)
  SmallString<128> USR;
  clang::index::generateUSRForType(Base, Context, USR);
  Fragments.append(Base.getAsString(),
                   DeclarationFragments::FragmentKind::TypeIdentifier, USR);

  return Fragments;
}

DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) {
  DeclarationFragments Fragments;
  if (Quals.hasConst())
    Fragments.append("const", DeclarationFragments::FragmentKind::Keyword);
  if (Quals.hasVolatile())
    Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword);
  if (Quals.hasRestrict())
    Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword);

  return Fragments;
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
    const QualType QT, ASTContext &Context, DeclarationFragments &After) {
  assert(!QT.isNull() && "invalid type");

  if (const ParenType *PT = dyn_cast<ParenType>(QT)) {
    After.append(")", DeclarationFragments::FragmentKind::Text);
    return getFragmentsForType(PT->getInnerType(), Context, After)
        .append("(", DeclarationFragments::FragmentKind::Text);
  }

  const SplitQualType SQT = QT.split();
  DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals),
                       TypeFragments =
                           getFragmentsForType(SQT.Ty, Context, After);
  if (QT.getAsString() == "_Bool")
    TypeFragments.replace("bool", 0);

  if (QualsFragments.getFragments().empty())
    return TypeFragments;

  // Use east qualifier for pointer types
  // For example:
  // ```
  // int *   const
  // ^----   ^----
  //  type    qualifier
  // ^-----------------
  //  const pointer to int
  // ```
  // should not be reconstructed as
  // ```
  // const       int       *
  // ^----       ^--
  //  qualifier   type
  // ^----------------     ^
  //  pointer to const int
  // ```
  if (SQT.Ty->isAnyPointerType())
    return TypeFragments.appendSpace().append(std::move(QualsFragments));

  return QualsFragments.appendSpace().append(std::move(TypeFragments));
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace(
    const NamespaceDecl *Decl) {
  DeclarationFragments Fragments;
  Fragments.append("namespace", DeclarationFragments::FragmentKind::Keyword);
  if (!Decl->isAnonymousNamespace())
    Fragments.appendSpace().append(
        Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
  return Fragments.appendSemicolon();
}

DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
  DeclarationFragments Fragments;
  if (Var->isConstexpr())
    Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
        .appendSpace();

  StorageClass SC = Var->getStorageClass();
  if (SC != SC_None)
    Fragments
        .append(VarDecl::getStorageClassSpecifierString(SC),
                DeclarationFragments::FragmentKind::Keyword)
        .appendSpace();

  // Capture potential fragments that needs to be placed after the variable name
  // ```
  // int nums[5];
  // char (*ptr_to_array)[6];
  // ```
  DeclarationFragments After;
  FunctionTypeLoc BlockLoc;
  FunctionProtoTypeLoc BlockProtoLoc;
  findTypeLocForBlockDecl(Var->getTypeSourceInfo(), BlockLoc, BlockProtoLoc);

  if (!BlockLoc) {
    QualType T = Var->getTypeSourceInfo()
                     ? Var->getTypeSourceInfo()->getType()
                     : Var->getASTContext().getUnqualifiedObjCPointerType(
                           Var->getType());

    Fragments.append(getFragmentsForType(T, Var->getASTContext(), After))
        .appendSpace();
  } else {
    Fragments.append(getFragmentsForBlock(Var, BlockLoc, BlockProtoLoc, After));
  }

  return Fragments
      .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
      .append(std::move(After))
      .appendSemicolon();
}

DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) {
  DeclarationFragments Fragments;
  if (Var->isConstexpr())
    Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
        .appendSpace();
  QualType T =
      Var->getTypeSourceInfo()
          ? Var->getTypeSourceInfo()->getType()
          : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType());

  // Might be a member, so might be static.
  if (Var->isStaticDataMember())
    Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
        .appendSpace();

  DeclarationFragments After;
  DeclarationFragments ArgumentFragment =
      getFragmentsForType(T, Var->getASTContext(), After);
  if (StringRef(ArgumentFragment.begin()->Spelling)
          .starts_with("type-parameter")) {
    std::string ProperArgName = T.getAsString();
    ArgumentFragment.begin()->Spelling.swap(ProperArgName);
  }
  Fragments.append(std::move(ArgumentFragment))
      .appendSpace()
      .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
      .appendSemicolon();
  return Fragments;
}

DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) {
  DeclarationFragments Fragments, After;

  auto *TSInfo = Param->getTypeSourceInfo();

  QualType T = TSInfo ? TSInfo->getType()
                      : Param->getASTContext().getUnqualifiedObjCPointerType(
                            Param->getType());

  FunctionTypeLoc BlockLoc;
  FunctionProtoTypeLoc BlockProtoLoc;
  findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc);

  DeclarationFragments TypeFragments;
  if (BlockLoc)
    TypeFragments.append(
        getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After));
  else
    TypeFragments.append(getFragmentsForType(T, Param->getASTContext(), After));

  if (StringRef(TypeFragments.begin()->Spelling)
          .starts_with("type-parameter")) {
    std::string ProperArgName = Param->getOriginalType().getAsString();
    TypeFragments.begin()->Spelling.swap(ProperArgName);
  }

  if (Param->isObjCMethodParameter()) {
    Fragments.append("(", DeclarationFragments::FragmentKind::Text)
        .append(std::move(TypeFragments))
        .append(std::move(After))
        .append(") ", DeclarationFragments::FragmentKind::Text)
        .append(Param->getName(),
                DeclarationFragments::FragmentKind::InternalParam);
  } else {
    Fragments.append(std::move(TypeFragments));
    if (!T->isBlockPointerType())
      Fragments.appendSpace();
    Fragments
        .append(Param->getName(),
                DeclarationFragments::FragmentKind::InternalParam)
        .append(std::move(After));
  }
  return Fragments;
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForBlock(
    const NamedDecl *BlockDecl, FunctionTypeLoc &Block,
    FunctionProtoTypeLoc &BlockProto, DeclarationFragments &After) {
  DeclarationFragments Fragments;

  DeclarationFragments RetTyAfter;
  auto ReturnValueFragment = getFragmentsForType(
      Block.getTypePtr()->getReturnType(), BlockDecl->getASTContext(), After);

  Fragments.append(std::move(ReturnValueFragment))
      .append(std::move(RetTyAfter))
      .appendSpace()
      .append("(^", DeclarationFragments::FragmentKind::Text);

  After.append(")", DeclarationFragments::FragmentKind::Text);
  unsigned NumParams = Block.getNumParams();

  if (!BlockProto || NumParams == 0) {
    if (BlockProto && BlockProto.getTypePtr()->isVariadic())
      After.append("(...)", DeclarationFragments::FragmentKind::Text);
    else
      After.append("()", DeclarationFragments::FragmentKind::Text);
  } else {
    After.append("(", DeclarationFragments::FragmentKind::Text);
    for (unsigned I = 0; I != NumParams; ++I) {
      if (I)
        After.append(", ", DeclarationFragments::FragmentKind::Text);
      After.append(getFragmentsForParam(Block.getParam(I)));
      if (I == NumParams - 1 && BlockProto.getTypePtr()->isVariadic())
        After.append(", ...", DeclarationFragments::FragmentKind::Text);
    }
    After.append(")", DeclarationFragments::FragmentKind::Text);
  }

  return Fragments;
}

DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
  DeclarationFragments Fragments;
  switch (Func->getStorageClass()) {
  case SC_None:
  case SC_PrivateExtern:
    break;
  case SC_Extern:
    Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword)
        .appendSpace();
    break;
  case SC_Static:
    Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
        .appendSpace();
    break;
  case SC_Auto:
  case SC_Register:
    llvm_unreachable("invalid for functions");
  }
  if (Func->isConsteval()) // if consteval, it is also constexpr
    Fragments.append("consteval", DeclarationFragments::FragmentKind::Keyword)
        .appendSpace();
  else if (Func->isConstexpr())
    Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
        .appendSpace();

  // FIXME: Is `after` actually needed here?
  DeclarationFragments After;
  auto ReturnValueFragment =
      getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After);
  if (StringRef(ReturnValueFragment.begin()->Spelling)
          .starts_with("type-parameter")) {
    std::string ProperArgName = Func->getReturnType().getAsString();
    ReturnValueFragment.begin()->Spelling.swap(ProperArgName);
  }

  Fragments.append(std::move(ReturnValueFragment))
      .appendSpace()
      .append(Func->getNameAsString(),
              DeclarationFragments::FragmentKind::Identifier);

  if (Func->getTemplateSpecializationInfo()) {
    Fragments.append("<", DeclarationFragments::FragmentKind::Text);

    for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) {
      if (i)
        Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
      Fragments.append(
          getFragmentsForType(Func->getParamDecl(i)->getType(),
                              Func->getParamDecl(i)->getASTContext(), After));
    }
    Fragments.append(">", DeclarationFragments::FragmentKind::Text);
  }
  Fragments.append(std::move(After));

  Fragments.append("(", DeclarationFragments::FragmentKind::Text);
  unsigned NumParams = Func->getNumParams();
  for (unsigned i = 0; i != NumParams; ++i) {
    if (i)
      Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
    Fragments.append(getFragmentsForParam(Func->getParamDecl(i)));
  }

  if (Func->isVariadic()) {
    if (NumParams > 0)
      Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
    Fragments.append("...", DeclarationFragments::FragmentKind::Text);
  }
  Fragments.append(")", DeclarationFragments::FragmentKind::Text);

  Fragments.append(DeclarationFragments::getExceptionSpecificationString(
      Func->getExceptionSpecType()));

  return Fragments.appendSemicolon();
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant(
    const EnumConstantDecl *EnumConstDecl) {
  DeclarationFragments Fragments;
  return Fragments.append(EnumConstDecl->getName(),
                          DeclarationFragments::FragmentKind::Identifier);
}

DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {
  if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl())
    return getFragmentsForTypedef(TypedefNameDecl);

  DeclarationFragments Fragments, After;
  Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword);

  if (!EnumDecl->getName().empty())
    Fragments.appendSpace().append(
        EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier);

  QualType IntegerType = EnumDecl->getIntegerType();
  if (!IntegerType.isNull())
    Fragments.appendSpace()
        .append(": ", DeclarationFragments::FragmentKind::Text)
        .append(
            getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))
        .append(std::move(After));

  if (EnumDecl->getName().empty())
    Fragments.appendSpace().append("{ ... }",
                                   DeclarationFragments::FragmentKind::Text);

  return Fragments.appendSemicolon();
}

DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) {
  DeclarationFragments After;
  DeclarationFragments Fragments;
  if (Field->isMutable())
    Fragments.append("mutable", DeclarationFragments::FragmentKind::Keyword)
        .appendSpace();
  return Fragments
      .append(
          getFragmentsForType(Field->getType(), Field->getASTContext(), After))
      .appendSpace()
      .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)
      .append(std::move(After))
      .appendSemicolon();
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
    const RecordDecl *Record) {
  if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
    return getFragmentsForTypedef(TypedefNameDecl);

  DeclarationFragments Fragments;
  if (Record->isUnion())
    Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);
  else
    Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);

  Fragments.appendSpace();
  if (!Record->getName().empty())
    Fragments.append(Record->getName(),
                     DeclarationFragments::FragmentKind::Identifier);
  else
    Fragments.append("{ ... }", DeclarationFragments::FragmentKind::Text);

  return Fragments.appendSemicolon();
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
    const CXXRecordDecl *Record) {
  if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
    return getFragmentsForTypedef(TypedefNameDecl);

  DeclarationFragments Fragments;
  Fragments.append(DeclarationFragments::getStructureTypeFragment(Record));

  if (!Record->getName().empty())
    Fragments.appendSpace().append(
        Record->getName(), DeclarationFragments::FragmentKind::Identifier);

  return Fragments.appendSemicolon();
}

DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(
    const CXXMethodDecl *Method) {
  DeclarationFragments Fragments;
  std::string Name;
  if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(Method)) {
    Name = Method->getNameAsString();
    if (Constructor->isExplicit())
      Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
          .appendSpace();
  } else if (isa<CXXDestructorDecl>(Method))
    Name = Method->getNameAsString();

  DeclarationFragments After;
  Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier)
      .append(std::move(After));
  Fragments.append("(", DeclarationFragments::FragmentKind::Text);
  for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
    if (i)
      Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
    Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
  }
  Fragments.append(")", DeclarationFragments::FragmentKind::Text);

  Fragments.append(DeclarationFragments::getExceptionSpecificationString(
      Method->getExceptionSpecType()));

  return Fragments.appendSemicolon();
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
    const CXXMethodDecl *Method) {
  DeclarationFragments Fragments;
  StringRef Name = Method->getName();
  if (Method->isStatic())
    Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
        .appendSpace();
  if (Method->isConstexpr())
    Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
        .appendSpace();
  if (Method->isVolatile())
    Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword)
        .appendSpace();

  // Build return type
  DeclarationFragments After;
  Fragments
      .append(getFragmentsForType(Method->getReturnType(),
                                  Method->getASTContext(), After))
      .appendSpace()
      .append(Name, DeclarationFragments::FragmentKind::Identifier)
      .append(std::move(After));
  Fragments.append("(", DeclarationFragments::FragmentKind::Text);
  for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
    if (i)
      Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
    Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
  }
  Fragments.append(")", DeclarationFragments::FragmentKind::Text);

  if (Method->isConst())
    Fragments.appendSpace().append("const",
                                   DeclarationFragments::FragmentKind::Keyword);

  Fragments.append(DeclarationFragments::getExceptionSpecificationString(
      Method->getExceptionSpecType()));

  return Fragments.appendSemicolon();
}

DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForConversionFunction(
    const CXXConversionDecl *ConversionFunction) {
  DeclarationFragments Fragments;

  if (ConversionFunction->isExplicit())
    Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
        .appendSpace();

  Fragments.append("operator", DeclarationFragments::FragmentKind::Keyword)
      .appendSpace();

  Fragments
      .append(ConversionFunction->getConversionType().getAsString(),
              DeclarationFragments::FragmentKind::TypeIdentifier)
      .append("(", DeclarationFragments::FragmentKind::Text);
  for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end;
       ++i) {
    if (i)
      Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
    Fragments.append(getFragmentsForParam(ConversionFunction->getParamDecl(i)));
  }
  Fragments.append(")", DeclarationFragments::FragmentKind::Text);

  if (ConversionFunction->isConst())
    Fragments.appendSpace().append("const",
                                   DeclarationFragments::FragmentKind::Keyword);

  return Fragments.appendSemicolon();
}

DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(
    const CXXMethodDecl *Method) {
  DeclarationFragments Fragments;

  // Build return type
  DeclarationFragments After;
  Fragments
      .append(getFragmentsForType(Method->getReturnType(),
                                  Method->getASTContext(), After))
      .appendSpace()
      .append(Method->getNameAsString(),
              DeclarationFragments::FragmentKind::Identifier)
      .append(std::move(After));
  Fragments.append("(", DeclarationFragments::FragmentKind::Text);
  for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
    if (i)
      Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
    Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
  }
  Fragments.append(")", DeclarationFragments::FragmentKind::Text);

  if (Method->isConst())
    Fragments.appendSpace().append("const",
                                   DeclarationFragments::FragmentKind::Keyword);

  Fragments.append(DeclarationFragments::getExceptionSpecificationString(
      Method->getExceptionSpecType()));

  return Fragments.appendSemicolon();
}

// Get fragments for template parameters, e.g. T in tempalte<typename T> ...
DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForTemplateParameters(
    ArrayRef<NamedDecl *> ParameterArray) {
  DeclarationFragments Fragments;
  for (unsigned i = 0, end = ParameterArray.size(); i != end; ++i) {
    if (i)
      Fragments.append(",", DeclarationFragments::FragmentKind::Text)
          .appendSpace();

    if (const auto *TemplateParam =
            dyn_cast<TemplateTypeParmDecl>(ParameterArray[i])) {
      if (TemplateParam->hasTypeConstraint())
        Fragments.append(TemplateParam->getTypeConstraint()
                             ->getNamedConcept()
                             ->getName()
                             .str(),
                         DeclarationFragments::FragmentKind::TypeIdentifier);
      else if (TemplateParam->wasDeclaredWithTypename())
        Fragments.append("typename",
                         DeclarationFragments::FragmentKind::Keyword);
      else
        Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);

      if (TemplateParam->isParameterPack())
        Fragments.append("...", DeclarationFragments::FragmentKind::Text);

      if (!TemplateParam->getName().empty())
        Fragments.appendSpace().append(
            TemplateParam->getName(),
            DeclarationFragments::FragmentKind::GenericParameter);

      if (TemplateParam->hasDefaultArgument()) {
        const auto Default = TemplateParam->getDefaultArgument();
        Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)
            .append(getFragmentsForTemplateArguments(
                {Default.getArgument()}, TemplateParam->getASTContext(),
                {Default}));
      }
    } else if (const auto *NTP =
                   dyn_cast<NonTypeTemplateParmDecl>(ParameterArray[i])) {
      DeclarationFragments After;
      const auto TyFragments =
          getFragmentsForType(NTP->getType(), NTP->getASTContext(), After);
      Fragments.append(std::move(TyFragments)).append(std::move(After));

      if (NTP->isParameterPack())
        Fragments.append("...", DeclarationFragments::FragmentKind::Text);

      if (!NTP->getName().empty())
        Fragments.appendSpace().append(
            NTP->getName(),
            DeclarationFragments::FragmentKind::GenericParameter);

      if (NTP->hasDefaultArgument()) {
        SmallString<8> ExprStr;
        raw_svector_ostream Output(ExprStr);
        NTP->getDefaultArgument().getArgument().print(
            NTP->getASTContext().getPrintingPolicy(), Output,
            /*IncludeType=*/false);
        Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)
            .append(ExprStr, DeclarationFragments::FragmentKind::Text);
      }
    } else if (const auto *TTP =
                   dyn_cast<TemplateTemplateParmDecl>(ParameterArray[i])) {
      Fragments.append("template", DeclarationFragments::FragmentKind::Keyword)
          .appendSpace()
          .append("<", DeclarationFragments::FragmentKind::Text)
          .append(getFragmentsForTemplateParameters(
              TTP->getTemplateParameters()->asArray()))
          .append(">", DeclarationFragments::FragmentKind::Text)
          .appendSpace()
          .append(TTP->wasDeclaredWithTypename() ? "typename" : "class",
                  DeclarationFragments::FragmentKind::Keyword);

      if (TTP->isParameterPack())
        Fragments.append("...", DeclarationFragments::FragmentKind::Text);

      if (!TTP->getName().empty())
        Fragments.appendSpace().append(
            TTP->getName(),
            DeclarationFragments::FragmentKind::GenericParameter);
      if (TTP->hasDefaultArgument()) {
        const auto Default = TTP->getDefaultArgument();
        Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)
            .append(getFragmentsForTemplateArguments(
                {Default.getArgument()}, TTP->getASTContext(), {Default}));
      }
    }
  }
  return Fragments;
}

// Get fragments for template arguments, e.g. int in template<typename T>
// Foo<int>;
//
// Note: TemplateParameters is only necessary if the Decl is a
// PartialSpecialization, where we need the parameters to deduce the name of the
// generic arguments.
DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForTemplateArguments(
    const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context,
    const std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs) {
  DeclarationFragments Fragments;
  for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) {
    if (i)
      Fragments.append(",", DeclarationFragments::FragmentKind::Text)
          .appendSpace();

    const auto &CTA = TemplateArguments[i];
    switch (CTA.getKind()) {
    case TemplateArgument::Type: {
      DeclarationFragments After;
      DeclarationFragments ArgumentFragment =
          getFragmentsForType(CTA.getAsType(), Context, After);

      if (StringRef(ArgumentFragment.begin()->Spelling)
              .starts_with("type-parameter")) {
        if (TemplateArgumentLocs.has_value() &&
            TemplateArgumentLocs->size() > i) {
          std::string ProperArgName = TemplateArgumentLocs.value()[i]
                                          .getTypeSourceInfo()
                                          ->getType()
                                          .getAsString();
          ArgumentFragment.begin()->Spelling.swap(ProperArgName);
        } else {
          auto &Spelling = ArgumentFragment.begin()->Spelling;
          Spelling.clear();
          raw_string_ostream OutStream(Spelling);
          CTA.print(Context.getPrintingPolicy(), OutStream, false);
        }
      }

      Fragments.append(std::move(ArgumentFragment));
      break;
    }
    case TemplateArgument::Declaration: {
      const auto *VD = CTA.getAsDecl();
      SmallString<128> USR;
      index::generateUSRForDecl(VD, USR);
      Fragments.append(VD->getNameAsString(),
                       DeclarationFragments::FragmentKind::Identifier, USR);
      break;
    }
    case TemplateArgument::NullPtr:
      Fragments.append("nullptr", DeclarationFragments::FragmentKind::Keyword);
      break;

    case TemplateArgument::Integral: {
      SmallString<4> Str;
      CTA.getAsIntegral().toString(Str);
      Fragments.append(Str, DeclarationFragments::FragmentKind::Text);
      break;
    }

    case TemplateArgument::StructuralValue: {
      const auto SVTy = CTA.getStructuralValueType();
      Fragments.append(CTA.getAsStructuralValue().getAsString(Context, SVTy),
                       DeclarationFragments::FragmentKind::Text);
      break;
    }

    case TemplateArgument::TemplateExpansion:
    case TemplateArgument::Template: {
      std::string Str;
      raw_string_ostream Stream(Str);
      CTA.getAsTemplate().print(Stream, Context.getPrintingPolicy());
      SmallString<64> USR("");
      if (const auto *TemplDecl =
              CTA.getAsTemplateOrTemplatePattern().getAsTemplateDecl())
        index::generateUSRForDecl(TemplDecl, USR);
      Fragments.append(Str, DeclarationFragments::FragmentKind::TypeIdentifier,
                       USR);
      if (CTA.getKind() == TemplateArgument::TemplateExpansion)
        Fragments.append("...", DeclarationFragments::FragmentKind::Text);
      break;
    }

    case TemplateArgument::Pack:
      Fragments.append("<", DeclarationFragments::FragmentKind::Text)
          .append(getFragmentsForTemplateArguments(CTA.pack_elements(), Context,
                                                   {}))
          .append(">", DeclarationFragments::FragmentKind::Text);
      break;

    case TemplateArgument::Expression: {
      SmallString<8> ExprStr;
      raw_svector_ostream Output(ExprStr);
      CTA.getAsExpr()->printPretty(Output, nullptr,
                                   Context.getPrintingPolicy());
      Fragments.append(ExprStr, DeclarationFragments::FragmentKind::Text);
      break;
    }

    case TemplateArgument::Null:
      break;
    }
  }
  return Fragments;
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept(
    const ConceptDecl *Concept) {
  DeclarationFragments Fragments;
  return Fragments
      .append("template", DeclarationFragments::FragmentKind::Keyword)
      .appendSpace()
      .append("<", DeclarationFragments::FragmentKind::Text)
      .append(getFragmentsForTemplateParameters(
          Concept->getTemplateParameters()->asArray()))
      .append("> ", DeclarationFragments::FragmentKind::Text)
      .appendSpace()
      .append("concept", DeclarationFragments::FragmentKind::Keyword)
      .appendSpace()
      .append(Concept->getName().str(),
              DeclarationFragments::FragmentKind::Identifier)
      .appendSemicolon();
}

DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
    const RedeclarableTemplateDecl *RedeclarableTemplate) {
  DeclarationFragments Fragments;
  Fragments.append("template", DeclarationFragments::FragmentKind::Keyword)
      .appendSpace()
      .append("<", DeclarationFragments::FragmentKind::Text)
      .append(getFragmentsForTemplateParameters(
          RedeclarableTemplate->getTemplateParameters()->asArray()))
      .append(">", DeclarationFragments::FragmentKind::Text)
      .appendSpace();

  if (isa<TypeAliasTemplateDecl>(RedeclarableTemplate))
    Fragments.appendSpace()
        .append("using", DeclarationFragments::FragmentKind::Keyword)
        .appendSpace()
        .append(RedeclarableTemplate->getName(),
                DeclarationFragments::FragmentKind::Identifier);
  // the templated records will be resposbible for injecting their templates
  return Fragments.appendSpace();
}

DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization(
    const ClassTemplateSpecializationDecl *Decl) {
  DeclarationFragments Fragments;
  std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs = {};
  if (auto *TemplateArgs = Decl->getTemplateArgsAsWritten()) {
    TemplateArgumentLocs = TemplateArgs->arguments();
  }
  return Fragments
      .append("template", DeclarationFragments::FragmentKind::Keyword)
      .appendSpace()
      .append("<", DeclarationFragments::FragmentKind::Text)
      .append(">", DeclarationFragments::FragmentKind::Text)
      .appendSpace()
      .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(
          cast<CXXRecordDecl>(Decl)))
      .pop_back() // there is an extra semicolon now
      .append("<", DeclarationFragments::FragmentKind::Text)
      .append(getFragmentsForTemplateArguments(
          Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
          TemplateArgumentLocs))
      .append(">", DeclarationFragments::FragmentKind::Text)
      .appendSemicolon();
}

DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization(
    const ClassTemplatePartialSpecializationDecl *Decl) {
  DeclarationFragments Fragments;
  return Fragments
      .append("template", DeclarationFragments::FragmentKind::Keyword)
      .appendSpace()
      .append("<", DeclarationFragments::FragmentKind::Text)
      .append(getFragmentsForTemplateParameters(
          Decl->getTemplateParameters()->asArray()))
      .append(">", DeclarationFragments::FragmentKind::Text)
      .appendSpace()
      .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(
          cast<CXXRecordDecl>(Decl)))
      .pop_back() // there is an extra semicolon now
      .append("<", DeclarationFragments::FragmentKind::Text)
      .append(getFragmentsForTemplateArguments(
          Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
          Decl->getTemplateArgsAsWritten()->arguments()))
      .append(">", DeclarationFragments::FragmentKind::Text)
      .appendSemicolon();
}

DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization(
    const VarTemplateSpecializationDecl *Decl) {
  DeclarationFragments Fragments;
  return Fragments
      .append("template", DeclarationFragments::FragmentKind::Keyword)
      .appendSpace()
      .append("<", DeclarationFragments::FragmentKind::Text)
      .append(">", DeclarationFragments::FragmentKind::Text)
      .appendSpace()
      .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))
      .pop_back() // there is an extra semicolon now
      .append("<", DeclarationFragments::FragmentKind::Text)
      .append(getFragmentsForTemplateArguments(
          Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
          Decl->getTemplateArgsAsWritten()->arguments()))
      .append(">", DeclarationFragments::FragmentKind::Text)
      .appendSemicolon();
}

DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization(
    const VarTemplatePartialSpecializationDecl *Decl) {
  DeclarationFragments Fragments;
  return Fragments
      .append("template", DeclarationFragments::FragmentKind::Keyword)
      .appendSpace()
      .append("<", DeclarationFragments::FragmentKind::Text)
      // Partial specs may have new params.
      .append(getFragmentsForTemplateParameters(
          Decl->getTemplateParameters()->asArray()))
      .append(">", DeclarationFragments::FragmentKind::Text)
      .appendSpace()
      .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))
      .pop_back() // there is an extra semicolon now
      .append("<", DeclarationFragments::FragmentKind::Text)
      .append(getFragmentsForTemplateArguments(
          Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
          Decl->getTemplateArgsAsWritten()->arguments()))
      .append(">", DeclarationFragments::FragmentKind::Text)
      .appendSemicolon();
}

DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(
    const FunctionTemplateDecl *Decl) {
  DeclarationFragments Fragments;
  return Fragments
      .append("template", DeclarationFragments::FragmentKind::Keyword)
      .appendSpace()
      .append("<", DeclarationFragments::FragmentKind::Text)
      // Partial specs may have new params.
      .append(getFragmentsForTemplateParameters(
          Decl->getTemplateParameters()->asArray()))
      .append(">", DeclarationFragments::FragmentKind::Text)
      .appendSpace()
      .append(DeclarationFragmentsBuilder::getFragmentsForFunction(
          Decl->getAsFunction()));
}

DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization(
    const FunctionDecl *Decl) {
  DeclarationFragments Fragments;
  return Fragments
      .append("template", DeclarationFragments::FragmentKind::Keyword)
      .appendSpace()
      .append("<>", DeclarationFragments::FragmentKind::Text)
      .appendSpace()
      .append(DeclarationFragmentsBuilder::getFragmentsForFunction(Decl));
}

DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name,
                                                  const MacroInfo *MI) {
  DeclarationFragments Fragments;
  Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword)
      .appendSpace();
  Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);

  if (MI->isFunctionLike()) {
    Fragments.append("(", DeclarationFragments::FragmentKind::Text);
    unsigned numParameters = MI->getNumParams();
    if (MI->isC99Varargs())
      --numParameters;
    for (unsigned i = 0; i < numParameters; ++i) {
      if (i)
        Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
      Fragments.append(MI->params()[i]->getName(),
                       DeclarationFragments::FragmentKind::InternalParam);
    }
    if (MI->isVariadic()) {
      if (numParameters && MI->isC99Varargs())
        Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
      Fragments.append("...", DeclarationFragments::FragmentKind::Text);
    }
    Fragments.append(")", DeclarationFragments::FragmentKind::Text);
  }
  return Fragments;
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory(
    const ObjCCategoryDecl *Category) {
  DeclarationFragments Fragments;

  auto *Interface = Category->getClassInterface();
  SmallString<128> InterfaceUSR;
  index::generateUSRForDecl(Interface, InterfaceUSR);

  Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
      .appendSpace()
      .append(Interface->getName(),
              DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR,
              Interface)
      .append(" (", DeclarationFragments::FragmentKind::Text)
      .append(Category->getName(),
              DeclarationFragments::FragmentKind::Identifier)
      .append(")", DeclarationFragments::FragmentKind::Text);

  return Fragments;
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface(
    const ObjCInterfaceDecl *Interface) {
  DeclarationFragments Fragments;
  // Build the base of the Objective-C interface declaration.
  Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
      .appendSpace()
      .append(Interface->getName(),
              DeclarationFragments::FragmentKind::Identifier);

  // Build the inheritance part of the declaration.
  if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) {
    SmallString<128> SuperUSR;
    index::generateUSRForDecl(SuperClass, SuperUSR);
    Fragments.append(" : ", DeclarationFragments::FragmentKind::Text)
        .append(SuperClass->getName(),
                DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR,
                SuperClass);
  }

  return Fragments;
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod(
    const ObjCMethodDecl *Method) {
  DeclarationFragments Fragments, After;
  // Build the instance/class method indicator.
  if (Method->isClassMethod())
    Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
  else if (Method->isInstanceMethod())
    Fragments.append("- ", DeclarationFragments::FragmentKind::Text);

  // Build the return type.
  Fragments.append("(", DeclarationFragments::FragmentKind::Text)
      .append(getFragmentsForType(Method->getReturnType(),
                                  Method->getASTContext(), After))
      .append(std::move(After))
      .append(")", DeclarationFragments::FragmentKind::Text);

  // Build the selector part.
  Selector Selector = Method->getSelector();
  if (Selector.getNumArgs() == 0)
    // For Objective-C methods that don't take arguments, the first (and only)
    // slot of the selector is the method name.
    Fragments.appendSpace().append(
        Selector.getNameForSlot(0),
        DeclarationFragments::FragmentKind::Identifier);

  // For Objective-C methods that take arguments, build the selector slots.
  for (unsigned i = 0, end = Method->param_size(); i != end; ++i) {
    // Objective-C method selector parts are considered as identifiers instead
    // of "external parameters" as in Swift. This is because Objective-C method
    // symbols are referenced with the entire selector, instead of just the
    // method name in Swift.
    SmallString<32> ParamID(Selector.getNameForSlot(i));
    ParamID.append(":");
    Fragments.appendSpace().append(
        ParamID, DeclarationFragments::FragmentKind::Identifier);

    // Build the internal parameter.
    const ParmVarDecl *Param = Method->getParamDecl(i);
    Fragments.append(getFragmentsForParam(Param));
  }

  return Fragments.appendSemicolon();
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
    const ObjCPropertyDecl *Property) {
  DeclarationFragments Fragments, After;

  // Build the Objective-C property keyword.
  Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword);

  const auto Attributes = Property->getPropertyAttributesAsWritten();
  // Build the attributes if there is any associated with the property.
  if (Attributes != ObjCPropertyAttribute::kind_noattr) {
    // No leading comma for the first attribute.
    bool First = true;
    Fragments.append(" (", DeclarationFragments::FragmentKind::Text);
    // Helper function to render the attribute.
    auto RenderAttribute =
        [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling,
            StringRef Arg = "",
            DeclarationFragments::FragmentKind ArgKind =
                DeclarationFragments::FragmentKind::Identifier) {
          // Check if the `Kind` attribute is set for this property.
          if ((Attributes & Kind) && !Spelling.empty()) {
            // Add a leading comma if this is not the first attribute rendered.
            if (!First)
              Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
            // Render the spelling of this attribute `Kind` as a keyword.
            Fragments.append(Spelling,
                             DeclarationFragments::FragmentKind::Keyword);
            // If this attribute takes in arguments (e.g. `getter=getterName`),
            // render the arguments.
            if (!Arg.empty())
              Fragments.append("=", DeclarationFragments::FragmentKind::Text)
                  .append(Arg, ArgKind);
            First = false;
          }
        };

    // Go through all possible Objective-C property attributes and render set
    // ones.
    RenderAttribute(ObjCPropertyAttribute::kind_class, "class");
    RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct");
    RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic");
    RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic");
    RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign");
    RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain");
    RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong");
    RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy");
    RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak");
    RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained,
                    "unsafe_unretained");
    RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite");
    RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly");
    RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter",
                    Property->getGetterName().getAsString());
    RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter",
                    Property->getSetterName().getAsString());

    // Render nullability attributes.
    if (Attributes & ObjCPropertyAttribute::kind_nullability) {
      QualType Type = Property->getType();
      if (const auto Nullability =
              AttributedType::stripOuterNullability(Type)) {
        if (!First)
          Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
        if (*Nullability == NullabilityKind::Unspecified &&
            (Attributes & ObjCPropertyAttribute::kind_null_resettable))
          Fragments.append("null_resettable",
                           DeclarationFragments::FragmentKind::Keyword);
        else
          Fragments.append(
              getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true),
              DeclarationFragments::FragmentKind::Keyword);
        First = false;
      }
    }

    Fragments.append(")", DeclarationFragments::FragmentKind::Text);
  }

  Fragments.appendSpace();

  FunctionTypeLoc BlockLoc;
  FunctionProtoTypeLoc BlockProtoLoc;
  findTypeLocForBlockDecl(Property->getTypeSourceInfo(), BlockLoc,
                          BlockProtoLoc);

  auto PropType = Property->getType();
  if (!BlockLoc)
    Fragments
        .append(getFragmentsForType(PropType, Property->getASTContext(), After))
        .appendSpace();
  else
    Fragments.append(
        getFragmentsForBlock(Property, BlockLoc, BlockProtoLoc, After));

  return Fragments
      .append(Property->getName(),
              DeclarationFragments::FragmentKind::Identifier)
      .append(std::move(After))
      .appendSemicolon();
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(
    const ObjCProtocolDecl *Protocol) {
  DeclarationFragments Fragments;
  // Build basic protocol declaration.
  Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword)
      .appendSpace()
      .append(Protocol->getName(),
              DeclarationFragments::FragmentKind::Identifier);

  // If this protocol conforms to other protocols, build the conformance list.
  if (!Protocol->protocols().empty()) {
    Fragments.append(" <", DeclarationFragments::FragmentKind::Text);
    for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin();
         It != Protocol->protocol_end(); It++) {
      // Add a leading comma if this is not the first protocol rendered.
      if (It != Protocol->protocol_begin())
        Fragments.append(", ", DeclarationFragments::FragmentKind::Text);

      SmallString<128> USR;
      index::generateUSRForDecl(*It, USR);
      Fragments.append((*It)->getName(),
                       DeclarationFragments::FragmentKind::TypeIdentifier, USR,
                       *It);
    }
    Fragments.append(">", DeclarationFragments::FragmentKind::Text);
  }

  return Fragments;
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(
    const TypedefNameDecl *Decl) {
  DeclarationFragments Fragments, After;
  Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword)
      .appendSpace()
      .append(getFragmentsForType(Decl->getUnderlyingType(),
                                  Decl->getASTContext(), After))
      .append(std::move(After))
      .appendSpace()
      .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier);

  return Fragments.appendSemicolon();
}

// Instantiate template for FunctionDecl.
template FunctionSignature
DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *);

// Instantiate template for ObjCMethodDecl.
template FunctionSignature
DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *);

// Subheading of a symbol defaults to its name.
DeclarationFragments
DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) {
  DeclarationFragments Fragments;
  if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl))
    Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(),
                     DeclarationFragments::FragmentKind::Identifier);
  else if (isa<CXXConversionDecl>(Decl)) {
    Fragments.append(
        cast<CXXConversionDecl>(Decl)->getConversionType().getAsString(),
        DeclarationFragments::FragmentKind::Identifier);
  } else if (isa<CXXMethodDecl>(Decl) &&
             cast<CXXMethodDecl>(Decl)->isOverloadedOperator()) {
    Fragments.append(Decl->getNameAsString(),
                     DeclarationFragments::FragmentKind::Identifier);
  } else if (isa<TagDecl>(Decl) &&
             cast<TagDecl>(Decl)->getTypedefNameForAnonDecl()) {
    return getSubHeading(cast<TagDecl>(Decl)->getTypedefNameForAnonDecl());
  } else if (Decl->getIdentifier()) {
    Fragments.append(Decl->getName(),
                     DeclarationFragments::FragmentKind::Identifier);
  } else
    Fragments.append(Decl->getDeclName().getAsString(),
                     DeclarationFragments::FragmentKind::Identifier);
  return Fragments;
}

// Subheading of an Objective-C method is a `+` or `-` sign indicating whether
// it's a class method or an instance method, followed by the selector name.
DeclarationFragments
DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) {
  DeclarationFragments Fragments;
  if (Method->isClassMethod())
    Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
  else if (Method->isInstanceMethod())
    Fragments.append("- ", DeclarationFragments::FragmentKind::Text);

  return Fragments.append(Method->getNameAsString(),
                          DeclarationFragments::FragmentKind::Identifier);
}

// Subheading of a symbol defaults to its name.
DeclarationFragments
DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) {
  DeclarationFragments Fragments;
  Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
  return Fragments;
}
