Coverage Report

Created: 2021-09-21 08:58

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Format/WhitespaceManager.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- WhitespaceManager.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 WhitespaceManager class.
11
///
12
//===----------------------------------------------------------------------===//
13
14
#include "WhitespaceManager.h"
15
#include "llvm/ADT/STLExtras.h"
16
#include "llvm/ADT/SmallVector.h"
17
#include <algorithm>
18
19
namespace clang {
20
namespace format {
21
22
bool WhitespaceManager::Change::IsBeforeInFile::operator()(
23
609k
    const Change &C1, const Change &C2) const {
24
609k
  return SourceMgr.isBeforeInTranslationUnit(
25
609k
      C1.OriginalWhitespaceRange.getBegin(),
26
609k
      C2.OriginalWhitespaceRange.getBegin());
27
609k
}
28
29
WhitespaceManager::Change::Change(const FormatToken &Tok,
30
                                  bool CreateReplacement,
31
                                  SourceRange OriginalWhitespaceRange,
32
                                  int Spaces, unsigned StartOfTokenColumn,
33
                                  unsigned NewlinesBefore,
34
                                  StringRef PreviousLinePostfix,
35
                                  StringRef CurrentLinePrefix, bool IsAligned,
36
                                  bool ContinuesPPDirective, bool IsInsideToken)
37
    : Tok(&Tok), CreateReplacement(CreateReplacement),
38
      OriginalWhitespaceRange(OriginalWhitespaceRange),
39
      StartOfTokenColumn(StartOfTokenColumn), NewlinesBefore(NewlinesBefore),
40
      PreviousLinePostfix(PreviousLinePostfix),
41
      CurrentLinePrefix(CurrentLinePrefix), IsAligned(IsAligned),
42
      ContinuesPPDirective(ContinuesPPDirective), Spaces(Spaces),
43
      IsInsideToken(IsInsideToken), IsTrailingComment(false), TokenLength(0),
44
      PreviousEndOfTokenColumn(0), EscapedNewlineColumn(0),
45
310k
      StartOfBlockComment(nullptr), IndentationOffset(0), ConditionalsLevel(0) {
46
310k
}
47
48
void WhitespaceManager::replaceWhitespace(FormatToken &Tok, unsigned Newlines,
49
                                          unsigned Spaces,
50
                                          unsigned StartOfTokenColumn,
51
287k
                                          bool IsAligned, bool InPPDirective) {
52
287k
  if (Tok.Finalized)
53
2.48k
    return;
54
284k
  Tok.setDecision((Newlines > 0) ? 
FD_Break37.6k
:
FD_Continue247k
);
55
284k
  Changes.push_back(Change(Tok, /*CreateReplacement=*/true, Tok.WhitespaceRange,
56
284k
                           Spaces, StartOfTokenColumn, Newlines, "", "",
57
284k
                           IsAligned, InPPDirective && 
!Tok.IsFirst1.80k
,
58
284k
                           /*IsInsideToken=*/false));
59
284k
}
60
61
void WhitespaceManager::addUntouchableToken(const FormatToken &Tok,
62
24.1k
                                            bool InPPDirective) {
63
24.1k
  if (Tok.Finalized)
64
24
    return;
65
24.1k
  Changes.push_back(Change(Tok, /*CreateReplacement=*/false,
66
24.1k
                           Tok.WhitespaceRange, /*Spaces=*/0,
67
24.1k
                           Tok.OriginalColumn, Tok.NewlinesBefore, "", "",
68
24.1k
                           /*IsAligned=*/false, InPPDirective && 
!Tok.IsFirst1.86k
,
69
24.1k
                           /*IsInsideToken=*/false));
70
24.1k
}
71
72
llvm::Error
73
196
WhitespaceManager::addReplacement(const tooling::Replacement &Replacement) {
74
196
  return Replaces.add(Replacement);
75
196
}
76
77
void WhitespaceManager::replaceWhitespaceInToken(
78
    const FormatToken &Tok, unsigned Offset, unsigned ReplaceChars,
79
    StringRef PreviousPostfix, StringRef CurrentPrefix, bool InPPDirective,
80
1.42k
    unsigned Newlines, int Spaces) {
81
1.42k
  if (Tok.Finalized)
82
4
    return;
83
1.42k
  SourceLocation Start = Tok.getStartOfNonWhitespace().getLocWithOffset(Offset);
84
1.42k
  Changes.push_back(
85
1.42k
      Change(Tok, /*CreateReplacement=*/true,
86
1.42k
             SourceRange(Start, Start.getLocWithOffset(ReplaceChars)), Spaces,
87
1.42k
             std::max(0, Spaces), Newlines, PreviousPostfix, CurrentPrefix,
88
1.42k
             /*IsAligned=*/true, InPPDirective && 
!Tok.IsFirst21
,
89
1.42k
             /*IsInsideToken=*/true));
90
1.42k
}
91
92
18.5k
const tooling::Replacements &WhitespaceManager::generateReplacements() {
93
18.5k
  if (Changes.empty())
94
40
    return Replaces;
95
96
18.4k
  llvm::sort(Changes, Change::IsBeforeInFile(SourceMgr));
97
18.4k
  calculateLineBreakInformation();
98
18.4k
  alignConsecutiveMacros();
99
18.4k
  alignConsecutiveDeclarations();
100
18.4k
  alignConsecutiveBitFields();
101
18.4k
  alignConsecutiveAssignments();
102
18.4k
  alignChainedConditionals();
103
18.4k
  alignTrailingComments();
104
18.4k
  alignEscapedNewlines();
105
18.4k
  alignArrayInitializers();
106
18.4k
  generateChanges();
107
108
18.4k
  return Replaces;
109
18.5k
}
110
111
18.4k
void WhitespaceManager::calculateLineBreakInformation() {
112
18.4k
  Changes[0].PreviousEndOfTokenColumn = 0;
113
18.4k
  Change *LastOutsideTokenChange = &Changes[0];
114
310k
  for (unsigned i = 1, e = Changes.size(); i != e; 
++i291k
) {
115
291k
    SourceLocation OriginalWhitespaceStart =
116
291k
        Changes[i].OriginalWhitespaceRange.getBegin();
117
291k
    SourceLocation PreviousOriginalWhitespaceEnd =
118
291k
        Changes[i - 1].OriginalWhitespaceRange.getEnd();
119
291k
    unsigned OriginalWhitespaceStartOffset =
120
291k
        SourceMgr.getFileOffset(OriginalWhitespaceStart);
121
291k
    unsigned PreviousOriginalWhitespaceEndOffset =
122
291k
        SourceMgr.getFileOffset(PreviousOriginalWhitespaceEnd);
123
291k
    assert(PreviousOriginalWhitespaceEndOffset <=
124
291k
           OriginalWhitespaceStartOffset);
125
0
    const char *const PreviousOriginalWhitespaceEndData =
126
291k
        SourceMgr.getCharacterData(PreviousOriginalWhitespaceEnd);
127
291k
    StringRef Text(PreviousOriginalWhitespaceEndData,
128
291k
                   SourceMgr.getCharacterData(OriginalWhitespaceStart) -
129
291k
                       PreviousOriginalWhitespaceEndData);
130
    // Usually consecutive changes would occur in consecutive tokens. This is
131
    // not the case however when analyzing some preprocessor runs of the
132
    // annotated lines. For example, in this code:
133
    //
134
    // #if A // line 1
135
    // int i = 1;
136
    // #else B // line 2
137
    // int i = 2;
138
    // #endif // line 3
139
    //
140
    // one of the runs will produce the sequence of lines marked with line 1, 2
141
    // and 3. So the two consecutive whitespace changes just before '// line 2'
142
    // and before '#endif // line 3' span multiple lines and tokens:
143
    //
144
    // #else B{change X}[// line 2
145
    // int i = 2;
146
    // ]{change Y}#endif // line 3
147
    //
148
    // For this reason, if the text between consecutive changes spans multiple
149
    // newlines, the token length must be adjusted to the end of the original
150
    // line of the token.
151
291k
    auto NewlinePos = Text.find_first_of('\n');
152
291k
    if (NewlinePos == StringRef::npos) {
153
291k
      Changes[i - 1].TokenLength = OriginalWhitespaceStartOffset -
154
291k
                                   PreviousOriginalWhitespaceEndOffset +
155
291k
                                   Changes[i].PreviousLinePostfix.size() +
156
291k
                                   Changes[i - 1].CurrentLinePrefix.size();
157
291k
    } else {
158
173
      Changes[i - 1].TokenLength =
159
173
          NewlinePos + Changes[i - 1].CurrentLinePrefix.size();
160
173
    }
161
162
    // If there are multiple changes in this token, sum up all the changes until
163
    // the end of the line.
164
291k
    if (Changes[i - 1].IsInsideToken && 
Changes[i - 1].NewlinesBefore == 01.42k
)
165
393
      LastOutsideTokenChange->TokenLength +=
166
393
          Changes[i - 1].TokenLength + Changes[i - 1].Spaces;
167
291k
    else
168
291k
      LastOutsideTokenChange = &Changes[i - 1];
169
170
291k
    Changes[i].PreviousEndOfTokenColumn =
171
291k
        Changes[i - 1].StartOfTokenColumn + Changes[i - 1].TokenLength;
172
173
291k
    Changes[i - 1].IsTrailingComment =
174
291k
        (Changes[i].NewlinesBefore > 0 || 
Changes[i].Tok->is(tok::eof)248k
||
175
291k
         
(232k
Changes[i].IsInsideToken232k
&&
Changes[i].Tok->is(tok::comment)393
)) &&
176
291k
        
Changes[i - 1].Tok->is(tok::comment)59.9k
&&
177
        // FIXME: This is a dirty hack. The problem is that
178
        // BreakableLineCommentSection does comment reflow changes and here is
179
        // the aligning of trailing comments. Consider the case where we reflow
180
        // the second line up in this example:
181
        //
182
        // // line 1
183
        // // line 2
184
        //
185
        // That amounts to 2 changes by BreakableLineCommentSection:
186
        //  - the first, delimited by (), for the whitespace between the tokens,
187
        //  - and second, delimited by [], for the whitespace at the beginning
188
        //  of the second token:
189
        //
190
        // // line 1(
191
        // )[// ]line 2
192
        //
193
        // So in the end we have two changes like this:
194
        //
195
        // // line1()[ ]line 2
196
        //
197
        // Note that the OriginalWhitespaceStart of the second change is the
198
        // same as the PreviousOriginalWhitespaceEnd of the first change.
199
        // In this case, the below check ensures that the second change doesn't
200
        // get treated as a trailing comment change here, since this might
201
        // trigger additional whitespace to be wrongly inserted before "line 2"
202
        // by the comment aligner here.
203
        //
204
        // For a proper solution we need a mechanism to say to WhitespaceManager
205
        // that a particular change breaks the current sequence of trailing
206
        // comments.
207
291k
        
OriginalWhitespaceStart != PreviousOriginalWhitespaceEnd5.32k
;
208
291k
  }
209
  // FIXME: The last token is currently not always an eof token; in those
210
  // cases, setting TokenLength of the last token to 0 is wrong.
211
18.4k
  Changes.back().TokenLength = 0;
212
18.4k
  Changes.back().IsTrailingComment = Changes.back().Tok->is(tok::comment);
213
214
18.4k
  const WhitespaceManager::Change *LastBlockComment = nullptr;
215
310k
  for (auto &Change : Changes) {
216
    // Reset the IsTrailingComment flag for changes inside of trailing comments
217
    // so they don't get realigned later. Comment line breaks however still need
218
    // to be aligned.
219
310k
    if (Change.IsInsideToken && 
Change.NewlinesBefore == 01.42k
)
220
393
      Change.IsTrailingComment = false;
221
310k
    Change.StartOfBlockComment = nullptr;
222
310k
    Change.IndentationOffset = 0;
223
310k
    if (Change.Tok->is(tok::comment)) {
224
5.77k
      if (Change.Tok->is(TT_LineComment) || 
!Change.IsInsideToken1.27k
)
225
5.21k
        LastBlockComment = &Change;
226
558
      else {
227
558
        if ((Change.StartOfBlockComment = LastBlockComment))
228
558
          Change.IndentationOffset =
229
558
              Change.StartOfTokenColumn -
230
558
              Change.StartOfBlockComment->StartOfTokenColumn;
231
558
      }
232
304k
    } else {
233
304k
      LastBlockComment = nullptr;
234
304k
    }
235
310k
  }
236
237
  // Compute conditional nesting level
238
  // Level is increased for each conditional, unless this conditional continues
239
  // a chain of conditional, i.e. starts immediately after the colon of another
240
  // conditional.
241
18.4k
  SmallVector<bool, 16> ScopeStack;
242
18.4k
  int ConditionalsLevel = 0;
243
310k
  for (auto &Change : Changes) {
244
333k
    for (unsigned i = 0, e = Change.Tok->FakeLParens.size(); i != e; 
++i23.1k
) {
245
23.1k
      bool isNestedConditional =
246
23.1k
          Change.Tok->FakeLParens[e - 1 - i] == prec::Conditional &&
247
23.1k
          
!(732
i == 0732
&&
Change.Tok->Previous728
&&
248
732
            
Change.Tok->Previous->is(TT_ConditionalExpr)701
&&
249
732
            
Change.Tok->Previous->is(tok::colon)209
);
250
23.1k
      if (isNestedConditional)
251
544
        ++ConditionalsLevel;
252
23.1k
      ScopeStack.push_back(isNestedConditional);
253
23.1k
    }
254
255
310k
    Change.ConditionalsLevel = ConditionalsLevel;
256
257
331k
    for (unsigned i = Change.Tok->FakeRParens; i > 0 && 
ScopeStack.size()21.3k
;
258
310k
         
--i21.2k
) {
259
21.2k
      if (ScopeStack.pop_back_val())
260
538
        --ConditionalsLevel;
261
21.2k
    }
262
310k
  }
263
18.4k
}
264
265
// Align a single sequence of tokens, see AlignTokens below.
266
template <typename F>
267
static void
268
AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
269
                   unsigned Column, F &&Matches,
270
1.74k
                   SmallVector<WhitespaceManager::Change, 16> &Changes) {
271
1.74k
  bool FoundMatchOnLine = false;
272
1.74k
  int Shift = 0;
273
274
  // ScopeStack keeps track of the current scope depth. It contains indices of
275
  // the first token on each scope.
276
  // We only run the "Matches" function on tokens from the outer-most scope.
277
  // However, we do need to pay special attention to one class of tokens
278
  // that are not in the outer-most scope, and that is function parameters
279
  // which are split across multiple lines, as illustrated by this example:
280
  //   double a(int x);
281
  //   int    b(int  y,
282
  //          double z);
283
  // In the above example, we need to take special care to ensure that
284
  // 'double z' is indented along with it's owning function 'b'.
285
  // The same holds for calling a function:
286
  //   double a = foo(x);
287
  //   int    b = bar(foo(y),
288
  //            foor(z));
289
  // Similar for broken string literals:
290
  //   double x = 3.14;
291
  //   auto s   = "Hello"
292
  //          "World";
293
  // Special handling is required for 'nested' ternary operators.
294
1.74k
  SmallVector<unsigned, 16> ScopeStack;
295
296
22.9k
  for (unsigned i = Start; i != End; 
++i21.2k
) {
297
21.2k
    if (ScopeStack.size() != 0 &&
298
21.2k
        Changes[i].indentAndNestingLevel() <
299
8.49k
            Changes[ScopeStack.back()].indentAndNestingLevel())
300
1.41k
      ScopeStack.pop_back();
301
302
    // Compare current token to previous non-comment token to ensure whether
303
    // it is in a deeper scope or not.
304
21.2k
    unsigned PreviousNonComment = i - 1;
305
21.5k
    while (PreviousNonComment > Start &&
306
21.5k
           
Changes[PreviousNonComment].Tok->is(tok::comment)18.0k
)
307
271
      PreviousNonComment--;
308
21.2k
    if (i != Start && Changes[i].indentAndNestingLevel() >
309
19.4k
                          Changes[PreviousNonComment].indentAndNestingLevel())
310
1.56k
      ScopeStack.push_back(i);
311
312
21.2k
    bool InsideNestedScope = ScopeStack.size() != 0;
313
21.2k
    bool ContinuedStringLiteral = i > Start &&
314
21.2k
                                  
Changes[i].Tok->is(tok::string_literal)19.4k
&&
315
21.2k
                                  
Changes[i - 1].Tok->is(tok::string_literal)411
;
316
21.2k
    bool SkipMatchCheck = InsideNestedScope || 
ContinuedStringLiteral12.6k
;
317
318
21.2k
    if (Changes[i].NewlinesBefore > 0 && 
!SkipMatchCheck2.67k
) {
319
1.70k
      Shift = 0;
320
1.70k
      FoundMatchOnLine = false;
321
1.70k
    }
322
323
    // If this is the first matching token to be aligned, remember by how many
324
    // spaces it has to be shifted, so the rest of the changes on the line are
325
    // shifted by the same amount
326
21.2k
    if (!FoundMatchOnLine && 
!SkipMatchCheck6.03k
&&
Matches(Changes[i])5.73k
) {
327
3.06k
      FoundMatchOnLine = true;
328
3.06k
      Shift = Column - Changes[i].StartOfTokenColumn;
329
3.06k
      Changes[i].Spaces += Shift;
330
3.06k
    }
331
332
    // This is for function parameters that are split across multiple lines,
333
    // as mentioned in the ScopeStack comment.
334
21.2k
    if (InsideNestedScope && 
Changes[i].NewlinesBefore > 08.64k
) {
335
943
      unsigned ScopeStart = ScopeStack.back();
336
943
      auto ShouldShiftBeAdded = [&] {
337
        // Function declaration
338
943
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
339
0
          return true;
340
341
        // Continued function declaration
342
943
        if (ScopeStart > Start + 1 &&
343
943
            
Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName)916
)
344
30
          return true;
345
346
        // Continued function call
347
913
        if (ScopeStart > Start + 1 &&
348
913
            
Changes[ScopeStart - 2].Tok->is(tok::identifier)886
&&
349
913
            
Changes[ScopeStart - 1].Tok->is(tok::l_paren)190
)
350
108
          return Style.BinPackArguments;
351
352
        // Ternary operator
353
805
        if (Changes[i].Tok->is(TT_ConditionalExpr))
354
66
          return true;
355
356
        // Period Initializer .XXX = 1.
357
739
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
358
36
          return true;
359
360
        // Continued ternary operator
361
703
        if (Changes[i].Tok->Previous &&
362
703
            
Changes[i].Tok->Previous->is(TT_ConditionalExpr)425
)
363
48
          return true;
364
365
655
        return false;
366
703
      };
WhitespaceManager.cpp:void clang::format::AlignTokenSequence<clang::format::WhitespaceManager::alignConsecutiveAssignments()::$_1&>(clang::format::FormatStyle const&, unsigned int, unsigned int, unsigned int, clang::format::WhitespaceManager::alignConsecutiveAssignments()::$_1&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&)::'lambda'()::operator()() const
Line
Count
Source
336
288
      auto ShouldShiftBeAdded = [&] {
337
        // Function declaration
338
288
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
339
0
          return true;
340
341
        // Continued function declaration
342
288
        if (ScopeStart > Start + 1 &&
343
288
            Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName))
344
0
          return true;
345
346
        // Continued function call
347
288
        if (ScopeStart > Start + 1 &&
348
288
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
349
288
            
Changes[ScopeStart - 1].Tok->is(tok::l_paren)85
)
350
36
          return Style.BinPackArguments;
351
352
        // Ternary operator
353
252
        if (Changes[i].Tok->is(TT_ConditionalExpr))
354
0
          return true;
355
356
        // Period Initializer .XXX = 1.
357
252
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
358
12
          return true;
359
360
        // Continued ternary operator
361
240
        if (Changes[i].Tok->Previous &&
362
240
            
Changes[i].Tok->Previous->is(TT_ConditionalExpr)192
)
363
0
          return true;
364
365
240
        return false;
366
240
      };
Unexecuted instantiation: WhitespaceManager.cpp:void clang::format::AlignTokenSequence<clang::format::WhitespaceManager::alignConsecutiveBitFields()::$_2&>(clang::format::FormatStyle const&, unsigned int, unsigned int, unsigned int, clang::format::WhitespaceManager::alignConsecutiveBitFields()::$_2&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&)::'lambda'()::operator()() const
WhitespaceManager.cpp:void clang::format::AlignTokenSequence<clang::format::WhitespaceManager::alignConsecutiveDeclarations()::$_3&>(clang::format::FormatStyle const&, unsigned int, unsigned int, unsigned int, clang::format::WhitespaceManager::alignConsecutiveDeclarations()::$_3&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&)::'lambda'()::operator()() const
Line
Count
Source
336
506
      auto ShouldShiftBeAdded = [&] {
337
        // Function declaration
338
506
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
339
0
          return true;
340
341
        // Continued function declaration
342
506
        if (ScopeStart > Start + 1 &&
343
506
            Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName))
344
30
          return true;
345
346
        // Continued function call
347
476
        if (ScopeStart > Start + 1 &&
348
476
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
349
476
            
Changes[ScopeStart - 1].Tok->is(tok::l_paren)78
)
350
54
          return Style.BinPackArguments;
351
352
        // Ternary operator
353
422
        if (Changes[i].Tok->is(TT_ConditionalExpr))
354
0
          return true;
355
356
        // Period Initializer .XXX = 1.
357
422
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
358
24
          return true;
359
360
        // Continued ternary operator
361
398
        if (Changes[i].Tok->Previous &&
362
398
            
Changes[i].Tok->Previous->is(TT_ConditionalExpr)173
)
363
0
          return true;
364
365
398
        return false;
366
398
      };
WhitespaceManager.cpp:void clang::format::AlignTokenSequence<clang::format::WhitespaceManager::alignChainedConditionals()::$_4&>(clang::format::FormatStyle const&, unsigned int, unsigned int, unsigned int, clang::format::WhitespaceManager::alignChainedConditionals()::$_4&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&)::'lambda'()::operator()() const
Line
Count
Source
336
87
      auto ShouldShiftBeAdded = [&] {
337
        // Function declaration
338
87
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
339
0
          return true;
340
341
        // Continued function declaration
342
87
        if (ScopeStart > Start + 1 &&
343
87
            
Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName)75
)
344
0
          return true;
345
346
        // Continued function call
347
87
        if (ScopeStart > Start + 1 &&
348
87
            
Changes[ScopeStart - 2].Tok->is(tok::identifier)75
&&
349
87
            
Changes[ScopeStart - 1].Tok->is(tok::l_paren)18
)
350
9
          return Style.BinPackArguments;
351
352
        // Ternary operator
353
78
        if (Changes[i].Tok->is(TT_ConditionalExpr))
354
66
          return true;
355
356
        // Period Initializer .XXX = 1.
357
12
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
358
0
          return true;
359
360
        // Continued ternary operator
361
12
        if (Changes[i].Tok->Previous &&
362
12
            
Changes[i].Tok->Previous->is(TT_ConditionalExpr)9
)
363
0
          return true;
364
365
12
        return false;
366
12
      };
