Coverage Report

Created: 2021-01-19 06:58

/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
222k
bool FormatToken::isSimpleTypeSpecifier() const {
40
222k
  switch (Tok.getKind()) {
41
3
  case tok::kw_short:
42
44
  case tok::kw_long:
43
44
  case tok::kw___int64:
44
44
  case tok::kw___int128:
45
44
  case tok::kw_signed:
46
305
  case tok::kw_unsigned:
47
9.00k
  case tok::kw_void:
48
9.21k
  case tok::kw_char:
49
23.9k
  case tok::kw_int:
50
23.9k
  case tok::kw_half:
51
24.1k
  case tok::kw_float:
52
24.3k
  case tok::kw_double:
53
24.3k
  case tok::kw___bf16:
54
24.3k
  case tok::kw__Float16:
55
24.3k
  case tok::kw___float128:
56
24.3k
  case tok::kw_wchar_t:
57
25.1k
  case tok::kw_bool:
58
25.1k
  case tok::kw___underlying_type:
59
25.1k
  case tok::annot_typename:
60
25.1k
  case tok::kw_char8_t:
61
25.1k
  case tok::kw_char16_t:
62
25.1k
  case tok::kw_char32_t:
63
25.2k
  case tok::kw_typeof:
64
25.2k
  case tok::kw_decltype:
65
25.3k
  case tok::kw__Atomic:
66
25.3k
    return true;
67
197k
  default:
68
197k
    return false;
69
222k
  }
70
222k
}
71
72
9.04k
TokenRole::~TokenRole() {}
73
74
0
void TokenRole::precomputeFormattingInfos(const FormatToken *Token) {}
75
76
unsigned CommaSeparatedList::formatAfterToken(LineState &State,
77
                                              ContinuationIndenter *Indenter,
78
130k
                                              bool DryRun) {
79
130k
  if (State.NextToken == nullptr || 
!State.NextToken->Previous130k
)
80
1
    return 0;
81
82
130k
  if (Formats.size() == 1)
83
108
    return 0; // Handled by formatFromToken
84
85
  // Ensure that we start on the opening brace.
86
130k
  const FormatToken *LBrace =
87
130k
      State.NextToken->Previous->getPreviousNonComment();
88
130k
  if (!LBrace || !LBrace->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
89
7.07k
      LBrace->is(BK_Block) || 
LBrace->is(TT_DictLiteral)6.68k
||
90
6.20k
      LBrace->Next->is(TT_DesignatedInitializerPeriod))
91
123k
    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
6.15k
  unsigned RemainingCodePoints =
96
6.15k
      Style.ColumnLimit - State.Column + State.NextToken->Previous->ColumnWidth;
97
98
  // Find the best ColumnFormat, i.e. the best number of columns to use.
99
6.15k
  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
6.15k
  if (!Format)
105
5.73k
    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
424
}
134
135
unsigned CommaSeparatedList::formatFromToken(LineState &State,
136
                                             ContinuationIndenter *Indenter,
137
72.3k
                                             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
72.3k
  if (Formats.size() == 1 || 
HasNestedBracedList72.2k
)
141
461
    State.Stack.back().AvoidBinPacking = true;
142
72.3k
  return 0;
143
72.3k
}
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
7.33k
                                  const FormatToken *End) {
149
7.33k
  assert(End->TotalLength >= Begin->TotalLength);
150
7.33k
  return End->TotalLength - Begin->TotalLength + Begin->ColumnWidth;
151
7.33k
}
152
153
4.02k
void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) {
154
  // FIXME: At some point we might want to do this for other lists, too.
155
4.02k
  if (!Token->MatchingParen ||
156
4.01k
      !Token->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare))
157
2.82k
    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.20k
  if (Style.Cpp11BracedListStyle && 
!Style.BinPackArguments1.03k
&&
163
34
      Commas.size() < 19)
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.17k
  if (Token->is(TT_ArrayInitializerLSquare) && 
Commas.size() < 19127
)
170
123
    return;
