Coverage Report

Created: 2022-07-16 07:03

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