WhitespaceManager.cpp:void clang::format::AlignTokenSequence<clang::format::WhitespaceManager::alignChainedConditionals()::$_6&>(clang::format::FormatStyle const&, unsigned int, unsigned int, unsigned int, clang::format::WhitespaceManager::alignChainedConditionals()::$_6&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&)::'lambda'()::operator()() const
Line
Count
Source
336
62
      auto ShouldShiftBeAdded = [&] {
337
        // Function declaration
338
62
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
339
0
          return true;
340
341
        // Continued function declaration
342
62
        if (ScopeStart > Start + 1 &&
343
62
            
Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName)47
)
344
0
          return true;
345
346
        // Continued function call
347
62
        if (ScopeStart > Start + 1 &&
348
62
            
Changes[ScopeStart - 2].Tok->is(tok::identifier)47
&&
349
62
            
Changes[ScopeStart - 1].Tok->is(tok::l_paren)9
)
350
9
          return Style.BinPackArguments;
351
352
        // Ternary operator
353
53
        if (Changes[i].Tok->is(TT_ConditionalExpr))
354
0
          return true;
355
356
        // Period Initializer .XXX = 1.
357
53
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
358
0
          return true;
359
360
        // Continued ternary operator
361
53
        if (Changes[i].Tok->Previous &&
362
53
            
Changes[i].Tok->Previous->is(TT_ConditionalExpr)51
)
363
48
          return true;
364
365
5
        return false;
366
53
      };
367
368
943
      if (ShouldShiftBeAdded())
369
279
        Changes[i].Spaces += Shift;
370
943
    }
371
372
21.2k
    if (ContinuedStringLiteral)
373
47
      Changes[i].Spaces += Shift;
374
375
21.2k
    assert(Shift >= 0);
376
377
0
    Changes[i].StartOfTokenColumn += Shift;
378
21.2k
    if (i + 1 != Changes.size())
379
20.7k
      Changes[i + 1].PreviousEndOfTokenColumn += Shift;
380
381
    // If PointerAlignment is PAS_Right, keep *s or &s next to the token
382
21.2k
    if (Style.PointerAlignment == FormatStyle::PAS_Right &&
383
21.2k
        
Changes[i].Spaces != 018.9k
) {
384
10.9k
      for (int Previous = i - 1;
385
11.0k
           Previous >= 0 &&
386
11.0k
           Changes[Previous].Tok->getType() == TT_PointerOrReference;
387
10.9k
           
--Previous71
) {
388
71
        Changes[Previous + 1].Spaces -= Shift;
389
71
        Changes[Previous].Spaces += Shift;
390
71
      }
391
10.9k
    }
392
21.2k
  }
393
1.74k
}
WhitespaceManager.cpp:void clang::format::AlignTokenSequence<clang::format::WhitespaceManager::alignConsecutiveAssignments()::$_1&>(clang::format::FormatStyle const&, unsigned int, unsigned int, unsigned int, clang::format::WhitespaceManager::alignConsecutiveAssignments()::$_1&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&)
Line
Count
Source
270
558
                   SmallVector<WhitespaceManager::Change, 16> &Changes) {
271
558
  bool FoundMatchOnLine = false;
272
558
  int Shift = 0;
273
274
  // ScopeStack keeps track of the current scope depth. It contains indices of
275
  // the first token on each scope.
276
  // We only run the "Matches" function on tokens from the outer-most scope.
277
  // However, we do need to pay special attention to one class of tokens
278
  // that are not in the outer-most scope, and that is function parameters
279
  // which are split across multiple lines, as illustrated by this example:
280
  //   double a(int x);
281
  //   int    b(int  y,
282
  //          double z);
283
  // In the above example, we need to take special care to ensure that
284
  // 'double z' is indented along with it's owning function 'b'.
285
  // The same holds for calling a function:
286
  //   double a = foo(x);
287
  //   int    b = bar(foo(y),
288
  //            foor(z));
289
  // Similar for broken string literals:
290
  //   double x = 3.14;
291
  //   auto s   = "Hello"
292
  //          "World";
293
  // Special handling is required for 'nested' ternary operators.
294
558
  SmallVector<unsigned, 16> ScopeStack;
295
296
7.96k
  for (unsigned i = Start; i != End; 
++i7.40k
) {
297
7.40k
    if (ScopeStack.size() != 0 &&
298
7.40k
        Changes[i].indentAndNestingLevel() <
299
3.04k
            Changes[ScopeStack.back()].indentAndNestingLevel())
300
558
      ScopeStack.pop_back();
301
302
    // Compare current token to previous non-comment token to ensure whether
303
    // it is in a deeper scope or not.
304
7.40k
    unsigned PreviousNonComment = i - 1;
305
7.56k
    while (PreviousNonComment > Start &&
306
7.56k
           
Changes[PreviousNonComment].Tok->is(tok::comment)6.44k
)
307
158
      PreviousNonComment--;
308
7.40k
    if (i != Start && Changes[i].indentAndNestingLevel() >
309
6.84k
                          Changes[PreviousNonComment].indentAndNestingLevel())
310
591
      ScopeStack.push_back(i);
311
312
7.40k
    bool InsideNestedScope = ScopeStack.size() != 0;
313
7.40k
    bool ContinuedStringLiteral = i > Start &&
314
7.40k
                                  
Changes[i].Tok->is(tok::string_literal)6.84k
&&
315
7.40k
                                  
Changes[i - 1].Tok->is(tok::string_literal)178
;
316
7.40k
    bool SkipMatchCheck = InsideNestedScope || 
ContinuedStringLiteral4.32k
;
317
318
7.40k
    if (Changes[i].NewlinesBefore > 0 && 
!SkipMatchCheck817
) {
319
517
      Shift = 0;
320
517
      FoundMatchOnLine = false;
321
517
    }
322
323
    // If this is the first matching token to be aligned, remember by how many
324
    // spaces it has to be shifted, so the rest of the changes on the line are
325
    // shifted by the same amount
326
7.40k
    if (!FoundMatchOnLine && 
!SkipMatchCheck2.24k
&&
Matches(Changes[i])2.02k
) {
327
917
      FoundMatchOnLine = true;
328
917
      Shift = Column - Changes[i].StartOfTokenColumn;
329
917
      Changes[i].Spaces += Shift;
330
917
    }
331
332
    // This is for function parameters that are split across multiple lines,
333
    // as mentioned in the ScopeStack comment.
334
7.40k
    if (InsideNestedScope && 
Changes[i].NewlinesBefore > 03.07k
) {
335
288
      unsigned ScopeStart = ScopeStack.back();
336
288
      auto ShouldShiftBeAdded = [&] {
337
        // Function declaration
338
288
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
339
288
          return true;
340
341
        // Continued function declaration
342
288
        if (ScopeStart > Start + 1 &&
343
288
            Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName))
344
288
          return true;
345
346
        // Continued function call
347
288
        if (ScopeStart > Start + 1 &&
348
288
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
349
288
            Changes[ScopeStart - 1].Tok->is(tok::l_paren))
350
288
          return Style.BinPackArguments;
351
352
        // Ternary operator
353
288
        if (Changes[i].Tok->is(TT_ConditionalExpr))
354
288
          return true;
355
356
        // Period Initializer .XXX = 1.
357
288
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
358
288
          return true;
359
360
        // Continued ternary operator
361
288
        if (Changes[i].Tok->Previous &&
362
288
            Changes[i].Tok->Previous->is(TT_ConditionalExpr))
363
288
          return true;
364
365
288
        return false;
366
288
      };
367
368
288
      if (ShouldShiftBeAdded())
369
39
        Changes[i].Spaces += Shift;
370
288
    }
371
372
7.40k
    if (ContinuedStringLiteral)
373
16
      Changes[i].Spaces += Shift;
374
375
7.40k
    assert(Shift >= 0);
376
377
0
    Changes[i].StartOfTokenColumn += Shift;
378
7.40k
    if (i + 1 != Changes.size())
379
7.22k
      Changes[i + 1].PreviousEndOfTokenColumn += Shift;
380
381
    // If PointerAlignment is PAS_Right, keep *s or &s next to the token
382
7.40k
    if (Style.PointerAlignment == FormatStyle::PAS_Right &&
383
7.40k
        
Changes[i].Spaces != 07.22k
) {
384
3.69k
      for (int Previous = i - 1;
385
3.69k
           Previous >= 0 &&
386
3.69k
           Changes[Previous].Tok->getType() == TT_PointerOrReference;
387
3.69k
           
--Previous0
) {
388
0
        Changes[Previous + 1].Spaces -= Shift;
389
0
        Changes[Previous].Spaces += Shift;
390
0
      }
391
3.69k
    }
392
7.40k
  }
393
558
}
WhitespaceManager.cpp:void clang::format::AlignTokenSequence<clang::format::WhitespaceManager::alignConsecutiveBitFields()::$_2&>(clang::format::FormatStyle const&, unsigned int, unsigned int, unsigned int, clang::format::WhitespaceManager::alignConsecutiveBitFields()::$_2&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&)
Line
Count
Source
270
36
                   SmallVector<WhitespaceManager::Change, 16> &Changes) {
271
36
  bool FoundMatchOnLine = false;
272
36
  int Shift = 0;
273
274
  // ScopeStack keeps track of the current scope depth. It contains indices of
275
  // the first token on each scope.
276
  // We only run the "Matches" function on tokens from the outer-most scope.
277
  // However, we do need to pay special attention to one class of tokens
278
  // that are not in the outer-most scope, and that is function parameters
279
  // which are split across multiple lines, as illustrated by this example:
280
  //   double a(int x);
281
  //   int    b(int  y,
282
  //          double z);
283
  // In the above example, we need to take special care to ensure that
284
  // 'double z' is indented along with it's owning function 'b'.
285
  // The same holds for calling a function:
286
  //   double a = foo(x);
287
  //   int    b = bar(foo(y),
288
  //            foor(z));
289
  // Similar for broken string literals:
290
  //   double x = 3.14;
291
  //   auto s   = "Hello"
292
  //          "World";
293
  // Special handling is required for 'nested' ternary operators.
294
36
  SmallVector<unsigned, 16> ScopeStack;
295
296
439
  for (unsigned i = Start; i != End; 
++i403
) {
297
403
    if (ScopeStack.size() != 0 &&
298
403
        Changes[i].indentAndNestingLevel() <
299
6
            Changes[ScopeStack.back()].indentAndNestingLevel())
300
3
      ScopeStack.pop_back();
301
302
    // Compare current token to previous non-comment token to ensure whether
303
    // it is in a deeper scope or not.
304
403
    unsigned PreviousNonComment = i - 1;
305
413
    while (PreviousNonComment > Start &&
306
413
           
Changes[PreviousNonComment].Tok->is(tok::comment)341
)
307
10
      PreviousNonComment--;
308
403
    if (i != Start && Changes[i].indentAndNestingLevel() >
309
367
                          Changes[PreviousNonComment].indentAndNestingLevel())
310
3
      ScopeStack.push_back(i);
311
312
403
    bool InsideNestedScope = ScopeStack.size() != 0;
313
403
    bool ContinuedStringLiteral = i > Start &&
314
403
                                  
Changes[i].Tok->is(tok::string_literal)367
&&
315
403
                                  
Changes[i - 1].Tok->is(tok::string_literal)0
;
316
403
    bool SkipMatchCheck = InsideNestedScope || 
ContinuedStringLiteral397
;
317
318
403
    if (Changes[i].NewlinesBefore > 0 && 
!SkipMatchCheck43
) {
319
43
      Shift = 0;
320
43
      FoundMatchOnLine = false;
321
43
    }
322
323
    // If this is the first matching token to be aligned, remember by how many
324
    // spaces it has to be shifted, so the rest of the changes on the line are
325
    // shifted by the same amount
326
403
    if (!FoundMatchOnLine && 
!SkipMatchCheck157
&&
Matches(Changes[i])157
) {
327
75
      FoundMatchOnLine = true;
328
75
      Shift = Column - Changes[i].StartOfTokenColumn;
329
75
      Changes[i].Spaces += Shift;
330
75
    }
331
332
    // This is for function parameters that are split across multiple lines,
333
    // as mentioned in the ScopeStack comment.
334
403
    if (InsideNestedScope && 
Changes[i].NewlinesBefore > 06
) {
335
0
      unsigned ScopeStart = ScopeStack.back();
336
0
      auto ShouldShiftBeAdded = [&] {
337
        // Function declaration
338
0
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
339
0
          return true;
340
341
        // Continued function declaration
342
0
        if (ScopeStart > Start + 1 &&
343
0
            Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName))
344
0
          return true;
345
346
        // Continued function call
347
0
        if (ScopeStart > Start + 1 &&
348
0
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
349
0
            Changes[ScopeStart - 1].Tok->is(tok::l_paren))
350
0
          return Style.BinPackArguments;
351
352
        // Ternary operator
353
0
        if (Changes[i].Tok->is(TT_ConditionalExpr))
354
0
          return true;
355
356
        // Period Initializer .XXX = 1.
357
0
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
358
0
          return true;
359
360
        // Continued ternary operator
361
0
        if (Changes[i].Tok->Previous &&
362
0
            Changes[i].Tok->Previous->is(TT_ConditionalExpr))
363
0
          return true;
364
365
0
        return false;
366
0
      };
367
368
0
      if (ShouldShiftBeAdded())
369
0
        Changes[i].Spaces += Shift;
370
0
    }
371
372
403
    if (ContinuedStringLiteral)
373
0
      Changes[i].Spaces += Shift;
374
375
403
    assert(Shift >= 0);
376
377
0
    Changes[i].StartOfTokenColumn += Shift;
378
403
    if (i + 1 != Changes.size())
379
367
      Changes[i + 1].PreviousEndOfTokenColumn += Shift;
380
381
    // If PointerAlignment is PAS_Right, keep *s or &s next to the token
382
403
    if (Style.PointerAlignment == FormatStyle::PAS_Right &&
383
403
        Changes[i].Spaces != 0) {
384
225
      for (int Previous = i - 1;
385
225
           Previous >= 0 &&
386
225
           Changes[Previous].Tok->getType() == TT_PointerOrReference;
387
225
           
--Previous0
) {
388
0
        Changes[Previous + 1].Spaces -= Shift;
389
0
        Changes[Previous].Spaces += Shift;
390
0
      }
391
225
    }
392
403
  }
393
36
}
WhitespaceManager.cpp:void clang::format::AlignTokenSequence<clang::format::WhitespaceManager::alignConsecutiveDeclarations()::$_3&>(clang::format::FormatStyle const&, unsigned int, unsigned int, unsigned int, clang::format::WhitespaceManager::alignConsecutiveDeclarations()::$_3&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&)
Line
Count
Source
270
589
                   SmallVector<WhitespaceManager::Change, 16> &Changes) {
271
589
  bool FoundMatchOnLine = false;
272
589
  int Shift = 0;
273
274
  // ScopeStack keeps track of the current scope depth. It contains indices of
275
  // the first token on each scope.
276
  // We only run the "Matches" function on tokens from the outer-most scope.
277
  // However, we do need to pay special attention to one class of tokens
278
  // that are not in the outer-most scope, and that is function parameters
279
  // which are split across multiple lines, as illustrated by this example:
280
  //   double a(int x);
281
  //   int    b(int  y,
282
  //          double z);
283
  // In the above example, we need to take special care to ensure that
284
  // 'double z' is indented along with it's owning function 'b'.
285
  // The same holds for calling a function:
286
  //   double a = foo(x);
287
  //   int    b = bar(foo(y),
288
  //            foor(z));
289
  // Similar for broken string literals:
290
  //   double x = 3.14;
291
  //   auto s   = "Hello"
292
  //          "World";
293
  // Special handling is required for 'nested' ternary operators.
294
589
  SmallVector<unsigned, 16> ScopeStack;
295
296
10.7k
  for (unsigned i = Start; i != End; 
++i10.1k
) {
297
10.1k
    if (ScopeStack.size() != 0 &&
298
10.1k
        Changes[i].indentAndNestingLevel() <
299
4.71k
            Changes[ScopeStack.back()].indentAndNestingLevel())
300
728
      ScopeStack.pop_back();
301
302
    // Compare current token to previous non-comment token to ensure whether
303
    // it is in a deeper scope or not.
304
10.1k
    unsigned PreviousNonComment = i - 1;
305
10.2k
    while (PreviousNonComment > Start &&
306
10.2k
           
Changes[PreviousNonComment].Tok->is(tok::comment)9.03k
)
307
91
      PreviousNonComment--;
308
10.1k
    if (i != Start && Changes[i].indentAndNestingLevel() >
309
9.52k
                          Changes[PreviousNonComment].indentAndNestingLevel())
310
809
      ScopeStack.push_back(i);
311
312
10.1k
    bool InsideNestedScope = ScopeStack.size() != 0;
313
10.1k
    bool ContinuedStringLiteral = i > Start &&
314
10.1k
                                  
Changes[i].Tok->is(tok::string_literal)9.52k
&&
315
10.1k
                                  
Changes[i - 1].Tok->is(tok::string_literal)205
;
316
10.1k
    bool SkipMatchCheck = InsideNestedScope || 
ContinuedStringLiteral5.32k
;
317
318
10.1k
    if (Changes[i].NewlinesBefore > 0 && 
!SkipMatchCheck1.12k
) {
319
603
      Shift = 0;
320
603
      FoundMatchOnLine = false;
321
603
    }
322
323
    // If this is the first matching token to be aligned, remember by how many
324
    // spaces it has to be shifted, so the rest of the changes on the line are
325
    // shifted by the same amount
326
10.1k
    if (!FoundMatchOnLine && 
!SkipMatchCheck2.38k
&&
Matches(Changes[i])2.29k
) {
327
1.08k
      FoundMatchOnLine = true;
328
1.08k
      Shift = Column - Changes[i].StartOfTokenColumn;
329
1.08k
      Changes[i].Spaces += Shift;
330
1.08k
    }
331
332
    // This is for function parameters that are split across multiple lines,
333
    // as mentioned in the ScopeStack comment.
334
10.1k
    if (InsideNestedScope && 
Changes[i].NewlinesBefore > 04.79k
) {
335
506
      unsigned ScopeStart = ScopeStack.back();
336
506
      auto ShouldShiftBeAdded = [&] {
337
        // Function declaration
338
506
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
339
506
          return true;
340
341
        // Continued function declaration
342
506
        if (ScopeStart > Start + 1 &&
343
506
            Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName))
344
506
          return true;
345
346
        // Continued function call
347
506
        if (ScopeStart > Start + 1 &&
348
506
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
349
506
            Changes[ScopeStart - 1].Tok->is(tok::l_paren))
350
506
          return Style.BinPackArguments;
351
352
        // Ternary operator
353
506
        if (Changes[i].Tok->is(TT_ConditionalExpr))
354
506
          return true;
355
356
        // Period Initializer .XXX = 1.
357
506
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
358
506
          return true;
359
360
        // Continued ternary operator
361
506
        if (Changes[i].Tok->Previous &&
362
506
            Changes[i].Tok->Previous->is(TT_ConditionalExpr))
363
506
          return true;
364
365
506
        return false;
366
506
      };
367
368
506
      if (ShouldShiftBeAdded())
369
108
        Changes[i].Spaces += Shift;
370
506
    }
371
372
10.1k
    if (ContinuedStringLiteral)
373
28
      Changes[i].Spaces += Shift;
374
375
10.1k
    assert(Shift >= 0);
376
377
0
    Changes[i].StartOfTokenColumn += Shift;
378
10.1k
    if (i + 1 != Changes.size())
379
9.86k
      Changes[i + 1].PreviousEndOfTokenColumn += Shift;
380
381
    // If PointerAlignment is PAS_Right, keep *s or &s next to the token
382
10.1k
    if (Style.PointerAlignment == FormatStyle::PAS_Right &&
383
10.1k
        
Changes[i].Spaces != 08.21k
) {
384
4.22k
      for (int Previous = i - 1;
385
4.29k
           Previous >= 0 &&
386
4.29k
           Changes[Previous].Tok->getType() == TT_PointerOrReference;
387
4.22k
           
--Previous71
) {
388
71
        Changes[Previous + 1].Spaces -= Shift;
389
71
        Changes[Previous].Spaces += Shift;
390
71
      }
391
4.22k
    }
392
10.1k
  }
