1e5dd7070Spatrick //===--- Comment.h - Comment AST nodes --------------------------*- C++ -*-===// 2e5dd7070Spatrick // 3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information. 5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e5dd7070Spatrick // 7e5dd7070Spatrick //===----------------------------------------------------------------------===// 8e5dd7070Spatrick // 9e5dd7070Spatrick // This file defines comment AST nodes. 10e5dd7070Spatrick // 11e5dd7070Spatrick //===----------------------------------------------------------------------===// 12e5dd7070Spatrick 13e5dd7070Spatrick #ifndef LLVM_CLANG_AST_COMMENT_H 14e5dd7070Spatrick #define LLVM_CLANG_AST_COMMENT_H 15e5dd7070Spatrick 16e5dd7070Spatrick #include "clang/AST/CommentCommandTraits.h" 17e5dd7070Spatrick #include "clang/AST/DeclObjC.h" 18e5dd7070Spatrick #include "clang/AST/Type.h" 19e5dd7070Spatrick #include "clang/Basic/SourceLocation.h" 20e5dd7070Spatrick #include "llvm/ADT/ArrayRef.h" 21e5dd7070Spatrick #include "llvm/ADT/StringRef.h" 22e5dd7070Spatrick 23e5dd7070Spatrick namespace clang { 24e5dd7070Spatrick class Decl; 25e5dd7070Spatrick class ParmVarDecl; 26e5dd7070Spatrick class TemplateParameterList; 27e5dd7070Spatrick 28e5dd7070Spatrick namespace comments { 29e5dd7070Spatrick class FullComment; 30e5dd7070Spatrick 31e5dd7070Spatrick /// Describes the syntax that was used in a documentation command. 32e5dd7070Spatrick /// 33e5dd7070Spatrick /// Exact values of this enumeration are important because they used to select 34e5dd7070Spatrick /// parts of diagnostic messages. Audit diagnostics before changing or adding 35e5dd7070Spatrick /// a new value. 36e5dd7070Spatrick enum CommandMarkerKind { 37e5dd7070Spatrick /// Command started with a backslash character: 38e5dd7070Spatrick /// \code 39e5dd7070Spatrick /// \foo 40e5dd7070Spatrick /// \endcode 41e5dd7070Spatrick CMK_Backslash = 0, 42e5dd7070Spatrick 43e5dd7070Spatrick /// Command started with an 'at' character: 44e5dd7070Spatrick /// \code 45e5dd7070Spatrick /// @foo 46e5dd7070Spatrick /// \endcode 47e5dd7070Spatrick CMK_At = 1 48e5dd7070Spatrick }; 49e5dd7070Spatrick 50e5dd7070Spatrick /// Any part of the comment. 51e5dd7070Spatrick /// Abstract class. 52e5dd7070Spatrick class Comment { 53e5dd7070Spatrick protected: 54e5dd7070Spatrick /// Preferred location to show caret. 55e5dd7070Spatrick SourceLocation Loc; 56e5dd7070Spatrick 57e5dd7070Spatrick /// Source range of this AST node. 58e5dd7070Spatrick SourceRange Range; 59e5dd7070Spatrick 60e5dd7070Spatrick class CommentBitfields { 61e5dd7070Spatrick friend class Comment; 62e5dd7070Spatrick 63e5dd7070Spatrick /// Type of this AST node. 64e5dd7070Spatrick unsigned Kind : 8; 65e5dd7070Spatrick }; 66e5dd7070Spatrick enum { NumCommentBits = 8 }; 67e5dd7070Spatrick 68e5dd7070Spatrick class InlineContentCommentBitfields { 69e5dd7070Spatrick friend class InlineContentComment; 70e5dd7070Spatrick 71e5dd7070Spatrick unsigned : NumCommentBits; 72e5dd7070Spatrick 73e5dd7070Spatrick /// True if there is a newline after this inline content node. 74e5dd7070Spatrick /// (There is no separate AST node for a newline.) 75e5dd7070Spatrick unsigned HasTrailingNewline : 1; 76e5dd7070Spatrick }; 77e5dd7070Spatrick enum { NumInlineContentCommentBits = NumCommentBits + 1 }; 78e5dd7070Spatrick 79e5dd7070Spatrick class TextCommentBitfields { 80e5dd7070Spatrick friend class TextComment; 81e5dd7070Spatrick 82e5dd7070Spatrick unsigned : NumInlineContentCommentBits; 83e5dd7070Spatrick 84e5dd7070Spatrick /// True if \c IsWhitespace field contains a valid value. 85e5dd7070Spatrick mutable unsigned IsWhitespaceValid : 1; 86e5dd7070Spatrick 87e5dd7070Spatrick /// True if this comment AST node contains only whitespace. 88e5dd7070Spatrick mutable unsigned IsWhitespace : 1; 89e5dd7070Spatrick }; 90e5dd7070Spatrick enum { NumTextCommentBits = NumInlineContentCommentBits + 2 }; 91e5dd7070Spatrick 92e5dd7070Spatrick class InlineCommandCommentBitfields { 93e5dd7070Spatrick friend class InlineCommandComment; 94e5dd7070Spatrick 95e5dd7070Spatrick unsigned : NumInlineContentCommentBits; 96e5dd7070Spatrick 97e5dd7070Spatrick unsigned RenderKind : 3; 98e5dd7070Spatrick 99e5dd7070Spatrick unsigned CommandID : CommandInfo::NumCommandIDBits; 100e5dd7070Spatrick }; 101e5dd7070Spatrick enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 3 + 102e5dd7070Spatrick CommandInfo::NumCommandIDBits }; 103e5dd7070Spatrick 104e5dd7070Spatrick class HTMLTagCommentBitfields { 105e5dd7070Spatrick friend class HTMLTagComment; 106e5dd7070Spatrick 107e5dd7070Spatrick unsigned : NumInlineContentCommentBits; 108e5dd7070Spatrick 109e5dd7070Spatrick /// True if we found that this tag is malformed in some way. 110e5dd7070Spatrick unsigned IsMalformed : 1; 111e5dd7070Spatrick }; 112e5dd7070Spatrick enum { NumHTMLTagCommentBits = NumInlineContentCommentBits + 1 }; 113e5dd7070Spatrick 114e5dd7070Spatrick class HTMLStartTagCommentBitfields { 115e5dd7070Spatrick friend class HTMLStartTagComment; 116e5dd7070Spatrick 117e5dd7070Spatrick unsigned : NumHTMLTagCommentBits; 118e5dd7070Spatrick 119e5dd7070Spatrick /// True if this tag is self-closing (e. g., <br />). This is based on tag 120e5dd7070Spatrick /// spelling in comment (plain <br> would not set this flag). 121e5dd7070Spatrick unsigned IsSelfClosing : 1; 122e5dd7070Spatrick }; 123e5dd7070Spatrick enum { NumHTMLStartTagCommentBits = NumHTMLTagCommentBits + 1 }; 124e5dd7070Spatrick 125e5dd7070Spatrick class ParagraphCommentBitfields { 126e5dd7070Spatrick friend class ParagraphComment; 127e5dd7070Spatrick 128e5dd7070Spatrick unsigned : NumCommentBits; 129e5dd7070Spatrick 130e5dd7070Spatrick /// True if \c IsWhitespace field contains a valid value. 131e5dd7070Spatrick mutable unsigned IsWhitespaceValid : 1; 132e5dd7070Spatrick 133e5dd7070Spatrick /// True if this comment AST node contains only whitespace. 134e5dd7070Spatrick mutable unsigned IsWhitespace : 1; 135e5dd7070Spatrick }; 136e5dd7070Spatrick enum { NumParagraphCommentBits = NumCommentBits + 2 }; 137e5dd7070Spatrick 138e5dd7070Spatrick class BlockCommandCommentBitfields { 139e5dd7070Spatrick friend class BlockCommandComment; 140e5dd7070Spatrick 141e5dd7070Spatrick unsigned : NumCommentBits; 142e5dd7070Spatrick 143e5dd7070Spatrick unsigned CommandID : CommandInfo::NumCommandIDBits; 144e5dd7070Spatrick 145e5dd7070Spatrick /// Describes the syntax that was used in a documentation command. 146e5dd7070Spatrick /// Contains values from CommandMarkerKind enum. 147e5dd7070Spatrick unsigned CommandMarker : 1; 148e5dd7070Spatrick }; 149e5dd7070Spatrick enum { NumBlockCommandCommentBits = NumCommentBits + 150e5dd7070Spatrick CommandInfo::NumCommandIDBits + 1 }; 151e5dd7070Spatrick 152e5dd7070Spatrick class ParamCommandCommentBitfields { 153e5dd7070Spatrick friend class ParamCommandComment; 154e5dd7070Spatrick 155e5dd7070Spatrick unsigned : NumBlockCommandCommentBits; 156e5dd7070Spatrick 157e5dd7070Spatrick /// Parameter passing direction, see ParamCommandComment::PassDirection. 158e5dd7070Spatrick unsigned Direction : 2; 159e5dd7070Spatrick 160e5dd7070Spatrick /// True if direction was specified explicitly in the comment. 161e5dd7070Spatrick unsigned IsDirectionExplicit : 1; 162e5dd7070Spatrick }; 163e5dd7070Spatrick enum { NumParamCommandCommentBits = NumBlockCommandCommentBits + 3 }; 164e5dd7070Spatrick 165e5dd7070Spatrick union { 166e5dd7070Spatrick CommentBitfields CommentBits; 167e5dd7070Spatrick InlineContentCommentBitfields InlineContentCommentBits; 168e5dd7070Spatrick TextCommentBitfields TextCommentBits; 169e5dd7070Spatrick InlineCommandCommentBitfields InlineCommandCommentBits; 170e5dd7070Spatrick HTMLTagCommentBitfields HTMLTagCommentBits; 171e5dd7070Spatrick HTMLStartTagCommentBitfields HTMLStartTagCommentBits; 172e5dd7070Spatrick ParagraphCommentBitfields ParagraphCommentBits; 173e5dd7070Spatrick BlockCommandCommentBitfields BlockCommandCommentBits; 174e5dd7070Spatrick ParamCommandCommentBitfields ParamCommandCommentBits; 175e5dd7070Spatrick }; 176e5dd7070Spatrick setSourceRange(SourceRange SR)177e5dd7070Spatrick void setSourceRange(SourceRange SR) { 178e5dd7070Spatrick Range = SR; 179e5dd7070Spatrick } 180e5dd7070Spatrick setLocation(SourceLocation L)181e5dd7070Spatrick void setLocation(SourceLocation L) { 182e5dd7070Spatrick Loc = L; 183e5dd7070Spatrick } 184e5dd7070Spatrick 185e5dd7070Spatrick public: 186e5dd7070Spatrick enum CommentKind { 187e5dd7070Spatrick NoCommentKind = 0, 188e5dd7070Spatrick #define COMMENT(CLASS, PARENT) CLASS##Kind, 189e5dd7070Spatrick #define COMMENT_RANGE(BASE, FIRST, LAST) \ 190e5dd7070Spatrick First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind, 191e5dd7070Spatrick #define LAST_COMMENT_RANGE(BASE, FIRST, LAST) \ 192e5dd7070Spatrick First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind 193e5dd7070Spatrick #define ABSTRACT_COMMENT(COMMENT) 194e5dd7070Spatrick #include "clang/AST/CommentNodes.inc" 195e5dd7070Spatrick }; 196e5dd7070Spatrick 197*12c85518Srobert struct Argument { 198*12c85518Srobert SourceRange Range; 199*12c85518Srobert StringRef Text; 200*12c85518Srobert }; 201*12c85518Srobert Comment(CommentKind K,SourceLocation LocBegin,SourceLocation LocEnd)202e5dd7070Spatrick Comment(CommentKind K, 203e5dd7070Spatrick SourceLocation LocBegin, 204e5dd7070Spatrick SourceLocation LocEnd) : 205e5dd7070Spatrick Loc(LocBegin), Range(SourceRange(LocBegin, LocEnd)) { 206e5dd7070Spatrick CommentBits.Kind = K; 207e5dd7070Spatrick } 208e5dd7070Spatrick getCommentKind()209e5dd7070Spatrick CommentKind getCommentKind() const { 210e5dd7070Spatrick return static_cast<CommentKind>(CommentBits.Kind); 211e5dd7070Spatrick } 212e5dd7070Spatrick 213e5dd7070Spatrick const char *getCommentKindName() const; 214e5dd7070Spatrick 215e5dd7070Spatrick void dump() const; 216e5dd7070Spatrick void dumpColor() const; 217ec727ea7Spatrick void dump(raw_ostream &OS, const ASTContext &Context) const; 218e5dd7070Spatrick getSourceRange()219e5dd7070Spatrick SourceRange getSourceRange() const LLVM_READONLY { return Range; } 220e5dd7070Spatrick getBeginLoc()221e5dd7070Spatrick SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } 222e5dd7070Spatrick getEndLoc()223e5dd7070Spatrick SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); } 224e5dd7070Spatrick getLocation()225e5dd7070Spatrick SourceLocation getLocation() const LLVM_READONLY { return Loc; } 226e5dd7070Spatrick 227e5dd7070Spatrick typedef Comment * const *child_iterator; 228e5dd7070Spatrick 229e5dd7070Spatrick child_iterator child_begin() const; 230e5dd7070Spatrick child_iterator child_end() const; 231e5dd7070Spatrick 232e5dd7070Spatrick // TODO: const child iterator 233e5dd7070Spatrick child_count()234e5dd7070Spatrick unsigned child_count() const { 235e5dd7070Spatrick return child_end() - child_begin(); 236e5dd7070Spatrick } 237e5dd7070Spatrick }; 238e5dd7070Spatrick 239e5dd7070Spatrick /// Inline content (contained within a block). 240e5dd7070Spatrick /// Abstract class. 241e5dd7070Spatrick class InlineContentComment : public Comment { 242e5dd7070Spatrick protected: InlineContentComment(CommentKind K,SourceLocation LocBegin,SourceLocation LocEnd)243e5dd7070Spatrick InlineContentComment(CommentKind K, 244e5dd7070Spatrick SourceLocation LocBegin, 245e5dd7070Spatrick SourceLocation LocEnd) : 246e5dd7070Spatrick Comment(K, LocBegin, LocEnd) { 247e5dd7070Spatrick InlineContentCommentBits.HasTrailingNewline = 0; 248e5dd7070Spatrick } 249e5dd7070Spatrick 250e5dd7070Spatrick public: classof(const Comment * C)251e5dd7070Spatrick static bool classof(const Comment *C) { 252e5dd7070Spatrick return C->getCommentKind() >= FirstInlineContentCommentConstant && 253e5dd7070Spatrick C->getCommentKind() <= LastInlineContentCommentConstant; 254e5dd7070Spatrick } 255e5dd7070Spatrick addTrailingNewline()256e5dd7070Spatrick void addTrailingNewline() { 257e5dd7070Spatrick InlineContentCommentBits.HasTrailingNewline = 1; 258e5dd7070Spatrick } 259e5dd7070Spatrick hasTrailingNewline()260e5dd7070Spatrick bool hasTrailingNewline() const { 261e5dd7070Spatrick return InlineContentCommentBits.HasTrailingNewline; 262e5dd7070Spatrick } 263e5dd7070Spatrick }; 264e5dd7070Spatrick 265e5dd7070Spatrick /// Plain text. 266e5dd7070Spatrick class TextComment : public InlineContentComment { 267e5dd7070Spatrick StringRef Text; 268e5dd7070Spatrick 269e5dd7070Spatrick public: TextComment(SourceLocation LocBegin,SourceLocation LocEnd,StringRef Text)270e5dd7070Spatrick TextComment(SourceLocation LocBegin, 271e5dd7070Spatrick SourceLocation LocEnd, 272e5dd7070Spatrick StringRef Text) : 273e5dd7070Spatrick InlineContentComment(TextCommentKind, LocBegin, LocEnd), 274e5dd7070Spatrick Text(Text) { 275e5dd7070Spatrick TextCommentBits.IsWhitespaceValid = false; 276e5dd7070Spatrick } 277e5dd7070Spatrick classof(const Comment * C)278e5dd7070Spatrick static bool classof(const Comment *C) { 279e5dd7070Spatrick return C->getCommentKind() == TextCommentKind; 280e5dd7070Spatrick } 281e5dd7070Spatrick child_begin()282e5dd7070Spatrick child_iterator child_begin() const { return nullptr; } 283e5dd7070Spatrick child_end()284e5dd7070Spatrick child_iterator child_end() const { return nullptr; } 285e5dd7070Spatrick getText()286e5dd7070Spatrick StringRef getText() const LLVM_READONLY { return Text; } 287e5dd7070Spatrick isWhitespace()288e5dd7070Spatrick bool isWhitespace() const { 289e5dd7070Spatrick if (TextCommentBits.IsWhitespaceValid) 290e5dd7070Spatrick return TextCommentBits.IsWhitespace; 291e5dd7070Spatrick 292e5dd7070Spatrick TextCommentBits.IsWhitespace = isWhitespaceNoCache(); 293e5dd7070Spatrick TextCommentBits.IsWhitespaceValid = true; 294e5dd7070Spatrick return TextCommentBits.IsWhitespace; 295e5dd7070Spatrick } 296e5dd7070Spatrick 297e5dd7070Spatrick private: 298e5dd7070Spatrick bool isWhitespaceNoCache() const; 299e5dd7070Spatrick }; 300e5dd7070Spatrick 301e5dd7070Spatrick /// A command with word-like arguments that is considered inline content. 302e5dd7070Spatrick class InlineCommandComment : public InlineContentComment { 303e5dd7070Spatrick public: 304e5dd7070Spatrick /// The most appropriate rendering mode for this command, chosen on command 305e5dd7070Spatrick /// semantics in Doxygen. 306e5dd7070Spatrick enum RenderKind { 307e5dd7070Spatrick RenderNormal, 308e5dd7070Spatrick RenderBold, 309e5dd7070Spatrick RenderMonospaced, 310e5dd7070Spatrick RenderEmphasized, 311e5dd7070Spatrick RenderAnchor 312e5dd7070Spatrick }; 313e5dd7070Spatrick 314e5dd7070Spatrick protected: 315e5dd7070Spatrick /// Command arguments. 316e5dd7070Spatrick ArrayRef<Argument> Args; 317e5dd7070Spatrick 318e5dd7070Spatrick public: InlineCommandComment(SourceLocation LocBegin,SourceLocation LocEnd,unsigned CommandID,RenderKind RK,ArrayRef<Argument> Args)319e5dd7070Spatrick InlineCommandComment(SourceLocation LocBegin, 320e5dd7070Spatrick SourceLocation LocEnd, 321e5dd7070Spatrick unsigned CommandID, 322e5dd7070Spatrick RenderKind RK, 323e5dd7070Spatrick ArrayRef<Argument> Args) : 324e5dd7070Spatrick InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd), 325e5dd7070Spatrick Args(Args) { 326e5dd7070Spatrick InlineCommandCommentBits.RenderKind = RK; 327e5dd7070Spatrick InlineCommandCommentBits.CommandID = CommandID; 328e5dd7070Spatrick } 329e5dd7070Spatrick classof(const Comment * C)330e5dd7070Spatrick static bool classof(const Comment *C) { 331e5dd7070Spatrick return C->getCommentKind() == InlineCommandCommentKind; 332e5dd7070Spatrick } 333e5dd7070Spatrick child_begin()334e5dd7070Spatrick child_iterator child_begin() const { return nullptr; } 335e5dd7070Spatrick child_end()336e5dd7070Spatrick child_iterator child_end() const { return nullptr; } 337e5dd7070Spatrick getCommandID()338e5dd7070Spatrick unsigned getCommandID() const { 339e5dd7070Spatrick return InlineCommandCommentBits.CommandID; 340e5dd7070Spatrick } 341e5dd7070Spatrick getCommandName(const CommandTraits & Traits)342e5dd7070Spatrick StringRef getCommandName(const CommandTraits &Traits) const { 343e5dd7070Spatrick return Traits.getCommandInfo(getCommandID())->Name; 344e5dd7070Spatrick } 345e5dd7070Spatrick getCommandNameRange()346e5dd7070Spatrick SourceRange getCommandNameRange() const { 347e5dd7070Spatrick return SourceRange(getBeginLoc().getLocWithOffset(-1), getEndLoc()); 348e5dd7070Spatrick } 349e5dd7070Spatrick getRenderKind()350e5dd7070Spatrick RenderKind getRenderKind() const { 351e5dd7070Spatrick return static_cast<RenderKind>(InlineCommandCommentBits.RenderKind); 352e5dd7070Spatrick } 353e5dd7070Spatrick getNumArgs()354e5dd7070Spatrick unsigned getNumArgs() const { 355e5dd7070Spatrick return Args.size(); 356e5dd7070Spatrick } 357e5dd7070Spatrick getArgText(unsigned Idx)358e5dd7070Spatrick StringRef getArgText(unsigned Idx) const { 359e5dd7070Spatrick return Args[Idx].Text; 360e5dd7070Spatrick } 361e5dd7070Spatrick getArgRange(unsigned Idx)362e5dd7070Spatrick SourceRange getArgRange(unsigned Idx) const { 363e5dd7070Spatrick return Args[Idx].Range; 364e5dd7070Spatrick } 365e5dd7070Spatrick }; 366e5dd7070Spatrick 367e5dd7070Spatrick /// Abstract class for opening and closing HTML tags. HTML tags are always 368e5dd7070Spatrick /// treated as inline content (regardless HTML semantics). 369e5dd7070Spatrick class HTMLTagComment : public InlineContentComment { 370e5dd7070Spatrick protected: 371e5dd7070Spatrick StringRef TagName; 372e5dd7070Spatrick SourceRange TagNameRange; 373e5dd7070Spatrick HTMLTagComment(CommentKind K,SourceLocation LocBegin,SourceLocation LocEnd,StringRef TagName,SourceLocation TagNameBegin,SourceLocation TagNameEnd)374e5dd7070Spatrick HTMLTagComment(CommentKind K, 375e5dd7070Spatrick SourceLocation LocBegin, 376e5dd7070Spatrick SourceLocation LocEnd, 377e5dd7070Spatrick StringRef TagName, 378e5dd7070Spatrick SourceLocation TagNameBegin, 379e5dd7070Spatrick SourceLocation TagNameEnd) : 380e5dd7070Spatrick InlineContentComment(K, LocBegin, LocEnd), 381e5dd7070Spatrick TagName(TagName), 382e5dd7070Spatrick TagNameRange(TagNameBegin, TagNameEnd) { 383e5dd7070Spatrick setLocation(TagNameBegin); 384e5dd7070Spatrick HTMLTagCommentBits.IsMalformed = 0; 385e5dd7070Spatrick } 386e5dd7070Spatrick 387e5dd7070Spatrick public: classof(const Comment * C)388e5dd7070Spatrick static bool classof(const Comment *C) { 389e5dd7070Spatrick return C->getCommentKind() >= FirstHTMLTagCommentConstant && 390e5dd7070Spatrick C->getCommentKind() <= LastHTMLTagCommentConstant; 391e5dd7070Spatrick } 392e5dd7070Spatrick getTagName()393e5dd7070Spatrick StringRef getTagName() const LLVM_READONLY { return TagName; } 394e5dd7070Spatrick getTagNameSourceRange()395e5dd7070Spatrick SourceRange getTagNameSourceRange() const LLVM_READONLY { 396e5dd7070Spatrick SourceLocation L = getLocation(); 397e5dd7070Spatrick return SourceRange(L.getLocWithOffset(1), 398e5dd7070Spatrick L.getLocWithOffset(1 + TagName.size())); 399e5dd7070Spatrick } 400e5dd7070Spatrick isMalformed()401e5dd7070Spatrick bool isMalformed() const { 402e5dd7070Spatrick return HTMLTagCommentBits.IsMalformed; 403e5dd7070Spatrick } 404e5dd7070Spatrick setIsMalformed()405e5dd7070Spatrick void setIsMalformed() { 406e5dd7070Spatrick HTMLTagCommentBits.IsMalformed = 1; 407e5dd7070Spatrick } 408e5dd7070Spatrick }; 409e5dd7070Spatrick 410e5dd7070Spatrick /// An opening HTML tag with attributes. 411e5dd7070Spatrick class HTMLStartTagComment : public HTMLTagComment { 412e5dd7070Spatrick public: 413e5dd7070Spatrick class Attribute { 414e5dd7070Spatrick public: 415e5dd7070Spatrick SourceLocation NameLocBegin; 416e5dd7070Spatrick StringRef Name; 417e5dd7070Spatrick 418e5dd7070Spatrick SourceLocation EqualsLoc; 419e5dd7070Spatrick 420e5dd7070Spatrick SourceRange ValueRange; 421e5dd7070Spatrick StringRef Value; 422e5dd7070Spatrick Attribute()423e5dd7070Spatrick Attribute() { } 424e5dd7070Spatrick Attribute(SourceLocation NameLocBegin,StringRef Name)425*12c85518Srobert Attribute(SourceLocation NameLocBegin, StringRef Name) 426*12c85518Srobert : NameLocBegin(NameLocBegin), Name(Name), EqualsLoc(SourceLocation()) {} 427e5dd7070Spatrick Attribute(SourceLocation NameLocBegin,StringRef Name,SourceLocation EqualsLoc,SourceRange ValueRange,StringRef Value)428e5dd7070Spatrick Attribute(SourceLocation NameLocBegin, StringRef Name, 429*12c85518Srobert SourceLocation EqualsLoc, SourceRange ValueRange, StringRef Value) 430*12c85518Srobert : NameLocBegin(NameLocBegin), Name(Name), EqualsLoc(EqualsLoc), 431*12c85518Srobert ValueRange(ValueRange), Value(Value) {} 432e5dd7070Spatrick getNameLocEnd()433e5dd7070Spatrick SourceLocation getNameLocEnd() const { 434e5dd7070Spatrick return NameLocBegin.getLocWithOffset(Name.size()); 435e5dd7070Spatrick } 436e5dd7070Spatrick getNameRange()437e5dd7070Spatrick SourceRange getNameRange() const { 438e5dd7070Spatrick return SourceRange(NameLocBegin, getNameLocEnd()); 439e5dd7070Spatrick } 440e5dd7070Spatrick }; 441e5dd7070Spatrick 442e5dd7070Spatrick private: 443e5dd7070Spatrick ArrayRef<Attribute> Attributes; 444e5dd7070Spatrick 445e5dd7070Spatrick public: HTMLStartTagComment(SourceLocation LocBegin,StringRef TagName)446e5dd7070Spatrick HTMLStartTagComment(SourceLocation LocBegin, 447e5dd7070Spatrick StringRef TagName) : 448e5dd7070Spatrick HTMLTagComment(HTMLStartTagCommentKind, 449e5dd7070Spatrick LocBegin, LocBegin.getLocWithOffset(1 + TagName.size()), 450e5dd7070Spatrick TagName, 451e5dd7070Spatrick LocBegin.getLocWithOffset(1), 452e5dd7070Spatrick LocBegin.getLocWithOffset(1 + TagName.size())) { 453e5dd7070Spatrick HTMLStartTagCommentBits.IsSelfClosing = false; 454e5dd7070Spatrick } 455e5dd7070Spatrick classof(const Comment * C)456e5dd7070Spatrick static bool classof(const Comment *C) { 457e5dd7070Spatrick return C->getCommentKind() == HTMLStartTagCommentKind; 458e5dd7070Spatrick } 459e5dd7070Spatrick child_begin()460e5dd7070Spatrick child_iterator child_begin() const { return nullptr; } 461e5dd7070Spatrick child_end()462e5dd7070Spatrick child_iterator child_end() const { return nullptr; } 463e5dd7070Spatrick getNumAttrs()464e5dd7070Spatrick unsigned getNumAttrs() const { 465e5dd7070Spatrick return Attributes.size(); 466e5dd7070Spatrick } 467e5dd7070Spatrick getAttr(unsigned Idx)468e5dd7070Spatrick const Attribute &getAttr(unsigned Idx) const { 469e5dd7070Spatrick return Attributes[Idx]; 470e5dd7070Spatrick } 471e5dd7070Spatrick setAttrs(ArrayRef<Attribute> Attrs)472e5dd7070Spatrick void setAttrs(ArrayRef<Attribute> Attrs) { 473e5dd7070Spatrick Attributes = Attrs; 474e5dd7070Spatrick if (!Attrs.empty()) { 475e5dd7070Spatrick const Attribute &Attr = Attrs.back(); 476e5dd7070Spatrick SourceLocation L = Attr.ValueRange.getEnd(); 477e5dd7070Spatrick if (L.isValid()) 478e5dd7070Spatrick Range.setEnd(L); 479e5dd7070Spatrick else { 480e5dd7070Spatrick Range.setEnd(Attr.getNameLocEnd()); 481e5dd7070Spatrick } 482e5dd7070Spatrick } 483e5dd7070Spatrick } 484e5dd7070Spatrick setGreaterLoc(SourceLocation GreaterLoc)485e5dd7070Spatrick void setGreaterLoc(SourceLocation GreaterLoc) { 486e5dd7070Spatrick Range.setEnd(GreaterLoc); 487e5dd7070Spatrick } 488e5dd7070Spatrick isSelfClosing()489e5dd7070Spatrick bool isSelfClosing() const { 490e5dd7070Spatrick return HTMLStartTagCommentBits.IsSelfClosing; 491e5dd7070Spatrick } 492e5dd7070Spatrick setSelfClosing()493e5dd7070Spatrick void setSelfClosing() { 494e5dd7070Spatrick HTMLStartTagCommentBits.IsSelfClosing = true; 495e5dd7070Spatrick } 496e5dd7070Spatrick }; 497e5dd7070Spatrick 498e5dd7070Spatrick /// A closing HTML tag. 499e5dd7070Spatrick class HTMLEndTagComment : public HTMLTagComment { 500e5dd7070Spatrick public: HTMLEndTagComment(SourceLocation LocBegin,SourceLocation LocEnd,StringRef TagName)501e5dd7070Spatrick HTMLEndTagComment(SourceLocation LocBegin, 502e5dd7070Spatrick SourceLocation LocEnd, 503e5dd7070Spatrick StringRef TagName) : 504e5dd7070Spatrick HTMLTagComment(HTMLEndTagCommentKind, 505e5dd7070Spatrick LocBegin, LocEnd, 506e5dd7070Spatrick TagName, 507e5dd7070Spatrick LocBegin.getLocWithOffset(2), 508e5dd7070Spatrick LocBegin.getLocWithOffset(2 + TagName.size())) 509e5dd7070Spatrick { } 510e5dd7070Spatrick classof(const Comment * C)511e5dd7070Spatrick static bool classof(const Comment *C) { 512e5dd7070Spatrick return C->getCommentKind() == HTMLEndTagCommentKind; 513e5dd7070Spatrick } 514e5dd7070Spatrick child_begin()515e5dd7070Spatrick child_iterator child_begin() const { return nullptr; } 516e5dd7070Spatrick child_end()517e5dd7070Spatrick child_iterator child_end() const { return nullptr; } 518e5dd7070Spatrick }; 519e5dd7070Spatrick 520e5dd7070Spatrick /// Block content (contains inline content). 521e5dd7070Spatrick /// Abstract class. 522e5dd7070Spatrick class BlockContentComment : public Comment { 523e5dd7070Spatrick protected: BlockContentComment(CommentKind K,SourceLocation LocBegin,SourceLocation LocEnd)524e5dd7070Spatrick BlockContentComment(CommentKind K, 525e5dd7070Spatrick SourceLocation LocBegin, 526e5dd7070Spatrick SourceLocation LocEnd) : 527e5dd7070Spatrick Comment(K, LocBegin, LocEnd) 528e5dd7070Spatrick { } 529e5dd7070Spatrick 530e5dd7070Spatrick public: classof(const Comment * C)531e5dd7070Spatrick static bool classof(const Comment *C) { 532e5dd7070Spatrick return C->getCommentKind() >= FirstBlockContentCommentConstant && 533e5dd7070Spatrick C->getCommentKind() <= LastBlockContentCommentConstant; 534e5dd7070Spatrick } 535e5dd7070Spatrick }; 536e5dd7070Spatrick 537e5dd7070Spatrick /// A single paragraph that contains inline content. 538e5dd7070Spatrick class ParagraphComment : public BlockContentComment { 539e5dd7070Spatrick ArrayRef<InlineContentComment *> Content; 540e5dd7070Spatrick 541e5dd7070Spatrick public: ParagraphComment(ArrayRef<InlineContentComment * > Content)542e5dd7070Spatrick ParagraphComment(ArrayRef<InlineContentComment *> Content) : 543e5dd7070Spatrick BlockContentComment(ParagraphCommentKind, 544e5dd7070Spatrick SourceLocation(), 545e5dd7070Spatrick SourceLocation()), 546e5dd7070Spatrick Content(Content) { 547e5dd7070Spatrick if (Content.empty()) { 548e5dd7070Spatrick ParagraphCommentBits.IsWhitespace = true; 549e5dd7070Spatrick ParagraphCommentBits.IsWhitespaceValid = true; 550e5dd7070Spatrick return; 551e5dd7070Spatrick } 552e5dd7070Spatrick 553e5dd7070Spatrick ParagraphCommentBits.IsWhitespaceValid = false; 554e5dd7070Spatrick 555e5dd7070Spatrick setSourceRange(SourceRange(Content.front()->getBeginLoc(), 556e5dd7070Spatrick Content.back()->getEndLoc())); 557e5dd7070Spatrick setLocation(Content.front()->getBeginLoc()); 558e5dd7070Spatrick } 559e5dd7070Spatrick classof(const Comment * C)560e5dd7070Spatrick static bool classof(const Comment *C) { 561e5dd7070Spatrick return C->getCommentKind() == ParagraphCommentKind; 562e5dd7070Spatrick } 563e5dd7070Spatrick child_begin()564e5dd7070Spatrick child_iterator child_begin() const { 565e5dd7070Spatrick return reinterpret_cast<child_iterator>(Content.begin()); 566e5dd7070Spatrick } 567e5dd7070Spatrick child_end()568e5dd7070Spatrick child_iterator child_end() const { 569e5dd7070Spatrick return reinterpret_cast<child_iterator>(Content.end()); 570e5dd7070Spatrick } 571e5dd7070Spatrick isWhitespace()572e5dd7070Spatrick bool isWhitespace() const { 573e5dd7070Spatrick if (ParagraphCommentBits.IsWhitespaceValid) 574e5dd7070Spatrick return ParagraphCommentBits.IsWhitespace; 575e5dd7070Spatrick 576e5dd7070Spatrick ParagraphCommentBits.IsWhitespace = isWhitespaceNoCache(); 577e5dd7070Spatrick ParagraphCommentBits.IsWhitespaceValid = true; 578e5dd7070Spatrick return ParagraphCommentBits.IsWhitespace; 579e5dd7070Spatrick } 580e5dd7070Spatrick 581e5dd7070Spatrick private: 582e5dd7070Spatrick bool isWhitespaceNoCache() const; 583e5dd7070Spatrick }; 584e5dd7070Spatrick 585e5dd7070Spatrick /// A command that has zero or more word-like arguments (number of word-like 586e5dd7070Spatrick /// arguments depends on command name) and a paragraph as an argument 587e5dd7070Spatrick /// (e. g., \\brief). 588e5dd7070Spatrick class BlockCommandComment : public BlockContentComment { 589e5dd7070Spatrick protected: 590e5dd7070Spatrick /// Word-like arguments. 591e5dd7070Spatrick ArrayRef<Argument> Args; 592e5dd7070Spatrick 593e5dd7070Spatrick /// Paragraph argument. 594e5dd7070Spatrick ParagraphComment *Paragraph; 595e5dd7070Spatrick BlockCommandComment(CommentKind K,SourceLocation LocBegin,SourceLocation LocEnd,unsigned CommandID,CommandMarkerKind CommandMarker)596e5dd7070Spatrick BlockCommandComment(CommentKind K, 597e5dd7070Spatrick SourceLocation LocBegin, 598e5dd7070Spatrick SourceLocation LocEnd, 599e5dd7070Spatrick unsigned CommandID, 600e5dd7070Spatrick CommandMarkerKind CommandMarker) : 601e5dd7070Spatrick BlockContentComment(K, LocBegin, LocEnd), 602e5dd7070Spatrick Paragraph(nullptr) { 603e5dd7070Spatrick setLocation(getCommandNameBeginLoc()); 604e5dd7070Spatrick BlockCommandCommentBits.CommandID = CommandID; 605e5dd7070Spatrick BlockCommandCommentBits.CommandMarker = CommandMarker; 606e5dd7070Spatrick } 607e5dd7070Spatrick 608e5dd7070Spatrick public: BlockCommandComment(SourceLocation LocBegin,SourceLocation LocEnd,unsigned CommandID,CommandMarkerKind CommandMarker)609e5dd7070Spatrick BlockCommandComment(SourceLocation LocBegin, 610e5dd7070Spatrick SourceLocation LocEnd, 611e5dd7070Spatrick unsigned CommandID, 612e5dd7070Spatrick CommandMarkerKind CommandMarker) : 613e5dd7070Spatrick BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd), 614e5dd7070Spatrick Paragraph(nullptr) { 615e5dd7070Spatrick setLocation(getCommandNameBeginLoc()); 616e5dd7070Spatrick BlockCommandCommentBits.CommandID = CommandID; 617e5dd7070Spatrick BlockCommandCommentBits.CommandMarker = CommandMarker; 618e5dd7070Spatrick } 619e5dd7070Spatrick classof(const Comment * C)620e5dd7070Spatrick static bool classof(const Comment *C) { 621e5dd7070Spatrick return C->getCommentKind() >= FirstBlockCommandCommentConstant && 622e5dd7070Spatrick C->getCommentKind() <= LastBlockCommandCommentConstant; 623e5dd7070Spatrick } 624e5dd7070Spatrick child_begin()625e5dd7070Spatrick child_iterator child_begin() const { 626e5dd7070Spatrick return reinterpret_cast<child_iterator>(&Paragraph); 627e5dd7070Spatrick } 628e5dd7070Spatrick child_end()629e5dd7070Spatrick child_iterator child_end() const { 630e5dd7070Spatrick return reinterpret_cast<child_iterator>(&Paragraph + 1); 631e5dd7070Spatrick } 632e5dd7070Spatrick getCommandID()633e5dd7070Spatrick unsigned getCommandID() const { 634e5dd7070Spatrick return BlockCommandCommentBits.CommandID; 635e5dd7070Spatrick } 636e5dd7070Spatrick getCommandName(const CommandTraits & Traits)637e5dd7070Spatrick StringRef getCommandName(const CommandTraits &Traits) const { 638e5dd7070Spatrick return Traits.getCommandInfo(getCommandID())->Name; 639e5dd7070Spatrick } 640e5dd7070Spatrick getCommandNameBeginLoc()641e5dd7070Spatrick SourceLocation getCommandNameBeginLoc() const { 642e5dd7070Spatrick return getBeginLoc().getLocWithOffset(1); 643e5dd7070Spatrick } 644e5dd7070Spatrick getCommandNameRange(const CommandTraits & Traits)645e5dd7070Spatrick SourceRange getCommandNameRange(const CommandTraits &Traits) const { 646e5dd7070Spatrick StringRef Name = getCommandName(Traits); 647e5dd7070Spatrick return SourceRange(getCommandNameBeginLoc(), 648e5dd7070Spatrick getBeginLoc().getLocWithOffset(1 + Name.size())); 649e5dd7070Spatrick } 650e5dd7070Spatrick getNumArgs()651e5dd7070Spatrick unsigned getNumArgs() const { 652e5dd7070Spatrick return Args.size(); 653e5dd7070Spatrick } 654e5dd7070Spatrick getArgText(unsigned Idx)655e5dd7070Spatrick StringRef getArgText(unsigned Idx) const { 656e5dd7070Spatrick return Args[Idx].Text; 657e5dd7070Spatrick } 658e5dd7070Spatrick getArgRange(unsigned Idx)659e5dd7070Spatrick SourceRange getArgRange(unsigned Idx) const { 660e5dd7070Spatrick return Args[Idx].Range; 661e5dd7070Spatrick } 662e5dd7070Spatrick setArgs(ArrayRef<Argument> A)663e5dd7070Spatrick void setArgs(ArrayRef<Argument> A) { 664e5dd7070Spatrick Args = A; 665e5dd7070Spatrick if (Args.size() > 0) { 666e5dd7070Spatrick SourceLocation NewLocEnd = Args.back().Range.getEnd(); 667e5dd7070Spatrick if (NewLocEnd.isValid()) 668e5dd7070Spatrick setSourceRange(SourceRange(getBeginLoc(), NewLocEnd)); 669e5dd7070Spatrick } 670e5dd7070Spatrick } 671e5dd7070Spatrick getParagraph()672e5dd7070Spatrick ParagraphComment *getParagraph() const LLVM_READONLY { 673e5dd7070Spatrick return Paragraph; 674e5dd7070Spatrick } 675e5dd7070Spatrick hasNonWhitespaceParagraph()676e5dd7070Spatrick bool hasNonWhitespaceParagraph() const { 677e5dd7070Spatrick return Paragraph && !Paragraph->isWhitespace(); 678e5dd7070Spatrick } 679e5dd7070Spatrick setParagraph(ParagraphComment * PC)680e5dd7070Spatrick void setParagraph(ParagraphComment *PC) { 681e5dd7070Spatrick Paragraph = PC; 682e5dd7070Spatrick SourceLocation NewLocEnd = PC->getEndLoc(); 683e5dd7070Spatrick if (NewLocEnd.isValid()) 684e5dd7070Spatrick setSourceRange(SourceRange(getBeginLoc(), NewLocEnd)); 685e5dd7070Spatrick } 686e5dd7070Spatrick getCommandMarker()687e5dd7070Spatrick CommandMarkerKind getCommandMarker() const LLVM_READONLY { 688e5dd7070Spatrick return static_cast<CommandMarkerKind>( 689e5dd7070Spatrick BlockCommandCommentBits.CommandMarker); 690e5dd7070Spatrick } 691e5dd7070Spatrick }; 692e5dd7070Spatrick 693e5dd7070Spatrick /// Doxygen \\param command. 694e5dd7070Spatrick class ParamCommandComment : public BlockCommandComment { 695e5dd7070Spatrick private: 696e5dd7070Spatrick /// Parameter index in the function declaration. 697e5dd7070Spatrick unsigned ParamIndex; 698e5dd7070Spatrick 699e5dd7070Spatrick public: 700e5dd7070Spatrick enum : unsigned { 701e5dd7070Spatrick InvalidParamIndex = ~0U, 702e5dd7070Spatrick VarArgParamIndex = ~0U/*InvalidParamIndex*/ - 1U 703e5dd7070Spatrick }; 704e5dd7070Spatrick ParamCommandComment(SourceLocation LocBegin,SourceLocation LocEnd,unsigned CommandID,CommandMarkerKind CommandMarker)705e5dd7070Spatrick ParamCommandComment(SourceLocation LocBegin, 706e5dd7070Spatrick SourceLocation LocEnd, 707e5dd7070Spatrick unsigned CommandID, 708e5dd7070Spatrick CommandMarkerKind CommandMarker) : 709e5dd7070Spatrick BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd, 710e5dd7070Spatrick CommandID, CommandMarker), 711e5dd7070Spatrick ParamIndex(InvalidParamIndex) { 712e5dd7070Spatrick ParamCommandCommentBits.Direction = In; 713e5dd7070Spatrick ParamCommandCommentBits.IsDirectionExplicit = false; 714e5dd7070Spatrick } 715e5dd7070Spatrick classof(const Comment * C)716e5dd7070Spatrick static bool classof(const Comment *C) { 717e5dd7070Spatrick return C->getCommentKind() == ParamCommandCommentKind; 718e5dd7070Spatrick } 719e5dd7070Spatrick 720e5dd7070Spatrick enum PassDirection { 721e5dd7070Spatrick In, 722e5dd7070Spatrick Out, 723e5dd7070Spatrick InOut 724e5dd7070Spatrick }; 725e5dd7070Spatrick 726e5dd7070Spatrick static const char *getDirectionAsString(PassDirection D); 727e5dd7070Spatrick getDirection()728e5dd7070Spatrick PassDirection getDirection() const LLVM_READONLY { 729e5dd7070Spatrick return static_cast<PassDirection>(ParamCommandCommentBits.Direction); 730e5dd7070Spatrick } 731e5dd7070Spatrick isDirectionExplicit()732e5dd7070Spatrick bool isDirectionExplicit() const LLVM_READONLY { 733e5dd7070Spatrick return ParamCommandCommentBits.IsDirectionExplicit; 734e5dd7070Spatrick } 735e5dd7070Spatrick setDirection(PassDirection Direction,bool Explicit)736e5dd7070Spatrick void setDirection(PassDirection Direction, bool Explicit) { 737e5dd7070Spatrick ParamCommandCommentBits.Direction = Direction; 738e5dd7070Spatrick ParamCommandCommentBits.IsDirectionExplicit = Explicit; 739e5dd7070Spatrick } 740e5dd7070Spatrick hasParamName()741e5dd7070Spatrick bool hasParamName() const { 742e5dd7070Spatrick return getNumArgs() > 0; 743e5dd7070Spatrick } 744e5dd7070Spatrick 745e5dd7070Spatrick StringRef getParamName(const FullComment *FC) const; 746e5dd7070Spatrick getParamNameAsWritten()747e5dd7070Spatrick StringRef getParamNameAsWritten() const { 748e5dd7070Spatrick return Args[0].Text; 749e5dd7070Spatrick } 750e5dd7070Spatrick getParamNameRange()751e5dd7070Spatrick SourceRange getParamNameRange() const { 752e5dd7070Spatrick return Args[0].Range; 753e5dd7070Spatrick } 754e5dd7070Spatrick isParamIndexValid()755e5dd7070Spatrick bool isParamIndexValid() const LLVM_READONLY { 756e5dd7070Spatrick return ParamIndex != InvalidParamIndex; 757e5dd7070Spatrick } 758e5dd7070Spatrick isVarArgParam()759e5dd7070Spatrick bool isVarArgParam() const LLVM_READONLY { 760e5dd7070Spatrick return ParamIndex == VarArgParamIndex; 761e5dd7070Spatrick } 762e5dd7070Spatrick setIsVarArgParam()763e5dd7070Spatrick void setIsVarArgParam() { 764e5dd7070Spatrick ParamIndex = VarArgParamIndex; 765e5dd7070Spatrick assert(isParamIndexValid()); 766e5dd7070Spatrick } 767e5dd7070Spatrick getParamIndex()768e5dd7070Spatrick unsigned getParamIndex() const LLVM_READONLY { 769e5dd7070Spatrick assert(isParamIndexValid()); 770e5dd7070Spatrick assert(!isVarArgParam()); 771e5dd7070Spatrick return ParamIndex; 772e5dd7070Spatrick } 773e5dd7070Spatrick setParamIndex(unsigned Index)774e5dd7070Spatrick void setParamIndex(unsigned Index) { 775e5dd7070Spatrick ParamIndex = Index; 776e5dd7070Spatrick assert(isParamIndexValid()); 777e5dd7070Spatrick assert(!isVarArgParam()); 778e5dd7070Spatrick } 779e5dd7070Spatrick }; 780e5dd7070Spatrick 781e5dd7070Spatrick /// Doxygen \\tparam command, describes a template parameter. 782e5dd7070Spatrick class TParamCommandComment : public BlockCommandComment { 783e5dd7070Spatrick private: 784e5dd7070Spatrick /// If this template parameter name was resolved (found in template parameter 785e5dd7070Spatrick /// list), then this stores a list of position indexes in all template 786e5dd7070Spatrick /// parameter lists. 787e5dd7070Spatrick /// 788e5dd7070Spatrick /// For example: 789e5dd7070Spatrick /// \verbatim 790e5dd7070Spatrick /// template<typename C, template<typename T> class TT> 791e5dd7070Spatrick /// void test(TT<int> aaa); 792e5dd7070Spatrick /// \endverbatim 793e5dd7070Spatrick /// For C: Position = { 0 } 794e5dd7070Spatrick /// For TT: Position = { 1 } 795e5dd7070Spatrick /// For T: Position = { 1, 0 } 796e5dd7070Spatrick ArrayRef<unsigned> Position; 797e5dd7070Spatrick 798e5dd7070Spatrick public: TParamCommandComment(SourceLocation LocBegin,SourceLocation LocEnd,unsigned CommandID,CommandMarkerKind CommandMarker)799e5dd7070Spatrick TParamCommandComment(SourceLocation LocBegin, 800e5dd7070Spatrick SourceLocation LocEnd, 801e5dd7070Spatrick unsigned CommandID, 802e5dd7070Spatrick CommandMarkerKind CommandMarker) : 803e5dd7070Spatrick BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, CommandID, 804e5dd7070Spatrick CommandMarker) 805e5dd7070Spatrick { } 806e5dd7070Spatrick classof(const Comment * C)807e5dd7070Spatrick static bool classof(const Comment *C) { 808e5dd7070Spatrick return C->getCommentKind() == TParamCommandCommentKind; 809e5dd7070Spatrick } 810e5dd7070Spatrick hasParamName()811e5dd7070Spatrick bool hasParamName() const { 812e5dd7070Spatrick return getNumArgs() > 0; 813e5dd7070Spatrick } 814e5dd7070Spatrick 815e5dd7070Spatrick StringRef getParamName(const FullComment *FC) const; 816e5dd7070Spatrick getParamNameAsWritten()817e5dd7070Spatrick StringRef getParamNameAsWritten() const { 818e5dd7070Spatrick return Args[0].Text; 819e5dd7070Spatrick } 820e5dd7070Spatrick getParamNameRange()821e5dd7070Spatrick SourceRange getParamNameRange() const { 822e5dd7070Spatrick return Args[0].Range; 823e5dd7070Spatrick } 824e5dd7070Spatrick isPositionValid()825e5dd7070Spatrick bool isPositionValid() const LLVM_READONLY { 826e5dd7070Spatrick return !Position.empty(); 827e5dd7070Spatrick } 828e5dd7070Spatrick getDepth()829e5dd7070Spatrick unsigned getDepth() const { 830e5dd7070Spatrick assert(isPositionValid()); 831e5dd7070Spatrick return Position.size(); 832e5dd7070Spatrick } 833e5dd7070Spatrick getIndex(unsigned Depth)834e5dd7070Spatrick unsigned getIndex(unsigned Depth) const { 835e5dd7070Spatrick assert(isPositionValid()); 836e5dd7070Spatrick return Position[Depth]; 837e5dd7070Spatrick } 838e5dd7070Spatrick setPosition(ArrayRef<unsigned> NewPosition)839e5dd7070Spatrick void setPosition(ArrayRef<unsigned> NewPosition) { 840e5dd7070Spatrick Position = NewPosition; 841e5dd7070Spatrick assert(isPositionValid()); 842e5dd7070Spatrick } 843e5dd7070Spatrick }; 844e5dd7070Spatrick 845e5dd7070Spatrick /// A line of text contained in a verbatim block. 846e5dd7070Spatrick class VerbatimBlockLineComment : public Comment { 847e5dd7070Spatrick StringRef Text; 848e5dd7070Spatrick 849e5dd7070Spatrick public: VerbatimBlockLineComment(SourceLocation LocBegin,StringRef Text)850e5dd7070Spatrick VerbatimBlockLineComment(SourceLocation LocBegin, 851e5dd7070Spatrick StringRef Text) : 852e5dd7070Spatrick Comment(VerbatimBlockLineCommentKind, 853e5dd7070Spatrick LocBegin, 854e5dd7070Spatrick LocBegin.getLocWithOffset(Text.size())), 855e5dd7070Spatrick Text(Text) 856e5dd7070Spatrick { } 857e5dd7070Spatrick classof(const Comment * C)858e5dd7070Spatrick static bool classof(const Comment *C) { 859e5dd7070Spatrick return C->getCommentKind() == VerbatimBlockLineCommentKind; 860e5dd7070Spatrick } 861e5dd7070Spatrick child_begin()862e5dd7070Spatrick child_iterator child_begin() const { return nullptr; } 863e5dd7070Spatrick child_end()864e5dd7070Spatrick child_iterator child_end() const { return nullptr; } 865e5dd7070Spatrick getText()866e5dd7070Spatrick StringRef getText() const LLVM_READONLY { 867e5dd7070Spatrick return Text; 868e5dd7070Spatrick } 869e5dd7070Spatrick }; 870e5dd7070Spatrick 871e5dd7070Spatrick /// A verbatim block command (e. g., preformatted code). Verbatim block has an 872e5dd7070Spatrick /// opening and a closing command and contains multiple lines of text 873e5dd7070Spatrick /// (VerbatimBlockLineComment nodes). 874e5dd7070Spatrick class VerbatimBlockComment : public BlockCommandComment { 875e5dd7070Spatrick protected: 876e5dd7070Spatrick StringRef CloseName; 877e5dd7070Spatrick SourceLocation CloseNameLocBegin; 878e5dd7070Spatrick ArrayRef<VerbatimBlockLineComment *> Lines; 879e5dd7070Spatrick 880e5dd7070Spatrick public: VerbatimBlockComment(SourceLocation LocBegin,SourceLocation LocEnd,unsigned CommandID)881e5dd7070Spatrick VerbatimBlockComment(SourceLocation LocBegin, 882e5dd7070Spatrick SourceLocation LocEnd, 883e5dd7070Spatrick unsigned CommandID) : 884e5dd7070Spatrick BlockCommandComment(VerbatimBlockCommentKind, 885e5dd7070Spatrick LocBegin, LocEnd, CommandID, 886e5dd7070Spatrick CMK_At) // FIXME: improve source fidelity. 887e5dd7070Spatrick { } 888e5dd7070Spatrick classof(const Comment * C)889e5dd7070Spatrick static bool classof(const Comment *C) { 890e5dd7070Spatrick return C->getCommentKind() == VerbatimBlockCommentKind; 891e5dd7070Spatrick } 892e5dd7070Spatrick child_begin()893e5dd7070Spatrick child_iterator child_begin() const { 894e5dd7070Spatrick return reinterpret_cast<child_iterator>(Lines.begin()); 895e5dd7070Spatrick } 896e5dd7070Spatrick child_end()897e5dd7070Spatrick child_iterator child_end() const { 898e5dd7070Spatrick return reinterpret_cast<child_iterator>(Lines.end()); 899e5dd7070Spatrick } 900e5dd7070Spatrick setCloseName(StringRef Name,SourceLocation LocBegin)901e5dd7070Spatrick void setCloseName(StringRef Name, SourceLocation LocBegin) { 902e5dd7070Spatrick CloseName = Name; 903e5dd7070Spatrick CloseNameLocBegin = LocBegin; 904e5dd7070Spatrick } 905e5dd7070Spatrick setLines(ArrayRef<VerbatimBlockLineComment * > L)906e5dd7070Spatrick void setLines(ArrayRef<VerbatimBlockLineComment *> L) { 907e5dd7070Spatrick Lines = L; 908e5dd7070Spatrick } 909e5dd7070Spatrick getCloseName()910e5dd7070Spatrick StringRef getCloseName() const { 911e5dd7070Spatrick return CloseName; 912e5dd7070Spatrick } 913e5dd7070Spatrick getNumLines()914e5dd7070Spatrick unsigned getNumLines() const { 915e5dd7070Spatrick return Lines.size(); 916e5dd7070Spatrick } 917e5dd7070Spatrick getText(unsigned LineIdx)918e5dd7070Spatrick StringRef getText(unsigned LineIdx) const { 919e5dd7070Spatrick return Lines[LineIdx]->getText(); 920e5dd7070Spatrick } 921e5dd7070Spatrick }; 922e5dd7070Spatrick 923e5dd7070Spatrick /// A verbatim line command. Verbatim line has an opening command, a single 924e5dd7070Spatrick /// line of text (up to the newline after the opening command) and has no 925e5dd7070Spatrick /// closing command. 926e5dd7070Spatrick class VerbatimLineComment : public BlockCommandComment { 927e5dd7070Spatrick protected: 928e5dd7070Spatrick StringRef Text; 929e5dd7070Spatrick SourceLocation TextBegin; 930e5dd7070Spatrick 931e5dd7070Spatrick public: VerbatimLineComment(SourceLocation LocBegin,SourceLocation LocEnd,unsigned CommandID,SourceLocation TextBegin,StringRef Text)932e5dd7070Spatrick VerbatimLineComment(SourceLocation LocBegin, 933e5dd7070Spatrick SourceLocation LocEnd, 934e5dd7070Spatrick unsigned CommandID, 935e5dd7070Spatrick SourceLocation TextBegin, 936e5dd7070Spatrick StringRef Text) : 937e5dd7070Spatrick BlockCommandComment(VerbatimLineCommentKind, 938e5dd7070Spatrick LocBegin, LocEnd, 939e5dd7070Spatrick CommandID, 940e5dd7070Spatrick CMK_At), // FIXME: improve source fidelity. 941e5dd7070Spatrick Text(Text), 942e5dd7070Spatrick TextBegin(TextBegin) 943e5dd7070Spatrick { } 944e5dd7070Spatrick classof(const Comment * C)945e5dd7070Spatrick static bool classof(const Comment *C) { 946e5dd7070Spatrick return C->getCommentKind() == VerbatimLineCommentKind; 947e5dd7070Spatrick } 948e5dd7070Spatrick child_begin()949e5dd7070Spatrick child_iterator child_begin() const { return nullptr; } 950e5dd7070Spatrick child_end()951e5dd7070Spatrick child_iterator child_end() const { return nullptr; } 952e5dd7070Spatrick getText()953e5dd7070Spatrick StringRef getText() const { 954e5dd7070Spatrick return Text; 955e5dd7070Spatrick } 956e5dd7070Spatrick getTextRange()957e5dd7070Spatrick SourceRange getTextRange() const { 958e5dd7070Spatrick return SourceRange(TextBegin, getEndLoc()); 959e5dd7070Spatrick } 960e5dd7070Spatrick }; 961e5dd7070Spatrick 962e5dd7070Spatrick /// Information about the declaration, useful to clients of FullComment. 963e5dd7070Spatrick struct DeclInfo { 964e5dd7070Spatrick /// Declaration the comment is actually attached to (in the source). 965e5dd7070Spatrick /// Should not be NULL. 966e5dd7070Spatrick const Decl *CommentDecl; 967e5dd7070Spatrick 968e5dd7070Spatrick /// CurrentDecl is the declaration with which the FullComment is associated. 969e5dd7070Spatrick /// 970e5dd7070Spatrick /// It can be different from \c CommentDecl. It happens when we decide 971e5dd7070Spatrick /// that the comment originally attached to \c CommentDecl is fine for 972e5dd7070Spatrick /// \c CurrentDecl too (for example, for a redeclaration or an overrider of 973e5dd7070Spatrick /// \c CommentDecl). 974e5dd7070Spatrick /// 975e5dd7070Spatrick /// The information in the DeclInfo corresponds to CurrentDecl. 976e5dd7070Spatrick const Decl *CurrentDecl; 977e5dd7070Spatrick 978e5dd7070Spatrick /// Parameters that can be referenced by \\param if \c CommentDecl is something 979e5dd7070Spatrick /// that we consider a "function". 980e5dd7070Spatrick ArrayRef<const ParmVarDecl *> ParamVars; 981e5dd7070Spatrick 982e5dd7070Spatrick /// Function return type if \c CommentDecl is something that we consider 983e5dd7070Spatrick /// a "function". 984e5dd7070Spatrick QualType ReturnType; 985e5dd7070Spatrick 986e5dd7070Spatrick /// Template parameters that can be referenced by \\tparam if \c CommentDecl is 987e5dd7070Spatrick /// a template (\c IsTemplateDecl or \c IsTemplatePartialSpecialization is 988e5dd7070Spatrick /// true). 989e5dd7070Spatrick const TemplateParameterList *TemplateParameters; 990e5dd7070Spatrick 991e5dd7070Spatrick /// A simplified description of \c CommentDecl kind that should be good enough 992e5dd7070Spatrick /// for documentation rendering purposes. 993e5dd7070Spatrick enum DeclKind { 994e5dd7070Spatrick /// Everything else not explicitly mentioned below. 995e5dd7070Spatrick OtherKind, 996e5dd7070Spatrick 997e5dd7070Spatrick /// Something that we consider a "function": 998e5dd7070Spatrick /// \li function, 999e5dd7070Spatrick /// \li function template, 1000e5dd7070Spatrick /// \li function template specialization, 1001e5dd7070Spatrick /// \li member function, 1002e5dd7070Spatrick /// \li member function template, 1003e5dd7070Spatrick /// \li member function template specialization, 1004e5dd7070Spatrick /// \li ObjC method, 1005e5dd7070Spatrick FunctionKind, 1006e5dd7070Spatrick 1007e5dd7070Spatrick /// Something that we consider a "class": 1008e5dd7070Spatrick /// \li class/struct, 1009e5dd7070Spatrick /// \li class template, 1010e5dd7070Spatrick /// \li class template (partial) specialization. 1011e5dd7070Spatrick ClassKind, 1012e5dd7070Spatrick 1013e5dd7070Spatrick /// Something that we consider a "variable": 1014*12c85518Srobert /// \li namespace scope variables and variable templates; 1015*12c85518Srobert /// \li static and non-static class data members and member templates; 1016e5dd7070Spatrick /// \li enumerators. 1017e5dd7070Spatrick VariableKind, 1018e5dd7070Spatrick 1019e5dd7070Spatrick /// A C++ namespace. 1020e5dd7070Spatrick NamespaceKind, 1021e5dd7070Spatrick 1022e5dd7070Spatrick /// A C++ typedef-name (a 'typedef' decl specifier or alias-declaration), 1023e5dd7070Spatrick /// see \c TypedefNameDecl. 1024e5dd7070Spatrick TypedefKind, 1025e5dd7070Spatrick 1026e5dd7070Spatrick /// An enumeration or scoped enumeration. 1027e5dd7070Spatrick EnumKind 1028e5dd7070Spatrick }; 1029e5dd7070Spatrick 1030e5dd7070Spatrick /// What kind of template specialization \c CommentDecl is. 1031e5dd7070Spatrick enum TemplateDeclKind { 1032e5dd7070Spatrick NotTemplate, 1033e5dd7070Spatrick Template, 1034e5dd7070Spatrick TemplateSpecialization, 1035e5dd7070Spatrick TemplatePartialSpecialization 1036e5dd7070Spatrick }; 1037e5dd7070Spatrick 1038e5dd7070Spatrick /// If false, only \c CommentDecl is valid. 1039e5dd7070Spatrick unsigned IsFilled : 1; 1040e5dd7070Spatrick 1041e5dd7070Spatrick /// Simplified kind of \c CommentDecl, see \c DeclKind enum. 1042e5dd7070Spatrick unsigned Kind : 3; 1043e5dd7070Spatrick 1044e5dd7070Spatrick /// Is \c CommentDecl a template declaration. 1045e5dd7070Spatrick unsigned TemplateKind : 2; 1046e5dd7070Spatrick 1047e5dd7070Spatrick /// Is \c CommentDecl an ObjCMethodDecl. 1048e5dd7070Spatrick unsigned IsObjCMethod : 1; 1049e5dd7070Spatrick 1050e5dd7070Spatrick /// Is \c CommentDecl a non-static member function of C++ class or 1051e5dd7070Spatrick /// instance method of ObjC class. 1052e5dd7070Spatrick /// Can be true only if \c IsFunctionDecl is true. 1053e5dd7070Spatrick unsigned IsInstanceMethod : 1; 1054e5dd7070Spatrick 1055e5dd7070Spatrick /// Is \c CommentDecl a static member function of C++ class or 1056e5dd7070Spatrick /// class method of ObjC class. 1057e5dd7070Spatrick /// Can be true only if \c IsFunctionDecl is true. 1058e5dd7070Spatrick unsigned IsClassMethod : 1; 1059e5dd7070Spatrick 1060*12c85518Srobert /// Is \c CommentDecl something we consider a "function" that's variadic. 1061*12c85518Srobert unsigned IsVariadic : 1; 1062*12c85518Srobert 1063e5dd7070Spatrick void fill(); 1064e5dd7070Spatrick getKindDeclInfo1065e5dd7070Spatrick DeclKind getKind() const LLVM_READONLY { 1066e5dd7070Spatrick return static_cast<DeclKind>(Kind); 1067e5dd7070Spatrick } 1068e5dd7070Spatrick getTemplateKindDeclInfo1069e5dd7070Spatrick TemplateDeclKind getTemplateKind() const LLVM_READONLY { 1070e5dd7070Spatrick return static_cast<TemplateDeclKind>(TemplateKind); 1071e5dd7070Spatrick } 1072*12c85518Srobert involvesFunctionTypeDeclInfo1073*12c85518Srobert bool involvesFunctionType() const { return !ReturnType.isNull(); } 1074e5dd7070Spatrick }; 1075e5dd7070Spatrick 1076e5dd7070Spatrick /// A full comment attached to a declaration, contains block content. 1077e5dd7070Spatrick class FullComment : public Comment { 1078e5dd7070Spatrick ArrayRef<BlockContentComment *> Blocks; 1079e5dd7070Spatrick DeclInfo *ThisDeclInfo; 1080e5dd7070Spatrick 1081e5dd7070Spatrick public: FullComment(ArrayRef<BlockContentComment * > Blocks,DeclInfo * D)1082e5dd7070Spatrick FullComment(ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) : 1083e5dd7070Spatrick Comment(FullCommentKind, SourceLocation(), SourceLocation()), 1084e5dd7070Spatrick Blocks(Blocks), ThisDeclInfo(D) { 1085e5dd7070Spatrick if (Blocks.empty()) 1086e5dd7070Spatrick return; 1087e5dd7070Spatrick 1088e5dd7070Spatrick setSourceRange( 1089e5dd7070Spatrick SourceRange(Blocks.front()->getBeginLoc(), Blocks.back()->getEndLoc())); 1090e5dd7070Spatrick setLocation(Blocks.front()->getBeginLoc()); 1091e5dd7070Spatrick } 1092e5dd7070Spatrick classof(const Comment * C)1093e5dd7070Spatrick static bool classof(const Comment *C) { 1094e5dd7070Spatrick return C->getCommentKind() == FullCommentKind; 1095e5dd7070Spatrick } 1096e5dd7070Spatrick child_begin()1097e5dd7070Spatrick child_iterator child_begin() const { 1098e5dd7070Spatrick return reinterpret_cast<child_iterator>(Blocks.begin()); 1099e5dd7070Spatrick } 1100e5dd7070Spatrick child_end()1101e5dd7070Spatrick child_iterator child_end() const { 1102e5dd7070Spatrick return reinterpret_cast<child_iterator>(Blocks.end()); 1103e5dd7070Spatrick } 1104e5dd7070Spatrick getDecl()1105e5dd7070Spatrick const Decl *getDecl() const LLVM_READONLY { 1106e5dd7070Spatrick return ThisDeclInfo->CommentDecl; 1107e5dd7070Spatrick } 1108e5dd7070Spatrick getDeclInfo()1109e5dd7070Spatrick const DeclInfo *getDeclInfo() const LLVM_READONLY { 1110e5dd7070Spatrick if (!ThisDeclInfo->IsFilled) 1111e5dd7070Spatrick ThisDeclInfo->fill(); 1112e5dd7070Spatrick return ThisDeclInfo; 1113e5dd7070Spatrick } 1114e5dd7070Spatrick getBlocks()1115e5dd7070Spatrick ArrayRef<BlockContentComment *> getBlocks() const { return Blocks; } 1116e5dd7070Spatrick 1117e5dd7070Spatrick }; 1118e5dd7070Spatrick } // end namespace comments 1119e5dd7070Spatrick } // end namespace clang 1120e5dd7070Spatrick 1121e5dd7070Spatrick #endif 1122e5dd7070Spatrick 1123