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