//===-- Serialize.cpp - ClangDoc Serializer ---------------------*- 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
//
//===----------------------------------------------------------------------===//

#include "Serialize.h"
#include "BitcodeWriter.h"

#include "clang/AST/Attr.h"
#include "clang/AST/Comment.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/Mangle.h"
#include "clang/Index/USRGeneration.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/SHA1.h"

using clang::comments::FullComment;

namespace clang {
namespace doc {
namespace serialize {

namespace {
static SmallString<16> exprToString(const clang::Expr *E) {
  clang::LangOptions Opts;
  clang::PrintingPolicy Policy(Opts);
  SmallString<16> Result;
  llvm::raw_svector_ostream OS(Result);
  E->printPretty(OS, nullptr, Policy);
  return Result;
}
} // namespace

SymbolID hashUSR(llvm::StringRef USR) {
  return llvm::SHA1::hash(arrayRefFromStringRef(USR));
}

template <typename T>
static void
populateParentNamespaces(llvm::SmallVector<Reference, 4> &Namespaces,
                         const T *D, bool &IsAnonymousNamespace);

static void populateMemberTypeInfo(MemberTypeInfo &I, const Decl *D);
static void populateMemberTypeInfo(RecordInfo &I, AccessSpecifier &Access,
                                   const DeclaratorDecl *D,
                                   bool IsStatic = false);

static void getTemplateParameters(const TemplateParameterList *TemplateParams,
                                  llvm::raw_ostream &Stream) {
  Stream << "template <";

  for (unsigned i = 0; i < TemplateParams->size(); ++i) {
    if (i > 0)
      Stream << ", ";

    const NamedDecl *Param = TemplateParams->getParam(i);
    if (const auto *TTP = llvm::dyn_cast<TemplateTypeParmDecl>(Param)) {
      if (TTP->wasDeclaredWithTypename())
        Stream << "typename";
      else
        Stream << "class";
      if (TTP->isParameterPack())
        Stream << "...";
      Stream << " " << TTP->getNameAsString();

      // We need to also handle type constraints for code like:
      //   template <class T = void>
      //   class C {};
      if (TTP->hasTypeConstraint()) {
        Stream << " = ";
        TTP->getTypeConstraint()->print(
            Stream, TTP->getASTContext().getPrintingPolicy());
      }
    } else if (const auto *NTTP =
                   llvm::dyn_cast<NonTypeTemplateParmDecl>(Param)) {
      NTTP->getType().print(Stream, NTTP->getASTContext().getPrintingPolicy());
      if (NTTP->isParameterPack())
        Stream << "...";
      Stream << " " << NTTP->getNameAsString();
    } else if (const auto *TTPD =
                   llvm::dyn_cast<TemplateTemplateParmDecl>(Param)) {
      Stream << "template <";
      getTemplateParameters(TTPD->getTemplateParameters(), Stream);
      Stream << "> class " << TTPD->getNameAsString();
    }
  }

  Stream << "> ";
}

// Extract the full function prototype from a FunctionDecl including
// Full Decl
static llvm::SmallString<256>
getFunctionPrototype(const FunctionDecl *FuncDecl) {
  llvm::SmallString<256> Result;
  llvm::raw_svector_ostream Stream(Result);
  const ASTContext &Ctx = FuncDecl->getASTContext();
  const auto *Method = llvm::dyn_cast<CXXMethodDecl>(FuncDecl);
  // If it's a templated function, handle the template parameters
  if (const auto *TmplDecl = FuncDecl->getDescribedTemplate())
    getTemplateParameters(TmplDecl->getTemplateParameters(), Stream);

  // If it's a virtual method
  if (Method && Method->isVirtual())
    Stream << "virtual ";

  // Print return type
  FuncDecl->getReturnType().print(Stream, Ctx.getPrintingPolicy());

  // Print function name
  Stream << " " << FuncDecl->getNameAsString() << "(";

  // Print parameter list with types, names, and default values
  for (unsigned I = 0; I < FuncDecl->getNumParams(); ++I) {
    if (I > 0)
      Stream << ", ";
    const ParmVarDecl *ParamDecl = FuncDecl->getParamDecl(I);
    QualType ParamType = ParamDecl->getType();
    ParamType.print(Stream, Ctx.getPrintingPolicy());

    // Print parameter name if it has one
    if (!ParamDecl->getName().empty())
      Stream << " " << ParamDecl->getNameAsString();

    // Print default argument if it exists
    if (ParamDecl->hasDefaultArg() &&
        !ParamDecl->hasUninstantiatedDefaultArg()) {
      if (const Expr *DefaultArg = ParamDecl->getDefaultArg()) {
        Stream << " = ";
        DefaultArg->printPretty(Stream, nullptr, Ctx.getPrintingPolicy());
      }
    }
  }

  // If it is a variadic function, add '...'
  if (FuncDecl->isVariadic()) {
    if (FuncDecl->getNumParams() > 0)
      Stream << ", ";
    Stream << "...";
  }

  Stream << ")";

  // If it's a const method, add 'const' qualifier
  if (Method) {
    if (Method->isDeleted())
      Stream << " = delete";
    if (Method->size_overridden_methods())
      Stream << " override";
    if (Method->hasAttr<clang::FinalAttr>())
      Stream << " final";
    if (Method->isConst())
      Stream << " const";
    if (Method->isPureVirtual())
      Stream << " = 0";
  }

  if (auto ExceptionSpecType = FuncDecl->getExceptionSpecType())
    Stream << " " << ExceptionSpecType;

  return Result; // Convert SmallString to std::string for return
}

static llvm::SmallString<16> getTypeAlias(const TypeAliasDecl *Alias) {
  llvm::SmallString<16> Result;
  llvm::raw_svector_ostream Stream(Result);
  const ASTContext &Ctx = Alias->getASTContext();
  if (const auto *TmplDecl = Alias->getDescribedTemplate())
    getTemplateParameters(TmplDecl->getTemplateParameters(), Stream);
  Stream << "using " << Alias->getNameAsString() << " = ";
  QualType Q = Alias->getUnderlyingType();
  Q.print(Stream, Ctx.getPrintingPolicy());

  return Result;
}

// extract full syntax for record declaration
static llvm::SmallString<16> getRecordPrototype(const CXXRecordDecl *CXXRD) {
  llvm::SmallString<16> Result;
  LangOptions LangOpts;
  PrintingPolicy Policy(LangOpts);
  Policy.SuppressTagKeyword = false;
  Policy.FullyQualifiedName = true;
  Policy.IncludeNewlines = false;
  llvm::raw_svector_ostream OS(Result);
  if (const auto *TD = CXXRD->getDescribedClassTemplate()) {
    OS << "template <";
    bool FirstParam = true;
    for (const auto *Param : *TD->getTemplateParameters()) {
      if (!FirstParam)
        OS << ", ";
      Param->print(OS, Policy);
      FirstParam = false;
    }
    OS << ">\n";
  }

  if (CXXRD->isStruct())
    OS << "struct ";
  else if (CXXRD->isClass())
    OS << "class ";
  else if (CXXRD->isUnion())
    OS << "union ";

  OS << CXXRD->getNameAsString();

  // We need to make sure we have a good enough declaration to check. In the
  // case where the class is a forward declaration, we'll fail assertions  in
  // DeclCXX.
  if (CXXRD->isCompleteDefinition() && CXXRD->getNumBases() > 0) {
    OS << " : ";
    bool FirstBase = true;
    for (const auto &Base : CXXRD->bases()) {
      if (!FirstBase)
        OS << ", ";
      if (Base.isVirtual())
        OS << "virtual ";
      OS << getAccessSpelling(Base.getAccessSpecifier()) << " ";
      OS << Base.getType().getAsString(Policy);
      FirstBase = false;
    }
  }
  return Result;
}

// A function to extract the appropriate relative path for a given info's
// documentation. The path returned is a composite of the parent namespaces.
//
// Example: Given the below, the directory path for class C info will be
// <root>/A/B
//
// namespace A {
// namespace B {
//
// class C {};
//
// }
// }
static llvm::SmallString<128>
getInfoRelativePath(const llvm::SmallVectorImpl<doc::Reference> &Namespaces) {
  llvm::SmallString<128> Path;
  for (auto R = Namespaces.rbegin(), E = Namespaces.rend(); R != E; ++R)
    llvm::sys::path::append(Path, R->Name);
  return Path;
}

static llvm::SmallString<128> getInfoRelativePath(const Decl *D) {
  llvm::SmallVector<Reference, 4> Namespaces;
  // The third arg in populateParentNamespaces is a boolean passed by reference,
  // its value is not relevant in here so it's not used anywhere besides the
  // function call
  bool B = true;
  populateParentNamespaces(Namespaces, D, B);
  return getInfoRelativePath(Namespaces);
}

class ClangDocCommentVisitor
    : public ConstCommentVisitor<ClangDocCommentVisitor> {
public:
  ClangDocCommentVisitor(CommentInfo &CI) : CurrentCI(CI) {}

  void parseComment(const comments::Comment *C);

  void visitTextComment(const TextComment *C);
  void visitInlineCommandComment(const InlineCommandComment *C);
  void visitHTMLStartTagComment(const HTMLStartTagComment *C);
  void visitHTMLEndTagComment(const HTMLEndTagComment *C);
  void visitBlockCommandComment(const BlockCommandComment *C);
  void visitParamCommandComment(const ParamCommandComment *C);
  void visitTParamCommandComment(const TParamCommandComment *C);
  void visitVerbatimBlockComment(const VerbatimBlockComment *C);
  void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
  void visitVerbatimLineComment(const VerbatimLineComment *C);

private:
  std::string getCommandName(unsigned CommandID) const;
  bool isWhitespaceOnly(StringRef S) const;

  CommentInfo &CurrentCI;
};

void ClangDocCommentVisitor::parseComment(const comments::Comment *C) {
  CurrentCI.Kind = stringToCommentKind(C->getCommentKindName());
  ConstCommentVisitor<ClangDocCommentVisitor>::visit(C);
  for (comments::Comment *Child :
       llvm::make_range(C->child_begin(), C->child_end())) {
    CurrentCI.Children.emplace_back(std::make_unique<CommentInfo>());
    ClangDocCommentVisitor Visitor(*CurrentCI.Children.back());
    Visitor.parseComment(Child);
  }
}

void ClangDocCommentVisitor::visitTextComment(const TextComment *C) {
  if (!isWhitespaceOnly(C->getText()))
    CurrentCI.Text = C->getText();
}

void ClangDocCommentVisitor::visitInlineCommandComment(
    const InlineCommandComment *C) {
  CurrentCI.Name = getCommandName(C->getCommandID());
  for (unsigned I = 0, E = C->getNumArgs(); I != E; ++I)
    CurrentCI.Args.push_back(C->getArgText(I));
}

void ClangDocCommentVisitor::visitHTMLStartTagComment(
    const HTMLStartTagComment *C) {
  CurrentCI.Name = C->getTagName();
  CurrentCI.SelfClosing = C->isSelfClosing();
  for (unsigned I = 0, E = C->getNumAttrs(); I < E; ++I) {
    const HTMLStartTagComment::Attribute &Attr = C->getAttr(I);
    CurrentCI.AttrKeys.push_back(Attr.Name);
    CurrentCI.AttrValues.push_back(Attr.Value);
  }
}

void ClangDocCommentVisitor::visitHTMLEndTagComment(
    const HTMLEndTagComment *C) {
  CurrentCI.Name = C->getTagName();
  CurrentCI.SelfClosing = true;
}

void ClangDocCommentVisitor::visitBlockCommandComment(
    const BlockCommandComment *C) {
  CurrentCI.Name = getCommandName(C->getCommandID());
  for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
    CurrentCI.Args.push_back(C->getArgText(I));
}

void ClangDocCommentVisitor::visitParamCommandComment(
    const ParamCommandComment *C) {
  CurrentCI.Direction =
      ParamCommandComment::getDirectionAsString(C->getDirection());
  CurrentCI.Explicit = C->isDirectionExplicit();
  if (C->hasParamName())
    CurrentCI.ParamName = C->getParamNameAsWritten();
}

void ClangDocCommentVisitor::visitTParamCommandComment(
    const TParamCommandComment *C) {
  if (C->hasParamName())
    CurrentCI.ParamName = C->getParamNameAsWritten();
}

void ClangDocCommentVisitor::visitVerbatimBlockComment(
    const VerbatimBlockComment *C) {
  CurrentCI.Name = getCommandName(C->getCommandID());
  CurrentCI.CloseName = C->getCloseName();
}

void ClangDocCommentVisitor::visitVerbatimBlockLineComment(
    const VerbatimBlockLineComment *C) {
  if (!isWhitespaceOnly(C->getText()))
    CurrentCI.Text = C->getText();
}

void ClangDocCommentVisitor::visitVerbatimLineComment(
    const VerbatimLineComment *C) {
  if (!isWhitespaceOnly(C->getText()))
    CurrentCI.Text = C->getText();
}

bool ClangDocCommentVisitor::isWhitespaceOnly(llvm::StringRef S) const {
  return llvm::all_of(S, isspace);
}

std::string ClangDocCommentVisitor::getCommandName(unsigned CommandID) const {
  const CommandInfo *Info = CommandTraits::getBuiltinCommandInfo(CommandID);
  if (Info)
    return Info->Name;
  // TODO: Add parsing for \file command.
  return "<not a builtin command>";
}

// Serializing functions.

static std::string getSourceCode(const Decl *D, const SourceRange &R) {
  return Lexer::getSourceText(CharSourceRange::getTokenRange(R),
                              D->getASTContext().getSourceManager(),
                              D->getASTContext().getLangOpts())
      .str();
}

template <typename T> static std::string serialize(T &I) {
  SmallString<2048> Buffer;
  llvm::BitstreamWriter Stream(Buffer);
  ClangDocBitcodeWriter Writer(Stream);
  Writer.emitBlock(I);
  return Buffer.str().str();
}

std::string serialize(std::unique_ptr<Info> &I) {
  switch (I->IT) {
  case InfoType::IT_namespace:
    return serialize(*static_cast<NamespaceInfo *>(I.get()));
  case InfoType::IT_record:
    return serialize(*static_cast<RecordInfo *>(I.get()));
  case InfoType::IT_enum:
    return serialize(*static_cast<EnumInfo *>(I.get()));
  case InfoType::IT_function:
    return serialize(*static_cast<FunctionInfo *>(I.get()));
  case InfoType::IT_concept:
    return serialize(*static_cast<ConceptInfo *>(I.get()));
  case InfoType::IT_variable:
    return serialize(*static_cast<VarInfo *>(I.get()));
  case InfoType::IT_friend:
  case InfoType::IT_typedef:
  case InfoType::IT_default:
    return "";
  }
  llvm_unreachable("unhandled enumerator");
}

static void parseFullComment(const FullComment *C, CommentInfo &CI) {
  ClangDocCommentVisitor Visitor(CI);
  Visitor.parseComment(C);
}

static SymbolID getUSRForDecl(const Decl *D) {
  llvm::SmallString<128> USR;
  if (index::generateUSRForDecl(D, USR))
    return SymbolID();
  return hashUSR(USR);
}

static TagDecl *getTagDeclForType(const QualType &T) {
  if (const TagDecl *D = T->getAsTagDecl())
    return D->getDefinition();
  return nullptr;
}

static RecordDecl *getRecordDeclForType(const QualType &T) {
  if (const RecordDecl *D = T->getAsRecordDecl())
    return D->getDefinition();
  return nullptr;
}

static TypeInfo getTypeInfoForType(const QualType &T,
                                   const PrintingPolicy &Policy) {
  const TagDecl *TD = getTagDeclForType(T);
  if (!TD) {
    TypeInfo TI = TypeInfo(Reference(SymbolID(), T.getAsString(Policy)));
    TI.IsBuiltIn = T->isBuiltinType();
    TI.IsTemplate = T->isTemplateTypeParmType();
    return TI;
  }
  InfoType IT;
  if (isa<EnumDecl>(TD)) {
    IT = InfoType::IT_enum;
  } else if (isa<RecordDecl>(TD)) {
    IT = InfoType::IT_record;
  } else {
    IT = InfoType::IT_default;
  }
  Reference R = Reference(getUSRForDecl(TD), TD->getNameAsString(), IT,
                          T.getAsString(Policy), getInfoRelativePath(TD));
  TypeInfo TI = TypeInfo(R);
  TI.IsBuiltIn = T->isBuiltinType();
  TI.IsTemplate = T->isTemplateTypeParmType();
  return TI;
}

static bool isPublic(const clang::AccessSpecifier AS,
                     const clang::Linkage Link) {
  if (AS == clang::AccessSpecifier::AS_private)
    return false;
  if ((Link == clang::Linkage::Module) || (Link == clang::Linkage::External))
    return true;
  return false; // otherwise, linkage is some form of internal linkage
}

static bool shouldSerializeInfo(bool PublicOnly, bool IsInAnonymousNamespace,
                                const NamedDecl *D) {
  bool IsAnonymousNamespace = false;
  if (const auto *N = dyn_cast<NamespaceDecl>(D))
    IsAnonymousNamespace = N->isAnonymousNamespace();
  return !PublicOnly ||
         (!IsInAnonymousNamespace && !IsAnonymousNamespace &&
          isPublic(D->getAccessUnsafe(), D->getLinkageInternal()));
}

// The InsertChild functions insert the given info into the given scope using
// the method appropriate for that type. Some types are moved into the
// appropriate vector, while other types have Reference objects generated to
// refer to them.
//
// See MakeAndInsertIntoParent().
static void InsertChild(ScopeChildren &Scope, const NamespaceInfo &Info) {
  Scope.Namespaces.emplace_back(Info.USR, Info.Name, InfoType::IT_namespace,
                                Info.Name, getInfoRelativePath(Info.Namespace));
}

static void InsertChild(ScopeChildren &Scope, const RecordInfo &Info) {
  Scope.Records.emplace_back(Info.USR, Info.Name, InfoType::IT_record,
                             Info.Name, getInfoRelativePath(Info.Namespace));
}

static void InsertChild(ScopeChildren &Scope, EnumInfo Info) {
  Scope.Enums.push_back(std::move(Info));
}

static void InsertChild(ScopeChildren &Scope, FunctionInfo Info) {
  Scope.Functions.push_back(std::move(Info));
}

static void InsertChild(ScopeChildren &Scope, TypedefInfo Info) {
  Scope.Typedefs.push_back(std::move(Info));
}

static void InsertChild(ScopeChildren &Scope, ConceptInfo Info) {
  Scope.Concepts.push_back(std::move(Info));
}

static void InsertChild(ScopeChildren &Scope, VarInfo Info) {
  Scope.Variables.push_back(std::move(Info));
}

// Creates a parent of the correct type for the given child and inserts it into
// that parent.
//
// This is complicated by the fact that namespaces and records are inserted by
// reference (constructing a "Reference" object with that namespace/record's
// info), while everything else is inserted by moving it directly into the child
// vectors.
//
// For namespaces and records, explicitly specify a const& template parameter
// when invoking this function:
//   MakeAndInsertIntoParent<const Record&>(...);
// Otherwise, specify an rvalue reference <EnumInfo&&> and move into the
// parameter. Since each variant is used once, it's not worth having a more
// elaborate system to automatically deduce this information.
template <typename ChildType>
static std::unique_ptr<Info> makeAndInsertIntoParent(ChildType Child) {
  if (Child.Namespace.empty()) {
    // Insert into unnamed parent namespace.
    auto ParentNS = std::make_unique<NamespaceInfo>();
    InsertChild(ParentNS->Children, std::forward<ChildType>(Child));
    return ParentNS;
  }

  switch (Child.Namespace[0].RefType) {
  case InfoType::IT_namespace: {
    auto ParentNS = std::make_unique<NamespaceInfo>();
    ParentNS->USR = Child.Namespace[0].USR;
    InsertChild(ParentNS->Children, std::forward<ChildType>(Child));
    return ParentNS;
  }
  case InfoType::IT_record: {
    auto ParentRec = std::make_unique<RecordInfo>();
    ParentRec->USR = Child.Namespace[0].USR;
    InsertChild(ParentRec->Children, std::forward<ChildType>(Child));
    return ParentRec;
  }
  case InfoType::IT_default:
  case InfoType::IT_enum:
  case InfoType::IT_function:
  case InfoType::IT_typedef:
  case InfoType::IT_concept:
  case InfoType::IT_variable:
  case InfoType::IT_friend:
    break;
  }
  llvm_unreachable("Invalid reference type for parent namespace");
}

// There are two uses for this function.
// 1) Getting the resulting mode of inheritance of a record.
//    Example: class A {}; class B : private A {}; class C : public B {};
//    It's explicit that C is publicly inherited from C and B is privately
//    inherited from A. It's not explicit but C is also privately inherited from
//    A. This is the AS that this function calculates. FirstAS is the
//    inheritance mode of `class C : B` and SecondAS is the inheritance mode of
//    `class B : A`.
// 2) Getting the inheritance mode of an inherited attribute / method.
//    Example : class A { public: int M; }; class B : private A {};
//    Class B is inherited from class A, which has a public attribute. This
//    attribute is now part of the derived class B but it's not public. This
//    will be private because the inheritance is private. This is the AS that
//    this function calculates. FirstAS is the inheritance mode and SecondAS is
//    the AS of the attribute / method.
static AccessSpecifier getFinalAccessSpecifier(AccessSpecifier FirstAS,
                                               AccessSpecifier SecondAS) {
  if (FirstAS == AccessSpecifier::AS_none ||
      SecondAS == AccessSpecifier::AS_none)
    return AccessSpecifier::AS_none;
  if (FirstAS == AccessSpecifier::AS_private ||
      SecondAS == AccessSpecifier::AS_private)
    return AccessSpecifier::AS_private;
  if (FirstAS == AccessSpecifier::AS_protected ||
      SecondAS == AccessSpecifier::AS_protected)
    return AccessSpecifier::AS_protected;
  return AccessSpecifier::AS_public;
}

// The Access parameter is only provided when parsing the field of an inherited
// record, the access specification of the field depends on the inheritance mode
static void parseFields(RecordInfo &I, const RecordDecl *D, bool PublicOnly,
                        AccessSpecifier Access = AccessSpecifier::AS_public) {
  for (const FieldDecl *F : D->fields()) {
    if (!shouldSerializeInfo(PublicOnly, /*IsInAnonymousNamespace=*/false, F))
      continue;
    populateMemberTypeInfo(I, Access, F);
  }
  const auto *CxxRD = dyn_cast<CXXRecordDecl>(D);
  if (!CxxRD)
    return;
  for (Decl *CxxDecl : CxxRD->decls()) {
    auto *VD = dyn_cast<VarDecl>(CxxDecl);
    if (!VD ||
        !shouldSerializeInfo(PublicOnly, /*IsInAnonymousNamespace=*/false, VD))
      continue;

    if (VD->isStaticDataMember())
      populateMemberTypeInfo(I, Access, VD, /*IsStatic=*/true);
  }
}

static void parseEnumerators(EnumInfo &I, const EnumDecl *D) {
  for (const EnumConstantDecl *E : D->enumerators()) {
    std::string ValueExpr;
    if (const Expr *InitExpr = E->getInitExpr())
      ValueExpr = getSourceCode(D, InitExpr->getSourceRange());
    SmallString<16> ValueStr;
    E->getInitVal().toString(ValueStr);
    I.Members.emplace_back(E->getNameAsString(), ValueStr.str(), ValueExpr);
    ASTContext &Context = E->getASTContext();
    if (RawComment *Comment =
            E->getASTContext().getRawCommentForDeclNoCache(E)) {
      Comment->setAttached();
      if (comments::FullComment *Fc = Comment->parse(Context, nullptr, E)) {
        EnumValueInfo &Member = I.Members.back();
        Member.Description.emplace_back();
        parseFullComment(Fc, Member.Description.back());
      }
    }
  }
}

static void parseParameters(FunctionInfo &I, const FunctionDecl *D) {
  auto &LO = D->getLangOpts();
  for (const ParmVarDecl *P : D->parameters()) {
    FieldTypeInfo &FieldInfo = I.Params.emplace_back(
        getTypeInfoForType(P->getOriginalType(), LO), P->getNameAsString());
    FieldInfo.DefaultValue = getSourceCode(D, P->getDefaultArgRange());
  }
}

// TODO: Remove the serialization of Parents and VirtualParents, this
// information is also extracted in the other definition of parseBases.
static void parseBases(RecordInfo &I, const CXXRecordDecl *D) {
  // Don't parse bases if this isn't a definition.
  if (!D->isThisDeclarationADefinition())
    return;

  for (const CXXBaseSpecifier &B : D->bases()) {
    if (B.isVirtual())
      continue;
    if (const auto *Ty = B.getType()->getAs<TemplateSpecializationType>()) {
      const TemplateDecl *D = Ty->getTemplateName().getAsTemplateDecl();
      I.Parents.emplace_back(getUSRForDecl(D), B.getType().getAsString(),
                             InfoType::IT_record, B.getType().getAsString());
    } else if (const RecordDecl *P = getRecordDeclForType(B.getType()))
      I.Parents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
                             InfoType::IT_record, P->getQualifiedNameAsString(),
                             getInfoRelativePath(P));
    else
      I.Parents.emplace_back(SymbolID(), B.getType().getAsString());
  }
  for (const CXXBaseSpecifier &B : D->vbases()) {
    if (const RecordDecl *P = getRecordDeclForType(B.getType()))
      I.VirtualParents.emplace_back(
          getUSRForDecl(P), P->getNameAsString(), InfoType::IT_record,
          P->getQualifiedNameAsString(), getInfoRelativePath(P));
    else
      I.VirtualParents.emplace_back(SymbolID(), B.getType().getAsString());
  }
}

template <typename T>
static void
populateParentNamespaces(llvm::SmallVector<Reference, 4> &Namespaces,
                         const T *D, bool &IsInAnonymousNamespace) {
  const DeclContext *DC = D->getDeclContext();
  do {
    if (const auto *N = dyn_cast<NamespaceDecl>(DC)) {
      std::string Namespace;
      if (N->isAnonymousNamespace()) {
        Namespace = "@nonymous_namespace";
        IsInAnonymousNamespace = true;
      } else
        Namespace = N->getNameAsString();
      Namespaces.emplace_back(getUSRForDecl(N), Namespace,
                              InfoType::IT_namespace,
                              N->getQualifiedNameAsString());
    } else if (const auto *N = dyn_cast<RecordDecl>(DC))
      Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
                              InfoType::IT_record,
                              N->getQualifiedNameAsString());
    else if (const auto *N = dyn_cast<FunctionDecl>(DC))
      Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
                              InfoType::IT_function,
                              N->getQualifiedNameAsString());
    else if (const auto *N = dyn_cast<EnumDecl>(DC))
      Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
                              InfoType::IT_enum, N->getQualifiedNameAsString());
  } while ((DC = DC->getParent()));
  // The global namespace should be added to the list of namespaces if the decl
  // corresponds to a Record and if it doesn't have any namespace (because this
  // means it's in the global namespace). Also if its outermost namespace is a
  // record because that record matches the previous condition mentioned.
  if ((Namespaces.empty() && isa<RecordDecl>(D)) ||
      (!Namespaces.empty() && Namespaces.back().RefType == InfoType::IT_record))
    Namespaces.emplace_back(SymbolID(), "GlobalNamespace",
                            InfoType::IT_namespace);
}