393
589
}
WhitespaceManager.cpp:void clang::format::AlignTokenSequence<clang::format::WhitespaceManager::alignChainedConditionals()::$_4&>(clang::format::FormatStyle const&, unsigned int, unsigned int, unsigned int, clang::format::WhitespaceManager::alignChainedConditionals()::$_4&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&)
Line
Count
Source
270
367
                   SmallVector<WhitespaceManager::Change, 16> &Changes) {
271
367
  bool FoundMatchOnLine = false;
272
367
  int Shift = 0;
273
274
  // ScopeStack keeps track of the current scope depth. It contains indices of
275
  // the first token on each scope.
276
  // We only run the "Matches" function on tokens from the outer-most scope.
277
  // However, we do need to pay special attention to one class of tokens
278
  // that are not in the outer-most scope, and that is function parameters
279
  // which are split across multiple lines, as illustrated by this example:
280
  //   double a(int x);
281
  //   int    b(int  y,
282
  //          double z);
283
  // In the above example, we need to take special care to ensure that
284
  // 'double z' is indented along with it's owning function 'b'.
285
  // The same holds for calling a function:
286
  //   double a = foo(x);
287
  //   int    b = bar(foo(y),
288
  //            foor(z));
289
  // Similar for broken string literals:
290
  //   double x = 3.14;
291
  //   auto s   = "Hello"
292
  //          "World";
293
  // Special handling is required for 'nested' ternary operators.
294
367
  SmallVector<unsigned, 16> ScopeStack;
295
296
2.33k
  for (unsigned i = Start; i != End; 
++i1.96k
) {
297
1.96k
    if (ScopeStack.size() != 0 &&
298
1.96k
        Changes[i].indentAndNestingLevel() <
299
427
            Changes[ScopeStack.back()].indentAndNestingLevel())
300
73
      ScopeStack.pop_back();
301
302
    // Compare current token to previous non-comment token to ensure whether
303
    // it is in a deeper scope or not.
304
1.96k
    unsigned PreviousNonComment = i - 1;
305
1.97k
    while (PreviousNonComment > Start &&
306
1.97k
           
Changes[PreviousNonComment].Tok->is(tok::comment)1.24k
)
307
9
      PreviousNonComment--;
308
1.96k
    if (i != Start && Changes[i].indentAndNestingLevel() >
309
1.60k
                          Changes[PreviousNonComment].indentAndNestingLevel())
310
94
      ScopeStack.push_back(i);
311
312
1.96k
    bool InsideNestedScope = ScopeStack.size() != 0;
313
1.96k
    bool ContinuedStringLiteral = i > Start &&
314
1.96k
                                  
Changes[i].Tok->is(tok::string_literal)1.60k
&&
315
1.96k
                                  
Changes[i - 1].Tok->is(tok::string_literal)20
;
316
1.96k
    bool SkipMatchCheck = InsideNestedScope || 
ContinuedStringLiteral1.52k
;
317
318
1.96k
    if (Changes[i].NewlinesBefore > 0 && 
!SkipMatchCheck388
) {
319
298
      Shift = 0;
320
298
      FoundMatchOnLine = false;
321
298
    }
322
323
    // If this is the first matching token to be aligned, remember by how many
324
    // spaces it has to be shifted, so the rest of the changes on the line are
325
    // shifted by the same amount
326
1.96k
    if (!FoundMatchOnLine && 
!SkipMatchCheck772
&&
Matches(Changes[i])772
) {
327
595
      FoundMatchOnLine = true;
328
595
      Shift = Column - Changes[i].StartOfTokenColumn;
329
595
      Changes[i].Spaces += Shift;
330
595
    }
331
332
    // This is for function parameters that are split across multiple lines,
333
    // as mentioned in the ScopeStack comment.
334
1.96k
    if (InsideNestedScope && 
Changes[i].NewlinesBefore > 0448
) {
335
87
      unsigned ScopeStart = ScopeStack.back();
336
87
      auto ShouldShiftBeAdded = [&] {
337
        // Function declaration
338
87
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
339
87
          return true;
340
341
        // Continued function declaration
342
87
        if (ScopeStart > Start + 1 &&
343
87
            Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName))
344
87
          return true;
345
346
        // Continued function call
347
87
        if (ScopeStart > Start + 1 &&
348
87
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
349
87
            Changes[ScopeStart - 1].Tok->is(tok::l_paren))
350
87
          return Style.BinPackArguments;
351
352
        // Ternary operator
353
87
        if (Changes[i].Tok->is(TT_ConditionalExpr))
354
87
          return true;
355
356
        // Period Initializer .XXX = 1.
357
87
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
358
87
          return true;
359
360
        // Continued ternary operator
361
87
        if (Changes[i].Tok->Previous &&
362
87
            Changes[i].Tok->Previous->is(TT_ConditionalExpr))
363
87
          return true;
364
365
87
        return false;
366
87
      };
367
368
87
      if (ShouldShiftBeAdded())
369
75
        Changes[i].Spaces += Shift;
370
87
    }
371
372
1.96k
    if (ContinuedStringLiteral)
373
3
      Changes[i].Spaces += Shift;
374
375
1.96k
    assert(Shift >= 0);
376
377
0
    Changes[i].StartOfTokenColumn += Shift;
378
1.96k
    if (i + 1 != Changes.size())
379
1.96k
      Changes[i + 1].PreviousEndOfTokenColumn += Shift;
380
381
    // If PointerAlignment is PAS_Right, keep *s or &s next to the token
382
1.96k
    if (Style.PointerAlignment == FormatStyle::PAS_Right &&
383
1.96k
        
Changes[i].Spaces != 01.88k
) {
384
1.67k
      for (int Previous = i - 1;
385
1.67k
           Previous >= 0 &&
386
1.67k
           Changes[Previous].Tok->getType() == TT_PointerOrReference;
387
1.67k
           
--Previous0
) {
388
0
        Changes[Previous + 1].Spaces -= Shift;
389
0
        Changes[Previous].Spaces += Shift;
390
0
      }
391
1.67k
    }
392
1.96k
  }
393
367
}
WhitespaceManager.cpp:void clang::format::AlignTokenSequence<clang::format::WhitespaceManager::alignChainedConditionals()::$_6&>(clang::format::FormatStyle const&, unsigned int, unsigned int, unsigned int, clang::format::WhitespaceManager::alignChainedConditionals()::$_6&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&)
Line
Count
Source
270
197
                   SmallVector<WhitespaceManager::Change, 16> &Changes) {
271
197
  bool FoundMatchOnLine = false;
272
197
  int Shift = 0;
273
274
  // ScopeStack keeps track of the current scope depth. It contains indices of
275
  // the first token on each scope.
276
  // We only run the "Matches" function on tokens from the outer-most scope.
277
  // However, we do need to pay special attention to one class of tokens
278
  // that are not in the outer-most scope, and that is function parameters
279
  // which are split across multiple lines, as illustrated by this example:
280
  //   double a(int x);
281
  //   int    b(int  y,
282
  //          double z);
283
  // In the above example, we need to take special care to ensure that
284
  // 'double z' is indented along with it's owning function 'b'.
285
  // The same holds for calling a function:
286
  //   double a = foo(x);
287
  //   int    b = bar(foo(y),
288
  //            foor(z));
289
  // Similar for broken string literals:
290
  //   double x = 3.14;
291
  //   auto s   = "Hello"
292
  //          "World";
293
  // Special handling is required for 'nested' ternary operators.
294
197
  SmallVector<unsigned, 16> ScopeStack;
295
296
1.54k
  for (unsigned i = Start; i != End; 
++i1.34k
) {
297
1.34k
    if (ScopeStack.size() != 0 &&
298
1.34k
        Changes[i].indentAndNestingLevel() <
299
302
            Changes[ScopeStack.back()].indentAndNestingLevel())
300
50
      ScopeStack.pop_back();
301
302
    // Compare current token to previous non-comment token to ensure whether
303
    // it is in a deeper scope or not.
304
1.34k
    unsigned PreviousNonComment = i - 1;
305
1.35k
    while (PreviousNonComment > Start &&
306
1.35k
           
Changes[PreviousNonComment].Tok->is(tok::comment)984
)
307
3
      PreviousNonComment--;
308
1.34k
    if (i != Start && Changes[i].indentAndNestingLevel() >
309
1.15k
                          Changes[PreviousNonComment].indentAndNestingLevel())
310
65
      ScopeStack.push_back(i);
311
312
1.34k
    bool InsideNestedScope = ScopeStack.size() != 0;
313
1.34k
    bool ContinuedStringLiteral = i > Start &&
314
1.34k
                                  
Changes[i].Tok->is(tok::string_literal)1.15k
&&
315
1.34k
                                  
Changes[i - 1].Tok->is(tok::string_literal)8
;
316
1.34k
    bool SkipMatchCheck = InsideNestedScope || 
ContinuedStringLiteral1.03k
;
317
318
1.34k
    if (Changes[i].NewlinesBefore > 0 && 
!SkipMatchCheck310
) {
319
248
      Shift = 0;
320
248
      FoundMatchOnLine = false;
321
248
    }
322
323
    // If this is the first matching token to be aligned, remember by how many
324
    // spaces it has to be shifted, so the rest of the changes on the line are
325
    // shifted by the same amount
326
1.34k
    if (!FoundMatchOnLine && 
!SkipMatchCheck475
&&
Matches(Changes[i])475
) {
327
394
      FoundMatchOnLine = true;
328
394
      Shift = Column - Changes[i].StartOfTokenColumn;
329
394
      Changes[i].Spaces += Shift;
330
394
    }
331
332
    // This is for function parameters that are split across multiple lines,
333
    // as mentioned in the ScopeStack comment.
334
1.34k
    if (InsideNestedScope && 
Changes[i].NewlinesBefore > 0317
) {
335
62
      unsigned ScopeStart = ScopeStack.back();
336
62
      auto ShouldShiftBeAdded = [&] {
337
        // Function declaration
338
62
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
339
62
          return true;
340
341
        // Continued function declaration
342
62
        if (ScopeStart > Start + 1 &&
343
62
            Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName))
344
62
          return true;
345
346
        // Continued function call
347
62
        if (ScopeStart > Start + 1 &&
348
62
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
349
62
            Changes[ScopeStart - 1].Tok->is(tok::l_paren))
350
62
          return Style.BinPackArguments;
351
352
        // Ternary operator
353
62
        if (Changes[i].Tok->is(TT_ConditionalExpr))
354
62
          return true;
355
356
        // Period Initializer .XXX = 1.
357
62
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
358
62
          return true;
359
360
        // Continued ternary operator
361
62
        if (Changes[i].Tok->Previous &&
362
62
            Changes[i].Tok->Previous->is(TT_ConditionalExpr))
363
62
          return true;
364
365
62
        return false;
366
62
      };
367
368
62
      if (ShouldShiftBeAdded())
369
57
        Changes[i].Spaces += Shift;
370
62
    }
371
372
1.34k
    if (ContinuedStringLiteral)
373
0
      Changes[i].Spaces += Shift;
374
375
1.34k
    assert(Shift >= 0);
376
377
0
    Changes[i].StartOfTokenColumn += Shift;
378
1.34k
    if (i + 1 != Changes.size())
379
1.34k
      Changes[i + 1].PreviousEndOfTokenColumn += Shift;
380
381
    // If PointerAlignment is PAS_Right, keep *s or &s next to the token
382
1.34k
    if (Style.PointerAlignment == FormatStyle::PAS_Right &&
383
1.34k
        
Changes[i].Spaces != 01.22k
) {
384
1.11k
      for (int Previous = i - 1;
385
1.11k
           Previous >= 0 &&
386
1.11k
           Changes[Previous].Tok->getType() == TT_PointerOrReference;
387
1.11k
           
--Previous0
) {
388
0
        Changes[Previous + 1].Spaces -= Shift;
389
0
        Changes[Previous].Spaces += Shift;
390
0
      }
391
1.11k
    }
392
1.34k
  }
393
197
}
394
395
// Walk through a subset of the changes, starting at StartAt, and find
396
// sequences of matching tokens to align. To do so, keep track of the lines and
397
// whether or not a matching token was found on a line. If a matching token is
398
// found, extend the current sequence. If the current line cannot be part of a
399
// sequence, e.g. because there is an empty line before it or it contains only
400
// non-matching tokens, finalize the previous sequence.
401
// The value returned is the token on which we stopped, either because we
402
// exhausted all items inside Changes, or because we hit a scope level higher
403
// than our initial scope.
404
// This function is recursive. Each invocation processes only the scope level
405
// equal to the initial level, which is the level of Changes[StartAt].
406
// If we encounter a scope level greater than the initial level, then we call
407
// ourselves recursively, thereby avoiding the pollution of the current state
408
// with the alignment requirements of the nested sub-level. This recursive
409
// behavior is necessary for aligning function prototypes that have one or more
410
// arguments.
411
// If this function encounters a scope level less than the initial level,
412
// it returns the current position.
413
// There is a non-obvious subtlety in the recursive behavior: Even though we
414
// defer processing of nested levels to recursive invocations of this
415
// function, when it comes time to align a sequence of tokens, we run the
416
// alignment on the entire sequence, including the nested levels.
417
// When doing so, most of the nested tokens are skipped, because their
418
// alignment was already handled by the recursive invocations of this function.
419
// However, the special exception is that we do NOT skip function parameters
420
// that are split across multiple lines. See the test case in FormatTest.cpp
421
// that mentions "split function parameter alignment" for an example of this.
422
template <typename F>
423
static unsigned AlignTokens(
424
    const FormatStyle &Style, F &&Matches,
425
    SmallVector<WhitespaceManager::Change, 16> &Changes, unsigned StartAt,
426
69.4k
    const FormatStyle::AlignConsecutiveStyle &ACS = FormatStyle::ACS_None) {
427
69.4k
  unsigned MinColumn = 0;
428
69.4k
  unsigned MaxColumn = UINT_MAX;
429
430
  // Line number of the start and the end of the current token sequence.
431
69.4k
  unsigned StartOfSequence = 0;
432
69.4k
  unsigned EndOfSequence = 0;
433
434
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
435
  // abort when we hit any token in a higher scope than the starting one.
436
69.4k
  auto IndentAndNestingLevel = StartAt < Changes.size()
437
69.4k
                                   ? Changes[StartAt].indentAndNestingLevel()
438
69.4k
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
439
440
  // Keep track of the number of commas before the matching tokens, we will only
441
  // align a sequence of matching tokens if they are preceded by the same number
442
  // of commas.
443
69.4k
  unsigned CommasBeforeLastMatch = 0;
444
69.4k
  unsigned CommasBeforeMatch = 0;
445
446
  // Whether a matching token has been found on the current line.
447
69.4k
  bool FoundMatchOnLine = false;
448
449
  // Whether the current line consists purely of comments.
450
69.4k
  bool LineIsComment = true;
451
452
  // Aligns a sequence of matching tokens, on the MinColumn column.
453
  //
454
  // Sequences start from the first matching token to align, and end at the
455
  // first token of the first line that doesn't need to be aligned.
456
  //
457
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
458
  // containing any matching token to be aligned and located after such token.
459
125k
  auto AlignCurrentSequence = [&] {
460
125k
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence2.00k
)
461
1.74k
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
1.74k
                         Matches, Changes);
463
125k
    MinColumn = 0;
464
125k
    MaxColumn = UINT_MAX;
465
125k
    StartOfSequence = 0;
466
125k
    EndOfSequence = 0;
467
125k
  };
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignConsecutiveAssignments()::$_1>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignConsecutiveAssignments()::$_1&&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)::'lambda'()::operator()() const
Line
Count
Source
459
1.15k
  auto AlignCurrentSequence = [&] {
460
1.15k
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence336
)
461
330
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
330
                         Matches, Changes);
463
1.15k
    MinColumn = 0;
464
1.15k
    MaxColumn = UINT_MAX;
465
1.15k
    StartOfSequence = 0;
466
1.15k
    EndOfSequence = 0;
467
1.15k
  };
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignConsecutiveAssignments()::$_1&>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignConsecutiveAssignments()::$_1&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)::'lambda'()::operator()() const
Line
Count
Source
459
1.96k
  auto AlignCurrentSequence = [&] {
460
1.96k
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence252
)
461
228
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
228
                         Matches, Changes);
463
1.96k
    MinColumn = 0;
464
1.96k
    MaxColumn = UINT_MAX;
465
1.96k
    StartOfSequence = 0;
466
1.96k
    EndOfSequence = 0;
467
1.96k
  };
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignConsecutiveBitFields()::$_2>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignConsecutiveBitFields()::$_2&&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)::'lambda'()::operator()() const
Line
Count
Source
459
36
  auto AlignCurrentSequence = [&] {
460
36
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
461
36
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
36
                         Matches, Changes);
463
36
    MinColumn = 0;
464
36
    MaxColumn = UINT_MAX;
465
36
    StartOfSequence = 0;
466
36
    EndOfSequence = 0;
467
36
  };
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignConsecutiveBitFields()::$_2&>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignConsecutiveBitFields()::$_2&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)::'lambda'()::operator()() const
Line
Count
Source
459
3
  auto AlignCurrentSequence = [&] {
460
3
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence0
)
461
0
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
0
                         Matches, Changes);
463
3
    MinColumn = 0;
464
3
    MaxColumn = UINT_MAX;
465
3
    StartOfSequence = 0;
466
3
    EndOfSequence = 0;
467
3
  };
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignConsecutiveDeclarations()::$_3>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignConsecutiveDeclarations()::$_3&&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)::'lambda'()::operator()() const
Line
Count
Source
459
887
  auto AlignCurrentSequence = [&] {
460
887
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence373
)
461
373
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
373
                         Matches, Changes);
463
887
    MinColumn = 0;
464
887
    MaxColumn = UINT_MAX;
465
887
    StartOfSequence = 0;
466
887
    EndOfSequence = 0;
467
887
  };
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignConsecutiveDeclarations()::$_3&>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignConsecutiveDeclarations()::$_3&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)::'lambda'()::operator()() const
Line
Count
Source
459
1.85k
  auto AlignCurrentSequence = [&] {
460
1.85k
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence300
)
461
216
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
216
                         Matches, Changes);
463
1.85k
    MinColumn = 0;
464
1.85k
    MaxColumn = UINT_MAX;
465
1.85k
    StartOfSequence = 0;
466
1.85k
    EndOfSequence = 0;
467
1.85k
  };
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignChainedConditionals()::$_4>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignChainedConditionals()::$_4&&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)::'lambda'()::operator()() const
Line
Count
Source
459
43.7k
  auto AlignCurrentSequence = [&] {
460
43.7k
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence23
)
461
16
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
16
                         Matches, Changes);
463
43.7k
    MinColumn = 0;
464
43.7k
    MaxColumn = UINT_MAX;
465
43.7k
    StartOfSequence = 0;
466
43.7k
    EndOfSequence = 0;
467
43.7k
  };
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignChainedConditionals()::$_4&>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignChainedConditionals()::$_4&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)::'lambda'()::operator()() const
Line
Count
Source
459
67.9k
  auto AlignCurrentSequence = [&] {
460
67.9k
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence485
)
461
351
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
351
                         Matches, Changes);
463
67.9k
    MinColumn = 0;
464
67.9k
    MaxColumn = UINT_MAX;
465
67.9k
    StartOfSequence = 0;
466
67.9k
    EndOfSequence = 0;
467
67.9k
  };
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignChainedConditionals()::$_6>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignChainedConditionals()::$_6&&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)::'lambda'()::operator()() const
Line
Count
Source
459
3.06k
  auto AlignCurrentSequence = [&] {
460
3.06k
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence11
)
461
11
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
11
                         Matches, Changes);
463
3.06k
    MinColumn = 0;
464
3.06k
    MaxColumn = UINT_MAX;
465
3.06k
    StartOfSequence = 0;
466
3.06k
    EndOfSequence = 0;
