//===-- Mapper.cpp - ClangDoc Mapper ----------------------------*- 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 "Mapper.h"
#include "BitcodeWriter.h"
#include "Serialize.h"
#include "clang/AST/Comment.h"
#include "clang/Index/USRGeneration.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Error.h"

using clang::comments::FullComment;

namespace clang {
namespace doc {

void MapASTVisitor::HandleTranslationUnit(ASTContext &Context) {
  TraverseDecl(Context.getTranslationUnitDecl());
}

template <typename T> bool MapASTVisitor::mapDecl(const T *D) {
  // If we're looking a decl not in user files, skip this decl.
  if (D->getASTContext().getSourceManager().isInSystemHeader(D->getLocation()))
    return true;

  // Skip function-internal decls.
  if (D->getParentFunctionOrMethod())
    return true;

  llvm::SmallString<128> USR;
  // If there is an error generating a USR for the decl, skip this decl.
  if (index::generateUSRForDecl(D, USR))
    return true;

  auto I = serialize::emitInfo(
      D, getComment(D, D->getASTContext()), getLine(D, D->getASTContext()),
      getFile(D, D->getASTContext()), CDCtx.PublicOnly);

  // A null in place of I indicates that the serializer is skipping this decl
  // for some reason (e.g. we're only reporting public decls).
  if (I.first)
    CDCtx.ECtx->reportResult(llvm::toHex(llvm::toStringRef(I.first->USR)),
                             serialize::serialize(I.first));
  if (I.second)
    CDCtx.ECtx->reportResult(llvm::toHex(llvm::toStringRef(I.second->USR)),
                             serialize::serialize(I.second));
  return true;
}

bool MapASTVisitor::VisitNamespaceDecl(const NamespaceDecl *D) {
  return mapDecl(D);
}

bool MapASTVisitor::VisitRecordDecl(const RecordDecl *D) { return mapDecl(D); }

bool MapASTVisitor::VisitEnumDecl(const EnumDecl *D) { return mapDecl(D); }

bool MapASTVisitor::VisitCXXMethodDecl(const CXXMethodDecl *D) {
  return mapDecl(D);
}

bool MapASTVisitor::VisitFunctionDecl(const FunctionDecl *D) {
  // Don't visit CXXMethodDecls twice
  if (dyn_cast<CXXMethodDecl>(D))
    return true;
  return mapDecl(D);
}

comments::FullComment *
MapASTVisitor::getComment(const NamedDecl *D, const ASTContext &Context) const {
  RawComment *Comment = Context.getRawCommentForDeclNoCache(D);
  // FIXME: Move setAttached to the initial comment parsing.
  if (Comment) {
    Comment->setAttached();
    return Comment->parse(Context, nullptr, D);
  }
  return nullptr;
}

int MapASTVisitor::getLine(const NamedDecl *D,
                           const ASTContext &Context) const {
  return Context.getSourceManager().getPresumedLoc(D->getBeginLoc()).getLine();
}

llvm::StringRef MapASTVisitor::getFile(const NamedDecl *D,
                                       const ASTContext &Context) const {
  return Context.getSourceManager()
      .getPresumedLoc(D->getBeginLoc())
      .getFilename();
}

} // namespace doc
} // namespace clang
