//===--- Comment.cpp - Comment AST node implementation --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/Comment.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/CharInfo.h"
#include "llvm/Support/ErrorHandling.h"

namespace clang {
namespace comments {

const char *Comment::getCommentKindName() const {
  switch (getCommentKind()) {
  case NoCommentKind: return "NoCommentKind";
#define ABSTRACT_COMMENT(COMMENT)
#define COMMENT(CLASS, PARENT) \
  case CLASS##Kind: \
    return #CLASS;
#include "clang/AST/CommentNodes.inc"
#undef COMMENT
#undef ABSTRACT_COMMENT
  }
  llvm_unreachable("Unknown comment kind!");
}

namespace {
struct good {};
struct bad {};

template <typename T>
good implements_child_begin_end(Comment::child_iterator (T::*)() const) {
  return good();
}

LLVM_ATTRIBUTE_UNUSED
static inline bad implements_child_begin_end(
                      Comment::child_iterator (Comment::*)() const) {
  return bad();
}

#define ASSERT_IMPLEMENTS_child_begin(function) \
  (void) good(implements_child_begin_end(function))

LLVM_ATTRIBUTE_UNUSED
static inline void CheckCommentASTNodes() {
#define ABSTRACT_COMMENT(COMMENT)
#define COMMENT(CLASS, PARENT) \
  ASSERT_IMPLEMENTS_child_begin(&CLASS::child_begin); \
  ASSERT_IMPLEMENTS_child_begin(&CLASS::child_end);
#include "clang/AST/CommentNodes.inc"
#undef COMMENT
#undef ABSTRACT_COMMENT
}

#undef ASSERT_IMPLEMENTS_child_begin

} // end unnamed namespace

Comment::child_iterator Comment::child_begin() const {
  switch (getCommentKind()) {
  case NoCommentKind: llvm_unreachable("comment without a kind");
#define ABSTRACT_COMMENT(COMMENT)
#define COMMENT(CLASS, PARENT) \
  case CLASS##Kind: \
    return static_cast<const CLASS *>(this)->child_begin();
#include "clang/AST/CommentNodes.inc"
#undef COMMENT
#undef ABSTRACT_COMMENT
  }
  llvm_unreachable("Unknown comment kind!");
}

Comment::child_iterator Comment::child_end() const {
  switch (getCommentKind()) {
  case NoCommentKind: llvm_unreachable("comment without a kind");
#define ABSTRACT_COMMENT(COMMENT)
#define COMMENT(CLASS, PARENT) \
  case CLASS##Kind: \
    return static_cast<const CLASS *>(this)->child_end();
#include "clang/AST/CommentNodes.inc"
#undef COMMENT
#undef ABSTRACT_COMMENT
  }
  llvm_unreachable("Unknown comment kind!");
}

bool TextComment::isWhitespaceNoCache() const {
  for (StringRef::const_iterator I = Text.begin(), E = Text.end();
       I != E; ++I) {
    if (!clang::isWhitespace(*I))
      return false;
  }
  return true;
}

bool ParagraphComment::isWhitespaceNoCache() const {
  for (child_iterator I = child_begin(), E = child_end(); I != E; ++I) {
    if (const TextComment *TC = dyn_cast<TextComment>(*I)) {
      if (!TC->isWhitespace())
        return false;
    } else
      return false;
  }
  return true;
}

static TypeLoc lookThroughTypedefOrTypeAliasLocs(TypeLoc &SrcTL) {
  TypeLoc TL = SrcTL.IgnoreParens();

  // Look through qualified types.
  if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>())
    return QualifiedTL.getUnqualifiedLoc();
  // Look through pointer types.
  if (PointerTypeLoc PointerTL = TL.getAs<PointerTypeLoc>())
    return PointerTL.getPointeeLoc().getUnqualifiedLoc();
  // Look through reference types.
  if (ReferenceTypeLoc ReferenceTL = TL.getAs<ReferenceTypeLoc>())
    return ReferenceTL.getPointeeLoc().getUnqualifiedLoc();
  // Look through adjusted types.
  if (AdjustedTypeLoc ATL = TL.getAs<AdjustedTypeLoc>())
    return ATL.getOriginalLoc();
  if (BlockPointerTypeLoc BlockPointerTL = TL.getAs<BlockPointerTypeLoc>())
    return BlockPointerTL.getPointeeLoc().getUnqualifiedLoc();
  if (MemberPointerTypeLoc MemberPointerTL = TL.getAs<MemberPointerTypeLoc>())
    return MemberPointerTL.getPointeeLoc().getUnqualifiedLoc();
  if (ElaboratedTypeLoc ETL = TL.getAs<ElaboratedTypeLoc>())
    return ETL.getNamedTypeLoc();

