#include "clang/AST/JSONNodeDumper.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/StringExtras.h"

using namespace clang;

void JSONNodeDumper::addPreviousDeclaration(const Decl *D) {
  switch (D->getKind()) {
#define DECL(DERIVED, BASE)                                                    \
  case Decl::DERIVED:                                                          \
    return writePreviousDeclImpl(cast<DERIVED##Decl>(D));
#define ABSTRACT_DECL(DECL)
#include "clang/AST/DeclNodes.inc"
#undef ABSTRACT_DECL
#undef DECL
  }
  llvm_unreachable("Decl that isn't part of DeclNodes.inc!");
}

void JSONNodeDumper::Visit(const Attr *A) {
  const char *AttrName = nullptr;
  switch (A->getKind()) {
#define ATTR(X)                                                                \
  case attr::X:                                                                \
    AttrName = #X"Attr";                                                       \
    break;
#include "clang/Basic/AttrList.inc"
#undef ATTR
  }
  JOS.attribute("id", createPointerRepresentation(A));
  JOS.attribute("kind", AttrName);
  JOS.attributeObject("range", [A, this] { writeSourceRange(A->getRange()); });
  attributeOnlyIfTrue("inherited", A->isInherited());
  attributeOnlyIfTrue("implicit", A->isImplicit());

  // FIXME: it would be useful for us to output the spelling kind as well as
  // the actual spelling. This would allow us to distinguish between the
  // various attribute syntaxes, but we don't currently track that information
  // within the AST.
  //JOS.attribute("spelling", A->getSpelling());

  InnerAttrVisitor::Visit(A);
}

void JSONNodeDumper::Visit(const Stmt *S) {
  if (!S)
    return;

  JOS.attribute("id", createPointerRepresentation(S));
  JOS.attribute("kind", S->getStmtClassName());
  JOS.attributeObject("range",
                      [S, this] { writeSourceRange(S->getSourceRange()); });

  if (const auto *E = dyn_cast<Expr>(S)) {
    JOS.attribute("type", createQualType(E->getType()));
    const char *Category = nullptr;
    switch (E->getValueKind()) {
    case VK_LValue: Category = "lvalue"; break;
    case VK_XValue: Category = "xvalue"; break;
    case VK_PRValue:
      Category = "prvalue";
      break;
    }
    JOS.attribute("valueCategory", Category);
  }
  InnerStmtVisitor::Visit(S);
}

void JSONNodeDumper::Visit(const Type *T) {
  JOS.attribute("id", createPointerRepresentation(T));

  if (!T)
    return;

  JOS.attribute("kind", (llvm::Twine(T->getTypeClassName()) + "Type").str());
  JOS.attribute("type", createQualType(QualType(T, 0), /*Desugar=*/false));
  attributeOnlyIfTrue("containsErrors", T->containsErrors());
  attributeOnlyIfTrue("isDependent", T->isDependentType());
  attributeOnlyIfTrue("isInstantiationDependent",
                      T->isInstantiationDependentType());
  attributeOnlyIfTrue("isVariablyModified", T->isVariablyModifiedType());
  attributeOnlyIfTrue("containsUnexpandedPack",
                      T->containsUnexpandedParameterPack());
  attributeOnlyIfTrue("isImported", T->isFromAST());
  InnerTypeVisitor::Visit(T);
}

void JSONNodeDumper::Visit(QualType T) {
  JOS.attribute("id", createPointerRepresentation(T.getAsOpaquePtr()));
  JOS.attribute("kind", "QualType");
  JOS.attribute("type", createQualType(T));
  JOS.attribute("qualifiers", T.split().Quals.getAsString());
}

void JSONNodeDumper::Visit(TypeLoc TL) {
  if (TL.isNull())
    return;
  JOS.attribute("kind",
                (llvm::Twine(TL.getTypeLocClass() == TypeLoc::Qualified
                                 ? "Qualified"
                                 : TL.getTypePtr()->getTypeClassName()) +
                 "TypeLoc")
                    .str());
  JOS.attribute("type",
                createQualType(QualType(TL.getType()), /*Desugar=*/false));
  JOS.attributeObject("range",
                      [TL, this] { writeSourceRange(TL.getSourceRange()); });
}

void JSONNodeDumper::Visit(const Decl *D) {
  JOS.attribute("id", createPointerRepresentation(D));

  if (!D)
    return;

  JOS.attribute("kind", (llvm::Twine(D->getDeclKindName()) + "Decl").str());
  JOS.attributeObject("loc",
                      [D, this] { writeSourceLocation(D->getLocation()); });
  JOS.attributeObject("range",
                      [D, this] { writeSourceRange(D->getSourceRange()); });
  attributeOnlyIfTrue("isImplicit", D->isImplicit());
  attributeOnlyIfTrue("isInvalid", D->isInvalidDecl());

  if (D->isUsed())
    JOS.attribute("isUsed", true);
  else if (D->isThisDeclarationReferenced())
    JOS.attribute("isReferenced", true);

  if (const auto *ND = dyn_cast<NamedDecl>(D))
    attributeOnlyIfTrue("isHidden", !ND->isUnconditionallyVisible());

  if (D->getLexicalDeclContext() != D->getDeclContext()) {
    // Because of multiple inheritance, a DeclContext pointer does not produce
    // the same pointer representation as a Decl pointer that references the
    // same AST Node.
    const auto *ParentDeclContextDecl = dyn_cast<Decl>(D->getDeclContext());
    JOS.attribute("parentDeclContextId",
                  createPointerRepresentation(ParentDeclContextDecl));
  }

  addPreviousDeclaration(D);
  InnerDeclVisitor::Visit(D);
}

void JSONNodeDumper::Visit(const comments::Comment *C,
                           const comments::FullComment *FC) {
  if (!C)
    return;

  JOS.attribute("id", createPointerRepresentation(C));
  JOS.attribute("kind", C->getCommentKindName());
  JOS.attributeObject("loc",
                      [C, this] { writeSourceLocation(C->getLocation()); });
  JOS.attributeObject("range",
                      [C, this] { writeSourceRange(C->getSourceRange()); });

  InnerCommentVisitor::visit(C, FC);
}

void JSONNodeDumper::Visit(const TemplateArgument &TA, SourceRange R,
                           const Decl *From, StringRef Label) {
  JOS.attribute("kind", "TemplateArgument");
  if (R.isValid())
    JOS.attributeObject("range", [R, this] { writeSourceRange(R); });

  if (From)
    JOS.attribute(Label.empty() ? "fromDecl" : Label, createBareDeclRef(From));

  InnerTemplateArgVisitor::Visit(TA);
}

void JSONNodeDumper::Visit(const CXXCtorInitializer *Init) {
  JOS.attribute("kind", "CXXCtorInitializer");
  if (Init->isAnyMemberInitializer())
    JOS.attribute("anyInit", createBareDeclRef(Init->getAnyMember()));
  else if (Init->isBaseInitializer())
    JOS.attribute("baseInit",
                  createQualType(QualType(Init->getBaseClass(), 0)));
  else if (Init->isDelegatingInitializer())
    JOS.attribute("delegatingInit",
                  createQualType(Init->getTypeSourceInfo()->getType()));
  else
    llvm_unreachable("Unknown initializer type");
}

void JSONNodeDumper::Visit(const OpenACCClause *C) {}

void JSONNodeDumper::Visit(const OMPClause *C) {}

void JSONNodeDumper::Visit(const BlockDecl::Capture &C) {
  JOS.attribute("kind", "Capture");
  attributeOnlyIfTrue("byref", C.isByRef());
  attributeOnlyIfTrue("nested", C.isNested());
  if (C.getVariable())
    JOS.attribute("var", createBareDeclRef(C.getVariable()));
}

void JSONNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) {
  JOS.attribute("associationKind", A.getTypeSourceInfo() ? "case" : "default");
  attributeOnlyIfTrue("selected", A.isSelected());
}

void JSONNodeDumper::Visit(const concepts::Requirement *R) {
  if (!R)
    return;

  switch (R->getKind()) {
  case concepts::Requirement::RK_Type:
    JOS.attribute("kind", "TypeRequirement");
    break;
  case concepts::Requirement::RK_Simple:
    JOS.attribute("kind", "SimpleRequirement");
    break;
  case concepts::Requirement::RK_Compound:
    JOS.attribute("kind", "CompoundRequirement");
    break;
  case concepts::Requirement::RK_Nested:
    JOS.attribute("kind", "NestedRequirement");
    break;
  }

  if (auto *ER = dyn_cast<concepts::ExprRequirement>(R))
    attributeOnlyIfTrue("noexcept", ER->hasNoexceptRequirement());

  attributeOnlyIfTrue("isDependent", R->isDependent());
  if (!R->isDependent())
    JOS.attribute("satisfied", R->isSatisfied());
  attributeOnlyIfTrue("containsUnexpandedPack",
                      R->containsUnexpandedParameterPack());
}

void JSONNodeDumper::Visit(const APValue &Value, QualType Ty) {
  std::string Str;
  llvm::raw_string_ostream OS(Str);
  Value.printPretty(OS, Ctx, Ty);
  JOS.attribute("value", Str);
}

void JSONNodeDumper::Visit(const ConceptReference *CR) {
  JOS.attribute("kind", "ConceptReference");
  JOS.attribute("id", createPointerRepresentation(CR->getNamedConcept()));
  if (const auto *Args = CR->getTemplateArgsAsWritten()) {
    JOS.attributeArray("templateArgsAsWritten", [Args, this] {
      for (const TemplateArgumentLoc &TAL : Args->arguments())
        JOS.object(
            [&TAL, this] { Visit(TAL.getArgument(), TAL.getSourceRange()); });
    });
  }
  JOS.attributeObject("loc",
                      [CR, this] { writeSourceLocation(CR->getLocation()); });
  JOS.attributeObject("range",
                      [CR, this] { writeSourceRange(CR->getSourceRange()); });
}

