Coverage Report

Created: 2022-05-17 06:19

/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
391k
bool FormatToken::isSimpleTypeSpecifier() const {
40
391k
  switch (Tok.getKind()) {
41
21
  case tok::kw_short:
42
427
  case tok::kw_long:
43
427
  case tok::kw___int64:
44
427
  case tok::kw___int128:
45
427
  case tok::kw_signed:
46
1.31k
  case tok::kw_unsigned:
47
14.2k
  case tok::kw_void:
48
15.0k
  case tok::kw_char:
49
48.4k
  case tok::kw_int:
50
48.4k
  case tok::kw_half:
51
48.8k
  case tok::kw_float:
52
49.2k
  case tok::kw_double:
53
49.2k
  case tok::kw___bf16:
54
49.2k
  case tok::kw__Float16:
55
49.2k
  case tok::kw___float128:
56
49.2k
  case tok::kw___ibm128:
57
49.2k
  case tok::kw_wchar_t:
58
50.6k
  case tok::kw_bool:
59
50.7k
  case tok::kw___underlying_type:
60
50.7k
  case tok::annot_typename:
61
50.7k
  case tok::kw_char8_t:
62
50.7k
  case tok::kw_char16_t:
63
50.7k
  case tok::kw_char32_t:
64
50.8k
  case tok::kw_typeof:
65
50.8k
  case tok::kw_decltype:
66
51.0k
  case tok::kw__Atomic:
67
51.0k
    return true;
68
340k
  default:
69
340k
    return false;
70
391k
  }
71
391k
}
72
73
8.25k
bool FormatToken::isTypeOrIdentifier() const {
74
8.25k
  return isSimpleTypeSpecifier() || 
Tok.isOneOf(tok::kw_auto, tok::identifier)5.36k
;
75
8.25k
}
76
77
558k
bool FormatToken::opensBlockOrBlockTypeList(const FormatStyle &Style) const {
78
  // C# Does not indent object initialisers as continuations.
79
558k
  if (is(tok::l_brace) && 
getBlockKind() == BK_BracedInit98.2k
&&
Style.isCSharp()56.0k
)
80
1.24k
    return true;
81
557k
  if (is(TT_TemplateString) && 
opensScope()124
)
82
50
    return true;
83
557k
  return is(TT_ArrayInitializerLSquare) || 
is(TT_ProtoExtensionLSquare)554k
||
84
557k
         
(554k
is(tok::l_brace)554k
&&
85
554k
          
(97.0k
getBlockKind() == BK_Block97.0k
||
is(TT_DictLiteral)61.9k
||
86
97.0k
           
(55.5k
!Style.Cpp11BracedListStyle55.5k
&&
NestingLevel == 01.57k
))) ||
87
557k
         
(512k
is(tok::less)512k
&&
(14.1k
Style.Language == FormatStyle::LK_Proto14.1k
||
88
14.1k
                            
Style.Language == FormatStyle::LK_TextProto12.9k
));
89
557k
}
90
91
16.9k
TokenRole::~TokenRole() {}
92
93
0
void TokenRole::precomputeFormattingInfos(const FormatToken *Token) {}
94
95
unsigned CommaSeparatedList::formatAfterToken(LineState &State,
96
                                              ContinuationIndenter *Indenter,
97
142k
                                              bool DryRun) {
98
142k
  if (State.NextToken == nullptr || 
!State.NextToken->Previous142k
)
99
1
    return 0;
100
101
142k
  if (Formats.size() == 1)
102
108
    return 0; // Handled by formatFromToken
103
104
  // Ensure that we start on the opening brace.
105
141k
  const FormatToken *LBrace =
106
141k
      State.NextToken->Previous->getPreviousNonComment();
107
141k
  if (!LBrace || !LBrace->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
108
141k
      
LBrace->is(BK_Block)16.5k
||
LBrace->is(TT_DictLiteral)16.0k
||
109
141k
      
LBrace->Next->is(TT_DesignatedInitializerPeriod)15.5k
)
110
126k
    return 0;
111
112
  // Calculate the number of code points we have to format this list. As the
113
  // first token is already placed, we have to subtract it.
114
15.5k
  unsigned RemainingCodePoints =
115
15.5k
      Style.ColumnLimit - State.Column + State.NextToken->Previous->ColumnWidth;
116
117
  // Find the best ColumnFormat, i.e. the best number of columns to use.
118
15.5k
  const ColumnFormat *Format = getColumnFormat(RemainingCodePoints);
119
120
  // If no ColumnFormat can be used, the braced list would generally be
121
  // bin-packed. Add a severe penalty to this so that column layouts are
122
  // preferred if possible.
123
15.5k
  if (!Format)
124
15.0k
    return 10000;
125
126
  // Format the entire list.
127
424
  unsigned Penalty = 0;
128
424
  unsigned Column = 0;
129
424
  unsigned Item = 0;
130
20.1k
  while (State.NextToken != LBrace->MatchingParen) {
131
19.7k
    bool NewLine = false;
132
19.7k
    unsigned ExtraSpaces = 0;
133
134
    // If the previous token was one of our commas, we are now on the next item.
135
19.7k
    if (Item < Commas.size() && 
State.NextToken->Previous == Commas[Item]19.1k
) {
136
6.63k
      if (!State.NextToken->isTrailingComment()) {
137
6.42k
        ExtraSpaces += Format->ColumnSizes[Column] - ItemLengths[Item];
138
6.42k
        ++Column;
139
6.42k
      }
140
6.63k
      ++Item;
141
6.63k
    }
142
143
19.7k
    if (Column == Format->Columns || 
State.NextToken->MustBreakBefore19.1k
) {
144
851
      Column = 0;
145
851
      NewLine = true;
146
851
    }
147
148
    // Place token using the continuation indenter and store the penalty.
149
19.7k
    Penalty += Indenter->addTokenToState(State, NewLine, DryRun, ExtraSpaces);
150
19.7k
  }
151
424
  return Penalty;
152
15.5k
}
153
154
unsigned CommaSeparatedList::formatFromToken(LineState &State,
155
                                             ContinuationIndenter *Indenter,
156
90.0k
                                             bool DryRun) {
157
  // Formatting with 1 Column isn't really a column layout, so we don't need the
158
  // special logic here. We can just avoid bin packing any of the parameters.
159
90.0k
  if (Formats.size() == 1 || 
HasNestedBracedList89.9k
)
160
2.13k
    State.Stack.back().AvoidBinPacking = true;
161
90.0k
  return 0;
162
90.0k
}
163
164
// Returns the lengths in code points between Begin and End (both included),
165
// assuming that the entire sequence is put on a single line.
166
static unsigned CodePointsBetween(const FormatToken *Begin,
167
12.5k
                                  const FormatToken *End) {
168
12.5k
  assert(End->TotalLength >= Begin->TotalLength);
169
0
  return End->TotalLength - Begin->TotalLength + Begin->ColumnWidth;
170
12.5k
}
171
172
5.89k
void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) {
173
  // FIXME: At some point we might want to do this for other lists, too.
174
5.89k
  if (!Token->MatchingParen ||
175
5.89k
      
!Token->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare)5.88k
)
176
3.77k
    return;
