//===--- Comment.h - Comment AST nodes --------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines comment AST nodes.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_COMMENT_H
#define LLVM_CLANG_AST_COMMENT_H

#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"

namespace clang {
class Decl;
class ParmVarDecl;
class TemplateParameterList;

namespace comments {
class FullComment;

/// Describes the syntax that was used in a documentation command.
///
/// Exact values of this enumeration are important because they used to select
/// parts of diagnostic messages.  Audit diagnostics before changing or adding
/// a new value.
enum CommandMarkerKind {
  /// Command started with a backslash character:
  /// \code
  ///   \foo
  /// \endcode
  CMK_Backslash = 0,

  /// Command started with an 'at' character:
  /// \code
  ///   @foo
  /// \endcode
  CMK_At = 1
};

/// Any part of the comment.
/// Abstract class.
class Comment {
protected:
  /// Preferred location to show caret.
  SourceLocation Loc;

  /// Source range of this AST node.
  SourceRange Range;

  class CommentBitfields {
    friend class Comment;

    /// Type of this AST node.
    unsigned Kind : 8;
  };
  enum { NumCommentBits = 8 };

  class InlineContentCommentBitfields {
    friend class InlineContentComment;

    unsigned : NumCommentBits;

    /// True if there is a newline after this inline content node.
    /// (There is no separate AST node for a newline.)
    unsigned HasTrailingNewline : 1;
  };
  enum { NumInlineContentCommentBits = NumCommentBits + 1 };

  class TextCommentBitfields {
    friend class TextComment;

    unsigned : NumInlineContentCommentBits;

    /// True if \c IsWhitespace field contains a valid value.
    mutable unsigned IsWhitespaceValid : 1;

    /// True if this comment AST node contains only whitespace.
    mutable unsigned IsWhitespace : 1;
  };
  enum { NumTextCommentBits = NumInlineContentCommentBits + 2 };

  class InlineCommandCommentBitfields {
    friend class InlineCommandComment;

    unsigned : NumInlineContentCommentBits;

    unsigned RenderKind : 2;
    unsigned CommandID : CommandInfo::NumCommandIDBits;
  };
  enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 2 +
                                       CommandInfo::NumCommandIDBits };

  class HTMLTagCommentBitfields {
    friend class HTMLTagComment;

    unsigned : NumInlineContentCommentBits;

    /// True if we found that this tag is malformed in some way.
    unsigned IsMalformed : 1;
  };
  enum { NumHTMLTagCommentBits = NumInlineContentCommentBits + 1 };

  class HTMLStartTagCommentBitfields {
    friend class HTMLStartTagComment;

    unsigned : NumHTMLTagCommentBits;

    /// True if this tag is self-closing (e. g., <br />).  This is based on tag
    /// spelling in comment (plain <br> would not set this flag).
    unsigned IsSelfClosing : 1;
  };
  enum { NumHTMLStartTagCommentBits = NumHTMLTagCommentBits + 1 };

  class ParagraphCommentBitfields {
    friend class ParagraphComment;

    unsigned : NumCommentBits;

    /// True if \c IsWhitespace field contains a valid value.
    mutable unsigned IsWhitespaceValid : 1;

    /// True if this comment AST node contains only whitespace.
    mutable unsigned IsWhitespace : 1;
  };
  enum { NumParagraphCommentBits = NumCommentBits + 2 };

  class BlockCommandCommentBitfields {
    friend class BlockCommandComment;

    unsigned : NumCommentBits;

    unsigned CommandID : CommandInfo::NumCommandIDBits;

    /// Describes the syntax that was used in a documentation command.
    /// Contains values from CommandMarkerKind enum.
    unsigned CommandMarker : 1;
  };
  enum { NumBlockCommandCommentBits = NumCommentBits +
                                      CommandInfo::NumCommandIDBits + 1 };

  class ParamCommandCommentBitfields {
    friend class ParamCommandComment;

    unsigned : NumBlockCommandCommentBits;

    /// Parameter passing direction, see ParamCommandComment::PassDirection.
    unsigned Direction : 2;