467
3.06k
  };
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignChainedConditionals()::$_6&>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignChainedConditionals()::$_6&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)::'lambda'()::operator()() const
Line
Count
Source
459
4.86k
  auto AlignCurrentSequence = [&] {
460
4.86k
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence186
)
461
186
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
186
                         Matches, Changes);
463
4.86k
    MinColumn = 0;
464
4.86k
    MaxColumn = UINT_MAX;
465
4.86k
    StartOfSequence = 0;
466
4.86k
    EndOfSequence = 0;
467
4.86k
  };
468
469
69.4k
  unsigned i = StartAt;
470
453k
  for (unsigned e = Changes.size(); i != e; 
++i383k
) {
471
433k
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
472
50.0k
      break;
473
474
383k
    if (Changes[i].NewlinesBefore != 0) {
475
57.6k
      CommasBeforeMatch = 0;
476
57.6k
      EndOfSequence = i;
477
478
      // Whether to break the alignment sequence because of an empty line.
479
57.6k
      bool EmptyLineBreak =
480
57.6k
          (Changes[i].NewlinesBefore > 1) &&
481
57.6k
          
(ACS != FormatStyle::ACS_AcrossEmptyLines)1.08k
&&
482
57.6k
          
(ACS != FormatStyle::ACS_AcrossEmptyLinesAndComments)1.07k
;
483
484
      // Whether to break the alignment sequence because of a line without a
485
      // match.
486
57.6k
      bool NoMatchBreak =
487
57.6k
          !FoundMatchOnLine &&
488
57.6k
          
!(55.7k
LineIsComment55.7k
&&
489
55.7k
            
(14.3k
(ACS == FormatStyle::ACS_AcrossComments)14.3k
||
490
14.3k
             
(ACS == FormatStyle::ACS_AcrossEmptyLinesAndComments)14.3k
));
491
492
57.6k
      if (EmptyLineBreak || 
NoMatchBreak56.5k
)
493
55.6k
        AlignCurrentSequence();
494
495
      // A new line starts, re-initialize line status tracking bools.
496
      // Keep the match state if a string literal is continued on this line.
497
57.6k
      if (i == 0 || 
!Changes[i].Tok->is(tok::string_literal)57.1k
||
498
57.6k
          
!Changes[i - 1].Tok->is(tok::string_literal)1.06k
)
499
57.2k
        FoundMatchOnLine = false;
500
57.6k
      LineIsComment = true;
501
57.6k
    }
502
503
383k
    if (!Changes[i].Tok->is(tok::comment)) {
504
377k
      LineIsComment = false;
505
377k
    }
506
507
383k
    if (Changes[i].Tok->is(tok::comma)) {
508
11.3k
      ++CommasBeforeMatch;
509
372k
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
510
      // Call AlignTokens recursively, skipping over this scope block.
511
50.0k
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
512
50.0k
      i = StoppedAt - 1;
513
50.0k
      continue;
514
50.0k
    }
515
516
333k
    if (!Matches(Changes[i]))
517
330k
      continue;
518
519
    // If there is more than one matching token per line, or if the number of
520
    // preceding commas, do not match anymore, end the sequence.
521
3.33k
    if (FoundMatchOnLine || 
CommasBeforeMatch != CommasBeforeLastMatch3.06k
)
522
328
      AlignCurrentSequence();
523
524
3.33k
    CommasBeforeLastMatch = CommasBeforeMatch;
525
3.33k
    FoundMatchOnLine = true;
526
527
3.33k
    if (StartOfSequence == 0)
528
1.98k
      StartOfSequence = i;
529
530
3.33k
    unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
531
3.33k
    int LineLengthAfter = Changes[i].TokenLength;
532
15.7k
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 014.8k
;
++j12.3k
) {
533
12.3k
      LineLengthAfter += Changes[j].Spaces;
534
      // Changes are generally 1:1 with the tokens, but a change could also be
535
      // inside of a token, in which case it's counted more than once: once for
536
      // the whitespace surrounding the token (!IsInsideToken) and once for
537
      // each whitespace change within it (IsInsideToken).
538
      // Therefore, changes inside of a token should only count the space.
539
12.3k
      if (!Changes[j].IsInsideToken)
540
12.3k
        LineLengthAfter += Changes[j].TokenLength;
541
12.3k
    }
542
3.33k
    unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
543
544
    // If we are restricted by the maximum column width, end the sequence.
545
3.33k
    if (ChangeMinColumn > MaxColumn || 
ChangeMaxColumn < MinColumn3.33k
||
546
3.33k
        
CommasBeforeLastMatch != CommasBeforeMatch3.32k
) {
547
15
      AlignCurrentSequence();
548
15
      StartOfSequence = i;
549
15
    }
550
551
3.33k
    MinColumn = std::max(MinColumn, ChangeMinColumn);
552
3.33k
    MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
553
3.33k
  }
554
555
69.4k
  EndOfSequence = i;
556
69.4k
  AlignCurrentSequence();
557
69.4k
  return i;
558
69.4k
}
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignConsecutiveAssignments()::$_1>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignConsecutiveAssignments()::$_1&&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)
Line
Count
Source
426
435
    const FormatStyle::AlignConsecutiveStyle &ACS = FormatStyle::ACS_None) {
427
435
  unsigned MinColumn = 0;
428
435
  unsigned MaxColumn = UINT_MAX;
429
430
  // Line number of the start and the end of the current token sequence.
431
435
  unsigned StartOfSequence = 0;
432
435
  unsigned EndOfSequence = 0;
433
434
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
435
  // abort when we hit any token in a higher scope than the starting one.
436
435
  auto IndentAndNestingLevel = StartAt < Changes.size()
437
435
                                   ? Changes[StartAt].indentAndNestingLevel()
438
435
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
439
440
  // Keep track of the number of commas before the matching tokens, we will only
441
  // align a sequence of matching tokens if they are preceded by the same number
442
  // of commas.
443
435
  unsigned CommasBeforeLastMatch = 0;
444
435
  unsigned CommasBeforeMatch = 0;
445
446
  // Whether a matching token has been found on the current line.
447
435
  bool FoundMatchOnLine = false;
448
449
  // Whether the current line consists purely of comments.
450
435
  bool LineIsComment = true;
451
452
  // Aligns a sequence of matching tokens, on the MinColumn column.
453
  //
454
  // Sequences start from the first matching token to align, and end at the
455
  // first token of the first line that doesn't need to be aligned.
456
  //
457
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
458
  // containing any matching token to be aligned and located after such token.
459
435
  auto AlignCurrentSequence = [&] {
460
435
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
461
435
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
435
                         Matches, Changes);
463
435
    MinColumn = 0;
464
435
    MaxColumn = UINT_MAX;
465
435
    StartOfSequence = 0;
466
435
    EndOfSequence = 0;
467
435
  };
468
469
435
  unsigned i = StartAt;
470
6.05k
  for (unsigned e = Changes.size(); i != e; 
++i5.62k
) {
471
5.62k
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
472
0
      break;
473
474
5.62k
    if (Changes[i].NewlinesBefore != 0) {
475
1.05k
      CommasBeforeMatch = 0;
476
1.05k
      EndOfSequence = i;
477
478
      // Whether to break the alignment sequence because of an empty line.
479
1.05k
      bool EmptyLineBreak =
480
1.05k
          (Changes[i].NewlinesBefore > 1) &&
481
1.05k
          
(ACS != FormatStyle::ACS_AcrossEmptyLines)31
&&
482
1.05k
          
(ACS != FormatStyle::ACS_AcrossEmptyLinesAndComments)26
;
483
484
      // Whether to break the alignment sequence because of a line without a
485
      // match.
486
1.05k
      bool NoMatchBreak =
487
1.05k
          !FoundMatchOnLine &&
488
1.05k
          
!(673
LineIsComment673
&&
489
673
            
(52
(ACS == FormatStyle::ACS_AcrossComments)52
||
490
52
             
(ACS == FormatStyle::ACS_AcrossEmptyLinesAndComments)42
));
491
492
1.05k
      if (EmptyLineBreak || 
NoMatchBreak1.04k
)
493
658
        AlignCurrentSequence();
494
495
      // A new line starts, re-initialize line status tracking bools.
496
      // Keep the match state if a string literal is continued on this line.
497
1.05k
      if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
498
1.05k
          
!Changes[i - 1].Tok->is(tok::string_literal)18
)
499
1.05k
        FoundMatchOnLine = false;
500
1.05k
      LineIsComment = true;
501
1.05k
    }
502
503
5.62k
    if (!Changes[i].Tok->is(tok::comment)) {
504
5.53k
      LineIsComment = false;
505
5.53k
    }
506
507
5.62k
    if (Changes[i].Tok->is(tok::comma)) {
508
30
      ++CommasBeforeMatch;
509
5.59k
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
510
      // Call AlignTokens recursively, skipping over this scope block.
511
628
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
512
628
      i = StoppedAt - 1;
513
628
      continue;
514
628
    }
515
516
4.99k
    if (!Matches(Changes[i]))
517
4.47k
      continue;
518
519
    // If there is more than one matching token per line, or if the number of
520
    // preceding commas, do not match anymore, end the sequence.
521
515
    if (FoundMatchOnLine || 
CommasBeforeMatch != CommasBeforeLastMatch494
)
522
54
      AlignCurrentSequence();
523
524
515
    CommasBeforeLastMatch = CommasBeforeMatch;
525
515
    FoundMatchOnLine = true;
526
527
515
    if (StartOfSequence == 0)
528
330
      StartOfSequence = i;
529
530
515
    unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
531
515
    int LineLengthAfter = Changes[i].TokenLength;
532
1.93k
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 01.82k
;
++j1.41k
) {
533
1.41k
      LineLengthAfter += Changes[j].Spaces;
534
      // Changes are generally 1:1 with the tokens, but a change could also be
535
      // inside of a token, in which case it's counted more than once: once for
536
      // the whitespace surrounding the token (!IsInsideToken) and once for
537
      // each whitespace change within it (IsInsideToken).
538
      // Therefore, changes inside of a token should only count the space.
539
1.41k
      if (!Changes[j].IsInsideToken)
540
1.41k
        LineLengthAfter += Changes[j].TokenLength;
541
1.41k
    }
542
515
    unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
543
544
    // If we are restricted by the maximum column width, end the sequence.
545
515
    if (ChangeMinColumn > MaxColumn || 
ChangeMaxColumn < MinColumn512
||
546
515
        
CommasBeforeLastMatch != CommasBeforeMatch509
) {
547
6
      AlignCurrentSequence();
548
6
      StartOfSequence = i;
549
6
    }
550
551
515
    MinColumn = std::max(MinColumn, ChangeMinColumn);
552
515
    MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
553
515
  }
554
555
435
  EndOfSequence = i;
556
435
  AlignCurrentSequence();
557
435
  return i;
558
435
}
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignConsecutiveAssignments()::$_1&>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignConsecutiveAssignments()::$_1&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)
Line
Count
Source
426
1.30k
    const FormatStyle::AlignConsecutiveStyle &ACS = FormatStyle::ACS_None) {
427
1.30k
  unsigned MinColumn = 0;
428
1.30k
  unsigned MaxColumn = UINT_MAX;
429
430
  // Line number of the start and the end of the current token sequence.
431
1.30k
  unsigned StartOfSequence = 0;
432
1.30k
  unsigned EndOfSequence = 0;
433
434
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
435
  // abort when we hit any token in a higher scope than the starting one.
436
1.30k
  auto IndentAndNestingLevel = StartAt < Changes.size()
437
1.30k
                                   ? Changes[StartAt].indentAndNestingLevel()
438
1.30k
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
439
440
  // Keep track of the number of commas before the matching tokens, we will only
441
  // align a sequence of matching tokens if they are preceded by the same number
442
  // of commas.
443
1.30k
  unsigned CommasBeforeLastMatch = 0;
444
1.30k
  unsigned CommasBeforeMatch = 0;
445
446
  // Whether a matching token has been found on the current line.
447
1.30k
  bool FoundMatchOnLine = false;
448
449
  // Whether the current line consists purely of comments.
450
1.30k
  bool LineIsComment = true;
451
452
  // Aligns a sequence of matching tokens, on the MinColumn column.
453
  //
454
  // Sequences start from the first matching token to align, and end at the
455
  // first token of the first line that doesn't need to be aligned.
456
  //
457
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
458
  // containing any matching token to be aligned and located after such token.
459
1.30k
  auto AlignCurrentSequence = [&] {
460
1.30k
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
461
1.30k
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
1.30k
                         Matches, Changes);
463
1.30k
    MinColumn = 0;
464
1.30k
    MaxColumn = UINT_MAX;
465
1.30k
    StartOfSequence = 0;
466
1.30k
    EndOfSequence = 0;
467
1.30k
  };
468
469
1.30k
  unsigned i = StartAt;
470
8.69k
  for (unsigned e = Changes.size(); i != e; 
++i7.39k
) {
471
8.69k
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
472
1.30k
      break;
473
474
7.39k
    if (Changes[i].NewlinesBefore != 0) {
475
946
      CommasBeforeMatch = 0;
476
946
      EndOfSequence = i;
477
478
      // Whether to break the alignment sequence because of an empty line.
479
946
      bool EmptyLineBreak =
480
946
          (Changes[i].NewlinesBefore > 1) &&
481
946
          
(ACS != FormatStyle::ACS_AcrossEmptyLines)6
&&
482
946
          
(ACS != FormatStyle::ACS_AcrossEmptyLinesAndComments)6
;
483
484
      // Whether to break the alignment sequence because of a line without a
485
      // match.
486
946
      bool NoMatchBreak =
487
946
          !FoundMatchOnLine &&
488
946
          
!(655
LineIsComment655
&&
489
655
            
(324
(ACS == FormatStyle::ACS_AcrossComments)324
||
490
324
             
(ACS == FormatStyle::ACS_AcrossEmptyLinesAndComments)317
));
491
492
946
      if (EmptyLineBreak || 
NoMatchBreak940
)
493
621
        AlignCurrentSequence();
494
495
      // A new line starts, re-initialize line status tracking bools.
496
      // Keep the match state if a string literal is continued on this line.
497
946
      if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
498
946
          
!Changes[i - 1].Tok->is(tok::string_literal)78
)
499
899
        FoundMatchOnLine = false;
500
946
      LineIsComment = true;
501
946
    }
502
503
7.39k
    if (!Changes[i].Tok->is(tok::comment)) {
504
7.28k
      LineIsComment = false;
505
7.28k
    }
506
507
7.39k
    if (Changes[i].Tok->is(tok::comma)) {
508
777
      ++CommasBeforeMatch;
509
6.61k
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
510
      // Call AlignTokens recursively, skipping over this scope block.
511
676
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
512
676
      i = StoppedAt - 1;
513
676
      continue;
514
676
    }
515
516
6.71k
    if (!Matches(Changes[i]))
517
6.27k
      continue;
518
519
    // If there is more than one matching token per line, or if the number of
520
    // preceding commas, do not match anymore, end the sequence.
521
447
    if (FoundMatchOnLine || 
CommasBeforeMatch != CommasBeforeLastMatch423
)
522
42
      AlignCurrentSequence();
523
524
447
    CommasBeforeLastMatch = CommasBeforeMatch;
525
447
    FoundMatchOnLine = true;
526
527
447
    if (StartOfSequence == 0)
528
252
      StartOfSequence = i;
529
530
447
    unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
531
447
    int LineLengthAfter = Changes[i].TokenLength;
532
2.20k
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 02.19k
;
++j1.76k
) {
533
1.76k
      LineLengthAfter += Changes[j].Spaces;
534
      // Changes are generally 1:1 with the tokens, but a change could also be
535
      // inside of a token, in which case it's counted more than once: once for
536
      // the whitespace surrounding the token (!IsInsideToken) and once for
537
      // each whitespace change within it (IsInsideToken).
538
      // Therefore, changes inside of a token should only count the space.
539
1.76k
      if (!Changes[j].IsInsideToken)
540
1.76k
        LineLengthAfter += Changes[j].TokenLength;
541
1.76k
    }
542
447
    unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
543
544
    // If we are restricted by the maximum column width, end the sequence.
545
447
    if (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn ||
546
447
        CommasBeforeLastMatch != CommasBeforeMatch) {
547
0
      AlignCurrentSequence();
548
0
      StartOfSequence = i;
549
0
    }
550
551
447
    MinColumn = std::max(MinColumn, ChangeMinColumn);
552
447
    MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
553
447
  }
554
555
1.30k
  EndOfSequence = i;
556
1.30k
  AlignCurrentSequence();
557
1.30k
  return i;
558
1.30k
}
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignConsecutiveBitFields()::$_2>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignConsecutiveBitFields()::$_2&&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)
Line
Count
Source
426
36
    const FormatStyle::AlignConsecutiveStyle &ACS = FormatStyle::ACS_None) {
427
36
  unsigned MinColumn = 0;
428
36
  unsigned MaxColumn = UINT_MAX;
429
430
  // Line number of the start and the end of the current token sequence.
431
36
  unsigned StartOfSequence = 0;
432
36
  unsigned EndOfSequence = 0;
433
434
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
435
  // abort when we hit any token in a higher scope than the starting one.
436
36
  auto IndentAndNestingLevel = StartAt < Changes.size()
437
36
                                   ? Changes[StartAt].indentAndNestingLevel()
438
36
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
439
440
  // Keep track of the number of commas before the matching tokens, we will only
441
  // align a sequence of matching tokens if they are preceded by the same number
442
  // of commas.
443
36
  unsigned CommasBeforeLastMatch = 0;
444
36
  unsigned CommasBeforeMatch = 0;
445
446
  // Whether a matching token has been found on the current line.
447
36
  bool FoundMatchOnLine = false;
448
449
  // Whether the current line consists purely of comments.
450
36
  bool LineIsComment = true;
451
452
  // Aligns a sequence of matching tokens, on the MinColumn column.
453
  //
454
  // Sequences start from the first matching token to align, and end at the
455
  // first token of the first line that doesn't need to be aligned.
456
  //
457
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
458
  // containing any matching token to be aligned and located after such token.
459
36
  auto AlignCurrentSequence = [&] {
460
36
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
461
36
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
36
                         Matches, Changes);
463
36
    MinColumn = 0;
464
36
    MaxColumn = UINT_MAX;
465
36
    StartOfSequence = 0;
466
36
    EndOfSequence = 0;
467
36
  };
468
469
36
  unsigned i = StartAt;
470
538
  for (unsigned e = Changes.size(); i != e; 
++i502
) {
471
502
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
472
0
      break;
473
474
502
    if (Changes[i].NewlinesBefore != 0) {
475
43
      CommasBeforeMatch = 0;
476
43
      EndOfSequence = i;
477
478
      // Whether to break the alignment sequence because of an empty line.
479
43
      bool EmptyLineBreak =
480
43
          (Changes[i].NewlinesBefore > 1) &&
481
43
          
(ACS != FormatStyle::ACS_AcrossEmptyLines)5
&&
482
43
          
(ACS != FormatStyle::ACS_AcrossEmptyLinesAndComments)5
;
483
484
      // Whether to break the alignment sequence because of a line without a
485
      // match.
486
43
      bool NoMatchBreak =
487
43
          !FoundMatchOnLine &&
488
43
          
!(4
LineIsComment4
&&
489
4
            ((ACS == FormatStyle::ACS_AcrossComments) ||
490
4
             (ACS == FormatStyle::ACS_AcrossEmptyLinesAndComments)));
491
492
43
      if (EmptyLineBreak || NoMatchBreak)
493
0
        AlignCurrentSequence();
494
495
      // A new line starts, re-initialize line status tracking bools.
496
      // Keep the match state if a string literal is continued on this line.
497
43
      if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
498
43
          
!Changes[i - 1].Tok->is(tok::string_literal)0
)
499
43
        FoundMatchOnLine = false;
500
43
      LineIsComment = true;
501
43
    }
502
503
502
    if (!Changes[i].Tok->is(tok::comment)) {
504
492
      LineIsComment = false;
505
492
    }
506
507
502
    if (Changes[i].Tok->is(tok::comma)) {
508
0
      ++CommasBeforeMatch;
509
502
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
510
      // Call AlignTokens recursively, skipping over this scope block.
511
3
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
512
3
      i = StoppedAt - 1;
513
3
      continue;
514
3
    }
515
516
499
    if (!Matches(Changes[i]))
517
424
      continue;
518
519
    // If there is more than one matching token per line, or if the number of
520
    // preceding commas, do not match anymore, end the sequence.
521
75
    if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch)
522
0
      AlignCurrentSequence();
523
524
75
    CommasBeforeLastMatch = CommasBeforeMatch;
525
75
    FoundMatchOnLine = true;
526
527
75
    if (StartOfSequence == 0)
528
36
      StartOfSequence = i;
529
530
75
    unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
531
75
    int LineLengthAfter = Changes[i].TokenLength;
532
321
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 0285
;
++j246
) {
533
246
      LineLengthAfter += Changes[j].Spaces;
534
      // Changes are generally 1:1 with the tokens, but a change could also be
535
      // inside of a token, in which case it's counted more than once: once for
536
      // the whitespace surrounding the token (!IsInsideToken) and once for
537
      // each whitespace change within it (IsInsideToken).
538
      // Therefore, changes inside of a token should only count the space.
539
246
      if (!Changes[j].IsInsideToken)
540
246
        LineLengthAfter += Changes[j].TokenLength;
541
246
    }
