Coverage Report

Created: 2020-11-24 06:42

/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
12
namespace clang {
13
namespace comments {
14
15
namespace {
16
16.7k
inline bool isWhitespace(char C) {
17
16.7k
  return C == ' ' || 
C == '\n'12.5k
||
C == '\r'12.5k
||
18
12.5k
         C == '\t' || 
C == '\f'12.5k
||
C == '\v'12.5k
;
19
16.7k
}
20
21
/// Convert all whitespace into spaces, remove leading and trailing spaces,
22
/// compress multiple spaces into one.
23
1.15k
void cleanupBrief(std::string &S) {
24
1.15k
  bool PrevWasSpace = true;
25
1.15k
  std::string::iterator O = S.begin();
26
1.15k
  for (std::string::iterator I = S.begin(), E = S.end();
27
16.7k
       I != E; 
++I15.6k
) {
28
15.6k
    const char C = *I;
29
15.6k
    if (isWhitespace(C)) {
30
3.23k
      if (!PrevWasSpace) {
31
1.86k
        *O++ = ' ';
32
1.86k
        PrevWasSpace = true;
33
1.86k
      }
34
3.23k
      continue;
35
12.3k
    } else {
36
12.3k
      *O++ = C;
37
12.3k
      PrevWasSpace = false;
38
12.3k
    }
39
15.6k
  }
40
1.15k
  if (O != S.begin() && 
*(O - 1) == ' '676
)
41
676
    --O;
42
43
1.15k
  S.resize(O - S.begin());
44
1.15k
}
45
46
640
bool isWhitespace(StringRef Text) {
47
640
  for (StringRef::const_iterator I = Text.begin(), E = Text.end();
48
1.56k
       I != E; 
++I924
) {
49
1.12k
    if (!isWhitespace(*I))
50
201
      return false;
51
1.12k
  }
52
439
  return true;
53
640
}
54
} // unnamed namespace
55
56
BriefParser::BriefParser(Lexer &L, const CommandTraits &Traits) :
57
891
    L(L), Traits(Traits) {
58
  // Get lookahead token.
59
891
  ConsumeToken();
60
891
}
61
62
891
std::string BriefParser::Parse() {
63
891
  std::string FirstParagraphOrBrief;
64
891
  std::string ReturnsParagraph;
65
891
  bool InFirstParagraph = true;
66
891
  bool InBrief = false;
67
891
  bool InReturns = false;
68
69
5.04k
  while (Tok.isNot(tok::eof)) {
70
4.38k
    if (Tok.is(tok::text)) {
71
1.59k
      if (InFirstParagraph || 
InBrief475
)
72
1.13k
        FirstParagraphOrBrief += Tok.getText();
73
461
      else if (InReturns)
74
78
        ReturnsParagraph += Tok.getText();
75
1.59k
      ConsumeToken();
76
1.59k
      continue;
77
1.59k
    }
78
79
2.78k
    if (Tok.is(tok::backslash_command) || 
Tok.is(tok::at_command)2.09k
) {
80
726
      const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
81
726
      if (Info->IsBriefCommand) {
82
250
        FirstParagraphOrBrief.clear();
83
250
        InBrief = true;
84
250
        ConsumeToken();
85
250
        continue;
86
250
      }
87
476
      if (Info->IsReturnsCommand) {
88
78
        InReturns = true;
89
78
        InBrief = false;
90
78
        InFirstParagraph = false;
91
78
        ReturnsParagraph += "Returns ";
92
78
        ConsumeToken();
93
78
        continue;
94
78
      }
95
      // Block commands implicitly start a new paragraph.
96
398
      if (Info->IsBlockCommand) {
97
        // We found an implicit paragraph end.
98
356
        InFirstParagraph = false;
99
356
        if (InBrief)
100
57
          break;
101
2.40k
      }
102
398
    }
103
104
2.40k
    if (Tok.is(tok::newline)) {
105
1.60k
      if (InFirstParagraph || 
InBrief494
)
106
1.13k
        FirstParagraphOrBrief += ' ';
107
475
      else if (InReturns)
108
78
        ReturnsParagraph += ' ';
109
1.60k
      ConsumeToken();
110
111
      // If the next token is a whitespace only text, ignore it.  Thus we allow
112
      // two paragraphs to be separated by line that has only whitespace in it.
113
      //
114
      // We don't need to add a space to the parsed text because we just added
115
      // a space for the newline.
116
1.60k
      if (Tok.is(tok::text)) {
117
528
        if (isWhitespace(Tok.getText()))
118
425
          ConsumeToken();
119
528
      }
120
121
1.60k
      if (Tok.is(tok::newline)) {
122
345
        ConsumeToken();
123
        // We found a paragraph end.  This ends the brief description if
124
        // \command or its equivalent was explicitly used.
125
        // Stop scanning text because an explicit \paragraph is the
126
        // preffered one.
127
345
        if (InBrief)
128
169
          break;
129
        // End first paragraph if we found some non-whitespace text.
130
176
        if (InFirstParagraph && 
!isWhitespace(FirstParagraphOrBrief)112
)
131
98
          InFirstParagraph = false;
132
        // End the \\returns paragraph because we found the paragraph end.
133
176
        InReturns = false;
134
176
      }
135
1.43k
      continue;
136
796
    }
137
138
    // We didn't handle this token, so just drop it.
139
796
    ConsumeToken();
140
796
  }
141
142
891
  cleanupBrief(FirstParagraphOrBrief);
143
891
  if (!FirstParagraphOrBrief.empty())
144
623
    return FirstParagraphOrBrief;
145
146
268
  cleanupBrief(ReturnsParagraph);
147
268
  return ReturnsParagraph;
148
268
}
149
150
} // end namespace comments
151
} // end namespace clang
152
153