static void
populateTemplateParameters(std::optional<TemplateInfo> &TemplateInfo,
                           const clang::Decl *D) {
  if (const TemplateParameterList *ParamList =
          D->getDescribedTemplateParams()) {
    if (!TemplateInfo) {
      TemplateInfo.emplace();
    }
    for (const NamedDecl *ND : *ParamList) {
      TemplateInfo->Params.emplace_back(
          getSourceCode(ND, ND->getSourceRange()));
    }
  }
}

static TemplateParamInfo convertTemplateArgToInfo(const clang::Decl *D,
                                                  const TemplateArgument &Arg) {
  // The TemplateArgument's pretty printing handles all the normal cases
  // well enough for our requirements.
  std::string Str;
  llvm::raw_string_ostream Stream(Str);
  Arg.print(PrintingPolicy(D->getLangOpts()), Stream, false);
  return TemplateParamInfo(Str);
}

template <typename T>
static void populateInfo(Info &I, const T *D, const FullComment *C,
                         bool &IsInAnonymousNamespace) {
  I.USR = getUSRForDecl(D);
  if (auto ConversionDecl = dyn_cast_or_null<CXXConversionDecl>(D);
      ConversionDecl && ConversionDecl->getConversionType()
                            .getTypePtr()
                            ->isTemplateTypeParmType())
    I.Name = "operator " + ConversionDecl->getConversionType().getAsString();
  else
    I.Name = D->getNameAsString();
  populateParentNamespaces(I.Namespace, D, IsInAnonymousNamespace);
  if (C) {
    I.Description.emplace_back();
    parseFullComment(C, I.Description.back());
  }
}