177
178
  // In C++11 braced list style, we should not format in columns unless they
179
  // have many items (20 or more) or we allow bin-packing of function call
180
  // arguments.
181
2.11k
  if (Style.Cpp11BracedListStyle && 
!Style.BinPackArguments1.95k
&&
182
2.11k
      
Commas.size() < 1949
)
183
46
    return;
184
185
  // Limit column layout for JavaScript array initializers to 20 or more items
186
  // for now to introduce it carefully. We can become more aggressive if this
187
  // necessary.
188
2.07k
  if (Token->is(TT_ArrayInitializerLSquare) && 
Commas.size() < 19149
)
189
145
    return;
190
191
  // Column format doesn't really make sense if we don't align after brackets.
192
1.92k
  if (Style.AlignAfterOpenBracket == FormatStyle::BAS_DontAlign)
193
18
    return;
194
195
1.91k
  FormatToken *ItemBegin = Token->Next;
196
1.95k
  while (ItemBegin->isTrailingComment())
197
42
    ItemBegin = ItemBegin->Next;
198
1.91k
  SmallVector<bool, 8> MustBreakBeforeItem;
199
200
  // The lengths of an item if it is put at the end of the line. This includes
201
  // trailing comments which are otherwise ignored for column alignment.
202
1.91k
  SmallVector<unsigned, 8> EndOfLineItemLength;