    /// True if direction was specified explicitly in the comment.
    unsigned IsDirectionExplicit : 1;
  };
  enum { NumParamCommandCommentBits = NumBlockCommandCommentBits + 3 };

  union {
    CommentBitfields CommentBits;
    InlineContentCommentBitfields InlineContentCommentBits;
    TextCommentBitfields TextCommentBits;
    InlineCommandCommentBitfields InlineCommandCommentBits;
    HTMLTagCommentBitfields HTMLTagCommentBits;
    HTMLStartTagCommentBitfields HTMLStartTagCommentBits;
    ParagraphCommentBitfields ParagraphCommentBits;
    BlockCommandCommentBitfields BlockCommandCommentBits;
    ParamCommandCommentBitfields ParamCommandCommentBits;
  };

  void setSourceRange(SourceRange SR) {
    Range = SR;
  }

  void setLocation(SourceLocation L) {
    Loc = L;
  }

public:
  enum CommentKind {
    NoCommentKind = 0,
#define COMMENT(CLASS, PARENT) CLASS##Kind,
#define COMMENT_RANGE(BASE, FIRST, LAST) \
    First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind,
#define LAST_COMMENT_RANGE(BASE, FIRST, LAST) \
    First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind
#define ABSTRACT_COMMENT(COMMENT)
#include "clang/AST/CommentNodes.inc"
  };

  Comment(CommentKind K,
          SourceLocation LocBegin,
          SourceLocation LocEnd) :
      Loc(LocBegin), Range(SourceRange(LocBegin, LocEnd)) {
    CommentBits.Kind = K;
  }

  CommentKind getCommentKind() const {
    return static_cast<CommentKind>(CommentBits.Kind);
  }

  const char *getCommentKindName() const;

  void dump() const;
  void dumpColor() const;
  void dump(const ASTContext &Context) const;
  void dump(raw_ostream &OS, const CommandTraits *Traits,
            const SourceManager *SM) const;

  SourceRange getSourceRange() const LLVM_READONLY { return Range; }

  SourceLocation getLocStart() const LLVM_READONLY { return getBeginLoc(); }
  SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }

  SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
  SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }

  SourceLocation getLocation() const LLVM_READONLY { return Loc; }

  typedef Comment * const *child_iterator;

  child_iterator child_begin() const;
  child_iterator child_end() const;

  // TODO: const child iterator

  unsigned child_count() const {
    return child_end() - child_begin();
  }
};

/// Inline content (contained within a block).
/// Abstract class.
class InlineContentComment : public Comment {
protected:
  InlineContentComment(CommentKind K,
                       SourceLocation LocBegin,
                       SourceLocation LocEnd) :
      Comment(K, LocBegin, LocEnd) {
    InlineContentCommentBits.HasTrailingNewline = 0;
  }

public:
  static bool classof(const Comment *C) {
    return C->getCommentKind() >= FirstInlineContentCommentConstant &&
           C->getCommentKind() <= LastInlineContentCommentConstant;
  }

  void addTrailingNewline() {
    InlineContentCommentBits.HasTrailingNewline = 1;
  }

  bool hasTrailingNewline() const {
    return InlineContentCommentBits.HasTrailingNewline;
  }
};

/// Plain text.
class TextComment : public InlineContentComment {
  StringRef Text;

public:
  TextComment(SourceLocation LocBegin,
              SourceLocation LocEnd,
              StringRef Text) :
      InlineContentComment(TextCommentKind, LocBegin, LocEnd),
      Text(Text) {
    TextCommentBits.IsWhitespaceValid = false;
  }

  static bool classof(const Comment *C) {
    return C->getCommentKind() == TextCommentKind;
  }

  child_iterator child_begin() const { return nullptr; }

  child_iterator child_end() const { return nullptr; }

  StringRef getText() const LLVM_READONLY { return Text; }

  bool isWhitespace() const {
    if (TextCommentBits.IsWhitespaceValid)
      return TextCommentBits.IsWhitespace;

    TextCommentBits.IsWhitespace = isWhitespaceNoCache();
    TextCommentBits.IsWhitespaceValid = true;
    return TextCommentBits.IsWhitespace;
  }

private:
  bool isWhitespaceNoCache() const;
};

