//===-- 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),
                             Info.MangledName);
}

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();
  // A 250 length limit was chosen since 255 is a common limit across
  // different filesystems, with a 5 character buffer for file extensions.
  if (MangledName.size() > 250)
    // File creation fails if the mangled name is too long, so default to the
    // USR. We should look for a better check since filesystems differ in
    // maximum filename length
    I.MangledName = llvm::toStringRef(llvm::toHex(I.USR));
  else
    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 auto *Base = B.getType()->getAsCXXRecordDecl()) {
      if (Base->isCompleteDefinition()) {
        // 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