203
1.91k
  MustBreakBeforeItem.reserve(Commas.size() + 1);
204
1.91k
  EndOfLineItemLength.reserve(Commas.size() + 1);
205
1.91k
  ItemLengths.reserve(Commas.size() + 1);
206
207
1.91k
  bool HasSeparatingComment = false;
208
7.77k
  for (unsigned i = 0, e = Commas.size() + 1; i != e; 
++i5.86k
) {
209
6.26k
    assert(ItemBegin);
210
    // Skip comments on their own line.
211
6.30k
    while (ItemBegin->HasUnescapedNewline && 
ItemBegin->isTrailingComment()894
) {
212
43
      ItemBegin = ItemBegin->Next;
213
43
      HasSeparatingComment = i > 0;
214
43
    }
215
216
6.26k
    MustBreakBeforeItem.push_back(ItemBegin->MustBreakBefore);
217
6.26k
    if (ItemBegin->is(tok::l_brace))
218
669
      HasNestedBracedList = true;
219
6.26k
    const FormatToken *ItemEnd = nullptr;
220
6.26k
    if (i == Commas.size()) {
221
1.67k
      ItemEnd = Token->MatchingParen;
222
1.67k
      const FormatToken *NonCommentEnd = ItemEnd->getPreviousNonComment();
223
1.67k
      ItemLengths.push_back(CodePointsBetween(ItemBegin, NonCommentEnd));
224
1.67k
      if (Style.Cpp11BracedListStyle &&
225
1.67k
          
!ItemEnd->Previous->isTrailingComment()1.54k
) {
226
        // In Cpp11 braced list style, the } and possibly other subsequent
227
        // tokens will need to stay on a line with the last element.
228
3.28k
        while (ItemEnd->Next && 
!ItemEnd->Next->CanBreakBefore2.29k
)
229
1.77k
          ItemEnd = ItemEnd->Next;
230
1.51k
      } else {
231
        // In other braced lists styles, the "}" can be wrapped to the new line.
232
159
        ItemEnd = Token->MatchingParen->Previous;
233
159
      }
234
4.58k
    } else {
235
4.58k
      ItemEnd = Commas[i];
236
      // The comma is counted as part of the item when calculating the length.
237
4.58k
      ItemLengths.push_back(CodePointsBetween(ItemBegin, ItemEnd));
238
239
      // Consume trailing comments so the are included in EndOfLineItemLength.
240
4.58k
      if (ItemEnd->Next && !ItemEnd->Next->HasUnescapedNewline &&
241
4.58k
          
ItemEnd->Next->isTrailingComment()4.04k
)
242
141
        ItemEnd = ItemEnd->Next;
243
4.58k
    }
244
6.26k
    EndOfLineItemLength.push_back(CodePointsBetween(ItemBegin, ItemEnd));
245
    // If there is a trailing comma in the list, the next item will start at the
246
    // closing brace. Don't create an extra item for this.
247
6.26k
    if (ItemEnd->getNextNonComment() == Token->MatchingParen)
248
398
      break;
249
5.86k
    ItemBegin = ItemEnd->Next;
250
5.86k
  }
251
252
  // Don't use column layout for lists with few elements and in presence of
253
  // separating comments.
254
1.91k
  if (Commas.size() < 5 || 
HasSeparatingComment114
)
255
1.79k
    return;