/// A command with word-like arguments that is considered inline content.
class InlineCommandComment : public InlineContentComment {
public:
  struct Argument {
    SourceRange Range;
    StringRef Text;

    Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
  };

  /// The most appropriate rendering mode for this command, chosen on command
  /// semantics in Doxygen.
  enum RenderKind {
    RenderNormal,
    RenderBold,
    RenderMonospaced,
    RenderEmphasized
  };

protected:
  /// Command arguments.
  ArrayRef<Argument> Args;

public:
  InlineCommandComment(SourceLocation LocBegin,
                       SourceLocation LocEnd,
                       unsigned CommandID,
                       RenderKind RK,
                       ArrayRef<Argument> Args) :
      InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd),
      Args(Args) {
    InlineCommandCommentBits.RenderKind = RK;
    InlineCommandCommentBits.CommandID = CommandID;
  }

  static bool classof(const Comment *C) {
    return C->getCommentKind() == InlineCommandCommentKind;
  }

  child_iterator child_begin() const { return nullptr; }

  child_iterator child_end() const { return nullptr; }

  unsigned getCommandID() const {
    return InlineCommandCommentBits.CommandID;
  }

  StringRef getCommandName(const CommandTraits &Traits) const {
    return Traits.getCommandInfo(getCommandID())->Name;
  }

  SourceRange getCommandNameRange() const {
    return SourceRange(getLocStart().getLocWithOffset(-1),
                       getLocEnd());
  }

  RenderKind getRenderKind() const {
    return static_cast<RenderKind>(InlineCommandCommentBits.RenderKind);
  }

  unsigned getNumArgs() const {
    return Args.size();
  }

  StringRef getArgText(unsigned Idx) const {
    return Args[Idx].Text;
  }

  SourceRange getArgRange(unsigned Idx) const {
    return Args[Idx].Range;
  }
};

/// Abstract class for opening and closing HTML tags.  HTML tags are always
/// treated as inline content (regardless HTML semantics).
class HTMLTagComment : public InlineContentComment {
protected:
  StringRef TagName;
  SourceRange TagNameRange;

  HTMLTagComment(CommentKind K,
                 SourceLocation LocBegin,
                 SourceLocation LocEnd,
                 StringRef TagName,
                 SourceLocation TagNameBegin,
                 SourceLocation TagNameEnd) :
      InlineContentComment(K, LocBegin, LocEnd),
      TagName(TagName),
      TagNameRange(TagNameBegin, TagNameEnd) {
    setLocation(TagNameBegin);
    HTMLTagCommentBits.IsMalformed = 0;
  }

public:
  static bool classof(const Comment *C) {
    return C->getCommentKind() >= FirstHTMLTagCommentConstant &&
           C->getCommentKind() <= LastHTMLTagCommentConstant;
  }

  StringRef getTagName() const LLVM_READONLY { return TagName; }

  SourceRange getTagNameSourceRange() const LLVM_READONLY {
    SourceLocation L = getLocation();
    return SourceRange(L.getLocWithOffset(1),
                       L.getLocWithOffset(1 + TagName.size()));
  }

  bool isMalformed() const {
    return HTMLTagCommentBits.IsMalformed;
  }

  void setIsMalformed() {
    HTMLTagCommentBits.IsMalformed = 1;
  }
};

/// An opening HTML tag with attributes.
class HTMLStartTagComment : public HTMLTagComment {
public:
  class Attribute {
  public:
    SourceLocation NameLocBegin;
    StringRef Name;

    SourceLocation EqualsLoc;

    SourceRange ValueRange;
    StringRef Value;

    Attribute() { }

    Attribute(SourceLocation NameLocBegin, StringRef Name) :
        NameLocBegin(NameLocBegin), Name(Name),
        EqualsLoc(SourceLocation()),
        ValueRange(SourceRange()), Value(StringRef())
    { }

    Attribute(SourceLocation NameLocBegin, StringRef Name,
              SourceLocation EqualsLoc,
              SourceRange ValueRange, StringRef Value) :
        NameLocBegin(NameLocBegin), Name(Name),
        EqualsLoc(EqualsLoc),
        ValueRange(ValueRange), Value(Value)
    { }