  return TL;
}

static bool getFunctionTypeLoc(TypeLoc TL, FunctionTypeLoc &ResFTL) {
  TypeLoc PrevTL;
  while (PrevTL != TL) {
    PrevTL = TL;
    TL = lookThroughTypedefOrTypeAliasLocs(TL);
  }

  if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
    ResFTL = FTL;
    return true;
  }

  if (TemplateSpecializationTypeLoc STL =
          TL.getAs<TemplateSpecializationTypeLoc>()) {
    // If we have a typedef to a template specialization with exactly one
    // template argument of a function type, this looks like std::function,
    // boost::function, or other function wrapper.  Treat these typedefs as
    // functions.
    if (STL.getNumArgs() != 1)
      return false;
    TemplateArgumentLoc MaybeFunction = STL.getArgLoc(0);
    if (MaybeFunction.getArgument().getKind() != TemplateArgument::Type)
      return false;
    TypeSourceInfo *MaybeFunctionTSI = MaybeFunction.getTypeSourceInfo();
    TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc();
    if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
      ResFTL = FTL;
      return true;
    }
  }

  return false;
}

const char *ParamCommandComment::getDirectionAsString(PassDirection D) {
  switch (D) {
  case ParamCommandComment::In:
    return "[in]";
  case ParamCommandComment::Out:
    return "[out]";
  case ParamCommandComment::InOut:
    return "[in,out]";
  }
  llvm_unreachable("unknown PassDirection");
}