void JSONNodeDumper::writeIncludeStack(PresumedLoc Loc, bool JustFirst) {
  if (Loc.isInvalid())
    return;

  JOS.attributeBegin("includedFrom");
  JOS.objectBegin();

  if (!JustFirst) {
    // Walk the stack recursively, then print out the presumed location.
    writeIncludeStack(SM.getPresumedLoc(Loc.getIncludeLoc()));
  }

  JOS.attribute("file", Loc.getFilename());
  JOS.objectEnd();
  JOS.attributeEnd();
}

void JSONNodeDumper::writeBareSourceLocation(SourceLocation Loc) {
  PresumedLoc Presumed = SM.getPresumedLoc(Loc);
  if (Presumed.isValid()) {
    StringRef ActualFile = SM.getBufferName(Loc);
    auto [FID, FilePos] = SM.getDecomposedLoc(Loc);
    unsigned ActualLine = SM.getLineNumber(FID, FilePos);
    JOS.attribute("offset", FilePos);
    if (LastLocFilename != ActualFile) {
      JOS.attribute("file", ActualFile);
      JOS.attribute("line", ActualLine);
    } else if (LastLocLine != ActualLine)
      JOS.attribute("line", ActualLine);

    StringRef PresumedFile = Presumed.getFilename();
    if (PresumedFile != ActualFile && LastLocPresumedFilename != PresumedFile)
      JOS.attribute("presumedFile", PresumedFile);

    unsigned PresumedLine = Presumed.getLine();
    if (ActualLine != PresumedLine && LastLocPresumedLine != PresumedLine)
      JOS.attribute("presumedLine", PresumedLine);

    JOS.attribute("col", Presumed.getColumn());
    JOS.attribute("tokLen",
                  Lexer::MeasureTokenLength(Loc, SM, Ctx.getLangOpts()));
    LastLocFilename = ActualFile;
    LastLocPresumedFilename = PresumedFile;
    LastLocPresumedLine = PresumedLine;
    LastLocLine = ActualLine;

    // Orthogonal to the file, line, and column de-duplication is whether the
    // given location was a result of an include. If so, print where the
    // include location came from.
    writeIncludeStack(SM.getPresumedLoc(Presumed.getIncludeLoc()),
                      /*JustFirst*/ true);
  }
}

void JSONNodeDumper::writeSourceLocation(SourceLocation Loc) {
  SourceLocation Spelling = SM.getSpellingLoc(Loc);
  SourceLocation Expansion = SM.getExpansionLoc(Loc);

  if (Expansion != Spelling) {
    // If the expansion and the spelling are different, output subobjects
    // describing both locations.
    JOS.attributeObject(
        "spellingLoc", [Spelling, this] { writeBareSourceLocation(Spelling); });
    JOS.attributeObject("expansionLoc", [Expansion, Loc, this] {
      writeBareSourceLocation(Expansion);
      // If there is a macro expansion, add extra information if the interesting
      // bit is the macro arg expansion.
      if (SM.isMacroArgExpansion(Loc))
        JOS.attribute("isMacroArgExpansion", true);
    });
  } else
    writeBareSourceLocation(Spelling);
}

void JSONNodeDumper::writeSourceRange(SourceRange R) {
  JOS.attributeObject("begin",
                      [R, this] { writeSourceLocation(R.getBegin()); });
  JOS.attributeObject("end", [R, this] { writeSourceLocation(R.getEnd()); });
}

std::string JSONNodeDumper::createPointerRepresentation(const void *Ptr) {
  // Because JSON stores integer values as signed 64-bit integers, trying to
  // represent them as such makes for very ugly pointer values in the resulting
  // output. Instead, we convert the value to hex and treat it as a string.
  return "0x" + llvm::utohexstr(reinterpret_cast<uint64_t>(Ptr), true);
}

llvm::json::Object JSONNodeDumper::createQualType(QualType QT, bool Desugar) {
  SplitQualType SQT = QT.split();
  std::string SQTS = QualType::getAsString(SQT, PrintPolicy);
  llvm::json::Object Ret{{"qualType", SQTS}};

  if (Desugar && !QT.isNull()) {
    SplitQualType DSQT = QT.getSplitDesugaredType();
    if (DSQT != SQT) {
      std::string DSQTS = QualType::getAsString(DSQT, PrintPolicy);
      if (DSQTS != SQTS)
        Ret["desugaredQualType"] = DSQTS;
    }
    if (const auto *TT = QT->getAs<TypedefType>())
      Ret["typeAliasDeclId"] = createPointerRepresentation(TT->getDecl());
  }
  return Ret;
}

void JSONNodeDumper::writeBareDeclRef(const Decl *D) {
  JOS.attribute("id", createPointerRepresentation(D));
  if (!D)
    return;

  JOS.attribute("kind", (llvm::Twine(D->getDeclKindName()) + "Decl").str());
  if (const auto *ND = dyn_cast<NamedDecl>(D))
    JOS.attribute("name", ND->getDeclName().getAsString());
  if (const auto *VD = dyn_cast<ValueDecl>(D))
    JOS.attribute("type", createQualType(VD->getType()));
}

llvm::json::Object JSONNodeDumper::createBareDeclRef(const Decl *D) {
  llvm::json::Object Ret{{"id", createPointerRepresentation(D)}};
  if (!D)
    return Ret;

  Ret["kind"] = (llvm::Twine(D->getDeclKindName()) + "Decl").str();
  if (const auto *ND = dyn_cast<NamedDecl>(D))
    Ret["name"] = ND->getDeclName().getAsString();
  if (const auto *VD = dyn_cast<ValueDecl>(D))
    Ret["type"] = createQualType(VD->getType());
  return Ret;
}

llvm::json::Array JSONNodeDumper::createCastPath(const CastExpr *C) {
  llvm::json::Array Ret;
  if (C->path_empty())
    return Ret;

  for (auto I = C->path_begin(), E = C->path_end(); I != E; ++I) {
    const CXXBaseSpecifier *Base = *I;
    const auto *RD = cast<CXXRecordDecl>(
        Base->getType()->castAsCanonical<RecordType>()->getDecl());

    llvm::json::Object Val{{"name", RD->getName()}};
    if (Base->isVirtual())
      Val["isVirtual"] = true;
    Ret.push_back(std::move(Val));
  }
  return Ret;
}

#define FIELD2(Name, Flag)  if (RD->Flag()) Ret[Name] = true
#define FIELD1(Flag)        FIELD2(#Flag, Flag)

static llvm::json::Object
createDefaultConstructorDefinitionData(const CXXRecordDecl *RD) {
  llvm::json::Object Ret;

  FIELD2("exists", hasDefaultConstructor);
  FIELD2("trivial", hasTrivialDefaultConstructor);
  FIELD2("nonTrivial", hasNonTrivialDefaultConstructor);
  FIELD2("userProvided", hasUserProvidedDefaultConstructor);
  FIELD2("isConstexpr", hasConstexprDefaultConstructor);
  FIELD2("needsImplicit", needsImplicitDefaultConstructor);
  FIELD2("defaultedIsConstexpr", defaultedDefaultConstructorIsConstexpr);

  return Ret;
}

static llvm::json::Object
createCopyConstructorDefinitionData(const CXXRecordDecl *RD) {
  llvm::json::Object Ret;

  FIELD2("simple", hasSimpleCopyConstructor);
  FIELD2("trivial", hasTrivialCopyConstructor);
  FIELD2("nonTrivial", hasNonTrivialCopyConstructor);
  FIELD2("userDeclared", hasUserDeclaredCopyConstructor);
  FIELD2("hasConstParam", hasCopyConstructorWithConstParam);
  FIELD2("implicitHasConstParam", implicitCopyConstructorHasConstParam);
  FIELD2("needsImplicit", needsImplicitCopyConstructor);
  FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyConstructor);
  if (!RD->needsOverloadResolutionForCopyConstructor())
    FIELD2("defaultedIsDeleted", defaultedCopyConstructorIsDeleted);

  return Ret;
}

static llvm::json::Object
createMoveConstructorDefinitionData(const CXXRecordDecl *RD) {
  llvm::json::Object Ret;

  FIELD2("exists", hasMoveConstructor);
  FIELD2("simple", hasSimpleMoveConstructor);
  FIELD2("trivial", hasTrivialMoveConstructor);
  FIELD2("nonTrivial", hasNonTrivialMoveConstructor);
  FIELD2("userDeclared", hasUserDeclaredMoveConstructor);
  FIELD2("needsImplicit", needsImplicitMoveConstructor);
  FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveConstructor);
  if (!RD->needsOverloadResolutionForMoveConstructor())
    FIELD2("defaultedIsDeleted", defaultedMoveConstructorIsDeleted);

  return Ret;
}

static llvm::json::Object
createCopyAssignmentDefinitionData(const CXXRecordDecl *RD) {
  llvm::json::Object Ret;

  FIELD2("simple", hasSimpleCopyAssignment);
  FIELD2("trivial", hasTrivialCopyAssignment);
  FIELD2("nonTrivial", hasNonTrivialCopyAssignment);
  FIELD2("hasConstParam", hasCopyAssignmentWithConstParam);
  FIELD2("implicitHasConstParam", implicitCopyAssignmentHasConstParam);
  FIELD2("userDeclared", hasUserDeclaredCopyAssignment);
  FIELD2("needsImplicit", needsImplicitCopyAssignment);
  FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyAssignment);

  return Ret;
}

static llvm::json::Object
createMoveAssignmentDefinitionData(const CXXRecordDecl *RD) {
  llvm::json::Object Ret;

  FIELD2("exists", hasMoveAssignment);
  FIELD2("simple", hasSimpleMoveAssignment);
  FIELD2("trivial", hasTrivialMoveAssignment);
  FIELD2("nonTrivial", hasNonTrivialMoveAssignment);
  FIELD2("userDeclared", hasUserDeclaredMoveAssignment);
  FIELD2("needsImplicit", needsImplicitMoveAssignment);
  FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveAssignment);

  return Ret;
}