171
172
  // Column format doesn't really make sense if we don't align after brackets.
173
1.05k
  if (Style.AlignAfterOpenBracket == FormatStyle::BAS_DontAlign)
174
18
    return;
175
176
1.03k
  FormatToken *ItemBegin = Token->Next;
177
1.07k
  while (ItemBegin->isTrailingComment())
178
42
    ItemBegin = ItemBegin->Next;
179
1.03k
  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.03k
  SmallVector<unsigned, 8> EndOfLineItemLength;
184
185
1.03k
  bool HasSeparatingComment = false;
186
4.37k
  for (unsigned i = 0, e = Commas.size() + 1; i != e; 
++i3.33k
) {
187
    // Skip comments on their own line.
188
3.71k
    while (ItemBegin->HasUnescapedNewline && 
ItemBegin->isTrailingComment()670
) {
189
43
      ItemBegin = ItemBegin->Next;
190
43
      HasSeparatingComment = i > 0;
191
43
    }
192
193
3.66k
    MustBreakBeforeItem.push_back(ItemBegin->MustBreakBefore);
194
3.66k
    if (ItemBegin->is(tok::l_brace))
195
231
      HasNestedBracedList = true;
196
3.66k
    const FormatToken *ItemEnd = nullptr;
197
3.66k
    if (i == Commas.size()) {
198
841
      ItemEnd = Token->MatchingParen;
199
841
      const FormatToken *NonCommentEnd = ItemEnd->getPreviousNonComment();
200
841
      ItemLengths.push_back(CodePointsBetween(ItemBegin, NonCommentEnd));
201
841
      if (Style.Cpp11BracedListStyle &&
202
719
          !ItemEnd->Previous->isTrailingComment()) {
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
1.50k
        while (ItemEnd->Next && 
!ItemEnd->Next->CanBreakBefore985
)
206
806
          ItemEnd = ItemEnd->Next;
207
138
      } else {
208
        // In other braced lists styles, the "}" can be wrapped to the new line.
209
138
        ItemEnd = Token->MatchingParen->Previous;
210
138
      }
211
2.82k
    } else {
212
2.82k
      ItemEnd = Commas[i];
213
      // The comma is counted as part of the item when calculating the length.
214
2.82k
      ItemLengths.push_back(CodePointsBetween(ItemBegin, ItemEnd));
215
216
      // Consume trailing comments so the are included in EndOfLineItemLength.
217
2.82k
      if (ItemEnd->Next && !ItemEnd->Next->HasUnescapedNewline &&
218
2.41k
          ItemEnd->Next->isTrailingComment())
219
93
        ItemEnd = ItemEnd->Next;
220
2.82k
    }
221
3.66k
    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
3.66k
    if (ItemEnd->getNextNonComment() == Token->MatchingParen)
225
331
      break;
226
3.33k
    ItemBegin = ItemEnd->Next;
227
3.33k
  }
228
229
  // Don't use column layout for lists with few elements and in presence of
230
  // separating comments.
231
1.03k
  if (Commas.size() < 5 || 
HasSeparatingComment100
)
232
937
    return;
233
234
97
  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
88
  unsigned MaxItems = Style.ColumnLimit / 3;
240
88
  std::vector<unsigned> MinSizeInColumn;
241
88
  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
17.1k
          (Column == Columns - 1) ? 
EndOfLineItemLength[i]3.68k
: ItemLengths[i];
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
88
}
290
291
const CommaSeparatedList::ColumnFormat *
292
6.15k
CommaSeparatedList::getColumnFormat(unsigned RemainingCharacters) const {
293
6.15k
  const ColumnFormat *BestFormat = nullptr;
294
6.15k
  for (SmallVector<ColumnFormat, 4>::const_reverse_iterator
295
6.15k
           I = Formats.rbegin(),
296
6.15k
           E = Formats.rend();
297
7.56k
       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
6.15k
  return BestFormat;
305
6.15k
}
306
307
} // namespace format
308
} // namespace clang