542
75
    unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
543
544
    // If we are restricted by the maximum column width, end the sequence.
545
75
    if (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn ||
546
75
        CommasBeforeLastMatch != CommasBeforeMatch) {
547
0
      AlignCurrentSequence();
548
0
      StartOfSequence = i;
549
0
    }
550
551
75
    MinColumn = std::max(MinColumn, ChangeMinColumn);
552
75
    MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
553
75
  }
554
555
36
  EndOfSequence = i;
556
36
  AlignCurrentSequence();
557
36
  return i;
558
36
}
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignConsecutiveBitFields()::$_2&>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignConsecutiveBitFields()::$_2&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)
Line
Count
Source
426
3
    const FormatStyle::AlignConsecutiveStyle &ACS = FormatStyle::ACS_None) {
427
3
  unsigned MinColumn = 0;
428
3
  unsigned MaxColumn = UINT_MAX;
429
430
  // Line number of the start and the end of the current token sequence.
431
3
  unsigned StartOfSequence = 0;
432
3
  unsigned EndOfSequence = 0;
433
434
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
435
  // abort when we hit any token in a higher scope than the starting one.
436
3
  auto IndentAndNestingLevel = StartAt < Changes.size()
437
3
                                   ? Changes[StartAt].indentAndNestingLevel()
438
3
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
439
440
  // Keep track of the number of commas before the matching tokens, we will only
441
  // align a sequence of matching tokens if they are preceded by the same number
442
  // of commas.
443
3
  unsigned CommasBeforeLastMatch = 0;
444
3
  unsigned CommasBeforeMatch = 0;
445
446
  // Whether a matching token has been found on the current line.
447
3
  bool FoundMatchOnLine = false;
448
449
  // Whether the current line consists purely of comments.
450
3
  bool LineIsComment = true;
451
452
  // Aligns a sequence of matching tokens, on the MinColumn column.
453
  //
454
  // Sequences start from the first matching token to align, and end at the
455
  // first token of the first line that doesn't need to be aligned.
456
  //
457
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
458
  // containing any matching token to be aligned and located after such token.
459
3
  auto AlignCurrentSequence = [&] {
460
3
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
461
3
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
3
                         Matches, Changes);
463
3
    MinColumn = 0;
464
3
    MaxColumn = UINT_MAX;
465
3
    StartOfSequence = 0;
466
3
    EndOfSequence = 0;
467
3
  };
468
469
3
  unsigned i = StartAt;
470
9
  for (unsigned e = Changes.size(); i != e; 
++i6
) {
471
9
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
472
3
      break;
473
474
6
    if (Changes[i].NewlinesBefore != 0) {
475
0
      CommasBeforeMatch = 0;
476
0
      EndOfSequence = i;
477
478
      // Whether to break the alignment sequence because of an empty line.
479
0
      bool EmptyLineBreak =
480
0
          (Changes[i].NewlinesBefore > 1) &&
481
0
          (ACS != FormatStyle::ACS_AcrossEmptyLines) &&
482
0
          (ACS != FormatStyle::ACS_AcrossEmptyLinesAndComments);
483
484
      // Whether to break the alignment sequence because of a line without a
485
      // match.
486
0
      bool NoMatchBreak =
487
0
          !FoundMatchOnLine &&
488
0
          !(LineIsComment &&
489
0
            ((ACS == FormatStyle::ACS_AcrossComments) ||
490
0
             (ACS == FormatStyle::ACS_AcrossEmptyLinesAndComments)));
491
492
0
      if (EmptyLineBreak || NoMatchBreak)
493
0
        AlignCurrentSequence();
494
495
      // A new line starts, re-initialize line status tracking bools.
496
      // Keep the match state if a string literal is continued on this line.
497
0
      if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
498
0
          !Changes[i - 1].Tok->is(tok::string_literal))
499
0
        FoundMatchOnLine = false;
500
0
      LineIsComment = true;
501
0
    }
502
503
6
    if (!Changes[i].Tok->is(tok::comment)) {
504
6
      LineIsComment = false;
505
6
    }
506
507
6
    if (Changes[i].Tok->is(tok::comma)) {
508
0
      ++CommasBeforeMatch;
509
6
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
510
      // Call AlignTokens recursively, skipping over this scope block.
511
0
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
512
0
      i = StoppedAt - 1;
513
0
      continue;
514
0
    }
515
516
6
    if (!Matches(Changes[i]))
517
6
      continue;
518
519
    // If there is more than one matching token per line, or if the number of
520
    // preceding commas, do not match anymore, end the sequence.
521
0
    if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch)
522
0
      AlignCurrentSequence();
523
524
0
    CommasBeforeLastMatch = CommasBeforeMatch;
525
0
    FoundMatchOnLine = true;
526
527
0
    if (StartOfSequence == 0)
528
0
      StartOfSequence = i;
529
530
0
    unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
531
0
    int LineLengthAfter = Changes[i].TokenLength;
532
0
    for (unsigned j = i + 1; j != e && Changes[j].NewlinesBefore == 0; ++j) {
533
0
      LineLengthAfter += Changes[j].Spaces;
534
      // Changes are generally 1:1 with the tokens, but a change could also be
535
      // inside of a token, in which case it's counted more than once: once for
536
      // the whitespace surrounding the token (!IsInsideToken) and once for
537
      // each whitespace change within it (IsInsideToken).
538
      // Therefore, changes inside of a token should only count the space.
539
0
      if (!Changes[j].IsInsideToken)
540
0
        LineLengthAfter += Changes[j].TokenLength;
541
0
    }
542
0
    unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
543
544
    // If we are restricted by the maximum column width, end the sequence.
545
0
    if (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn ||
546
0
        CommasBeforeLastMatch != CommasBeforeMatch) {
547
0
      AlignCurrentSequence();
548
0
      StartOfSequence = i;
549
0
    }
550
551
0
    MinColumn = std::max(MinColumn, ChangeMinColumn);
552
0
    MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
553
0
  }
554
555
3
  EndOfSequence = i;
556
3
  AlignCurrentSequence();
557
3
  return i;
558
3
}
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignConsecutiveDeclarations()::$_3>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignConsecutiveDeclarations()::$_3&&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)
Line
Count
Source
426
453
    const FormatStyle::AlignConsecutiveStyle &ACS = FormatStyle::ACS_None) {
427
453
  unsigned MinColumn = 0;
428
453
  unsigned MaxColumn = UINT_MAX;
429
430
  // Line number of the start and the end of the current token sequence.
431
453
  unsigned StartOfSequence = 0;
432
453
  unsigned EndOfSequence = 0;
433
434
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
435
  // abort when we hit any token in a higher scope than the starting one.
436
453
  auto IndentAndNestingLevel = StartAt < Changes.size()
437
453
                                   ? Changes[StartAt].indentAndNestingLevel()
438
453
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
439
440
  // Keep track of the number of commas before the matching tokens, we will only
441
  // align a sequence of matching tokens if they are preceded by the same number
442
  // of commas.
443
453
  unsigned CommasBeforeLastMatch = 0;
444
453
  unsigned CommasBeforeMatch = 0;
445
446
  // Whether a matching token has been found on the current line.
447
453
  bool FoundMatchOnLine = false;
448
449
  // Whether the current line consists purely of comments.
450
453
  bool LineIsComment = true;
451
452
  // Aligns a sequence of matching tokens, on the MinColumn column.
453
  //
454
  // Sequences start from the first matching token to align, and end at the
455
  // first token of the first line that doesn't need to be aligned.
456
  //
457
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
458
  // containing any matching token to be aligned and located after such token.
459
453
  auto AlignCurrentSequence = [&] {
460
453
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
461
453
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
453
                         Matches, Changes);
463
453
    MinColumn = 0;
464
453
    MaxColumn = UINT_MAX;
465
453
    StartOfSequence = 0;
466
453
    EndOfSequence = 0;
467
453
  };
468
469
453
  unsigned i = StartAt;
470
6.34k
  for (unsigned e = Changes.size(); i != e; 
++i5.89k
) {
471
5.89k
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
472
0
      break;
473
474
5.89k
    if (Changes[i].NewlinesBefore != 0) {
475
937
      CommasBeforeMatch = 0;
476
937
      EndOfSequence = i;
477
478
      // Whether to break the alignment sequence because of an empty line.
479
937
      bool EmptyLineBreak =
480
937
          (Changes[i].NewlinesBefore > 1) &&
481
937
          
(ACS != FormatStyle::ACS_AcrossEmptyLines)17
&&
482
937
          
(ACS != FormatStyle::ACS_AcrossEmptyLinesAndComments)17
;
483
484
      // Whether to break the alignment sequence because of a line without a
485
      // match.
486
937
      bool NoMatchBreak =
487
937
          !FoundMatchOnLine &&
488
937
          
!(429
LineIsComment429
&&
489
429
            
(30
(ACS == FormatStyle::ACS_AcrossComments)30
||
490
30
             (ACS == FormatStyle::ACS_AcrossEmptyLinesAndComments)));
491
492
937
      if (EmptyLineBreak || 
NoMatchBreak924
)
493
428
        AlignCurrentSequence();
494
495
      // A new line starts, re-initialize line status tracking bools.
496
      // Keep the match state if a string literal is continued on this line.
497
937
      if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
498
937
          
!Changes[i - 1].Tok->is(tok::string_literal)18
)
499
937
        FoundMatchOnLine = false;
500
937
      LineIsComment = true;
501
937
    }
502
503
5.89k
    if (!Changes[i].Tok->is(tok::comment)) {
504
5.82k
      LineIsComment = false;
505
5.82k
    }
506
507
5.89k
    if (Changes[i].Tok->is(tok::comma)) {
508
18
      ++CommasBeforeMatch;
509
5.87k
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
510
      // Call AlignTokens recursively, skipping over this scope block.
511
633
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
512
633
      i = StoppedAt - 1;
513
633
      continue;
514
633
    }
515
516
5.26k
    if (!Matches(Changes[i]))
517
4.56k
      continue;
518
519
    // If there is more than one matching token per line, or if the number of
520
    // preceding commas, do not match anymore, end the sequence.
521
694
    if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch)
522
0
      AlignCurrentSequence();
523
524
694
    CommasBeforeLastMatch = CommasBeforeMatch;
525
694
    FoundMatchOnLine = true;
526
527
694
    if (StartOfSequence == 0)
528
367
      StartOfSequence = i;
529
530
694
    unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
531
694
    int LineLengthAfter = Changes[i].TokenLength;
532
3.53k
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 03.35k
;
++j2.84k
) {
533
2.84k
      LineLengthAfter += Changes[j].Spaces;
534
      // Changes are generally 1:1 with the tokens, but a change could also be
535
      // inside of a token, in which case it's counted more than once: once for
536
      // the whitespace surrounding the token (!IsInsideToken) and once for
537
      // each whitespace change within it (IsInsideToken).
538
      // Therefore, changes inside of a token should only count the space.
539
2.84k
      if (!Changes[j].IsInsideToken)
540
2.84k
        LineLengthAfter += Changes[j].TokenLength;
541
2.84k
    }
542
694
    unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
543
544
    // If we are restricted by the maximum column width, end the sequence.
545
694
    if (ChangeMinColumn > MaxColumn || 
ChangeMaxColumn < MinColumn691
||
546
694
        
CommasBeforeLastMatch != CommasBeforeMatch688
) {
547
6
      AlignCurrentSequence();
548
6
      StartOfSequence = i;
549
6
    }
550
551
694
    MinColumn = std::max(MinColumn, ChangeMinColumn);
552
694
    MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
553
694
  }
554
555
453
  EndOfSequence = i;
556
453
  AlignCurrentSequence();
557
453
  return i;
558
453
}
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignConsecutiveDeclarations()::$_3&>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignConsecutiveDeclarations()::$_3&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)
Line
Count
Source
426
1.19k
    const FormatStyle::AlignConsecutiveStyle &ACS = FormatStyle::ACS_None) {
427
1.19k
  unsigned MinColumn = 0;
428
1.19k
  unsigned MaxColumn = UINT_MAX;
429
430
  // Line number of the start and the end of the current token sequence.
431
1.19k
  unsigned StartOfSequence = 0;
432
1.19k
  unsigned EndOfSequence = 0;
433
434
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
435
  // abort when we hit any token in a higher scope than the starting one.
436
1.19k
  auto IndentAndNestingLevel = StartAt < Changes.size()
437
1.19k
                                   ? Changes[StartAt].indentAndNestingLevel()
438
1.19k
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
439
440
  // Keep track of the number of commas before the matching tokens, we will only
441
  // align a sequence of matching tokens if they are preceded by the same number
442
  // of commas.
443
1.19k
  unsigned CommasBeforeLastMatch = 0;
444
1.19k
  unsigned CommasBeforeMatch = 0;
445
446
  // Whether a matching token has been found on the current line.
447
1.19k
  bool FoundMatchOnLine = false;
448
449
  // Whether the current line consists purely of comments.
450
1.19k
  bool LineIsComment = true;
451
452
  // Aligns a sequence of matching tokens, on the MinColumn column.
453
  //
454
  // Sequences start from the first matching token to align, and end at the
455
  // first token of the first line that doesn't need to be aligned.
456
  //
457
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
458
  // containing any matching token to be aligned and located after such token.
459
1.19k
  auto AlignCurrentSequence = [&] {
460
1.19k
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
461
1.19k
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
1.19k
                         Matches, Changes);
463
1.19k
    MinColumn = 0;
464
1.19k
    MaxColumn = UINT_MAX;
465
1.19k
    StartOfSequence = 0;
466
1.19k
    EndOfSequence = 0;
467
1.19k
  };
468
469
1.19k
  unsigned i = StartAt;
470
7.83k
  for (unsigned e = Changes.size(); i != e; 
++i6.63k
) {
471
7.83k
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
472
1.19k
      break;
473
474
6.63k
    if (Changes[i].NewlinesBefore != 0) {
475
826
      CommasBeforeMatch = 0;
476
826
      EndOfSequence = i;
477
478
      // Whether to break the alignment sequence because of an empty line.
479
826
      bool EmptyLineBreak =
480
826
          (Changes[i].NewlinesBefore > 1) &&
481
826
          
(ACS != FormatStyle::ACS_AcrossEmptyLines)6
&&
482
826
          
(ACS != FormatStyle::ACS_AcrossEmptyLinesAndComments)6
;
483
484
      // Whether to break the alignment sequence because of a line without a
485
      // match.
486
826
      bool NoMatchBreak =
487
826
          !FoundMatchOnLine &&
488
826
          
!(569
LineIsComment569
&&
489
569
            
(279
(ACS == FormatStyle::ACS_AcrossComments)279
||
490
279
             
(ACS == FormatStyle::ACS_AcrossEmptyLinesAndComments)272
));
491
492
826
      if (EmptyLineBreak || 
NoMatchBreak820
)
493
568
        AlignCurrentSequence();
494
495
      // A new line starts, re-initialize line status tracking bools.
496
      // Keep the match state if a string literal is continued on this line.
497
826
      if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
498
826
          
!Changes[i - 1].Tok->is(tok::string_literal)78
)
499
779
        FoundMatchOnLine = false;
500
826
      LineIsComment = true;
501
826
    }
502
503
6.63k
    if (!Changes[i].Tok->is(tok::comment)) {
504
6.54k
      LineIsComment = false;
505
6.54k
    }
506
507
6.63k
    if (Changes[i].Tok->is(tok::comma)) {
508
804
      ++CommasBeforeMatch;
509
5.83k
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
510
      // Call AlignTokens recursively, skipping over this scope block.
511
562
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
512
562
      i = StoppedAt - 1;
513
562
      continue;
514
562
    }
515
516
6.07k
    if (!Matches(Changes[i]))
517
5.59k
      continue;
518
519
    // If there is more than one matching token per line, or if the number of
520
    // preceding commas, do not match anymore, end the sequence.
521
477
    if (FoundMatchOnLine || 
CommasBeforeMatch != CommasBeforeLastMatch393
)
522
87
      AlignCurrentSequence();
523
524
477
    CommasBeforeLastMatch = CommasBeforeMatch;
525
477
    FoundMatchOnLine = true;
526
527
477
    if (StartOfSequence == 0)
528
300
      StartOfSequence = i;
529
530
477
    unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
531
477
    int LineLengthAfter = Changes[i].TokenLength;
532
2.76k
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 02.63k
;
++j2.28k
) {
533
2.28k
      LineLengthAfter += Changes[j].Spaces;
534
      // Changes are generally 1:1 with the tokens, but a change could also be
535
      // inside of a token, in which case it's counted more than once: once for
536
      // the whitespace surrounding the token (!IsInsideToken) and once for
537
      // each whitespace change within it (IsInsideToken).
538
      // Therefore, changes inside of a token should only count the space.
539
2.28k
      if (!Changes[j].IsInsideToken)
540
2.28k
        LineLengthAfter += Changes[j].TokenLength;
541
2.28k
    }
542
477
    unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
543
544
    // If we are restricted by the maximum column width, end the sequence.
545
477
    if (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn ||
546
477
        CommasBeforeLastMatch != CommasBeforeMatch) {
547
0
      AlignCurrentSequence();
548
0
      StartOfSequence = i;
549
0
    }
550
551
477
    MinColumn = std::max(MinColumn, ChangeMinColumn);
552
477
    MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
553
477
  }
554
555
1.19k
  EndOfSequence = i;
556
1.19k
  AlignCurrentSequence();
557
1.19k
  return i;
558
1.19k
}
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignChainedConditionals()::$_4>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignChainedConditionals()::$_4&&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)
Line
Count
Source
426
16.9k
    const FormatStyle::AlignConsecutiveStyle &ACS = FormatStyle::ACS_None) {
427
16.9k
  unsigned MinColumn = 0;
428
16.9k
  unsigned MaxColumn = UINT_MAX;
429
430
  // Line number of the start and the end of the current token sequence.
431
16.9k
  unsigned StartOfSequence = 0;
432
16.9k
  unsigned EndOfSequence = 0;
433
434
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
435
  // abort when we hit any token in a higher scope than the starting one.
436
16.9k
  auto IndentAndNestingLevel = StartAt < Changes.size()
437
16.9k
                                   ? Changes[StartAt].indentAndNestingLevel()
438
16.9k
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
439
440
  // Keep track of the number of commas before the matching tokens, we will only
441
  // align a sequence of matching tokens if they are preceded by the same number
442
  // of commas.
443
16.9k
  unsigned CommasBeforeLastMatch = 0;
444
16.9k
  unsigned CommasBeforeMatch = 0;
445
446
  // Whether a matching token has been found on the current line.
447
16.9k
  bool FoundMatchOnLine = false;
448
449
  // Whether the current line consists purely of comments.
450
16.9k
  bool LineIsComment = true;
451
452
  // Aligns a sequence of matching tokens, on the MinColumn column.
453
  //
454
  // Sequences start from the first matching token to align, and end at the
455
  // first token of the first line that doesn't need to be aligned.
456
  //
457
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
458
  // containing any matching token to be aligned and located after such token.
459
16.9k
  auto AlignCurrentSequence = [&] {
460
16.9k
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
461
16.9k
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
16.9k
                         Matches, Changes);
463
16.9k
    MinColumn = 0;
464
16.9k
    MaxColumn = UINT_MAX;
465
16.9k
    StartOfSequence = 0;
466
16.9k
    EndOfSequence = 0;
467
16.9k
  };
468
469
16.9k
  unsigned i = StartAt;