static llvm::json::Object
createDestructorDefinitionData(const CXXRecordDecl *RD) {
  llvm::json::Object Ret;

  FIELD2("simple", hasSimpleDestructor);
  FIELD2("irrelevant", hasIrrelevantDestructor);
  FIELD2("trivial", hasTrivialDestructor);
  FIELD2("nonTrivial", hasNonTrivialDestructor);
  FIELD2("userDeclared", hasUserDeclaredDestructor);
  FIELD2("needsImplicit", needsImplicitDestructor);
  FIELD2("needsOverloadResolution", needsOverloadResolutionForDestructor);
  if (!RD->needsOverloadResolutionForDestructor())
    FIELD2("defaultedIsDeleted", defaultedDestructorIsDeleted);

  return Ret;
}

llvm::json::Object
JSONNodeDumper::createCXXRecordDefinitionData(const CXXRecordDecl *RD) {
  llvm::json::Object Ret;

  // This data is common to all C++ classes.
  FIELD1(isGenericLambda);
  FIELD1(isLambda);
  FIELD1(isEmpty);
  FIELD1(isAggregate);
  FIELD1(isStandardLayout);
  FIELD1(isTriviallyCopyable);
  FIELD1(isPOD);
  FIELD1(isTrivial);
  FIELD1(isPolymorphic);
  FIELD1(isAbstract);
  FIELD1(isLiteral);
  FIELD1(canPassInRegisters);
  FIELD1(hasUserDeclaredConstructor);
  FIELD1(hasConstexprNonCopyMoveConstructor);
  FIELD1(hasMutableFields);
  FIELD1(hasVariantMembers);
  FIELD2("canConstDefaultInit", allowConstDefaultInit);

  Ret["defaultCtor"] = createDefaultConstructorDefinitionData(RD);
  Ret["copyCtor"] = createCopyConstructorDefinitionData(RD);
  Ret["moveCtor"] = createMoveConstructorDefinitionData(RD);
  Ret["copyAssign"] = createCopyAssignmentDefinitionData(RD);
  Ret["moveAssign"] = createMoveAssignmentDefinitionData(RD);
  Ret["dtor"] = createDestructorDefinitionData(RD);

  return Ret;
}

#undef FIELD1
#undef FIELD2

std::string JSONNodeDumper::createAccessSpecifier(AccessSpecifier AS) {
  const auto AccessSpelling = getAccessSpelling(AS);
  if (AccessSpelling.empty())
    return "none";
  return AccessSpelling.str();
}

llvm::json::Object
JSONNodeDumper::createCXXBaseSpecifier(const CXXBaseSpecifier &BS) {
  llvm::json::Object Ret;

  Ret["type"] = createQualType(BS.getType());
  Ret["access"] = createAccessSpecifier(BS.getAccessSpecifier());
  Ret["writtenAccess"] =
      createAccessSpecifier(BS.getAccessSpecifierAsWritten());
  if (BS.isVirtual())
    Ret["isVirtual"] = true;
  if (BS.isPackExpansion())
    Ret["isPackExpansion"] = true;

  return Ret;
}

void JSONNodeDumper::VisitAliasAttr(const AliasAttr *AA) {
  JOS.attribute("aliasee", AA->getAliasee());
}

void JSONNodeDumper::VisitCleanupAttr(const CleanupAttr *CA) {
  JOS.attribute("cleanup_function", createBareDeclRef(CA->getFunctionDecl()));
}

void JSONNodeDumper::VisitDeprecatedAttr(const DeprecatedAttr *DA) {
  if (!DA->getMessage().empty())
    JOS.attribute("message", DA->getMessage());
  if (!DA->getReplacement().empty())
    JOS.attribute("replacement", DA->getReplacement());
}

void JSONNodeDumper::VisitUnavailableAttr(const UnavailableAttr *UA) {
  if (!UA->getMessage().empty())
    JOS.attribute("message", UA->getMessage());
}

void JSONNodeDumper::VisitSectionAttr(const SectionAttr *SA) {
  JOS.attribute("section_name", SA->getName());
}

void JSONNodeDumper::VisitVisibilityAttr(const VisibilityAttr *VA) {
  JOS.attribute("visibility", VisibilityAttr::ConvertVisibilityTypeToStr(
                                  VA->getVisibility()));
}

void JSONNodeDumper::VisitTLSModelAttr(const TLSModelAttr *TA) {
  JOS.attribute("tls_model", TA->getModel());
}

void JSONNodeDumper::VisitTypedefType(const TypedefType *TT) {
  JOS.attribute("decl", createBareDeclRef(TT->getDecl()));
  if (!TT->typeMatchesDecl())
    JOS.attribute("type", createQualType(TT->desugar()));
}

void JSONNodeDumper::VisitUsingType(const UsingType *TT) {
  JOS.attribute("decl", createBareDeclRef(TT->getDecl()));
  JOS.attribute("type", createQualType(TT->desugar()));
}

void JSONNodeDumper::VisitFunctionType(const FunctionType *T) {
  FunctionType::ExtInfo E = T->getExtInfo();
  attributeOnlyIfTrue("noreturn", E.getNoReturn());
  attributeOnlyIfTrue("producesResult", E.getProducesResult());
  if (E.getHasRegParm())
    JOS.attribute("regParm", E.getRegParm());
  JOS.attribute("cc", FunctionType::getNameForCallConv(E.getCC()));
}

void JSONNodeDumper::VisitFunctionProtoType(const FunctionProtoType *T) {
  FunctionProtoType::ExtProtoInfo E = T->getExtProtoInfo();
  attributeOnlyIfTrue("trailingReturn", E.HasTrailingReturn);
  attributeOnlyIfTrue("const", T->isConst());
  attributeOnlyIfTrue("volatile", T->isVolatile());
  attributeOnlyIfTrue("restrict", T->isRestrict());
  attributeOnlyIfTrue("variadic", E.Variadic);
  switch (E.RefQualifier) {
  case RQ_LValue: JOS.attribute("refQualifier", "&"); break;
  case RQ_RValue: JOS.attribute("refQualifier", "&&"); break;
  case RQ_None: break;
  }
  switch (E.ExceptionSpec.Type) {
  case EST_DynamicNone:
  case EST_Dynamic: {
    JOS.attribute("exceptionSpec", "throw");
    llvm::json::Array Types;
    for (QualType QT : E.ExceptionSpec.Exceptions)
      Types.push_back(createQualType(QT));
    JOS.attribute("exceptionTypes", std::move(Types));
  } break;
  case EST_MSAny:
    JOS.attribute("exceptionSpec", "throw");
    JOS.attribute("throwsAny", true);
    break;
  case EST_BasicNoexcept:
    JOS.attribute("exceptionSpec", "noexcept");
    break;
  case EST_NoexceptTrue:
  case EST_NoexceptFalse:
    JOS.attribute("exceptionSpec", "noexcept");
    JOS.attribute("conditionEvaluatesTo",
                E.ExceptionSpec.Type == EST_NoexceptTrue);
    //JOS.attributeWithCall("exceptionSpecExpr",
    //                    [this, E]() { Visit(E.ExceptionSpec.NoexceptExpr); });
    break;
  case EST_NoThrow:
    JOS.attribute("exceptionSpec", "nothrow");
    break;
  // FIXME: I cannot find a way to trigger these cases while dumping the AST. I
  // suspect you can only run into them when executing an AST dump from within
  // the debugger, which is not a use case we worry about for the JSON dumping
  // feature.
  case EST_DependentNoexcept:
  case EST_Unevaluated:
  case EST_Uninstantiated:
  case EST_Unparsed:
  case EST_None: break;
  }
  VisitFunctionType(T);
}

void JSONNodeDumper::VisitRValueReferenceType(const ReferenceType *RT) {
  attributeOnlyIfTrue("spelledAsLValue", RT->isSpelledAsLValue());
}

void JSONNodeDumper::VisitArrayType(const ArrayType *AT) {
  switch (AT->getSizeModifier()) {
  case ArraySizeModifier::Star:
    JOS.attribute("sizeModifier", "*");
    break;
  case ArraySizeModifier::Static:
    JOS.attribute("sizeModifier", "static");
    break;
  case ArraySizeModifier::Normal:
    break;
  }

  std::string Str = AT->getIndexTypeQualifiers().getAsString();
  if (!Str.empty())
    JOS.attribute("indexTypeQualifiers", Str);
}

void JSONNodeDumper::VisitConstantArrayType(const ConstantArrayType *CAT) {
  // FIXME: this should use ZExt instead of SExt, but JSON doesn't allow a
  // narrowing conversion to int64_t so it cannot be expressed.
  JOS.attribute("size", CAT->getSExtSize());
  VisitArrayType(CAT);
}

void JSONNodeDumper::VisitDependentSizedExtVectorType(
    const DependentSizedExtVectorType *VT) {
  JOS.attributeObject(
      "attrLoc", [VT, this] { writeSourceLocation(VT->getAttributeLoc()); });
}

void JSONNodeDumper::VisitVectorType(const VectorType *VT) {
  JOS.attribute("numElements", VT->getNumElements());
  switch (VT->getVectorKind()) {
  case VectorKind::Generic:
    break;
  case VectorKind::AltiVecVector:
    JOS.attribute("vectorKind", "altivec");
    break;
  case VectorKind::AltiVecPixel:
    JOS.attribute("vectorKind", "altivec pixel");
    break;
  case VectorKind::AltiVecBool:
    JOS.attribute("vectorKind", "altivec bool");
    break;
  case VectorKind::Neon:
    JOS.attribute("vectorKind", "neon");
    break;
  case VectorKind::NeonPoly:
    JOS.attribute("vectorKind", "neon poly");
    break;
  case VectorKind::SveFixedLengthData:
    JOS.attribute("vectorKind", "fixed-length sve data vector");
    break;
  case VectorKind::SveFixedLengthPredicate:
    JOS.attribute("vectorKind", "fixed-length sve predicate vector");
    break;
  case VectorKind::RVVFixedLengthData:
    JOS.attribute("vectorKind", "fixed-length rvv data vector");
    break;
  case VectorKind::RVVFixedLengthMask:
  case VectorKind::RVVFixedLengthMask_1:
  case VectorKind::RVVFixedLengthMask_2:
  case VectorKind::RVVFixedLengthMask_4:
    JOS.attribute("vectorKind", "fixed-length rvv mask vector");
    break;
  }
}

