Coverage Report

Created: 2021-08-24 07:12

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Format/FormatToken.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- FormatToken.cpp - Format C++ code --------------------------------===//
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
/// \file
10
/// This file implements specific functions of \c FormatTokens and their
11
/// roles.
12
///
13
//===----------------------------------------------------------------------===//
14
15
#include "FormatToken.h"
16
#include "ContinuationIndenter.h"
17
#include "llvm/ADT/SmallVector.h"
18
#include "llvm/Support/Debug.h"
19
#include <climits>
20
21
namespace clang {
22
namespace format {
23
24
0
const char *getTokenTypeName(TokenType Type) {
25
0
  static const char *const TokNames[] = {
26
0
#define TYPE(X) #X,
27
0
      LIST_TOKEN_TYPES
28
0
#undef TYPE
29
0
      nullptr};
30
31
0
  if (Type < NUM_TOKEN_TYPES)
32
0
    return TokNames[Type];
33
0
  llvm_unreachable("unknown TokenType");
34
0
  return nullptr;
35
0
}
36
37
// FIXME: This is copy&pasted from Sema. Put it in a common place and remove
38
// duplication.
39
241k
bool FormatToken::isSimpleTypeSpecifier() const {
40
241k
  switch (Tok.getKind()) {
41
17
  case tok::kw_short:
42
58
  case tok::kw_long:
43
58
  case tok::kw___int64:
44
58
  case tok::kw___int128:
45
58
  case tok::kw_signed:
46
418
  case tok::kw_unsigned:
47
9.69k
  case tok::kw_void:
48
9.90k
  case tok::kw_char:
49
26.9k
  case tok::kw_int:
50
26.9k
  case tok::kw_half:
51
27.3k
  case tok::kw_float:
52
27.5k
  case tok::kw_double:
53
27.5k
  case tok::kw___bf16:
54
27.5k
  case tok::kw__Float16:
55
27.5k
  case tok::kw___float128:
56
27.5k
  case tok::kw_wchar_t:
57
28.3k
  case tok::kw_bool:
58
28.3k
  case tok::kw___underlying_type:
59
28.3k
  case tok::annot_typename:
60
28.4k
  case tok::kw_char8_t:
61
28.4k
  case tok::kw_char16_t:
62
28.4k
  case tok::kw_char32_t:
63
28.4k
  case tok::kw_typeof:
64
28.5k
  case tok::kw_decltype:
65
28.6k
  case tok::kw__Atomic:
66
28.6k
    return true;
67
212k
  default:
68
212k
    return false;
69
241k
  }
70
241k
}
71
72
10.6k
TokenRole::~TokenRole() {}
73
74
0
void TokenRole::precomputeFormattingInfos(const FormatToken *Token) {}
75
76
unsigned CommaSeparatedList::formatAfterToken(LineState &State,
77
                                              ContinuationIndenter *Indenter,
78
137k
                                              bool DryRun) {
79
137k
  if (State.NextToken == nullptr || 
!State.NextToken->Previous137k
)
80
1
    return 0;
81
82
137k
  if (Formats.size() == 1)
83
108
    return 0; // Handled by formatFromToken
84
85
  // Ensure that we start on the opening brace.
86
137k
  const FormatToken *LBrace =
87
137k
      State.NextToken->Previous->getPreviousNonComment();
88
137k
  if (!LBrace || !LBrace->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
89
137k
      
LBrace->is(BK_Block)13.5k
||
LBrace->is(TT_DictLiteral)13.1k
||
90
137k
      
LBrace->Next->is(TT_DesignatedInitializerPeriod)12.6k
)
91
124k
    return 0;
92
93
  // Calculate the number of code points we have to format this list. As the
94
  // first token is already placed, we have to subtract it.
95
12.6k
  unsigned RemainingCodePoints =
96
12.6k
      Style.ColumnLimit - State.Column + State.NextToken->Previous->ColumnWidth;
97
98
  // Find the best ColumnFormat, i.e. the best number of columns to use.
99
12.6k
  const ColumnFormat *Format = getColumnFormat(RemainingCodePoints);
100
101
  // If no ColumnFormat can be used, the braced list would generally be
102
  // bin-packed. Add a severe penalty to this so that column layouts are
103
  // preferred if possible.
104
12.6k
  if (!Format)
105
12.1k
    return 10000;
106
107
  // Format the entire list.
108
424
  unsigned Penalty = 0;
109
424
  unsigned Column = 0;
110
424
  unsigned Item = 0;
111
20.1k
  while (State.NextToken != LBrace->MatchingParen) {
112
19.7k
    bool NewLine = false;
113
19.7k
    unsigned ExtraSpaces = 0;
114
115
    // If the previous token was one of our commas, we are now on the next item.
116
19.7k
    if (Item < Commas.size() && 
State.NextToken->Previous == Commas[Item]19.1k
) {
117
6.63k
      if (!State.NextToken->isTrailingComment()) {
118
6.42k
        ExtraSpaces += Format->ColumnSizes[Column] - ItemLengths[Item];
119
6.42k
        ++Column;
120
6.42k
      }
121
6.63k
      ++Item;
122
6.63k
    }
123
124
19.7k
    if (Column == Format->Columns || 
State.NextToken->MustBreakBefore19.1k
) {
125
851
      Column = 0;
126
851
      NewLine = true;
127
851
    }
128
129
    // Place token using the continuation indenter and store the penalty.
130
19.7k
    Penalty += Indenter->addTokenToState(State, NewLine, DryRun, ExtraSpaces);
131
19.7k
  }
132
424
  return Penalty;
133
12.6k
}
134
135
unsigned CommaSeparatedList::formatFromToken(LineState &State,
136
                                             ContinuationIndenter *Indenter,
137
84.2k
                                             bool DryRun) {
138
  // Formatting with 1 Column isn't really a column layout, so we don't need the
139
  // special logic here. We can just avoid bin packing any of the parameters.
140
84.2k
  if (Formats.size() == 1 || 
HasNestedBracedList84.1k
)
141
1.67k
    State.Stack.back().AvoidBinPacking = true;
142
84.2k
  return 0;
143
84.2k
}
144
145
// Returns the lengths in code points between Begin and End (both included),
146
// assuming that the entire sequence is put on a single line.
147
static unsigned CodePointsBetween(const FormatToken *Begin,
148
10.2k
                                  const FormatToken *End) {
149
10.2k
  assert(End->TotalLength >= Begin->TotalLength);
150
0
  return End->TotalLength - Begin->TotalLength + Begin->ColumnWidth;
151
10.2k
}
152
153
4.74k
void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) {
154
  // FIXME: At some point we might want to do this for other lists, too.
155
4.74k
  if (!Token->MatchingParen ||
156
4.74k
      
!Token->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare)4.72k
)
157
3.04k
    return;
158
159
  // In C++11 braced list style, we should not format in columns unless they
160
  // have many items (20 or more) or we allow bin-packing of function call
161
  // arguments.
162
1.70k
  if (Style.Cpp11BracedListStyle && 
!Style.BinPackArguments1.53k
&&
163
1.70k
      
Commas.size() < 1934
)
164
31
    return;
165
166
  // Limit column layout for JavaScript array initializers to 20 or more items
167
  // for now to introduce it carefully. We can become more aggressive if this
168
  // necessary.
169
1.66k
  if (Token->is(TT_ArrayInitializerLSquare) && 
Commas.size() < 19149
)
170
145
    return;
171
172
  // Column format doesn't really make sense if we don't align after brackets.
173
1.52k
  if (Style.AlignAfterOpenBracket == FormatStyle::BAS_DontAlign)
174
18
    return;
175
176
1.50k
  FormatToken *ItemBegin = Token->Next;
177
1.54k
  while (ItemBegin->isTrailingComment())
178
42
    ItemBegin = ItemBegin->Next;
179
1.50k
  SmallVector<bool, 8> MustBreakBeforeItem;
180
181
  // The lengths of an item if it is put at the end of the line. This includes
182
  // trailing comments which are otherwise ignored for column alignment.
183
1.50k
  SmallVector<unsigned, 8> EndOfLineItemLength;
184
185
1.50k
  bool HasSeparatingComment = false;
186
6.23k
  for (unsigned i = 0, e = Commas.size() + 1; i != e; 
++i4.73k
) {
187
    // Skip comments on their own line.
188
5.15k
    while (ItemBegin->HasUnescapedNewline && 
ItemBegin->isTrailingComment()827
) {
189
43
      ItemBegin = ItemBegin->Next;
190
43
      HasSeparatingComment = i > 0;
191
43
    }
192
193
5.11k
    MustBreakBeforeItem.push_back(ItemBegin->MustBreakBefore);
194
5.11k
    if (ItemBegin->is(tok::l_brace))
195
543
      HasNestedBracedList = true;
196
5.11k
    const FormatToken *ItemEnd = nullptr;
197
5.11k
    if (i == Commas.size()) {
198
1.28k
      ItemEnd = Token->MatchingParen;
199
1.28k
      const FormatToken *NonCommentEnd = ItemEnd->getPreviousNonComment();
200
1.28k
      ItemLengths.push_back(CodePointsBetween(ItemBegin, NonCommentEnd));
201
1.28k
      if (Style.Cpp11BracedListStyle &&
202
1.28k
          
!ItemEnd->Previous->isTrailingComment()1.16k
) {
203
        // In Cpp11 braced list style, the } and possibly other subsequent
204
        // tokens will need to stay on a line with the last element.
205
2.47k
        while (ItemEnd->Next && 
!ItemEnd->Next->CanBreakBefore1.81k
)
206
1.35k
          ItemEnd = ItemEnd->Next;
207
1.12k
      } else {
208
        // In other braced lists styles, the "}" can be wrapped to the new line.
209
156
        ItemEnd = Token->MatchingParen->Previous;
210
156
      }
211
3.82k
    } else {
212
3.82k
      ItemEnd = Commas[i];
213
      // The comma is counted as part of the item when calculating the length.
214
3.82k
      ItemLengths.push_back(CodePointsBetween(ItemBegin, ItemEnd));
215
216
      // Consume trailing comments so the are included in EndOfLineItemLength.
217
3.82k
      if (ItemEnd->Next && !ItemEnd->Next->HasUnescapedNewline &&
218
3.82k
          
ItemEnd->Next->isTrailingComment()3.32k
)
219
129
        ItemEnd = ItemEnd->Next;
220
3.82k
    }
221
5.11k
    EndOfLineItemLength.push_back(CodePointsBetween(ItemBegin, ItemEnd));
222
    // If there is a trailing comma in the list, the next item will start at the
223
    // closing brace. Don't create an extra item for this.
224
5.11k
    if (ItemEnd->getNextNonComment() == Token->MatchingParen)
225
380
      break;
226
4.73k
    ItemBegin = ItemEnd->Next;
227
4.73k
  }
228
229
  // Don't use column layout for lists with few elements and in presence of
230
  // separating comments.
231
1.50k
  if (Commas.size() < 5 || 
HasSeparatingComment102
)
232
1.40k
    return;
233
234
99
  if (Token->NestingLevel != 0 && 
Token->is(tok::l_brace)14
&&
Commas.size() < 1912
)
235
9
    return;
236
237
  // We can never place more than ColumnLimit / 3 items in a row (because of the
238
  // spaces and the comma).
239
90
  unsigned MaxItems = Style.ColumnLimit / 3;
240
90
  std::vector<unsigned> MinSizeInColumn;
241
90
  MinSizeInColumn.reserve(MaxItems);
242
1.04k
  for (unsigned Columns = 1; Columns <= MaxItems; 
++Columns959
) {
243
1.03k
    ColumnFormat Format;
244
1.03k
    Format.Columns = Columns;
245
1.03k
    Format.ColumnSizes.resize(Columns);
246
1.03k
    MinSizeInColumn.assign(Columns, UINT_MAX);
247
1.03k
    Format.LineCount = 1;
248
1.03k
    bool HasRowWithSufficientColumns = false;
249
1.03k
    unsigned Column = 0;
250
21.8k
    for (unsigned i = 0, e = ItemLengths.size(); i != e; 
++i20.7k
) {
251
20.7k
      assert(i < MustBreakBeforeItem.size());
252
20.7k
      if (MustBreakBeforeItem[i] || 
Column == Columns20.2k
) {
253
3.80k
        ++Format.LineCount;
254
3.80k
        Column = 0;
255
3.80k
      }
256
20.7k
      if (Column == Columns - 1)
257
3.68k
        HasRowWithSufficientColumns = true;
258
20.7k
      unsigned Length =
259
20.7k
          (Column == Columns - 1) ? 
EndOfLineItemLength[i]3.68k
:
ItemLengths[i]17.1k
;
260
20.7k
      Format.ColumnSizes[Column] = std::max(Format.ColumnSizes[Column], Length);
261
20.7k
      MinSizeInColumn[Column] = std::min(MinSizeInColumn[Column], Length);
262
20.7k
      ++Column;
263
20.7k
    }
264
    // If all rows are terminated early (e.g. by trailing comments), we don't
265
    // need to look further.
266
1.03k
    if (!HasRowWithSufficientColumns)
267
78
      break;
268
959
    Format.TotalWidth = Columns - 1; // Width of the N-1 spaces.
269
270
8.76k
    for (unsigned i = 0; i < Columns; 
++i7.80k
)
271
7.80k
      Format.TotalWidth += Format.ColumnSizes[i];
272
273
    // Don't use this Format, if the difference between the longest and shortest
274
    // element in a column exceeds a threshold to avoid excessive spaces.
275
959
    if ([&] {
276
7.44k
          for (unsigned i = 0; i < Columns - 1; 
++i6.49k
)
277
6.61k
            if (Format.ColumnSizes[i] - MinSizeInColumn[i] > 10)
278
129
              return true;
279
830
          return false;
280
959
        }())
281
129
      continue;
282
283
    // Ignore layouts that are bound to violate the column limit.
284
830
    if (Format.TotalWidth > Style.ColumnLimit && 
Columns > 1234
)
285
234
      continue;
286
287
596
    Formats.push_back(Format);
288
596
  }
289
90
}
290
291
const CommaSeparatedList::ColumnFormat *
292
12.6k
CommaSeparatedList::getColumnFormat(unsigned RemainingCharacters) const {
293
12.6k
  const ColumnFormat *BestFormat = nullptr;
294
12.6k
  for (SmallVector<ColumnFormat, 4>::const_reverse_iterator
295
12.6k
           I = Formats.rbegin(),
296
12.6k
           E = Formats.rend();
297
14.0k
       I != E; 
++I1.40k
) {
298
1.83k
    if (I->TotalWidth <= RemainingCharacters || 
I->Columns == 1485
) {
299
1.34k
      if (BestFormat && 
I->LineCount > BestFormat->LineCount923
)
300
424
        break;
301
923
      BestFormat = &*I;
302
923
    }
303
1.83k
  }
304
12.6k
  return BestFormat;
305
12.6k
}
306
307
} // namespace format
308
} // namespace clang