470
184k
  for (unsigned e = Changes.size(); i != e; 
++i167k
) {
471
167k
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
472
24
      break;
473
474
167k
    if (Changes[i].NewlinesBefore != 0) {
475
26.7k
      CommasBeforeMatch = 0;
476
26.7k
      EndOfSequence = i;
477
478
      // Whether to break the alignment sequence because of an empty line.
479
26.7k
      bool EmptyLineBreak =
480
26.7k
          (Changes[i].NewlinesBefore > 1) &&
481
26.7k
          
(ACS != FormatStyle::ACS_AcrossEmptyLines)722
&&
482
26.7k
          
(ACS != FormatStyle::ACS_AcrossEmptyLinesAndComments)722
;
483
484
      // Whether to break the alignment sequence because of a line without a
485
      // match.
486
26.7k
      bool NoMatchBreak =
487
26.7k
          !FoundMatchOnLine &&
488
26.7k
          
!(26.7k
LineIsComment26.7k
&&
489
26.7k
            
(2.24k
(ACS == FormatStyle::ACS_AcrossComments)2.24k
||
490
2.24k
             (ACS == FormatStyle::ACS_AcrossEmptyLinesAndComments)));
491
492
26.7k
      if (EmptyLineBreak || 
NoMatchBreak26.0k
)
493
26.7k
        AlignCurrentSequence();
494
495
      // A new line starts, re-initialize line status tracking bools.
496
      // Keep the match state if a string literal is continued on this line.
497
26.7k
      if (i == 0 || 
!Changes[i].Tok->is(tok::string_literal)26.2k
||
498
26.7k
          
!Changes[i - 1].Tok->is(tok::string_literal)228
)
499
26.6k
        FoundMatchOnLine = false;
500
26.7k
      LineIsComment = true;
501
26.7k
    }
502
503
167k
    if (!Changes[i].Tok->is(tok::comment)) {
504
163k
      LineIsComment = false;
505
163k
    }
506
507
167k
    if (Changes[i].Tok->is(tok::comma)) {
508
844
      ++CommasBeforeMatch;
509
166k
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
510
      // Call AlignTokens recursively, skipping over this scope block.
511
26.6k
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
512
26.6k
      i = StoppedAt - 1;
513
26.6k
      continue;
514
26.6k
    }
515
516
140k
    if (!Matches(Changes[i]))
517
140k
      continue;
518
519
    // If there is more than one matching token per line, or if the number of
520
    // preceding commas, do not match anymore, end the sequence.
521
24
    if (FoundMatchOnLine || 
CommasBeforeMatch != CommasBeforeLastMatch17
)
522
7
      AlignCurrentSequence();
523
524
24
    CommasBeforeLastMatch = CommasBeforeMatch;
525
24
    FoundMatchOnLine = true;
526
527
24
    if (StartOfSequence == 0)
528
24
      StartOfSequence = i;
529
530
24
    unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
531
24
    int LineLengthAfter = Changes[i].TokenLength;
532
158
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 0137
;
++j134
) {
533
134
      LineLengthAfter += Changes[j].Spaces;
534
      // Changes are generally 1:1 with the tokens, but a change could also be
535
      // inside of a token, in which case it's counted more than once: once for
536
      // the whitespace surrounding the token (!IsInsideToken) and once for
537
      // each whitespace change within it (IsInsideToken).
538
      // Therefore, changes inside of a token should only count the space.
539
134
      if (!Changes[j].IsInsideToken)
540
134
        LineLengthAfter += Changes[j].TokenLength;
541
134
    }
542
24
    unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
543
544
    // If we are restricted by the maximum column width, end the sequence.
545
24
    if (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn ||
546
24
        CommasBeforeLastMatch != CommasBeforeMatch) {
547
0
      AlignCurrentSequence();
548
0
      StartOfSequence = i;
549
0
    }
550
551
24
    MinColumn = std::max(MinColumn, ChangeMinColumn);
552
24
    MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
553
24
  }
554
555
16.9k
  EndOfSequence = i;
556
16.9k
  AlignCurrentSequence();
557
16.9k
  return i;
558
16.9k
}
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignChainedConditionals()::$_4&>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignChainedConditionals()::$_4&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)
Line
Count
Source
426
44.5k
    const FormatStyle::AlignConsecutiveStyle &ACS = FormatStyle::ACS_None) {
427
44.5k
  unsigned MinColumn = 0;
428
44.5k
  unsigned MaxColumn = UINT_MAX;
429
430
  // Line number of the start and the end of the current token sequence.
431
44.5k
  unsigned StartOfSequence = 0;
432
44.5k
  unsigned EndOfSequence = 0;
433
434
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
435
  // abort when we hit any token in a higher scope than the starting one.
436
44.5k
  auto IndentAndNestingLevel = StartAt < Changes.size()
437
44.5k
                                   ? Changes[StartAt].indentAndNestingLevel()
438
44.5k
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
439
440
  // Keep track of the number of commas before the matching tokens, we will only
441
  // align a sequence of matching tokens if they are preceded by the same number
442
  // of commas.
443
44.5k
  unsigned CommasBeforeLastMatch = 0;
444
44.5k
  unsigned CommasBeforeMatch = 0;
445
446
  // Whether a matching token has been found on the current line.
447
44.5k
  bool FoundMatchOnLine = false;
448
449
  // Whether the current line consists purely of comments.
450
44.5k
  bool LineIsComment = true;
451
452
  // Aligns a sequence of matching tokens, on the MinColumn column.
453
  //
454
  // Sequences start from the first matching token to align, and end at the
455
  // first token of the first line that doesn't need to be aligned.
456
  //
457
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
458
  // containing any matching token to be aligned and located after such token.
459
44.5k
  auto AlignCurrentSequence = [&] {
460
44.5k
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
461
44.5k
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
44.5k
                         Matches, Changes);
463
44.5k
    MinColumn = 0;
464
44.5k
    MaxColumn = UINT_MAX;
465
44.5k
    StartOfSequence = 0;
466
44.5k
    EndOfSequence = 0;
467
44.5k
  };
468
469
44.5k
  unsigned i = StartAt;
470
212k
  for (unsigned e = Changes.size(); i != e; 
++i167k
) {
471
212k
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
472
44.5k
      break;
473
474
167k
    if (Changes[i].NewlinesBefore != 0) {
475
23.4k
      CommasBeforeMatch = 0;
476
23.4k
      EndOfSequence = i;
477
478
      // Whether to break the alignment sequence because of an empty line.
479
23.4k
      bool EmptyLineBreak =
480
23.4k
          (Changes[i].NewlinesBefore > 1) &&
481
23.4k
          
(ACS != FormatStyle::ACS_AcrossEmptyLines)263
&&
482
23.4k
          
(ACS != FormatStyle::ACS_AcrossEmptyLinesAndComments)263
;
483
484
      // Whether to break the alignment sequence because of a line without a
485
      // match.
486
23.4k
      bool NoMatchBreak =
487
23.4k
          !FoundMatchOnLine &&
488
23.4k
          
!(23.2k
LineIsComment23.2k
&&
489
23.2k
            
(10.2k
(ACS == FormatStyle::ACS_AcrossComments)10.2k
||
490
10.2k
             (ACS == FormatStyle::ACS_AcrossEmptyLinesAndComments)));
491
492
23.4k
      if (EmptyLineBreak || 
NoMatchBreak23.1k
)
493
23.2k
        AlignCurrentSequence();
494
495
      // A new line starts, re-initialize line status tracking bools.
496
      // Keep the match state if a string literal is continued on this line.
497
23.4k
      if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
498
23.4k
          
!Changes[i - 1].Tok->is(tok::string_literal)579
)
499
23.2k
        FoundMatchOnLine = false;
500
23.4k
      LineIsComment = true;
501
23.4k
    }
502
503
167k
    if (!Changes[i].Tok->is(tok::comment)) {
504
166k
      LineIsComment = false;
505
166k
    }
506
507
167k
    if (Changes[i].Tok->is(tok::comma)) {
508
8.29k
      ++CommasBeforeMatch;
509
159k
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
510
      // Call AlignTokens recursively, skipping over this scope block.
511
17.8k
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
512
17.8k
      i = StoppedAt - 1;
513
17.8k
      continue;
514
17.8k
    }
515
516
150k
    if (!Matches(Changes[i]))
517
149k
      continue;
518
519
    // If there is more than one matching token per line, or if the number of
520
    // preceding commas, do not match anymore, end the sequence.
521
713
    if (FoundMatchOnLine || 
CommasBeforeMatch != CommasBeforeLastMatch579
)
522
138
      AlignCurrentSequence();
523
524
713
    CommasBeforeLastMatch = CommasBeforeMatch;
525
713
    FoundMatchOnLine = true;
526
527
713
    if (StartOfSequence == 0)
528
485
      StartOfSequence = i;
529
530
713
    unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
531
713
    int LineLengthAfter = Changes[i].TokenLength;
532
3.33k
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 03.01k
;
++j2.61k
) {
533
2.61k
      LineLengthAfter += Changes[j].Spaces;
534
      // Changes are generally 1:1 with the tokens, but a change could also be
535
      // inside of a token, in which case it's counted more than once: once for
536
      // the whitespace surrounding the token (!IsInsideToken) and once for
537
      // each whitespace change within it (IsInsideToken).
538
      // Therefore, changes inside of a token should only count the space.
539
2.61k
      if (!Changes[j].IsInsideToken)
540
2.61k
        LineLengthAfter += Changes[j].TokenLength;
541
2.61k
    }
542
713
    unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
543
544
    // If we are restricted by the maximum column width, end the sequence.
545
713
    if (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn ||
546
713
        CommasBeforeLastMatch != CommasBeforeMatch) {
547
0
      AlignCurrentSequence();
548
0
      StartOfSequence = i;
549
0
    }
550
551
713
    MinColumn = std::max(MinColumn, ChangeMinColumn);
552
713
    MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
553
713
  }
554
555
44.5k
  EndOfSequence = i;
556
44.5k
  AlignCurrentSequence();
557
44.5k
  return i;
558
44.5k
}
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignChainedConditionals()::$_6>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignChainedConditionals()::$_6&&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)
Line
Count
Source
426
1.54k
    const FormatStyle::AlignConsecutiveStyle &ACS = FormatStyle::ACS_None) {
427
1.54k
  unsigned MinColumn = 0;
428
1.54k
  unsigned MaxColumn = UINT_MAX;
429
430
  // Line number of the start and the end of the current token sequence.
431
1.54k
  unsigned StartOfSequence = 0;
432
1.54k
  unsigned EndOfSequence = 0;
433
434
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
435
  // abort when we hit any token in a higher scope than the starting one.
436
1.54k
  auto IndentAndNestingLevel = StartAt < Changes.size()
437
1.54k
                                   ? Changes[StartAt].indentAndNestingLevel()
438
1.54k
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
439
440
  // Keep track of the number of commas before the matching tokens, we will only
441
  // align a sequence of matching tokens if they are preceded by the same number
442
  // of commas.
443
1.54k
  unsigned CommasBeforeLastMatch = 0;
444
1.54k
  unsigned CommasBeforeMatch = 0;
445
446
  // Whether a matching token has been found on the current line.
447
1.54k
  bool FoundMatchOnLine = false;
448
449
  // Whether the current line consists purely of comments.
450
1.54k
  bool LineIsComment = true;
451
452
  // Aligns a sequence of matching tokens, on the MinColumn column.
453
  //
454
  // Sequences start from the first matching token to align, and end at the
455
  // first token of the first line that doesn't need to be aligned.
456
  //
457
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
458
  // containing any matching token to be aligned and located after such token.
459
1.54k
  auto AlignCurrentSequence = [&] {
460
1.54k
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
461
1.54k
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
1.54k
                         Matches, Changes);
463
1.54k
    MinColumn = 0;
464
1.54k
    MaxColumn = UINT_MAX;
465
1.54k
    StartOfSequence = 0;
466
1.54k
    EndOfSequence = 0;
467
1.54k
  };
468
469
1.54k
  unsigned i = StartAt;
470
13.1k
  for (unsigned e = Changes.size(); i != e; 
++i11.6k
) {
471
11.6k
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
472
11
      break;
473
474
11.6k
    if (Changes[i].NewlinesBefore != 0) {
475
1.51k
      CommasBeforeMatch = 0;
476
1.51k
      EndOfSequence = i;
477
478
      // Whether to break the alignment sequence because of an empty line.
479
1.51k
      bool EmptyLineBreak =
480
1.51k
          (Changes[i].NewlinesBefore > 1) &&
481
1.51k
          
(ACS != FormatStyle::ACS_AcrossEmptyLines)31
&&
482
1.51k
          
(ACS != FormatStyle::ACS_AcrossEmptyLinesAndComments)31
;
483
484
      // Whether to break the alignment sequence because of a line without a
485
      // match.
486
1.51k
      bool NoMatchBreak =
487
1.51k
          !FoundMatchOnLine &&
488
1.51k
          
!(1.51k
LineIsComment1.51k
&&
489
1.51k
            
(176
(ACS == FormatStyle::ACS_AcrossComments)176
||
490
176
             (ACS == FormatStyle::ACS_AcrossEmptyLinesAndComments)));
491
492
1.51k
      if (EmptyLineBreak || 
NoMatchBreak1.48k
)
493
1.51k
        AlignCurrentSequence();
494
495
      // A new line starts, re-initialize line status tracking bools.
496
      // Keep the match state if a string literal is continued on this line.
497
1.51k
      if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
498
1.51k
          
!Changes[i - 1].Tok->is(tok::string_literal)38
)
499
1.51k
        FoundMatchOnLine = false;
500
1.51k
      LineIsComment = true;
501
1.51k
    }
502
503
11.6k
    if (!Changes[i].Tok->is(tok::comment)) {
504
11.3k
      LineIsComment = false;
505
11.3k
    }
506
507
11.6k
    if (Changes[i].Tok->is(tok::comma)) {
508
8
      ++CommasBeforeMatch;
509
11.5k
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
510
      // Call AlignTokens recursively, skipping over this scope block.
511
1.72k
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
512
1.72k
      i = StoppedAt - 1;
513
1.72k
      continue;
514
1.72k
    }
515
516
9.88k
    if (!Matches(Changes[i]))
517
9.87k
      continue;
518
519
    // If there is more than one matching token per line, or if the number of
520
    // preceding commas, do not match anymore, end the sequence.
521
11
    if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch)
522
0
      AlignCurrentSequence();
523
524
11
    CommasBeforeLastMatch = CommasBeforeMatch;
525
11
    FoundMatchOnLine = true;
526
527
11
    if (StartOfSequence == 0)
528
11
      StartOfSequence = i;
529
530
11
    unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
531
11
    int LineLengthAfter = Changes[i].TokenLength;
532
36
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 028
;
++j25
) {
533
25
      LineLengthAfter += Changes[j].Spaces;
534
      // Changes are generally 1:1 with the tokens, but a change could also be
535
      // inside of a token, in which case it's counted more than once: once for
536
      // the whitespace surrounding the token (!IsInsideToken) and once for
537
      // each whitespace change within it (IsInsideToken).
538
      // Therefore, changes inside of a token should only count the space.
539
25
      if (!Changes[j].IsInsideToken)
540
25
        LineLengthAfter += Changes[j].TokenLength;
541
25
    }
542
11
    unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
543
544
    // If we are restricted by the maximum column width, end the sequence.
545
11
    if (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn ||
546
11
        CommasBeforeLastMatch != CommasBeforeMatch) {
547
0
      AlignCurrentSequence();
548
0
      StartOfSequence = i;
549
0
    }
550
551
11
    MinColumn = std::max(MinColumn, ChangeMinColumn);
552
11
    MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
553
11
  }
554
555
1.54k
  EndOfSequence = i;
556
1.54k
  AlignCurrentSequence();
557
1.54k
  return i;
558
1.54k
}
WhitespaceManager.cpp:unsigned int clang::format::AlignTokens<clang::format::WhitespaceManager::alignChainedConditionals()::$_6&>(clang::format::FormatStyle const&, clang::format::WhitespaceManager::alignChainedConditionals()::$_6&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&, unsigned int, clang::format::FormatStyle::AlignConsecutiveStyle const&)
Line
Count
Source
426
2.99k
    const FormatStyle::AlignConsecutiveStyle &ACS = FormatStyle::ACS_None) {
427
2.99k
  unsigned MinColumn = 0;
428
2.99k
  unsigned MaxColumn = UINT_MAX;
429
430
  // Line number of the start and the end of the current token sequence.
431
2.99k
  unsigned StartOfSequence = 0;
432
2.99k
  unsigned EndOfSequence = 0;
433
434
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
435
  // abort when we hit any token in a higher scope than the starting one.
436
2.99k
  auto IndentAndNestingLevel = StartAt < Changes.size()
437
2.99k
                                   ? Changes[StartAt].indentAndNestingLevel()
438
2.99k
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
439
440
  // Keep track of the number of commas before the matching tokens, we will only
441
  // align a sequence of matching tokens if they are preceded by the same number
442
  // of commas.
443
2.99k
  unsigned CommasBeforeLastMatch = 0;
444
2.99k
  unsigned CommasBeforeMatch = 0;
445
446
  // Whether a matching token has been found on the current line.
447
2.99k
  bool FoundMatchOnLine = false;
448
449
  // Whether the current line consists purely of comments.
450
2.99k
  bool LineIsComment = true;
451
452
  // Aligns a sequence of matching tokens, on the MinColumn column.
453
  //
454
  // Sequences start from the first matching token to align, and end at the
455
  // first token of the first line that doesn't need to be aligned.
456
  //
457
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
458
  // containing any matching token to be aligned and located after such token.
459
2.99k
  auto AlignCurrentSequence = [&] {
460
2.99k
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
461
2.99k
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
462
2.99k
                         Matches, Changes);
463
2.99k
    MinColumn = 0;
464
2.99k
    MaxColumn = UINT_MAX;
465
2.99k
    StartOfSequence = 0;
466
2.99k
    EndOfSequence = 0;
467
2.99k
  };
468
469
2.99k
  unsigned i = StartAt;
470
13.7k
  for (unsigned e = Changes.size(); i != e; 
++i10.8k
) {
471
13.7k
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
472
2.98k
      break;
473
474
10.8k
    if (Changes[i].NewlinesBefore != 0) {
475
2.07k
      CommasBeforeMatch = 0;
476
2.07k
      EndOfSequence = i;
477
478
      // Whether to break the alignment sequence because of an empty line.
479
2.07k
      bool EmptyLineBreak =
480
2.07k
          (Changes[i].NewlinesBefore > 1) &&
481
2.07k
          
(ACS != FormatStyle::ACS_AcrossEmptyLines)3
&&
482
2.07k
          
(ACS != FormatStyle::ACS_AcrossEmptyLinesAndComments)3
;
483
484
      // Whether to break the alignment sequence because of a line without a
485
      // match.
486
2.07k
      bool NoMatchBreak =
487
2.07k
          !FoundMatchOnLine &&
488
2.07k
          
!(1.86k
LineIsComment1.86k
&&
489
1.86k
            
(1.02k
(ACS == FormatStyle::ACS_AcrossComments)1.02k
||
490
1.02k
             (ACS == FormatStyle::ACS_AcrossEmptyLinesAndComments)));
491
492
2.07k
      if (EmptyLineBreak || 
NoMatchBreak2.07k
)
493
1.86k
        AlignCurrentSequence();
494
495
      // A new line starts, re-initialize line status tracking bools.
496
      // Keep the match state if a string literal is continued on this line.
497
2.07k
      if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
498
2.07k
          
!Changes[i - 1].Tok->is(tok::string_literal)28
)
499
2.07k
        FoundMatchOnLine = false;
500
2.07k
      LineIsComment = true;
501
2.07k
    }
502
503
10.8k
    if (!Changes[i].Tok->is(tok::comment)) {
504
10.6k
      LineIsComment = false;
505
10.6k
    }
506
507
10.8k
    if (Changes[i].Tok->is(tok::comma)) {
508
613
      ++CommasBeforeMatch;
509
10.1k
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
510
      // Call AlignTokens recursively, skipping over this scope block.
511
1.26k
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
512
1.26k
      i = StoppedAt - 1;
513
1.26k
      continue;
514
1.26k
    }
515
516
9.53k
    if (!Matches(Changes[i]))
517
9.14k
      continue;
518
519
    // If there is more than one matching token per line, or if the number of
520
    // preceding commas, do not match anymore, end the sequence.
521
383
    if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch)
522
0
      AlignCurrentSequence();
523
524
383
    CommasBeforeLastMatch = CommasBeforeMatch;
525
383
    FoundMatchOnLine = true;
526
527
383
    if (StartOfSequence == 0)
528
183
      StartOfSequence = i;
529
530
383
    unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
531
383
    int LineLengthAfter = Changes[i].TokenLength;
532
1.44k
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 01.33k
;
++j1.06k
) {
533
1.06k
      LineLengthAfter += Changes[j].Spaces;
534
      // Changes are generally 1:1 with the tokens, but a change could also be
535
      // inside of a token, in which case it's counted more than once: once for
536
      // the whitespace surrounding the token (!IsInsideToken) and once for
537
      // each whitespace change within it (IsInsideToken).
538
      // Therefore, changes inside of a token should only count the space.
539
1.06k
      if (!Changes[j].IsInsideToken)
540
1.06k
        LineLengthAfter += Changes[j].TokenLength;
541
1.06k
    }
542
383
    unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
543
544
    // If we are restricted by the maximum column width, end the sequence.
545
383
    if (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn ||
546
383
        
CommasBeforeLastMatch != CommasBeforeMatch380
) {
547
3
      AlignCurrentSequence();
548
3
      StartOfSequence = i;
549
3
    }
550
551
383
    MinColumn = std::max(MinColumn, ChangeMinColumn);
552
383
    MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
553
383
  }
554
555
2.99k
  EndOfSequence = i;
556
2.99k
  AlignCurrentSequence();
557
2.99k
  return i;