void JSONNodeDumper::VisitUnresolvedUsingType(const UnresolvedUsingType *UUT) {
  JOS.attribute("decl", createBareDeclRef(UUT->getDecl()));
}

void JSONNodeDumper::VisitUnaryTransformType(const UnaryTransformType *UTT) {
  switch (UTT->getUTTKind()) {
#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait)                                  \
  case UnaryTransformType::Enum:                                               \
    JOS.attribute("transformKind", #Trait);                                    \
    break;
#include "clang/Basic/TransformTypeTraits.def"
  }
}

void JSONNodeDumper::VisitTagType(const TagType *TT) {
  if (NestedNameSpecifier Qualifier = TT->getQualifier()) {
    std::string Str;
    llvm::raw_string_ostream OS(Str);
    Qualifier.print(OS, PrintPolicy, /*ResolveTemplateArguments=*/true);
    JOS.attribute("qualifier", Str);
  }
  JOS.attribute("decl", createBareDeclRef(TT->getDecl()));
  if (TT->isTagOwned())
    JOS.attribute("isTagOwned", true);
}

void JSONNodeDumper::VisitTemplateTypeParmType(
    const TemplateTypeParmType *TTPT) {
  JOS.attribute("depth", TTPT->getDepth());
  JOS.attribute("index", TTPT->getIndex());
  attributeOnlyIfTrue("isPack", TTPT->isParameterPack());
  JOS.attribute("decl", createBareDeclRef(TTPT->getDecl()));
}

void JSONNodeDumper::VisitSubstTemplateTypeParmType(
    const SubstTemplateTypeParmType *STTPT) {
  JOS.attribute("index", STTPT->getIndex());
  if (auto PackIndex = STTPT->getPackIndex())
    JOS.attribute("pack_index", *PackIndex);
}

void JSONNodeDumper::VisitSubstTemplateTypeParmPackType(
    const SubstTemplateTypeParmPackType *T) {
  JOS.attribute("index", T->getIndex());
}

void JSONNodeDumper::VisitAutoType(const AutoType *AT) {
  JOS.attribute("undeduced", !AT->isDeduced());
  switch (AT->getKeyword()) {
  case AutoTypeKeyword::Auto:
    JOS.attribute("typeKeyword", "auto");
    break;
  case AutoTypeKeyword::DecltypeAuto:
    JOS.attribute("typeKeyword", "decltype(auto)");
    break;
  case AutoTypeKeyword::GNUAutoType:
    JOS.attribute("typeKeyword", "__auto_type");
    break;
  }
}

void JSONNodeDumper::VisitTemplateSpecializationType(
    const TemplateSpecializationType *TST) {
  attributeOnlyIfTrue("isAlias", TST->isTypeAlias());

  std::string Str;
  llvm::raw_string_ostream OS(Str);
  TST->getTemplateName().print(OS, PrintPolicy);
  JOS.attribute("templateName", Str);
}

void JSONNodeDumper::VisitInjectedClassNameType(
    const InjectedClassNameType *ICNT) {
  JOS.attribute("decl", createBareDeclRef(ICNT->getDecl()));
}

void JSONNodeDumper::VisitObjCInterfaceType(const ObjCInterfaceType *OIT) {
  JOS.attribute("decl", createBareDeclRef(OIT->getDecl()));
}

void JSONNodeDumper::VisitPackExpansionType(const PackExpansionType *PET) {
  if (UnsignedOrNone N = PET->getNumExpansions())
    JOS.attribute("numExpansions", *N);
}

void JSONNodeDumper::VisitMacroQualifiedType(const MacroQualifiedType *MQT) {
  JOS.attribute("macroName", MQT->getMacroIdentifier()->getName());
}

void JSONNodeDumper::VisitMemberPointerType(const MemberPointerType *MPT) {
  attributeOnlyIfTrue("isData", MPT->isMemberDataPointer());
  attributeOnlyIfTrue("isFunction", MPT->isMemberFunctionPointer());
}

void JSONNodeDumper::VisitNamedDecl(const NamedDecl *ND) {
  if (ND && ND->getDeclName()) {
    JOS.attribute("name", ND->getNameAsString());
    // FIXME: There are likely other contexts in which it makes no sense to ask
    // for a mangled name.
    if (isa<RequiresExprBodyDecl>(ND->getDeclContext()))
      return;

    // If the declaration is dependent or is in a dependent context, then the
    // mangling is unlikely to be meaningful (and in some cases may cause
    // "don't know how to mangle this" assertion failures.
    if (ND->isTemplated())
      return;

    // Mangled names are not meaningful for locals, and may not be well-defined
    // in the case of VLAs.
    auto *VD = dyn_cast<VarDecl>(ND);
    if (VD && VD->hasLocalStorage())
      return;

    // Do not mangle template deduction guides.
    if (isa<CXXDeductionGuideDecl>(ND))
      return;

    std::string MangledName = ASTNameGen.getName(ND);
    if (!MangledName.empty())
      JOS.attribute("mangledName", MangledName);
  }
}

void JSONNodeDumper::VisitTypedefDecl(const TypedefDecl *TD) {
  VisitNamedDecl(TD);
  JOS.attribute("type", createQualType(TD->getUnderlyingType()));
}

void JSONNodeDumper::VisitTypeAliasDecl(const TypeAliasDecl *TAD) {
  VisitNamedDecl(TAD);
  JOS.attribute("type", createQualType(TAD->getUnderlyingType()));
}

void JSONNodeDumper::VisitNamespaceDecl(const NamespaceDecl *ND) {
  VisitNamedDecl(ND);
  attributeOnlyIfTrue("isInline", ND->isInline());
  attributeOnlyIfTrue("isNested", ND->isNested());
  if (!ND->isFirstDecl())
    JOS.attribute("originalNamespace", createBareDeclRef(ND->getFirstDecl()));
}

void JSONNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD) {
  JOS.attribute("nominatedNamespace",
                createBareDeclRef(UDD->getNominatedNamespace()));
}

void JSONNodeDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD) {
  VisitNamedDecl(NAD);
  JOS.attribute("aliasedNamespace",
                createBareDeclRef(NAD->getAliasedNamespace()));
}

void JSONNodeDumper::VisitUsingDecl(const UsingDecl *UD) {
  std::string Name;
  if (NestedNameSpecifier Qualifier = UD->getQualifier()) {
    llvm::raw_string_ostream SOS(Name);
    Qualifier.print(SOS, UD->getASTContext().getPrintingPolicy());
  }
  Name += UD->getNameAsString();
  JOS.attribute("name", Name);
}

void JSONNodeDumper::VisitUsingEnumDecl(const UsingEnumDecl *UED) {
  JOS.attribute("target", createBareDeclRef(UED->getEnumDecl()));
}

void JSONNodeDumper::VisitUsingShadowDecl(const UsingShadowDecl *USD) {
  JOS.attribute("target", createBareDeclRef(USD->getTargetDecl()));
}

void JSONNodeDumper::VisitVarDecl(const VarDecl *VD) {
  VisitNamedDecl(VD);
  JOS.attribute("type", createQualType(VD->getType()));
  if (const auto *P = dyn_cast<ParmVarDecl>(VD))
    attributeOnlyIfTrue("explicitObjectParameter",
                        P->isExplicitObjectParameter());

  StorageClass SC = VD->getStorageClass();
  if (SC != SC_None)
    JOS.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC));
  switch (VD->getTLSKind()) {
  case VarDecl::TLS_Dynamic: JOS.attribute("tls", "dynamic"); break;
  case VarDecl::TLS_Static: JOS.attribute("tls", "static"); break;
  case VarDecl::TLS_None: break;
  }
  attributeOnlyIfTrue("nrvo", VD->isNRVOVariable());
  attributeOnlyIfTrue("inline", VD->isInline());
  attributeOnlyIfTrue("constexpr", VD->isConstexpr());
  attributeOnlyIfTrue("modulePrivate", VD->isModulePrivate());
  if (VD->hasInit()) {
    switch (VD->getInitStyle()) {
    case VarDecl::CInit: JOS.attribute("init", "c");  break;
    case VarDecl::CallInit: JOS.attribute("init", "call"); break;
    case VarDecl::ListInit: JOS.attribute("init", "list"); break;
    case VarDecl::ParenListInit:
      JOS.attribute("init", "paren-list");
      break;
    }
  }
  attributeOnlyIfTrue("isParameterPack", VD->isParameterPack());
  if (const auto *Instance = VD->getTemplateInstantiationPattern())
    JOS.attribute("TemplateInstantiationPattern",
                  createPointerRepresentation(Instance));
}

void JSONNodeDumper::VisitFieldDecl(const FieldDecl *FD) {
  VisitNamedDecl(FD);
  JOS.attribute("type", createQualType(FD->getType()));
  attributeOnlyIfTrue("mutable", FD->isMutable());
  attributeOnlyIfTrue("modulePrivate", FD->isModulePrivate());
  attributeOnlyIfTrue("isBitfield", FD->isBitField());
  attributeOnlyIfTrue("hasInClassInitializer", FD->hasInClassInitializer());
}

