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 { return getBeginLoc(); }
219 SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
221 SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
222 SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
224 SourceLocation getLocation() const LLVM_READONLY { return Loc; }
226 typedef Comment * const *child_iterator;
228 child_iterator child_begin() const;
229 child_iterator child_end() const;
231 // TODO: const child iterator
233 unsigned child_count() const {
234 return child_end() - child_begin();
238 /// Inline content (contained within a block).
240 class InlineContentComment : public Comment {
242 InlineContentComment(CommentKind K,
243 SourceLocation LocBegin,
244 SourceLocation LocEnd) :
245 Comment(K, LocBegin, LocEnd) {
246 InlineContentCommentBits.HasTrailingNewline = 0;
250 static bool classof(const Comment *C) {
251 return C->getCommentKind() >= FirstInlineContentCommentConstant &&
252 C->getCommentKind() <= LastInlineContentCommentConstant;
255 void addTrailingNewline() {
256 InlineContentCommentBits.HasTrailingNewline = 1;
259 bool hasTrailingNewline() const {
260 return InlineContentCommentBits.HasTrailingNewline;
265 class TextComment : public InlineContentComment {
269 TextComment(SourceLocation LocBegin,
270 SourceLocation LocEnd,
272 InlineContentComment(TextCommentKind, LocBegin, LocEnd),
274 TextCommentBits.IsWhitespaceValid = false;
277 static bool classof(const Comment *C) {
278 return C->getCommentKind() == TextCommentKind;
281 child_iterator child_begin() const { return nullptr; }
283 child_iterator child_end() const { return nullptr; }
285 StringRef getText() const LLVM_READONLY { return Text; }
287 bool isWhitespace() const {
288 if (TextCommentBits.IsWhitespaceValid)
289 return TextCommentBits.IsWhitespace;
291 TextCommentBits.IsWhitespace = isWhitespaceNoCache();
292 TextCommentBits.IsWhitespaceValid = true;
293 return TextCommentBits.IsWhitespace;
297 bool isWhitespaceNoCache() const;
300 /// A command with word-like arguments that is considered inline content.
301 class InlineCommandComment : public InlineContentComment {
307 Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
310 /// The most appropriate rendering mode for this command, chosen on command
311 /// semantics in Doxygen.
320 /// Command arguments.
321 ArrayRef<Argument> Args;
324 InlineCommandComment(SourceLocation LocBegin,
325 SourceLocation LocEnd,
328 ArrayRef<Argument> Args) :
329 InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd),
331 InlineCommandCommentBits.RenderKind = RK;
332 InlineCommandCommentBits.CommandID = CommandID;
335 static bool classof(const Comment *C) {
336 return C->getCommentKind() == InlineCommandCommentKind;
339 child_iterator child_begin() const { return nullptr; }
341 child_iterator child_end() const { return nullptr; }
343 unsigned getCommandID() const {
344 return InlineCommandCommentBits.CommandID;
347 StringRef getCommandName(const CommandTraits &Traits) const {
348 return Traits.getCommandInfo(getCommandID())->Name;
351 SourceRange getCommandNameRange() const {
352 return SourceRange(getLocStart().getLocWithOffset(-1),
356 RenderKind getRenderKind() const {
357 return static_cast<RenderKind>(InlineCommandCommentBits.RenderKind);
360 unsigned getNumArgs() const {
364 StringRef getArgText(unsigned Idx) const {
365 return Args[Idx].Text;
368 SourceRange getArgRange(unsigned Idx) const {
369 return Args[Idx].Range;
373 /// Abstract class for opening and closing HTML tags. HTML tags are always
374 /// treated as inline content (regardless HTML semantics).
375 class HTMLTagComment : public InlineContentComment {
378 SourceRange TagNameRange;
380 HTMLTagComment(CommentKind K,
381 SourceLocation LocBegin,
382 SourceLocation LocEnd,
384 SourceLocation TagNameBegin,
385 SourceLocation TagNameEnd) :
386 InlineContentComment(K, LocBegin, LocEnd),
388 TagNameRange(TagNameBegin, TagNameEnd) {
389 setLocation(TagNameBegin);
390 HTMLTagCommentBits.IsMalformed = 0;
394 static bool classof(const Comment *C) {
395 return C->getCommentKind() >= FirstHTMLTagCommentConstant &&
396 C->getCommentKind() <= LastHTMLTagCommentConstant;
399 StringRef getTagName() const LLVM_READONLY { return TagName; }
401 SourceRange getTagNameSourceRange() const LLVM_READONLY {
402 SourceLocation L = getLocation();
403 return SourceRange(L.getLocWithOffset(1),
404 L.getLocWithOffset(1 + TagName.size()));
407 bool isMalformed() const {
408 return HTMLTagCommentBits.IsMalformed;
411 void setIsMalformed() {
412 HTMLTagCommentBits.IsMalformed = 1;
416 /// An opening HTML tag with attributes.
417 class HTMLStartTagComment : public HTMLTagComment {
421 SourceLocation NameLocBegin;
424 SourceLocation EqualsLoc;
426 SourceRange ValueRange;
431 Attribute(SourceLocation NameLocBegin, StringRef Name) :
432 NameLocBegin(NameLocBegin), Name(Name),
433 EqualsLoc(SourceLocation()),
434 ValueRange(SourceRange()), Value(StringRef())
437 Attribute(SourceLocation NameLocBegin, StringRef Name,
438 SourceLocation EqualsLoc,
439 SourceRange ValueRange, StringRef Value) :
440 NameLocBegin(NameLocBegin), Name(Name),
441 EqualsLoc(EqualsLoc),
442 ValueRange(ValueRange), Value(Value)
445 SourceLocation getNameLocEnd() const {
446 return NameLocBegin.getLocWithOffset(Name.size());
449 SourceRange getNameRange() const {
450 return SourceRange(NameLocBegin, getNameLocEnd());
455 ArrayRef<Attribute> Attributes;
458 HTMLStartTagComment(SourceLocation LocBegin,
460 HTMLTagComment(HTMLStartTagCommentKind,
461 LocBegin, LocBegin.getLocWithOffset(1 + TagName.size()),
463 LocBegin.getLocWithOffset(1),
464 LocBegin.getLocWithOffset(1 + TagName.size())) {
465 HTMLStartTagCommentBits.IsSelfClosing = false;
468 static bool classof(const Comment *C) {
469 return C->getCommentKind() == HTMLStartTagCommentKind;
472 child_iterator child_begin() const { return nullptr; }
474 child_iterator child_end() const { return nullptr; }
476 unsigned getNumAttrs() const {
477 return Attributes.size();
480 const Attribute &getAttr(unsigned Idx) const {
481 return Attributes[Idx];
484 void setAttrs(ArrayRef<Attribute> Attrs) {
486 if (!Attrs.empty()) {
487 const Attribute &Attr = Attrs.back();
488 SourceLocation L = Attr.ValueRange.getEnd();
492 Range.setEnd(Attr.getNameLocEnd());
497 void setGreaterLoc(SourceLocation GreaterLoc) {
498 Range.setEnd(GreaterLoc);
501 bool isSelfClosing() const {
502 return HTMLStartTagCommentBits.IsSelfClosing;
505 void setSelfClosing() {
506 HTMLStartTagCommentBits.IsSelfClosing = true;
510 /// A closing HTML tag.
511 class HTMLEndTagComment : public HTMLTagComment {
513 HTMLEndTagComment(SourceLocation LocBegin,
514 SourceLocation LocEnd,
516 HTMLTagComment(HTMLEndTagCommentKind,
519 LocBegin.getLocWithOffset(2),
520 LocBegin.getLocWithOffset(2 + TagName.size()))
523 static bool classof(const Comment *C) {
524 return C->getCommentKind() == HTMLEndTagCommentKind;
527 child_iterator child_begin() const { return nullptr; }
529 child_iterator child_end() const { return nullptr; }
532 /// Block content (contains inline content).
534 class BlockContentComment : public Comment {
536 BlockContentComment(CommentKind K,
537 SourceLocation LocBegin,
538 SourceLocation LocEnd) :
539 Comment(K, LocBegin, LocEnd)
543 static bool classof(const Comment *C) {
544 return C->getCommentKind() >= FirstBlockContentCommentConstant &&
545 C->getCommentKind() <= LastBlockContentCommentConstant;
549 /// A single paragraph that contains inline content.
550 class ParagraphComment : public BlockContentComment {
551 ArrayRef<InlineContentComment *> Content;
554 ParagraphComment(ArrayRef<InlineContentComment *> Content) :
555 BlockContentComment(ParagraphCommentKind,
559 if (Content.empty()) {
560 ParagraphCommentBits.IsWhitespace = true;
561 ParagraphCommentBits.IsWhitespaceValid = true;
565 ParagraphCommentBits.IsWhitespaceValid = false;
567 setSourceRange(SourceRange(Content.front()->getLocStart(),
568 Content.back()->getLocEnd()));
569 setLocation(Content.front()->getLocStart());
572 static bool classof(const Comment *C) {
573 return C->getCommentKind() == ParagraphCommentKind;
576 child_iterator child_begin() const {
577 return reinterpret_cast<child_iterator>(Content.begin());
580 child_iterator child_end() const {
581 return reinterpret_cast<child_iterator>(Content.end());
584 bool isWhitespace() const {
585 if (ParagraphCommentBits.IsWhitespaceValid)
586 return ParagraphCommentBits.IsWhitespace;
588 ParagraphCommentBits.IsWhitespace = isWhitespaceNoCache();
589 ParagraphCommentBits.IsWhitespaceValid = true;
590 return ParagraphCommentBits.IsWhitespace;
594 bool isWhitespaceNoCache() const;
597 /// A command that has zero or more word-like arguments (number of word-like
598 /// arguments depends on command name) and a paragraph as an argument
599 /// (e. g., \\brief).
600 class BlockCommandComment : public BlockContentComment {
607 Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
611 /// Word-like arguments.
612 ArrayRef<Argument> Args;
614 /// Paragraph argument.
615 ParagraphComment *Paragraph;
617 BlockCommandComment(CommentKind K,
618 SourceLocation LocBegin,
619 SourceLocation LocEnd,
621 CommandMarkerKind CommandMarker) :
622 BlockContentComment(K, LocBegin, LocEnd),
624 setLocation(getCommandNameBeginLoc());
625 BlockCommandCommentBits.CommandID = CommandID;
626 BlockCommandCommentBits.CommandMarker = CommandMarker;
630 BlockCommandComment(SourceLocation LocBegin,
631 SourceLocation LocEnd,
633 CommandMarkerKind CommandMarker) :
634 BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd),
636 setLocation(getCommandNameBeginLoc());
637 BlockCommandCommentBits.CommandID = CommandID;
638 BlockCommandCommentBits.CommandMarker = CommandMarker;
641 static bool classof(const Comment *C) {
642 return C->getCommentKind() >= FirstBlockCommandCommentConstant &&
643 C->getCommentKind() <= LastBlockCommandCommentConstant;
646 child_iterator child_begin() const {
647 return reinterpret_cast<child_iterator>(&Paragraph);
650 child_iterator child_end() const {
651 return reinterpret_cast<child_iterator>(&Paragraph + 1);
654 unsigned getCommandID() const {
655 return BlockCommandCommentBits.CommandID;
658 StringRef getCommandName(const CommandTraits &Traits) const {
659 return Traits.getCommandInfo(getCommandID())->Name;
662 SourceLocation getCommandNameBeginLoc() const {
663 return getLocStart().getLocWithOffset(1);
666 SourceRange getCommandNameRange(const CommandTraits &Traits) const {
667 StringRef Name = getCommandName(Traits);
668 return SourceRange(getCommandNameBeginLoc(),
669 getLocStart().getLocWithOffset(1 + Name.size()));
672 unsigned getNumArgs() const {
676 StringRef getArgText(unsigned Idx) const {
677 return Args[Idx].Text;
680 SourceRange getArgRange(unsigned Idx) const {
681 return Args[Idx].Range;
684 void setArgs(ArrayRef<Argument> A) {
686 if (Args.size() > 0) {
687 SourceLocation NewLocEnd = Args.back().Range.getEnd();
688 if (NewLocEnd.isValid())
689 setSourceRange(SourceRange(getLocStart(), NewLocEnd));
693 ParagraphComment *getParagraph() const LLVM_READONLY {
697 bool hasNonWhitespaceParagraph() const {
698 return Paragraph && !Paragraph->isWhitespace();
701 void setParagraph(ParagraphComment *PC) {
703 SourceLocation NewLocEnd = PC->getLocEnd();
704 if (NewLocEnd.isValid())
705 setSourceRange(SourceRange(getLocStart(), NewLocEnd));
708 CommandMarkerKind getCommandMarker() const LLVM_READONLY {
709 return static_cast<CommandMarkerKind>(
710 BlockCommandCommentBits.CommandMarker);
714 /// Doxygen \\param command.
715 class ParamCommandComment : public BlockCommandComment {
717 /// Parameter index in the function declaration.
722 InvalidParamIndex = ~0U,
723 VarArgParamIndex = ~0U/*InvalidParamIndex*/ - 1U
726 ParamCommandComment(SourceLocation LocBegin,
727 SourceLocation LocEnd,
729 CommandMarkerKind CommandMarker) :
730 BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd,
731 CommandID, CommandMarker),
732 ParamIndex(InvalidParamIndex) {
733 ParamCommandCommentBits.Direction = In;
734 ParamCommandCommentBits.IsDirectionExplicit = false;
737 static bool classof(const Comment *C) {
738 return C->getCommentKind() == ParamCommandCommentKind;
747 static const char *getDirectionAsString(PassDirection D);
749 PassDirection getDirection() const LLVM_READONLY {
750 return static_cast<PassDirection>(ParamCommandCommentBits.Direction);
753 bool isDirectionExplicit() const LLVM_READONLY {
754 return ParamCommandCommentBits.IsDirectionExplicit;
757 void setDirection(PassDirection Direction, bool Explicit) {
758 ParamCommandCommentBits.Direction = Direction;
759 ParamCommandCommentBits.IsDirectionExplicit = Explicit;
762 bool hasParamName() const {
763 return getNumArgs() > 0;
766 StringRef getParamName(const FullComment *FC) const;
768 StringRef getParamNameAsWritten() const {
772 SourceRange getParamNameRange() const {
773 return Args[0].Range;
776 bool isParamIndexValid() const LLVM_READONLY {
777 return ParamIndex != InvalidParamIndex;
780 bool isVarArgParam() const LLVM_READONLY {
781 return ParamIndex == VarArgParamIndex;
784 void setIsVarArgParam() {
785 ParamIndex = VarArgParamIndex;
786 assert(isParamIndexValid());
789 unsigned getParamIndex() const LLVM_READONLY {
790 assert(isParamIndexValid());
791 assert(!isVarArgParam());
795 void setParamIndex(unsigned Index) {
797 assert(isParamIndexValid());
798 assert(!isVarArgParam());
802 /// Doxygen \\tparam command, describes a template parameter.
803 class TParamCommandComment : public BlockCommandComment {
805 /// If this template parameter name was resolved (found in template parameter
806 /// list), then this stores a list of position indexes in all template
811 /// template<typename C, template<typename T> class TT>
812 /// void test(TT<int> aaa);
814 /// For C: Position = { 0 }
815 /// For TT: Position = { 1 }
816 /// For T: Position = { 1, 0 }
817 ArrayRef<unsigned> Position;
820 TParamCommandComment(SourceLocation LocBegin,
821 SourceLocation LocEnd,
823 CommandMarkerKind CommandMarker) :
824 BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, CommandID,
828 static bool classof(const Comment *C) {
829 return C->getCommentKind() == TParamCommandCommentKind;
832 bool hasParamName() const {
833 return getNumArgs() > 0;
836 StringRef getParamName(const FullComment *FC) const;
838 StringRef getParamNameAsWritten() const {
842 SourceRange getParamNameRange() const {
843 return Args[0].Range;
846 bool isPositionValid() const LLVM_READONLY {
847 return !Position.empty();
850 unsigned getDepth() const {
851 assert(isPositionValid());
852 return Position.size();
855 unsigned getIndex(unsigned Depth) const {
856 assert(isPositionValid());
857 return Position[Depth];
860 void setPosition(ArrayRef<unsigned> NewPosition) {
861 Position = NewPosition;
862 assert(isPositionValid());
866 /// A line of text contained in a verbatim block.
867 class VerbatimBlockLineComment : public Comment {
871 VerbatimBlockLineComment(SourceLocation LocBegin,
873 Comment(VerbatimBlockLineCommentKind,
875 LocBegin.getLocWithOffset(Text.size())),
879 static bool classof(const Comment *C) {
880 return C->getCommentKind() == VerbatimBlockLineCommentKind;
883 child_iterator child_begin() const { return nullptr; }
885 child_iterator child_end() const { return nullptr; }
887 StringRef getText() const LLVM_READONLY {
892 /// A verbatim block command (e. g., preformatted code). Verbatim block has an
893 /// opening and a closing command and contains multiple lines of text
894 /// (VerbatimBlockLineComment nodes).
895 class VerbatimBlockComment : public BlockCommandComment {
898 SourceLocation CloseNameLocBegin;
899 ArrayRef<VerbatimBlockLineComment *> Lines;
902 VerbatimBlockComment(SourceLocation LocBegin,
903 SourceLocation LocEnd,
904 unsigned CommandID) :
905 BlockCommandComment(VerbatimBlockCommentKind,
906 LocBegin, LocEnd, CommandID,
907 CMK_At) // FIXME: improve source fidelity.
910 static bool classof(const Comment *C) {
911 return C->getCommentKind() == VerbatimBlockCommentKind;
914 child_iterator child_begin() const {
915 return reinterpret_cast<child_iterator>(Lines.begin());
918 child_iterator child_end() const {
919 return reinterpret_cast<child_iterator>(Lines.end());
922 void setCloseName(StringRef Name, SourceLocation LocBegin) {
924 CloseNameLocBegin = LocBegin;
927 void setLines(ArrayRef<VerbatimBlockLineComment *> L) {
931 StringRef getCloseName() const {
935 unsigned getNumLines() const {
939 StringRef getText(unsigned LineIdx) const {
940 return Lines[LineIdx]->getText();
944 /// A verbatim line command. Verbatim line has an opening command, a single
945 /// line of text (up to the newline after the opening command) and has no
947 class VerbatimLineComment : public BlockCommandComment {
950 SourceLocation TextBegin;
953 VerbatimLineComment(SourceLocation LocBegin,
954 SourceLocation LocEnd,
956 SourceLocation TextBegin,
958 BlockCommandComment(VerbatimLineCommentKind,
961 CMK_At), // FIXME: improve source fidelity.
966 static bool classof(const Comment *C) {
967 return C->getCommentKind() == VerbatimLineCommentKind;
970 child_iterator child_begin() const { return nullptr; }
972 child_iterator child_end() const { return nullptr; }
974 StringRef getText() const {
978 SourceRange getTextRange() const {
979 return SourceRange(TextBegin, getLocEnd());
983 /// Information about the declaration, useful to clients of FullComment.
985 /// Declaration the comment is actually attached to (in the source).
986 /// Should not be NULL.
987 const Decl *CommentDecl;
989 /// CurrentDecl is the declaration with which the FullComment is associated.
991 /// It can be different from \c CommentDecl. It happens when we decide
992 /// that the comment originally attached to \c CommentDecl is fine for
993 /// \c CurrentDecl too (for example, for a redeclaration or an overrider of
996 /// The information in the DeclInfo corresponds to CurrentDecl.
997 const Decl *CurrentDecl;
999 /// Parameters that can be referenced by \\param if \c CommentDecl is something
1000 /// that we consider a "function".
1001 ArrayRef<const ParmVarDecl *> ParamVars;
1003 /// Function return type if \c CommentDecl is something that we consider
1005 QualType ReturnType;
1007 /// Template parameters that can be referenced by \\tparam if \c CommentDecl is
1008 /// a template (\c IsTemplateDecl or \c IsTemplatePartialSpecialization is
1010 const TemplateParameterList *TemplateParameters;
1012 /// A simplified description of \c CommentDecl kind that should be good enough
1013 /// for documentation rendering purposes.
1015 /// Everything else not explicitly mentioned below.
1018 /// Something that we consider a "function":
1020 /// \li function template,
1021 /// \li function template specialization,
1022 /// \li member function,
1023 /// \li member function template,
1024 /// \li member function template specialization,
1025 /// \li ObjC method,
1026 /// \li a typedef for a function pointer, member function pointer,
1030 /// Something that we consider a "class":
1031 /// \li class/struct,
1032 /// \li class template,
1033 /// \li class template (partial) specialization.
1036 /// Something that we consider a "variable":
1037 /// \li namespace scope variables;
1038 /// \li static and non-static class data members;
1039 /// \li enumerators.
1042 /// A C++ namespace.
1045 /// A C++ typedef-name (a 'typedef' decl specifier or alias-declaration),
1046 /// see \c TypedefNameDecl.
1049 /// An enumeration or scoped enumeration.
1053 /// What kind of template specialization \c CommentDecl is.
1054 enum TemplateDeclKind {
1057 TemplateSpecialization,
1058 TemplatePartialSpecialization
1061 /// If false, only \c CommentDecl is valid.
1062 unsigned IsFilled : 1;
1064 /// Simplified kind of \c CommentDecl, see \c DeclKind enum.
1067 /// Is \c CommentDecl a template declaration.
1068 unsigned TemplateKind : 2;
1070 /// Is \c CommentDecl an ObjCMethodDecl.
1071 unsigned IsObjCMethod : 1;
1073 /// Is \c CommentDecl a non-static member function of C++ class or
1074 /// instance method of ObjC class.
1075 /// Can be true only if \c IsFunctionDecl is true.
1076 unsigned IsInstanceMethod : 1;
1078 /// Is \c CommentDecl a static member function of C++ class or
1079 /// class method of ObjC class.
1080 /// Can be true only if \c IsFunctionDecl is true.
1081 unsigned IsClassMethod : 1;
1085 DeclKind getKind() const LLVM_READONLY {
1086 return static_cast<DeclKind>(Kind);
1089 TemplateDeclKind getTemplateKind() const LLVM_READONLY {
1090 return static_cast<TemplateDeclKind>(TemplateKind);
1094 /// A full comment attached to a declaration, contains block content.
1095 class FullComment : public Comment {
1096 ArrayRef<BlockContentComment *> Blocks;
1097 DeclInfo *ThisDeclInfo;
1100 FullComment(ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) :
1101 Comment(FullCommentKind, SourceLocation(), SourceLocation()),
1102 Blocks(Blocks), ThisDeclInfo(D) {
1106 setSourceRange(SourceRange(Blocks.front()->getLocStart(),
1107 Blocks.back()->getLocEnd()));
1108 setLocation(Blocks.front()->getLocStart());
1111 static bool classof(const Comment *C) {
1112 return C->getCommentKind() == FullCommentKind;
1115 child_iterator child_begin() const {
1116 return reinterpret_cast<child_iterator>(Blocks.begin());
1119 child_iterator child_end() const {
1120 return reinterpret_cast<child_iterator>(Blocks.end());
1123 const Decl *getDecl() const LLVM_READONLY {
1124 return ThisDeclInfo->CommentDecl;
1127 const DeclInfo *getDeclInfo() const LLVM_READONLY {
1128 if (!ThisDeclInfo->IsFilled)
1129 ThisDeclInfo->fill();
1130 return ThisDeclInfo;
1133 ArrayRef<BlockContentComment *> getBlocks() const { return Blocks; }
1136 } // end namespace comments
1137 } // end namespace clang