    SourceLocation getNameLocEnd() const {
      return NameLocBegin.getLocWithOffset(Name.size());
    }

    SourceRange getNameRange() const {
      return SourceRange(NameLocBegin, getNameLocEnd());
    }
  };

private:
  ArrayRef<Attribute> Attributes;

public:
  HTMLStartTagComment(SourceLocation LocBegin,
                      StringRef TagName) :
      HTMLTagComment(HTMLStartTagCommentKind,
                     LocBegin, LocBegin.getLocWithOffset(1 + TagName.size()),
                     TagName,
                     LocBegin.getLocWithOffset(1),
                     LocBegin.getLocWithOffset(1 + TagName.size())) {
    HTMLStartTagCommentBits.IsSelfClosing = false;
  }

  static bool classof(const Comment *C) {
    return C->getCommentKind() == HTMLStartTagCommentKind;
  }

  child_iterator child_begin() const { return nullptr; }

  child_iterator child_end() const { return nullptr; }

  unsigned getNumAttrs() const {
    return Attributes.size();
  }

  const Attribute &getAttr(unsigned Idx) const {
    return Attributes[Idx];
  }

  void setAttrs(ArrayRef<Attribute> Attrs) {
    Attributes = Attrs;
    if (!Attrs.empty()) {
      const Attribute &Attr = Attrs.back();
      SourceLocation L = Attr.ValueRange.getEnd();
      if (L.isValid())
        Range.setEnd(L);
      else {
        Range.setEnd(Attr.getNameLocEnd());
      }
    }
  }

  void setGreaterLoc(SourceLocation GreaterLoc) {
    Range.setEnd(GreaterLoc);
  }

  bool isSelfClosing() const {
    return HTMLStartTagCommentBits.IsSelfClosing;
  }

  void setSelfClosing() {
    HTMLStartTagCommentBits.IsSelfClosing = true;
  }
};

/// A closing HTML tag.
class HTMLEndTagComment : public HTMLTagComment {
public:
  HTMLEndTagComment(SourceLocation LocBegin,
                    SourceLocation LocEnd,
                    StringRef TagName) :
      HTMLTagComment(HTMLEndTagCommentKind,
                     LocBegin, LocEnd,
                     TagName,
                     LocBegin.getLocWithOffset(2),
                     LocBegin.getLocWithOffset(2 + TagName.size()))
  { }

  static bool classof(const Comment *C) {
    return C->getCommentKind() == HTMLEndTagCommentKind;
  }

  child_iterator child_begin() const { return nullptr; }

  child_iterator child_end() const { return nullptr; }
};

/// Block content (contains inline content).
/// Abstract class.
class BlockContentComment : public Comment {
protected:
  BlockContentComment(CommentKind K,
                      SourceLocation LocBegin,
                      SourceLocation LocEnd) :
      Comment(K, LocBegin, LocEnd)
  { }

public:
  static bool classof(const Comment *C) {
    return C->getCommentKind() >= FirstBlockContentCommentConstant &&
           C->getCommentKind() <= LastBlockContentCommentConstant;
  }
};

/// A single paragraph that contains inline content.
class ParagraphComment : public BlockContentComment {
  ArrayRef<InlineContentComment *> Content;

public:
  ParagraphComment(ArrayRef<InlineContentComment *> Content) :
      BlockContentComment(ParagraphCommentKind,
                          SourceLocation(),
                          SourceLocation()),
      Content(Content) {
    if (Content.empty()) {
      ParagraphCommentBits.IsWhitespace = true;
      ParagraphCommentBits.IsWhitespaceValid = true;
      return;
    }

    ParagraphCommentBits.IsWhitespaceValid = false;

    setSourceRange(SourceRange(Content.front()->getLocStart(),
                               Content.back()->getLocEnd()));
    setLocation(Content.front()->getLocStart());
  }

  static bool classof(const Comment *C) {
    return C->getCommentKind() == ParagraphCommentKind;
  }