void DeclInfo::fill() {
  assert(!IsFilled);

  // Set defaults.
  Kind = OtherKind;
  TemplateKind = NotTemplate;
  IsObjCMethod = false;
  IsInstanceMethod = false;
  IsClassMethod = false;
  ParamVars = None;
  TemplateParameters = nullptr;

  if (!CommentDecl) {
    // If there is no declaration, the defaults is our only guess.
    IsFilled = true;
    return;
  }
  CurrentDecl = CommentDecl;
  
  Decl::Kind K = CommentDecl->getKind();
  switch (K) {
  default:
    // Defaults are should be good for declarations we don't handle explicitly.
    break;
  case Decl::Function:
  case Decl::CXXMethod:
  case Decl::CXXConstructor:
  case Decl::CXXDestructor:
  case Decl::CXXConversion: {
    const FunctionDecl *FD = cast<FunctionDecl>(CommentDecl);
    Kind = FunctionKind;
    ParamVars = FD->parameters();
    ReturnType = FD->getReturnType();
    unsigned NumLists = FD->getNumTemplateParameterLists();
    if (NumLists != 0) {
      TemplateKind = TemplateSpecialization;
      TemplateParameters =
          FD->getTemplateParameterList(NumLists - 1);
    }

    if (K == Decl::CXXMethod || K == Decl::CXXConstructor ||
        K == Decl::CXXDestructor || K == Decl::CXXConversion) {
      const CXXMethodDecl *MD = cast<CXXMethodDecl>(CommentDecl);
      IsInstanceMethod = MD->isInstance();
      IsClassMethod = !IsInstanceMethod;
    }
    break;
  }
  case Decl::ObjCMethod: {
    const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(CommentDecl);
    Kind = FunctionKind;
    ParamVars = MD->parameters();
    ReturnType = MD->getReturnType();
    IsObjCMethod = true;
    IsInstanceMethod = MD->isInstanceMethod();
    IsClassMethod = !IsInstanceMethod;
    break;
  }
  case Decl::FunctionTemplate: {
    const FunctionTemplateDecl *FTD = cast<FunctionTemplateDecl>(CommentDecl);
    Kind = FunctionKind;
    TemplateKind = Template;
    const FunctionDecl *FD = FTD->getTemplatedDecl();
    ParamVars = FD->parameters();
    ReturnType = FD->getReturnType();
    TemplateParameters = FTD->getTemplateParameters();
    break;
  }
  case Decl::ClassTemplate: {
    const ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(CommentDecl);
    Kind = ClassKind;
    TemplateKind = Template;
    TemplateParameters = CTD->getTemplateParameters();
    break;
  }
  case Decl::ClassTemplatePartialSpecialization: {
    const ClassTemplatePartialSpecializationDecl *CTPSD =
        cast<ClassTemplatePartialSpecializationDecl>(CommentDecl);
    Kind = ClassKind;
    TemplateKind = TemplatePartialSpecialization;
    TemplateParameters = CTPSD->getTemplateParameters();
    break;
  }
  case Decl::ClassTemplateSpecialization:
    Kind = ClassKind;
    TemplateKind = TemplateSpecialization;
    break;
  case Decl::Record:
  case Decl::CXXRecord:
    Kind = ClassKind;
    break;
  case Decl::Var:
  case Decl::Field:
  case Decl::EnumConstant:
  case Decl::ObjCIvar:
  case Decl::ObjCAtDefsField:
    Kind = VariableKind;
    break;
  case Decl::Namespace:
    Kind = NamespaceKind;
    break;
  case Decl::TypeAlias:
  case Decl::Typedef: {
    Kind = TypedefKind;
    // If this is a typedef / using to something we consider a function, extract
    // arguments and return type.
    const TypeSourceInfo *TSI =
        K == Decl::Typedef
            ? cast<TypedefDecl>(CommentDecl)->getTypeSourceInfo()
            : cast<TypeAliasDecl>(CommentDecl)->getTypeSourceInfo();
    if (!TSI)
      break;
    TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc();
    FunctionTypeLoc FTL;
    if (getFunctionTypeLoc(TL, FTL)) {
      Kind = FunctionKind;
      ParamVars = FTL.getParams();
      ReturnType = FTL.getReturnLoc().getType();
    }
    break;
  }
  case Decl::TypeAliasTemplate: {
    const TypeAliasTemplateDecl *TAT = cast<TypeAliasTemplateDecl>(CommentDecl);
    Kind = TypedefKind;
    TemplateKind = Template;
    TemplateParameters = TAT->getTemplateParameters();
    TypeAliasDecl *TAD = TAT->getTemplatedDecl();
    if (!TAD)
      break;

    const TypeSourceInfo *TSI = TAD->getTypeSourceInfo();
    if (!TSI)
      break;
    TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc();
    FunctionTypeLoc FTL;
    if (getFunctionTypeLoc(TL, FTL)) {
      Kind = FunctionKind;
      ParamVars = FTL.getParams();
      ReturnType = FTL.getReturnLoc().getType();
    }
    break;
  }
  case Decl::Enum:
    Kind = EnumKind;
    break;
  }

  IsFilled = true;
}

StringRef ParamCommandComment::getParamName(const FullComment *FC) const {
  assert(isParamIndexValid());
  if (isVarArgParam())
    return "...";
  return FC->getDeclInfo()->ParamVars[getParamIndex()]->getName();
}

StringRef TParamCommandComment::getParamName(const FullComment *FC) const {
  assert(isPositionValid());
  const TemplateParameterList *TPL = FC->getDeclInfo()->TemplateParameters;
  for (unsigned i = 0, e = getDepth(); i != e; ++i) {
    if (i == e-1)
      return TPL->getParam(getIndex(i))->getName();
    const NamedDecl *Param = TPL->getParam(getIndex(i));
    if (const TemplateTemplateParmDecl *TTP =
          dyn_cast<TemplateTemplateParmDecl>(Param))
      TPL = TTP->getTemplateParameters();
  }
  return "";
}

} // end namespace comments
} // end namespace clang

