Coverage Report

Created: 2022-05-17 06:19

/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.17k
void cleanupBrief(std::string &S) {
21
1.17k
  bool PrevWasSpace = true;
22
1.17k
  std::string::iterator O = S.begin();
23
1.17k
  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.7k
    } else {
32
12.7k
      *O++ = C;
33
12.7k
      PrevWasSpace = false;
34
12.7k
    }
35
15.9k
  }
36
1.17k
  if (O != S.begin() && 
*(O - 1) == ' '685
)
37
684
    --O;
38
39
1.17k
  S.resize(O - S.begin());
40
1.17k
}
41
42
662
bool isWhitespace(StringRef Text) {
43
662
  return llvm::all_of(Text, clang::isWhitespace);
44
662
}
45
} // unnamed namespace
46
47
BriefParser::BriefParser(Lexer &L, const CommandTraits &Traits) :
48
901
    L(L), Traits(Traits) {
49
  // Get lookahead token.
50
901
  ConsumeToken();
51
901
}
52
53
901
std::string BriefParser::Parse() {
54
901
  std::string FirstParagraphOrBrief;
55
901
  std::string ReturnsParagraph;
56
901
  bool InFirstParagraph = true;
57
901
  bool InBrief = false;
58
901
  bool InReturns = false;
59
60
5.14k
  while (Tok.isNot(tok::eof)) {
61
4.47k
    if (Tok.is(tok::text)) {
62
1.63k
      if (InFirstParagraph || 
InBrief496
)
63
1.14k
        FirstParagraphOrBrief += Tok.getText();
64
482
      else if (InReturns)
65
82
        ReturnsParagraph += Tok.getText();
66
1.63k
      ConsumeToken();
67
1.63k
      continue;
68
1.63k
    }
69
70
2.84k
    if (Tok.is(tok::backslash_command) || 
Tok.is(tok::at_command)2.13k
) {
71
747
      const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
72
747
      if (Info->IsBriefCommand) {
73
251
        FirstParagraphOrBrief.clear();
74
251
        InBrief = true;
75
251
        ConsumeToken();
76
251
        continue;
77
251
      }
78
496
      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
414
      if (Info->IsBlockCommand) {
88
        // We found an implicit paragraph end.
89
366
        InFirstParagraph = false;
90
366
        if (InBrief)
91
57
          break;
92
366
      }
93
414
    }
94
95
2.45k
    if (Tok.is(tok::newline)) {
96
1.64k
      if (InFirstParagraph || 
InBrief514
)
97
1.14k
        FirstParagraphOrBrief += ' ';
98
495
      else if (InReturns)
99
82
        ReturnsParagraph += ' ';
100
1.64k
      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.64k
      if (Tok.is(tok::text)) {
108
546
        if (isWhitespace(Tok.getText()))
109
437
          ConsumeToken();
110
546
      }
111
112
1.64k
      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.47k
      continue;
127
1.64k
    }
128
129
    // We didn't handle this token, so just drop it.
130
811
    ConsumeToken();
131
811
  }
132
133
901
  cleanupBrief(FirstParagraphOrBrief);
134
901
  if (!FirstParagraphOrBrief.empty())
135
631
    return FirstParagraphOrBrief;
136
137
270
  cleanupBrief(ReturnsParagraph);
138
270
  return ReturnsParagraph;
139
901
}
140
141
} // end namespace comments
142
} // end namespace clang
143
144