void JSONNodeDumper::VisitFunctionDecl(const FunctionDecl *FD) {
  VisitNamedDecl(FD);
  JOS.attribute("type", createQualType(FD->getType()));
  StorageClass SC = FD->getStorageClass();
  if (SC != SC_None)
    JOS.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC));
  attributeOnlyIfTrue("inline", FD->isInlineSpecified());
  attributeOnlyIfTrue("virtual", FD->isVirtualAsWritten());
  attributeOnlyIfTrue("pure", FD->isPureVirtual());
  attributeOnlyIfTrue("explicitlyDeleted", FD->isDeletedAsWritten());
  attributeOnlyIfTrue("constexpr", FD->isConstexpr());
  attributeOnlyIfTrue("variadic", FD->isVariadic());
  attributeOnlyIfTrue("immediate", FD->isImmediateFunction());

  if (FD->isDefaulted())
    JOS.attribute("explicitlyDefaulted",
                  FD->isDeleted() ? "deleted" : "default");

  if (StringLiteral *Msg = FD->getDeletedMessage())
    JOS.attribute("deletedMessage", Msg->getString());

  if (const auto *Instance = FD->getTemplateInstantiationPattern())
    JOS.attribute("TemplateInstantiationPattern",
                  createPointerRepresentation(Instance));
}

void JSONNodeDumper::VisitEnumDecl(const EnumDecl *ED) {
  VisitNamedDecl(ED);
  if (ED->isFixed())
    JOS.attribute("fixedUnderlyingType", createQualType(ED->getIntegerType()));
  if (ED->isScoped())
    JOS.attribute("scopedEnumTag",
                  ED->isScopedUsingClassTag() ? "class" : "struct");
  if (const auto *Instance = ED->getTemplateInstantiationPattern())
    JOS.attribute("TemplateInstantiationPattern",
                  createPointerRepresentation(Instance));
}
void JSONNodeDumper::VisitEnumConstantDecl(const EnumConstantDecl *ECD) {
  VisitNamedDecl(ECD);
  JOS.attribute("type", createQualType(ECD->getType()));
}

void JSONNodeDumper::VisitRecordDecl(const RecordDecl *RD) {
  VisitNamedDecl(RD);
  JOS.attribute("tagUsed", RD->getKindName());
  attributeOnlyIfTrue("completeDefinition", RD->isCompleteDefinition());
}
void JSONNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *RD) {
  VisitRecordDecl(RD);

  if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
    if (CTSD->hasStrictPackMatch())
      JOS.attribute("strict-pack-match", true);
  }

  if (const auto *Instance = RD->getTemplateInstantiationPattern())
    JOS.attribute("TemplateInstantiationPattern",
                  createPointerRepresentation(Instance));

  // All other information requires a complete definition.
  if (!RD->isCompleteDefinition())
    return;

  JOS.attribute("definitionData", createCXXRecordDefinitionData(RD));
  if (RD->getNumBases()) {
    JOS.attributeArray("bases", [this, RD] {
      for (const auto &Spec : RD->bases())
        JOS.value(createCXXBaseSpecifier(Spec));
    });
  }
}

void JSONNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl *D) {
  VisitNamedDecl(D);
  JOS.attribute("bufferKind", D->isCBuffer() ? "cbuffer" : "tbuffer");
}

void JSONNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
  VisitNamedDecl(D);
  JOS.attribute("tagUsed", D->wasDeclaredWithTypename() ? "typename" : "class");
  JOS.attribute("depth", D->getDepth());
  JOS.attribute("index", D->getIndex());
  attributeOnlyIfTrue("isParameterPack", D->isParameterPack());

  if (D->hasDefaultArgument())
    JOS.attributeObject("defaultArg", [=] {
      Visit(D->getDefaultArgument().getArgument(), SourceRange(),
            D->getDefaultArgStorage().getInheritedFrom(),
            D->defaultArgumentWasInherited() ? "inherited from" : "previous");
    });
}

void JSONNodeDumper::VisitNonTypeTemplateParmDecl(
    const NonTypeTemplateParmDecl *D) {
  VisitNamedDecl(D);
  JOS.attribute("type", createQualType(D->getType()));
  JOS.attribute("depth", D->getDepth());
  JOS.attribute("index", D->getIndex());
  attributeOnlyIfTrue("isParameterPack", D->isParameterPack());

  if (D->hasDefaultArgument())
    JOS.attributeObject("defaultArg", [=] {
      Visit(D->getDefaultArgument().getArgument(), SourceRange(),
            D->getDefaultArgStorage().getInheritedFrom(),
            D->defaultArgumentWasInherited() ? "inherited from" : "previous");
    });
}

void JSONNodeDumper::VisitTemplateTemplateParmDecl(
    const TemplateTemplateParmDecl *D) {
  VisitNamedDecl(D);
  JOS.attribute("depth", D->getDepth());
  JOS.attribute("index", D->getIndex());
  attributeOnlyIfTrue("isParameterPack", D->isParameterPack());

  if (D->hasDefaultArgument())
    JOS.attributeObject("defaultArg", [=] {
      const auto *InheritedFrom = D->getDefaultArgStorage().getInheritedFrom();
      Visit(D->getDefaultArgument().getArgument(),
            InheritedFrom ? InheritedFrom->getSourceRange() : SourceLocation{},
            InheritedFrom,
            D->defaultArgumentWasInherited() ? "inherited from" : "previous");
    });
}

void JSONNodeDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *LSD) {
  StringRef Lang;
  switch (LSD->getLanguage()) {
  case LinkageSpecLanguageIDs::C:
    Lang = "C";
    break;
  case LinkageSpecLanguageIDs::CXX:
    Lang = "C++";
    break;
  }
  JOS.attribute("language", Lang);
  attributeOnlyIfTrue("hasBraces", LSD->hasBraces());
}

void JSONNodeDumper::VisitAccessSpecDecl(const AccessSpecDecl *ASD) {
  JOS.attribute("access", createAccessSpecifier(ASD->getAccess()));
}

void JSONNodeDumper::VisitFriendDecl(const FriendDecl *FD) {
  if (const TypeSourceInfo *T = FD->getFriendType())
    JOS.attribute("type", createQualType(T->getType()));
  attributeOnlyIfTrue("isPackExpansion", FD->isPackExpansion());
}

void JSONNodeDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) {
  VisitNamedDecl(D);
  JOS.attribute("type", createQualType(D->getType()));
  attributeOnlyIfTrue("synthesized", D->getSynthesize());
  switch (D->getAccessControl()) {
  case ObjCIvarDecl::None: JOS.attribute("access", "none"); break;
  case ObjCIvarDecl::Private: JOS.attribute("access", "private"); break;
  case ObjCIvarDecl::Protected: JOS.attribute("access", "protected"); break;
  case ObjCIvarDecl::Public: JOS.attribute("access", "public"); break;
  case ObjCIvarDecl::Package: JOS.attribute("access", "package"); break;
  }
}

void JSONNodeDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
  VisitNamedDecl(D);
  JOS.attribute("returnType", createQualType(D->getReturnType()));
  JOS.attribute("instance", D->isInstanceMethod());
  attributeOnlyIfTrue("variadic", D->isVariadic());
}

void JSONNodeDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) {
  VisitNamedDecl(D);
  JOS.attribute("type", createQualType(D->getUnderlyingType()));
  attributeOnlyIfTrue("bounded", D->hasExplicitBound());
  switch (D->getVariance()) {
  case ObjCTypeParamVariance::Invariant:
    break;
  case ObjCTypeParamVariance::Covariant:
    JOS.attribute("variance", "covariant");
    break;
  case ObjCTypeParamVariance::Contravariant:
    JOS.attribute("variance", "contravariant");
    break;
  }
}

void JSONNodeDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
  VisitNamedDecl(D);
  JOS.attribute("interface", createBareDeclRef(D->getClassInterface()));
  JOS.attribute("implementation", createBareDeclRef(D->getImplementation()));

  llvm::json::Array Protocols;
  for (const auto* P : D->protocols())
    Protocols.push_back(createBareDeclRef(P));
  if (!Protocols.empty())
    JOS.attribute("protocols", std::move(Protocols));
}

void JSONNodeDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
  VisitNamedDecl(D);
  JOS.attribute("interface", createBareDeclRef(D->getClassInterface()));
  JOS.attribute("categoryDecl", createBareDeclRef(D->getCategoryDecl()));
}

void JSONNodeDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
  VisitNamedDecl(D);

  llvm::json::Array Protocols;
  for (const auto *P : D->protocols())
    Protocols.push_back(createBareDeclRef(P));
  if (!Protocols.empty())
    JOS.attribute("protocols", std::move(Protocols));
}

void JSONNodeDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
  VisitNamedDecl(D);
  JOS.attribute("super", createBareDeclRef(D->getSuperClass()));
  JOS.attribute("implementation", createBareDeclRef(D->getImplementation()));

  llvm::json::Array Protocols;
  for (const auto* P : D->protocols())
    Protocols.push_back(createBareDeclRef(P));
  if (!Protocols.empty())
    JOS.attribute("protocols", std::move(Protocols));
}

void JSONNodeDumper::VisitObjCImplementationDecl(
    const ObjCImplementationDecl *D) {
  VisitNamedDecl(D);
  JOS.attribute("super", createBareDeclRef(D->getSuperClass()));
  JOS.attribute("interface", createBareDeclRef(D->getClassInterface()));
}

void JSONNodeDumper::VisitObjCCompatibleAliasDecl(
    const ObjCCompatibleAliasDecl *D) {
  VisitNamedDecl(D);
  JOS.attribute("interface", createBareDeclRef(D->getClassInterface()));
}

void JSONNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
  VisitNamedDecl(D);
  JOS.attribute("type", createQualType(D->getType()));

  switch (D->getPropertyImplementation()) {
  case ObjCPropertyDecl::None: break;
  case ObjCPropertyDecl::Required: JOS.attribute("control", "required"); break;
  case ObjCPropertyDecl::Optional: JOS.attribute("control", "optional"); break;
  }

  ObjCPropertyAttribute::Kind Attrs = D->getPropertyAttributes();
  if (Attrs != ObjCPropertyAttribute::kind_noattr) {
    if (Attrs & ObjCPropertyAttribute::kind_getter)
      JOS.attribute("getter", createBareDeclRef(D->getGetterMethodDecl()));
    if (Attrs & ObjCPropertyAttribute::kind_setter)
      JOS.attribute("setter", createBareDeclRef(D->getSetterMethodDecl()));
    attributeOnlyIfTrue("readonly",
                        Attrs & ObjCPropertyAttribute::kind_readonly);
    attributeOnlyIfTrue("assign", Attrs & ObjCPropertyAttribute::kind_assign);
    attributeOnlyIfTrue("readwrite",
                        Attrs & ObjCPropertyAttribute::kind_readwrite);
    attributeOnlyIfTrue("retain", Attrs & ObjCPropertyAttribute::kind_retain);
    attributeOnlyIfTrue("copy", Attrs & ObjCPropertyAttribute::kind_copy);
    attributeOnlyIfTrue("nonatomic",
                        Attrs & ObjCPropertyAttribute::kind_nonatomic);
    attributeOnlyIfTrue("atomic", Attrs & ObjCPropertyAttribute::kind_atomic);
    attributeOnlyIfTrue("weak", Attrs & ObjCPropertyAttribute::kind_weak);
    attributeOnlyIfTrue("strong", Attrs & ObjCPropertyAttribute::kind_strong);
    attributeOnlyIfTrue("unsafe_unretained",
                        Attrs & ObjCPropertyAttribute::kind_unsafe_unretained);
    attributeOnlyIfTrue("class", Attrs & ObjCPropertyAttribute::kind_class);
    attributeOnlyIfTrue("direct", Attrs & ObjCPropertyAttribute::kind_direct);
    attributeOnlyIfTrue("nullability",
                        Attrs & ObjCPropertyAttribute::kind_nullability);
    attributeOnlyIfTrue("null_resettable",
                        Attrs & ObjCPropertyAttribute::kind_null_resettable);
  }
}

void JSONNodeDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
  VisitNamedDecl(D->getPropertyDecl());
  JOS.attribute("implKind", D->getPropertyImplementation() ==
                                    ObjCPropertyImplDecl::Synthesize
                                ? "synthesize"
                                : "dynamic");
  JOS.attribute("propertyDecl", createBareDeclRef(D->getPropertyDecl()));
  JOS.attribute("ivarDecl", createBareDeclRef(D->getPropertyIvarDecl()));
}

void JSONNodeDumper::VisitBlockDecl(const BlockDecl *D) {
  attributeOnlyIfTrue("variadic", D->isVariadic());
  attributeOnlyIfTrue("capturesThis", D->capturesCXXThis());
}

void JSONNodeDumper::VisitAtomicExpr(const AtomicExpr *AE) {
  JOS.attribute("name", AE->getOpAsString());
}

void JSONNodeDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *OEE) {
  JOS.attribute("encodedType", createQualType(OEE->getEncodedType()));
}

void JSONNodeDumper::VisitObjCMessageExpr(const ObjCMessageExpr *OME) {
  std::string Str;
  llvm::raw_string_ostream OS(Str);

  OME->getSelector().print(OS);
  JOS.attribute("selector", Str);

  switch (OME->getReceiverKind()) {
  case ObjCMessageExpr::Instance:
    JOS.attribute("receiverKind", "instance");
    break;
  case ObjCMessageExpr::Class:
    JOS.attribute("receiverKind", "class");
    JOS.attribute("classType", createQualType(OME->getClassReceiver()));
    break;
  case ObjCMessageExpr::SuperInstance:
    JOS.attribute("receiverKind", "super (instance)");
    JOS.attribute("superType", createQualType(OME->getSuperType()));
    break;
  case ObjCMessageExpr::SuperClass:
    JOS.attribute("receiverKind", "super (class)");
    JOS.attribute("superType", createQualType(OME->getSuperType()));
    break;
  }

  QualType CallReturnTy = OME->getCallReturnType(Ctx);
  if (OME->getType() != CallReturnTy)
    JOS.attribute("callReturnType", createQualType(CallReturnTy));
}

void JSONNodeDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *OBE) {
  if (const ObjCMethodDecl *MD = OBE->getBoxingMethod()) {
    std::string Str;
    llvm::raw_string_ostream OS(Str);

    MD->getSelector().print(OS);
    JOS.attribute("selector", Str);
  }
}

void JSONNodeDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *OSE) {
  std::string Str;
  llvm::raw_string_ostream OS(Str);

  OSE->getSelector().print(OS);
  JOS.attribute("selector", Str);
}

void JSONNodeDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *OPE) {
  JOS.attribute("protocol", createBareDeclRef(OPE->getProtocol()));
}

void JSONNodeDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *OPRE) {
  if (OPRE->isImplicitProperty()) {
    JOS.attribute("propertyKind", "implicit");
    if (const ObjCMethodDecl *MD = OPRE->getImplicitPropertyGetter())
      JOS.attribute("getter", createBareDeclRef(MD));
    if (const ObjCMethodDecl *MD = OPRE->getImplicitPropertySetter())
      JOS.attribute("setter", createBareDeclRef(MD));
  } else {
    JOS.attribute("propertyKind", "explicit");
    JOS.attribute("property", createBareDeclRef(OPRE->getExplicitProperty()));
  }

  attributeOnlyIfTrue("isSuperReceiver", OPRE->isSuperReceiver());
  attributeOnlyIfTrue("isMessagingGetter", OPRE->isMessagingGetter());
  attributeOnlyIfTrue("isMessagingSetter", OPRE->isMessagingSetter());
}

void JSONNodeDumper::VisitObjCSubscriptRefExpr(
    const ObjCSubscriptRefExpr *OSRE) {
  JOS.attribute("subscriptKind",
                OSRE->isArraySubscriptRefExpr() ? "array" : "dictionary");

  if (const ObjCMethodDecl *MD = OSRE->getAtIndexMethodDecl())
    JOS.attribute("getter", createBareDeclRef(MD));
  if (const ObjCMethodDecl *MD = OSRE->setAtIndexMethodDecl())
    JOS.attribute("setter", createBareDeclRef(MD));
}

void JSONNodeDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE) {
  JOS.attribute("decl", createBareDeclRef(OIRE->getDecl()));
  attributeOnlyIfTrue("isFreeIvar", OIRE->isFreeIvar());
  JOS.attribute("isArrow", OIRE->isArrow());
}

void JSONNodeDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *OBLE) {
  JOS.attribute("value", OBLE->getValue() ? "__objc_yes" : "__objc_no");
}

void JSONNodeDumper::VisitDeclRefExpr(const DeclRefExpr *DRE) {
  JOS.attribute("referencedDecl", createBareDeclRef(DRE->getDecl()));
  if (DRE->getDecl() != DRE->getFoundDecl())
    JOS.attribute("foundReferencedDecl",
                  createBareDeclRef(DRE->getFoundDecl()));
  switch (DRE->isNonOdrUse()) {
  case NOUR_None: break;
  case NOUR_Unevaluated: JOS.attribute("nonOdrUseReason", "unevaluated"); break;
  case NOUR_Constant: JOS.attribute("nonOdrUseReason", "constant"); break;
  case NOUR_Discarded: JOS.attribute("nonOdrUseReason", "discarded"); break;
  }
  attributeOnlyIfTrue("isImmediateEscalating", DRE->isImmediateEscalating());
}

void JSONNodeDumper::VisitSYCLUniqueStableNameExpr(
    const SYCLUniqueStableNameExpr *E) {
  JOS.attribute("typeSourceInfo",
                createQualType(E->getTypeSourceInfo()->getType()));
}

void JSONNodeDumper::VisitOpenACCAsteriskSizeExpr(
    const OpenACCAsteriskSizeExpr *E) {}

void JSONNodeDumper::VisitOpenACCDeclareDecl(const OpenACCDeclareDecl *D) {}
void JSONNodeDumper::VisitOpenACCRoutineDecl(const OpenACCRoutineDecl *D) {}

void JSONNodeDumper::VisitPredefinedExpr(const PredefinedExpr *PE) {
  JOS.attribute("name", PredefinedExpr::getIdentKindName(PE->getIdentKind()));
}

void JSONNodeDumper::VisitUnaryOperator(const UnaryOperator *UO) {
  JOS.attribute("isPostfix", UO->isPostfix());
  JOS.attribute("opcode", UnaryOperator::getOpcodeStr(UO->getOpcode()));
  if (!UO->canOverflow())
    JOS.attribute("canOverflow", false);
}

void JSONNodeDumper::VisitBinaryOperator(const BinaryOperator *BO) {
  JOS.attribute("opcode", BinaryOperator::getOpcodeStr(BO->getOpcode()));
}

void JSONNodeDumper::VisitCompoundAssignOperator(
    const CompoundAssignOperator *CAO) {
  VisitBinaryOperator(CAO);
  JOS.attribute("computeLHSType", createQualType(CAO->getComputationLHSType()));
  JOS.attribute("computeResultType",
                createQualType(CAO->getComputationResultType()));
}

void JSONNodeDumper::VisitMemberExpr(const MemberExpr *ME) {
  // Note, we always write this Boolean field because the information it conveys
  // is critical to understanding the AST node.
  ValueDecl *VD = ME->getMemberDecl();
  JOS.attribute("name", VD && VD->getDeclName() ? VD->getNameAsString() : "");
  JOS.attribute("isArrow", ME->isArrow());
  JOS.attribute("referencedMemberDecl", createPointerRepresentation(VD));
  switch (ME->isNonOdrUse()) {
  case NOUR_None: break;
  case NOUR_Unevaluated: JOS.attribute("nonOdrUseReason", "unevaluated"); break;
  case NOUR_Constant: JOS.attribute("nonOdrUseReason", "constant"); break;
  case NOUR_Discarded: JOS.attribute("nonOdrUseReason", "discarded"); break;
  }
}