template <typename T>
static void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C,
                               Location Loc, bool &IsInAnonymousNamespace) {
  populateInfo(I, D, C, IsInAnonymousNamespace);
  if (D->isThisDeclarationADefinition())
    I.DefLoc = Loc;
  else
    I.Loc.emplace_back(Loc);

  auto *Mangler = ItaniumMangleContext::create(
      D->getASTContext(), D->getASTContext().getDiagnostics());
  std::string MangledName;
  llvm::raw_string_ostream MangledStream(MangledName);
  if (auto *CXXD = dyn_cast<CXXRecordDecl>(D))
    Mangler->mangleCXXVTable(CXXD, MangledStream);
  else
    MangledStream << D->getNameAsString();
  I.MangledName = MangledName;
  delete Mangler;
}

static void
handleCompoundConstraints(const Expr *Constraint,
                          std::vector<ConstraintInfo> &ConstraintInfos) {
  if (Constraint->getStmtClass() == Stmt::ParenExprClass) {
    handleCompoundConstraints(dyn_cast<ParenExpr>(Constraint)->getSubExpr(),
                              ConstraintInfos);
  } else if (Constraint->getStmtClass() == Stmt::BinaryOperatorClass) {
    auto *BinaryOpExpr = dyn_cast<BinaryOperator>(Constraint);
    handleCompoundConstraints(BinaryOpExpr->getLHS(), ConstraintInfos);
    handleCompoundConstraints(BinaryOpExpr->getRHS(), ConstraintInfos);
  } else if (Constraint->getStmtClass() ==
             Stmt::ConceptSpecializationExprClass) {
    auto *Concept = dyn_cast<ConceptSpecializationExpr>(Constraint);
    ConstraintInfo CI(getUSRForDecl(Concept->getNamedConcept()),
                      Concept->getNamedConcept()->getNameAsString());
    CI.ConstraintExpr = exprToString(Concept);
    ConstraintInfos.push_back(CI);
  }
}

