Coverage Report

Created: 2022-01-25 06:29

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/CommentBriefParser.cpp
Line
Count
Source
1
//===--- CommentBriefParser.cpp - Dumb comment parser ---------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "clang/AST/CommentBriefParser.h"
10
#include "clang/AST/CommentCommandTraits.h"
11
#include "clang/Basic/CharInfo.h"
12
13
namespace clang {
14
namespace comments {
15
16
namespace {
17
18
/// Convert all whitespace into spaces, remove leading and trailing spaces,
19
/// compress multiple spaces into one.
20
1.16k
void cleanupBrief(std::string &S) {
21
1.16k
  bool PrevWasSpace = true;
22
1.16k
  std::string::iterator O = S.begin();
23
1.16k
  for (std::string::iterator I = S.begin(), E = S.end();
24
17.1k
       I != E; 
++I15.9k
) {
25
15.9k
    const char C = *I;
26
15.9k
    if (clang::isWhitespace(C)) {
27
3.28k
      if (!PrevWasSpace) {
28
1.90k
        *O++ = ' ';
29
1.90k
        PrevWasSpace = true;
30
1.90k
      }
31
12.6k
    } else {
32
12.6k
      *O++ = C;
33
12.6k
      PrevWasSpace = false;
34
12.6k
    }
35
15.9k
  }
36
1.16k
  if (O != S.begin() && 
*(O - 1) == ' '684
)
37
684
    --O;
38
39
1.16k
  S.resize(O - S.begin());
40
1.16k
}
41
42
661
bool isWhitespace(StringRef Text) {
43
661
  return llvm::all_of(Text, clang::isWhitespace);
44
661
}
45
} // unnamed namespace
46
47
BriefParser::BriefParser(Lexer &L, const CommandTraits &Traits) :
48
899
    L(L), Traits(Traits) {
49
  // Get lookahead token.
50
899
  ConsumeToken();
51
899
}
52
53
899
std::string BriefParser::Parse() {
54
899
  std::string FirstParagraphOrBrief;
55
899
  std::string ReturnsParagraph;
56
899
  bool InFirstParagraph = true;
57
899
  bool InBrief = false;
58
899
  bool InReturns = false;
59
60
5.13k
  while (Tok.isNot(tok::eof)) {
61
4.45k
    if (Tok.is(tok::text)) {
62
1.62k
      if (InFirstParagraph || 
InBrief493
)
63
1.14k
        FirstParagraphOrBrief += Tok.getText();
64
479
      else if (InReturns)
65
82
        ReturnsParagraph += Tok.getText();
66
1.62k
      ConsumeToken();
67
1.62k
      continue;
68
1.62k
    }
69
70
2.83k
    if (Tok.is(tok::backslash_command) || 
Tok.is(tok::at_command)2.13k
) {
71
740
      const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
72
740
      if (Info->IsBriefCommand) {
73
251
        FirstParagraphOrBrief.clear();
74
251
        InBrief = true;
75
251
        ConsumeToken();
76
251
        continue;
77
251
      }
78
489
      if (Info->IsReturnsCommand) {
79
82
        InReturns = true;
80
82
        InBrief = false;
81
82
        InFirstParagraph = false;
82
82
        ReturnsParagraph += "Returns ";
83
82
        ConsumeToken();
84
82
        continue;
85
82
      }
86
      // Block commands implicitly start a new paragraph.
87
407
      if (Info->IsBlockCommand) {
88
        // We found an implicit paragraph end.
89
363
        InFirstParagraph = false;
90
363
        if (InBrief)
91
57
          break;
92
363
      }
93
407
    }
94
95
2.44k
    if (Tok.is(tok::newline)) {
96
1.63k
      if (InFirstParagraph || 
InBrief511
)
97
1.14k
        FirstParagraphOrBrief += ' ';
98
492
      else if (InReturns)
99
82
        ReturnsParagraph += ' ';
100
1.63k
      ConsumeToken();
101
102
      // If the next token is a whitespace only text, ignore it.  Thus we allow
103
      // two paragraphs to be separated by line that has only whitespace in it.
104
      //
105
      // We don't need to add a space to the parsed text because we just added
106
      // a space for the newline.
107
1.63k
      if (Tok.is(tok::text)) {
108
545
        if (isWhitespace(Tok.getText()))
109
436
          ConsumeToken();
110
545
      }
111
112
1.63k
      if (Tok.is(tok::newline)) {
113
354
        ConsumeToken();
114
        // We found a paragraph end.  This ends the brief description if
115
        // \command or its equivalent was explicitly used.
116
        // Stop scanning text because an explicit \paragraph is the
117
        // preferred one.
118
354
        if (InBrief)
119
169
          break;
120
        // End first paragraph if we found some non-whitespace text.
121
185
        if (InFirstParagraph && 
!isWhitespace(FirstParagraphOrBrief)116
)
122
102
          InFirstParagraph = false;
123
        // End the \\returns paragraph because we found the paragraph end.
124
185
        InReturns = false;
125
185
      }
126
1.46k
      continue;
127
1.63k
    }
128
129
    // We didn't handle this token, so just drop it.
130
808
    ConsumeToken();
131
808
  }
132
133
899
  cleanupBrief(FirstParagraphOrBrief);
134
899
  if (!FirstParagraphOrBrief.empty())
135
630
    return FirstParagraphOrBrief;
136
137
269
  cleanupBrief(ReturnsParagraph);
138
269
  return ReturnsParagraph;
139
899
}
140
141
} // end namespace comments
142
} // end namespace clang
143
144