void JSONNodeDumper::VisitCXXNewExpr(const CXXNewExpr *NE) {
  attributeOnlyIfTrue("isGlobal", NE->isGlobalNew());
  attributeOnlyIfTrue("isArray", NE->isArray());
  attributeOnlyIfTrue("isPlacement", NE->getNumPlacementArgs() != 0);
  switch (NE->getInitializationStyle()) {
  case CXXNewInitializationStyle::None:
    break;
  case CXXNewInitializationStyle::Parens:
    JOS.attribute("initStyle", "call");
    break;
  case CXXNewInitializationStyle::Braces:
    JOS.attribute("initStyle", "list");
    break;
  }
  if (const FunctionDecl *FD = NE->getOperatorNew())
    JOS.attribute("operatorNewDecl", createBareDeclRef(FD));
  if (const FunctionDecl *FD = NE->getOperatorDelete())
    JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD));
}
void JSONNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *DE) {
  attributeOnlyIfTrue("isGlobal", DE->isGlobalDelete());
  attributeOnlyIfTrue("isArray", DE->isArrayForm());
  attributeOnlyIfTrue("isArrayAsWritten", DE->isArrayFormAsWritten());
  if (const FunctionDecl *FD = DE->getOperatorDelete())
    JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD));
}

void JSONNodeDumper::VisitCXXThisExpr(const CXXThisExpr *TE) {
  attributeOnlyIfTrue("implicit", TE->isImplicit());
}

void JSONNodeDumper::VisitCastExpr(const CastExpr *CE) {
  JOS.attribute("castKind", CE->getCastKindName());
  llvm::json::Array Path = createCastPath(CE);
  if (!Path.empty())
    JOS.attribute("path", std::move(Path));
  // FIXME: This may not be useful information as it can be obtusely gleaned
  // from the inner[] array.
  if (const NamedDecl *ND = CE->getConversionFunction())
    JOS.attribute("conversionFunc", createBareDeclRef(ND));
}

void JSONNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *ICE) {
  VisitCastExpr(ICE);
  attributeOnlyIfTrue("isPartOfExplicitCast", ICE->isPartOfExplicitCast());
}

void JSONNodeDumper::VisitCallExpr(const CallExpr *CE) {
  attributeOnlyIfTrue("adl", CE->usesADL());
}

void JSONNodeDumper::VisitUnaryExprOrTypeTraitExpr(
    const UnaryExprOrTypeTraitExpr *TTE) {
  JOS.attribute("name", getTraitSpelling(TTE->getKind()));
  if (TTE->isArgumentType())
    JOS.attribute("argType", createQualType(TTE->getArgumentType()));
}

void JSONNodeDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *SOPE) {
  VisitNamedDecl(SOPE->getPack());
}

void JSONNodeDumper::VisitUnresolvedLookupExpr(
    const UnresolvedLookupExpr *ULE) {
  JOS.attribute("usesADL", ULE->requiresADL());
  JOS.attribute("name", ULE->getName().getAsString());

  JOS.attributeArray("lookups", [this, ULE] {
    for (const NamedDecl *D : ULE->decls())
      JOS.value(createBareDeclRef(D));
  });
}

void JSONNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *ALE) {
  JOS.attribute("name", ALE->getLabel()->getName());
  JOS.attribute("labelDeclId", createPointerRepresentation(ALE->getLabel()));
}

void JSONNodeDumper::VisitCXXTypeidExpr(const CXXTypeidExpr *CTE) {
  if (CTE->isTypeOperand()) {
    QualType Adjusted = CTE->getTypeOperand(Ctx);
    QualType Unadjusted = CTE->getTypeOperandSourceInfo()->getType();
    JOS.attribute("typeArg", createQualType(Unadjusted));
    if (Adjusted != Unadjusted)
      JOS.attribute("adjustedTypeArg", createQualType(Adjusted));
  }
}

void JSONNodeDumper::VisitConstantExpr(const ConstantExpr *CE) {
  if (CE->getResultAPValueKind() != APValue::None)
    Visit(CE->getAPValueResult(), CE->getType());
}

void JSONNodeDumper::VisitInitListExpr(const InitListExpr *ILE) {
  if (const FieldDecl *FD = ILE->getInitializedFieldInUnion())
    JOS.attribute("field", createBareDeclRef(FD));
}

void JSONNodeDumper::VisitGenericSelectionExpr(
    const GenericSelectionExpr *GSE) {
  attributeOnlyIfTrue("resultDependent", GSE->isResultDependent());
}

void JSONNodeDumper::VisitCXXUnresolvedConstructExpr(
    const CXXUnresolvedConstructExpr *UCE) {
  if (UCE->getType() != UCE->getTypeAsWritten())
    JOS.attribute("typeAsWritten", createQualType(UCE->getTypeAsWritten()));
  attributeOnlyIfTrue("list", UCE->isListInitialization());
}

void JSONNodeDumper::VisitCXXConstructExpr(const CXXConstructExpr *CE) {
  CXXConstructorDecl *Ctor = CE->getConstructor();
  JOS.attribute("ctorType", createQualType(Ctor->getType()));
  attributeOnlyIfTrue("elidable", CE->isElidable());
  attributeOnlyIfTrue("list", CE->isListInitialization());
  attributeOnlyIfTrue("initializer_list", CE->isStdInitListInitialization());
  attributeOnlyIfTrue("zeroing", CE->requiresZeroInitialization());
  attributeOnlyIfTrue("hadMultipleCandidates", CE->hadMultipleCandidates());
  attributeOnlyIfTrue("isImmediateEscalating", CE->isImmediateEscalating());

  switch (CE->getConstructionKind()) {
  case CXXConstructionKind::Complete:
    JOS.attribute("constructionKind", "complete");
    break;
  case CXXConstructionKind::Delegating:
    JOS.attribute("constructionKind", "delegating");
    break;
  case CXXConstructionKind::NonVirtualBase:
    JOS.attribute("constructionKind", "non-virtual base");
    break;
  case CXXConstructionKind::VirtualBase:
    JOS.attribute("constructionKind", "virtual base");
    break;
  }
}

void JSONNodeDumper::VisitExprWithCleanups(const ExprWithCleanups *EWC) {
  attributeOnlyIfTrue("cleanupsHaveSideEffects",
                      EWC->cleanupsHaveSideEffects());
  if (EWC->getNumObjects()) {
    JOS.attributeArray("cleanups", [this, EWC] {
      for (const ExprWithCleanups::CleanupObject &CO : EWC->getObjects())
        if (auto *BD = dyn_cast<BlockDecl *>(CO)) {
          JOS.value(createBareDeclRef(BD));
        } else if (auto *CLE = dyn_cast<CompoundLiteralExpr *>(CO)) {
          llvm::json::Object Obj;
          Obj["id"] = createPointerRepresentation(CLE);
          Obj["kind"] = CLE->getStmtClassName();
          JOS.value(std::move(Obj));
        } else {
          llvm_unreachable("unexpected cleanup object type");
        }
    });
  }
}

void JSONNodeDumper::VisitCXXBindTemporaryExpr(
    const CXXBindTemporaryExpr *BTE) {
  const CXXTemporary *Temp = BTE->getTemporary();
  JOS.attribute("temp", createPointerRepresentation(Temp));
  if (const CXXDestructorDecl *Dtor = Temp->getDestructor())
    JOS.attribute("dtor", createBareDeclRef(Dtor));
}

void JSONNodeDumper::VisitMaterializeTemporaryExpr(
    const MaterializeTemporaryExpr *MTE) {
  if (const ValueDecl *VD = MTE->getExtendingDecl())
    JOS.attribute("extendingDecl", createBareDeclRef(VD));

  switch (MTE->getStorageDuration()) {
  case SD_Automatic:
    JOS.attribute("storageDuration", "automatic");
    break;
  case SD_Dynamic:
    JOS.attribute("storageDuration", "dynamic");
    break;
  case SD_FullExpression:
    JOS.attribute("storageDuration", "full expression");
    break;
  case SD_Static:
    JOS.attribute("storageDuration", "static");
    break;
  case SD_Thread:
    JOS.attribute("storageDuration", "thread");
    break;
  }

  attributeOnlyIfTrue("boundToLValueRef", MTE->isBoundToLvalueReference());
}

void JSONNodeDumper::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) {
  attributeOnlyIfTrue("hasRewrittenInit", Node->hasRewrittenInit());
}

void JSONNodeDumper::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) {
  attributeOnlyIfTrue("hasRewrittenInit", Node->hasRewrittenInit());
}

void JSONNodeDumper::VisitCXXDependentScopeMemberExpr(
    const CXXDependentScopeMemberExpr *DSME) {
  JOS.attribute("isArrow", DSME->isArrow());
  JOS.attribute("member", DSME->getMember().getAsString());
  attributeOnlyIfTrue("hasTemplateKeyword", DSME->hasTemplateKeyword());
  attributeOnlyIfTrue("hasExplicitTemplateArgs",
                      DSME->hasExplicitTemplateArgs());

  if (DSME->getNumTemplateArgs()) {
    JOS.attributeArray("explicitTemplateArgs", [DSME, this] {
      for (const TemplateArgumentLoc &TAL : DSME->template_arguments())
        JOS.object(
            [&TAL, this] { Visit(TAL.getArgument(), TAL.getSourceRange()); });
    });
  }
}

void JSONNodeDumper::VisitRequiresExpr(const RequiresExpr *RE) {
  if (!RE->isValueDependent())
    JOS.attribute("satisfied", RE->isSatisfied());
}

void JSONNodeDumper::VisitIntegerLiteral(const IntegerLiteral *IL) {
  llvm::SmallString<16> Buffer;
  IL->getValue().toString(Buffer,
                          /*Radix=*/10, IL->getType()->isSignedIntegerType());
  JOS.attribute("value", Buffer);
}
void JSONNodeDumper::VisitCharacterLiteral(const CharacterLiteral *CL) {
  // FIXME: This should probably print the character literal as a string,
  // rather than as a numerical value. It would be nice if the behavior matched
  // what we do to print a string literal; right now, it is impossible to tell
  // the difference between 'a' and L'a' in C from the JSON output.
  JOS.attribute("value", CL->getValue());
}
void JSONNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *FPL) {
  JOS.attribute("value", FPL->getValueAsString(/*Radix=*/10));
}
void JSONNodeDumper::VisitFloatingLiteral(const FloatingLiteral *FL) {
  llvm::SmallString<16> Buffer;
  FL->getValue().toString(Buffer);
  JOS.attribute("value", Buffer);
}
void JSONNodeDumper::VisitStringLiteral(const StringLiteral *SL) {
  std::string Buffer;
  llvm::raw_string_ostream SS(Buffer);
  SL->outputString(SS);
  JOS.attribute("value", Buffer);
}
void JSONNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *BLE) {
  JOS.attribute("value", BLE->getValue());
}