558
2.99k
}
559
560
// Aligns a sequence of matching tokens, on the MinColumn column.
561
//
562
// Sequences start from the first matching token to align, and end at the
563
// first token of the first line that doesn't need to be aligned.
564
//
565
// We need to adjust the StartOfTokenColumn of each Change that is on a line
566
// containing any matching token to be aligned and located after such token.
567
static void AlignMacroSequence(
568
    unsigned &StartOfSequence, unsigned &EndOfSequence, unsigned &MinColumn,
569
    unsigned &MaxColumn, bool &FoundMatchOnLine,
570
    std::function<bool(const WhitespaceManager::Change &C)> AlignMacrosMatches,
571
1.66k
    SmallVector<WhitespaceManager::Change, 16> &Changes) {
572
1.66k
  if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence30
) {
573
574
30
    FoundMatchOnLine = false;
575
30
    int Shift = 0;
576
577
636
    for (unsigned I = StartOfSequence; I != EndOfSequence; 
++I606
) {
578
606
      if (Changes[I].NewlinesBefore > 0) {
579
75
        Shift = 0;
580
75
        FoundMatchOnLine = false;
581
75
      }
582
583
      // If this is the first matching token to be aligned, remember by how many
584
      // spaces it has to be shifted, so the rest of the changes on the line are
585
      // shifted by the same amount
586
606
      if (!FoundMatchOnLine && 
AlignMacrosMatches(Changes[I])402
) {
587
90
        FoundMatchOnLine = true;
588
90
        Shift = MinColumn - Changes[I].StartOfTokenColumn;
589
90
        Changes[I].Spaces += Shift;
590
90
      }
591
592
606
      assert(Shift >= 0);
593
0
      Changes[I].StartOfTokenColumn += Shift;
594
606
      if (I + 1 != Changes.size())
595
581
        Changes[I + 1].PreviousEndOfTokenColumn += Shift;
596
606
    }
597
30
  }
598
599
1.66k
  MinColumn = 0;
600
1.66k
  MaxColumn = UINT_MAX;
601
1.66k
  StartOfSequence = 0;
602
1.66k
  EndOfSequence = 0;
603
1.66k
}
604
605
18.4k
void WhitespaceManager::alignConsecutiveMacros() {
606
18.4k
  if (Style.AlignConsecutiveMacros == FormatStyle::ACS_None)
607
18.0k
    return;
608
609
9.60k
  
auto AlignMacrosMatches = [](const Change &C) 385
{
610
9.60k
    const FormatToken *Current = C.Tok;
611
9.60k
    unsigned SpacesRequiredBefore = 1;
612
613
9.60k
    if (Current->SpacesRequiredBefore == 0 || 
!Current->Previous6.75k
)
614
4.79k
      return false;
615
616
4.81k
    Current = Current->Previous;
617
618
    // If token is a ")", skip over the parameter list, to the
619
    // token that precedes the "("
620
4.81k
    if (Current->is(tok::r_paren) && 
Current->MatchingParen150
) {
621
150
      Current = Current->MatchingParen->Previous;
622
150
      SpacesRequiredBefore = 0;
623
150
    }
624
625
4.81k
    if (!Current || !Current->is(tok::identifier))
626
3.15k
      return false;
627
628
1.65k
    if (!Current->Previous || 
!Current->Previous->is(tok::pp_define)1.48k
)
629
1.47k
      return false;
630
631
    // For a macro function, 0 spaces are required between the
632
    // identifier and the lparen that opens the parameter list.
633
    // For a simple macro, 1 space is required between the
634
    // identifier and the first token of the defined value.
635
180
    return Current->Next->SpacesRequiredBefore == SpacesRequiredBefore;
636
1.65k
  };
637
638
385
  unsigned MinColumn = 0;
639
385
  unsigned MaxColumn = UINT_MAX;
640
641
  // Start and end of the token sequence we're processing.
642
385
  unsigned StartOfSequence = 0;
643
385
  unsigned EndOfSequence = 0;
644
645
  // Whether a matching token has been found on the current line.
646
385
  bool FoundMatchOnLine = false;
647
648
  // Whether the current line consists only of comments
649
385
  bool LineIsComment = true;
650
651
385
  unsigned I = 0;
652
9.59k
  for (unsigned E = Changes.size(); I != E; 
++I9.20k
) {
653
9.20k
    if (Changes[I].NewlinesBefore != 0) {
654
1.35k
      EndOfSequence = I;
655
656
      // Whether to break the alignment sequence because of an empty line.
657
1.35k
      bool EmptyLineBreak =
658
1.35k
          (Changes[I].NewlinesBefore > 1) &&
659
1.35k
          
(Style.AlignConsecutiveMacros != FormatStyle::ACS_AcrossEmptyLines)40
&&
660
1.35k
          (Style.AlignConsecutiveMacros !=
661
38
           FormatStyle::ACS_AcrossEmptyLinesAndComments);
662
663
      // Whether to break the alignment sequence because of a line without a
664
      // match.
665
1.35k
      bool NoMatchBreak =
666
1.35k
          !FoundMatchOnLine &&
667
1.35k
          
!(1.29k
LineIsComment1.29k
&&
(39
(Style.AlignConsecutiveMacros ==
668
39
                               FormatStyle::ACS_AcrossComments) ||
669
39
                              (Style.AlignConsecutiveMacros ==
670
33
                               FormatStyle::ACS_AcrossEmptyLinesAndComments)));
671
672
1.35k
      if (EmptyLineBreak || 
NoMatchBreak1.32k
)
673
1.28k
        AlignMacroSequence(StartOfSequence, EndOfSequence, MinColumn, MaxColumn,
674
1.28k
                           FoundMatchOnLine, AlignMacrosMatches, Changes);
675
676
      // A new line starts, re-initialize line status tracking bools.
677
1.35k
      FoundMatchOnLine = false;
678
1.35k
      LineIsComment = true;
679
1.35k
    }
680
681
9.20k
    if (!Changes[I].Tok->is(tok::comment)) {
682
9.10k
      LineIsComment = false;
683
9.10k
    }
684
685
9.20k
    if (!AlignMacrosMatches(Changes[I]))
686
9.11k
      continue;
687
688
90
    FoundMatchOnLine = true;
689
690
90
    if (StartOfSequence == 0)
691
30
      StartOfSequence = I;
692
693
90
    unsigned ChangeMinColumn = Changes[I].StartOfTokenColumn;
694
90
    int LineLengthAfter = -Changes[I].Spaces;
695
384
    for (unsigned j = I; j != E && 
Changes[j].NewlinesBefore == 0359
;
++j294
)
696
294
      LineLengthAfter += Changes[j].Spaces + Changes[j].TokenLength;
697
90
    unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
698
699
90
    MinColumn = std::max(MinColumn, ChangeMinColumn);
700
90
    MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
701
90
  }
702
703
385
  EndOfSequence = I;
704
385
  AlignMacroSequence(StartOfSequence, EndOfSequence, MinColumn, MaxColumn,
705
385
                     FoundMatchOnLine, AlignMacrosMatches, Changes);
706
385
}
707
708
18.4k
void WhitespaceManager::alignConsecutiveAssignments() {
709
18.4k
  if (Style.AlignConsecutiveAssignments == FormatStyle::ACS_None)
710
18.0k
    return;
711
712
435
  AlignTokens(
713
435
      Style,
714
13.7k
      [&](const Change &C) {
715
        // Do not align on equal signs that are first on a line.
716
13.7k
        if (C.NewlinesBefore > 0)
717
2.21k
          return false;
718
719
        // Do not align on equal signs that are last on a line.
720
11.5k
        if (&C != &Changes.back() && 
(&C + 1)->NewlinesBefore > 011.1k
)
721
1.61k
          return false;
722
723
9.91k
        return C.Tok->is(tok::equal);
724
11.5k
      },
725
435
      Changes, /*StartAt=*/0, Style.AlignConsecutiveAssignments);
726
435
}
727
728
18.4k
void WhitespaceManager::alignConsecutiveBitFields() {
729
18.4k
  if (Style.AlignConsecutiveBitFields == FormatStyle::ACS_None)
730
18.4k
    return;
731
732
36
  AlignTokens(
733
36
      Style,
734
662
      [&](Change const &C) {
735
        // Do not align on ':' that is first on a line.
736
662
        if (C.NewlinesBefore > 0)
737
86
          return false;
738
739
        // Do not align on ':' that is last on a line.
740
576
        if (&C != &Changes.back() && 
(&C + 1)->NewlinesBefore > 0540
)
741
39
          return false;
742
743
537
        return C.Tok->is(TT_BitFieldColon);
744
576
      },
745
36
      Changes, /*StartAt=*/0, Style.AlignConsecutiveBitFields);
746
36
}
747
748
18.4k
void WhitespaceManager::alignConsecutiveDeclarations() {
749
18.4k
  if (Style.AlignConsecutiveDeclarations == FormatStyle::ACS_None)
750
18.0k
    return;
751
752
453
  AlignTokens(
753
453
      Style,
754
13.6k
      [](Change const &C) {
755
        // tok::kw_operator is necessary for aligning operator overload
756
        // definitions.
757
13.6k
        if (C.Tok->isOneOf(TT_FunctionDeclarationName, tok::kw_operator))
758
316
          return true;
759
13.3k
        if (C.Tok->isNot(TT_StartOfName))
760
11.3k
          return false;
761
1.98k
        if (C.Tok->Previous &&
762
1.98k
            C.Tok->Previous->is(TT_StatementAttributeLikeMacro))
763
5
          return false;
764
        // Check if there is a subsequent name that starts the same declaration.
765
1.98k
        
for (FormatToken *Next = C.Tok->Next; 1.98k
Next;
Next = Next->Next2
) {
766
1.98k
          if (Next->is(tok::comment))
767
2
            continue;
768
1.98k
          if (Next->is(TT_PointerOrReference))
769
36
            return false;
770
1.94k
          if (!Next->Tok.getIdentifierInfo())
771
1.94k
            break;
772
2
          if (Next->isOneOf(TT_StartOfName, TT_FunctionDeclarationName,
773
2
                            tok::kw_operator))
774
2
            return false;
775
2
        }
776
1.94k
        return true;
777
1.98k
      },
778
453
      Changes, /*StartAt=*/0, Style.AlignConsecutiveDeclarations);
779
453
}
780
781
18.4k
void WhitespaceManager::alignChainedConditionals() {
782
18.4k
  if (Style.BreakBeforeTernaryOperators) {
783
16.9k
    AlignTokens(
784
16.9k
        Style,
785
291k
        [](Change const &C) {
786
          // Align question operators and last colon
787
291k
          return C.Tok->is(TT_ConditionalExpr) &&
788
291k
                 
(1.60k
(1.60k
C.Tok->is(tok::question)1.60k
&&
!C.NewlinesBefore714
) ||
789
1.60k
                  
(970
C.Tok->is(tok::colon)970
&&
C.Tok->Next888
&&
790
970
                   
(888
C.Tok->Next->FakeLParens.size() == 0888
||
791
888
                    
C.Tok->Next->FakeLParens.back() != prec::Conditional254
)));
792
291k
        },
793
16.9k
        Changes, /*StartAt=*/0);
794
16.9k
  } else {
795
38.8k
    static auto AlignWrappedOperand = [](Change const &C) {
796
38.8k
      FormatToken *Previous = C.Tok->getPreviousNonComment();
797
38.8k
      return C.NewlinesBefore && 
Previous5.49k
&&
Previous->is(TT_ConditionalExpr)2.93k
&&
798
38.8k
             
(865
Previous->is(tok::colon)865
&&
799
865
              
(753
C.Tok->FakeLParens.size() == 0753
||
800
753
               
C.Tok->FakeLParens.back() != prec::Conditional279
));
801
38.8k
    };
802
    // Ensure we keep alignment of wrapped operands with non-wrapped operands
803
    // Since we actually align the operators, the wrapped operands need the
804
    // extra offset to be properly aligned.
805
19.4k
    for (Change &C : Changes) {
806
19.4k
      if (AlignWrappedOperand(C))
807
167
        C.StartOfTokenColumn -= 2;
808
19.4k
    }
809
1.54k
    AlignTokens(
810
1.54k
        Style,
811
19.8k
        [this](Change const &C) {
812
          // Align question operators if next operand is not wrapped, as
813
          // well as wrapped operands after question operator or last
814
          // colon in conditional sequence
815
19.8k
          return (C.Tok->is(TT_ConditionalExpr) && 
C.Tok->is(tok::question)789
&&
816
19.8k
                  
&C != &Changes.back()508
&&
(&C + 1)->NewlinesBefore == 0508
&&
817
19.8k
                  
!(&C + 1)->IsTrailingComment466
) ||
818
19.8k
                 
AlignWrappedOperand(C)19.4k
;
819
19.8k
        },
820
1.54k
        Changes, /*StartAt=*/0);
821
1.54k
  }
822
18.4k
}
823
824
18.4k
void WhitespaceManager::alignTrailingComments() {
825
18.4k
  unsigned MinColumn = 0;
826
18.4k
  unsigned MaxColumn = UINT_MAX;
827
18.4k
  unsigned StartOfSequence = 0;
828
18.4k
  bool BreakBeforeNext = false;
829
18.4k
  unsigned Newlines = 0;
830
328k
  for (unsigned i = 0, e = Changes.size(); i != e; 
++i310k
) {
831
310k
    if (Changes[i].StartOfBlockComment)
832
558
      continue;
833
309k
    Newlines += Changes[i].NewlinesBefore;
834
309k
    if (!Changes[i].IsTrailingComment)
835
305k
      continue;
836
837
4.27k
    unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
838
4.27k
    unsigned ChangeMaxColumn;
839
840
4.27k
    if (Style.ColumnLimit == 0)
841
286
      ChangeMaxColumn = UINT_MAX;
842
3.98k
    else if (Style.ColumnLimit >= Changes[i].TokenLength)
843
3.93k
      ChangeMaxColumn = Style.ColumnLimit - Changes[i].TokenLength;
844
59
    else
845
59
      ChangeMaxColumn = ChangeMinColumn;
846
847
    // If we don't create a replacement for this change, we have to consider
848
    // it to be immovable.
849
4.27k
    if (!Changes[i].CreateReplacement)
850
469
      ChangeMaxColumn = ChangeMinColumn;
851
852
4.27k
    if (i + 1 != e && 
Changes[i + 1].ContinuesPPDirective4.26k
)
853
68
      ChangeMaxColumn -= 2;
854
    // If this comment follows an } in column 0, it probably documents the
855
    // closing of a namespace and we don't want to align it.
856
4.27k
    bool FollowsRBraceInColumn0 = i > 0 && 
Changes[i].NewlinesBefore == 03.85k
&&
857
4.27k
                                  
Changes[i - 1].Tok->is(tok::r_brace)2.09k
&&
858
4.27k
                                  
Changes[i - 1].StartOfTokenColumn == 0910
;
859
4.27k
    bool WasAlignedWithStartOfNextLine = false;
860
4.27k
    if (Changes[i].NewlinesBefore == 1) { // A comment on its own line.
861
1.61k
      unsigned CommentColumn = SourceMgr.getSpellingColumnNumber(
862
1.61k
          Changes[i].OriginalWhitespaceRange.getEnd());
863
6.41k
      for (unsigned j = i + 1; j != e; 
++j4.80k
) {
864
6.41k
        if (Changes[j].Tok->is(tok::comment))
865
4.80k
          continue;
866
867
1.61k
        unsigned NextColumn = SourceMgr.getSpellingColumnNumber(
868
1.61k
            Changes[j].OriginalWhitespaceRange.getEnd());
869
        // The start of the next token was previously aligned with the
870
        // start of this comment.
871
1.61k
        WasAlignedWithStartOfNextLine =
872
1.61k
            CommentColumn == NextColumn ||
873
1.61k
            
CommentColumn == NextColumn + Style.IndentWidth741
;
874
1.61k
        break;
875
6.41k
      }
876
1.61k
    }
877
4.27k
    if (!Style.AlignTrailingComments || 
FollowsRBraceInColumn04.18k
) {
878
448
      alignTrailingComments(StartOfSequence, i, MinColumn);
879
448
      MinColumn = ChangeMinColumn;
880
448
      MaxColumn = ChangeMinColumn;
881
448
      StartOfSequence = i;
882
3.82k
    } else if (BreakBeforeNext || 
Newlines > 12.83k
||
883
3.82k
               
(1.97k
ChangeMinColumn > MaxColumn1.97k
||
ChangeMaxColumn < MinColumn1.96k
) ||
884
               // Break the comment sequence if the previous line did not end
885
               // in a trailing comment.
886
3.82k
               
(1.95k
Changes[i].NewlinesBefore == 11.95k
&&
i > 0490
&&
887
1.95k
                
!Changes[i - 1].IsTrailingComment477
) ||
888
3.82k
               
WasAlignedWithStartOfNextLine1.59k
) {
889
2.28k
      alignTrailingComments(StartOfSequence, i, MinColumn);
890
2.28k
      MinColumn = ChangeMinColumn;
891
2.28k
      MaxColumn = ChangeMaxColumn;
892
2.28k
      StartOfSequence = i;
893
2.28k
    } else {
894
1.53k
      MinColumn = std::max(MinColumn, ChangeMinColumn);
895
1.53k
      MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
896
1.53k
    }
897
4.27k
    BreakBeforeNext = (i == 0) || 
(Changes[i].NewlinesBefore > 1)3.85k
||
898
                      // Never start a sequence with a comment at the beginning
899
                      // of the line.
900
4.27k
                      
(3.69k
Changes[i].NewlinesBefore == 13.69k
&&
StartOfSequence == i1.59k
);
901
4.27k
    Newlines = 0;
902
4.27k
  }
903
18.4k
  alignTrailingComments(StartOfSequence, Changes.size(), MinColumn);
904
18.4k
}
905
906
void WhitespaceManager::alignTrailingComments(unsigned Start, unsigned End,
907
21.2k
                                              unsigned Column) {
908
331k
  for (unsigned i = Start; i != End; 
++i310k
) {
909
310k
    int Shift = 0;
910
310k
    if (Changes[i].IsTrailingComment) {
911
4.77k
      Shift = Column - Changes[i].StartOfTokenColumn;
912
4.77k
    }
913
310k
    if (Changes[i].StartOfBlockComment) {
914
558
      Shift = Changes[i].IndentationOffset +
915
558
              Changes[i].StartOfBlockComment->StartOfTokenColumn -
916
558
              Changes[i].StartOfTokenColumn;
917
558
    }
918
310k
    assert(Shift >= 0);
919
0
    Changes[i].Spaces += Shift;
920
310k
    if (i + 1 != Changes.size())
921
291k
      Changes[i + 1].PreviousEndOfTokenColumn += Shift;
922
310k
    Changes[i].StartOfTokenColumn += Shift;
923
310k
  }
924
21.2k
}
925
926
18.4k
void WhitespaceManager::alignEscapedNewlines() {
927
18.4k
  if (Style.AlignEscapedNewlines == FormatStyle::ENAS_DontAlign)
928
10
    return;
929
930
18.4k
  bool AlignLeft = Style.AlignEscapedNewlines == FormatStyle::ENAS_Left;
931
18.4k
  unsigned MaxEndOfLine = AlignLeft ? 
04.01k
:
Style.ColumnLimit14.4k
;
932
18.4k
  unsigned StartOfMacro = 0;
933
310k
  for (unsigned i = 1, e = Changes.size(); i < e; 
++i291k
) {
934
291k
    Change &C = Changes[i];
935
291k
    if (C.NewlinesBefore > 0) {
936
42.8k
      if (C.ContinuesPPDirective) {
937
637
        MaxEndOfLine = std::max(C.PreviousEndOfTokenColumn + 2, MaxEndOfLine);
938
42.1k
      } else {
939
42.1k
        alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);
940
42.1k
        MaxEndOfLine = AlignLeft ? 
08.72k
:
Style.ColumnLimit33.4k
;
941
42.1k
        StartOfMacro = i;
942
42.1k
      }
943
42.8k
    }
944
291k
  }
945
18.4k
  alignEscapedNewlines(StartOfMacro + 1, Changes.size(), MaxEndOfLine);