256
257
111
  if (Token->NestingLevel != 0 && 
Token->is(tok::l_brace)26
&&
Commas.size() < 1924
)
258
21
    return;
259
260
  // We can never place more than ColumnLimit / 3 items in a row (because of the
261
  // spaces and the comma).
262
90
  unsigned MaxItems = Style.ColumnLimit / 3;
263
90
  std::vector<unsigned> MinSizeInColumn;
264
90
  MinSizeInColumn.reserve(MaxItems);
265
1.04k
  for (unsigned Columns = 1; Columns <= MaxItems; 
++Columns959
) {
266
1.03k
    ColumnFormat Format;
267
1.03k
    Format.Columns = Columns;
268
1.03k
    Format.ColumnSizes.resize(Columns);
269
1.03k
    MinSizeInColumn.assign(Columns, UINT_MAX);
270
1.03k
    Format.LineCount = 1;
271
1.03k
    bool HasRowWithSufficientColumns = false;
272
1.03k
    unsigned Column = 0;
273
21.8k
    for (unsigned i = 0, e = ItemLengths.size(); i != e; 
++i20.7k
) {
274
20.7k
      assert(i < MustBreakBeforeItem.size());
275
20.7k
      if (MustBreakBeforeItem[i] || 
Column == Columns20.2k
) {
276
3.80k
        ++Format.LineCount;
277
3.80k
        Column = 0;
278
3.80k
      }
279
20.7k
      if (Column == Columns - 1)
280
3.68k
        HasRowWithSufficientColumns = true;
281
20.7k
      unsigned Length =
282
20.7k
          (Column == Columns - 1) ? 
EndOfLineItemLength[i]3.68k
:
ItemLengths[i]17.1k
;
283
20.7k
      Format.ColumnSizes[Column] = std::max(Format.ColumnSizes[Column], Length);
284
20.7k
      MinSizeInColumn[Column] = std::min(MinSizeInColumn[Column], Length);
285
20.7k
      ++Column;
286
20.7k
    }
287
    // If all rows are terminated early (e.g. by trailing comments), we don't
288
    // need to look further.
289
1.03k
    if (!HasRowWithSufficientColumns)
290
78
      break;
291
959
    Format.TotalWidth = Columns - 1; // Width of the N-1 spaces.
292
293
8.76k
    for (unsigned i = 0; i < Columns; 
++i7.80k
)
294
7.80k
      Format.TotalWidth += Format.ColumnSizes[i];
295
296
    // Don't use this Format, if the difference between the longest and shortest
297
    // element in a column exceeds a threshold to avoid excessive spaces.
298
959
    if ([&] {
299
7.44k
          for (unsigned i = 0; i < Columns - 1; 
++i6.49k
)
300
6.61k
            if (Format.ColumnSizes[i] - MinSizeInColumn[i] > 10)
301
129
              return true;
302
830
          return false;
303
959
        }())
304
129
      continue;
305
306
    // Ignore layouts that are bound to violate the column limit.
307
830
    if (Format.TotalWidth > Style.ColumnLimit && 
Columns > 1234
)
308
234
      continue;
309
310
596
    Formats.push_back(Format);
311
596
  }
312
90
}
313
314
const CommaSeparatedList::ColumnFormat *
315
15.5k
CommaSeparatedList::getColumnFormat(unsigned RemainingCharacters) const {
316
15.5k
  const ColumnFormat *BestFormat = nullptr;
317
15.5k
  for (const ColumnFormat &Format : llvm::reverse(Formats)) {
318
1.83k
    if (Format.TotalWidth <= RemainingCharacters || 
Format.Columns == 1485
) {
319
1.34k
      if (BestFormat && 
Format.LineCount > BestFormat->LineCount923
)
320
424
        break;
321
923
      BestFormat = &Format;
322
923
    }
323
1.83k
  }
324
15.5k
  return BestFormat;
325
15.5k
}
326
327
} // namespace format
328
} // namespace clang