static void populateConstraints(TemplateInfo &I, const TemplateDecl *D) {
  if (!D || !D->hasAssociatedConstraints())
    return;

  SmallVector<AssociatedConstraint> AssociatedConstraints;
  D->getAssociatedConstraints(AssociatedConstraints);
  for (const auto &Constraint : AssociatedConstraints) {
    if (!Constraint)
      continue;

    // TODO: Investigate if atomic constraints need to be handled specifically.
    if (const auto *ConstraintExpr =
            dyn_cast_or_null<ConceptSpecializationExpr>(
                Constraint.ConstraintExpr)) {
      ConstraintInfo CI(getUSRForDecl(ConstraintExpr->getNamedConcept()),
                        ConstraintExpr->getNamedConcept()->getNameAsString());
      CI.ConstraintExpr = exprToString(ConstraintExpr);
      I.Constraints.push_back(std::move(CI));
    } else {
      handleCompoundConstraints(Constraint.ConstraintExpr, I.Constraints);
    }
  }
}

static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
                                 const FullComment *FC, Location Loc,
                                 bool &IsInAnonymousNamespace) {
  populateSymbolInfo(I, D, FC, Loc, IsInAnonymousNamespace);
  auto &LO = D->getLangOpts();
  I.ReturnType = getTypeInfoForType(D->getReturnType(), LO);
  I.Prototype = getFunctionPrototype(D);
  parseParameters(I, D);
  I.IsStatic = D->isStatic();

  populateTemplateParameters(I.Template, D);
  if (I.Template)
    populateConstraints(I.Template.value(), D->getDescribedFunctionTemplate());

  // Handle function template specializations.
  if (const FunctionTemplateSpecializationInfo *FTSI =
          D->getTemplateSpecializationInfo()) {
    if (!I.Template)
      I.Template.emplace();
    I.Template->Specialization.emplace();
    auto &Specialization = *I.Template->Specialization;

    Specialization.SpecializationOf = getUSRForDecl(FTSI->getTemplate());

    // Template parameters to the specialization.
    if (FTSI->TemplateArguments) {
      for (const TemplateArgument &Arg : FTSI->TemplateArguments->asArray()) {
        Specialization.Params.push_back(convertTemplateArgToInfo(D, Arg));
      }
    }
  }
}