946
18.4k
}
947
948
void WhitespaceManager::alignEscapedNewlines(unsigned Start, unsigned End,
949
60.6k
                                             unsigned Column) {
950
310k
  for (unsigned i = Start; i < End; 
++i249k
) {
951
249k
    Change &C = Changes[i];
952
249k
    if (C.NewlinesBefore > 0) {
953
637
      assert(C.ContinuesPPDirective);
954
637
      if (C.PreviousEndOfTokenColumn + 1 > Column)
955
0
        C.EscapedNewlineColumn = 0;
956
637
      else
957
637
        C.EscapedNewlineColumn = Column;
958
637
    }
959
249k
  }
960
60.6k
}
961
962
18.4k
void WhitespaceManager::alignArrayInitializers() {
963
18.4k
  if (Style.AlignArrayOfStructures == FormatStyle::AIAS_None)
964
18.3k
    return;
965
966
103
  for (unsigned ChangeIndex = 1U, ChangeEnd = Changes.size();
967
868
       ChangeIndex < ChangeEnd; 
++ChangeIndex765
) {
968
765
    auto &C = Changes[ChangeIndex];
969
765
    if (C.Tok->IsArrayInitializer) {
970
109
      bool FoundComplete = false;
971
3.09k
      for (unsigned InsideIndex = ChangeIndex + 1; InsideIndex < ChangeEnd;
972
3.09k
           
++InsideIndex2.98k
) {
973
3.09k
        if (Changes[InsideIndex].Tok == C.Tok->MatchingParen) {
974
109
          alignArrayInitializers(ChangeIndex, InsideIndex + 1);
975
109
          ChangeIndex = InsideIndex + 1;
976
109
          FoundComplete = true;
977
109
          break;
978
109
        }
979
3.09k
      }
980
109
      if (!FoundComplete)
981
0
        ChangeIndex = ChangeEnd;
982
109
    }
983
765
  }
984
103
}
985
986
109
void WhitespaceManager::alignArrayInitializers(unsigned Start, unsigned End) {
987
988
109
  if (Style.AlignArrayOfStructures == FormatStyle::AIAS_Right)
989
61
    alignArrayInitializersRightJustified(getCells(Start, End));
990
48
  else if (Style.AlignArrayOfStructures == FormatStyle::AIAS_Left)
991
48
    alignArrayInitializersLeftJustified(getCells(Start, End));
992
109
}
993
994
void WhitespaceManager::alignArrayInitializersRightJustified(
995
61
    CellDescriptions &&CellDescs) {
996
61
  auto &Cells = CellDescs.Cells;
997
998
  // Now go through and fixup the spaces.
999
61
  auto *CellIter = Cells.begin();
1000
305
  for (auto i = 0U; i < CellDescs.CellCount; 
i++, ++CellIter244
) {
1001
244
    unsigned NetWidth = 0U;
1002
244
    if (isSplitCell(*CellIter))
1003
13
      NetWidth = getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1004
244
    auto CellWidth = getMaximumCellWidth(CellIter, NetWidth);
1005
1006
244
    if (Changes[CellIter->Index].Tok->is(tok::r_brace)) {
1007
      // So in here we want to see if there is a brace that falls
1008
      // on a line that was split. If so on that line we make sure that
1009
      // the spaces in front of the brace are enough.
1010
61
      Changes[CellIter->Index].NewlinesBefore = 0;
1011
61
      Changes[CellIter->Index].Spaces = 0;
1012
174
      for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
1013
113
           Next = Next->NextColumnElement) {
1014
113
        Changes[Next->Index].Spaces = 0;
1015
113
        Changes[Next->Index].NewlinesBefore = 0;
1016
113
      }
1017
      // Unless the array is empty, we need the position of all the
1018
      // immediately adjacent cells
1019
61
      if (CellIter != Cells.begin()) {
1020
61
        auto ThisNetWidth =
1021
61
            getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1022
61
        auto MaxNetWidth =
1023
61
            getMaximumNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces,
1024
61
                               CellDescs.CellCount);
1025
61
        if (ThisNetWidth < MaxNetWidth)
1026
1
          Changes[CellIter->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1027
61
        auto RowCount = 1U;
1028
61
        auto Offset = std::distance(Cells.begin(), CellIter);
1029
174
        for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
1030
113
             Next = Next->NextColumnElement) {
1031
113
          auto *Start = (Cells.begin() + RowCount * CellDescs.CellCount);
1032
113
          auto *End = Start + Offset;
1033
113
          ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1034
113
          if (ThisNetWidth < MaxNetWidth)
1035
1
            Changes[Next->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1036
113
          ++RowCount;
1037
113
        }
1038
61
      }
1039
183
    } else {
1040
183
      auto ThisWidth =
1041
183
          calculateCellWidth(CellIter->Index, CellIter->EndIndex, true) +
1042
183
          NetWidth;
1043
183
      if (Changes[CellIter->Index].NewlinesBefore == 0) {
1044
170
        Changes[CellIter->Index].Spaces = (CellWidth - (ThisWidth + NetWidth));
1045
170
        Changes[CellIter->Index].Spaces += (i > 0) ? 
1110
:
060
;
1046
170
      }
1047
183
      alignToStartOfCell(CellIter->Index, CellIter->EndIndex);
1048
540
      for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
1049
357
           Next = Next->NextColumnElement) {
1050
357
        ThisWidth =
1051
357
            calculateCellWidth(Next->Index, Next->EndIndex, true) + NetWidth;
1052
357
        if (Changes[Next->Index].NewlinesBefore == 0) {
1053
355
          Changes[Next->Index].Spaces = (CellWidth - ThisWidth);
1054
355
          Changes[Next->Index].Spaces += (i > 0) ? 
1242
:
0113
;
1055
355
        }
1056
357
        alignToStartOfCell(Next->Index, Next->EndIndex);
1057
357
      }
1058
183
    }
1059
244
  }
1060
61
}
1061
1062
void WhitespaceManager::alignArrayInitializersLeftJustified(
1063
48
    CellDescriptions &&CellDescs) {
1064
48
  auto &Cells = CellDescs.Cells;
1065
1066
  // Now go through and fixup the spaces.
1067
48
  auto *CellIter = Cells.begin();
1068
  // The first cell needs to be against the left brace.
1069
48
  if (Changes[CellIter->Index].NewlinesBefore == 0)
1070
47
    Changes[CellIter->Index].Spaces = 0;
1071
1
  else
1072
1
    Changes[CellIter->Index].Spaces = CellDescs.InitialSpaces;
1073
48
  ++CellIter;
1074
192
  for (auto i = 1U; i < CellDescs.CellCount; 
i++, ++CellIter144
) {
1075
144
    auto MaxNetWidth = getMaximumNetWidth(
1076
144
        Cells.begin(), CellIter, CellDescs.InitialSpaces, CellDescs.CellCount);
1077
144
    auto ThisNetWidth =
1078
144
        getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1079
144
    if (Changes[CellIter->Index].NewlinesBefore == 0) {
1080
136
      Changes[CellIter->Index].Spaces =
1081
136
          MaxNetWidth - ThisNetWidth +
1082
136
          (Changes[CellIter->Index].Tok->isNot(tok::r_brace) ? 
188
:
048
);
1083
136
    }
1084
144
    auto RowCount = 1U;
1085
144
    auto Offset = std::distance(Cells.begin(), CellIter);
1086
423
    for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
1087
279
         Next = Next->NextColumnElement) {
1088
279
      auto *Start = (Cells.begin() + RowCount * CellDescs.CellCount);
1089
279
      auto *End = Start + Offset;
1090
279
      auto ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1091
279
      if (Changes[Next->Index].NewlinesBefore == 0) {
1092
277
        Changes[Next->Index].Spaces =
1093
277
            MaxNetWidth - ThisNetWidth +
1094
277
            (Changes[Next->Index].Tok->isNot(tok::r_brace) ? 
1187
:
090
);
1095
277
      }
1096
279
      ++RowCount;
1097
279
    }
1098
144
  }
1099
48
}
1100
1101
244
bool WhitespaceManager::isSplitCell(const CellDescription &Cell) {
1102
244
  if (Cell.HasSplit)
1103
13
    return true;
1104
687
  
for (const auto *Next = Cell.NextColumnElement; 231
Next != nullptr;
1105
456
       Next = Next->NextColumnElement) {
1106
456
    if (Next->HasSplit)
1107
0
      return true;
1108
456
  }
1109
231
  return false;
1110
231
}
1111
1112
WhitespaceManager::CellDescriptions WhitespaceManager::getCells(unsigned Start,
1113
109
                                                                unsigned End) {
1114
1115
109
  unsigned Depth = 0;
1116
109
  unsigned Cell = 0;
1117
109
  unsigned CellCount = 0;
1118
109
  unsigned InitialSpaces = 0;
1119
109
  unsigned InitialTokenLength = 0;
1120
109
  unsigned EndSpaces = 0;
1121
109
  SmallVector<CellDescription> Cells;
1122
109
  const FormatToken *MatchingParen = nullptr;
1123
3.28k
  for (unsigned i = Start; i < End; 
++i3.17k
) {
1124
3.17k
    auto &C = Changes[i];
1125
3.17k
    if (C.Tok->is(tok::l_brace))
1126
481
      ++Depth;
1127
2.69k
    else if (C.Tok->is(tok::r_brace))
1128
481
      --Depth;
1129
3.17k
    if (Depth == 2) {
1130
2.05k
      if (C.Tok->is(tok::l_brace)) {
1131
312
        Cell = 0;
1132
312
        MatchingParen = C.Tok->MatchingParen;
1133
312
        if (InitialSpaces == 0) {
1134
109
          InitialSpaces = C.Spaces + C.TokenLength;
1135
109
          InitialTokenLength = C.TokenLength;
1136
109
          auto j = i - 1;
1137
109
          for (; Changes[j].NewlinesBefore == 0 && 
j > Start101
;
--j0
) {
1138
0
            InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1139
0
            InitialTokenLength += Changes[j].TokenLength;
1140
0
          }
1141
109
          if (C.NewlinesBefore == 0) {
1142
8
            InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1143
8
            InitialTokenLength += Changes[j].TokenLength;
1144
8
          }
1145
109
        }
1146
1.74k
      } else if (C.Tok->is(tok::comma)) {
1147
651
        if (!Cells.empty())
1148
651
          Cells.back().EndIndex = i;
1149
651
        Cell++;
1150
651
      }
1151
2.05k
    } else 
if (1.12k
Depth == 11.12k
) {
1152
754
      if (C.Tok == MatchingParen) {
1153
312
        if (!Cells.empty())
1154
312
          Cells.back().EndIndex = i;
1155
312
        Cells.push_back(CellDescription{i, ++Cell, i + 1, false, nullptr});
1156
312
        CellCount = Cell + 1;
1157
        // Go to the next non-comment and ensure there is a break in front
1158
312
        const auto *NextNonComment = C.Tok->getNextNonComment();
1159
537
        while (NextNonComment->is(tok::comma))
1160
225
          NextNonComment = NextNonComment->getNextNonComment();
1161
312
        auto j = i;
1162
933
        while (Changes[j].Tok != NextNonComment && 
j < End621
)
1163
621
          j++;
1164
312
        if (j < End && Changes[j].NewlinesBefore == 0 &&
1165
312
            
Changes[j].Tok->isNot(tok::r_brace)141
) {
1166
78
          Changes[j].NewlinesBefore = 1;
1167
          // Account for the added token lengths
1168
78
          Changes[j].Spaces = InitialSpaces - InitialTokenLength;
1169
78
        }
1170
442
      } else if (C.Tok->is(tok::comment)) {
1171
        // Trailing comments stay at a space past the last token
1172
54
        C.Spaces = Changes[i - 1].Tok->is(tok::comma) ? 
130
:
224
;
1173
388
      } else if (C.Tok->is(tok::l_brace)) {
1174
        // We need to make sure that the ending braces is aligned to the
1175
        // start of our initializer
1176
109
        auto j = i - 1;
1177
650
        for (; j > 0 && 
!Changes[j].Tok->ArrayInitializerLineStart547
;
--j541
)
1178
541
          ; // Nothing the loop does the work
1179
109
        EndSpaces = Changes[j].Spaces;
1180
109
      }
1181
754
    } else 
if (367
Depth == 0367
&&
C.Tok->is(tok::r_brace)109
) {
1182
109
      C.NewlinesBefore = 1;
1183
109
      C.Spaces = EndSpaces;
1184
109
    }
1185
3.17k
    if (C.Tok->StartsColumn) {
1186
      // This gets us past tokens that have been split over multiple
1187
      // lines
1188
963
      bool HasSplit = false;
1189
963
      if (Changes[i].NewlinesBefore > 0) {
1190
        // So if we split a line previously and the tail line + this token is
1191
        // less then the column limit we remove the split here and just put
1192
        // the column start at a space past the comma
1193
27
        auto j = i - 1;
1194
27
        if ((j - 1) > Start && Changes[j].Tok->is(tok::comma) &&
1195
27
            
Changes[j - 1].NewlinesBefore > 025
) {
1196
1
          --j;
1197
1
          auto LineLimit = Changes[j].Spaces + Changes[j].TokenLength;
1198
1
          if (LineLimit < Style.ColumnLimit) {
1199
1
            Changes[i].NewlinesBefore = 0;
1200
1
            Changes[i].Spaces = 1;
1201
1
          }
1202
1
        }
1203
27
      }
1204
1.01k
      while (Changes[i].NewlinesBefore > 0 && 
Changes[i].Tok == C.Tok61
) {
1205
55
        Changes[i].Spaces = InitialSpaces;
1206
55
        ++i;
1207
55
        HasSplit = true;
1208
55
      }
1209
963
      if (Changes[i].Tok != C.Tok)
1210
26
        --i;
1211
963
      Cells.push_back(CellDescription{i, Cell, i, HasSplit, nullptr});
1212
963
    }
1213
3.17k
  }
1214
1215
109
  return linkCells({Cells, CellCount, InitialSpaces});
1216
109
}
1217
1218
unsigned WhitespaceManager::calculateCellWidth(unsigned Start, unsigned End,
1219
4.08k
                                               bool WithSpaces) const {
1220
4.08k
  unsigned CellWidth = 0;
1221
9.82k
  for (auto i = Start; i < End; 
i++5.73k
) {
1222
5.73k
    if (Changes[i].NewlinesBefore > 0)
1223
105
      CellWidth = 0;
1224
5.73k
    CellWidth += Changes[i].TokenLength;
1225
5.73k
    CellWidth += (WithSpaces ? Changes[i].Spaces : 
00
);
1226
5.73k
  }
1227
4.08k
  return CellWidth;
1228
4.08k
}
1229
1230
540
void WhitespaceManager::alignToStartOfCell(unsigned Start, unsigned End) {
1231
540
  if ((End - Start) <= 1)
1232
446
    return;
1233
  // If the line is broken anywhere in there make sure everything
1234
  // is aligned to the parent
1235
317
  
for (auto i = Start + 1; 94
i < End;
i++223
) {
1236
223
    if (Changes[i].NewlinesBefore > 0)
1237
3
      Changes[i].Spaces = Changes[Start].Spaces;
1238
223
  }
1239
94
}
1240
1241
WhitespaceManager::CellDescriptions
1242
109
WhitespaceManager::linkCells(CellDescriptions &&CellDesc) {
1243
109
  auto &Cells = CellDesc.Cells;
1244
1.38k
  for (auto *CellIter = Cells.begin(); CellIter != Cells.end(); 
++CellIter1.27k
) {
1245
1.27k
    if (CellIter->NextColumnElement == nullptr &&
1246
1.27k
        ((CellIter + 1) != Cells.end())) {
1247
4.48k
      for (auto *NextIter = CellIter + 1; NextIter != Cells.end(); 
++NextIter3.31k
) {
1248
4.15k
        if (NextIter->Cell == CellIter->Cell) {
1249
839
          CellIter->NextColumnElement = &(*NextIter);
1250
839
          break;
1251
839
        }
1252
4.15k
      }
1253
1.16k
    }
1254
1.27k
  }
1255
109
  return std::move(CellDesc);
1256
109
}
1257
1258
18.4k
void WhitespaceManager::generateChanges() {
1259
328k
  for (unsigned i = 0, e = Changes.size(); i != e; 
++i310k
) {
1260
310k
    const Change &C = Changes[i];
1261
310k
    if (i > 0) {
1262
291k
      assert(Changes[i - 1].OriginalWhitespaceRange.getBegin() !=
1263
291k
                 C.OriginalWhitespaceRange.getBegin() &&
1264
291k
             "Generating two replacements for the same location");
1265
291k
    }
1266
310k
    if (C.CreateReplacement) {
1267
286k
      std::string ReplacementText = C.PreviousLinePostfix;
1268
286k
      if (C.ContinuesPPDirective)
1269
618
        appendEscapedNewlineText(ReplacementText, C.NewlinesBefore,
1270
618
                                 C.PreviousEndOfTokenColumn,
1271
618
                                 C.EscapedNewlineColumn);
1272
285k
      else
1273
285k
        appendNewlineText(ReplacementText, C.NewlinesBefore);
1274
286k
      appendIndentText(
1275
286k
          ReplacementText, C.Tok->IndentLevel, std::max(0, C.Spaces),
1276
286k
          C.StartOfTokenColumn - std::max(0, C.Spaces), C.IsAligned);
1277
286k
      ReplacementText.append(C.CurrentLinePrefix);
1278
286k
      storeReplacement(C.OriginalWhitespaceRange, ReplacementText);
1279
286k
    }
1280
310k
  }
1281
18.4k
}
1282
1283
286k
void WhitespaceManager::storeReplacement(SourceRange Range, StringRef Text) {
1284
286k
  unsigned WhitespaceLength = SourceMgr.getFileOffset(Range.getEnd()) -
1285
286k
                              SourceMgr.getFileOffset(Range.getBegin());
1286
  // Don't create a replacement, if it does not change anything.
1287
286k
  if (StringRef(SourceMgr.getCharacterData(Range.getBegin()),
1288
286k
                WhitespaceLength) == Text)
1289
260k
    return;
1290
25.4k
  auto Err = Replaces.add(tooling::Replacement(
1291
25.4k
      SourceMgr, CharSourceRange::getCharRange(Range), Text));
1292
  // FIXME: better error handling. For now, just print an error message in the
1293
  // release version.
1294
25.4k
  if (Err) {
1295
0
    llvm::errs() << llvm::toString(std::move(Err)) << "\n";
1296
0
    assert(false);
1297
0
  }
1298
25.4k
}
1299
1300
void WhitespaceManager::appendNewlineText(std::string &Text,
1301
285k
                                          unsigned Newlines) {
1302
324k
  for (unsigned i = 0; i < Newlines; 
++i39.0k
)
1303
39.0k
    Text.append(UseCRLF ? 
"\r\n"67
:
"\n"38.9k
);
1304
285k
}
1305
1306
void WhitespaceManager::appendEscapedNewlineText(
1307
    std::string &Text, unsigned Newlines, unsigned PreviousEndOfTokenColumn,
1308
618
    unsigned EscapedNewlineColumn) {
1309
618
  if (Newlines > 0) {
1310
615
    unsigned Spaces =
1311
615
        std::max<int>(1, EscapedNewlineColumn - PreviousEndOfTokenColumn - 1);
1312
1.23k
    for (unsigned i = 0; i < Newlines; 
++i620
) {
1313
620
      Text.append(Spaces, ' ');
1314
620
      Text.append(UseCRLF ? 
"\\\r\n"7
:
"\\\n"613
);
1315
620
      Spaces = std::max<int>(0, EscapedNewlineColumn - 1);
1316
620
    }
1317
615
  }
1318
618
}
1319
1320
void WhitespaceManager::appendIndentText(std::string &Text,
1321
                                         unsigned IndentLevel, unsigned Spaces,
1322
                                         unsigned WhitespaceStartColumn,
1323
286k
                                         bool IsAligned) {
1324
286k
  switch (Style.UseTab) {
1325
283k
  case FormatStyle::UT_Never:
1326
283k
    Text.append(Spaces, ' ');
1327
283k
    break;
1328
481
  case FormatStyle::UT_Always: {
1329
481
    if (Style.TabWidth) {
1330
463
      unsigned FirstTabWidth =
1331
463
          Style.TabWidth - WhitespaceStartColumn % Style.TabWidth;
1332
1333
      // Insert only spaces when we want to end up before the next tab.
1334
463
      if (Spaces < FirstTabWidth || 
Spaces == 1116
) {
1335
368
        Text.append(Spaces, ' ');
1336
368
        break;
1337
368
      }
1338
      // Align to the next tab.
1339
95
      Spaces -= FirstTabWidth;
1340
95
      Text.append("\t");
1341
1342
95
      Text.append(Spaces / Style.TabWidth, '\t');
1343
95
      Text.append(Spaces % Style.TabWidth, ' ');
1344
95
    } else 
if (18
Spaces == 118
) {
1345
2
      Text.append(Spaces, ' ');
1346
2
    }
1347
113
    break;
1348
481
  }
1349
304
  case FormatStyle::UT_ForIndentation:
1350
304
    if (WhitespaceStartColumn == 0) {
1351
144
      unsigned Indentation = IndentLevel * Style.IndentWidth;
1352
144
      Spaces = appendTabIndent(Text, Spaces, Indentation);
1353
144
    }
1354
304
    Text.append(Spaces, ' ');
1355
304
    break;
1356
738
  case FormatStyle::UT_ForContinuationAndIndentation:
1357
738
    if (WhitespaceStartColumn == 0)
1358
319
      Spaces = appendTabIndent(Text, Spaces, Spaces);
1359
738
    Text.append(Spaces, ' ');
1360
738
    break;
1361
840
  case FormatStyle::UT_AlignWithSpaces:
1362
840
    if (WhitespaceStartColumn == 0) {
1363
358
      unsigned Indentation =
1364
358
          IsAligned ? 
IndentLevel * Style.IndentWidth57
:
Spaces301
;
1365
358
      Spaces = appendTabIndent(Text, Spaces, Indentation);
1366
358
    }
1367
840
    Text.append(Spaces, ' ');
1368
840
    break;
1369
286k
  }
1370
286k
}
1371
1372
unsigned WhitespaceManager::appendTabIndent(std::string &Text, unsigned Spaces,
1373
821
                                            unsigned Indentation) {
1374
  // This happens, e.g. when a line in a block comment is indented less than the
1375
  // first one.
1376
821
  if (Indentation > Spaces)
1377
4
    Indentation = Spaces;
1378
821
  if (Style.TabWidth) {
1379
797
    unsigned Tabs = Indentation / Style.TabWidth;
1380
797
    Text.append(Tabs, '\t');
1381
797
    Spaces -= Tabs * Style.TabWidth;
1382
797
  }
1383
821
  return Spaces;
1384
821
}
1385
1386
} // namespace format
1387
} // namespace clang