//===-- Serializer.cpp - ClangDoc Serializer --------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Serialize.h"
#include "BitcodeWriter.h"
#include "clang/AST/Comment.h"
#include "clang/Index/USRGeneration.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/SHA1.h"

using clang::comments::FullComment;

namespace clang {
namespace doc {
namespace serialize {

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

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 = C->getCommentKindName();
  ConstCommentVisitor<ClangDocCommentVisitor>::visit(C);
  for (comments::Comment *Child :
       llvm::make_range(C->child_begin(), C->child_end())) {
    CurrentCI.Children.emplace_back(llvm::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 std::all_of(S.begin(), S.end(), 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.

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()));
  default:
    return "";
  }
}

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 RecordDecl *getDeclForType(const QualType &T) {
  auto *Ty = T->getAs<RecordType>();
  if (!Ty)
    return nullptr;
  return Ty->getDecl()->getDefinition();
}

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

static void parseFields(RecordInfo &I, const RecordDecl *D, bool PublicOnly) {
  for (const FieldDecl *F : D->fields()) {
    if (PublicOnly && !isPublic(F->getAccessUnsafe(), F->getLinkageInternal()))
      continue;
    if (const auto *T = getDeclForType(F->getTypeSourceInfo()->getType())) {
      // Use getAccessUnsafe so that we just get the default AS_none if it's not
      // valid, as opposed to an assert.
      if (const auto *N = dyn_cast<EnumDecl>(T)) {
        I.Members.emplace_back(getUSRForDecl(T), N->getNameAsString(),
                               InfoType::IT_enum, F->getNameAsString(),
                               N->getAccessUnsafe());
        continue;
      } else if (const auto *N = dyn_cast<RecordDecl>(T)) {
        I.Members.emplace_back(getUSRForDecl(T), N->getNameAsString(),
                               InfoType::IT_record, F->getNameAsString(),
                               N->getAccessUnsafe());
        continue;
      }
    }
    I.Members.emplace_back(F->getTypeSourceInfo()->getType().getAsString(),
                           F->getNameAsString(), F->getAccessUnsafe());
  }
}

static void parseEnumerators(EnumInfo &I, const EnumDecl *D) {
  for (const EnumConstantDecl *E : D->enumerators())
    I.Members.emplace_back(E->getNameAsString());
}

static void parseParameters(FunctionInfo &I, const FunctionDecl *D) {
  for (const ParmVarDecl *P : D->parameters()) {
    if (const auto *T = getDeclForType(P->getOriginalType())) {
      if (const auto *N = dyn_cast<EnumDecl>(T)) {
        I.Params.emplace_back(getUSRForDecl(N), N->getNameAsString(),
                              InfoType::IT_enum, P->getNameAsString());
        continue;
      } else if (const auto *N = dyn_cast<RecordDecl>(T)) {
        I.Params.emplace_back(getUSRForDecl(N), N->getNameAsString(),
                              InfoType::IT_record, P->getNameAsString());
        continue;
      }
    }
    I.Params.emplace_back(P->getOriginalType().getAsString(),
                          P->getNameAsString());
  }
}

static void parseBases(RecordInfo &I, const CXXRecordDecl *D) {
  for (const CXXBaseSpecifier &B : D->bases()) {
    if (B.isVirtual())
      continue;
    if (const auto *P = getDeclForType(B.getType()))
      I.Parents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
                             InfoType::IT_record);
    else
      I.Parents.emplace_back(B.getType().getAsString());
  }
  for (const CXXBaseSpecifier &B : D->vbases()) {
    if (const auto *P = getDeclForType(B.getType()))
      I.VirtualParents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
                                    InfoType::IT_record);
    else
      I.VirtualParents.emplace_back(B.getType().getAsString());
  }
}

template <typename T>
static void
populateParentNamespaces(llvm::SmallVector<Reference, 4> &Namespaces,
                         const T *D) {
  const auto *DC = dyn_cast<DeclContext>(D);
  while ((DC = DC->getParent())) {
    if (const auto *N = dyn_cast<NamespaceDecl>(DC))
      Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
                              InfoType::IT_namespace);
    else if (const auto *N = dyn_cast<RecordDecl>(DC))
      Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
                              InfoType::IT_record);
    else if (const auto *N = dyn_cast<FunctionDecl>(DC))
      Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
                              InfoType::IT_function);
    else if (const auto *N = dyn_cast<EnumDecl>(DC))
      Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
                              InfoType::IT_enum);
  }
}

template <typename T>
static void populateInfo(Info &I, const T *D, const FullComment *C) {
  I.USR = getUSRForDecl(D);
  I.Name = D->getNameAsString();
  populateParentNamespaces(I.Namespace, D);
  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,
                               int LineNumber, StringRef Filename) {
  populateInfo(I, D, C);
  if (D->isThisDeclarationADefinition())
    I.DefLoc.emplace(LineNumber, Filename);
  else
    I.Loc.emplace_back(LineNumber, Filename);
}