static void populateMemberTypeInfo(MemberTypeInfo &I, const Decl *D) {
  assert(D && "Expect non-null FieldDecl in populateMemberTypeInfo");

  ASTContext &Context = D->getASTContext();
  // TODO investigate whether we can use ASTContext::getCommentForDecl instead
  // of this logic. See also similar code in Mapper.cpp.
  RawComment *Comment = Context.getRawCommentForDeclNoCache(D);
  if (!Comment)
    return;

  Comment->setAttached();
  if (comments::FullComment *Fc = Comment->parse(Context, nullptr, D)) {
    I.Description.emplace_back();
    parseFullComment(Fc, I.Description.back());
  }
}

static void populateMemberTypeInfo(RecordInfo &I, AccessSpecifier &Access,
                                   const DeclaratorDecl *D, bool IsStatic) {
  // Use getAccessUnsafe so that we just get the default AS_none if it's not
  // valid, as opposed to an assert.
  MemberTypeInfo &NewMember = I.Members.emplace_back(
      getTypeInfoForType(D->getTypeSourceInfo()->getType(), D->getLangOpts()),
      D->getNameAsString(),
      getFinalAccessSpecifier(Access, D->getAccessUnsafe()), IsStatic);
  populateMemberTypeInfo(NewMember, D);
}

