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