  child_iterator child_begin() const {
    return reinterpret_cast<child_iterator>(Content.begin());
  }

  child_iterator child_end() const {
    return reinterpret_cast<child_iterator>(Content.end());
  }

  bool isWhitespace() const {
    if (ParagraphCommentBits.IsWhitespaceValid)
      return ParagraphCommentBits.IsWhitespace;

    ParagraphCommentBits.IsWhitespace = isWhitespaceNoCache();
    ParagraphCommentBits.IsWhitespaceValid = true;
    return ParagraphCommentBits.IsWhitespace;
  }

private:
  bool isWhitespaceNoCache() const;
};

/// A command that has zero or more word-like arguments (number of word-like
/// arguments depends on command name) and a paragraph as an argument
/// (e. g., \\brief).
class BlockCommandComment : public BlockContentComment {
public:
  struct Argument {
    SourceRange Range;
    StringRef Text;

    Argument() { }
    Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
  };

protected:
  /// Word-like arguments.
  ArrayRef<Argument> Args;

  /// Paragraph argument.
  ParagraphComment *Paragraph;

  BlockCommandComment(CommentKind K,
                      SourceLocation LocBegin,
                      SourceLocation LocEnd,
                      unsigned CommandID,
                      CommandMarkerKind CommandMarker) :
      BlockContentComment(K, LocBegin, LocEnd),
      Paragraph(nullptr) {
    setLocation(getCommandNameBeginLoc());
    BlockCommandCommentBits.CommandID = CommandID;
    BlockCommandCommentBits.CommandMarker = CommandMarker;
  }

public:
  BlockCommandComment(SourceLocation LocBegin,
                      SourceLocation LocEnd,
                      unsigned CommandID,
                      CommandMarkerKind CommandMarker) :
      BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd),
      Paragraph(nullptr) {
    setLocation(getCommandNameBeginLoc());
    BlockCommandCommentBits.CommandID = CommandID;
    BlockCommandCommentBits.CommandMarker = CommandMarker;
  }

  static bool classof(const Comment *C) {
    return C->getCommentKind() >= FirstBlockCommandCommentConstant &&
           C->getCommentKind() <= LastBlockCommandCommentConstant;
  }

  child_iterator child_begin() const {
    return reinterpret_cast<child_iterator>(&Paragraph);
  }

  child_iterator child_end() const {
    return reinterpret_cast<child_iterator>(&Paragraph + 1);
  }

  unsigned getCommandID() const {
    return BlockCommandCommentBits.CommandID;
  }

  StringRef getCommandName(const CommandTraits &Traits) const {
    return Traits.getCommandInfo(getCommandID())->Name;
  }

  SourceLocation getCommandNameBeginLoc() const {
    return getLocStart().getLocWithOffset(1);
  }

  SourceRange getCommandNameRange(const CommandTraits &Traits) const {
    StringRef Name = getCommandName(Traits);
    return SourceRange(getCommandNameBeginLoc(),
                       getLocStart().getLocWithOffset(1 + Name.size()));
  }

  unsigned getNumArgs() const {
    return Args.size();
  }

  StringRef getArgText(unsigned Idx) const {
    return Args[Idx].Text;
  }

  SourceRange getArgRange(unsigned Idx) const {
    return Args[Idx].Range;
  }

  void setArgs(ArrayRef<Argument> A) {
    Args = A;
    if (Args.size() > 0) {
      SourceLocation NewLocEnd = Args.back().Range.getEnd();
      if (NewLocEnd.isValid())
        setSourceRange(SourceRange(getLocStart(), NewLocEnd));
    }
  }

  ParagraphComment *getParagraph() const LLVM_READONLY {
    return Paragraph;
  }

  bool hasNonWhitespaceParagraph() const {
    return Paragraph && !Paragraph->isWhitespace();
  }

  void setParagraph(ParagraphComment *PC) {
    Paragraph = PC;
    SourceLocation NewLocEnd = PC->getLocEnd();
    if (NewLocEnd.isValid())
      setSourceRange(SourceRange(getLocStart(), NewLocEnd));
  }

  CommandMarkerKind getCommandMarker() const LLVM_READONLY {
    return static_cast<CommandMarkerKind>(
        BlockCommandCommentBits.CommandMarker);
  }
};