static void
parseBases(RecordInfo &I, const CXXRecordDecl *D, bool IsFileInRootDir,
           bool PublicOnly, bool IsParent,
           AccessSpecifier ParentAccess = AccessSpecifier::AS_public) {
  // Don't parse bases if this isn't a definition.
  if (!D->isThisDeclarationADefinition())
    return;
  for (const CXXBaseSpecifier &B : D->bases()) {
    if (const RecordType *Ty = B.getType()->getAs<RecordType>()) {
      if (const CXXRecordDecl *Base =
              cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition())) {
        // Initialized without USR and name, this will be set in the following
        // if-else stmt.
        BaseRecordInfo BI(
            {}, "", getInfoRelativePath(Base), B.isVirtual(),
            getFinalAccessSpecifier(ParentAccess, B.getAccessSpecifier()),
            IsParent);
        if (const auto *Ty = B.getType()->getAs<TemplateSpecializationType>()) {
          const TemplateDecl *D = Ty->getTemplateName().getAsTemplateDecl();
          BI.USR = getUSRForDecl(D);
          BI.Name = B.getType().getAsString();
        } else {
          BI.USR = getUSRForDecl(Base);
          BI.Name = Base->getNameAsString();
        }
        parseFields(BI, Base, PublicOnly, BI.Access);
        for (const auto &Decl : Base->decls())
          if (const auto *MD = dyn_cast<CXXMethodDecl>(Decl)) {
            // Don't serialize private methods
            if (MD->getAccessUnsafe() == AccessSpecifier::AS_private ||
                !MD->isUserProvided())
              continue;
            FunctionInfo FI;
            FI.IsMethod = true;
            FI.IsStatic = MD->isStatic();
            // The seventh arg in populateFunctionInfo is a boolean passed by
            // reference, its value is not relevant in here so it's not used
            // anywhere besides the function call.
            bool IsInAnonymousNamespace;
            populateFunctionInfo(FI, MD, /*FullComment=*/{}, /*Location=*/{},
                                 IsInAnonymousNamespace);
            FI.Access =
                getFinalAccessSpecifier(BI.Access, MD->getAccessUnsafe());
            BI.Children.Functions.emplace_back(std::move(FI));
          }
        I.Bases.emplace_back(std::move(BI));
        // Call this function recursively to get the inherited classes of
        // this base; these new bases will also get stored in the original
        // RecordInfo: I.
        parseBases(I, Base, IsFileInRootDir, PublicOnly, false,
                   I.Bases.back().Access);
      }
    }
  }
}