static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
                                 const FullComment *FC, int LineNumber,
                                 StringRef Filename) {
  populateSymbolInfo(I, D, FC, LineNumber, Filename);
  if (const auto *T = getDeclForType(D->getReturnType())) {
    if (dyn_cast<EnumDecl>(T))
      I.ReturnType =
          TypeInfo(getUSRForDecl(T), T->getNameAsString(), InfoType::IT_enum);
    else if (dyn_cast<RecordDecl>(T))
      I.ReturnType =
          TypeInfo(getUSRForDecl(T), T->getNameAsString(), InfoType::IT_record);
  } else {
    I.ReturnType = TypeInfo(D->getReturnType().getAsString());
  }
  parseParameters(I, D);
}

std::unique_ptr<Info> emitInfo(const NamespaceDecl *D, const FullComment *FC,
                               int LineNumber, llvm::StringRef File,
                               bool PublicOnly) {
  if (PublicOnly && ((D->isAnonymousNamespace()) ||
                     !isPublic(D->getAccess(), D->getLinkageInternal())))
    return nullptr;
  auto I = llvm::make_unique<NamespaceInfo>();
  populateInfo(*I, D, FC);
  return std::unique_ptr<Info>{std::move(I)};
}

std::unique_ptr<Info> emitInfo(const RecordDecl *D, const FullComment *FC,
                               int LineNumber, llvm::StringRef File,
                               bool PublicOnly) {
  if (PublicOnly && !isPublic(D->getAccess(), D->getLinkageInternal()))
    return nullptr;
  auto I = llvm::make_unique<RecordInfo>();
  populateSymbolInfo(*I, D, FC, LineNumber, File);
  I->TagType = D->getTagKind();
  parseFields(*I, D, PublicOnly);
  if (const auto *C = dyn_cast<CXXRecordDecl>(D))
    parseBases(*I, C);
  return std::unique_ptr<Info>{std::move(I)};
}

std::unique_ptr<Info> emitInfo(const FunctionDecl *D, const FullComment *FC,
                               int LineNumber, llvm::StringRef File,
                               bool PublicOnly) {
  if (PublicOnly && !isPublic(D->getAccess(), D->getLinkageInternal()))
    return nullptr;
  FunctionInfo Func;
  populateFunctionInfo(Func, D, FC, LineNumber, File);
  Func.Access = clang::AccessSpecifier::AS_none;

  // Wrap in enclosing scope
  auto I = llvm::make_unique<NamespaceInfo>();
  if (!Func.Namespace.empty())
    I->USR = Func.Namespace[0].USR;
  else
    I->USR = SymbolID();
  I->ChildFunctions.emplace_back(std::move(Func));
  return std::unique_ptr<Info>{std::move(I)};
}

std::unique_ptr<Info> emitInfo(const CXXMethodDecl *D, const FullComment *FC,
                               int LineNumber, llvm::StringRef File,
                               bool PublicOnly) {
  if (PublicOnly && !isPublic(D->getAccess(), D->getLinkageInternal()))
    return nullptr;
  FunctionInfo Func;
  populateFunctionInfo(Func, D, FC, LineNumber, File);
  Func.IsMethod = true;

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

  // Wrap in enclosing scope
  auto I = llvm::make_unique<RecordInfo>();
  I->USR = ParentUSR;
  I->ChildFunctions.emplace_back(std::move(Func));
  return std::unique_ptr<Info>{std::move(I)};
}

std::unique_ptr<Info> emitInfo(const EnumDecl *D, const FullComment *FC,
                               int LineNumber, llvm::StringRef File,
                               bool PublicOnly) {
  if (PublicOnly && !isPublic(D->getAccess(), D->getLinkageInternal()))
    return nullptr;
  EnumInfo Enum;
  populateSymbolInfo(Enum, D, FC, LineNumber, File);
  Enum.Scoped = D->isScoped();
  parseEnumerators(Enum, D);

  // Wrap in enclosing scope
  if (!Enum.Namespace.empty()) {
    switch (Enum.Namespace[0].RefType) {
    case InfoType::IT_namespace: {
      auto I = llvm::make_unique<NamespaceInfo>();
      I->USR = Enum.Namespace[0].USR;
      I->ChildEnums.emplace_back(std::move(Enum));
      return std::unique_ptr<Info>{std::move(I)};
    }
    case InfoType::IT_record: {
      auto I = llvm::make_unique<RecordInfo>();
      I->USR = Enum.Namespace[0].USR;
      I->ChildEnums.emplace_back(std::move(Enum));
      return std::unique_ptr<Info>{std::move(I)};
    }
    default:
      break;
    }
  }

  // Put in global namespace
  auto I = llvm::make_unique<NamespaceInfo>();
  I->USR = SymbolID();
  I->ChildEnums.emplace_back(std::move(Enum));
  return std::unique_ptr<Info>{std::move(I)};
}

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