clang  6.0.0svn
CommentBriefParser.cpp
Go to the documentation of this file.
1 //===--- CommentBriefParser.cpp - Dumb comment parser ---------------------===//
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 
12 
13 namespace clang {
14 namespace comments {
15 
16 namespace {
17 inline bool isWhitespace(char C) {
18  return C == ' ' || C == '\n' || C == '\r' ||
19  C == '\t' || C == '\f' || C == '\v';
20 }
21 
22 /// Convert all whitespace into spaces, remove leading and trailing spaces,
23 /// compress multiple spaces into one.
24 void cleanupBrief(std::string &S) {
25  bool PrevWasSpace = true;
26  std::string::iterator O = S.begin();
27  for (std::string::iterator I = S.begin(), E = S.end();
28  I != E; ++I) {
29  const char C = *I;
30  if (isWhitespace(C)) {
31  if (!PrevWasSpace) {
32  *O++ = ' ';
33  PrevWasSpace = true;
34  }
35  continue;
36  } else {
37  *O++ = C;
38  PrevWasSpace = false;
39  }
40  }
41  if (O != S.begin() && *(O - 1) == ' ')
42  --O;
43 
44  S.resize(O - S.begin());
45 }
46 
47 bool isWhitespace(StringRef Text) {
48  for (StringRef::const_iterator I = Text.begin(), E = Text.end();
49  I != E; ++I) {
50  if (!isWhitespace(*I))
51  return false;
52  }
53  return true;
54 }
55 } // unnamed namespace
56 
58  L(L), Traits(Traits) {
59  // Get lookahead token.
60  ConsumeToken();
61 }
62 
63 std::string BriefParser::Parse() {
64  std::string FirstParagraphOrBrief;
65  std::string ReturnsParagraph;
66  bool InFirstParagraph = true;
67  bool InBrief = false;
68  bool InReturns = false;
69 
70  while (Tok.isNot(tok::eof)) {
71  if (Tok.is(tok::text)) {
72  if (InFirstParagraph || InBrief)
73  FirstParagraphOrBrief += Tok.getText();
74  else if (InReturns)
75  ReturnsParagraph += Tok.getText();
76  ConsumeToken();
77  continue;
78  }
79 
80  if (Tok.is(tok::backslash_command) || Tok.is(tok::at_command)) {
81  const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
82  if (Info->IsBriefCommand) {
83  FirstParagraphOrBrief.clear();
84  InBrief = true;
85  ConsumeToken();
86  continue;
87  }
88  if (Info->IsReturnsCommand) {
89  InReturns = true;
90  InBrief = false;
91  InFirstParagraph = false;
92  ReturnsParagraph += "Returns ";
93  ConsumeToken();
94  continue;
95  }
96  // Block commands implicitly start a new paragraph.
97  if (Info->IsBlockCommand) {
98  // We found an implicit paragraph end.
99  InFirstParagraph = false;
100  if (InBrief)
101  break;
102  }
103  }
104 
105  if (Tok.is(tok::newline)) {
106  if (InFirstParagraph || InBrief)
107  FirstParagraphOrBrief += ' ';
108  else if (InReturns)
109  ReturnsParagraph += ' ';
110  ConsumeToken();
111 
112  // If the next token is a whitespace only text, ignore it. Thus we allow
113  // two paragraphs to be separated by line that has only whitespace in it.
114  //
115  // We don't need to add a space to the parsed text because we just added
116  // a space for the newline.
117  if (Tok.is(tok::text)) {
118  if (isWhitespace(Tok.getText()))
119  ConsumeToken();
120  }
121 
122  if (Tok.is(tok::newline)) {
123  ConsumeToken();
124  // We found a paragraph end. This ends the brief description if
125  // \\brief command or its equivalent was explicitly used.
126  // Stop scanning text because an explicit \\brief paragraph is the
127  // preffered one.
128  if (InBrief)
129  break;
130  // End first paragraph if we found some non-whitespace text.
131  if (InFirstParagraph && !isWhitespace(FirstParagraphOrBrief))
132  InFirstParagraph = false;
133  // End the \\returns paragraph because we found the paragraph end.
134  InReturns = false;
135  }
136  continue;
137  }
138 
139  // We didn't handle this token, so just drop it.
140  ConsumeToken();
141  }
142 
143  cleanupBrief(FirstParagraphOrBrief);
144  if (!FirstParagraphOrBrief.empty())
145  return FirstParagraphOrBrief;
146 
147  cleanupBrief(ReturnsParagraph);
148  return ReturnsParagraph;
149 }
150 
151 } // end namespace comments
152 } // end namespace clang
153 
154 
Information about a single command.
bool isNot(tok::TokenKind K) const LLVM_READONLY
Definition: CommentLexer.h:94
LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t', '\f', '\v', '\n', '\r'.
Definition: CharInfo.h:88
unsigned IsBriefCommand
True if this command is introducing a brief documentation paragraph (\brief or an alias)...
bool is(tok::TokenKind K) const LLVM_READONLY
Definition: CommentLexer.h:93
This class provides information about commands that can be used in comments.
Comment lexer.
Definition: CommentLexer.h:221
const CommandInfo * getCommandInfo(StringRef Name) const
Dataflow Directional Tag Classes.
std::string Parse()
Return the best "brief description" we can find.
unsigned getCommandID() const LLVM_READONLY
Definition: CommentLexer.h:121
unsigned IsBlockCommand
True if this command is a block command (of any kind).
unsigned IsReturnsCommand
True if this command is \returns or an alias.
StringRef getText() const LLVM_READONLY
Definition: CommentLexer.h:99
StringRef Text
Definition: Format.cpp:1346
BriefParser(Lexer &L, const CommandTraits &Traits)