void JSONNodeDumper::VisitIfStmt(const IfStmt *IS) {
  attributeOnlyIfTrue("hasInit", IS->hasInitStorage());
  attributeOnlyIfTrue("hasVar", IS->hasVarStorage());
  attributeOnlyIfTrue("hasElse", IS->hasElseStorage());
  attributeOnlyIfTrue("isConstexpr", IS->isConstexpr());
  attributeOnlyIfTrue("isConsteval", IS->isConsteval());
  attributeOnlyIfTrue("constevalIsNegated", IS->isNegatedConsteval());
}

void JSONNodeDumper::VisitSwitchStmt(const SwitchStmt *SS) {
  attributeOnlyIfTrue("hasInit", SS->hasInitStorage());
  attributeOnlyIfTrue("hasVar", SS->hasVarStorage());
}
void JSONNodeDumper::VisitCaseStmt(const CaseStmt *CS) {
  attributeOnlyIfTrue("isGNURange", CS->caseStmtIsGNURange());
}

void JSONNodeDumper::VisitLabelStmt(const LabelStmt *LS) {
  JOS.attribute("name", LS->getName());
  JOS.attribute("declId", createPointerRepresentation(LS->getDecl()));
  attributeOnlyIfTrue("sideEntry", LS->isSideEntry());
}

void JSONNodeDumper::VisitLoopControlStmt(const LoopControlStmt *LS) {
  if (LS->hasLabelTarget())
    JOS.attribute("targetLabelDeclId",
                  createPointerRepresentation(LS->getLabelDecl()));
}

void JSONNodeDumper::VisitGotoStmt(const GotoStmt *GS) {
  JOS.attribute("targetLabelDeclId",
                createPointerRepresentation(GS->getLabel()));
}

void JSONNodeDumper::VisitWhileStmt(const WhileStmt *WS) {
  attributeOnlyIfTrue("hasVar", WS->hasVarStorage());
}

void JSONNodeDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt* OACS) {
  // FIXME: it would be nice for the ASTNodeTraverser would handle the catch
  // parameter the same way for C++ and ObjC rather. In this case, C++ gets a
  // null child node and ObjC gets no child node.
  attributeOnlyIfTrue("isCatchAll", OACS->getCatchParamDecl() == nullptr);
}

void JSONNodeDumper::VisitNullTemplateArgument(const TemplateArgument &TA) {
  JOS.attribute("isNull", true);
}
void JSONNodeDumper::VisitTypeTemplateArgument(const TemplateArgument &TA) {
  JOS.attribute("type", createQualType(TA.getAsType()));
}
void JSONNodeDumper::VisitDeclarationTemplateArgument(
    const TemplateArgument &TA) {
  JOS.attribute("decl", createBareDeclRef(TA.getAsDecl()));
}
void JSONNodeDumper::VisitNullPtrTemplateArgument(const TemplateArgument &TA) {
  JOS.attribute("isNullptr", true);
}
void JSONNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) {
  JOS.attribute("value", TA.getAsIntegral().getSExtValue());
}
void JSONNodeDumper::VisitStructuralValueTemplateArgument(
    const TemplateArgument &TA) {
  Visit(TA.getAsStructuralValue(), TA.getStructuralValueType());
}
void JSONNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) {
  // FIXME: cannot just call dump() on the argument, as that doesn't specify
  // the output format.
}
void JSONNodeDumper::VisitTemplateExpansionTemplateArgument(
    const TemplateArgument &TA) {
  // FIXME: cannot just call dump() on the argument, as that doesn't specify
  // the output format.
}
void JSONNodeDumper::VisitExpressionTemplateArgument(
    const TemplateArgument &TA) {
  JOS.attribute("isExpr", true);
  if (TA.isCanonicalExpr())
    JOS.attribute("isCanonical", true);
}
void JSONNodeDumper::VisitPackTemplateArgument(const TemplateArgument &TA) {
  JOS.attribute("isPack", true);
}

StringRef JSONNodeDumper::getCommentCommandName(unsigned CommandID) const {
  if (Traits)
    return Traits->getCommandInfo(CommandID)->Name;
  if (const comments::CommandInfo *Info =
          comments::CommandTraits::getBuiltinCommandInfo(CommandID))
    return Info->Name;
  return "<invalid>";
}

void JSONNodeDumper::visitTextComment(const comments::TextComment *C,
                                      const comments::FullComment *) {
  JOS.attribute("text", C->getText());
}

void JSONNodeDumper::visitInlineCommandComment(
    const comments::InlineCommandComment *C, const comments::FullComment *) {
  JOS.attribute("name", getCommentCommandName(C->getCommandID()));

  switch (C->getRenderKind()) {
  case comments::InlineCommandRenderKind::Normal:
    JOS.attribute("renderKind", "normal");
    break;
  case comments::InlineCommandRenderKind::Bold:
    JOS.attribute("renderKind", "bold");
    break;
  case comments::InlineCommandRenderKind::Emphasized:
    JOS.attribute("renderKind", "emphasized");
    break;
  case comments::InlineCommandRenderKind::Monospaced:
    JOS.attribute("renderKind", "monospaced");
    break;
  case comments::InlineCommandRenderKind::Anchor:
    JOS.attribute("renderKind", "anchor");
    break;
  }

  llvm::json::Array Args;
  for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
    Args.push_back(C->getArgText(I));

  if (!Args.empty())
    JOS.attribute("args", std::move(Args));
}

void JSONNodeDumper::visitHTMLStartTagComment(
    const comments::HTMLStartTagComment *C, const comments::FullComment *) {
  JOS.attribute("name", C->getTagName());
  attributeOnlyIfTrue("selfClosing", C->isSelfClosing());
  attributeOnlyIfTrue("malformed", C->isMalformed());

  llvm::json::Array Attrs;
  for (unsigned I = 0, E = C->getNumAttrs(); I < E; ++I)
    Attrs.push_back(
        {{"name", C->getAttr(I).Name}, {"value", C->getAttr(I).Value}});

  if (!Attrs.empty())
    JOS.attribute("attrs", std::move(Attrs));
}

void JSONNodeDumper::visitHTMLEndTagComment(
    const comments::HTMLEndTagComment *C, const comments::FullComment *) {
  JOS.attribute("name", C->getTagName());
}

void JSONNodeDumper::visitBlockCommandComment(
    const comments::BlockCommandComment *C, const comments::FullComment *) {
  JOS.attribute("name", getCommentCommandName(C->getCommandID()));

  llvm::json::Array Args;
  for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
    Args.push_back(C->getArgText(I));

  if (!Args.empty())
    JOS.attribute("args", std::move(Args));
}

void JSONNodeDumper::visitParamCommandComment(
    const comments::ParamCommandComment *C, const comments::FullComment *FC) {
  switch (C->getDirection()) {
  case comments::ParamCommandPassDirection::In:
    JOS.attribute("direction", "in");
    break;
  case comments::ParamCommandPassDirection::Out:
    JOS.attribute("direction", "out");
    break;
  case comments::ParamCommandPassDirection::InOut:
    JOS.attribute("direction", "in,out");
    break;
  }
  attributeOnlyIfTrue("explicit", C->isDirectionExplicit());

  if (C->hasParamName())
    JOS.attribute("param", C->isParamIndexValid() ? C->getParamName(FC)
                                                  : C->getParamNameAsWritten());

  if (C->isParamIndexValid() && !C->isVarArgParam())
    JOS.attribute("paramIdx", C->getParamIndex());
}

void JSONNodeDumper::visitTParamCommandComment(
    const comments::TParamCommandComment *C, const comments::FullComment *FC) {
  if (C->hasParamName())
    JOS.attribute("param", C->isPositionValid() ? C->getParamName(FC)
                                                : C->getParamNameAsWritten());
  if (C->isPositionValid()) {
    llvm::json::Array Positions;
    for (unsigned I = 0, E = C->getDepth(); I < E; ++I)
      Positions.push_back(C->getIndex(I));

    if (!Positions.empty())
      JOS.attribute("positions", std::move(Positions));
  }
}

void JSONNodeDumper::visitVerbatimBlockComment(
    const comments::VerbatimBlockComment *C, const comments::FullComment *) {
  JOS.attribute("name", getCommentCommandName(C->getCommandID()));
  JOS.attribute("closeName", C->getCloseName());
}

void JSONNodeDumper::visitVerbatimBlockLineComment(
    const comments::VerbatimBlockLineComment *C,
    const comments::FullComment *) {
  JOS.attribute("text", C->getText());
}

void JSONNodeDumper::visitVerbatimLineComment(
    const comments::VerbatimLineComment *C, const comments::FullComment *) {
  JOS.attribute("text", C->getText());
}

llvm::json::Object JSONNodeDumper::createFPOptions(FPOptionsOverride FPO) {
  llvm::json::Object Ret;
#define FP_OPTION(NAME, TYPE, WIDTH, PREVIOUS)                                 \
  if (FPO.has##NAME##Override())                                               \
    Ret.try_emplace(#NAME, static_cast<unsigned>(FPO.get##NAME##Override()));
#include "clang/Basic/FPOptions.def"
  return Ret;
}

void JSONNodeDumper::VisitCompoundStmt(const CompoundStmt *S) {
  VisitStmt(S);
  if (S->hasStoredFPFeatures())
    JOS.attribute("fpoptions", createFPOptions(S->getStoredFPFeatures()));
}