std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
emitInfo(const NamespaceDecl *D, const FullComment *FC, Location Loc,
         bool PublicOnly) {
  auto NSI = std::make_unique<NamespaceInfo>();
  bool IsInAnonymousNamespace = false;
  populateInfo(*NSI, D, FC, IsInAnonymousNamespace);
  if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
    return {};

  NSI->Name = D->isAnonymousNamespace()
                  ? llvm::SmallString<16>("@nonymous_namespace")
                  : NSI->Name;
  NSI->Path = getInfoRelativePath(NSI->Namespace);
  if (NSI->Namespace.empty() && NSI->USR == SymbolID())
    return {std::unique_ptr<Info>{std::move(NSI)}, nullptr};

  // Namespaces are inserted into the parent by reference, so we need to return
  // both the parent and the record itself.
  return {std::move(NSI), makeAndInsertIntoParent<const NamespaceInfo &>(*NSI)};
}

static void parseFriends(RecordInfo &RI, const CXXRecordDecl *D) {
  if (!D->hasDefinition() || !D->hasFriends())
    return;

  for (const FriendDecl *FD : D->friends()) {
    if (FD->isUnsupportedFriend())
      continue;

    FriendInfo F(InfoType::IT_friend, getUSRForDecl(FD));
    const auto *ActualDecl = FD->getFriendDecl();
    if (!ActualDecl) {
      const auto *FriendTypeInfo = FD->getFriendType();
      if (!FriendTypeInfo)
        continue;
      ActualDecl = FriendTypeInfo->getType()->getAsCXXRecordDecl();

      if (!ActualDecl)
        continue;
      F.IsClass = true;
    }

    if (const auto *ActualTD = dyn_cast_or_null<TemplateDecl>(ActualDecl)) {
      if (isa<RecordDecl>(ActualTD->getTemplatedDecl()))
        F.IsClass = true;
      F.Template.emplace();
      for (const auto *Param : ActualTD->getTemplateParameters()->asArray())
        F.Template->Params.emplace_back(
            getSourceCode(Param, Param->getSourceRange()));
      ActualDecl = ActualTD->getTemplatedDecl();
    }

    if (auto *FuncDecl = dyn_cast_or_null<FunctionDecl>(ActualDecl)) {
      FunctionInfo TempInfo;
      parseParameters(TempInfo, FuncDecl);
      F.Params.emplace();
      F.Params = std::move(TempInfo.Params);
      F.ReturnType = getTypeInfoForType(FuncDecl->getReturnType(),
                                        FuncDecl->getLangOpts());
    }

    F.Ref =
        Reference(getUSRForDecl(ActualDecl), ActualDecl->getNameAsString(),
                  InfoType::IT_default, ActualDecl->getQualifiedNameAsString(),
                  getInfoRelativePath(ActualDecl));

    RI.Friends.push_back(std::move(F));
  }
}

std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc,
         bool PublicOnly) {

  auto RI = std::make_unique<RecordInfo>();
  bool IsInAnonymousNamespace = false;

  populateSymbolInfo(*RI, D, FC, Loc, IsInAnonymousNamespace);
  if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
    return {};

  RI->TagType = D->getTagKind();
  parseFields(*RI, D, PublicOnly);

  if (const auto *C = dyn_cast<CXXRecordDecl>(D)) {
    RI->FullName = getRecordPrototype(C);
    if (const TypedefNameDecl *TD = C->getTypedefNameForAnonDecl()) {
      RI->Name = TD->getNameAsString();
      RI->IsTypeDef = true;
    }
    // TODO: remove first call to parseBases, that function should be deleted
    parseBases(*RI, C);
    parseBases(*RI, C, /*IsFileInRootDir=*/true, PublicOnly, /*IsParent=*/true);
    parseFriends(*RI, C);
  }
  RI->Path = getInfoRelativePath(RI->Namespace);

  populateTemplateParameters(RI->Template, D);
  if (RI->Template)
    populateConstraints(RI->Template.value(), D->getDescribedTemplate());

  // Full and partial specializations.
  if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
    if (!RI->Template)
      RI->Template.emplace();
    RI->Template->Specialization.emplace();
    auto &Specialization = *RI->Template->Specialization;

    // What this is a specialization of.
    auto SpecOf = CTSD->getSpecializedTemplateOrPartial();
    if (auto *SpecTD = dyn_cast<ClassTemplateDecl *>(SpecOf))
      Specialization.SpecializationOf = getUSRForDecl(SpecTD);
    else if (auto *SpecTD =
                 dyn_cast<ClassTemplatePartialSpecializationDecl *>(SpecOf))
      Specialization.SpecializationOf = getUSRForDecl(SpecTD);

    // Parameters to the specialization. For partial specializations, get the
    // parameters "as written" from the ClassTemplatePartialSpecializationDecl
    // because the non-explicit template parameters will have generated internal
    // placeholder names rather than the names the user typed that match the
    // template parameters.
    if (const ClassTemplatePartialSpecializationDecl *CTPSD =
            dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
      if (const ASTTemplateArgumentListInfo *AsWritten =
              CTPSD->getTemplateArgsAsWritten()) {
        for (unsigned Idx = 0; Idx < AsWritten->getNumTemplateArgs(); Idx++) {
          Specialization.Params.emplace_back(
              getSourceCode(D, (*AsWritten)[Idx].getSourceRange()));
        }
      }
    } else {
      for (const TemplateArgument &Arg : CTSD->getTemplateArgs().asArray()) {
        Specialization.Params.push_back(convertTemplateArgToInfo(D, Arg));
      }
    }
  }

  // Records are inserted into the parent by reference, so we need to return
  // both the parent and the record itself.
  auto Parent = makeAndInsertIntoParent<const RecordInfo &>(*RI);
  return {std::move(RI), std::move(Parent)};
}

