Comment.h revision 0f7f10bd0ea08abf56c69fea9316275a1ee0e40c
1//===--- Comment.h - Comment AST nodes --------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file defines comment AST nodes.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_AST_COMMENT_H
15#define LLVM_CLANG_AST_COMMENT_H
16
17#include "clang/Basic/SourceLocation.h"
18#include "llvm/ADT/ArrayRef.h"
19#include "llvm/ADT/StringRef.h"
20
21namespace clang {
22namespace comments {
23
24/// Any part of the comment.
25/// Abstract class.
26class Comment {
27protected:
28  /// Preferred location to show caret.
29  SourceLocation Loc;
30
31  /// Source range of this AST node.
32  SourceRange Range;
33
34  class CommentBitfields {
35    friend class Comment;
36
37    /// Type of this AST node.
38    unsigned Kind : 8;
39  };
40  enum { NumCommentBits = 8 };
41
42  class InlineContentCommentBitfields {
43    friend class InlineContentComment;
44
45    unsigned : NumCommentBits;
46
47    /// True if there is a newline after this inline content node.
48    /// (There is no separate AST node for a newline.)
49    unsigned HasTrailingNewline : 1;
50  };
51  enum { NumInlineContentCommentBits = NumCommentBits + 1 };
52
53  class TextCommentBitfields {
54    friend class TextComment;
55
56    unsigned : NumInlineContentCommentBits;
57
58    /// True if \c IsWhitespace field contains a valid value.
59    mutable unsigned IsWhitespaceValid : 1;
60
61    /// True if this comment AST node contains only whitespace.
62    mutable unsigned IsWhitespace : 1;
63  };
64  enum { NumTextCommentBits = NumInlineContentCommentBits + 2 };
65
66  class HTMLStartTagCommentBitfields {
67    friend class HTMLStartTagComment;
68
69    unsigned : NumInlineContentCommentBits;
70
71    /// True if this tag is self-closing (e. g., <br />).  This is based on tag
72    /// spelling in comment (plain <br> would not set this flag).
73    unsigned IsSelfClosing : 1;
74  };
75
76  class ParagraphCommentBitfields {
77    friend class ParagraphComment;
78
79    unsigned : NumCommentBits;
80
81    /// True if \c IsWhitespace field contains a valid value.
82    mutable unsigned IsWhitespaceValid : 1;
83
84    /// True if this comment AST node contains only whitespace.
85    mutable unsigned IsWhitespace : 1;
86  };
87  enum { NumParagraphCommentBits = NumCommentBits + 2 };
88
89  class ParamCommandCommentBitfields {
90    friend class ParamCommandComment;
91
92    unsigned : NumCommentBits;
93
94    /// Parameter passing direction, see ParamCommandComment::PassDirection.
95    unsigned Direction : 2;
96
97    /// True if direction was specified explicitly in the comment.
98    unsigned IsDirectionExplicit : 1;
99  };
100  enum { NumParamCommandCommentBits = 11 };
101
102  union {
103    CommentBitfields CommentBits;
104    InlineContentCommentBitfields InlineContentCommentBits;
105    TextCommentBitfields TextCommentBits;
106    HTMLStartTagCommentBitfields HTMLStartTagCommentBits;
107    ParagraphCommentBitfields ParagraphCommentBits;
108    ParamCommandCommentBitfields ParamCommandCommentBits;
109  };
110
111  void setSourceRange(SourceRange SR) {
112    Range = SR;
113  }
114
115  void setLocation(SourceLocation L) {
116    Loc = L;
117  }
118
119public:
120  enum CommentKind {
121    NoCommentKind = 0,
122#define COMMENT(CLASS, PARENT) CLASS##Kind,
123#define COMMENT_RANGE(BASE, FIRST, LAST) \
124    First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind,
125#define LAST_COMMENT_RANGE(BASE, FIRST, LAST) \
126    First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind
127#define ABSTRACT_COMMENT(COMMENT)
128#include "clang/AST/CommentNodes.inc"
129  };
130
131  Comment(CommentKind K,
132          SourceLocation LocBegin,
133          SourceLocation LocEnd) :
134      Loc(LocBegin), Range(SourceRange(LocBegin, LocEnd)) {
135    CommentBits.Kind = K;
136  }
137
138  CommentKind getCommentKind() const {
139    return static_cast<CommentKind>(CommentBits.Kind);
140  }
141
142  const char *getCommentKindName() const;
143
144  LLVM_ATTRIBUTE_USED void dump() const;
145  LLVM_ATTRIBUTE_USED void dump(SourceManager &SM) const;
146  void dump(llvm::raw_ostream &OS, SourceManager *SM) const;
147
148  static bool classof(const Comment *) { return true; }
149
150  SourceRange getSourceRange() const LLVM_READONLY { return Range; }
151
152  SourceLocation getLocStart() const LLVM_READONLY {
153    return Range.getBegin();
154  }
155
156  SourceLocation getLocEnd() const LLVM_READONLY {
157    return Range.getEnd();
158  }
159
160  SourceLocation getLocation() const LLVM_READONLY { return Loc; }
161
162  typedef Comment * const *child_iterator;
163
164  child_iterator child_begin() const;
165  child_iterator child_end() const;
166
167  // TODO: const child iterator
168
169  unsigned child_count() const {
170    return child_end() - child_begin();
171  }
172};
173
174/// Inline content (contained within a block).
175/// Abstract class.
176class InlineContentComment : public Comment {
177protected:
178  InlineContentComment(CommentKind K,
179                       SourceLocation LocBegin,
180                       SourceLocation LocEnd) :
181      Comment(K, LocBegin, LocEnd) {
182    InlineContentCommentBits.HasTrailingNewline = 0;
183  }
184
185public:
186  static bool classof(const Comment *C) {
187    return C->getCommentKind() >= FirstInlineContentCommentConstant &&
188           C->getCommentKind() <= LastInlineContentCommentConstant;
189  }
190
191  static bool classof(const InlineContentComment *) { return true; }
192
193  void addTrailingNewline() {
194    InlineContentCommentBits.HasTrailingNewline = 1;
195  }
196
197  bool hasTrailingNewline() const {
198    return InlineContentCommentBits.HasTrailingNewline;
199  }
200};
201
202/// Plain text.
203class TextComment : public InlineContentComment {
204  StringRef Text;
205
206public:
207  TextComment(SourceLocation LocBegin,
208              SourceLocation LocEnd,
209              StringRef Text) :
210      InlineContentComment(TextCommentKind, LocBegin, LocEnd),
211      Text(Text) {
212    TextCommentBits.IsWhitespaceValid = false;
213  }
214
215  static bool classof(const Comment *C) {
216    return C->getCommentKind() == TextCommentKind;
217  }
218
219  static bool classof(const TextComment *) { return true; }
220
221  child_iterator child_begin() const { return NULL; }
222
223  child_iterator child_end() const { return NULL; }
224
225  StringRef getText() const LLVM_READONLY { return Text; }
226
227  bool isWhitespace() const {
228    if (TextCommentBits.IsWhitespaceValid)
229      return TextCommentBits.IsWhitespace;
230
231    TextCommentBits.IsWhitespace = isWhitespaceNoCache();
232    TextCommentBits.IsWhitespaceValid = true;
233    return TextCommentBits.IsWhitespace;
234  }
235
236private:
237  bool isWhitespaceNoCache() const;
238};
239
240/// A command with word-like arguments that is considered inline content.
241class InlineCommandComment : public InlineContentComment {
242public:
243  struct Argument {
244    SourceRange Range;
245    StringRef Text;
246
247    Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
248  };
249
250protected:
251  /// Command name.
252  StringRef Name;
253
254  /// Command arguments.
255  llvm::ArrayRef<Argument> Args;
256
257public:
258  InlineCommandComment(SourceLocation LocBegin,
259                       SourceLocation LocEnd,
260                       StringRef Name,
261                       llvm::ArrayRef<Argument> Args) :
262    InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd),
263    Name(Name), Args(Args)
264  { }
265
266  static bool classof(const Comment *C) {
267    return C->getCommentKind() == InlineCommandCommentKind;
268  }
269
270  static bool classof(const InlineCommandComment *) { return true; }
271
272  child_iterator child_begin() const { return NULL; }
273
274  child_iterator child_end() const { return NULL; }
275
276  StringRef getCommandName() const {
277    return Name;
278  }
279
280  SourceRange getCommandNameRange() const {
281    return SourceRange(getLocStart().getLocWithOffset(-1),
282                       getLocEnd());
283  }
284
285  unsigned getNumArgs() const {
286    return Args.size();
287  }
288
289  StringRef getArgText(unsigned Idx) const {
290    return Args[Idx].Text;
291  }
292
293  SourceRange getArgRange(unsigned Idx) const {
294    return Args[Idx].Range;
295  }
296};
297
298/// Abstract class for opening and closing HTML tags.  HTML tags are always
299/// treated as inline content (regardless HTML semantics); opening and closing
300/// tags are not matched.
301class HTMLTagComment : public InlineContentComment {
302protected:
303  StringRef TagName;
304  SourceRange TagNameRange;
305
306  HTMLTagComment(CommentKind K,
307                 SourceLocation LocBegin,
308                 SourceLocation LocEnd,
309                 StringRef TagName,
310                 SourceLocation TagNameBegin,
311                 SourceLocation TagNameEnd) :
312      InlineContentComment(K, LocBegin, LocEnd),
313      TagName(TagName),
314      TagNameRange(TagNameBegin, TagNameEnd) {
315    setLocation(TagNameBegin);
316  }
317
318public:
319  static bool classof(const Comment *C) {
320    return C->getCommentKind() >= FirstHTMLTagCommentConstant &&
321           C->getCommentKind() <= LastHTMLTagCommentConstant;
322  }
323
324  static bool classof(const HTMLTagComment *) { return true; }
325
326  StringRef getTagName() const LLVM_READONLY { return TagName; }
327
328  SourceRange getTagNameSourceRange() const LLVM_READONLY {
329    SourceLocation L = getLocation();
330    return SourceRange(L.getLocWithOffset(1),
331                       L.getLocWithOffset(1 + TagName.size()));
332  }
333};
334
335/// An opening HTML tag with attributes.
336class HTMLStartTagComment : public HTMLTagComment {
337public:
338  class Attribute {
339  public:
340    SourceLocation NameLocBegin;
341    StringRef Name;
342
343    SourceLocation EqualsLoc;
344
345    SourceRange ValueRange;
346    StringRef Value;
347
348    Attribute() { }
349
350    Attribute(SourceLocation NameLocBegin, StringRef Name) :
351        NameLocBegin(NameLocBegin), Name(Name),
352        EqualsLoc(SourceLocation()),
353        ValueRange(SourceRange()), Value(StringRef())
354    { }
355
356    Attribute(SourceLocation NameLocBegin, StringRef Name,
357              SourceLocation EqualsLoc,
358              SourceRange ValueRange, StringRef Value) :
359        NameLocBegin(NameLocBegin), Name(Name),
360        EqualsLoc(EqualsLoc),
361        ValueRange(ValueRange), Value(Value)
362    { }
363
364    SourceLocation getNameLocEnd() const {
365      return NameLocBegin.getLocWithOffset(Name.size());
366    }
367
368    SourceRange getNameRange() const {
369      return SourceRange(NameLocBegin, getNameLocEnd());
370    }
371  };
372
373private:
374  ArrayRef<Attribute> Attributes;
375
376public:
377  HTMLStartTagComment(SourceLocation LocBegin,
378                      StringRef TagName) :
379      HTMLTagComment(HTMLStartTagCommentKind,
380                     LocBegin, LocBegin.getLocWithOffset(1 + TagName.size()),
381                     TagName,
382                     LocBegin.getLocWithOffset(1),
383                     LocBegin.getLocWithOffset(1 + TagName.size())) {
384    HTMLStartTagCommentBits.IsSelfClosing = false;
385  }
386
387  static bool classof(const Comment *C) {
388    return C->getCommentKind() == HTMLStartTagCommentKind;
389  }
390
391  static bool classof(const HTMLStartTagComment *) { return true; }
392
393  child_iterator child_begin() const { return NULL; }
394
395  child_iterator child_end() const { return NULL; }
396
397  unsigned getNumAttrs() const {
398    return Attributes.size();
399  }
400
401  const Attribute &getAttr(unsigned Idx) const {
402    return Attributes[Idx];
403  }
404
405  void setAttrs(ArrayRef<Attribute> Attrs) {
406    Attributes = Attrs;
407    if (!Attrs.empty()) {
408      const Attribute &Attr = Attrs.back();
409      SourceLocation L = Attr.ValueRange.getEnd();
410      if (L.isValid())
411        Range.setEnd(L);
412      else {
413        Range.setEnd(Attr.getNameLocEnd());
414      }
415    }
416  }
417
418  void setGreaterLoc(SourceLocation GreaterLoc) {
419    Range.setEnd(GreaterLoc);
420  }
421
422  bool isSelfClosing() const {
423    return HTMLStartTagCommentBits.IsSelfClosing;
424  }
425
426  void setSelfClosing() {
427    HTMLStartTagCommentBits.IsSelfClosing = true;
428  }
429};
430
431/// A closing HTML tag.
432class HTMLEndTagComment : public HTMLTagComment {
433public:
434  HTMLEndTagComment(SourceLocation LocBegin,
435                    SourceLocation LocEnd,
436                    StringRef TagName) :
437      HTMLTagComment(HTMLEndTagCommentKind,
438                     LocBegin, LocEnd,
439                     TagName,
440                     LocBegin.getLocWithOffset(2),
441                     LocBegin.getLocWithOffset(2 + TagName.size()))
442  { }
443
444  static bool classof(const Comment *C) {
445    return C->getCommentKind() == HTMLEndTagCommentKind;
446  }
447
448  static bool classof(const HTMLEndTagComment *) { return true; }
449
450  child_iterator child_begin() const { return NULL; }
451
452  child_iterator child_end() const { return NULL; }
453};
454
455/// Block content (contains inline content).
456/// Abstract class.
457class BlockContentComment : public Comment {
458protected:
459  BlockContentComment(CommentKind K,
460                      SourceLocation LocBegin,
461                      SourceLocation LocEnd) :
462      Comment(K, LocBegin, LocEnd)
463  { }
464
465public:
466  static bool classof(const Comment *C) {
467    return C->getCommentKind() >= FirstBlockContentCommentConstant &&
468           C->getCommentKind() <= LastBlockContentCommentConstant;
469  }
470
471  static bool classof(const BlockContentComment *) { return true; }
472};
473
474/// A single paragraph that contains inline content.
475class ParagraphComment : public BlockContentComment {
476  llvm::ArrayRef<InlineContentComment *> Content;
477
478public:
479  ParagraphComment(llvm::ArrayRef<InlineContentComment *> Content) :
480      BlockContentComment(ParagraphCommentKind,
481                          SourceLocation(),
482                          SourceLocation()),
483      Content(Content) {
484    if (Content.empty()) {
485      ParagraphCommentBits.IsWhitespace = true;
486      ParagraphCommentBits.IsWhitespaceValid = true;
487      return;
488    }
489
490    ParagraphCommentBits.IsWhitespaceValid = false;
491
492    setSourceRange(SourceRange(Content.front()->getLocStart(),
493                               Content.back()->getLocEnd()));
494    setLocation(Content.front()->getLocStart());
495  }
496
497  static bool classof(const Comment *C) {
498    return C->getCommentKind() == ParagraphCommentKind;
499  }
500
501  static bool classof(const ParagraphComment *) { return true; }
502
503  child_iterator child_begin() const {
504    return reinterpret_cast<child_iterator>(Content.begin());
505  }
506
507  child_iterator child_end() const {
508    return reinterpret_cast<child_iterator>(Content.end());
509  }
510
511  bool isWhitespace() const {
512    if (ParagraphCommentBits.IsWhitespaceValid)
513      return ParagraphCommentBits.IsWhitespace;
514
515    ParagraphCommentBits.IsWhitespace = isWhitespaceNoCache();
516    ParagraphCommentBits.IsWhitespaceValid = true;
517    return ParagraphCommentBits.IsWhitespace;
518  }
519
520private:
521  bool isWhitespaceNoCache() const;
522};
523
524/// A command that has zero or more word-like arguments (number of word-like
525/// arguments depends on command name) and a paragraph as an argument
526/// (e. g., \\brief).
527class BlockCommandComment : public BlockContentComment {
528public:
529  struct Argument {
530    SourceRange Range;
531    StringRef Text;
532
533    Argument() { }
534    Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
535  };
536
537protected:
538  /// Command name.
539  StringRef Name;
540
541  /// Word-like arguments.
542  llvm::ArrayRef<Argument> Args;
543
544  /// Paragraph argument.
545  ParagraphComment *Paragraph;
546
547  BlockCommandComment(CommentKind K,
548                      SourceLocation LocBegin,
549                      SourceLocation LocEnd,
550                      StringRef Name) :
551      BlockContentComment(K, LocBegin, LocEnd),
552      Name(Name),
553      Paragraph(NULL) {
554    setLocation(getCommandNameRange().getBegin());
555  }
556
557public:
558  BlockCommandComment(SourceLocation LocBegin,
559                      SourceLocation LocEnd,
560                      StringRef Name) :
561      BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd),
562      Name(Name),
563      Paragraph(NULL) {
564    setLocation(getCommandNameRange().getBegin());
565  }
566
567  static bool classof(const Comment *C) {
568    return C->getCommentKind() >= FirstBlockCommandCommentConstant &&
569           C->getCommentKind() <= LastBlockCommandCommentConstant;
570  }
571
572  static bool classof(const BlockCommandComment *) { return true; }
573
574  child_iterator child_begin() const {
575    return reinterpret_cast<child_iterator>(&Paragraph);
576  }
577
578  child_iterator child_end() const {
579    return reinterpret_cast<child_iterator>(&Paragraph + 1);
580  }
581
582  StringRef getCommandName() const {
583    return Name;
584  }
585
586  SourceRange getCommandNameRange() const {
587    return SourceRange(getLocStart().getLocWithOffset(1),
588                       getLocStart().getLocWithOffset(1 + Name.size()));
589  }
590
591  unsigned getNumArgs() const {
592    return Args.size();
593  }
594
595  StringRef getArgText(unsigned Idx) const {
596    return Args[Idx].Text;
597  }
598
599  SourceRange getArgRange(unsigned Idx) const {
600    return Args[Idx].Range;
601  }
602
603  void setArgs(llvm::ArrayRef<Argument> A) {
604    Args = A;
605    if (Args.size() > 0) {
606      SourceLocation NewLocEnd = Args.back().Range.getEnd();
607      if (NewLocEnd.isValid())
608        setSourceRange(SourceRange(getLocStart(), NewLocEnd));
609    }
610  }
611
612  ParagraphComment *getParagraph() const LLVM_READONLY {
613    return Paragraph;
614  }
615
616  void setParagraph(ParagraphComment *PC) {
617    Paragraph = PC;
618    SourceLocation NewLocEnd = PC->getLocEnd();
619    if (NewLocEnd.isValid())
620      setSourceRange(SourceRange(getLocStart(), NewLocEnd));
621  }
622};
623
624/// Doxygen \\param command.
625class ParamCommandComment : public BlockCommandComment {
626private:
627  /// Parameter index in the function declaration.
628  unsigned ParamIndex;
629
630public:
631  enum { InvalidParamIndex = ~0U };
632
633  ParamCommandComment(SourceLocation LocBegin,
634                      SourceLocation LocEnd,
635                      StringRef Name) :
636      BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd, Name),
637      ParamIndex(InvalidParamIndex) {
638    ParamCommandCommentBits.Direction = In;
639    ParamCommandCommentBits.IsDirectionExplicit = false;
640  }
641
642  static bool classof(const Comment *C) {
643    return C->getCommentKind() == ParamCommandCommentKind;
644  }
645
646  static bool classof(const ParamCommandComment *) { return true; }
647
648  enum PassDirection {
649    In,
650    Out,
651    InOut
652  };
653
654  static const char *getDirectionAsString(PassDirection D);
655
656  PassDirection getDirection() const LLVM_READONLY {
657    return static_cast<PassDirection>(ParamCommandCommentBits.Direction);
658  }
659
660  bool isDirectionExplicit() const LLVM_READONLY {
661    return ParamCommandCommentBits.IsDirectionExplicit;
662  }
663
664  void setDirection(PassDirection Direction, bool Explicit) {
665    ParamCommandCommentBits.Direction = Direction;
666    ParamCommandCommentBits.IsDirectionExplicit = Explicit;
667  }
668
669  bool hasParamName() const {
670    return getNumArgs() > 0;
671  }
672
673  StringRef getParamName() const {
674    return Args[0].Text;
675  }
676
677  SourceRange getParamNameRange() const {
678    return Args[0].Range;
679  }
680
681  bool isParamIndexValid() const LLVM_READONLY {
682    return ParamIndex != InvalidParamIndex;
683  }
684
685  unsigned getParamIndex() const LLVM_READONLY {
686    return ParamIndex;
687  }
688
689  void setParamIndex(unsigned Index) {
690    ParamIndex = Index;
691    assert(isParamIndexValid());
692  }
693};
694
695/// A line of text contained in a verbatim block.
696class VerbatimBlockLineComment : public Comment {
697  StringRef Text;
698
699public:
700  VerbatimBlockLineComment(SourceLocation LocBegin,
701                           StringRef Text) :
702      Comment(VerbatimBlockLineCommentKind,
703              LocBegin,
704              LocBegin.getLocWithOffset(Text.size())),
705      Text(Text)
706  { }
707
708  static bool classof(const Comment *C) {
709    return C->getCommentKind() == VerbatimBlockLineCommentKind;
710  }
711
712  static bool classof(const VerbatimBlockLineComment *) { return true; }
713
714  child_iterator child_begin() const { return NULL; }
715
716  child_iterator child_end() const { return NULL; }
717
718  StringRef getText() const LLVM_READONLY {
719    return Text;
720  }
721};
722
723/// A verbatim block command (e. g., preformatted code).  Verbatim block has an
724/// opening and a closing command and contains multiple lines of text
725/// (VerbatimBlockLineComment nodes).
726class VerbatimBlockComment : public BlockCommandComment {
727protected:
728  StringRef CloseName;
729  SourceLocation CloseNameLocBegin;
730  llvm::ArrayRef<VerbatimBlockLineComment *> Lines;
731
732public:
733  VerbatimBlockComment(SourceLocation LocBegin,
734                       SourceLocation LocEnd,
735                       StringRef Name) :
736      BlockCommandComment(VerbatimBlockCommentKind,
737                          LocBegin, LocEnd, Name)
738  { }
739
740  static bool classof(const Comment *C) {
741    return C->getCommentKind() == VerbatimBlockCommentKind;
742  }
743
744  static bool classof(const VerbatimBlockComment *) { return true; }
745
746  child_iterator child_begin() const {
747    return reinterpret_cast<child_iterator>(Lines.begin());
748  }
749
750  child_iterator child_end() const {
751    return reinterpret_cast<child_iterator>(Lines.end());
752  }
753
754  void setCloseName(StringRef Name, SourceLocation LocBegin) {
755    CloseName = Name;
756    CloseNameLocBegin = LocBegin;
757  }
758
759  void setLines(llvm::ArrayRef<VerbatimBlockLineComment *> L) {
760    Lines = L;
761  }
762
763  StringRef getCloseName() const {
764    return CloseName;
765  }
766
767  unsigned getNumLines() const {
768    return Lines.size();
769  }
770
771  StringRef getText(unsigned LineIdx) const {
772    return Lines[LineIdx]->getText();
773  }
774};
775
776/// A verbatim line command.  Verbatim line has an opening command, a single
777/// line of text (up to the newline after the opening command) and has no
778/// closing command.
779class VerbatimLineComment : public BlockCommandComment {
780protected:
781  StringRef Text;
782  SourceLocation TextBegin;
783
784public:
785  VerbatimLineComment(SourceLocation LocBegin,
786                      SourceLocation LocEnd,
787                      StringRef Name,
788                      SourceLocation TextBegin,
789                      StringRef Text) :
790      BlockCommandComment(VerbatimLineCommentKind,
791                          LocBegin, LocEnd,
792                          Name),
793      Text(Text),
794      TextBegin(TextBegin)
795  { }
796
797  static bool classof(const Comment *C) {
798    return C->getCommentKind() == VerbatimLineCommentKind;
799  }
800
801  static bool classof(const VerbatimLineComment *) { return true; }
802
803  child_iterator child_begin() const { return NULL; }
804
805  child_iterator child_end() const { return NULL; }
806
807  StringRef getText() const {
808    return Text;
809  }
810
811  SourceRange getTextRange() const {
812    return SourceRange(TextBegin, getLocEnd());
813  }
814};
815
816/// A full comment attached to a declaration, contains block content.
817class FullComment : public Comment {
818  llvm::ArrayRef<BlockContentComment *> Blocks;
819
820public:
821  FullComment(llvm::ArrayRef<BlockContentComment *> Blocks) :
822      Comment(FullCommentKind, SourceLocation(), SourceLocation()),
823      Blocks(Blocks) {
824    if (Blocks.empty())
825      return;
826
827    setSourceRange(SourceRange(Blocks.front()->getLocStart(),
828                               Blocks.back()->getLocEnd()));
829    setLocation(Blocks.front()->getLocStart());
830  }
831
832  static bool classof(const Comment *C) {
833    return C->getCommentKind() == FullCommentKind;
834  }
835
836  static bool classof(const FullComment *) { return true; }
837
838  child_iterator child_begin() const {
839    return reinterpret_cast<child_iterator>(Blocks.begin());
840  }
841
842  child_iterator child_end() const {
843    return reinterpret_cast<child_iterator>(Blocks.end());
844  }
845};
846
847} // end namespace comments
848} // end namespace clang
849
850#endif
851
852