/// Doxygen \\param command.
class ParamCommandComment : public BlockCommandComment {
private:
  /// Parameter index in the function declaration.
  unsigned ParamIndex;

public:
  enum : unsigned {
    InvalidParamIndex = ~0U,
    VarArgParamIndex = ~0U/*InvalidParamIndex*/ - 1U
  };

  ParamCommandComment(SourceLocation LocBegin,
                      SourceLocation LocEnd,
                      unsigned CommandID,
                      CommandMarkerKind CommandMarker) :
      BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd,
                          CommandID, CommandMarker),
      ParamIndex(InvalidParamIndex) {
    ParamCommandCommentBits.Direction = In;
    ParamCommandCommentBits.IsDirectionExplicit = false;
  }

  static bool classof(const Comment *C) {
    return C->getCommentKind() == ParamCommandCommentKind;
  }

  enum PassDirection {
    In,
    Out,
    InOut
  };

  static const char *getDirectionAsString(PassDirection D);

  PassDirection getDirection() const LLVM_READONLY {
    return static_cast<PassDirection>(ParamCommandCommentBits.Direction);
  }

  bool isDirectionExplicit() const LLVM_READONLY {
    return ParamCommandCommentBits.IsDirectionExplicit;
  }

  void setDirection(PassDirection Direction, bool Explicit) {
    ParamCommandCommentBits.Direction = Direction;
    ParamCommandCommentBits.IsDirectionExplicit = Explicit;
  }

  bool hasParamName() const {
    return getNumArgs() > 0;
  }

  StringRef getParamName(const FullComment *FC) const;

  StringRef getParamNameAsWritten() const {
    return Args[0].Text;
  }

  SourceRange getParamNameRange() const {
    return Args[0].Range;
  }

  bool isParamIndexValid() const LLVM_READONLY {
    return ParamIndex != InvalidParamIndex;
  }

  bool isVarArgParam() const LLVM_READONLY {
    return ParamIndex == VarArgParamIndex;
  }

  void setIsVarArgParam() {
    ParamIndex = VarArgParamIndex;
    assert(isParamIndexValid());
  }

  unsigned getParamIndex() const LLVM_READONLY {
    assert(isParamIndexValid());
    assert(!isVarArgParam());
    return ParamIndex;
  }

  void setParamIndex(unsigned Index) {
    ParamIndex = Index;
    assert(isParamIndexValid());
    assert(!isVarArgParam());
  }
};

/// Doxygen \\tparam command, describes a template parameter.
class TParamCommandComment : public BlockCommandComment {
private:
  /// If this template parameter name was resolved (found in template parameter
  /// list), then this stores a list of position indexes in all template
  /// parameter lists.
  ///
  /// For example:
  /// \verbatim
  ///     template<typename C, template<typename T> class TT>
  ///     void test(TT<int> aaa);
  /// \endverbatim
  /// For C:  Position = { 0 }
  /// For TT: Position = { 1 }
  /// For T:  Position = { 1, 0 }
  ArrayRef<unsigned> Position;

public:
  TParamCommandComment(SourceLocation LocBegin,
                       SourceLocation LocEnd,
                       unsigned CommandID,
                       CommandMarkerKind CommandMarker) :
      BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, CommandID,
                          CommandMarker)
  { }

  static bool classof(const Comment *C) {
    return C->getCommentKind() == TParamCommandCommentKind;
  }

  bool hasParamName() const {
    return getNumArgs() > 0;
  }

  StringRef getParamName(const FullComment *FC) const;

  StringRef getParamNameAsWritten() const {
    return Args[0].Text;
  }

  SourceRange getParamNameRange() const {
    return Args[0].Range;
  }

  bool isPositionValid() const LLVM_READONLY {
    return !Position.empty();
  }

  unsigned getDepth() const {
    assert(isPositionValid());
    return Position.size();
  }

  unsigned getIndex(unsigned Depth) const {
    assert(isPositionValid());
    return Position[Depth];
  }

  void setPosition(ArrayRef<unsigned> NewPosition) {
    Position = NewPosition;
    assert(isPositionValid());
  }
};