std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
emitInfo(const FunctionDecl *D, const FullComment *FC, Location Loc,
         bool PublicOnly) {
  FunctionInfo Func;
  bool IsInAnonymousNamespace = false;
  populateFunctionInfo(Func, D, FC, Loc, IsInAnonymousNamespace);
  Func.Access = clang::AccessSpecifier::AS_none;
  if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
    return {};

  // Info is wrapped in its parent scope so is returned in the second position.
  return {nullptr, makeAndInsertIntoParent<FunctionInfo &&>(std::move(Func))};
}

std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
emitInfo(const CXXMethodDecl *D, const FullComment *FC, Location Loc,
         bool PublicOnly) {
  FunctionInfo Func;
  bool IsInAnonymousNamespace = false;
  populateFunctionInfo(Func, D, FC, Loc, IsInAnonymousNamespace);
  if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
    return {};

  Func.IsMethod = true;
  Func.IsStatic = D->isStatic();

  const NamedDecl *Parent = nullptr;
  if (const auto *SD =
          dyn_cast<ClassTemplateSpecializationDecl>(D->getParent()))
    Parent = SD->getSpecializedTemplate();
  else
    Parent = D->getParent();

  SymbolID ParentUSR = getUSRForDecl(Parent);
  Func.Parent =
      Reference{ParentUSR, Parent->getNameAsString(), InfoType::IT_record,
                Parent->getQualifiedNameAsString()};
  Func.Access = D->getAccess();

  // Info is wrapped in its parent scope so is returned in the second position.
  return {nullptr, makeAndInsertIntoParent<FunctionInfo &&>(std::move(Func))};
}

static void extractCommentFromDecl(const Decl *D, TypedefInfo &Info) {
  assert(D && "Invalid Decl when extracting comment");
  ASTContext &Context = D->getASTContext();
  RawComment *Comment = Context.getRawCommentForDeclNoCache(D);
  if (!Comment)
    return;

  Comment->setAttached();
  if (comments::FullComment *Fc = Comment->parse(Context, nullptr, D)) {
    Info.Description.emplace_back();
    parseFullComment(Fc, Info.Description.back());
  }
}

std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
emitInfo(const TypedefDecl *D, const FullComment *FC, Location Loc,
         bool PublicOnly) {
  TypedefInfo Info;
  bool IsInAnonymousNamespace = false;
  populateInfo(Info, D, FC, IsInAnonymousNamespace);

  if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
    return {};

  Info.DefLoc = Loc;
  auto &LO = D->getLangOpts();
  Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);

  if (Info.Underlying.Type.Name.empty()) {
    // Typedef for an unnamed type. This is like "typedef struct { } Foo;"
    // The record serializer explicitly checks for this syntax and constructs
    // a record with that name, so we don't want to emit a duplicate here.
    return {};
  }
  Info.IsUsing = false;
  extractCommentFromDecl(D, Info);

  // Info is wrapped in its parent scope so is returned in the second position.
  return {nullptr, makeAndInsertIntoParent<TypedefInfo &&>(std::move(Info))};
}

// A type alias is a C++ "using" declaration for a type. It gets mapped to a
// TypedefInfo with the IsUsing flag set.
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
emitInfo(const TypeAliasDecl *D, const FullComment *FC, Location Loc,
         bool PublicOnly) {
  TypedefInfo Info;
  bool IsInAnonymousNamespace = false;
  populateInfo(Info, D, FC, IsInAnonymousNamespace);
  if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
    return {};

  Info.DefLoc = Loc;
  const LangOptions &LO = D->getLangOpts();
  Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);
  Info.TypeDeclaration = getTypeAlias(D);
  Info.IsUsing = true;

  extractCommentFromDecl(D, Info);

  // Info is wrapped in its parent scope so is returned in the second position.
  return {nullptr, makeAndInsertIntoParent<TypedefInfo &&>(std::move(Info))};
}

std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
emitInfo(const EnumDecl *D, const FullComment *FC, Location Loc,
         bool PublicOnly) {
  EnumInfo Enum;
  bool IsInAnonymousNamespace = false;
  populateSymbolInfo(Enum, D, FC, Loc, IsInAnonymousNamespace);

  if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
    return {};

  Enum.Scoped = D->isScoped();
  if (D->isFixed()) {
    auto Name = D->getIntegerType().getAsString();
    Enum.BaseType = TypeInfo(Name, Name);
  }
  parseEnumerators(Enum, D);

  // Info is wrapped in its parent scope so is returned in the second position.
  return {nullptr, makeAndInsertIntoParent<EnumInfo &&>(std::move(Enum))};
}

std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
emitInfo(const ConceptDecl *D, const FullComment *FC, const Location &Loc,
         bool PublicOnly) {
  ConceptInfo Concept;

  bool IsInAnonymousNamespace = false;
  populateInfo(Concept, D, FC, IsInAnonymousNamespace);
  Concept.IsType = D->isTypeConcept();
  Concept.DefLoc = Loc;
  Concept.ConstraintExpression = exprToString(D->getConstraintExpr());

  if (auto *ConceptParams = D->getTemplateParameters()) {
    for (const auto *Param : ConceptParams->asArray()) {
      Concept.Template.Params.emplace_back(
          getSourceCode(Param, Param->getSourceRange()));
    }
  }

  if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
    return {};

  return {nullptr, makeAndInsertIntoParent<ConceptInfo &&>(std::move(Concept))};
}

std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
emitInfo(const VarDecl *D, const FullComment *FC, const Location &Loc,
         bool PublicOnly) {
  VarInfo Var;
  bool IsInAnonymousNamespace = false;
  populateSymbolInfo(Var, D, FC, Loc, IsInAnonymousNamespace);
  if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
    return {};

  if (D->getStorageClass() == StorageClass::SC_Static)
    Var.IsStatic = true;
  Var.Type =
      getTypeInfoForType(D->getType(), D->getASTContext().getPrintingPolicy());

  if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
    return {};

  return {nullptr, makeAndInsertIntoParent<VarInfo &&>(std::move(Var))};
}

} // namespace serialize
} // namespace doc
} // namespace clang
