1 //===--- Comment.h - Comment AST nodes --------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines comment AST nodes.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_AST_COMMENT_H
15 #define LLVM_CLANG_AST_COMMENT_H
17 #include "clang/AST/CommentCommandTraits.h"
18 #include "clang/AST/DeclObjC.h"
19 #include "clang/AST/Type.h"
20 #include "clang/Basic/SourceLocation.h"
21 #include "llvm/ADT/ArrayRef.h"
22 #include "llvm/ADT/StringRef.h"
27 class TemplateParameterList;
32 /// Describes the syntax that was used in a documentation command.
34 /// Exact values of this enumeration are important because they used to select
35 /// parts of diagnostic messages. Audit diagnostics before changing or adding
37 enum CommandMarkerKind {
38 /// Command started with a backslash character:
44 /// Command started with an 'at' character:
51 /// Any part of the comment.
55 /// Preferred location to show caret.
58 /// Source range of this AST node.
61 class CommentBitfields {
64 /// Type of this AST node.
67 enum { NumCommentBits = 8 };
69 class InlineContentCommentBitfields {
70 friend class InlineContentComment;
72 unsigned : NumCommentBits;
74 /// True if there is a newline after this inline content node.
75 /// (There is no separate AST node for a newline.)
76 unsigned HasTrailingNewline : 1;
78 enum { NumInlineContentCommentBits = NumCommentBits + 1 };
80 class TextCommentBitfields {
81 friend class TextComment;
83 unsigned : NumInlineContentCommentBits;
85 /// True if \c IsWhitespace field contains a valid value.
86 mutable unsigned IsWhitespaceValid : 1;
88 /// True if this comment AST node contains only whitespace.
89 mutable unsigned IsWhitespace : 1;
91 enum { NumTextCommentBits = NumInlineContentCommentBits + 2 };
93 class InlineCommandCommentBitfields {
94 friend class InlineCommandComment;
96 unsigned : NumInlineContentCommentBits;
98 unsigned RenderKind : 2;
99 unsigned CommandID : CommandInfo::NumCommandIDBits;
101 enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 2 +
102 CommandInfo::NumCommandIDBits };
104 class HTMLTagCommentBitfields {
105 friend class HTMLTagComment;
107 unsigned : NumInlineContentCommentBits;
109 /// True if we found that this tag is malformed in some way.
110 unsigned IsMalformed : 1;
112 enum { NumHTMLTagCommentBits = NumInlineContentCommentBits + 1 };
114 class HTMLStartTagCommentBitfields {
115 friend class HTMLStartTagComment;
117 unsigned : NumHTMLTagCommentBits;
119 /// True if this tag is self-closing (e. g., <br />). This is based on tag
120 /// spelling in comment (plain <br> would not set this flag).
121 unsigned IsSelfClosing : 1;
123 enum { NumHTMLStartTagCommentBits = NumHTMLTagCommentBits + 1 };
125 class ParagraphCommentBitfields {
126 friend class ParagraphComment;
128 unsigned : NumCommentBits;
130 /// True if \c IsWhitespace field contains a valid value.
131 mutable unsigned IsWhitespaceValid : 1;
133 /// True if this comment AST node contains only whitespace.
134 mutable unsigned IsWhitespace : 1;
136 enum { NumParagraphCommentBits = NumCommentBits + 2 };
138 class BlockCommandCommentBitfields {
139 friend class BlockCommandComment;
141 unsigned : NumCommentBits;
143 unsigned CommandID : CommandInfo::NumCommandIDBits;
145 /// Describes the syntax that was used in a documentation command.
146 /// Contains values from CommandMarkerKind enum.
147 unsigned CommandMarker : 1;
149 enum { NumBlockCommandCommentBits = NumCommentBits +
150 CommandInfo::NumCommandIDBits + 1 };
152 class ParamCommandCommentBitfields {
153 friend class ParamCommandComment;
155 unsigned : NumBlockCommandCommentBits;
157 /// Parameter passing direction, see ParamCommandComment::PassDirection.
158 unsigned Direction : 2;
160 /// True if direction was specified explicitly in the comment.
161 unsigned IsDirectionExplicit : 1;
163 enum { NumParamCommandCommentBits = NumBlockCommandCommentBits + 3 };
166 CommentBitfields CommentBits;
167 InlineContentCommentBitfields InlineContentCommentBits;
168 TextCommentBitfields TextCommentBits;
169 InlineCommandCommentBitfields InlineCommandCommentBits;
170 HTMLTagCommentBitfields HTMLTagCommentBits;
171 HTMLStartTagCommentBitfields HTMLStartTagCommentBits;
172 ParagraphCommentBitfields ParagraphCommentBits;
173 BlockCommandCommentBitfields BlockCommandCommentBits;
174 ParamCommandCommentBitfields ParamCommandCommentBits;
177 void setSourceRange(SourceRange SR) {
181 void setLocation(SourceLocation L) {
188 #define COMMENT(CLASS, PARENT) CLASS##Kind,
189 #define COMMENT_RANGE(BASE, FIRST, LAST) \
190 First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind,
191 #define LAST_COMMENT_RANGE(BASE, FIRST, LAST) \
192 First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind
193 #define ABSTRACT_COMMENT(COMMENT)
194 #include "clang/AST/CommentNodes.inc"
197 Comment(CommentKind K,
198 SourceLocation LocBegin,
199 SourceLocation LocEnd) :
200 Loc(LocBegin), Range(SourceRange(LocBegin, LocEnd)) {
201 CommentBits.Kind = K;
204 CommentKind getCommentKind() const {
205 return static_cast<CommentKind>(CommentBits.Kind);
208 const char *getCommentKindName() const;
211 void dumpColor() const;
212 void dump(const ASTContext &Context) const;
213 void dump(raw_ostream &OS, const CommandTraits *Traits,
214 const SourceManager *SM) const;
216 SourceRange getSourceRange() const LLVM_READONLY { return Range; }
218 SourceLocation getLocStart() const LLVM_READONLY {
219 return Range.getBegin();
222 SourceLocation getLocEnd() const LLVM_READONLY {
223 return Range.getEnd();
226 SourceLocation getLocation() const LLVM_READONLY { return Loc; }
228 typedef Comment * const *child_iterator;
230 child_iterator child_begin() const;
231 child_iterator child_end() const;
233 // TODO: const child iterator
235 unsigned child_count() const {
236 return child_end() - child_begin();
240 /// Inline content (contained within a block).
242 class InlineContentComment : public Comment {
244 InlineContentComment(CommentKind K,
245 SourceLocation LocBegin,
246 SourceLocation LocEnd) :
247 Comment(K, LocBegin, LocEnd) {
248 InlineContentCommentBits.HasTrailingNewline = 0;
252 static bool classof(const Comment *C) {
253 return C->getCommentKind() >= FirstInlineContentCommentConstant &&
254 C->getCommentKind() <= LastInlineContentCommentConstant;
257 void addTrailingNewline() {
258 InlineContentCommentBits.HasTrailingNewline = 1;
261 bool hasTrailingNewline() const {
262 return InlineContentCommentBits.HasTrailingNewline;
267 class TextComment : public InlineContentComment {
271 TextComment(SourceLocation LocBegin,
272 SourceLocation LocEnd,
274 InlineContentComment(TextCommentKind, LocBegin, LocEnd),
276 TextCommentBits.IsWhitespaceValid = false;
279 static bool classof(const Comment *C) {
280 return C->getCommentKind() == TextCommentKind;
283 child_iterator child_begin() const { return nullptr; }
285 child_iterator child_end() const { return nullptr; }
287 StringRef getText() const LLVM_READONLY { return Text; }
289 bool isWhitespace() const {
290 if (TextCommentBits.IsWhitespaceValid)
291 return TextCommentBits.IsWhitespace;
293 TextCommentBits.IsWhitespace = isWhitespaceNoCache();
294 TextCommentBits.IsWhitespaceValid = true;
295 return TextCommentBits.IsWhitespace;
299 bool isWhitespaceNoCache() const;
302 /// A command with word-like arguments that is considered inline content.
303 class InlineCommandComment : public InlineContentComment {
309 Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
312 /// The most appropriate rendering mode for this command, chosen on command
313 /// semantics in Doxygen.
322 /// Command arguments.
323 ArrayRef<Argument> Args;
326 InlineCommandComment(SourceLocation LocBegin,
327 SourceLocation LocEnd,
330 ArrayRef<Argument> Args) :
331 InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd),
333 InlineCommandCommentBits.RenderKind = RK;
334 InlineCommandCommentBits.CommandID = CommandID;
337 static bool classof(const Comment *C) {
338 return C->getCommentKind() == InlineCommandCommentKind;
341 child_iterator child_begin() const { return nullptr; }
343 child_iterator child_end() const { return nullptr; }
345 unsigned getCommandID() const {
346 return InlineCommandCommentBits.CommandID;
349 StringRef getCommandName(const CommandTraits &Traits) const {
350 return Traits.getCommandInfo(getCommandID())->Name;
353 SourceRange getCommandNameRange() const {
354 return SourceRange(getLocStart().getLocWithOffset(-1),
358 RenderKind getRenderKind() const {
359 return static_cast<RenderKind>(InlineCommandCommentBits.RenderKind);
362 unsigned getNumArgs() const {
366 StringRef getArgText(unsigned Idx) const {
367 return Args[Idx].Text;
370 SourceRange getArgRange(unsigned Idx) const {
371 return Args[Idx].Range;
375 /// Abstract class for opening and closing HTML tags. HTML tags are always
376 /// treated as inline content (regardless HTML semantics).
377 class HTMLTagComment : public InlineContentComment {
380 SourceRange TagNameRange;
382 HTMLTagComment(CommentKind K,
383 SourceLocation LocBegin,
384 SourceLocation LocEnd,
386 SourceLocation TagNameBegin,
387 SourceLocation TagNameEnd) :
388 InlineContentComment(K, LocBegin, LocEnd),
390 TagNameRange(TagNameBegin, TagNameEnd) {
391 setLocation(TagNameBegin);
392 HTMLTagCommentBits.IsMalformed = 0;
396 static bool classof(const Comment *C) {
397 return C->getCommentKind() >= FirstHTMLTagCommentConstant &&
398 C->getCommentKind() <= LastHTMLTagCommentConstant;
401 StringRef getTagName() const LLVM_READONLY { return TagName; }
403 SourceRange getTagNameSourceRange() const LLVM_READONLY {
404 SourceLocation L = getLocation();
405 return SourceRange(L.getLocWithOffset(1),
406 L.getLocWithOffset(1 + TagName.size()));
409 bool isMalformed() const {
410 return HTMLTagCommentBits.IsMalformed;
413 void setIsMalformed() {
414 HTMLTagCommentBits.IsMalformed = 1;
418 /// An opening HTML tag with attributes.
419 class HTMLStartTagComment : public HTMLTagComment {
423 SourceLocation NameLocBegin;
426 SourceLocation EqualsLoc;
428 SourceRange ValueRange;
433 Attribute(SourceLocation NameLocBegin, StringRef Name) :
434 NameLocBegin(NameLocBegin), Name(Name),
435 EqualsLoc(SourceLocation()),
436 ValueRange(SourceRange()), Value(StringRef())
439 Attribute(SourceLocation NameLocBegin, StringRef Name,
440 SourceLocation EqualsLoc,
441 SourceRange ValueRange, StringRef Value) :
442 NameLocBegin(NameLocBegin), Name(Name),
443 EqualsLoc(EqualsLoc),
444 ValueRange(ValueRange), Value(Value)
447 SourceLocation getNameLocEnd() const {
448 return NameLocBegin.getLocWithOffset(Name.size());
451 SourceRange getNameRange() const {
452 return SourceRange(NameLocBegin, getNameLocEnd());
457 ArrayRef<Attribute> Attributes;
460 HTMLStartTagComment(SourceLocation LocBegin,
462 HTMLTagComment(HTMLStartTagCommentKind,
463 LocBegin, LocBegin.getLocWithOffset(1 + TagName.size()),
465 LocBegin.getLocWithOffset(1),
466 LocBegin.getLocWithOffset(1 + TagName.size())) {
467 HTMLStartTagCommentBits.IsSelfClosing = false;
470 static bool classof(const Comment *C) {
471 return C->getCommentKind() == HTMLStartTagCommentKind;
474 child_iterator child_begin() const { return nullptr; }
476 child_iterator child_end() const { return nullptr; }
478 unsigned getNumAttrs() const {
479 return Attributes.size();
482 const Attribute &getAttr(unsigned Idx) const {
483 return Attributes[Idx];
486 void setAttrs(ArrayRef<Attribute> Attrs) {
488 if (!Attrs.empty()) {
489 const Attribute &Attr = Attrs.back();
490 SourceLocation L = Attr.ValueRange.getEnd();
494 Range.setEnd(Attr.getNameLocEnd());
499 void setGreaterLoc(SourceLocation GreaterLoc) {
500 Range.setEnd(GreaterLoc);
503 bool isSelfClosing() const {
504 return HTMLStartTagCommentBits.IsSelfClosing;
507 void setSelfClosing() {
508 HTMLStartTagCommentBits.IsSelfClosing = true;
512 /// A closing HTML tag.
513 class HTMLEndTagComment : public HTMLTagComment {
515 HTMLEndTagComment(SourceLocation LocBegin,
516 SourceLocation LocEnd,
518 HTMLTagComment(HTMLEndTagCommentKind,
521 LocBegin.getLocWithOffset(2),
522 LocBegin.getLocWithOffset(2 + TagName.size()))
525 static bool classof(const Comment *C) {
526 return C->getCommentKind() == HTMLEndTagCommentKind;
529 child_iterator child_begin() const { return nullptr; }
531 child_iterator child_end() const { return nullptr; }
534 /// Block content (contains inline content).
536 class BlockContentComment : public Comment {
538 BlockContentComment(CommentKind K,
539 SourceLocation LocBegin,
540 SourceLocation LocEnd) :
541 Comment(K, LocBegin, LocEnd)
545 static bool classof(const Comment *C) {
546 return C->getCommentKind() >= FirstBlockContentCommentConstant &&
547 C->getCommentKind() <= LastBlockContentCommentConstant;
551 /// A single paragraph that contains inline content.
552 class ParagraphComment : public BlockContentComment {
553 ArrayRef<InlineContentComment *> Content;
556 ParagraphComment(ArrayRef<InlineContentComment *> Content) :
557 BlockContentComment(ParagraphCommentKind,
561 if (Content.empty()) {
562 ParagraphCommentBits.IsWhitespace = true;
563 ParagraphCommentBits.IsWhitespaceValid = true;
567 ParagraphCommentBits.IsWhitespaceValid = false;
569 setSourceRange(SourceRange(Content.front()->getLocStart(),
570 Content.back()->getLocEnd()));
571 setLocation(Content.front()->getLocStart());
574 static bool classof(const Comment *C) {
575 return C->getCommentKind() == ParagraphCommentKind;
578 child_iterator child_begin() const {
579 return reinterpret_cast<child_iterator>(Content.begin());
582 child_iterator child_end() const {
583 return reinterpret_cast<child_iterator>(Content.end());
586 bool isWhitespace() const {
587 if (ParagraphCommentBits.IsWhitespaceValid)
588 return ParagraphCommentBits.IsWhitespace;
590 ParagraphCommentBits.IsWhitespace = isWhitespaceNoCache();
591 ParagraphCommentBits.IsWhitespaceValid = true;
592 return ParagraphCommentBits.IsWhitespace;
596 bool isWhitespaceNoCache() const;
599 /// A command that has zero or more word-like arguments (number of word-like
600 /// arguments depends on command name) and a paragraph as an argument
601 /// (e. g., \\brief).
602 class BlockCommandComment : public BlockContentComment {
609 Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
613 /// Word-like arguments.
614 ArrayRef<Argument> Args;
616 /// Paragraph argument.
617 ParagraphComment *Paragraph;
619 BlockCommandComment(CommentKind K,
620 SourceLocation LocBegin,
621 SourceLocation LocEnd,
623 CommandMarkerKind CommandMarker) :
624 BlockContentComment(K, LocBegin, LocEnd),
626 setLocation(getCommandNameBeginLoc());
627 BlockCommandCommentBits.CommandID = CommandID;
628 BlockCommandCommentBits.CommandMarker = CommandMarker;
632 BlockCommandComment(SourceLocation LocBegin,
633 SourceLocation LocEnd,
635 CommandMarkerKind CommandMarker) :
636 BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd),
638 setLocation(getCommandNameBeginLoc());
639 BlockCommandCommentBits.CommandID = CommandID;
640 BlockCommandCommentBits.CommandMarker = CommandMarker;
643 static bool classof(const Comment *C) {
644 return C->getCommentKind() >= FirstBlockCommandCommentConstant &&
645 C->getCommentKind() <= LastBlockCommandCommentConstant;
648 child_iterator child_begin() const {
649 return reinterpret_cast<child_iterator>(&Paragraph);
652 child_iterator child_end() const {
653 return reinterpret_cast<child_iterator>(&Paragraph + 1);
656 unsigned getCommandID() const {
657 return BlockCommandCommentBits.CommandID;
660 StringRef getCommandName(const CommandTraits &Traits) const {
661 return Traits.getCommandInfo(getCommandID())->Name;
664 SourceLocation getCommandNameBeginLoc() const {
665 return getLocStart().getLocWithOffset(1);
668 SourceRange getCommandNameRange(const CommandTraits &Traits) const {
669 StringRef Name = getCommandName(Traits);
670 return SourceRange(getCommandNameBeginLoc(),
671 getLocStart().getLocWithOffset(1 + Name.size()));
674 unsigned getNumArgs() const {
678 StringRef getArgText(unsigned Idx) const {
679 return Args[Idx].Text;
682 SourceRange getArgRange(unsigned Idx) const {
683 return Args[Idx].Range;
686 void setArgs(ArrayRef<Argument> A) {
688 if (Args.size() > 0) {
689 SourceLocation NewLocEnd = Args.back().Range.getEnd();
690 if (NewLocEnd.isValid())
691 setSourceRange(SourceRange(getLocStart(), NewLocEnd));
695 ParagraphComment *getParagraph() const LLVM_READONLY {
699 bool hasNonWhitespaceParagraph() const {
700 return Paragraph && !Paragraph->isWhitespace();
703 void setParagraph(ParagraphComment *PC) {
705 SourceLocation NewLocEnd = PC->getLocEnd();
706 if (NewLocEnd.isValid())
707 setSourceRange(SourceRange(getLocStart(), NewLocEnd));
710 CommandMarkerKind getCommandMarker() const LLVM_READONLY {
711 return static_cast<CommandMarkerKind>(
712 BlockCommandCommentBits.CommandMarker);
716 /// Doxygen \\param command.
717 class ParamCommandComment : public BlockCommandComment {
719 /// Parameter index in the function declaration.
724 InvalidParamIndex = ~0U,
725 VarArgParamIndex = ~0U/*InvalidParamIndex*/ - 1U
728 ParamCommandComment(SourceLocation LocBegin,
729 SourceLocation LocEnd,
731 CommandMarkerKind CommandMarker) :
732 BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd,
733 CommandID, CommandMarker),
734 ParamIndex(InvalidParamIndex) {
735 ParamCommandCommentBits.Direction = In;
736 ParamCommandCommentBits.IsDirectionExplicit = false;
739 static bool classof(const Comment *C) {
740 return C->getCommentKind() == ParamCommandCommentKind;
749 static const char *getDirectionAsString(PassDirection D);
751 PassDirection getDirection() const LLVM_READONLY {
752 return static_cast<PassDirection>(ParamCommandCommentBits.Direction);
755 bool isDirectionExplicit() const LLVM_READONLY {
756 return ParamCommandCommentBits.IsDirectionExplicit;
759 void setDirection(PassDirection Direction, bool Explicit) {
760 ParamCommandCommentBits.Direction = Direction;
761 ParamCommandCommentBits.IsDirectionExplicit = Explicit;
764 bool hasParamName() const {
765 return getNumArgs() > 0;
768 StringRef getParamName(const FullComment *FC) const;
770 StringRef getParamNameAsWritten() const {
774 SourceRange getParamNameRange() const {
775 return Args[0].Range;
778 bool isParamIndexValid() const LLVM_READONLY {
779 return ParamIndex != InvalidParamIndex;
782 bool isVarArgParam() const LLVM_READONLY {
783 return ParamIndex == VarArgParamIndex;
786 void setIsVarArgParam() {
787 ParamIndex = VarArgParamIndex;
788 assert(isParamIndexValid());
791 unsigned getParamIndex() const LLVM_READONLY {
792 assert(isParamIndexValid());
793 assert(!isVarArgParam());
797 void setParamIndex(unsigned Index) {
799 assert(isParamIndexValid());
800 assert(!isVarArgParam());
804 /// Doxygen \\tparam command, describes a template parameter.
805 class TParamCommandComment : public BlockCommandComment {
807 /// If this template parameter name was resolved (found in template parameter
808 /// list), then this stores a list of position indexes in all template
813 /// template<typename C, template<typename T> class TT>
814 /// void test(TT<int> aaa);
816 /// For C: Position = { 0 }
817 /// For TT: Position = { 1 }
818 /// For T: Position = { 1, 0 }
819 ArrayRef<unsigned> Position;
822 TParamCommandComment(SourceLocation LocBegin,
823 SourceLocation LocEnd,
825 CommandMarkerKind CommandMarker) :
826 BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, CommandID,
830 static bool classof(const Comment *C) {
831 return C->getCommentKind() == TParamCommandCommentKind;
834 bool hasParamName() const {
835 return getNumArgs() > 0;
838 StringRef getParamName(const FullComment *FC) const;
840 StringRef getParamNameAsWritten() const {
844 SourceRange getParamNameRange() const {
845 return Args[0].Range;
848 bool isPositionValid() const LLVM_READONLY {
849 return !Position.empty();
852 unsigned getDepth() const {
853 assert(isPositionValid());
854 return Position.size();
857 unsigned getIndex(unsigned Depth) const {
858 assert(isPositionValid());
859 return Position[Depth];
862 void setPosition(ArrayRef<unsigned> NewPosition) {
863 Position = NewPosition;
864 assert(isPositionValid());
868 /// A line of text contained in a verbatim block.
869 class VerbatimBlockLineComment : public Comment {
873 VerbatimBlockLineComment(SourceLocation LocBegin,
875 Comment(VerbatimBlockLineCommentKind,
877 LocBegin.getLocWithOffset(Text.size())),
881 static bool classof(const Comment *C) {
882 return C->getCommentKind() == VerbatimBlockLineCommentKind;
885 child_iterator child_begin() const { return nullptr; }
887 child_iterator child_end() const { return nullptr; }
889 StringRef getText() const LLVM_READONLY {
894 /// A verbatim block command (e. g., preformatted code). Verbatim block has an
895 /// opening and a closing command and contains multiple lines of text
896 /// (VerbatimBlockLineComment nodes).
897 class VerbatimBlockComment : public BlockCommandComment {
900 SourceLocation CloseNameLocBegin;
901 ArrayRef<VerbatimBlockLineComment *> Lines;
904 VerbatimBlockComment(SourceLocation LocBegin,
905 SourceLocation LocEnd,
906 unsigned CommandID) :
907 BlockCommandComment(VerbatimBlockCommentKind,
908 LocBegin, LocEnd, CommandID,
909 CMK_At) // FIXME: improve source fidelity.
912 static bool classof(const Comment *C) {
913 return C->getCommentKind() == VerbatimBlockCommentKind;
916 child_iterator child_begin() const {
917 return reinterpret_cast<child_iterator>(Lines.begin());
920 child_iterator child_end() const {
921 return reinterpret_cast<child_iterator>(Lines.end());
924 void setCloseName(StringRef Name, SourceLocation LocBegin) {
926 CloseNameLocBegin = LocBegin;
929 void setLines(ArrayRef<VerbatimBlockLineComment *> L) {
933 StringRef getCloseName() const {
937 unsigned getNumLines() const {
941 StringRef getText(unsigned LineIdx) const {
942 return Lines[LineIdx]->getText();
946 /// A verbatim line command. Verbatim line has an opening command, a single
947 /// line of text (up to the newline after the opening command) and has no
949 class VerbatimLineComment : public BlockCommandComment {
952 SourceLocation TextBegin;
955 VerbatimLineComment(SourceLocation LocBegin,
956 SourceLocation LocEnd,
958 SourceLocation TextBegin,
960 BlockCommandComment(VerbatimLineCommentKind,
963 CMK_At), // FIXME: improve source fidelity.
968 static bool classof(const Comment *C) {
969 return C->getCommentKind() == VerbatimLineCommentKind;
972 child_iterator child_begin() const { return nullptr; }
974 child_iterator child_end() const { return nullptr; }
976 StringRef getText() const {
980 SourceRange getTextRange() const {
981 return SourceRange(TextBegin, getLocEnd());
985 /// Information about the declaration, useful to clients of FullComment.
987 /// Declaration the comment is actually attached to (in the source).
988 /// Should not be NULL.
989 const Decl *CommentDecl;
991 /// CurrentDecl is the declaration with which the FullComment is associated.
993 /// It can be different from \c CommentDecl. It happens when we decide
994 /// that the comment originally attached to \c CommentDecl is fine for
995 /// \c CurrentDecl too (for example, for a redeclaration or an overrider of
998 /// The information in the DeclInfo corresponds to CurrentDecl.
999 const Decl *CurrentDecl;
1001 /// Parameters that can be referenced by \\param if \c CommentDecl is something
1002 /// that we consider a "function".
1003 ArrayRef<const ParmVarDecl *> ParamVars;
1005 /// Function return type if \c CommentDecl is something that we consider
1007 QualType ReturnType;
1009 /// Template parameters that can be referenced by \\tparam if \c CommentDecl is
1010 /// a template (\c IsTemplateDecl or \c IsTemplatePartialSpecialization is
1012 const TemplateParameterList *TemplateParameters;
1014 /// A simplified description of \c CommentDecl kind that should be good enough
1015 /// for documentation rendering purposes.
1017 /// Everything else not explicitly mentioned below.
1020 /// Something that we consider a "function":
1022 /// \li function template,
1023 /// \li function template specialization,
1024 /// \li member function,
1025 /// \li member function template,
1026 /// \li member function template specialization,
1027 /// \li ObjC method,
1028 /// \li a typedef for a function pointer, member function pointer,
1032 /// Something that we consider a "class":
1033 /// \li class/struct,
1034 /// \li class template,
1035 /// \li class template (partial) specialization.
1038 /// Something that we consider a "variable":
1039 /// \li namespace scope variables;
1040 /// \li static and non-static class data members;
1041 /// \li enumerators.
1044 /// A C++ namespace.
1047 /// A C++ typedef-name (a 'typedef' decl specifier or alias-declaration),
1048 /// see \c TypedefNameDecl.
1051 /// An enumeration or scoped enumeration.
1055 /// What kind of template specialization \c CommentDecl is.
1056 enum TemplateDeclKind {
1059 TemplateSpecialization,
1060 TemplatePartialSpecialization
1063 /// If false, only \c CommentDecl is valid.
1064 unsigned IsFilled : 1;
1066 /// Simplified kind of \c CommentDecl, see \c DeclKind enum.
1069 /// Is \c CommentDecl a template declaration.
1070 unsigned TemplateKind : 2;
1072 /// Is \c CommentDecl an ObjCMethodDecl.
1073 unsigned IsObjCMethod : 1;
1075 /// Is \c CommentDecl a non-static member function of C++ class or
1076 /// instance method of ObjC class.
1077 /// Can be true only if \c IsFunctionDecl is true.
1078 unsigned IsInstanceMethod : 1;
1080 /// Is \c CommentDecl a static member function of C++ class or
1081 /// class method of ObjC class.
1082 /// Can be true only if \c IsFunctionDecl is true.
1083 unsigned IsClassMethod : 1;
1087 DeclKind getKind() const LLVM_READONLY {
1088 return static_cast<DeclKind>(Kind);
1091 TemplateDeclKind getTemplateKind() const LLVM_READONLY {
1092 return static_cast<TemplateDeclKind>(TemplateKind);
1096 /// A full comment attached to a declaration, contains block content.
1097 class FullComment : public Comment {
1098 ArrayRef<BlockContentComment *> Blocks;
1099 DeclInfo *ThisDeclInfo;
1102 FullComment(ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) :
1103 Comment(FullCommentKind, SourceLocation(), SourceLocation()),
1104 Blocks(Blocks), ThisDeclInfo(D) {
1108 setSourceRange(SourceRange(Blocks.front()->getLocStart(),
1109 Blocks.back()->getLocEnd()));
1110 setLocation(Blocks.front()->getLocStart());
1113 static bool classof(const Comment *C) {
1114 return C->getCommentKind() == FullCommentKind;
1117 child_iterator child_begin() const {
1118 return reinterpret_cast<child_iterator>(Blocks.begin());
1121 child_iterator child_end() const {
1122 return reinterpret_cast<child_iterator>(Blocks.end());
1125 const Decl *getDecl() const LLVM_READONLY {
1126 return ThisDeclInfo->CommentDecl;
1129 const DeclInfo *getDeclInfo() const LLVM_READONLY {
1130 if (!ThisDeclInfo->IsFilled)
1131 ThisDeclInfo->fill();
1132 return ThisDeclInfo;
1135 ArrayRef<BlockContentComment *> getBlocks() const { return Blocks; }
1138 } // end namespace comments
1139 } // end namespace clang