/// A line of text contained in a verbatim block.
class VerbatimBlockLineComment : public Comment {
  StringRef Text;

public:
  VerbatimBlockLineComment(SourceLocation LocBegin,
                           StringRef Text) :
      Comment(VerbatimBlockLineCommentKind,
              LocBegin,
              LocBegin.getLocWithOffset(Text.size())),
      Text(Text)
  { }

  static bool classof(const Comment *C) {
    return C->getCommentKind() == VerbatimBlockLineCommentKind;
  }

  child_iterator child_begin() const { return nullptr; }

  child_iterator child_end() const { return nullptr; }

  StringRef getText() const LLVM_READONLY {
    return Text;
  }
};

/// A verbatim block command (e. g., preformatted code).  Verbatim block has an
/// opening and a closing command and contains multiple lines of text
/// (VerbatimBlockLineComment nodes).
class VerbatimBlockComment : public BlockCommandComment {
protected:
  StringRef CloseName;
  SourceLocation CloseNameLocBegin;
  ArrayRef<VerbatimBlockLineComment *> Lines;

public:
  VerbatimBlockComment(SourceLocation LocBegin,
                       SourceLocation LocEnd,
                       unsigned CommandID) :
      BlockCommandComment(VerbatimBlockCommentKind,
                          LocBegin, LocEnd, CommandID,
                          CMK_At) // FIXME: improve source fidelity.
  { }

  static bool classof(const Comment *C) {
    return C->getCommentKind() == VerbatimBlockCommentKind;
  }

  child_iterator child_begin() const {
    return reinterpret_cast<child_iterator>(Lines.begin());
  }

  child_iterator child_end() const {
    return reinterpret_cast<child_iterator>(Lines.end());
  }

  void setCloseName(StringRef Name, SourceLocation LocBegin) {
    CloseName = Name;
    CloseNameLocBegin = LocBegin;
  }

  void setLines(ArrayRef<VerbatimBlockLineComment *> L) {
    Lines = L;
  }

  StringRef getCloseName() const {
    return CloseName;
  }

  unsigned getNumLines() const {
    return Lines.size();
  }

  StringRef getText(unsigned LineIdx) const {
    return Lines[LineIdx]->getText();
  }
};

/// A verbatim line command.  Verbatim line has an opening command, a single
/// line of text (up to the newline after the opening command) and has no
/// closing command.
class VerbatimLineComment : public BlockCommandComment {
protected:
  StringRef Text;
  SourceLocation TextBegin;

public:
  VerbatimLineComment(SourceLocation LocBegin,
                      SourceLocation LocEnd,
                      unsigned CommandID,
                      SourceLocation TextBegin,
                      StringRef Text) :
      BlockCommandComment(VerbatimLineCommentKind,
                          LocBegin, LocEnd,
                          CommandID,
                          CMK_At), // FIXME: improve source fidelity.
      Text(Text),
      TextBegin(TextBegin)
  { }

  static bool classof(const Comment *C) {
    return C->getCommentKind() == VerbatimLineCommentKind;
  }

  child_iterator child_begin() const { return nullptr; }

  child_iterator child_end() const { return nullptr; }

  StringRef getText() const {
    return Text;
  }

  SourceRange getTextRange() const {
    return SourceRange(TextBegin, getLocEnd());
  }
};

/// Information about the declaration, useful to clients of FullComment.
struct DeclInfo {
  /// Declaration the comment is actually attached to (in the source).
  /// Should not be NULL.
  const Decl *CommentDecl;

  /// CurrentDecl is the declaration with which the FullComment is associated.
  ///
  /// It can be different from \c CommentDecl.  It happens when we decide
  /// that the comment originally attached to \c CommentDecl is fine for
  /// \c CurrentDecl too (for example, for a redeclaration or an overrider of
  /// \c CommentDecl).
  ///
  /// The information in the DeclInfo corresponds to CurrentDecl.
  const Decl *CurrentDecl;

  /// Parameters that can be referenced by \\param if \c CommentDecl is something
  /// that we consider a "function".
  ArrayRef<const ParmVarDecl *> ParamVars;

  /// Function return type if \c CommentDecl is something that we consider
  /// a "function".
  QualType ReturnType;

  /// Template parameters that can be referenced by \\tparam if \c CommentDecl is
  /// a template (\c IsTemplateDecl or \c IsTemplatePartialSpecialization is
  /// true).
  const TemplateParameterList *TemplateParameters;

  /// A simplified description of \c CommentDecl kind that should be good enough
  /// for documentation rendering purposes.
  enum DeclKind {
    /// Everything else not explicitly mentioned below.
    OtherKind,

    /// Something that we consider a "function":
    /// \li function,
    /// \li function template,
    /// \li function template specialization,
    /// \li member function,
    /// \li member function template,
    /// \li member function template specialization,
    /// \li ObjC method,
    /// \li a typedef for a function pointer, member function pointer,
    ///     ObjC block.
    FunctionKind,

    /// Something that we consider a "class":
    /// \li class/struct,
    /// \li class template,
    /// \li class template (partial) specialization.
    ClassKind,

    /// Something that we consider a "variable":
    /// \li namespace scope variables;
    /// \li static and non-static class data members;
    /// \li enumerators.
    VariableKind,

    /// A C++ namespace.
    NamespaceKind,

    /// A C++ typedef-name (a 'typedef' decl specifier or alias-declaration),
    /// see \c TypedefNameDecl.
    TypedefKind,

    /// An enumeration or scoped enumeration.
    EnumKind
  };

  /// What kind of template specialization \c CommentDecl is.
  enum TemplateDeclKind {
    NotTemplate,
    Template,
    TemplateSpecialization,
    TemplatePartialSpecialization
  };

  /// If false, only \c CommentDecl is valid.
  unsigned IsFilled : 1;

  /// Simplified kind of \c CommentDecl, see \c DeclKind enum.
  unsigned Kind : 3;

  /// Is \c CommentDecl a template declaration.
  unsigned TemplateKind : 2;

  /// Is \c CommentDecl an ObjCMethodDecl.
  unsigned IsObjCMethod : 1;

  /// Is \c CommentDecl a non-static member function of C++ class or
  /// instance method of ObjC class.
  /// Can be true only if \c IsFunctionDecl is true.
  unsigned IsInstanceMethod : 1;

  /// Is \c CommentDecl a static member function of C++ class or
  /// class method of ObjC class.
  /// Can be true only if \c IsFunctionDecl is true.
  unsigned IsClassMethod : 1;

  void fill();

  DeclKind getKind() const LLVM_READONLY {
    return static_cast<DeclKind>(Kind);
  }

  TemplateDeclKind getTemplateKind() const LLVM_READONLY {
    return static_cast<TemplateDeclKind>(TemplateKind);
  }
};

/// A full comment attached to a declaration, contains block content.
class FullComment : public Comment {
  ArrayRef<BlockContentComment *> Blocks;
  DeclInfo *ThisDeclInfo;

public:
  FullComment(ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) :
      Comment(FullCommentKind, SourceLocation(), SourceLocation()),
      Blocks(Blocks), ThisDeclInfo(D) {
    if (Blocks.empty())
      return;

    setSourceRange(SourceRange(Blocks.front()->getLocStart(),
                               Blocks.back()->getLocEnd()));
    setLocation(Blocks.front()->getLocStart());
  }

  static bool classof(const Comment *C) {
    return C->getCommentKind() == FullCommentKind;
  }

  child_iterator child_begin() const {
    return reinterpret_cast<child_iterator>(Blocks.begin());
  }

  child_iterator child_end() const {
    return reinterpret_cast<child_iterator>(Blocks.end());
  }

  const Decl *getDecl() const LLVM_READONLY {
    return ThisDeclInfo->CommentDecl;
  }

  const DeclInfo *getDeclInfo() const LLVM_READONLY {
    if (!ThisDeclInfo->IsFilled)
      ThisDeclInfo->fill();
    return ThisDeclInfo;
  }

  ArrayRef<BlockContentComment *> getBlocks() const { return Blocks; }

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

#endif

