Coverage Report

Created: 2022-05-17 06:19

/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
730k
    const Change &C1, const Change &C2) const {
24
730k
  return SourceMgr.isBeforeInTranslationUnit(
25
730k
      C1.OriginalWhitespaceRange.getBegin(),
26
730k
      C2.OriginalWhitespaceRange.getBegin());
27
730k
}
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
372k
      StartOfBlockComment(nullptr), IndentationOffset(0), ConditionalsLevel(0) {
46
372k
}
47
48
void WhitespaceManager::replaceWhitespace(FormatToken &Tok, unsigned Newlines,
49
                                          unsigned Spaces,
50
                                          unsigned StartOfTokenColumn,
51
350k
                                          bool IsAligned, bool InPPDirective) {
52
350k
  if (Tok.Finalized)
53
4.34k
    return;
54
346k
  Tok.setDecision((Newlines > 0) ? 
FD_Break44.2k
:
FD_Continue302k
);
55
346k
  Changes.push_back(Change(Tok, /*CreateReplacement=*/true, Tok.WhitespaceRange,
56
346k
                           Spaces, StartOfTokenColumn, Newlines, "", "",
57
346k
                           IsAligned, InPPDirective && 
!Tok.IsFirst1.98k
,
58
346k
                           /*IsInsideToken=*/false));
59
346k
}
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
22.2k
bool WhitespaceManager::inputUsesCRLF(StringRef Text, bool DefaultToCRLF) {
78
22.2k
  size_t LF = Text.count('\n');
79
22.2k
  size_t CR = Text.count('\r') * 2;
80
22.2k
  return LF == CR ? 
DefaultToCRLF14.3k
:
CR > LF7.96k
;
81
22.2k
}
82
83
void WhitespaceManager::replaceWhitespaceInToken(
84
    const FormatToken &Tok, unsigned Offset, unsigned ReplaceChars,
85
    StringRef PreviousPostfix, StringRef CurrentPrefix, bool InPPDirective,
86
1.74k
    unsigned Newlines, int Spaces) {
87
1.74k
  if (Tok.Finalized)
88
4
    return;
89
1.74k
  SourceLocation Start = Tok.getStartOfNonWhitespace().getLocWithOffset(Offset);
90
1.74k
  Changes.push_back(
91
1.74k
      Change(Tok, /*CreateReplacement=*/true,
92
1.74k
             SourceRange(Start, Start.getLocWithOffset(ReplaceChars)), Spaces,
93
1.74k
             std::max(0, Spaces), Newlines, PreviousPostfix, CurrentPrefix,
94
1.74k
             /*IsAligned=*/true, InPPDirective && 
!Tok.IsFirst21
,
95
1.74k
             /*IsInsideToken=*/true));
96
1.74k
}
97
98
22.2k
const tooling::Replacements &WhitespaceManager::generateReplacements() {
99
22.2k
  if (Changes.empty())
100
72
    return Replaces;
101
102
22.2k
  llvm::sort(Changes, Change::IsBeforeInFile(SourceMgr));
103
22.2k
  calculateLineBreakInformation();
104
22.2k
  alignConsecutiveMacros();
105
22.2k
  alignConsecutiveDeclarations();
106
22.2k
  alignConsecutiveBitFields();
107
22.2k
  alignConsecutiveAssignments();
108
22.2k
  alignChainedConditionals();
109
22.2k
  alignTrailingComments();
110
22.2k
  alignEscapedNewlines();
111
22.2k
  alignArrayInitializers();
112
22.2k
  generateChanges();
113
114
22.2k
  return Replaces;
115
22.2k
}
116
117
22.2k
void WhitespaceManager::calculateLineBreakInformation() {
118
22.2k
  Changes[0].PreviousEndOfTokenColumn = 0;
119
22.2k
  Change *LastOutsideTokenChange = &Changes[0];
120
372k
  for (unsigned i = 1, e = Changes.size(); i != e; 
++i350k
) {
121
350k
    SourceLocation OriginalWhitespaceStart =
122
350k
        Changes[i].OriginalWhitespaceRange.getBegin();
123
350k
    SourceLocation PreviousOriginalWhitespaceEnd =
124
350k
        Changes[i - 1].OriginalWhitespaceRange.getEnd();
125
350k
    unsigned OriginalWhitespaceStartOffset =
126
350k
        SourceMgr.getFileOffset(OriginalWhitespaceStart);
127
350k
    unsigned PreviousOriginalWhitespaceEndOffset =
128
350k
        SourceMgr.getFileOffset(PreviousOriginalWhitespaceEnd);
129
350k
    assert(PreviousOriginalWhitespaceEndOffset <=
130
350k
           OriginalWhitespaceStartOffset);
131
0
    const char *const PreviousOriginalWhitespaceEndData =
132
350k
        SourceMgr.getCharacterData(PreviousOriginalWhitespaceEnd);
133
350k
    StringRef Text(PreviousOriginalWhitespaceEndData,
134
350k
                   SourceMgr.getCharacterData(OriginalWhitespaceStart) -
135
350k
                       PreviousOriginalWhitespaceEndData);
136
    // Usually consecutive changes would occur in consecutive tokens. This is
137
    // not the case however when analyzing some preprocessor runs of the
138
    // annotated lines. For example, in this code:
139
    //
140
    // #if A // line 1
141
    // int i = 1;
142
    // #else B // line 2
143
    // int i = 2;
144
    // #endif // line 3
145
    //
146
    // one of the runs will produce the sequence of lines marked with line 1, 2
147
    // and 3. So the two consecutive whitespace changes just before '// line 2'
148
    // and before '#endif // line 3' span multiple lines and tokens:
149
    //
150
    // #else B{change X}[// line 2
151
    // int i = 2;
152
    // ]{change Y}#endif // line 3
153
    //
154
    // For this reason, if the text between consecutive changes spans multiple
155
    // newlines, the token length must be adjusted to the end of the original
156
    // line of the token.
157
350k
    auto NewlinePos = Text.find_first_of('\n');
158
350k
    if (NewlinePos == StringRef::npos) {
159
349k
      Changes[i - 1].TokenLength = OriginalWhitespaceStartOffset -
160
349k
                                   PreviousOriginalWhitespaceEndOffset +
161
349k
                                   Changes[i].PreviousLinePostfix.size() +
162
349k
                                   Changes[i - 1].CurrentLinePrefix.size();
163
349k
    } else {
164
424
      Changes[i - 1].TokenLength =
165
424
          NewlinePos + Changes[i - 1].CurrentLinePrefix.size();
166
424
    }
167
168
    // If there are multiple changes in this token, sum up all the changes until
169
    // the end of the line.
170
350k
    if (Changes[i - 1].IsInsideToken && 
Changes[i - 1].NewlinesBefore == 01.74k
)
171
469
      LastOutsideTokenChange->TokenLength +=
172
469
          Changes[i - 1].TokenLength + Changes[i - 1].Spaces;
173
349k
    else
174
349k
      LastOutsideTokenChange = &Changes[i - 1];
175
176
350k
    Changes[i].PreviousEndOfTokenColumn =
177
350k
        Changes[i - 1].StartOfTokenColumn + Changes[i - 1].TokenLength;
178
179
350k
    Changes[i - 1].IsTrailingComment =
180
350k
        (Changes[i].NewlinesBefore > 0 || 
Changes[i].Tok->is(tok::eof)300k
||
181
350k
         
(280k
Changes[i].IsInsideToken280k
&&
Changes[i].Tok->is(tok::comment)469
)) &&
182
350k
        
Changes[i - 1].Tok->is(tok::comment)70.1k
&&
183
        // FIXME: This is a dirty hack. The problem is that
184
        // BreakableLineCommentSection does comment reflow changes and here is
185
        // the aligning of trailing comments. Consider the case where we reflow
186
        // the second line up in this example:
187
        //
188
        // // line 1
189
        // // line 2
190
        //
191
        // That amounts to 2 changes by BreakableLineCommentSection:
192
        //  - the first, delimited by (), for the whitespace between the tokens,
193
        //  - and second, delimited by [], for the whitespace at the beginning
194
        //  of the second token:
195
        //
196
        // // line 1(
197
        // )[// ]line 2
198
        //
199
        // So in the end we have two changes like this:
200
        //
201
        // // line1()[ ]line 2
202
        //
203
        // Note that the OriginalWhitespaceStart of the second change is the
204
        // same as the PreviousOriginalWhitespaceEnd of the first change.
205
        // In this case, the below check ensures that the second change doesn't
206
        // get treated as a trailing comment change here, since this might
207
        // trigger additional whitespace to be wrongly inserted before "line 2"
208
        // by the comment aligner here.
209
        //
210
        // For a proper solution we need a mechanism to say to WhitespaceManager
211
        // that a particular change breaks the current sequence of trailing
212
        // comments.
213
350k
        
OriginalWhitespaceStart != PreviousOriginalWhitespaceEnd6.47k
;
214
350k
  }
215
  // FIXME: The last token is currently not always an eof token; in those
216
  // cases, setting TokenLength of the last token to 0 is wrong.
217
22.2k
  Changes.back().TokenLength = 0;
218
22.2k
  Changes.back().IsTrailingComment = Changes.back().Tok->is(tok::comment);
219
220
22.2k
  const WhitespaceManager::Change *LastBlockComment = nullptr;
221
372k
  for (auto &Change : Changes) {
222
    // Reset the IsTrailingComment flag for changes inside of trailing comments
223
    // so they don't get realigned later. Comment line breaks however still need
224
    // to be aligned.
225
372k
    if (Change.IsInsideToken && 
Change.NewlinesBefore == 01.74k
)
226
469
      Change.IsTrailingComment = false;
227
372k
    Change.StartOfBlockComment = nullptr;
228
372k
    Change.IndentationOffset = 0;
229
372k
    if (Change.Tok->is(tok::comment)) {
230
7.11k
      if (Change.Tok->is(TT_LineComment) || 
!Change.IsInsideToken1.75k
)
231
6.40k
        LastBlockComment = &Change;
232
714
      else {
233
714
        if ((Change.StartOfBlockComment = LastBlockComment))
234
714
          Change.IndentationOffset =
235
714
              Change.StartOfTokenColumn -
236
714
              Change.StartOfBlockComment->StartOfTokenColumn;
237
714
      }
238
365k
    } else {
239
365k
      LastBlockComment = nullptr;
240
365k
    }
241
372k
  }
242
243
  // Compute conditional nesting level
244
  // Level is increased for each conditional, unless this conditional continues
245
  // a chain of conditional, i.e. starts immediately after the colon of another
246
  // conditional.
247
22.2k
  SmallVector<bool, 16> ScopeStack;
248
22.2k
  int ConditionalsLevel = 0;
249
372k
  for (auto &Change : Changes) {
250
400k
    for (unsigned i = 0, e = Change.Tok->FakeLParens.size(); i != e; 
++i27.7k
) {
251
27.7k
      bool isNestedConditional =
252
27.7k
          Change.Tok->FakeLParens[e - 1 - i] == prec::Conditional &&
253
27.7k
          
!(762
i == 0762
&&
Change.Tok->Previous758
&&
254
762
            
Change.Tok->Previous->is(TT_ConditionalExpr)731
&&
255
762
            
Change.Tok->Previous->is(tok::colon)209
);
256
27.7k
      if (isNestedConditional)
257
574
        ++ConditionalsLevel;
258
27.7k
      ScopeStack.push_back(isNestedConditional);
259
27.7k
    }
260
261
372k
    Change.ConditionalsLevel = ConditionalsLevel;
262
263
398k
    for (unsigned i = Change.Tok->FakeRParens; i > 0 && 
ScopeStack.size()25.7k
;
--i25.6k
)
264
25.6k
      if (ScopeStack.pop_back_val())
265
559
        --ConditionalsLevel;
266
372k
  }
267
22.2k
}
268
269
// Align a single sequence of tokens, see AlignTokens below.
270
// Column - The token for which Matches returns true is moved to this column.
271
// RightJustify - Whether it is the token's right end or left end that gets
272
// moved to that column.
273
template <typename F>
274
static void
275
AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
276
                   unsigned Column, bool RightJustify, F &&Matches,
277
2.16k
                   SmallVector<WhitespaceManager::Change, 16> &Changes) {
278
2.16k
  bool FoundMatchOnLine = false;
279
2.16k
  int Shift = 0;
280
281
  // ScopeStack keeps track of the current scope depth. It contains indices of
282
  // the first token on each scope.
283
  // We only run the "Matches" function on tokens from the outer-most scope.
284
  // However, we do need to pay special attention to one class of tokens
285
  // that are not in the outer-most scope, and that is function parameters
286
  // which are split across multiple lines, as illustrated by this example:
287
  //   double a(int x);
288
  //   int    b(int  y,
289
  //          double z);
290
  // In the above example, we need to take special care to ensure that
291
  // 'double z' is indented along with it's owning function 'b'.
292
  // The same holds for calling a function:
293
  //   double a = foo(x);
294
  //   int    b = bar(foo(y),
295
  //            foor(z));
296
  // Similar for broken string literals:
297
  //   double x = 3.14;
298
  //   auto s   = "Hello"
299
  //          "World";
300
  // Special handling is required for 'nested' ternary operators.
301
2.16k
  SmallVector<unsigned, 16> ScopeStack;
302
303
28.7k
  for (unsigned i = Start; i != End; 
++i26.5k
) {
304
26.5k
    if (ScopeStack.size() != 0 &&
305
26.5k
        Changes[i].indentAndNestingLevel() <
306
10.8k
            Changes[ScopeStack.back()].indentAndNestingLevel())
307
1.96k
      ScopeStack.pop_back();
308
309
    // Compare current token to previous non-comment token to ensure whether
310
    // it is in a deeper scope or not.
311
26.5k
    unsigned PreviousNonComment = i - 1;
312
26.8k
    while (PreviousNonComment > Start &&
313
26.8k
           
Changes[PreviousNonComment].Tok->is(tok::comment)22.5k
)
314
282
      --PreviousNonComment;
315
26.5k
    if (i != Start && Changes[i].indentAndNestingLevel() >
316
24.4k
                          Changes[PreviousNonComment].indentAndNestingLevel())
317
2.15k
      ScopeStack.push_back(i);
318
319
26.5k
    bool InsideNestedScope = ScopeStack.size() != 0;
320
26.5k
    bool ContinuedStringLiteral = i > Start &&
321
26.5k
                                  
Changes[i].Tok->is(tok::string_literal)24.4k
&&
322
26.5k
                                  
Changes[i - 1].Tok->is(tok::string_literal)357
;
323
26.5k
    bool SkipMatchCheck = InsideNestedScope || 
ContinuedStringLiteral15.5k
;
324
325
26.5k
    if (Changes[i].NewlinesBefore > 0 && 
!SkipMatchCheck3.09k
) {
326
1.98k
      Shift = 0;
327
1.98k
      FoundMatchOnLine = false;
328
1.98k
    }
329
330
    // If this is the first matching token to be aligned, remember by how many
331
    // spaces it has to be shifted, so the rest of the changes on the line are
332
    // shifted by the same amount
333
26.5k
    if (!FoundMatchOnLine && 
!SkipMatchCheck7.52k
&&
Matches(Changes[i])7.08k
) {
334
3.69k
      FoundMatchOnLine = true;
335
3.69k
      Shift = Column - (RightJustify ? 
Changes[i].TokenLength758
:
02.93k
) -
336
3.69k
              Changes[i].StartOfTokenColumn;
337
3.69k
      Changes[i].Spaces += Shift;
338
      // FIXME: This is a workaround that should be removed when we fix
339
      // http://llvm.org/PR53699. An assertion later below verifies this.
340
3.69k
      if (Changes[i].NewlinesBefore == 0)
341
3.30k
        Changes[i].Spaces =
342
3.30k
            std::max(Changes[i].Spaces,
343
3.30k
                     static_cast<int>(Changes[i].Tok->SpacesRequiredBefore));
344
3.69k
    }
345
346
    // This is for function parameters that are split across multiple lines,
347
    // as mentioned in the ScopeStack comment.
348
26.5k
    if (InsideNestedScope && 
Changes[i].NewlinesBefore > 011.0k
) {
349
1.08k
      unsigned ScopeStart = ScopeStack.back();
350
1.08k
      auto ShouldShiftBeAdded = [&] {
351
        // Function declaration
352
1.08k
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
353
0
          return true;
354
355
        // Lambda.
356
1.08k
        if (Changes[ScopeStart - 1].Tok->is(TT_LambdaLBrace))
357
93
          return false;
358
359
        // Continued function declaration
360
989
        if (ScopeStart > Start + 1 &&
361
989
            
Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName)962
)
362
30
          return true;
363
364
        // Continued function call
365
959
        if (ScopeStart > Start + 1 &&
366
959
            
Changes[ScopeStart - 2].Tok->is(tok::identifier)932
&&
367
959
            
Changes[ScopeStart - 1].Tok->is(tok::l_paren)238
&&
368
959
            
Changes[ScopeStart].Tok->isNot(TT_LambdaLSquare)126
) {
369
123
          if (Changes[i].Tok->MatchingParen &&
370
123
              
Changes[i].Tok->MatchingParen->is(TT_LambdaLBrace)9
)
371
6
            return false;
372
117
          if (Changes[ScopeStart].NewlinesBefore > 0)
373
39
            return false;
374
78
          if (Changes[i].Tok->is(tok::l_brace) &&
375
78
              
Changes[i].Tok->is(BK_BracedInit)3
)
376
3
            return true;
377
75
          return Style.BinPackArguments;
378
78
        }
379
380
        // Ternary operator
381
836
        if (Changes[i].Tok->is(TT_ConditionalExpr))
382
66
          return true;
383
384
        // Period Initializer .XXX = 1.
385
770
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
386
36
          return true;
387
388
        // Continued ternary operator
389
734
        if (Changes[i].Tok->Previous &&
390
734
            
Changes[i].Tok->Previous->is(TT_ConditionalExpr)486
)
391
48
          return true;
392
393
        // Continued direct-list-initialization using braced list.
394
686
        if (ScopeStart > Start + 1 &&
395
686
            
Changes[ScopeStart - 2].Tok->is(tok::identifier)683
&&
396
686
            
Changes[ScopeStart - 1].Tok->is(tok::l_brace)109
&&
397
686
            
Changes[i].Tok->is(tok::l_brace)99
&&
398
686
            
Changes[i].Tok->is(BK_BracedInit)21
)
399
21
          return true;
400
401
        // Continued braced list.
402
665
        if (ScopeStart > Start + 1 &&
403
665
            
Changes[ScopeStart - 2].Tok->isNot(tok::identifier)662
&&
404
665
            
Changes[ScopeStart - 1].Tok->is(tok::l_brace)574
&&
405
665
            
Changes[i].Tok->isNot(tok::r_brace)538
) {
406
536
          for (unsigned OuterScopeStart : llvm::reverse(ScopeStack)) {
407
            // Lambda.
408
536
            if (OuterScopeStart > Start &&
409
536
                Changes[OuterScopeStart - 1].Tok->is(TT_LambdaLBrace))
410
3
              return false;
411
536
          }
412
488
          if (Changes[ScopeStart].NewlinesBefore > 0)
413
458
            return false;
414
30
          return true;
415
488
        }
416
417
174
        return false;
418
665
      };
WhitespaceManager.cpp:void clang::format::AlignTokenSequence<clang::format::WhitespaceManager::alignConsecutiveAssignments()::$_1&>(clang::format::FormatStyle const&, unsigned int, unsigned int, unsigned int, bool, clang::format::WhitespaceManager::alignConsecutiveAssignments()::$_1&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&)::'lambda'()::operator()() const
Line
Count
Source
350
356
      auto ShouldShiftBeAdded = [&] {
351
        // Function declaration
352
356
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
353
0
          return true;
354
355
        // Lambda.
356
356
        if (Changes[ScopeStart - 1].Tok->is(TT_LambdaLBrace))
357
54
          return false;
358
359
        // Continued function declaration
360
302
        if (ScopeStart > Start + 1 &&
361
302
            Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName))
362
0
          return true;
363
364
        // Continued function call
365
302
        if (ScopeStart > Start + 1 &&
366
302
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
367
302
            
Changes[ScopeStart - 1].Tok->is(tok::l_paren)115
&&
368
302
            
Changes[ScopeStart].Tok->isNot(TT_LambdaLSquare)54
) {
369
51
          if (Changes[i].Tok->MatchingParen &&
370
51
              
Changes[i].Tok->MatchingParen->is(TT_LambdaLBrace)6
)
371
3
            return false;
372
48
          if (Changes[ScopeStart].NewlinesBefore > 0)
373
15
            return false;
374
33
          if (Changes[i].Tok->is(tok::l_brace) &&
375
33
              
Changes[i].Tok->is(BK_BracedInit)3
)
376
3
            return true;
377
30
          return Style.BinPackArguments;
378
33
        }
379
380
        // Ternary operator
381
251
        if (Changes[i].Tok->is(TT_ConditionalExpr))
382
0
          return true;
383
384
        // Period Initializer .XXX = 1.
385
251
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
386
12
          return true;
387
388
        // Continued ternary operator
389
239
        if (Changes[i].Tok->Previous &&
390
239
            
Changes[i].Tok->Previous->is(TT_ConditionalExpr)218
)
391
0
          return true;
392
393
        // Continued direct-list-initialization using braced list.
394
239
        if (ScopeStart > Start + 1 &&
395
239
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
396
239
            
Changes[ScopeStart - 1].Tok->is(tok::l_brace)64
&&
397
239
            
Changes[i].Tok->is(tok::l_brace)57
&&
398
239
            
Changes[i].Tok->is(BK_BracedInit)9
)
399
9
          return true;
400
401
        // Continued braced list.
402
230
        if (ScopeStart > Start + 1 &&
403
230
            Changes[ScopeStart - 2].Tok->isNot(tok::identifier) &&
404
230
            
Changes[ScopeStart - 1].Tok->is(tok::l_brace)175
&&
405
230
            
Changes[i].Tok->isNot(tok::r_brace)157
) {
406
156
          for (unsigned OuterScopeStart : llvm::reverse(ScopeStack)) {
407
            // Lambda.
408
156
            if (OuterScopeStart > Start &&
409
156
                Changes[OuterScopeStart - 1].Tok->is(TT_LambdaLBrace))
410
3
              return false;
411
156
          }
412
132
          if (Changes[ScopeStart].NewlinesBefore > 0)
413
117
            return false;
414
15
          return true;
415
132
        }
416
417
95
        return false;
418
230
      };
Unexecuted instantiation: WhitespaceManager.cpp:void clang::format::AlignTokenSequence<clang::format::WhitespaceManager::alignConsecutiveBitFields()::$_2&>(clang::format::FormatStyle const&, unsigned int, unsigned int, unsigned int, bool, 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, bool, clang::format::WhitespaceManager::alignConsecutiveDeclarations()::$_3&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&)::'lambda'()::operator()() const
Line
Count
Source
350
577
      auto ShouldShiftBeAdded = [&] {
351
        // Function declaration
352
577
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
353
0
          return true;
354
355
        // Lambda.
356
577
        if (Changes[ScopeStart - 1].Tok->is(TT_LambdaLBrace))
357
36
          return false;
358
359
        // Continued function declaration
360
541
        if (ScopeStart > Start + 1 &&
361
541
            Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName))
362
30
          return true;
363
364
        // Continued function call
365
511
        if (ScopeStart > Start + 1 &&
366
511
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
367
511
            
Changes[ScopeStart - 1].Tok->is(tok::l_paren)96
&&
368
511
            
Changes[ScopeStart].Tok->isNot(TT_LambdaLSquare)54
) {
369
54
          if (Changes[i].Tok->MatchingParen &&
370
54
              
Changes[i].Tok->MatchingParen->is(TT_LambdaLBrace)3
)
371
3
            return false;
372
51
          if (Changes[ScopeStart].NewlinesBefore > 0)
373
6
            return false;
374
45
          if (Changes[i].Tok->is(tok::l_brace) &&
375
45
              
Changes[i].Tok->is(BK_BracedInit)0
)
376
0
            return true;
377
45
          return Style.BinPackArguments;
378
45
        }
379
380
        // Ternary operator
381
457
        if (Changes[i].Tok->is(TT_ConditionalExpr))
382
0
          return true;
383
384
        // Period Initializer .XXX = 1.
385
457
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
386
24
          return true;
387
388
        // Continued ternary operator
389
433
        if (Changes[i].Tok->Previous &&
390
433
            
Changes[i].Tok->Previous->is(TT_ConditionalExpr)208
)
391
0
          return true;
392
393
        // Continued direct-list-initialization using braced list.
394
433
        if (ScopeStart > Start + 1 &&
395
433
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
396
433
            
Changes[ScopeStart - 1].Tok->is(tok::l_brace)42
&&
397
433
            
Changes[i].Tok->is(tok::l_brace)42
&&
398
433
            
Changes[i].Tok->is(BK_BracedInit)12
)
399
12
          return true;
400
401
        // Continued braced list.
402
421
        if (ScopeStart > Start + 1 &&
403
421
            Changes[ScopeStart - 2].Tok->isNot(tok::identifier) &&
404
421
            
Changes[ScopeStart - 1].Tok->is(tok::l_brace)391
&&
405
421
            
Changes[i].Tok->isNot(tok::r_brace)373
) {
406
372
          for (unsigned OuterScopeStart : llvm::reverse(ScopeStack)) {
407
            // Lambda.
408
372
            if (OuterScopeStart > Start &&
409
372
                Changes[OuterScopeStart - 1].Tok->is(TT_LambdaLBrace))
410
0
              return false;
411
372
          }
412
348
          if (Changes[ScopeStart].NewlinesBefore > 0)
413
339
            return false;
414
9
          return true;
415
348
        }
416
417
73
        return false;
418
421
      };
WhitespaceManager.cpp:void clang::format::AlignTokenSequence<clang::format::WhitespaceManager::alignChainedConditionals()::$_4&>(clang::format::FormatStyle const&, unsigned int, unsigned int, unsigned int, bool, clang::format::WhitespaceManager::alignChainedConditionals()::$_4&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&)::'lambda'()::operator()() const
Line
Count
Source
350
87
      auto ShouldShiftBeAdded = [&] {
351
        // Function declaration
352
87
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
353
0
          return true;
354
355
        // Lambda.
356
87
        if (Changes[ScopeStart - 1].Tok->is(TT_LambdaLBrace))
357
3
          return false;
358
359
        // Continued function declaration
360
84
        if (ScopeStart > Start + 1 &&
361
84
            
Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName)72
)
362
0
          return true;
363
364
        // Continued function call
365
84
        if (ScopeStart > Start + 1 &&
366
84
            
Changes[ScopeStart - 2].Tok->is(tok::identifier)72
&&
367
84
            
Changes[ScopeStart - 1].Tok->is(tok::l_paren)18
&&
368
84
            
Changes[ScopeStart].Tok->isNot(TT_LambdaLSquare)9
) {
369
9
          if (Changes[i].Tok->MatchingParen &&
370
9
              
Changes[i].Tok->MatchingParen->is(TT_LambdaLBrace)0
)
371
0
            return false;
372
9
          if (Changes[ScopeStart].NewlinesBefore > 0)
373
9
            return false;
374
0
          if (Changes[i].Tok->is(tok::l_brace) &&
375
0
              Changes[i].Tok->is(BK_BracedInit))
376
0
            return true;
377
0
          return Style.BinPackArguments;
378
0
        }
379
380
        // Ternary operator
381
75
        if (Changes[i].Tok->is(TT_ConditionalExpr))
382
66
          return true;
383
384
        // Period Initializer .XXX = 1.
385
9
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
386
0
          return true;
387
388
        // Continued ternary operator
389
9
        if (Changes[i].Tok->Previous &&
390
9
            Changes[i].Tok->Previous->is(TT_ConditionalExpr))
391
0
          return true;
392
393
        // Continued direct-list-initialization using braced list.
394
9
        if (ScopeStart > Start + 1 &&
395
9
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
396
9
            
Changes[ScopeStart - 1].Tok->is(tok::l_brace)3
&&
397
9
            
Changes[i].Tok->is(tok::l_brace)0
&&
398
9
            
Changes[i].Tok->is(BK_BracedInit)0
)
399
0
          return true;
400
401
        // Continued braced list.
402
9
        if (ScopeStart > Start + 1 &&
403
9
            Changes[ScopeStart - 2].Tok->isNot(tok::identifier) &&
404
9
            
Changes[ScopeStart - 1].Tok->is(tok::l_brace)6
&&
405
9
            
Changes[i].Tok->isNot(tok::r_brace)6
) {
406
6
          for (unsigned OuterScopeStart : llvm::reverse(ScopeStack)) {
407
            // Lambda.
408
6
            if (OuterScopeStart > Start &&
409
6
                Changes[OuterScopeStart - 1].Tok->is(TT_LambdaLBrace))
410
0
              return false;
411
6
          }
412
6
          if (Changes[ScopeStart].NewlinesBefore > 0)
413
0
            return false;
414
6
          return true;
415
6
        }
416
417
3
        return false;
418
9
      };
WhitespaceManager.cpp:void clang::format::AlignTokenSequence<clang::format::WhitespaceManager::alignChainedConditionals()::$_6&>(clang::format::FormatStyle const&, unsigned int, unsigned int, unsigned int, bool, clang::format::WhitespaceManager::alignChainedConditionals()::$_6&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&)::'lambda'()::operator()() const
Line
Count
Source
350
62
      auto ShouldShiftBeAdded = [&] {
351
        // Function declaration
352
62
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
353
0
          return true;
354
355
        // Lambda.
356
62
        if (Changes[ScopeStart - 1].Tok->is(TT_LambdaLBrace))
357
0
          return false;
358
359
        // Continued function declaration
360
62
        if (ScopeStart > Start + 1 &&
361
62
            
Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName)47
)
362
0
          return true;
363
364
        // Continued function call
365
62
        if (ScopeStart > Start + 1 &&
366
62
            
Changes[ScopeStart - 2].Tok->is(tok::identifier)47
&&
367
62
            
Changes[ScopeStart - 1].Tok->is(tok::l_paren)9
&&
368
62
            
Changes[ScopeStart].Tok->isNot(TT_LambdaLSquare)9
) {
369
9
          if (Changes[i].Tok->MatchingParen &&
370
9
              
Changes[i].Tok->MatchingParen->is(TT_LambdaLBrace)0
)
371
0
            return false;
372
9
          if (Changes[ScopeStart].NewlinesBefore > 0)
373
9
            return false;
374
0
          if (Changes[i].Tok->is(tok::l_brace) &&
375
0
              Changes[i].Tok->is(BK_BracedInit))
376
0
            return true;
377
0
          return Style.BinPackArguments;
378
0
        }
379
380
        // Ternary operator
381
53
        if (Changes[i].Tok->is(TT_ConditionalExpr))
382
0
          return true;
383
384
        // Period Initializer .XXX = 1.
385
53
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
386
0
          return true;
387
388
        // Continued ternary operator
389
53
        if (Changes[i].Tok->Previous &&
390
53
            
Changes[i].Tok->Previous->is(TT_ConditionalExpr)51
)
391
48
          return true;
392
393
        // Continued direct-list-initialization using braced list.
394
5
        if (ScopeStart > Start + 1 &&
395
5
            
Changes[ScopeStart - 2].Tok->is(tok::identifier)2
&&
396
5
            
Changes[ScopeStart - 1].Tok->is(tok::l_brace)0
&&
397
5
            
Changes[i].Tok->is(tok::l_brace)0
&&
398
5
            
Changes[i].Tok->is(BK_BracedInit)0
)
399
0
          return true;
400
401
        // Continued braced list.
402
5
        if (ScopeStart > Start + 1 &&
403
5
            
Changes[ScopeStart - 2].Tok->isNot(tok::identifier)2
&&
404
5
            
Changes[ScopeStart - 1].Tok->is(tok::l_brace)2
&&
405
5
            
Changes[i].Tok->isNot(tok::r_brace)2
) {
406
2
          for (unsigned OuterScopeStart : llvm::reverse(ScopeStack)) {
407
            // Lambda.
408
2
            if (OuterScopeStart > Start &&
409
2
                Changes[OuterScopeStart - 1].Tok->is(TT_LambdaLBrace))
410
0
              return false;
411
2
          }
412
2
          if (Changes[ScopeStart].NewlinesBefore > 0)
413
2
            return false;
414
0
          return true;
415
2
        }
416
417
3
        return false;
418
5
      };
419
420
1.08k
      if (ShouldShiftBeAdded())
421
309
        Changes[i].Spaces += Shift;
422
1.08k
    }
423
424
26.5k
    if (ContinuedStringLiteral)
425
45
      Changes[i].Spaces += Shift;
426
427
    // We should not remove required spaces unless we break the line before.
428
26.5k
    assert(Shift >= 0 || Changes[i].NewlinesBefore > 0 ||
429
26.5k
           Changes[i].Spaces >=
430
26.5k
               static_cast<int>(Changes[i].Tok->SpacesRequiredBefore) ||
431
26.5k
           Changes[i].Tok->is(tok::eof));
432
433
0
    Changes[i].StartOfTokenColumn += Shift;
434
26.5k
    if (i + 1 != Changes.size())
435
25.8k
      Changes[i + 1].PreviousEndOfTokenColumn += Shift;
436
437
    // If PointerAlignment is PAS_Right, keep *s or &s next to the token
438
26.5k
    if (Style.PointerAlignment == FormatStyle::PAS_Right &&
439
26.5k
        
Changes[i].Spaces != 022.1k
) {
440
12.4k
      for (int Previous = i - 1;
441
12.4k
           Previous >= 0 &&
442
12.4k
           Changes[Previous].Tok->getType() == TT_PointerOrReference;
443
12.4k
           
--Previous77
) {
444
77
        Changes[Previous + 1].Spaces -= Shift;
445
77
        Changes[Previous].Spaces += Shift;
446
77
        Changes[Previous].StartOfTokenColumn += Shift;
447
77
      }
448
12.4k
    }
449
26.5k
  }
450
2.16k
}
WhitespaceManager.cpp:void clang::format::AlignTokenSequence<clang::format::WhitespaceManager::alignConsecutiveAssignments()::$_1&>(clang::format::FormatStyle const&, unsigned int, unsigned int, unsigned int, bool, clang::format::WhitespaceManager::alignConsecutiveAssignments()::$_1&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&)
Line
Count
Source
277
706
                   SmallVector<WhitespaceManager::Change, 16> &Changes) {
278
706
  bool FoundMatchOnLine = false;
279
706
  int Shift = 0;
280
281
  // ScopeStack keeps track of the current scope depth. It contains indices of
282
  // the first token on each scope.
283
  // We only run the "Matches" function on tokens from the outer-most scope.
284
  // However, we do need to pay special attention to one class of tokens
285
  // that are not in the outer-most scope, and that is function parameters
286
  // which are split across multiple lines, as illustrated by this example:
287
  //   double a(int x);
288
  //   int    b(int  y,
289
  //          double z);
290
  // In the above example, we need to take special care to ensure that
291
  // 'double z' is indented along with it's owning function 'b'.
292
  // The same holds for calling a function:
293
  //   double a = foo(x);
294
  //   int    b = bar(foo(y),
295
  //            foor(z));
296
  // Similar for broken string literals:
297
  //   double x = 3.14;
298
  //   auto s   = "Hello"
299
  //          "World";
300
  // Special handling is required for 'nested' ternary operators.
301
706
  SmallVector<unsigned, 16> ScopeStack;
302
303
10.3k
  for (unsigned i = Start; i != End; 
++i9.66k
) {
304
9.66k
    if (ScopeStack.size() != 0 &&
305
9.66k
        Changes[i].indentAndNestingLevel() <
306
3.77k
            Changes[ScopeStack.back()].indentAndNestingLevel())
307
764
      ScopeStack.pop_back();
308
309
    // Compare current token to previous non-comment token to ensure whether
310
    // it is in a deeper scope or not.
311
9.66k
    unsigned PreviousNonComment = i - 1;
312
9.82k
    while (PreviousNonComment > Start &&
313
9.82k
           
Changes[PreviousNonComment].Tok->is(tok::comment)8.41k
)
314
166
      --PreviousNonComment;
315
9.66k
    if (i != Start && Changes[i].indentAndNestingLevel() >
316
8.95k
                          Changes[PreviousNonComment].indentAndNestingLevel())
317
821
      ScopeStack.push_back(i);
318
319
9.66k
    bool InsideNestedScope = ScopeStack.size() != 0;
320
9.66k
    bool ContinuedStringLiteral = i > Start &&
321
9.66k
                                  
Changes[i].Tok->is(tok::string_literal)8.95k
&&
322
9.66k
                                  
Changes[i - 1].Tok->is(tok::string_literal)150
;
323
9.66k
    bool SkipMatchCheck = InsideNestedScope || 
ContinuedStringLiteral5.83k
;
324
325
9.66k
    if (Changes[i].NewlinesBefore > 0 && 
!SkipMatchCheck1.06k
) {
326
699
      Shift = 0;
327
699
      FoundMatchOnLine = false;
328
699
    }
329
330
    // If this is the first matching token to be aligned, remember by how many
331
    // spaces it has to be shifted, so the rest of the changes on the line are
332
    // shifted by the same amount
333
9.66k
    if (!FoundMatchOnLine && 
!SkipMatchCheck3.12k
&&
Matches(Changes[i])2.83k
) {
334
1.20k
      FoundMatchOnLine = true;
335
1.20k
      Shift = Column - (RightJustify ? 
Changes[i].TokenLength758
:
0444
) -
336
1.20k
              Changes[i].StartOfTokenColumn;
337
1.20k
      Changes[i].Spaces += Shift;
338
      // FIXME: This is a workaround that should be removed when we fix
339
      // http://llvm.org/PR53699. An assertion later below verifies this.
340
1.20k
      if (Changes[i].NewlinesBefore == 0)
341
1.20k
        Changes[i].Spaces =
342
1.20k
            std::max(Changes[i].Spaces,
343
1.20k
                     static_cast<int>(Changes[i].Tok->SpacesRequiredBefore));
344
1.20k
    }
345
346
    // This is for function parameters that are split across multiple lines,
347
    // as mentioned in the ScopeStack comment.
348
9.66k
    if (InsideNestedScope && 
Changes[i].NewlinesBefore > 03.83k
) {
349
356
      unsigned ScopeStart = ScopeStack.back();
350
356
      auto ShouldShiftBeAdded = [&] {
351
        // Function declaration
352
356
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
353
356
          return true;
354
355
        // Lambda.
356
356
        if (Changes[ScopeStart - 1].Tok->is(TT_LambdaLBrace))
357
356
          return false;
358
359
        // Continued function declaration
360
356
        if (ScopeStart > Start + 1 &&
361
356
            Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName))
362
356
          return true;
363
364
        // Continued function call
365
356
        if (ScopeStart > Start + 1 &&
366
356
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
367
356
            Changes[ScopeStart - 1].Tok->is(tok::l_paren) &&
368
356
            Changes[ScopeStart].Tok->isNot(TT_LambdaLSquare)) {
369
356
          if (Changes[i].Tok->MatchingParen &&
370
356
              Changes[i].Tok->MatchingParen->is(TT_LambdaLBrace))
371
356
            return false;
372
356
          if (Changes[ScopeStart].NewlinesBefore > 0)
373
356
            return false;
374
356
          if (Changes[i].Tok->is(tok::l_brace) &&
375
356
              Changes[i].Tok->is(BK_BracedInit))
376
356
            return true;
377
356
          return Style.BinPackArguments;
378
356
        }
379
380
        // Ternary operator
381
356
        if (Changes[i].Tok->is(TT_ConditionalExpr))
382
356
          return true;
383
384
        // Period Initializer .XXX = 1.
385
356
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
386
356
          return true;
387
388
        // Continued ternary operator
389
356
        if (Changes[i].Tok->Previous &&
390
356
            Changes[i].Tok->Previous->is(TT_ConditionalExpr))
391
356
          return true;
392
393
        // Continued direct-list-initialization using braced list.
394
356
        if (ScopeStart > Start + 1 &&
395
356
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
396
356
            Changes[ScopeStart - 1].Tok->is(tok::l_brace) &&
397
356
            Changes[i].Tok->is(tok::l_brace) &&
398
356
            Changes[i].Tok->is(BK_BracedInit))
399
356
          return true;
400
401
        // Continued braced list.
402
356
        if (ScopeStart > Start + 1 &&
403
356
            Changes[ScopeStart - 2].Tok->isNot(tok::identifier) &&
404
356
            Changes[ScopeStart - 1].Tok->is(tok::l_brace) &&
405
356
            Changes[i].Tok->isNot(tok::r_brace)) {
406
356
          for (unsigned OuterScopeStart : llvm::reverse(ScopeStack)) {
407
            // Lambda.
408
356
            if (OuterScopeStart > Start &&
409
356
                Changes[OuterScopeStart - 1].Tok->is(TT_LambdaLBrace))
410
356
              return false;
411
356
          }
412
356
          if (Changes[ScopeStart].NewlinesBefore > 0)
413
356
            return false;
414
356
          return true;
415
356
        }
416
417
356
        return false;
418
356
      };
419
420
356
      if (ShouldShiftBeAdded())
421
69
        Changes[i].Spaces += Shift;
422
356
    }
423
424
9.66k
    if (ContinuedStringLiteral)
425
15
      Changes[i].Spaces += Shift;
426
427
    // We should not remove required spaces unless we break the line before.
428
9.66k
    assert(Shift >= 0 || Changes[i].NewlinesBefore > 0 ||
429
9.66k
           Changes[i].Spaces >=
430
9.66k
               static_cast<int>(Changes[i].Tok->SpacesRequiredBefore) ||
431
9.66k
           Changes[i].Tok->is(tok::eof));
432
433
0
    Changes[i].StartOfTokenColumn += Shift;
434
9.66k
    if (i + 1 != Changes.size())
435
9.35k
      Changes[i + 1].PreviousEndOfTokenColumn += Shift;
436
437
    // If PointerAlignment is PAS_Right, keep *s or &s next to the token
438
9.66k
    if (Style.PointerAlignment == FormatStyle::PAS_Right &&
439
9.66k
        
Changes[i].Spaces != 09.18k
) {
440
4.55k
      for (int Previous = i - 1;
441
4.55k
           Previous >= 0 &&
442
4.55k
           Changes[Previous].Tok->getType() == TT_PointerOrReference;
443
4.55k
           
--Previous0
) {
444
0
        Changes[Previous + 1].Spaces -= Shift;
445
0
        Changes[Previous].Spaces += Shift;
446
0
        Changes[Previous].StartOfTokenColumn += Shift;
447
0
      }
448
4.55k
    }
449
9.66k
  }
450
706
}
WhitespaceManager.cpp:void clang::format::AlignTokenSequence<clang::format::WhitespaceManager::alignConsecutiveBitFields()::$_2&>(clang::format::FormatStyle const&, unsigned int, unsigned int, unsigned int, bool, clang::format::WhitespaceManager::alignConsecutiveBitFields()::$_2&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&)
Line
Count
Source
277
36
                   SmallVector<WhitespaceManager::Change, 16> &Changes) {
278
36
  bool FoundMatchOnLine = false;
279
36
  int Shift = 0;
280
281
  // ScopeStack keeps track of the current scope depth. It contains indices of
282
  // the first token on each scope.
283
  // We only run the "Matches" function on tokens from the outer-most scope.
284
  // However, we do need to pay special attention to one class of tokens
285
  // that are not in the outer-most scope, and that is function parameters
286
  // which are split across multiple lines, as illustrated by this example:
287
  //   double a(int x);
288
  //   int    b(int  y,
289
  //          double z);
290
  // In the above example, we need to take special care to ensure that
291
  // 'double z' is indented along with it's owning function 'b'.
292
  // The same holds for calling a function:
293
  //   double a = foo(x);
294
  //   int    b = bar(foo(y),
295
  //            foor(z));
296
  // Similar for broken string literals:
297
  //   double x = 3.14;
298
  //   auto s   = "Hello"
299
  //          "World";
300
  // Special handling is required for 'nested' ternary operators.
301
36
  SmallVector<unsigned, 16> ScopeStack;
302
303
439
  for (unsigned i = Start; i != End; 
++i403
) {
304
403
    if (ScopeStack.size() != 0 &&
305
403
        Changes[i].indentAndNestingLevel() <
306
6
            Changes[ScopeStack.back()].indentAndNestingLevel())
307
3
      ScopeStack.pop_back();
308
309
    // Compare current token to previous non-comment token to ensure whether
310
    // it is in a deeper scope or not.
311
403
    unsigned PreviousNonComment = i - 1;
312
413
    while (PreviousNonComment > Start &&
313
413
           
Changes[PreviousNonComment].Tok->is(tok::comment)341
)
314
10
      --PreviousNonComment;
315
403
    if (i != Start && Changes[i].indentAndNestingLevel() >
316
367
                          Changes[PreviousNonComment].indentAndNestingLevel())
317
3
      ScopeStack.push_back(i);
318
319
403
    bool InsideNestedScope = ScopeStack.size() != 0;
320
403
    bool ContinuedStringLiteral = i > Start &&
321
403
                                  
Changes[i].Tok->is(tok::string_literal)367
&&
322
403
                                  
Changes[i - 1].Tok->is(tok::string_literal)0
;
323
403
    bool SkipMatchCheck = InsideNestedScope || 
ContinuedStringLiteral397
;
324
325
403
    if (Changes[i].NewlinesBefore > 0 && 
!SkipMatchCheck43
) {
326
43
      Shift = 0;
327
43
      FoundMatchOnLine = false;
328
43
    }
329
330
    // If this is the first matching token to be aligned, remember by how many
331
    // spaces it has to be shifted, so the rest of the changes on the line are
332
    // shifted by the same amount
333
403
    if (!FoundMatchOnLine && 
!SkipMatchCheck157
&&
Matches(Changes[i])157
) {
334
75
      FoundMatchOnLine = true;
335
75
      Shift = Column - (RightJustify ? 
Changes[i].TokenLength0
: 0) -
336
75
              Changes[i].StartOfTokenColumn;
337
75
      Changes[i].Spaces += Shift;
338
      // FIXME: This is a workaround that should be removed when we fix
339
      // http://llvm.org/PR53699. An assertion later below verifies this.
340
75
      if (Changes[i].NewlinesBefore == 0)
341
75
        Changes[i].Spaces =
342
75
            std::max(Changes[i].Spaces,
343
75
                     static_cast<int>(Changes[i].Tok->SpacesRequiredBefore));
344
75
    }
345
346
    // This is for function parameters that are split across multiple lines,
347
    // as mentioned in the ScopeStack comment.
348
403
    if (InsideNestedScope && 
Changes[i].NewlinesBefore > 06
) {
349
0
      unsigned ScopeStart = ScopeStack.back();
350
0
      auto ShouldShiftBeAdded = [&] {
351
        // Function declaration
352
0
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
353
0
          return true;
354
355
        // Lambda.
356
0
        if (Changes[ScopeStart - 1].Tok->is(TT_LambdaLBrace))
357
0
          return false;
358
359
        // Continued function declaration
360
0
        if (ScopeStart > Start + 1 &&
361
0
            Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName))
362
0
          return true;
363
364
        // Continued function call
365
0
        if (ScopeStart > Start + 1 &&
366
0
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
367
0
            Changes[ScopeStart - 1].Tok->is(tok::l_paren) &&
368
0
            Changes[ScopeStart].Tok->isNot(TT_LambdaLSquare)) {
369
0
          if (Changes[i].Tok->MatchingParen &&
370
0
              Changes[i].Tok->MatchingParen->is(TT_LambdaLBrace))
371
0
            return false;
372
0
          if (Changes[ScopeStart].NewlinesBefore > 0)
373
0
            return false;
374
0
          if (Changes[i].Tok->is(tok::l_brace) &&
375
0
              Changes[i].Tok->is(BK_BracedInit))
376
0
            return true;
377
0
          return Style.BinPackArguments;
378
0
        }
379
380
        // Ternary operator
381
0
        if (Changes[i].Tok->is(TT_ConditionalExpr))
382
0
          return true;
383
384
        // Period Initializer .XXX = 1.
385
0
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
386
0
          return true;
387
388
        // Continued ternary operator
389
0
        if (Changes[i].Tok->Previous &&
390
0
            Changes[i].Tok->Previous->is(TT_ConditionalExpr))
391
0
          return true;
392
393
        // Continued direct-list-initialization using braced list.
394
0
        if (ScopeStart > Start + 1 &&
395
0
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
396
0
            Changes[ScopeStart - 1].Tok->is(tok::l_brace) &&
397
0
            Changes[i].Tok->is(tok::l_brace) &&
398
0
            Changes[i].Tok->is(BK_BracedInit))
399
0
          return true;
400
401
        // Continued braced list.
402
0
        if (ScopeStart > Start + 1 &&
403
0
            Changes[ScopeStart - 2].Tok->isNot(tok::identifier) &&
404
0
            Changes[ScopeStart - 1].Tok->is(tok::l_brace) &&
405
0
            Changes[i].Tok->isNot(tok::r_brace)) {
406
0
          for (unsigned OuterScopeStart : llvm::reverse(ScopeStack)) {
407
            // Lambda.
408
0
            if (OuterScopeStart > Start &&
409
0
                Changes[OuterScopeStart - 1].Tok->is(TT_LambdaLBrace))
410
0
              return false;
411
0
          }
412
0
          if (Changes[ScopeStart].NewlinesBefore > 0)
413
0
            return false;
414
0
          return true;
415
0
        }
416
417
0
        return false;
418
0
      };
419
420
0
      if (ShouldShiftBeAdded())
421
0
        Changes[i].Spaces += Shift;
422
0
    }
423
424
403
    if (ContinuedStringLiteral)
425
0
      Changes[i].Spaces += Shift;
426
427
    // We should not remove required spaces unless we break the line before.
428
403
    assert(Shift >= 0 || Changes[i].NewlinesBefore > 0 ||
429
403
           Changes[i].Spaces >=
430
403
               static_cast<int>(Changes[i].Tok->SpacesRequiredBefore) ||
431
403
           Changes[i].Tok->is(tok::eof));
432
433
0
    Changes[i].StartOfTokenColumn += Shift;
434
403
    if (i + 1 != Changes.size())
435
367
      Changes[i + 1].PreviousEndOfTokenColumn += Shift;
436
437
    // If PointerAlignment is PAS_Right, keep *s or &s next to the token
438
403
    if (Style.PointerAlignment == FormatStyle::PAS_Right &&
439
403
        Changes[i].Spaces != 0) {
440
225
      for (int Previous = i - 1;
441
225
           Previous >= 0 &&
442
225
           Changes[Previous].Tok->getType() == TT_PointerOrReference;
443
225
           
--Previous0
) {
444
0
        Changes[Previous + 1].Spaces -= Shift;
445
0
        Changes[Previous].Spaces += Shift;
446
0
        Changes[Previous].StartOfTokenColumn += Shift;
447
0
      }
448
225
    }
449
403
  }
450
36
}
WhitespaceManager.cpp:void clang::format::AlignTokenSequence<clang::format::WhitespaceManager::alignConsecutiveDeclarations()::$_3&>(clang::format::FormatStyle const&, unsigned int, unsigned int, unsigned int, bool, clang::format::WhitespaceManager::alignConsecutiveDeclarations()::$_3&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&)
Line
Count
Source
277
830
                   SmallVector<WhitespaceManager::Change, 16> &Changes) {
278
830
  bool FoundMatchOnLine = false;
279
830
  int Shift = 0;
280
281
  // ScopeStack keeps track of the current scope depth. It contains indices of
282
  // the first token on each scope.
283
  // We only run the "Matches" function on tokens from the outer-most scope.
284
  // However, we do need to pay special attention to one class of tokens
285
  // that are not in the outer-most scope, and that is function parameters
286
  // which are split across multiple lines, as illustrated by this example:
287
  //   double a(int x);
288
  //   int    b(int  y,
289
  //          double z);
290
  // In the above example, we need to take special care to ensure that
291
  // 'double z' is indented along with it's owning function 'b'.
292
  // The same holds for calling a function:
293
  //   double a = foo(x);
294
  //   int    b = bar(foo(y),
295
  //            foor(z));
296
  // Similar for broken string literals:
297
  //   double x = 3.14;
298
  //   auto s   = "Hello"
299
  //          "World";
300
  // Special handling is required for 'nested' ternary operators.
301
830
  SmallVector<unsigned, 16> ScopeStack;
302
303
13.9k
  for (unsigned i = Start; i != End; 
++i13.0k
) {
304
13.0k
    if (ScopeStack.size() != 0 &&
305
13.0k
        Changes[i].indentAndNestingLevel() <
306
6.26k
            Changes[ScopeStack.back()].indentAndNestingLevel())
307
1.06k
      ScopeStack.pop_back();
308
309
    // Compare current token to previous non-comment token to ensure whether
310
    // it is in a deeper scope or not.
311
13.0k
    unsigned PreviousNonComment = i - 1;
312
13.1k
    while (PreviousNonComment > Start &&
313
13.1k
           
Changes[PreviousNonComment].Tok->is(tok::comment)11.5k
)
314
94
      --PreviousNonComment;
315
13.0k
    if (i != Start && Changes[i].indentAndNestingLevel() >
316
12.2k
                          Changes[PreviousNonComment].indentAndNestingLevel())
317
1.16k
      ScopeStack.push_back(i);
318
319
13.0k
    bool InsideNestedScope = ScopeStack.size() != 0;
320
13.0k
    bool ContinuedStringLiteral = i > Start &&
321
13.0k
                                  
Changes[i].Tok->is(tok::string_literal)12.2k
&&
322
13.0k
                                  
Changes[i - 1].Tok->is(tok::string_literal)177
;
323
13.0k
    bool SkipMatchCheck = InsideNestedScope || 
ContinuedStringLiteral6.71k
;
324
325
13.0k
    if (Changes[i].NewlinesBefore > 0 && 
!SkipMatchCheck1.27k
) {
326
686
      Shift = 0;
327
686
      FoundMatchOnLine = false;
328
686
    }
329
330
    // If this is the first matching token to be aligned, remember by how many
331
    // spaces it has to be shifted, so the rest of the changes on the line are
332
    // shifted by the same amount
333
13.0k
    if (!FoundMatchOnLine && 
!SkipMatchCheck2.95k
&&
Matches(Changes[i])2.81k
) {
334
1.38k
      FoundMatchOnLine = true;
335
1.38k
      Shift = Column - (RightJustify ? 
Changes[i].TokenLength0
: 0) -
336
1.38k
              Changes[i].StartOfTokenColumn;
337
1.38k
      Changes[i].Spaces += Shift;
338
      // FIXME: This is a workaround that should be removed when we fix
339
      // http://llvm.org/PR53699. An assertion later below verifies this.
340
1.38k
      if (Changes[i].NewlinesBefore == 0)
341
1.38k
        Changes[i].Spaces =
342
1.38k
            std::max(Changes[i].Spaces,
343
1.38k
                     static_cast<int>(Changes[i].Tok->SpacesRequiredBefore));
344
1.38k
    }
345
346
    // This is for function parameters that are split across multiple lines,
347
    // as mentioned in the ScopeStack comment.
348
13.0k
    if (InsideNestedScope && 
Changes[i].NewlinesBefore > 06.36k
) {
349
577
      unsigned ScopeStart = ScopeStack.back();
350
577
      auto ShouldShiftBeAdded = [&] {
351
        // Function declaration
352
577
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
353
577
          return true;
354
355
        // Lambda.
356
577
        if (Changes[ScopeStart - 1].Tok->is(TT_LambdaLBrace))
357
577
          return false;
358
359
        // Continued function declaration
360
577
        if (ScopeStart > Start + 1 &&
361
577
            Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName))
362
577
          return true;
363
364
        // Continued function call
365
577
        if (ScopeStart > Start + 1 &&
366
577
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
367
577
            Changes[ScopeStart - 1].Tok->is(tok::l_paren) &&
368
577
            Changes[ScopeStart].Tok->isNot(TT_LambdaLSquare)) {
369
577
          if (Changes[i].Tok->MatchingParen &&
370
577
              Changes[i].Tok->MatchingParen->is(TT_LambdaLBrace))
371
577
            return false;
372
577
          if (Changes[ScopeStart].NewlinesBefore > 0)
373
577
            return false;
374
577
          if (Changes[i].Tok->is(tok::l_brace) &&
375
577
              Changes[i].Tok->is(BK_BracedInit))
376
577
            return true;
377
577
          return Style.BinPackArguments;
378
577
        }
379
380
        // Ternary operator
381
577
        if (Changes[i].Tok->is(TT_ConditionalExpr))
382
577
          return true;
383
384
        // Period Initializer .XXX = 1.
385
577
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
386
577
          return true;
387
388
        // Continued ternary operator
389
577
        if (Changes[i].Tok->Previous &&
390
577
            Changes[i].Tok->Previous->is(TT_ConditionalExpr))
391
577
          return true;
392
393
        // Continued direct-list-initialization using braced list.
394
577
        if (ScopeStart > Start + 1 &&
395
577
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
396
577
            Changes[ScopeStart - 1].Tok->is(tok::l_brace) &&
397
577
            Changes[i].Tok->is(tok::l_brace) &&
398
577
            Changes[i].Tok->is(BK_BracedInit))
399
577
          return true;
400
401
        // Continued braced list.
402
577
        if (ScopeStart > Start + 1 &&
403
577
            Changes[ScopeStart - 2].Tok->isNot(tok::identifier) &&
404
577
            Changes[ScopeStart - 1].Tok->is(tok::l_brace) &&
405
577
            Changes[i].Tok->isNot(tok::r_brace)) {
406
577
          for (unsigned OuterScopeStart : llvm::reverse(ScopeStack)) {
407
            // Lambda.
408
577
            if (OuterScopeStart > Start &&
409
577
                Changes[OuterScopeStart - 1].Tok->is(TT_LambdaLBrace))
410
577
              return false;
411
577
          }
412
577
          if (Changes[ScopeStart].NewlinesBefore > 0)
413
577
            return false;
414
577
          return true;
415
577
        }
416
417
577
        return false;
418
577
      };
419
420
577
      if (ShouldShiftBeAdded())
421
120
        Changes[i].Spaces += Shift;
422
577
    }
423
424
13.0k
    if (ContinuedStringLiteral)
425
27
      Changes[i].Spaces += Shift;
426
427
    // We should not remove required spaces unless we break the line before.
428
13.0k
    assert(Shift >= 0 || Changes[i].NewlinesBefore > 0 ||
429
13.0k
           Changes[i].Spaces >=
430
13.0k
               static_cast<int>(Changes[i].Tok->SpacesRequiredBefore) ||
431
13.0k
           Changes[i].Tok->is(tok::eof));
432
433
0
    Changes[i].StartOfTokenColumn += Shift;
434
13.0k
    if (i + 1 != Changes.size())
435
12.7k
      Changes[i + 1].PreviousEndOfTokenColumn += Shift;
436
437
    // If PointerAlignment is PAS_Right, keep *s or &s next to the token
438
13.0k
    if (Style.PointerAlignment == FormatStyle::PAS_Right &&
439
13.0k
        
Changes[i].Spaces != 09.43k
) {
440
4.76k
      for (int Previous = i - 1;
441
4.84k
           Previous >= 0 &&
442
4.84k
           Changes[Previous].Tok->getType() == TT_PointerOrReference;
443
4.76k
           
--Previous77
) {
444
77
        Changes[Previous + 1].Spaces -= Shift;
445
77
        Changes[Previous].Spaces += Shift;
446
77
        Changes[Previous].StartOfTokenColumn += Shift;
447
77
      }
448
4.76k
    }
449
13.0k
  }
450
830
}
WhitespaceManager.cpp:void clang::format::AlignTokenSequence<clang::format::WhitespaceManager::alignChainedConditionals()::$_4&>(clang::format::FormatStyle const&, unsigned int, unsigned int, unsigned int, bool, clang::format::WhitespaceManager::alignChainedConditionals()::$_4&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&)
Line
Count
Source
277
389
                   SmallVector<WhitespaceManager::Change, 16> &Changes) {
278
389
  bool FoundMatchOnLine = false;
279
389
  int Shift = 0;
280
281
  // ScopeStack keeps track of the current scope depth. It contains indices of
282
  // the first token on each scope.
283
  // We only run the "Matches" function on tokens from the outer-most scope.
284
  // However, we do need to pay special attention to one class of tokens
285
  // that are not in the outer-most scope, and that is function parameters
286
  // which are split across multiple lines, as illustrated by this example:
287
  //   double a(int x);
288
  //   int    b(int  y,
289
  //          double z);
290
  // In the above example, we need to take special care to ensure that
291
  // 'double z' is indented along with it's owning function 'b'.
292
  // The same holds for calling a function:
293
  //   double a = foo(x);
294
  //   int    b = bar(foo(y),
295
  //            foor(z));
296
  // Similar for broken string literals:
297
  //   double x = 3.14;
298
  //   auto s   = "Hello"
299
  //          "World";
300
  // Special handling is required for 'nested' ternary operators.
301
389
  SmallVector<unsigned, 16> ScopeStack;
302
303
2.41k
  for (unsigned i = Start; i != End; 
++i2.02k
) {
304
2.02k
    if (ScopeStack.size() != 0 &&
305
2.02k
        Changes[i].indentAndNestingLevel() <
306
427
            Changes[ScopeStack.back()].indentAndNestingLevel())
307
73
      ScopeStack.pop_back();
308
309
    // Compare current token to previous non-comment token to ensure whether
310
    // it is in a deeper scope or not.
311
2.02k
    unsigned PreviousNonComment = i - 1;
312
2.03k
    while (PreviousNonComment > Start &&
313
2.03k
           
Changes[PreviousNonComment].Tok->is(tok::comment)1.25k
)
314
9
      --PreviousNonComment;
315
2.02k
    if (i != Start && Changes[i].indentAndNestingLevel() >
316
1.63k
                          Changes[PreviousNonComment].indentAndNestingLevel())
317
94
      ScopeStack.push_back(i);
318
319
2.02k
    bool InsideNestedScope = ScopeStack.size() != 0;
320
2.02k
    bool ContinuedStringLiteral = i > Start &&
321
2.02k
                                  
Changes[i].Tok->is(tok::string_literal)1.63k
&&
322
2.02k
                                  
Changes[i - 1].Tok->is(tok::string_literal)20
;
323
2.02k
    bool SkipMatchCheck = InsideNestedScope || 
ContinuedStringLiteral1.57k
;
324
325
2.02k
    if (Changes[i].NewlinesBefore > 0 && 
!SkipMatchCheck394
) {
326
304
      Shift = 0;
327
304
      FoundMatchOnLine = false;
328
304
    }
329
330
    // If this is the first matching token to be aligned, remember by how many
331
    // spaces it has to be shifted, so the rest of the changes on the line are
332
    // shifted by the same amount
333
2.02k
    if (!FoundMatchOnLine && 
!SkipMatchCheck800
&&
Matches(Changes[i])800
) {
334
623
      FoundMatchOnLine = true;
335
623
      Shift = Column - (RightJustify ? 
Changes[i].TokenLength0
: 0) -
336
623
              Changes[i].StartOfTokenColumn;
337
623
      Changes[i].Spaces += Shift;
338
      // FIXME: This is a workaround that should be removed when we fix
339
      // http://llvm.org/PR53699. An assertion later below verifies this.
340
623
      if (Changes[i].NewlinesBefore == 0)
341
409
        Changes[i].Spaces =
342
409
            std::max(Changes[i].Spaces,
343
409
                     static_cast<int>(Changes[i].Tok->SpacesRequiredBefore));
344
623
    }
345
346
    // This is for function parameters that are split across multiple lines,
347
    // as mentioned in the ScopeStack comment.
348
2.02k
    if (InsideNestedScope && 
Changes[i].NewlinesBefore > 0448
) {
349
87
      unsigned ScopeStart = ScopeStack.back();
350
87
      auto ShouldShiftBeAdded = [&] {
351
        // Function declaration
352
87
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
353
87
          return true;
354
355
        // Lambda.
356
87
        if (Changes[ScopeStart - 1].Tok->is(TT_LambdaLBrace))
357
87
          return false;
358
359
        // Continued function declaration
360
87
        if (ScopeStart > Start + 1 &&
361
87
            Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName))
362
87
          return true;
363
364
        // Continued function call
365
87
        if (ScopeStart > Start + 1 &&
366
87
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
367
87
            Changes[ScopeStart - 1].Tok->is(tok::l_paren) &&
368
87
            Changes[ScopeStart].Tok->isNot(TT_LambdaLSquare)) {
369
87
          if (Changes[i].Tok->MatchingParen &&
370
87
              Changes[i].Tok->MatchingParen->is(TT_LambdaLBrace))
371
87
            return false;
372
87
          if (Changes[ScopeStart].NewlinesBefore > 0)
373
87
            return false;
374
87
          if (Changes[i].Tok->is(tok::l_brace) &&
375
87
              Changes[i].Tok->is(BK_BracedInit))
376
87
            return true;
377
87
          return Style.BinPackArguments;
378
87
        }
379
380
        // Ternary operator
381
87
        if (Changes[i].Tok->is(TT_ConditionalExpr))
382
87
          return true;
383
384
        // Period Initializer .XXX = 1.
385
87
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
386
87
          return true;
387
388
        // Continued ternary operator
389
87
        if (Changes[i].Tok->Previous &&
390
87
            Changes[i].Tok->Previous->is(TT_ConditionalExpr))
391
87
          return true;
392
393
        // Continued direct-list-initialization using braced list.
394
87
        if (ScopeStart > Start + 1 &&
395
87
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
396
87
            Changes[ScopeStart - 1].Tok->is(tok::l_brace) &&
397
87
            Changes[i].Tok->is(tok::l_brace) &&
398
87
            Changes[i].Tok->is(BK_BracedInit))
399
87
          return true;
400
401
        // Continued braced list.
402
87
        if (ScopeStart > Start + 1 &&
403
87
            Changes[ScopeStart - 2].Tok->isNot(tok::identifier) &&
404
87
            Changes[ScopeStart - 1].Tok->is(tok::l_brace) &&
405
87
            Changes[i].Tok->isNot(tok::r_brace)) {
406
87
          for (unsigned OuterScopeStart : llvm::reverse(ScopeStack)) {
407
            // Lambda.
408
87
            if (OuterScopeStart > Start &&
409
87
                Changes[OuterScopeStart - 1].Tok->is(TT_LambdaLBrace))
410
87
              return false;
411
87
          }
412
87
          if (Changes[ScopeStart].NewlinesBefore > 0)
413
87
            return false;
414
87
          return true;
415
87
        }
416
417
87
        return false;
418
87
      };
419
420
87
      if (ShouldShiftBeAdded())
421
72
        Changes[i].Spaces += Shift;
422
87
    }
423
424
2.02k
    if (ContinuedStringLiteral)
425
3
      Changes[i].Spaces += Shift;
426
427
    // We should not remove required spaces unless we break the line before.
428
2.02k
    assert(Shift >= 0 || Changes[i].NewlinesBefore > 0 ||
429
2.02k
           Changes[i].Spaces >=
430
2.02k
               static_cast<int>(Changes[i].Tok->SpacesRequiredBefore) ||
431
2.02k
           Changes[i].Tok->is(tok::eof));
432
433
0
    Changes[i].StartOfTokenColumn += Shift;
434
2.02k
    if (i + 1 != Changes.size())
435
2.02k
      Changes[i + 1].PreviousEndOfTokenColumn += Shift;
436
437
    // If PointerAlignment is PAS_Right, keep *s or &s next to the token
438
2.02k
    if (Style.PointerAlignment == FormatStyle::PAS_Right &&
439
2.02k
        
Changes[i].Spaces != 01.94k
) {
440
1.72k
      for (int Previous = i - 1;
441
1.72k
           Previous >= 0 &&
442
1.72k
           Changes[Previous].Tok->getType() == TT_PointerOrReference;
443
1.72k
           
--Previous0
) {
444
0
        Changes[Previous + 1].Spaces -= Shift;
445
0
        Changes[Previous].Spaces += Shift;
446
0
        Changes[Previous].StartOfTokenColumn += Shift;
447
0
      }
448
1.72k
    }
449
2.02k
  }
450
389
}
WhitespaceManager.cpp:void clang::format::AlignTokenSequence<clang::format::WhitespaceManager::alignChainedConditionals()::$_6&>(clang::format::FormatStyle const&, unsigned int, unsigned int, unsigned int, bool, clang::format::WhitespaceManager::alignChainedConditionals()::$_6&, llvm::SmallVector<clang::format::WhitespaceManager::Change, 16u>&)
Line
Count
Source
277
205
                   SmallVector<WhitespaceManager::Change, 16> &Changes) {
278
205
  bool FoundMatchOnLine = false;
279
205
  int Shift = 0;
280
281
  // ScopeStack keeps track of the current scope depth. It contains indices of
282
  // the first token on each scope.
283
  // We only run the "Matches" function on tokens from the outer-most scope.
284
  // However, we do need to pay special attention to one class of tokens
285
  // that are not in the outer-most scope, and that is function parameters
286
  // which are split across multiple lines, as illustrated by this example:
287
  //   double a(int x);
288
  //   int    b(int  y,
289
  //          double z);
290
  // In the above example, we need to take special care to ensure that
291
  // 'double z' is indented along with it's owning function 'b'.
292
  // The same holds for calling a function:
293
  //   double a = foo(x);
294
  //   int    b = bar(foo(y),
295
  //            foor(z));
296
  // Similar for broken string literals:
297
  //   double x = 3.14;
298
  //   auto s   = "Hello"
299
  //          "World";
300
  // Special handling is required for 'nested' ternary operators.
301
205
  SmallVector<unsigned, 16> ScopeStack;
302
303
1.60k
  for (unsigned i = Start; i != End; 
++i1.40k
) {
304
1.40k
    if (ScopeStack.size() != 0 &&
305
1.40k
        Changes[i].indentAndNestingLevel() <
306
332
            Changes[ScopeStack.back()].indentAndNestingLevel())
307
56
      ScopeStack.pop_back();
308
309
    // Compare current token to previous non-comment token to ensure whether
310
    // it is in a deeper scope or not.
311
1.40k
    unsigned PreviousNonComment = i - 1;
312
1.40k
    while (PreviousNonComment > Start &&
313
1.40k
           
Changes[PreviousNonComment].Tok->is(tok::comment)1.02k
)
314
3
      --PreviousNonComment;
315
1.40k
    if (i != Start && Changes[i].indentAndNestingLevel() >
316
1.19k
                          Changes[PreviousNonComment].indentAndNestingLevel())
317
73
      ScopeStack.push_back(i);
318
319
1.40k
    bool InsideNestedScope = ScopeStack.size() != 0;
320
1.40k
    bool ContinuedStringLiteral = i > Start &&
321
1.40k
                                  
Changes[i].Tok->is(tok::string_literal)1.19k
&&
322
1.40k
                                  
Changes[i - 1].Tok->is(tok::string_literal)10
;
323
1.40k
    bool SkipMatchCheck = InsideNestedScope || 
ContinuedStringLiteral1.05k
;
324
325
1.40k
    if (Changes[i].NewlinesBefore > 0 && 
!SkipMatchCheck318
) {
326
256
      Shift = 0;
327
256
      FoundMatchOnLine = false;
328
256
    }
329
330
    // If this is the first matching token to be aligned, remember by how many
331
    // spaces it has to be shifted, so the rest of the changes on the line are
332
    // shifted by the same amount
333
1.40k
    if (!FoundMatchOnLine && 
!SkipMatchCheck488
&&
Matches(Changes[i])488
) {
334
407
      FoundMatchOnLine = true;
335
407
      Shift = Column - (RightJustify ? 
Changes[i].TokenLength0
: 0) -
336
407
              Changes[i].StartOfTokenColumn;
337
407
      Changes[i].Spaces += Shift;
338
      // FIXME: This is a workaround that should be removed when we fix
339
      // http://llvm.org/PR53699. An assertion later below verifies this.
340
407
      if (Changes[i].NewlinesBefore == 0)
341
232
        Changes[i].Spaces =
342
232
            std::max(Changes[i].Spaces,
343
232
                     static_cast<int>(Changes[i].Tok->SpacesRequiredBefore));
344
407
    }
345
346
    // This is for function parameters that are split across multiple lines,
347
    // as mentioned in the ScopeStack comment.
348
1.40k
    if (InsideNestedScope && 
Changes[i].NewlinesBefore > 0349
) {
349
62
      unsigned ScopeStart = ScopeStack.back();
350
62
      auto ShouldShiftBeAdded = [&] {
351
        // Function declaration
352
62
        if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
353
62
          return true;
354
355
        // Lambda.
356
62
        if (Changes[ScopeStart - 1].Tok->is(TT_LambdaLBrace))
357
62
          return false;
358
359
        // Continued function declaration
360
62
        if (ScopeStart > Start + 1 &&
361
62
            Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName))
362
62
          return true;
363
364
        // Continued function call
365
62
        if (ScopeStart > Start + 1 &&
366
62
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
367
62
            Changes[ScopeStart - 1].Tok->is(tok::l_paren) &&
368
62
            Changes[ScopeStart].Tok->isNot(TT_LambdaLSquare)) {
369
62
          if (Changes[i].Tok->MatchingParen &&
370
62
              Changes[i].Tok->MatchingParen->is(TT_LambdaLBrace))
371
62
            return false;
372
62
          if (Changes[ScopeStart].NewlinesBefore > 0)
373
62
            return false;
374
62
          if (Changes[i].Tok->is(tok::l_brace) &&
375
62
              Changes[i].Tok->is(BK_BracedInit))
376
62
            return true;
377
62
          return Style.BinPackArguments;
378
62
        }
379
380
        // Ternary operator
381
62
        if (Changes[i].Tok->is(TT_ConditionalExpr))
382
62
          return true;
383
384
        // Period Initializer .XXX = 1.
385
62
        if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
386
62
          return true;
387
388
        // Continued ternary operator
389
62
        if (Changes[i].Tok->Previous &&
390
62
            Changes[i].Tok->Previous->is(TT_ConditionalExpr))
391
62
          return true;
392
393
        // Continued direct-list-initialization using braced list.
394
62
        if (ScopeStart > Start + 1 &&
395
62
            Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
396
62
            Changes[ScopeStart - 1].Tok->is(tok::l_brace) &&
397
62
            Changes[i].Tok->is(tok::l_brace) &&
398
62
            Changes[i].Tok->is(BK_BracedInit))
399
62
          return true;
400
401
        // Continued braced list.
402
62
        if (ScopeStart > Start + 1 &&
403
62
            Changes[ScopeStart - 2].Tok->isNot(tok::identifier) &&
404
62
            Changes[ScopeStart - 1].Tok->is(tok::l_brace) &&
405
62
            Changes[i].Tok->isNot(tok::r_brace)) {
406
62
          for (unsigned OuterScopeStart : llvm::reverse(ScopeStack)) {
407
            // Lambda.
408
62
            if (OuterScopeStart > Start &&
409
62
                Changes[OuterScopeStart - 1].Tok->is(TT_LambdaLBrace))
410
62
              return false;
411
62
          }
412
62
          if (Changes[ScopeStart].NewlinesBefore > 0)
413
62
            return false;
414
62
          return true;
415
62
        }
416
417
62
        return false;
418
62
      };
419
420
62
      if (ShouldShiftBeAdded())
421
48
        Changes[i].Spaces += Shift;
422
62
    }
423
424
1.40k
    if (ContinuedStringLiteral)
425
0
      Changes[i].Spaces += Shift;
426
427
    // We should not remove required spaces unless we break the line before.
428
1.40k
    assert(Shift >= 0 || Changes[i].NewlinesBefore > 0 ||
429
1.40k
           Changes[i].Spaces >=
430
1.40k
               static_cast<int>(Changes[i].Tok->SpacesRequiredBefore) ||
431
1.40k
           Changes[i].Tok->is(tok::eof));
432
433
0
    Changes[i].StartOfTokenColumn += Shift;
434
1.40k
    if (i + 1 != Changes.size())
435
1.40k
      Changes[i + 1].PreviousEndOfTokenColumn += Shift;
436
437
    // If PointerAlignment is PAS_Right, keep *s or &s next to the token
438
1.40k
    if (Style.PointerAlignment == FormatStyle::PAS_Right &&
439
1.40k
        
Changes[i].Spaces != 01.23k
) {
440
1.12k
      for (int Previous = i - 1;
441
1.12k
           Previous >= 0 &&
442
1.12k
           Changes[Previous].Tok->getType() == TT_PointerOrReference;
443
1.12k
           
--Previous0
) {
444
0
        Changes[Previous + 1].Spaces -= Shift;
445
0
        Changes[Previous].Spaces += Shift;
446
0
        Changes[Previous].StartOfTokenColumn += Shift;
447
0
      }
448
1.12k
    }
449
1.40k
  }
450
205
}
451
452
// Walk through a subset of the changes, starting at StartAt, and find
453
// sequences of matching tokens to align. To do so, keep track of the lines and
454
// whether or not a matching token was found on a line. If a matching token is
455
// found, extend the current sequence. If the current line cannot be part of a
456
// sequence, e.g. because there is an empty line before it or it contains only
457
// non-matching tokens, finalize the previous sequence.
458
// The value returned is the token on which we stopped, either because we
459
// exhausted all items inside Changes, or because we hit a scope level higher
460
// than our initial scope.
461
// This function is recursive. Each invocation processes only the scope level
462
// equal to the initial level, which is the level of Changes[StartAt].
463
// If we encounter a scope level greater than the initial level, then we call
464
// ourselves recursively, thereby avoiding the pollution of the current state
465
// with the alignment requirements of the nested sub-level. This recursive
466
// behavior is necessary for aligning function prototypes that have one or more
467
// arguments.
468
// If this function encounters a scope level less than the initial level,
469
// it returns the current position.
470
// There is a non-obvious subtlety in the recursive behavior: Even though we
471
// defer processing of nested levels to recursive invocations of this
472
// function, when it comes time to align a sequence of tokens, we run the
473
// alignment on the entire sequence, including the nested levels.
474
// When doing so, most of the nested tokens are skipped, because their
475
// alignment was already handled by the recursive invocations of this function.
476
// However, the special exception is that we do NOT skip function parameters
477
// that are split across multiple lines. See the test case in FormatTest.cpp
478
// that mentions "split function parameter alignment" for an example of this.
479
// When the parameter RightJustify is true, the operator will be
480
// right-justified. It is used to align compound assignments like `+=` and `=`.
481
// When RightJustify and ACS.PadOperators are true, operators in each block to
482
// be aligned will be padded on the left to the same length before aligning.
483
template <typename F>
484
static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,
485
                            SmallVector<WhitespaceManager::Change, 16> &Changes,
486
                            unsigned StartAt,
487
                            const FormatStyle::AlignConsecutiveStyle &ACS = {},
488
83.9k
                            bool RightJustify = false) {
489
  // We arrange each line in 3 parts. The operator to be aligned (the anchor),
490
  // and text to its left and right. In the aligned text the width of each part
491
  // will be the maximum of that over the block that has been aligned. Maximum
492
  // widths of each part so far. When RightJustify is true and ACS.PadOperators
493
  // is false, the part from start of line to the right end of the anchor.
494
  // Otherwise, only the part to the left of the anchor. Including the space
495
  // that exists on its left from the start. Not including the padding added on
496
  // the left to right-justify the anchor.
497
83.9k
  unsigned WidthLeft = 0;
498
  // The operator to be aligned when RightJustify is true and ACS.PadOperators
499
  // is false. 0 otherwise.
500
83.9k
  unsigned WidthAnchor = 0;
501
  // Width to the right of the anchor. Plus width of the anchor when
502
  // RightJustify is false.
503
83.9k
  unsigned WidthRight = 0;
504
505
  // Line number of the start and the end of the current token sequence.
506
83.9k
  unsigned StartOfSequence = 0;
507
83.9k
  unsigned EndOfSequence = 0;
508
509
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
510
  // abort when we hit any token in a higher scope than the starting one.
511
83.9k
  auto IndentAndNestingLevel = StartAt < Changes.size()
512
83.9k
                                   ? Changes[StartAt].indentAndNestingLevel()
513
83.9k
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
514
515
  // Keep track of the number of commas before the matching tokens, we will only
516
  // align a sequence of matching tokens if they are preceded by the same number
517
  // of commas.
518
83.9k
  unsigned CommasBeforeLastMatch = 0;
519
83.9k
  unsigned CommasBeforeMatch = 0;
520
521
  // Whether a matching token has been found on the current line.
522
83.9k
  bool FoundMatchOnLine = false;
523
524
  // Whether the current line consists purely of comments.
525
83.9k
  bool LineIsComment = true;
526
527
  // Aligns a sequence of matching tokens, on the MinColumn column.
528
  //
529
  // Sequences start from the first matching token to align, and end at the
530
  // first token of the first line that doesn't need to be aligned.
531
  //
532
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
533
  // containing any matching token to be aligned and located after such token.
534
148k
  auto AlignCurrentSequence = [&] {
535
148k
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence2.53k
)
536
2.16k
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
2.16k
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
2.16k
                         Changes);
539
148k
    WidthLeft = 0;
540
148k
    WidthAnchor = 0;
541
148k
    WidthRight = 0;
542
148k
    StartOfSequence = 0;
543
148k
    EndOfSequence = 0;
544
148k
  };
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&, bool)::'lambda'()::operator()() const
Line
Count
Source
534
1.36k
  auto AlignCurrentSequence = [&] {
535
1.36k
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence469
)
536
463
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
463
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
463
                         Changes);
539
1.36k
    WidthLeft = 0;
540
1.36k
    WidthAnchor = 0;
541
1.36k
    WidthRight = 0;
542
1.36k
    StartOfSequence = 0;
543
1.36k
    EndOfSequence = 0;
544
1.36k
  };
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&, bool)::'lambda'()::operator()() const
Line
Count
Source
534
2.48k
  auto AlignCurrentSequence = [&] {
535
2.48k
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence267
)
536
243
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
243
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
243
                         Changes);
539
2.48k
    WidthLeft = 0;
540
2.48k
    WidthAnchor = 0;
541
2.48k
    WidthRight = 0;
542
2.48k
    StartOfSequence = 0;
543
2.48k
    EndOfSequence = 0;
544
2.48k
  };
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&, bool)::'lambda'()::operator()() const
Line
Count
Source
534
36
  auto AlignCurrentSequence = [&] {
535
36
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
536
36
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
36
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
36
                         Changes);
539
36
    WidthLeft = 0;
540
36
    WidthAnchor = 0;
541
36
    WidthRight = 0;
542
36
    StartOfSequence = 0;
543
36
    EndOfSequence = 0;
544
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&, bool)::'lambda'()::operator()() const
Line
Count
Source
534
3
  auto AlignCurrentSequence = [&] {
535
3
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence0
)
536
0
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
0
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
0
                         Changes);
539
3
    WidthLeft = 0;
540
3
    WidthAnchor = 0;
541
3
    WidthRight = 0;
542
3
    StartOfSequence = 0;
543
3
    EndOfSequence = 0;
544
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&, bool)::'lambda'()::operator()() const
Line
Count
Source
534
1.13k
  auto AlignCurrentSequence = [&] {
535
1.13k
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence461
)
536
461
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
461
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
461
                         Changes);
539
1.13k
    WidthLeft = 0;
540
1.13k
    WidthAnchor = 0;
541
1.13k
    WidthRight = 0;
542
1.13k
    StartOfSequence = 0;
543
1.13k
    EndOfSequence = 0;
544
1.13k
  };
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&, bool)::'lambda'()::operator()() const
Line
Count
Source
534
2.61k
  auto AlignCurrentSequence = [&] {
535
2.61k
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence555
)
536
369
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
369
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
369
                         Changes);
539
2.61k
    WidthLeft = 0;
540
2.61k
    WidthAnchor = 0;
541
2.61k
    WidthRight = 0;
542
2.61k
    StartOfSequence = 0;
543
2.61k
    EndOfSequence = 0;
544
2.61k
  };
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&, bool)::'lambda'()::operator()() const
Line
Count
Source
534
52.4k
  auto AlignCurrentSequence = [&] {
535
52.4k
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence23
)
536
16
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
16
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
16
                         Changes);
539
52.4k
    WidthLeft = 0;
540
52.4k
    WidthAnchor = 0;
541
52.4k
    WidthRight = 0;
542
52.4k
    StartOfSequence = 0;
543
52.4k
    EndOfSequence = 0;
544
52.4k
  };
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&, bool)::'lambda'()::operator()() const
Line
Count
Source
534
80.4k
  auto AlignCurrentSequence = [&] {
535
80.4k
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence523
)
536
373
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
373
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
373
                         Changes);
539
80.4k
    WidthLeft = 0;
540
80.4k
    WidthAnchor = 0;
541
80.4k
    WidthRight = 0;
542
80.4k
    StartOfSequence = 0;
543
80.4k
    EndOfSequence = 0;
544
80.4k
  };
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&, bool)::'lambda'()::operator()() const
Line
Count
Source
534
3.19k
  auto AlignCurrentSequence = [&] {
535
3.19k
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence11
)
536
11
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
11
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
11
                         Changes);
539
3.19k
    WidthLeft = 0;
540
3.19k
    WidthAnchor = 0;
541
3.19k
    WidthRight = 0;
542
3.19k
    StartOfSequence = 0;
543
3.19k
    EndOfSequence = 0;
544
3.19k
  };
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&, bool)::'lambda'()::operator()() const
Line
Count
Source
534
4.95k
  auto AlignCurrentSequence = [&] {
535
4.95k
    if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence194
)
536
194
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
194
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
194
                         Changes);
539
4.95k
    WidthLeft = 0;
540
4.95k
    WidthAnchor = 0;
541
4.95k
    WidthRight = 0;
542
4.95k
    StartOfSequence = 0;
543
4.95k
    EndOfSequence = 0;
544
4.95k
  };
545
546
83.9k
  unsigned i = StartAt;
547
547k
  for (unsigned e = Changes.size(); i != e; 
++i463k
) {
548
524k
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
549
60.3k
      break;
550
551
463k
    if (Changes[i].NewlinesBefore != 0) {
552
66.6k
      CommasBeforeMatch = 0;
553
66.6k
      EndOfSequence = i;
554
555
      // Whether to break the alignment sequence because of an empty line.
556
66.6k
      bool EmptyLineBreak =
557
66.6k
          (Changes[i].NewlinesBefore > 1) && 
!ACS.AcrossEmptyLines1.43k
;
558
559
      // Whether to break the alignment sequence because of a line without a
560
      // match.
561
66.6k
      bool NoMatchBreak =
562
66.6k
          !FoundMatchOnLine && 
!(64.3k
LineIsComment64.3k
&&
ACS.AcrossComments17.0k
);
563
564
66.6k
      if (EmptyLineBreak || 
NoMatchBreak65.2k
)
565
64.3k
        AlignCurrentSequence();
566
567
      // A new line starts, re-initialize line status tracking bools.
568
      // Keep the match state if a string literal is continued on this line.
569
66.6k
      if (i == 0 || 
!Changes[i].Tok->is(tok::string_literal)65.9k
||
570
66.6k
          
!Changes[i - 1].Tok->is(tok::string_literal)1.07k
)
571
66.2k
        FoundMatchOnLine = false;
572
66.6k
      LineIsComment = true;
573
66.6k
    }
574
575
463k
    if (!Changes[i].Tok->is(tok::comment))
576
455k
      LineIsComment = false;
577
578
463k
    if (Changes[i].Tok->is(tok::comma)) {
579
14.0k
      ++CommasBeforeMatch;
580
449k
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
581
      // Call AlignTokens recursively, skipping over this scope block.
582
60.4k
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
583
60.4k
      i = StoppedAt - 1;
584
60.4k
      continue;
585
60.4k
    }
586
587
403k
    if (!Matches(Changes[i]))
588
399k
      continue;
589
590
    // If there is more than one matching token per line, or if the number of
591
    // preceding commas, do not match anymore, end the sequence.
592
4.07k
    if (FoundMatchOnLine || 
CommasBeforeMatch != CommasBeforeLastMatch3.68k
)
593
446
      AlignCurrentSequence();
594
595
4.07k
    CommasBeforeLastMatch = CommasBeforeMatch;
596
4.07k
    FoundMatchOnLine = true;
597
598
4.07k
    if (StartOfSequence == 0)
599
2.52k
      StartOfSequence = i;
600
601
4.07k
    unsigned ChangeWidthLeft = Changes[i].StartOfTokenColumn;
602
4.07k
    unsigned ChangeWidthAnchor = 0;
603
4.07k
    unsigned ChangeWidthRight = 0;
604
4.07k
    if (RightJustify) {
605
779
      if (ACS.PadOperators)
606
746
        ChangeWidthAnchor = Changes[i].TokenLength;
607
33
      else
608
33
        ChangeWidthLeft += Changes[i].TokenLength;
609
779
    } else
610
3.29k
      ChangeWidthRight = Changes[i].TokenLength;
611
21.1k
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 019.9k
;
++j17.1k
) {
612
17.1k
      ChangeWidthRight += Changes[j].Spaces;
613
      // Changes are generally 1:1 with the tokens, but a change could also be
614
      // inside of a token, in which case it's counted more than once: once for
615
      // the whitespace surrounding the token (!IsInsideToken) and once for
616
      // each whitespace change within it (IsInsideToken).
617
      // Therefore, changes inside of a token should only count the space.
618
17.1k
      if (!Changes[j].IsInsideToken)
619
17.1k
        ChangeWidthRight += Changes[j].TokenLength;
620
17.1k
    }
621
622
    // If we are restricted by the maximum column width, end the sequence.
623
4.07k
    unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
624
4.07k
    unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
625
4.07k
    unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
626
    // `ColumnLimit == 0` means there is no column limit.
627
4.07k
    if (Style.ColumnLimit != 0 &&
628
4.07k
        
Style.ColumnLimit < NewLeft + NewAnchor + NewRight4.06k
) {
629
15
      AlignCurrentSequence();
630
15
      StartOfSequence = i;
631
15
      WidthLeft = ChangeWidthLeft;
632
15
      WidthAnchor = ChangeWidthAnchor;
633
15
      WidthRight = ChangeWidthRight;
634
4.06k
    } else {
635
4.06k
      WidthLeft = NewLeft;
636
4.06k
      WidthAnchor = NewAnchor;
637
4.06k
      WidthRight = NewRight;
638
4.06k
    }
639
4.07k
  }
640
641
83.9k
  EndOfSequence = i;
642
83.9k
  AlignCurrentSequence();
643
83.9k
  return i;
644
83.9k
}
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&, bool)
Line
Count
Source
488
594
                            bool RightJustify = false) {
489
  // We arrange each line in 3 parts. The operator to be aligned (the anchor),
490
  // and text to its left and right. In the aligned text the width of each part
491
  // will be the maximum of that over the block that has been aligned. Maximum
492
  // widths of each part so far. When RightJustify is true and ACS.PadOperators
493
  // is false, the part from start of line to the right end of the anchor.
494
  // Otherwise, only the part to the left of the anchor. Including the space
495
  // that exists on its left from the start. Not including the padding added on
496
  // the left to right-justify the anchor.
497
594
  unsigned WidthLeft = 0;
498
  // The operator to be aligned when RightJustify is true and ACS.PadOperators
499
  // is false. 0 otherwise.
500
594
  unsigned WidthAnchor = 0;
501
  // Width to the right of the anchor. Plus width of the anchor when
502
  // RightJustify is false.
503
594
  unsigned WidthRight = 0;
504
505
  // Line number of the start and the end of the current token sequence.
506
594
  unsigned StartOfSequence = 0;
507
594
  unsigned EndOfSequence = 0;
508
509
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
510
  // abort when we hit any token in a higher scope than the starting one.
511
594
  auto IndentAndNestingLevel = StartAt < Changes.size()
512
594
                                   ? Changes[StartAt].indentAndNestingLevel()
513
594
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
514
515
  // Keep track of the number of commas before the matching tokens, we will only
516
  // align a sequence of matching tokens if they are preceded by the same number
517
  // of commas.
518
594
  unsigned CommasBeforeLastMatch = 0;
519
594
  unsigned CommasBeforeMatch = 0;
520
521
  // Whether a matching token has been found on the current line.
522
594
  bool FoundMatchOnLine = false;
523
524
  // Whether the current line consists purely of comments.
525
594
  bool LineIsComment = true;
526
527
  // Aligns a sequence of matching tokens, on the MinColumn column.
528
  //
529
  // Sequences start from the first matching token to align, and end at the
530
  // first token of the first line that doesn't need to be aligned.
531
  //
532
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
533
  // containing any matching token to be aligned and located after such token.
534
594
  auto AlignCurrentSequence = [&] {
535
594
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
536
594
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
594
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
594
                         Changes);
539
594
    WidthLeft = 0;
540
594
    WidthAnchor = 0;
541
594
    WidthRight = 0;
542
594
    StartOfSequence = 0;
543
594
    EndOfSequence = 0;
544
594
  };
545
546
594
  unsigned i = StartAt;
547
8.29k
  for (unsigned e = Changes.size(); i != e; 
++i7.69k
) {
548
7.69k
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
549
0
      break;
550
551
7.69k
    if (Changes[i].NewlinesBefore != 0) {
552
1.29k
      CommasBeforeMatch = 0;
553
1.29k
      EndOfSequence = i;
554
555
      // Whether to break the alignment sequence because of an empty line.
556
1.29k
      bool EmptyLineBreak =
557
1.29k
          (Changes[i].NewlinesBefore > 1) && 
!ACS.AcrossEmptyLines35
;
558
559
      // Whether to break the alignment sequence because of a line without a
560
      // match.
561
1.29k
      bool NoMatchBreak =
562
1.29k
          !FoundMatchOnLine && 
!(722
LineIsComment722
&&
ACS.AcrossComments56
);
563
564
1.29k
      if (EmptyLineBreak || 
NoMatchBreak1.28k
)
565
707
        AlignCurrentSequence();
566
567
      // A new line starts, re-initialize line status tracking bools.
568
      // Keep the match state if a string literal is continued on this line.
569
1.29k
      if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
570
1.29k
          
!Changes[i - 1].Tok->is(tok::string_literal)18
)
571
1.29k
        FoundMatchOnLine = false;
572
1.29k
      LineIsComment = true;
573
1.29k
    }
574
575
7.69k
    if (!Changes[i].Tok->is(tok::comment))
576
7.59k
      LineIsComment = false;
577
578
7.69k
    if (Changes[i].Tok->is(tok::comma)) {
579
30
      ++CommasBeforeMatch;
580
7.66k
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
581
      // Call AlignTokens recursively, skipping over this scope block.
582
848
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
583
848
      i = StoppedAt - 1;
584
848
      continue;
585
848
    }
586
587
6.85k
    if (!Matches(Changes[i]))
588
6.07k
      continue;
589
590
    // If there is more than one matching token per line, or if the number of
591
    // preceding commas, do not match anymore, end the sequence.
592
779
    if (FoundMatchOnLine || 
CommasBeforeMatch != CommasBeforeLastMatch758
)
593
54
      AlignCurrentSequence();
594
595
779
    CommasBeforeLastMatch = CommasBeforeMatch;
596
779
    FoundMatchOnLine = true;
597
598
779
    if (StartOfSequence == 0)
599
463
      StartOfSequence = i;
600
601
779
    unsigned ChangeWidthLeft = Changes[i].StartOfTokenColumn;
602
779
    unsigned ChangeWidthAnchor = 0;
603
779
    unsigned ChangeWidthRight = 0;
604
779
    if (RightJustify) {
605
779
      if (ACS.PadOperators)
606
746
        ChangeWidthAnchor = Changes[i].TokenLength;
607
33
      else
608
33
        ChangeWidthLeft += Changes[i].TokenLength;
609
779
    } else
610
0
      ChangeWidthRight = Changes[i].TokenLength;
611
2.86k
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 02.69k
;
++j2.08k
) {
612
2.08k
      ChangeWidthRight += Changes[j].Spaces;
613
      // Changes are generally 1:1 with the tokens, but a change could also be
614
      // inside of a token, in which case it's counted more than once: once for
615
      // the whitespace surrounding the token (!IsInsideToken) and once for
616
      // each whitespace change within it (IsInsideToken).
617
      // Therefore, changes inside of a token should only count the space.
618
2.08k
      if (!Changes[j].IsInsideToken)
619
2.08k
        ChangeWidthRight += Changes[j].TokenLength;
620
2.08k
    }
621
622
    // If we are restricted by the maximum column width, end the sequence.
623
779
    unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
624
779
    unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
625
779
    unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
626
    // `ColumnLimit == 0` means there is no column limit.
627
779
    if (Style.ColumnLimit != 0 &&
628
779
        
Style.ColumnLimit < NewLeft + NewAnchor + NewRight778
) {
629
6
      AlignCurrentSequence();
630
6
      StartOfSequence = i;
631
6
      WidthLeft = ChangeWidthLeft;
632
6
      WidthAnchor = ChangeWidthAnchor;
633
6
      WidthRight = ChangeWidthRight;
634
773
    } else {
635
773
      WidthLeft = NewLeft;
636
773
      WidthAnchor = NewAnchor;
637
773
      WidthRight = NewRight;
638
773
    }
639
779
  }
640
641
594
  EndOfSequence = i;
642
594
  AlignCurrentSequence();
643
594
  return i;
644
594
}
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&, bool)
Line
Count
Source
488
1.67k
                            bool RightJustify = false) {
489
  // We arrange each line in 3 parts. The operator to be aligned (the anchor),
490
  // and text to its left and right. In the aligned text the width of each part
491
  // will be the maximum of that over the block that has been aligned. Maximum
492
  // widths of each part so far. When RightJustify is true and ACS.PadOperators
493
  // is false, the part from start of line to the right end of the anchor.
494
  // Otherwise, only the part to the left of the anchor. Including the space
495
  // that exists on its left from the start. Not including the padding added on
496
  // the left to right-justify the anchor.
497
1.67k
  unsigned WidthLeft = 0;
498
  // The operator to be aligned when RightJustify is true and ACS.PadOperators
499
  // is false. 0 otherwise.
500
1.67k
  unsigned WidthAnchor = 0;
501
  // Width to the right of the anchor. Plus width of the anchor when
502
  // RightJustify is false.
503
1.67k
  unsigned WidthRight = 0;
504
505
  // Line number of the start and the end of the current token sequence.
506
1.67k
  unsigned StartOfSequence = 0;
507
1.67k
  unsigned EndOfSequence = 0;
508
509
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
510
  // abort when we hit any token in a higher scope than the starting one.
511
1.67k
  auto IndentAndNestingLevel = StartAt < Changes.size()
512
1.67k
                                   ? Changes[StartAt].indentAndNestingLevel()
513
1.67k
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
514
515
  // Keep track of the number of commas before the matching tokens, we will only
516
  // align a sequence of matching tokens if they are preceded by the same number
517
  // of commas.
518
1.67k
  unsigned CommasBeforeLastMatch = 0;
519
1.67k
  unsigned CommasBeforeMatch = 0;
520
521
  // Whether a matching token has been found on the current line.
522
1.67k
  bool FoundMatchOnLine = false;
523
524
  // Whether the current line consists purely of comments.
525
1.67k
  bool LineIsComment = true;
526
527
  // Aligns a sequence of matching tokens, on the MinColumn column.
528
  //
529
  // Sequences start from the first matching token to align, and end at the
530
  // first token of the first line that doesn't need to be aligned.
531
  //
532
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
533
  // containing any matching token to be aligned and located after such token.
534
1.67k
  auto AlignCurrentSequence = [&] {
535
1.67k
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
536
1.67k
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
1.67k
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
1.67k
                         Changes);
539
1.67k
    WidthLeft = 0;
540
1.67k
    WidthAnchor = 0;
541
1.67k
    WidthRight = 0;
542
1.67k
    StartOfSequence = 0;
543
1.67k
    EndOfSequence = 0;
544
1.67k
  };
545
546
1.67k
  unsigned i = StartAt;
547
10.3k
  for (unsigned e = Changes.size(); i != e; 
++i8.65k
) {
548
10.3k
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
549
1.65k
      break;
550
551
8.65k
    if (Changes[i].NewlinesBefore != 0) {
552
1.11k
      CommasBeforeMatch = 0;
553
1.11k
      EndOfSequence = i;
554
555
      // Whether to break the alignment sequence because of an empty line.
556
1.11k
      bool EmptyLineBreak =
557
1.11k
          (Changes[i].NewlinesBefore > 1) && 
!ACS.AcrossEmptyLines6
;
558
559
      // Whether to break the alignment sequence because of a line without a
560
      // match.
561
1.11k
      bool NoMatchBreak =
562
1.11k
          !FoundMatchOnLine && 
!(801
LineIsComment801
&&
ACS.AcrossComments410
);
563
564
1.11k
      if (EmptyLineBreak || 
NoMatchBreak1.10k
)
565
774
        AlignCurrentSequence();
566
567
      // A new line starts, re-initialize line status tracking bools.
568
      // Keep the match state if a string literal is continued on this line.
569
1.11k
      if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
570
1.11k
          
!Changes[i - 1].Tok->is(tok::string_literal)79
)
571
1.06k
        FoundMatchOnLine = false;
572
1.11k
      LineIsComment = true;
573
1.11k
    }
574
575
8.65k
    if (!Changes[i].Tok->is(tok::comment))
576
8.54k
      LineIsComment = false;
577
578
8.65k
    if (Changes[i].Tok->is(tok::comma)) {
579
1.00k
      ++CommasBeforeMatch;
580
7.64k
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
581
      // Call AlignTokens recursively, skipping over this scope block.
582
823
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
583
823
      i = StoppedAt - 1;
584
823
      continue;
585
823
    }
586
587
7.83k
    if (!Matches(Changes[i]))
588
7.36k
      continue;
589
590
    // If there is more than one matching token per line, or if the number of
591
    // preceding commas, do not match anymore, end the sequence.
592
468
    if (FoundMatchOnLine || 
CommasBeforeMatch != CommasBeforeLastMatch444
)
593
42
      AlignCurrentSequence();
594
595
468
    CommasBeforeLastMatch = CommasBeforeMatch;
596
468
    FoundMatchOnLine = true;
597
598
468
    if (StartOfSequence == 0)
599
267
      StartOfSequence = i;
600
601
468
    unsigned ChangeWidthLeft = Changes[i].StartOfTokenColumn;
602
468
    unsigned ChangeWidthAnchor = 0;
603
468
    unsigned ChangeWidthRight = 0;
604
468
    if (RightJustify) {
605
0
      if (ACS.PadOperators)
606
0
        ChangeWidthAnchor = Changes[i].TokenLength;
607
0
      else
608
0
        ChangeWidthLeft += Changes[i].TokenLength;
609
0
    } else
610
468
      ChangeWidthRight = Changes[i].TokenLength;
611
2.27k
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 02.25k
;
++j1.80k
) {
612
1.80k
      ChangeWidthRight += Changes[j].Spaces;
613
      // Changes are generally 1:1 with the tokens, but a change could also be
614
      // inside of a token, in which case it's counted more than once: once for
615
      // the whitespace surrounding the token (!IsInsideToken) and once for
616
      // each whitespace change within it (IsInsideToken).
617
      // Therefore, changes inside of a token should only count the space.
618
1.80k
      if (!Changes[j].IsInsideToken)
619
1.80k
        ChangeWidthRight += Changes[j].TokenLength;
620
1.80k
    }
621
622
    // If we are restricted by the maximum column width, end the sequence.
623
468
    unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
624
468
    unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
625
468
    unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
626
    // `ColumnLimit == 0` means there is no column limit.
627
468
    if (Style.ColumnLimit != 0 &&
628
468
        Style.ColumnLimit < NewLeft + NewAnchor + NewRight) {
629
0
      AlignCurrentSequence();
630
0
      StartOfSequence = i;
631
0
      WidthLeft = ChangeWidthLeft;
632
0
      WidthAnchor = ChangeWidthAnchor;
633
0
      WidthRight = ChangeWidthRight;
634
468
    } else {
635
468
      WidthLeft = NewLeft;
636
468
      WidthAnchor = NewAnchor;
637
468
      WidthRight = NewRight;
638
468
    }
639
468
  }
640
641
1.67k
  EndOfSequence = i;
642
1.67k
  AlignCurrentSequence();
643
1.67k
  return i;
644
1.67k
}
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&, bool)
Line
Count
Source
488
36
                            bool RightJustify = false) {
489
  // We arrange each line in 3 parts. The operator to be aligned (the anchor),
490
  // and text to its left and right. In the aligned text the width of each part
491
  // will be the maximum of that over the block that has been aligned. Maximum
492
  // widths of each part so far. When RightJustify is true and ACS.PadOperators
493
  // is false, the part from start of line to the right end of the anchor.
494
  // Otherwise, only the part to the left of the anchor. Including the space
495
  // that exists on its left from the start. Not including the padding added on
496
  // the left to right-justify the anchor.
497
36
  unsigned WidthLeft = 0;
498
  // The operator to be aligned when RightJustify is true and ACS.PadOperators
499
  // is false. 0 otherwise.
500
36
  unsigned WidthAnchor = 0;
501
  // Width to the right of the anchor. Plus width of the anchor when
502
  // RightJustify is false.
503
36
  unsigned WidthRight = 0;
504
505
  // Line number of the start and the end of the current token sequence.
506
36
  unsigned StartOfSequence = 0;
507
36
  unsigned EndOfSequence = 0;
508
509
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
510
  // abort when we hit any token in a higher scope than the starting one.
511
36
  auto IndentAndNestingLevel = StartAt < Changes.size()
512
36
                                   ? Changes[StartAt].indentAndNestingLevel()
513
36
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
514
515
  // Keep track of the number of commas before the matching tokens, we will only
516
  // align a sequence of matching tokens if they are preceded by the same number
517
  // of commas.
518
36
  unsigned CommasBeforeLastMatch = 0;
519
36
  unsigned CommasBeforeMatch = 0;
520
521
  // Whether a matching token has been found on the current line.
522
36
  bool FoundMatchOnLine = false;
523
524
  // Whether the current line consists purely of comments.
525
36
  bool LineIsComment = true;
526
527
  // Aligns a sequence of matching tokens, on the MinColumn column.
528
  //
529
  // Sequences start from the first matching token to align, and end at the
530
  // first token of the first line that doesn't need to be aligned.
531
  //
532
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
533
  // containing any matching token to be aligned and located after such token.
534
36
  auto AlignCurrentSequence = [&] {
535
36
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
536
36
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
36
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
36
                         Changes);
539
36
    WidthLeft = 0;
540
36
    WidthAnchor = 0;
541
36
    WidthRight = 0;
542
36
    StartOfSequence = 0;
543
36
    EndOfSequence = 0;
544
36
  };
545
546
36
  unsigned i = StartAt;
547
538
  for (unsigned e = Changes.size(); i != e; 
++i502
) {
548
502
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
549
0
      break;
550
551
502
    if (Changes[i].NewlinesBefore != 0) {
552
43
      CommasBeforeMatch = 0;
553
43
      EndOfSequence = i;
554
555
      // Whether to break the alignment sequence because of an empty line.
556
43
      bool EmptyLineBreak =
557
43
          (Changes[i].NewlinesBefore > 1) && 
!ACS.AcrossEmptyLines5
;
558
559
      // Whether to break the alignment sequence because of a line without a
560
      // match.
561
43
      bool NoMatchBreak =
562
43
          !FoundMatchOnLine && 
!(4
LineIsComment4
&&
ACS.AcrossComments4
);
563
564
43
      if (EmptyLineBreak || NoMatchBreak)
565
0
        AlignCurrentSequence();
566
567
      // A new line starts, re-initialize line status tracking bools.
568
      // Keep the match state if a string literal is continued on this line.
569
43
      if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
570
43
          
!Changes[i - 1].Tok->is(tok::string_literal)0
)
571
43
        FoundMatchOnLine = false;
572
43
      LineIsComment = true;
573
43
    }
574
575
502
    if (!Changes[i].Tok->is(tok::comment))
576
492
      LineIsComment = false;
577
578
502
    if (Changes[i].Tok->is(tok::comma)) {
579
0
      ++CommasBeforeMatch;
580
502
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
581
      // Call AlignTokens recursively, skipping over this scope block.
582
3
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
583
3
      i = StoppedAt - 1;
584
3
      continue;
585
3
    }
586
587
499
    if (!Matches(Changes[i]))
588
424
      continue;
589
590
    // If there is more than one matching token per line, or if the number of
591
    // preceding commas, do not match anymore, end the sequence.
592
75
    if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch)
593
0
      AlignCurrentSequence();
594
595
75
    CommasBeforeLastMatch = CommasBeforeMatch;
596
75
    FoundMatchOnLine = true;
597
598
75
    if (StartOfSequence == 0)
599
36
      StartOfSequence = i;
600
601
75
    unsigned ChangeWidthLeft = Changes[i].StartOfTokenColumn;
602
75
    unsigned ChangeWidthAnchor = 0;
603
75
    unsigned ChangeWidthRight = 0;
604
75
    if (RightJustify) {
605
0
      if (ACS.PadOperators)
606
0
        ChangeWidthAnchor = Changes[i].TokenLength;
607
0
      else
608
0
        ChangeWidthLeft += Changes[i].TokenLength;
609
0
    } else
610
75
      ChangeWidthRight = Changes[i].TokenLength;
611
321
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 0285
;
++j246
) {
612
246
      ChangeWidthRight += Changes[j].Spaces;
613
      // Changes are generally 1:1 with the tokens, but a change could also be
614
      // inside of a token, in which case it's counted more than once: once for
615
      // the whitespace surrounding the token (!IsInsideToken) and once for
616
      // each whitespace change within it (IsInsideToken).
617
      // Therefore, changes inside of a token should only count the space.
618
246
      if (!Changes[j].IsInsideToken)
619
246
        ChangeWidthRight += Changes[j].TokenLength;
620
246
    }
621
622
    // If we are restricted by the maximum column width, end the sequence.
623
75
    unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
624
75
    unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
625
75
    unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
626
    // `ColumnLimit == 0` means there is no column limit.
627
75
    if (Style.ColumnLimit != 0 &&
628
75
        Style.ColumnLimit < NewLeft + NewAnchor + NewRight) {
629
0
      AlignCurrentSequence();
630
0
      StartOfSequence = i;
631
0
      WidthLeft = ChangeWidthLeft;
632
0
      WidthAnchor = ChangeWidthAnchor;
633
0
      WidthRight = ChangeWidthRight;
634
75
    } else {
635
75
      WidthLeft = NewLeft;
636
75
      WidthAnchor = NewAnchor;
637
75
      WidthRight = NewRight;
638
75
    }
639
75
  }
640
641
36
  EndOfSequence = i;
642
36
  AlignCurrentSequence();
643
36
  return i;
644
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&, bool)
Line
Count
Source
488
3
                            bool RightJustify = false) {
489
  // We arrange each line in 3 parts. The operator to be aligned (the anchor),
490
  // and text to its left and right. In the aligned text the width of each part
491
  // will be the maximum of that over the block that has been aligned. Maximum
492
  // widths of each part so far. When RightJustify is true and ACS.PadOperators
493
  // is false, the part from start of line to the right end of the anchor.
494
  // Otherwise, only the part to the left of the anchor. Including the space
495
  // that exists on its left from the start. Not including the padding added on
496
  // the left to right-justify the anchor.
497
3
  unsigned WidthLeft = 0;
498
  // The operator to be aligned when RightJustify is true and ACS.PadOperators
499
  // is false. 0 otherwise.
500
3
  unsigned WidthAnchor = 0;
501
  // Width to the right of the anchor. Plus width of the anchor when
502
  // RightJustify is false.
503
3
  unsigned WidthRight = 0;
504
505
  // Line number of the start and the end of the current token sequence.
506
3
  unsigned StartOfSequence = 0;
507
3
  unsigned EndOfSequence = 0;
508
509
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
510
  // abort when we hit any token in a higher scope than the starting one.
511
3
  auto IndentAndNestingLevel = StartAt < Changes.size()
512
3
                                   ? Changes[StartAt].indentAndNestingLevel()
513
3
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
514
515
  // Keep track of the number of commas before the matching tokens, we will only
516
  // align a sequence of matching tokens if they are preceded by the same number
517
  // of commas.
518
3
  unsigned CommasBeforeLastMatch = 0;
519
3
  unsigned CommasBeforeMatch = 0;
520
521
  // Whether a matching token has been found on the current line.
522
3
  bool FoundMatchOnLine = false;
523
524
  // Whether the current line consists purely of comments.
525
3
  bool LineIsComment = true;
526
527
  // Aligns a sequence of matching tokens, on the MinColumn column.
528
  //
529
  // Sequences start from the first matching token to align, and end at the
530
  // first token of the first line that doesn't need to be aligned.
531
  //
532
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
533
  // containing any matching token to be aligned and located after such token.
534
3
  auto AlignCurrentSequence = [&] {
535
3
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
536
3
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
3
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
3
                         Changes);
539
3
    WidthLeft = 0;
540
3
    WidthAnchor = 0;
541
3
    WidthRight = 0;
542
3
    StartOfSequence = 0;
543
3
    EndOfSequence = 0;
544
3
  };
545
546
3
  unsigned i = StartAt;
547
9
  for (unsigned e = Changes.size(); i != e; 
++i6
) {
548
9
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
549
3
      break;
550
551
6
    if (Changes[i].NewlinesBefore != 0) {
552
0
      CommasBeforeMatch = 0;
553
0
      EndOfSequence = i;
554
555
      // Whether to break the alignment sequence because of an empty line.
556
0
      bool EmptyLineBreak =
557
0
          (Changes[i].NewlinesBefore > 1) && !ACS.AcrossEmptyLines;
558
559
      // Whether to break the alignment sequence because of a line without a
560
      // match.
561
0
      bool NoMatchBreak =
562
0
          !FoundMatchOnLine && !(LineIsComment && ACS.AcrossComments);
563
564
0
      if (EmptyLineBreak || NoMatchBreak)
565
0
        AlignCurrentSequence();
566
567
      // A new line starts, re-initialize line status tracking bools.
568
      // Keep the match state if a string literal is continued on this line.
569
0
      if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
570
0
          !Changes[i - 1].Tok->is(tok::string_literal))
571
0
        FoundMatchOnLine = false;
572
0
      LineIsComment = true;
573
0
    }
574
575
6
    if (!Changes[i].Tok->is(tok::comment))
576
6
      LineIsComment = false;
577
578
6
    if (Changes[i].Tok->is(tok::comma)) {
579
0
      ++CommasBeforeMatch;
580
6
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
581
      // Call AlignTokens recursively, skipping over this scope block.
582
0
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
583
0
      i = StoppedAt - 1;
584
0
      continue;
585
0
    }
586
587
6
    if (!Matches(Changes[i]))
588
6
      continue;
589
590
    // If there is more than one matching token per line, or if the number of
591
    // preceding commas, do not match anymore, end the sequence.
592
0
    if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch)
593
0
      AlignCurrentSequence();
594
595
0
    CommasBeforeLastMatch = CommasBeforeMatch;
596
0
    FoundMatchOnLine = true;
597
598
0
    if (StartOfSequence == 0)
599
0
      StartOfSequence = i;
600
601
0
    unsigned ChangeWidthLeft = Changes[i].StartOfTokenColumn;
602
0
    unsigned ChangeWidthAnchor = 0;
603
0
    unsigned ChangeWidthRight = 0;
604
0
    if (RightJustify) {
605
0
      if (ACS.PadOperators)
606
0
        ChangeWidthAnchor = Changes[i].TokenLength;
607
0
      else
608
0
        ChangeWidthLeft += Changes[i].TokenLength;
609
0
    } else
610
0
      ChangeWidthRight = Changes[i].TokenLength;
611
0
    for (unsigned j = i + 1; j != e && Changes[j].NewlinesBefore == 0; ++j) {
612
0
      ChangeWidthRight += Changes[j].Spaces;
613
      // Changes are generally 1:1 with the tokens, but a change could also be
614
      // inside of a token, in which case it's counted more than once: once for
615
      // the whitespace surrounding the token (!IsInsideToken) and once for
616
      // each whitespace change within it (IsInsideToken).
617
      // Therefore, changes inside of a token should only count the space.
618
0
      if (!Changes[j].IsInsideToken)
619
0
        ChangeWidthRight += Changes[j].TokenLength;
620
0
    }
621
622
    // If we are restricted by the maximum column width, end the sequence.
623
0
    unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
624
0
    unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
625
0
    unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
626
    // `ColumnLimit == 0` means there is no column limit.
627
0
    if (Style.ColumnLimit != 0 &&
628
0
        Style.ColumnLimit < NewLeft + NewAnchor + NewRight) {
629
0
      AlignCurrentSequence();
630
0
      StartOfSequence = i;
631
0
      WidthLeft = ChangeWidthLeft;
632
0
      WidthAnchor = ChangeWidthAnchor;
633
0
      WidthRight = ChangeWidthRight;
634
0
    } else {
635
0
      WidthLeft = NewLeft;
636
0
      WidthAnchor = NewAnchor;
637
0
      WidthRight = NewRight;
638
0
    }
639
0
  }
640
641
3
  EndOfSequence = i;
642
3
  AlignCurrentSequence();
643
3
  return i;
644
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&, bool)
Line
Count
Source
488
676
                            bool RightJustify = false) {
489
  // We arrange each line in 3 parts. The operator to be aligned (the anchor),
490
  // and text to its left and right. In the aligned text the width of each part
491
  // will be the maximum of that over the block that has been aligned. Maximum
492
  // widths of each part so far. When RightJustify is true and ACS.PadOperators
493
  // is false, the part from start of line to the right end of the anchor.
494
  // Otherwise, only the part to the left of the anchor. Including the space
495
  // that exists on its left from the start. Not including the padding added on
496
  // the left to right-justify the anchor.
497
676
  unsigned WidthLeft = 0;
498
  // The operator to be aligned when RightJustify is true and ACS.PadOperators
499
  // is false. 0 otherwise.
500
676
  unsigned WidthAnchor = 0;
501
  // Width to the right of the anchor. Plus width of the anchor when
502
  // RightJustify is false.
503
676
  unsigned WidthRight = 0;
504
505
  // Line number of the start and the end of the current token sequence.
506
676
  unsigned StartOfSequence = 0;
507
676
  unsigned EndOfSequence = 0;
508
509
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
510
  // abort when we hit any token in a higher scope than the starting one.
511
676
  auto IndentAndNestingLevel = StartAt < Changes.size()
512
676
                                   ? Changes[StartAt].indentAndNestingLevel()
513
676
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
514
515
  // Keep track of the number of commas before the matching tokens, we will only
516
  // align a sequence of matching tokens if they are preceded by the same number
517
  // of commas.
518
676
  unsigned CommasBeforeLastMatch = 0;
519
676
  unsigned CommasBeforeMatch = 0;
520
521
  // Whether a matching token has been found on the current line.
522
676
  bool FoundMatchOnLine = false;
523
524
  // Whether the current line consists purely of comments.
525
676
  bool LineIsComment = true;
526
527
  // Aligns a sequence of matching tokens, on the MinColumn column.
528
  //
529
  // Sequences start from the first matching token to align, and end at the
530
  // first token of the first line that doesn't need to be aligned.
531
  //
532
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
533
  // containing any matching token to be aligned and located after such token.
534
676
  auto AlignCurrentSequence = [&] {
535
676
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
536
676
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
676
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
676
                         Changes);
539
676
    WidthLeft = 0;
540
676
    WidthAnchor = 0;
541
676
    WidthRight = 0;
542
676
    StartOfSequence = 0;
543
676
    EndOfSequence = 0;
544
676
  };
545
546
676
  unsigned i = StartAt;
547
8.08k
  for (unsigned e = Changes.size(); i != e; 
++i7.40k
) {
548
7.40k
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
549
0
      break;
550
551
7.40k
    if (Changes[i].NewlinesBefore != 0) {
552
1.04k
      CommasBeforeMatch = 0;
553
1.04k
      EndOfSequence = i;
554
555
      // Whether to break the alignment sequence because of an empty line.
556
1.04k
      bool EmptyLineBreak =
557
1.04k
          (Changes[i].NewlinesBefore > 1) && 
!ACS.AcrossEmptyLines17
;
558
559
      // Whether to break the alignment sequence because of a line without a
560
      // match.
561
1.04k
      bool NoMatchBreak =
562
1.04k
          !FoundMatchOnLine && 
!(450
LineIsComment450
&&
ACS.AcrossComments30
);
563
564
1.04k
      if (EmptyLineBreak || 
NoMatchBreak1.02k
)
565
449
        AlignCurrentSequence();
566
567
      // A new line starts, re-initialize line status tracking bools.
568
      // Keep the match state if a string literal is continued on this line.
569
1.04k
      if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
570
1.04k
          
!Changes[i - 1].Tok->is(tok::string_literal)18
)
571
1.04k
        FoundMatchOnLine = false;
572
1.04k
      LineIsComment = true;
573
1.04k
    }
574
575
7.40k
    if (!Changes[i].Tok->is(tok::comment))
576
7.34k
      LineIsComment = false;
577
578
7.40k
    if (Changes[i].Tok->is(tok::comma)) {
579
24
      ++CommasBeforeMatch;
580
7.38k
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
581
      // Call AlignTokens recursively, skipping over this scope block.
582
904
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
583
904
      i = StoppedAt - 1;
584
904
      continue;
585
904
    }
586
587
6.50k
    if (!Matches(Changes[i]))
588
5.67k
      continue;
589
590
    // If there is more than one matching token per line, or if the number of
591
    // preceding commas, do not match anymore, end the sequence.
592
826
    if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch)
593
0
      AlignCurrentSequence();
594
595
826
    CommasBeforeLastMatch = CommasBeforeMatch;
596
826
    FoundMatchOnLine = true;
597
598
826
    if (StartOfSequence == 0)
599
455
      StartOfSequence = i;
600
601
826
    unsigned ChangeWidthLeft = Changes[i].StartOfTokenColumn;
602
826
    unsigned ChangeWidthAnchor = 0;
603
826
    unsigned ChangeWidthRight = 0;
604
826
    if (RightJustify) {
605
0
      if (ACS.PadOperators)
606
0
        ChangeWidthAnchor = Changes[i].TokenLength;
607
0
      else
608
0
        ChangeWidthLeft += Changes[i].TokenLength;
609
0
    } else
610
826
      ChangeWidthRight = Changes[i].TokenLength;
611
4.20k
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 03.97k
;
++j3.37k
) {
612
3.37k
      ChangeWidthRight += Changes[j].Spaces;
613
      // Changes are generally 1:1 with the tokens, but a change could also be
614
      // inside of a token, in which case it's counted more than once: once for
615
      // the whitespace surrounding the token (!IsInsideToken) and once for
616
      // each whitespace change within it (IsInsideToken).
617
      // Therefore, changes inside of a token should only count the space.
618
3.37k
      if (!Changes[j].IsInsideToken)
619
3.37k
        ChangeWidthRight += Changes[j].TokenLength;
620
3.37k
    }
621
622
    // If we are restricted by the maximum column width, end the sequence.
623
826
    unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
624
826
    unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
625
826
    unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
626
    // `ColumnLimit == 0` means there is no column limit.
627
826
    if (Style.ColumnLimit != 0 &&
628
826
        
Style.ColumnLimit < NewLeft + NewAnchor + NewRight821
) {
629
6
      AlignCurrentSequence();
630
6
      StartOfSequence = i;
631
6
      WidthLeft = ChangeWidthLeft;
632
6
      WidthAnchor = ChangeWidthAnchor;
633
6
      WidthRight = ChangeWidthRight;
634
820
    } else {
635
820
      WidthLeft = NewLeft;
636
820
      WidthAnchor = NewAnchor;
637
820
      WidthRight = NewRight;
638
820
    }
639
826
  }
640
641
676
  EndOfSequence = i;
642
676
  AlignCurrentSequence();
643
676
  return i;
644
676
}
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&, bool)
Line
Count
Source
488
1.74k
                            bool RightJustify = false) {
489
  // We arrange each line in 3 parts. The operator to be aligned (the anchor),
490
  // and text to its left and right. In the aligned text the width of each part
491
  // will be the maximum of that over the block that has been aligned. Maximum
492
  // widths of each part so far. When RightJustify is true and ACS.PadOperators
493
  // is false, the part from start of line to the right end of the anchor.
494
  // Otherwise, only the part to the left of the anchor. Including the space
495
  // that exists on its left from the start. Not including the padding added on
496
  // the left to right-justify the anchor.
497
1.74k
  unsigned WidthLeft = 0;
498
  // The operator to be aligned when RightJustify is true and ACS.PadOperators
499
  // is false. 0 otherwise.
500
1.74k
  unsigned WidthAnchor = 0;
501
  // Width to the right of the anchor. Plus width of the anchor when
502
  // RightJustify is false.
503
1.74k
  unsigned WidthRight = 0;
504
505
  // Line number of the start and the end of the current token sequence.
506
1.74k
  unsigned StartOfSequence = 0;
507
1.74k
  unsigned EndOfSequence = 0;
508
509
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
510
  // abort when we hit any token in a higher scope than the starting one.
511
1.74k
  auto IndentAndNestingLevel = StartAt < Changes.size()
512
1.74k
                                   ? Changes[StartAt].indentAndNestingLevel()
513
1.74k
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
514
515
  // Keep track of the number of commas before the matching tokens, we will only
516
  // align a sequence of matching tokens if they are preceded by the same number
517
  // of commas.
518
1.74k
  unsigned CommasBeforeLastMatch = 0;
519
1.74k
  unsigned CommasBeforeMatch = 0;
520
521
  // Whether a matching token has been found on the current line.
522
1.74k
  bool FoundMatchOnLine = false;
523
524
  // Whether the current line consists purely of comments.
525
1.74k
  bool LineIsComment = true;
526
527
  // Aligns a sequence of matching tokens, on the MinColumn column.
528
  //
529
  // Sequences start from the first matching token to align, and end at the
530
  // first token of the first line that doesn't need to be aligned.
531
  //
532
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
533
  // containing any matching token to be aligned and located after such token.
534
1.74k
  auto AlignCurrentSequence = [&] {
535
1.74k
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
536
1.74k
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
1.74k
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
1.74k
                         Changes);
539
1.74k
    WidthLeft = 0;
540
1.74k
    WidthAnchor = 0;
541
1.74k
    WidthRight = 0;
542
1.74k
    StartOfSequence = 0;
543
1.74k
    EndOfSequence = 0;
544
1.74k
  };
545
546
1.74k
  unsigned i = StartAt;
547
12.0k
  for (unsigned e = Changes.size(); i != e; 
++i10.2k
) {
548
12.0k
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
549
1.74k
      break;
550
551
10.2k
    if (Changes[i].NewlinesBefore != 0) {
552
951
      CommasBeforeMatch = 0;
553
951
      EndOfSequence = i;
554
555
      // Whether to break the alignment sequence because of an empty line.
556
951
      bool EmptyLineBreak =
557
951
          (Changes[i].NewlinesBefore > 1) && 
!ACS.AcrossEmptyLines6
;
558
559
      // Whether to break the alignment sequence because of a line without a
560
      // match.
561
951
      bool NoMatchBreak =
562
951
          !FoundMatchOnLine && 
!(667
LineIsComment667
&&
ACS.AcrossComments353
);
563
564
951
      if (EmptyLineBreak || 
NoMatchBreak945
)
565
673
        AlignCurrentSequence();
566
567
      // A new line starts, re-initialize line status tracking bools.
568
      // Keep the match state if a string literal is continued on this line.
569
951
      if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
570
951
          
!Changes[i - 1].Tok->is(tok::string_literal)79
)
571
905
        FoundMatchOnLine = false;
572
951
      LineIsComment = true;
573
951
    }
574
575
10.2k
    if (!Changes[i].Tok->is(tok::comment))
576
10.1k
      LineIsComment = false;
577
578
10.2k
    if (Changes[i].Tok->is(tok::comma)) {
579
1.30k
      ++CommasBeforeMatch;
580
8.96k
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
581
      // Call AlignTokens recursively, skipping over this scope block.
582
844
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
583
844
      i = StoppedAt - 1;
584
844
      continue;
585
844
    }
586
587
9.42k
    if (!Matches(Changes[i]))
588
8.68k
      continue;
589
590
    // If there is more than one matching token per line, or if the number of
591
    // preceding commas, do not match anymore, end the sequence.
592
741
    if (FoundMatchOnLine || 
CommasBeforeMatch != CommasBeforeLastMatch555
)
593
189
      AlignCurrentSequence();
594
595
741
    CommasBeforeLastMatch = CommasBeforeMatch;
596
741
    FoundMatchOnLine = true;
597
598
741
    if (StartOfSequence == 0)
599
555
      StartOfSequence = i;
600
601
741
    unsigned ChangeWidthLeft = Changes[i].StartOfTokenColumn;
602
741
    unsigned ChangeWidthAnchor = 0;
603
741
    unsigned ChangeWidthRight = 0;
604
741
    if (RightJustify) {
605
0
      if (ACS.PadOperators)
606
0
        ChangeWidthAnchor = Changes[i].TokenLength;
607
0
      else
608
0
        ChangeWidthLeft += Changes[i].TokenLength;
609
0
    } else
610
741
      ChangeWidthRight = Changes[i].TokenLength;
611
6.32k
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 05.97k
;
++j5.58k
) {
612
5.58k
      ChangeWidthRight += Changes[j].Spaces;
613
      // Changes are generally 1:1 with the tokens, but a change could also be
614
      // inside of a token, in which case it's counted more than once: once for
615
      // the whitespace surrounding the token (!IsInsideToken) and once for
616
      // each whitespace change within it (IsInsideToken).
617
      // Therefore, changes inside of a token should only count the space.
618
5.58k
      if (!Changes[j].IsInsideToken)
619
5.58k
        ChangeWidthRight += Changes[j].TokenLength;
620
5.58k
    }
621
622
    // If we are restricted by the maximum column width, end the sequence.
623
741
    unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
624
741
    unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
625
741
    unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
626
    // `ColumnLimit == 0` means there is no column limit.
627
741
    if (Style.ColumnLimit != 0 &&
628
741
        
Style.ColumnLimit < NewLeft + NewAnchor + NewRight734
) {
629
0
      AlignCurrentSequence();
630
0
      StartOfSequence = i;
631
0
      WidthLeft = ChangeWidthLeft;
632
0
      WidthAnchor = ChangeWidthAnchor;
633
0
      WidthRight = ChangeWidthRight;
634
741
    } else {
635
741
      WidthLeft = NewLeft;
636
741
      WidthAnchor = NewAnchor;
637
741
      WidthRight = NewRight;
638
741
    }
639
741
  }
640
641
1.74k
  EndOfSequence = i;
642
1.74k
  AlignCurrentSequence();
643
1.74k
  return i;
644
1.74k
}
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&, bool)
Line
Count
Source
488
20.6k
                            bool RightJustify = false) {
489
  // We arrange each line in 3 parts. The operator to be aligned (the anchor),
490
  // and text to its left and right. In the aligned text the width of each part
491
  // will be the maximum of that over the block that has been aligned. Maximum
492
  // widths of each part so far. When RightJustify is true and ACS.PadOperators
493
  // is false, the part from start of line to the right end of the anchor.
494
  // Otherwise, only the part to the left of the anchor. Including the space
495
  // that exists on its left from the start. Not including the padding added on
496
  // the left to right-justify the anchor.
497
20.6k
  unsigned WidthLeft = 0;
498
  // The operator to be aligned when RightJustify is true and ACS.PadOperators
499
  // is false. 0 otherwise.
500
20.6k
  unsigned WidthAnchor = 0;
501
  // Width to the right of the anchor. Plus width of the anchor when
502
  // RightJustify is false.
503
20.6k
  unsigned WidthRight = 0;
504
505
  // Line number of the start and the end of the current token sequence.
506
20.6k
  unsigned StartOfSequence = 0;
507
20.6k
  unsigned EndOfSequence = 0;
508
509
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
510
  // abort when we hit any token in a higher scope than the starting one.
511
20.6k
  auto IndentAndNestingLevel = StartAt < Changes.size()
512
20.6k
                                   ? Changes[StartAt].indentAndNestingLevel()
513
20.6k
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
514
515
  // Keep track of the number of commas before the matching tokens, we will only
516
  // align a sequence of matching tokens if they are preceded by the same number
517
  // of commas.
518
20.6k
  unsigned CommasBeforeLastMatch = 0;
519
20.6k
  unsigned CommasBeforeMatch = 0;
520
521
  // Whether a matching token has been found on the current line.
522
20.6k
  bool FoundMatchOnLine = false;
523
524
  // Whether the current line consists purely of comments.
525
20.6k
  bool LineIsComment = true;
526
527
  // Aligns a sequence of matching tokens, on the MinColumn column.
528
  //
529
  // Sequences start from the first matching token to align, and end at the
530
  // first token of the first line that doesn't need to be aligned.
531
  //
532
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
533
  // containing any matching token to be aligned and located after such token.
534
20.6k
  auto AlignCurrentSequence = [&] {
535
20.6k
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
536
20.6k
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
20.6k
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
20.6k
                         Changes);
539
20.6k
    WidthLeft = 0;
540
20.6k
    WidthAnchor = 0;
541
20.6k
    WidthRight = 0;
542
20.6k
    StartOfSequence = 0;
543
20.6k
    EndOfSequence = 0;
544
20.6k
  };
545
546
20.6k
  unsigned i = StartAt;
547
223k
  for (unsigned e = Changes.size(); i != e; 
++i202k
) {
548
203k
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
549
24
      break;
550
551
202k
    if (Changes[i].NewlinesBefore != 0) {
552
31.8k
      CommasBeforeMatch = 0;
553
31.8k
      EndOfSequence = i;
554
555
      // Whether to break the alignment sequence because of an empty line.
556
31.8k
      bool EmptyLineBreak =
557
31.8k
          (Changes[i].NewlinesBefore > 1) && 
!ACS.AcrossEmptyLines1.06k
;
558
559
      // Whether to break the alignment sequence because of a line without a
560
      // match.
561
31.8k
      bool NoMatchBreak =
562
31.8k
          !FoundMatchOnLine && 
!(31.8k
LineIsComment31.8k
&&
ACS.AcrossComments3.06k
);
563
564
31.8k
      if (EmptyLineBreak || 
NoMatchBreak30.7k
)
565
31.8k
        AlignCurrentSequence();
566
567
      // A new line starts, re-initialize line status tracking bools.
568
      // Keep the match state if a string literal is continued on this line.
569
31.8k
      if (i == 0 || 
!Changes[i].Tok->is(tok::string_literal)31.2k
||
570
31.8k
          
!Changes[i - 1].Tok->is(tok::string_literal)229
)
571
31.7k
        FoundMatchOnLine = false;
572
31.8k
      LineIsComment = true;
573
31.8k
    }
574
575
202k
    if (!Changes[i].Tok->is(tok::comment))
576
197k
      LineIsComment = false;
577
578
202k
    if (Changes[i].Tok->is(tok::comma)) {
579
1.01k
      ++CommasBeforeMatch;
580
201k
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
581
      // Call AlignTokens recursively, skipping over this scope block.
582
32.4k
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
583
32.4k
      i = StoppedAt - 1;
584
32.4k
      continue;
585
32.4k
    }
586
587
170k
    if (!Matches(Changes[i]))
588
170k
      continue;
589
590
    // If there is more than one matching token per line, or if the number of
591
    // preceding commas, do not match anymore, end the sequence.
592
24
    if (FoundMatchOnLine || 
CommasBeforeMatch != CommasBeforeLastMatch17
)
593
7
      AlignCurrentSequence();
594
595
24
    CommasBeforeLastMatch = CommasBeforeMatch;
596
24
    FoundMatchOnLine = true;
597
598
24
    if (StartOfSequence == 0)
599
24
      StartOfSequence = i;
600
601
24
    unsigned ChangeWidthLeft = Changes[i].StartOfTokenColumn;
602
24
    unsigned ChangeWidthAnchor = 0;
603
24
    unsigned ChangeWidthRight = 0;
604
24
    if (RightJustify) {
605
0
      if (ACS.PadOperators)
606
0
        ChangeWidthAnchor = Changes[i].TokenLength;
607
0
      else
608
0
        ChangeWidthLeft += Changes[i].TokenLength;
609
0
    } else
610
24
      ChangeWidthRight = Changes[i].TokenLength;
611
158
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 0137
;
++j134
) {
612
134
      ChangeWidthRight += Changes[j].Spaces;
613
      // Changes are generally 1:1 with the tokens, but a change could also be
614
      // inside of a token, in which case it's counted more than once: once for
615
      // the whitespace surrounding the token (!IsInsideToken) and once for
616
      // each whitespace change within it (IsInsideToken).
617
      // Therefore, changes inside of a token should only count the space.
618
134
      if (!Changes[j].IsInsideToken)
619
134
        ChangeWidthRight += Changes[j].TokenLength;
620
134
    }
621
622
    // If we are restricted by the maximum column width, end the sequence.
623
24
    unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
624
24
    unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
625
24
    unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
626
    // `ColumnLimit == 0` means there is no column limit.
627
24
    if (Style.ColumnLimit != 0 &&
628
24
        Style.ColumnLimit < NewLeft + NewAnchor + NewRight) {
629
0
      AlignCurrentSequence();
630
0
      StartOfSequence = i;
631
0
      WidthLeft = ChangeWidthLeft;
632
0
      WidthAnchor = ChangeWidthAnchor;
633
0
      WidthRight = ChangeWidthRight;
634
24
    } else {
635
24
      WidthLeft = NewLeft;
636
24
      WidthAnchor = NewAnchor;
637
24
      WidthRight = NewRight;
638
24
    }
639
24
  }
640
641
20.6k
  EndOfSequence = i;
642
20.6k
  AlignCurrentSequence();
643
20.6k
  return i;
644
20.6k
}
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&, bool)
Line
Count
Source
488
53.9k
                            bool RightJustify = false) {
489
  // We arrange each line in 3 parts. The operator to be aligned (the anchor),
490
  // and text to its left and right. In the aligned text the width of each part
491
  // will be the maximum of that over the block that has been aligned. Maximum
492
  // widths of each part so far. When RightJustify is true and ACS.PadOperators
493
  // is false, the part from start of line to the right end of the anchor.
494
  // Otherwise, only the part to the left of the anchor. Including the space
495
  // that exists on its left from the start. Not including the padding added on
496
  // the left to right-justify the anchor.
497
53.9k
  unsigned WidthLeft = 0;
498
  // The operator to be aligned when RightJustify is true and ACS.PadOperators
499
  // is false. 0 otherwise.
500
53.9k
  unsigned WidthAnchor = 0;
501
  // Width to the right of the anchor. Plus width of the anchor when
502
  // RightJustify is false.
503
53.9k
  unsigned WidthRight = 0;
504
505
  // Line number of the start and the end of the current token sequence.
506
53.9k
  unsigned StartOfSequence = 0;
507
53.9k
  unsigned EndOfSequence = 0;
508
509
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
510
  // abort when we hit any token in a higher scope than the starting one.
511
53.9k
  auto IndentAndNestingLevel = StartAt < Changes.size()
512
53.9k
                                   ? Changes[StartAt].indentAndNestingLevel()
513
53.9k
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
514
515
  // Keep track of the number of commas before the matching tokens, we will only
516
  // align a sequence of matching tokens if they are preceded by the same number
517
  // of commas.
518
53.9k
  unsigned CommasBeforeLastMatch = 0;
519
53.9k
  unsigned CommasBeforeMatch = 0;
520
521
  // Whether a matching token has been found on the current line.
522
53.9k
  bool FoundMatchOnLine = false;
523
524
  // Whether the current line consists purely of comments.
525
53.9k
  bool LineIsComment = true;
526
527
  // Aligns a sequence of matching tokens, on the MinColumn column.
528
  //
529
  // Sequences start from the first matching token to align, and end at the
530
  // first token of the first line that doesn't need to be aligned.
531
  //
532
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
533
  // containing any matching token to be aligned and located after such token.
534
53.9k
  auto AlignCurrentSequence = [&] {
535
53.9k
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
536
53.9k
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
53.9k
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
53.9k
                         Changes);
539
53.9k
    WidthLeft = 0;
540
53.9k
    WidthAnchor = 0;
541
53.9k
    WidthRight = 0;
542
53.9k
    StartOfSequence = 0;
543
53.9k
    EndOfSequence = 0;
544
53.9k
  };
545
546
53.9k
  unsigned i = StartAt;
547
256k
  for (unsigned e = Changes.size(); i != e; 
++i202k
) {
548
256k
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
549
53.8k
      break;
550
551
202k
    if (Changes[i].NewlinesBefore != 0) {
552
26.6k
      CommasBeforeMatch = 0;
553
26.6k
      EndOfSequence = i;
554
555
      // Whether to break the alignment sequence because of an empty line.
556
26.6k
      bool EmptyLineBreak =
557
26.6k
          (Changes[i].NewlinesBefore > 1) && 
!ACS.AcrossEmptyLines268
;
558
559
      // Whether to break the alignment sequence because of a line without a
560
      // match.
561
26.6k
      bool NoMatchBreak =
562
26.6k
          !FoundMatchOnLine && 
!(26.3k
LineIsComment26.3k
&&
ACS.AcrossComments11.9k
);
563
564
26.6k
      if (EmptyLineBreak || 
NoMatchBreak26.3k
)
565
26.3k
        AlignCurrentSequence();
566
567
      // A new line starts, re-initialize line status tracking bools.
568
      // Keep the match state if a string literal is continued on this line.
569
26.6k
      if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
570
26.6k
          
!Changes[i - 1].Tok->is(tok::string_literal)583
)
571
26.4k
        FoundMatchOnLine = false;
572
26.6k
      LineIsComment = true;
573
26.6k
    }
574
575
202k
    if (!Changes[i].Tok->is(tok::comment))
576
200k
      LineIsComment = false;
577
578
202k
    if (Changes[i].Tok->is(tok::comma)) {
579
10.0k
      ++CommasBeforeMatch;
580
192k
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
581
      // Call AlignTokens recursively, skipping over this scope block.
582
21.4k
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
583
21.4k
      i = StoppedAt - 1;
584
21.4k
      continue;
585
21.4k
    }
586
587
181k
    if (!Matches(Changes[i]))
588
180k
      continue;
589
590
    // If there is more than one matching token per line, or if the number of
591
    // preceding commas, do not match anymore, end the sequence.
592
757
    if (FoundMatchOnLine || 
CommasBeforeMatch != CommasBeforeLastMatch607
)
593
154
      AlignCurrentSequence();
594
595
757
    CommasBeforeLastMatch = CommasBeforeMatch;
596
757
    FoundMatchOnLine = true;
597
598
757
    if (StartOfSequence == 0)
599
523
      StartOfSequence = i;
600
601
757
    unsigned ChangeWidthLeft = Changes[i].StartOfTokenColumn;
602
757
    unsigned ChangeWidthAnchor = 0;
603
757
    unsigned ChangeWidthRight = 0;
604
757
    if (RightJustify) {
605
0
      if (ACS.PadOperators)
606
0
        ChangeWidthAnchor = Changes[i].TokenLength;
607
0
      else
608
0
        ChangeWidthLeft += Changes[i].TokenLength;
609
0
    } else
610
757
      ChangeWidthRight = Changes[i].TokenLength;
611
3.51k
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 03.17k
;
++j2.75k
) {
612
2.75k
      ChangeWidthRight += Changes[j].Spaces;
613
      // Changes are generally 1:1 with the tokens, but a change could also be
614
      // inside of a token, in which case it's counted more than once: once for
615
      // the whitespace surrounding the token (!IsInsideToken) and once for
616
      // each whitespace change within it (IsInsideToken).
617
      // Therefore, changes inside of a token should only count the space.
618
2.75k
      if (!Changes[j].IsInsideToken)
619
2.75k
        ChangeWidthRight += Changes[j].TokenLength;
620
2.75k
    }
621
622
    // If we are restricted by the maximum column width, end the sequence.
623
757
    unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
624
757
    unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
625
757
    unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
626
    // `ColumnLimit == 0` means there is no column limit.
627
757
    if (Style.ColumnLimit != 0 &&
628
757
        Style.ColumnLimit < NewLeft + NewAnchor + NewRight) {
629
0
      AlignCurrentSequence();
630
0
      StartOfSequence = i;
631
0
      WidthLeft = ChangeWidthLeft;
632
0
      WidthAnchor = ChangeWidthAnchor;
633
0
      WidthRight = ChangeWidthRight;
634
757
    } else {
635
757
      WidthLeft = NewLeft;
636
757
      WidthAnchor = NewAnchor;
637
757
      WidthRight = NewRight;
638
757
    }
639
757
  }
640
641
53.9k
  EndOfSequence = i;
642
53.9k
  AlignCurrentSequence();
643
53.9k
  return i;
644
53.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&, bool)
Line
Count
Source
488
1.60k
                            bool RightJustify = false) {
489
  // We arrange each line in 3 parts. The operator to be aligned (the anchor),
490
  // and text to its left and right. In the aligned text the width of each part
491
  // will be the maximum of that over the block that has been aligned. Maximum
492
  // widths of each part so far. When RightJustify is true and ACS.PadOperators
493
  // is false, the part from start of line to the right end of the anchor.
494
  // Otherwise, only the part to the left of the anchor. Including the space
495
  // that exists on its left from the start. Not including the padding added on
496
  // the left to right-justify the anchor.
497
1.60k
  unsigned WidthLeft = 0;
498
  // The operator to be aligned when RightJustify is true and ACS.PadOperators
499
  // is false. 0 otherwise.
500
1.60k
  unsigned WidthAnchor = 0;
501
  // Width to the right of the anchor. Plus width of the anchor when
502
  // RightJustify is false.
503
1.60k
  unsigned WidthRight = 0;
504
505
  // Line number of the start and the end of the current token sequence.
506
1.60k
  unsigned StartOfSequence = 0;
507
1.60k
  unsigned EndOfSequence = 0;
508
509
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
510
  // abort when we hit any token in a higher scope than the starting one.
511
1.60k
  auto IndentAndNestingLevel = StartAt < Changes.size()
512
1.60k
                                   ? Changes[StartAt].indentAndNestingLevel()
513
1.60k
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
514
515
  // Keep track of the number of commas before the matching tokens, we will only
516
  // align a sequence of matching tokens if they are preceded by the same number
517
  // of commas.
518
1.60k
  unsigned CommasBeforeLastMatch = 0;
519
1.60k
  unsigned CommasBeforeMatch = 0;
520
521
  // Whether a matching token has been found on the current line.
522
1.60k
  bool FoundMatchOnLine = false;
523
524
  // Whether the current line consists purely of comments.
525
1.60k
  bool LineIsComment = true;
526
527
  // Aligns a sequence of matching tokens, on the MinColumn column.
528
  //
529
  // Sequences start from the first matching token to align, and end at the
530
  // first token of the first line that doesn't need to be aligned.
531
  //
532
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
533
  // containing any matching token to be aligned and located after such token.
534
1.60k
  auto AlignCurrentSequence = [&] {
535
1.60k
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
536
1.60k
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
1.60k
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
1.60k
                         Changes);
539
1.60k
    WidthLeft = 0;
540
1.60k
    WidthAnchor = 0;
541
1.60k
    WidthRight = 0;
542
1.60k
    StartOfSequence = 0;
543
1.60k
    EndOfSequence = 0;
544
1.60k
  };
545
546
1.60k
  unsigned i = StartAt;
547
13.9k
  for (unsigned e = Changes.size(); i != e; 
++i12.2k
) {
548
12.3k
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
549
11
      break;
550
551
12.2k
    if (Changes[i].NewlinesBefore != 0) {
552
1.59k
      CommasBeforeMatch = 0;
553
1.59k
      EndOfSequence = i;
554
555
      // Whether to break the alignment sequence because of an empty line.
556
1.59k
      bool EmptyLineBreak =
557
1.59k
          (Changes[i].NewlinesBefore > 1) && 
!ACS.AcrossEmptyLines34
;
558
559
      // Whether to break the alignment sequence because of a line without a
560
      // match.
561
1.59k
      bool NoMatchBreak =
562
1.59k
          !FoundMatchOnLine && 
!(1.59k
LineIsComment1.59k
&&
ACS.AcrossComments176
);
563
564
1.59k
      if (EmptyLineBreak || 
NoMatchBreak1.55k
)
565
1.59k
        AlignCurrentSequence();
566
567
      // A new line starts, re-initialize line status tracking bools.
568
      // Keep the match state if a string literal is continued on this line.
569
1.59k
      if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
570
1.59k
          
!Changes[i - 1].Tok->is(tok::string_literal)38
)
571
1.59k
        FoundMatchOnLine = false;
572
1.59k
      LineIsComment = true;
573
1.59k
    }
574
575
12.2k
    if (!Changes[i].Tok->is(tok::comment))
576
12.0k
      LineIsComment = false;
577
578
12.2k
    if (Changes[i].Tok->is(tok::comma)) {
579
8
      ++CommasBeforeMatch;
580
12.2k
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
581
      // Call AlignTokens recursively, skipping over this scope block.
582
1.75k
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
583
1.75k
      i = StoppedAt - 1;
584
1.75k
      continue;
585
1.75k
    }
586
587
10.5k
    if (!Matches(Changes[i]))
588
10.5k
      continue;
589
590
    // If there is more than one matching token per line, or if the number of
591
    // preceding commas, do not match anymore, end the sequence.
592
11
    if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch)
593
0
      AlignCurrentSequence();
594
595
11
    CommasBeforeLastMatch = CommasBeforeMatch;
596
11
    FoundMatchOnLine = true;
597
598
11
    if (StartOfSequence == 0)
599
11
      StartOfSequence = i;
600
601
11
    unsigned ChangeWidthLeft = Changes[i].StartOfTokenColumn;
602
11
    unsigned ChangeWidthAnchor = 0;
603
11
    unsigned ChangeWidthRight = 0;
604
11
    if (RightJustify) {
605
0
      if (ACS.PadOperators)
606
0
        ChangeWidthAnchor = Changes[i].TokenLength;
607
0
      else
608
0
        ChangeWidthLeft += Changes[i].TokenLength;
609
0
    } else
610
11
      ChangeWidthRight = Changes[i].TokenLength;
611
36
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 028
;
++j25
) {
612
25
      ChangeWidthRight += Changes[j].Spaces;
613
      // Changes are generally 1:1 with the tokens, but a change could also be
614
      // inside of a token, in which case it's counted more than once: once for
615
      // the whitespace surrounding the token (!IsInsideToken) and once for
616
      // each whitespace change within it (IsInsideToken).
617
      // Therefore, changes inside of a token should only count the space.
618
25
      if (!Changes[j].IsInsideToken)
619
25
        ChangeWidthRight += Changes[j].TokenLength;
620
25
    }
621
622
    // If we are restricted by the maximum column width, end the sequence.
623
11
    unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
624
11
    unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
625
11
    unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
626
    // `ColumnLimit == 0` means there is no column limit.
627
11
    if (Style.ColumnLimit != 0 &&
628
11
        Style.ColumnLimit < NewLeft + NewAnchor + NewRight) {
629
0
      AlignCurrentSequence();
630
0
      StartOfSequence = i;
631
0
      WidthLeft = ChangeWidthLeft;
632
0
      WidthAnchor = ChangeWidthAnchor;
633
0
      WidthRight = ChangeWidthRight;
634
11
    } else {
635
11
      WidthLeft = NewLeft;
636
11
      WidthAnchor = NewAnchor;
637
11
      WidthRight = NewRight;
638
11
    }
639
11
  }
640
641
1.60k
  EndOfSequence = i;
642
1.60k
  AlignCurrentSequence();
643
1.60k
  return i;
644
1.60k
}
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&, bool)
Line
Count
Source
488
3.05k
                            bool RightJustify = false) {
489
  // We arrange each line in 3 parts. The operator to be aligned (the anchor),
490
  // and text to its left and right. In the aligned text the width of each part
491
  // will be the maximum of that over the block that has been aligned. Maximum
492
  // widths of each part so far. When RightJustify is true and ACS.PadOperators
493
  // is false, the part from start of line to the right end of the anchor.
494
  // Otherwise, only the part to the left of the anchor. Including the space
495
  // that exists on its left from the start. Not including the padding added on
496
  // the left to right-justify the anchor.
497
3.05k
  unsigned WidthLeft = 0;
498
  // The operator to be aligned when RightJustify is true and ACS.PadOperators
499
  // is false. 0 otherwise.
500
3.05k
  unsigned WidthAnchor = 0;
501
  // Width to the right of the anchor. Plus width of the anchor when
502
  // RightJustify is false.
503
3.05k
  unsigned WidthRight = 0;
504
505
  // Line number of the start and the end of the current token sequence.
506
3.05k
  unsigned StartOfSequence = 0;
507
3.05k
  unsigned EndOfSequence = 0;
508
509
  // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
510
  // abort when we hit any token in a higher scope than the starting one.
511
3.05k
  auto IndentAndNestingLevel = StartAt < Changes.size()
512
3.05k
                                   ? Changes[StartAt].indentAndNestingLevel()
513
3.05k
                                   : 
std::tuple<unsigned, unsigned, unsigned>()0
;
514
515
  // Keep track of the number of commas before the matching tokens, we will only
516
  // align a sequence of matching tokens if they are preceded by the same number
517
  // of commas.
518
3.05k
  unsigned CommasBeforeLastMatch = 0;
519
3.05k
  unsigned CommasBeforeMatch = 0;
520
521
  // Whether a matching token has been found on the current line.
522
3.05k
  bool FoundMatchOnLine = false;
523
524
  // Whether the current line consists purely of comments.
525
3.05k
  bool LineIsComment = true;
526
527
  // Aligns a sequence of matching tokens, on the MinColumn column.
528
  //
529
  // Sequences start from the first matching token to align, and end at the
530
  // first token of the first line that doesn't need to be aligned.
531
  //
532
  // We need to adjust the StartOfTokenColumn of each Change that is on a line
533
  // containing any matching token to be aligned and located after such token.
534
3.05k
  auto AlignCurrentSequence = [&] {
535
3.05k
    if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
536
3.05k
      AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
537
3.05k
                         WidthLeft + WidthAnchor, RightJustify, Matches,
538
3.05k
                         Changes);
539
3.05k
    WidthLeft = 0;
540
3.05k
    WidthAnchor = 0;
541
3.05k
    WidthRight = 0;
542
3.05k
    StartOfSequence = 0;
543
3.05k
    EndOfSequence = 0;
544
3.05k
  };
545
546
3.05k
  unsigned i = StartAt;
547
14.0k
  for (unsigned e = Changes.size(); i != e; 
++i10.9k
) {
548
14.0k
    if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
549
3.04k
      break;
550
551
10.9k
    if (Changes[i].NewlinesBefore != 0) {
552
2.11k
      CommasBeforeMatch = 0;
553
2.11k
      EndOfSequence = i;
554
555
      // Whether to break the alignment sequence because of an empty line.
556
2.11k
      bool EmptyLineBreak =
557
2.11k
          (Changes[i].NewlinesBefore > 1) && 
!ACS.AcrossEmptyLines3
;
558
559
      // Whether to break the alignment sequence because of a line without a
560
      // match.
561
2.11k
      bool NoMatchBreak =
562
2.11k
          !FoundMatchOnLine && 
!(1.90k
LineIsComment1.90k
&&
ACS.AcrossComments1.04k
);
563
564
2.11k
      if (EmptyLineBreak || 
NoMatchBreak2.11k
)
565
1.90k
        AlignCurrentSequence();
566
567
      // A new line starts, re-initialize line status tracking bools.
568
      // Keep the match state if a string literal is continued on this line.
569
2.11k
      if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
570
2.11k
          
!Changes[i - 1].Tok->is(tok::string_literal)28
)
571
2.11k
        FoundMatchOnLine = false;
572
2.11k
      LineIsComment = true;
573
2.11k
    }
574
575
10.9k
    if (!Changes[i].Tok->is(tok::comment))
576
10.8k
      LineIsComment = false;
577
578
10.9k
    if (Changes[i].Tok->is(tok::comma)) {
579
613
      ++CommasBeforeMatch;
580
10.3k
    } else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
581
      // Call AlignTokens recursively, skipping over this scope block.
582
1.29k
      unsigned StoppedAt = AlignTokens(Style, Matches, Changes, i, ACS);
583
1.29k
      i = StoppedAt - 1;
584
1.29k
      continue;
585
1.29k
    }
586
587
9.69k
    if (!Matches(Changes[i]))
588
9.29k
      continue;
589
590
    // If there is more than one matching token per line, or if the number of
591
    // preceding commas, do not match anymore, end the sequence.
592
396
    if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch)
593
0
      AlignCurrentSequence();
594
595
396
    CommasBeforeLastMatch = CommasBeforeMatch;
596
396
    FoundMatchOnLine = true;
597
598
396
    if (StartOfSequence == 0)
599
191
      StartOfSequence = i;
600
601
396
    unsigned ChangeWidthLeft = Changes[i].StartOfTokenColumn;
602
396
    unsigned ChangeWidthAnchor = 0;
603
396
    unsigned ChangeWidthRight = 0;
604
396
    if (RightJustify) {
605
0
      if (ACS.PadOperators)
606
0
        ChangeWidthAnchor = Changes[i].TokenLength;
607
0
      else
608
0
        ChangeWidthLeft += Changes[i].TokenLength;
609
0
    } else
610
396
      ChangeWidthRight = Changes[i].TokenLength;
611
1.50k
    for (unsigned j = i + 1; j != e && 
Changes[j].NewlinesBefore == 01.39k
;
++j1.10k
) {
612
1.10k
      ChangeWidthRight += Changes[j].Spaces;
613
      // Changes are generally 1:1 with the tokens, but a change could also be
614
      // inside of a token, in which case it's counted more than once: once for
615
      // the whitespace surrounding the token (!IsInsideToken) and once for
616
      // each whitespace change within it (IsInsideToken).
617
      // Therefore, changes inside of a token should only count the space.
618
1.10k
      if (!Changes[j].IsInsideToken)
619
1.10k
        ChangeWidthRight += Changes[j].TokenLength;
620
1.10k
    }
621
622
    // If we are restricted by the maximum column width, end the sequence.
623
396
    unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
624
396
    unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
625
396
    unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
626
    // `ColumnLimit == 0` means there is no column limit.
627
396
    if (Style.ColumnLimit != 0 &&
628
396
        Style.ColumnLimit < NewLeft + NewAnchor + NewRight) {
629
3
      AlignCurrentSequence();
630
3
      StartOfSequence = i;
631
3
      WidthLeft = ChangeWidthLeft;
632
3
      WidthAnchor = ChangeWidthAnchor;
633
3
      WidthRight = ChangeWidthRight;
634
393
    } else {
635
393
      WidthLeft = NewLeft;
636
393
      WidthAnchor = NewAnchor;
637
393
      WidthRight = NewRight;
638
393
    }
639
396
  }
640
641
3.05k
  EndOfSequence = i;
642
3.05k
  AlignCurrentSequence();
643
3.05k
  return i;
644
3.05k
}
645
646
// Aligns a sequence of matching tokens, on the MinColumn column.
647
//
648
// Sequences start from the first matching token to align, and end at the
649
// first token of the first line that doesn't need to be aligned.
650
//
651
// We need to adjust the StartOfTokenColumn of each Change that is on a line
652
// containing any matching token to be aligned and located after such token.
653
static void AlignMacroSequence(
654
    unsigned &StartOfSequence, unsigned &EndOfSequence, unsigned &MinColumn,
655
    unsigned &MaxColumn, bool &FoundMatchOnLine,
656
    std::function<bool(const WhitespaceManager::Change &C)> AlignMacrosMatches,
657
1.83k
    SmallVector<WhitespaceManager::Change, 16> &Changes) {
658
1.83k
  if (StartOfSequence > 0 && 
StartOfSequence < EndOfSequence33
) {
659
660
33
    FoundMatchOnLine = false;
661
33
    int Shift = 0;
662
663
657
    for (unsigned I = StartOfSequence; I != EndOfSequence; 
++I624
) {
664
624
      if (Changes[I].NewlinesBefore > 0) {
665
78
        Shift = 0;
666
78
        FoundMatchOnLine = false;
667
78
      }
668
669
      // If this is the first matching token to be aligned, remember by how many
670
      // spaces it has to be shifted, so the rest of the changes on the line are
671
      // shifted by the same amount
672
624
      if (!FoundMatchOnLine && 
AlignMacrosMatches(Changes[I])417
) {
673
96
        FoundMatchOnLine = true;
674
96
        Shift = MinColumn - Changes[I].StartOfTokenColumn;
675
96
        Changes[I].Spaces += Shift;
676
96
      }
677
678
624
      assert(Shift >= 0);
679
0
      Changes[I].StartOfTokenColumn += Shift;
680
624
      if (I + 1 != Changes.size())
681
596
        Changes[I + 1].PreviousEndOfTokenColumn += Shift;
682
624
    }
683
33
  }
684
685
1.83k
  MinColumn = 0;
686
1.83k
  MaxColumn = UINT_MAX;
687
1.83k
  StartOfSequence = 0;
688
1.83k
  EndOfSequence = 0;
689
1.83k
}
690
691
22.2k
void WhitespaceManager::alignConsecutiveMacros() {
692
22.2k
  if (!Style.AlignConsecutiveMacros.Enabled)
693
21.7k
    return;
694
695
10.6k
  
auto AlignMacrosMatches = [](const Change &C) 433
{
696
10.6k
    const FormatToken *Current = C.Tok;
697
10.6k
    unsigned SpacesRequiredBefore = 1;
698
699
10.6k
    if (Current->SpacesRequiredBefore == 0 || 
!Current->Previous7.35k
)
700
5.47k
      return false;
701
702
5.21k
    Current = Current->Previous;
703
704
    // If token is a ")", skip over the parameter list, to the
705
    // token that precedes the "("
706
5.21k
    if (Current->is(tok::r_paren) && 
Current->MatchingParen225
) {
707
225
      Current = Current->MatchingParen->Previous;
708
225
      SpacesRequiredBefore = 0;
709
225
    }
710
711
5.21k
    if (!Current || !Current->is(tok::identifier))
712
3.46k
      return false;
713
714
1.74k
    if (!Current->Previous || 
!Current->Previous->is(tok::pp_define)1.56k
)
715
1.55k
      return false;
716
717
    // For a macro function, 0 spaces are required between the
718
    // identifier and the lparen that opens the parameter list.
719
    // For a simple macro, 1 space is required between the
720
    // identifier and the first token of the defined value.
721
192
    return Current->Next->SpacesRequiredBefore == SpacesRequiredBefore;
722
1.74k
  };
723
724
433
  unsigned MinColumn = 0;
725
433
  unsigned MaxColumn = UINT_MAX;
726
727
  // Start and end of the token sequence we're processing.
728
433
  unsigned StartOfSequence = 0;
729
433
  unsigned EndOfSequence = 0;
730
731
  // Whether a matching token has been found on the current line.
732
433
  bool FoundMatchOnLine = false;
733
734
  // Whether the current line consists only of comments
735
433
  bool LineIsComment = true;
736
737
433
  unsigned I = 0;
738
10.7k
  for (unsigned E = Changes.size(); I != E; 
++I10.2k
) {
739
10.2k
    if (Changes[I].NewlinesBefore != 0) {
740
1.48k
      EndOfSequence = I;
741
742
      // Whether to break the alignment sequence because of an empty line.
743
1.48k
      bool EmptyLineBreak = (Changes[I].NewlinesBefore > 1) &&
744
1.48k
                            
!Style.AlignConsecutiveMacros.AcrossEmptyLines40
;
745
746
      // Whether to break the alignment sequence because of a line without a
747
      // match.
748
1.48k
      bool NoMatchBreak =
749
1.48k
          !FoundMatchOnLine &&
750
1.48k
          
!(1.41k
LineIsComment1.41k
&&
Style.AlignConsecutiveMacros.AcrossComments39
);
751
752
1.48k
      if (EmptyLineBreak || 
NoMatchBreak1.44k
)
753
1.40k
        AlignMacroSequence(StartOfSequence, EndOfSequence, MinColumn, MaxColumn,
754
1.40k
                           FoundMatchOnLine, AlignMacrosMatches, Changes);
755
756
      // A new line starts, re-initialize line status tracking bools.
757
1.48k
      FoundMatchOnLine = false;
758
1.48k
      LineIsComment = true;
759
1.48k
    }
760
761
10.2k
    if (!Changes[I].Tok->is(tok::comment))
762
10.1k
      LineIsComment = false;
763
764
10.2k
    if (!AlignMacrosMatches(Changes[I]))
765
10.1k
      continue;
766
767
96
    FoundMatchOnLine = true;
768
769
96
    if (StartOfSequence == 0)
770
33
      StartOfSequence = I;
771
772
96
    unsigned ChangeMinColumn = Changes[I].StartOfTokenColumn;
773
96
    int LineLengthAfter = -Changes[I].Spaces;
774
399
    for (unsigned j = I; j != E && 
Changes[j].NewlinesBefore == 0371
;
++j303
)
775
303
      LineLengthAfter += Changes[j].Spaces + Changes[j].TokenLength;
776
96
    unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
777
778
96
    MinColumn = std::max(MinColumn, ChangeMinColumn);
779
96
    MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
780
96
  }
781
782
433
  EndOfSequence = I;
783
433
  AlignMacroSequence(StartOfSequence, EndOfSequence, MinColumn, MaxColumn,
784
433
                     FoundMatchOnLine, AlignMacrosMatches, Changes);
785
433
}
786
787
22.2k
void WhitespaceManager::alignConsecutiveAssignments() {
788
22.2k
  if (!Style.AlignConsecutiveAssignments.Enabled)
789
21.6k
    return;
790
791
594
  AlignTokens(
792
594
      Style,
793
17.5k
      [&](const Change &C) {
794
        // Do not align on equal signs that are first on a line.
795
17.5k
        if (C.NewlinesBefore > 0)
796
2.71k
          return false;
797
798
        // Do not align on equal signs that are last on a line.
799
14.7k
        if (&C != &Changes.back() && 
(&C + 1)->NewlinesBefore > 014.3k
)
800
1.92k
          return false;
801
802
        // Do not align operator= overloads.
803
12.8k
        FormatToken *Previous = C.Tok->getPreviousNonComment();
804
12.8k
        if (Previous && 
Previous->is(tok::kw_operator)11.8k
)
805
126
          return false;
806
807
12.7k
        return Style.AlignConsecutiveAssignments.AlignCompound
808
12.7k
                   ? 
C.Tok->getPrecedence() == prec::Assignment371
809
12.7k
                   : 
C.Tok->is(tok::equal)12.3k
;
810
12.8k
      },
811
594
      Changes, /*StartAt=*/0, Style.AlignConsecutiveAssignments,
812
594
      /*RightJustify=*/true);
813
594
}
814
815
22.2k
void WhitespaceManager::alignConsecutiveBitFields() {
816
22.2k
  if (!Style.AlignConsecutiveBitFields.Enabled)
817
22.1k
    return;
818
819
36
  AlignTokens(
820
36
      Style,
821
662
      [&](Change const &C) {
822
        // Do not align on ':' that is first on a line.
823
662
        if (C.NewlinesBefore > 0)
824
86
          return false;
825
826
        // Do not align on ':' that is last on a line.
827
576
        if (&C != &Changes.back() && 
(&C + 1)->NewlinesBefore > 0540
)
828
39
          return false;
829
830
537
        return C.Tok->is(TT_BitFieldColon);
831
576
      },
832
36
      Changes, /*StartAt=*/0, Style.AlignConsecutiveBitFields);
833
36
}
834
835
22.2k
void WhitespaceManager::alignConsecutiveDeclarations() {
836
22.2k
  if (!Style.AlignConsecutiveDeclarations.Enabled)
837
21.5k
    return;
838
839
676
  AlignTokens(
840
676
      Style,
841
18.7k
      [](Change const &C) {
842
        // tok::kw_operator is necessary for aligning operator overload
843
        // definitions.
844
18.7k
        if (C.Tok->isOneOf(TT_FunctionDeclarationName, tok::kw_operator))
845
346
          return true;
846
18.3k
        if (C.Tok->isNot(TT_StartOfName))
847
15.7k
          return false;
848
2.65k
        if (C.Tok->Previous &&
849
2.65k
            C.Tok->Previous->is(TT_StatementAttributeLikeMacro))
850
5
          return false;
851
        // Check if there is a subsequent name that starts the same declaration.
852
2.64k
        
for (FormatToken *Next = C.Tok->Next; 2.64k
Next;
Next = Next->Next2
) {
853
2.64k
          if (Next->is(tok::comment))
854
2
            continue;
855
2.64k
          if (Next->is(TT_PointerOrReference))
856
36
            return false;
857
2.61k
          if (!Next->Tok.getIdentifierInfo())
858
2.60k
            break;
859
2
          if (Next->isOneOf(TT_StartOfName, TT_FunctionDeclarationName,
860
2
                            tok::kw_operator))
861
2
            return false;
862
2
        }
863
2.60k
        return true;
864
2.64k
      },
865
676
      Changes, /*StartAt=*/0, Style.AlignConsecutiveDeclarations);
866
676
}
867
868
22.2k
void WhitespaceManager::alignChainedConditionals() {
869
22.2k
  if (Style.BreakBeforeTernaryOperators) {
870
20.6k
    AlignTokens(
871
20.6k
        Style,
872
352k
        [](Change const &C) {
873
          // Align question operators and last colon
874
352k
          return C.Tok->is(TT_ConditionalExpr) &&
875
352k
                 
(1.67k
(1.67k
C.Tok->is(tok::question)1.67k
&&
!C.NewlinesBefore742
) ||
876
1.67k
                  
(1.01k
C.Tok->is(tok::colon)1.01k
&&
C.Tok->Next932
&&
877
1.01k
                   
(932
C.Tok->Next->FakeLParens.size() == 0932
||
878
932
                    
C.Tok->Next->FakeLParens.back() != prec::Conditional254
)));
879
352k
        },
880
20.6k
        Changes, /*StartAt=*/0);
881
20.6k
  } else {
882
40.4k
    static auto AlignWrappedOperand = [](Change const &C) {
883
40.4k
      FormatToken *Previous = C.Tok->getPreviousNonComment();
884
40.4k
      return C.NewlinesBefore && 
Previous5.68k
&&
Previous->is(TT_ConditionalExpr)2.96k
&&
885
40.4k
             
(895
Previous->is(tok::colon)895
&&
886
895
              
(777
C.Tok->FakeLParens.size() == 0777
||
887
777
               
C.Tok->FakeLParens.back() != prec::Conditional279
));
888
40.4k
    };
889
    // Ensure we keep alignment of wrapped operands with non-wrapped operands
890
    // Since we actually align the operators, the wrapped operands need the
891
    // extra offset to be properly aligned.
892
1.60k
    for (Change &C : Changes)
893
20.2k
      if (AlignWrappedOperand(C))
894
175
        C.StartOfTokenColumn -= 2;
895
1.60k
    AlignTokens(
896
1.60k
        Style,
897
20.7k
        [this](Change const &C) {
898
          // Align question operators if next operand is not wrapped, as
899
          // well as wrapped operands after question operator or last
900
          // colon in conditional sequence
901
20.7k
          return (C.Tok->is(TT_ConditionalExpr) && 
C.Tok->is(tok::question)810
&&
902
20.7k
                  
&C != &Changes.back()521
&&
(&C + 1)->NewlinesBefore == 0521
&&
903
20.7k
                  
!(&C + 1)->IsTrailingComment476
) ||
904
20.7k
                 
AlignWrappedOperand(C)20.2k
;
905
20.7k
        },
906
1.60k
        Changes, /*StartAt=*/0);
907
1.60k
  }
908
22.2k
}
909
910
22.2k
void WhitespaceManager::alignTrailingComments() {
911
22.2k
  unsigned MinColumn = 0;
912
22.2k
  unsigned MaxColumn = UINT_MAX;
913
22.2k
  unsigned StartOfSequence = 0;
914
22.2k
  bool BreakBeforeNext = false;
915
22.2k
  unsigned Newlines = 0;
916
394k
  for (unsigned i = 0, e = Changes.size(); i != e; 
++i372k
) {
917
372k
    if (Changes[i].StartOfBlockComment)
918
714
      continue;
919
371k
    Newlines += Changes[i].NewlinesBefore;
920
371k
    if (!Changes[i].IsTrailingComment)
921
366k
      continue;
922
923
5.15k
    unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
924
5.15k
    unsigned ChangeMaxColumn;
925
926
5.15k
    if (Style.ColumnLimit == 0)
927
322
      ChangeMaxColumn = UINT_MAX;
928
4.83k
    else if (Style.ColumnLimit >= Changes[i].TokenLength)
929
4.77k
      ChangeMaxColumn = Style.ColumnLimit - Changes[i].TokenLength;
930
60
    else
931
60
      ChangeMaxColumn = ChangeMinColumn;
932
933
    // If we don't create a replacement for this change, we have to consider
934
    // it to be immovable.
935
5.15k
    if (!Changes[i].CreateReplacement)
936
469
      ChangeMaxColumn = ChangeMinColumn;
937
938
5.15k
    if (i + 1 != e && 
Changes[i + 1].ContinuesPPDirective5.13k
)
939
68
      ChangeMaxColumn -= 2;
940
    // If this comment follows an } in column 0, it probably documents the
941
    // closing of a namespace and we don't want to align it.
942
5.15k
    bool FollowsRBraceInColumn0 = i > 0 && 
Changes[i].NewlinesBefore == 04.62k
&&
943
5.15k
                                  
Changes[i - 1].Tok->is(tok::r_brace)2.33k
&&
944
5.15k
                                  
Changes[i - 1].StartOfTokenColumn == 01.04k
;
945
5.15k
    bool WasAlignedWithStartOfNextLine = false;
946
5.15k
    if (Changes[i].NewlinesBefore == 1) { // A comment on its own line.
947
2.02k
      unsigned CommentColumn = SourceMgr.getSpellingColumnNumber(
948
2.02k
          Changes[i].OriginalWhitespaceRange.getEnd());
949
10.1k
      for (unsigned j = i + 1; j != e; 
++j8.08k
) {
950
10.0k
        if (Changes[j].Tok->is(tok::comment))
951
8.08k
          continue;
952
953
2.01k
        unsigned NextColumn = SourceMgr.getSpellingColumnNumber(
954
2.01k
            Changes[j].OriginalWhitespaceRange.getEnd());
955
        // The start of the next token was previously aligned with the
956
        // start of this comment.
957
2.01k
        WasAlignedWithStartOfNextLine =
958
2.01k
            CommentColumn == NextColumn ||
959
2.01k
            
CommentColumn == NextColumn + Style.IndentWidth816
;
960
2.01k
        break;
961
10.0k
      }
962
2.02k
    }
963
5.15k
    if (!Style.AlignTrailingComments || 
FollowsRBraceInColumn05.05k
) {
964
586
      alignTrailingComments(StartOfSequence, i, MinColumn);
965
586
      MinColumn = ChangeMinColumn;
966
586
      MaxColumn = ChangeMinColumn;
967
586
      StartOfSequence = i;
968
4.56k
    } else if (BreakBeforeNext || 
Newlines > 13.13k
||
969
4.56k
               
(2.17k
ChangeMinColumn > MaxColumn2.17k
||
ChangeMaxColumn < MinColumn2.16k
) ||
970
               // Break the comment sequence if the previous line did not end
971
               // in a trailing comment.
972
4.56k
               
(2.15k
Changes[i].NewlinesBefore == 12.15k
&&
i > 0538
&&
973
2.15k
                
!Changes[i - 1].IsTrailingComment509
) ||
974
4.56k
               
WasAlignedWithStartOfNextLine1.77k
) {
975
2.87k
      alignTrailingComments(StartOfSequence, i, MinColumn);
976
2.87k
      MinColumn = ChangeMinColumn;
977
2.87k
      MaxColumn = ChangeMaxColumn;
978
2.87k
      StartOfSequence = i;
979
2.87k
    } else {
980
1.69k
      MinColumn = std::max(MinColumn, ChangeMinColumn);
981
1.69k
      MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
982
1.69k
    }
983
5.15k
    BreakBeforeNext = (i == 0) || 
(Changes[i].NewlinesBefore > 1)4.62k
||
984
                      // Never start a sequence with a comment at the beginning
985
                      // of the line.
986
5.15k
                      
(4.32k
Changes[i].NewlinesBefore == 14.32k
&&
StartOfSequence == i1.99k
);
987
5.15k
    Newlines = 0;
988
5.15k
  }
989
22.2k
  alignTrailingComments(StartOfSequence, Changes.size(), MinColumn);
990
22.2k
}
991
992
void WhitespaceManager::alignTrailingComments(unsigned Start, unsigned End,
993
25.6k
                                              unsigned Column) {
994
398k
  for (unsigned i = Start; i != End; 
++i372k
) {
995
372k
    int Shift = 0;
996
372k
    if (Changes[i].IsTrailingComment)
997
5.81k
      Shift = Column - Changes[i].StartOfTokenColumn;
998
372k
    if (Changes[i].StartOfBlockComment) {
999
714
      Shift = Changes[i].IndentationOffset +
1000
714
              Changes[i].StartOfBlockComment->StartOfTokenColumn -
1001
714
              Changes[i].StartOfTokenColumn;
1002
714
    }
1003
372k
    if (Shift < 0)
1004
0
      continue;
1005
372k
    Changes[i].Spaces += Shift;
1006
372k
    if (i + 1 != Changes.size())
1007
350k
      Changes[i + 1].PreviousEndOfTokenColumn += Shift;
1008
372k
    Changes[i].StartOfTokenColumn += Shift;
1009
372k
  }
1010
25.6k
}
1011
1012
22.2k
void WhitespaceManager::alignEscapedNewlines() {
1013
22.2k
  if (Style.AlignEscapedNewlines == FormatStyle::ENAS_DontAlign)
1014
10
    return;
1015
1016
22.2k
  bool AlignLeft = Style.AlignEscapedNewlines == FormatStyle::ENAS_Left;
1017
22.2k
  unsigned MaxEndOfLine = AlignLeft ? 
04.16k
:
Style.ColumnLimit18.0k
;
1018
22.2k
  unsigned StartOfMacro = 0;
1019
372k
  for (unsigned i = 1, e = Changes.size(); i < e; 
++i349k
) {
1020
349k
    Change &C = Changes[i];
1021
349k
    if (C.NewlinesBefore > 0) {
1022
49.5k
      if (C.ContinuesPPDirective) {
1023
658
        MaxEndOfLine = std::max(C.PreviousEndOfTokenColumn + 2, MaxEndOfLine);
1024
48.8k
      } else {
1025
48.8k
        alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);
1026
48.8k
        MaxEndOfLine = AlignLeft ? 
09.06k
:
Style.ColumnLimit39.8k
;
1027
48.8k
        StartOfMacro = i;
1028
48.8k
      }
1029
49.5k
    }
1030
349k
  }
1031
22.2k
  alignEscapedNewlines(StartOfMacro + 1, Changes.size(), MaxEndOfLine);
1032
22.2k
}
1033
1034
void WhitespaceManager::alignEscapedNewlines(unsigned Start, unsigned End,
1035
71.0k
                                             unsigned Column) {
1036
372k
  for (unsigned i = Start; i < End; 
++i301k
) {
1037
301k
    Change &C = Changes[i];
1038
301k
    if (C.NewlinesBefore > 0) {
1039
658
      assert(C.ContinuesPPDirective);
1040
658
      if (C.PreviousEndOfTokenColumn + 1 > Column)
1041
0
        C.EscapedNewlineColumn = 0;
1042
658
      else
1043
658
        C.EscapedNewlineColumn = Column;
1044
658
    }
1045
301k
  }
1046
71.0k
}
1047
1048
22.2k
void WhitespaceManager::alignArrayInitializers() {
1049
22.2k
  if (Style.AlignArrayOfStructures == FormatStyle::AIAS_None)
1050
22.0k
    return;
1051
1052
151
  for (unsigned ChangeIndex = 1U, ChangeEnd = Changes.size();
1053
1.21k
       ChangeIndex < ChangeEnd; 
++ChangeIndex1.06k
) {
1054
1.06k
    auto &C = Changes[ChangeIndex];
1055
1.06k
    if (C.Tok->IsArrayInitializer) {
1056
157
      bool FoundComplete = false;
1057
4.10k
      for (unsigned InsideIndex = ChangeIndex + 1; InsideIndex < ChangeEnd;
1058
4.10k
           
++InsideIndex3.94k
) {
1059
4.10k
        if (Changes[InsideIndex].Tok == C.Tok->MatchingParen) {
1060
157
          alignArrayInitializers(ChangeIndex, InsideIndex + 1);
1061
157
          ChangeIndex = InsideIndex + 1;
1062
157
          FoundComplete = true;
1063
157
          break;
1064
157
        }
1065
4.10k
      }
1066
157
      if (!FoundComplete)
1067
0
        ChangeIndex = ChangeEnd;
1068
157
    }
1069
1.06k
  }
1070
151
}
1071
1072
157
void WhitespaceManager::alignArrayInitializers(unsigned Start, unsigned End) {
1073
1074
157
  if (Style.AlignArrayOfStructures == FormatStyle::AIAS_Right)
1075
85
    alignArrayInitializersRightJustified(getCells(Start, End));
1076
72
  else if (Style.AlignArrayOfStructures == FormatStyle::AIAS_Left)
1077
72
    alignArrayInitializersLeftJustified(getCells(Start, End));
1078
157
}
1079
1080
void WhitespaceManager::alignArrayInitializersRightJustified(
1081
85
    CellDescriptions &&CellDescs) {
1082
85
  if (!CellDescs.isRectangular())
1083
18
    return;
1084
1085
67
  auto &Cells = CellDescs.Cells;
1086
  // Now go through and fixup the spaces.
1087
67
  auto *CellIter = Cells.begin();
1088
329
  for (auto i = 0U; i < CellDescs.CellCounts[0]; 
++i, ++CellIter262
) {
1089
262
    unsigned NetWidth = 0U;
1090
262
    if (isSplitCell(*CellIter))
1091
19
      NetWidth = getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1092
262
    auto CellWidth = getMaximumCellWidth(CellIter, NetWidth);
1093
1094
262
    if (Changes[CellIter->Index].Tok->is(tok::r_brace)) {
1095
      // So in here we want to see if there is a brace that falls
1096
      // on a line that was split. If so on that line we make sure that
1097
      // the spaces in front of the brace are enough.
1098
64
      const auto *Next = CellIter;
1099
177
      do {
1100
177
        const FormatToken *Previous = Changes[Next->Index].Tok->Previous;
1101
177
        if (Previous && Previous->isNot(TT_LineComment)) {
1102
174
          Changes[Next->Index].Spaces = 0;
1103
174
          Changes[Next->Index].NewlinesBefore = 0;
1104
174
        }
1105
177
        Next = Next->NextColumnElement;
1106
177
      } while (Next);
1107
      // Unless the array is empty, we need the position of all the
1108
      // immediately adjacent cells
1109
64
      if (CellIter != Cells.begin()) {
1110
64
        auto ThisNetWidth =
1111
64
            getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1112
64
        auto MaxNetWidth = getMaximumNetWidth(
1113
64
            Cells.begin(), CellIter, CellDescs.InitialSpaces,
1114
64
            CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1115
64
        if (ThisNetWidth < MaxNetWidth)
1116
1
          Changes[CellIter->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1117
64
        auto RowCount = 1U;
1118
64
        auto Offset = std::distance(Cells.begin(), CellIter);
1119
177
        for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
1120
113
             Next = Next->NextColumnElement) {
1121
113
          auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1122
113
          auto *End = Start + Offset;
1123
113
          ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1124
113
          if (ThisNetWidth < MaxNetWidth)
1125
1
            Changes[Next->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1126
113
          ++RowCount;
1127
113
        }
1128
64
      }
1129
198
    } else {
1130
198
      auto ThisWidth =
1131
198
          calculateCellWidth(CellIter->Index, CellIter->EndIndex, true) +
1132
198
          NetWidth;
1133
198
      if (Changes[CellIter->Index].NewlinesBefore == 0) {
1134
179
        Changes[CellIter->Index].Spaces = (CellWidth - (ThisWidth + NetWidth));
1135
179
        Changes[CellIter->Index].Spaces += (i > 0) ? 
1119
:
060
;
1136
179
      }
1137
198
      alignToStartOfCell(CellIter->Index, CellIter->EndIndex);
1138
558
      for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
1139
360
           Next = Next->NextColumnElement) {
1140
360
        ThisWidth =
1141
360
            calculateCellWidth(Next->Index, Next->EndIndex, true) + NetWidth;
1142
360
        if (Changes[Next->Index].NewlinesBefore == 0) {
1143
358
          Changes[Next->Index].Spaces = (CellWidth - ThisWidth);
1144
358
          Changes[Next->Index].Spaces += (i > 0) ? 
1245
:
0113
;
1145
358
        }
1146
360
        alignToStartOfCell(Next->Index, Next->EndIndex);
1147
360
      }
1148
198
    }
1149
262
  }
1150
67
}
1151
1152
void WhitespaceManager::alignArrayInitializersLeftJustified(
1153
72
    CellDescriptions &&CellDescs) {
1154
1155
72
  if (!CellDescs.isRectangular())
1156
18
    return;
1157
1158
54
  auto &Cells = CellDescs.Cells;
1159
  // Now go through and fixup the spaces.
1160
54
  auto *CellIter = Cells.begin();
1161
  // The first cell needs to be against the left brace.
1162
54
  if (Changes[CellIter->Index].NewlinesBefore == 0)
1163
47
    Changes[CellIter->Index].Spaces = 0;
1164
7
  else
1165
7
    Changes[CellIter->Index].Spaces = CellDescs.InitialSpaces;
1166
54
  ++CellIter;
1167
207
  for (auto i = 1U; i < CellDescs.CellCounts[0]; 
i++, ++CellIter153
) {
1168
153
    auto MaxNetWidth = getMaximumNetWidth(
1169
153
        Cells.begin(), CellIter, CellDescs.InitialSpaces,
1170
153
        CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1171
153
    auto ThisNetWidth =
1172
153
        getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1173
153
    if (Changes[CellIter->Index].NewlinesBefore == 0) {
1174
145
      Changes[CellIter->Index].Spaces =
1175
145
          MaxNetWidth - ThisNetWidth +
1176
145
          (Changes[CellIter->Index].Tok->isNot(tok::r_brace) ? 
197
:
048
);
1177
145
    }
1178
153
    auto RowCount = 1U;
1179
153
    auto Offset = std::distance(Cells.begin(), CellIter);
1180
435
    for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
1181
282
         Next = Next->NextColumnElement) {
1182
282
      if (RowCount > CellDescs.CellCounts.size())
1183
0
        break;
1184
282
      auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1185
282
      auto *End = Start + Offset;
1186
282
      auto ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1187
282
      if (Changes[Next->Index].NewlinesBefore == 0) {
1188
280
        Changes[Next->Index].Spaces =
1189
280
            MaxNetWidth - ThisNetWidth +
1190
280
            (Changes[Next->Index].Tok->isNot(tok::r_brace) ? 
1190
:
090
);
1191
280
      }
1192
282
      ++RowCount;
1193
282
    }
1194
153
  }
1195
54
}
1196
1197
262
bool WhitespaceManager::isSplitCell(const CellDescription &Cell) {
1198
262
  if (Cell.HasSplit)
1199
19
    return true;
1200
702
  
for (const auto *Next = Cell.NextColumnElement; 243
Next != nullptr;
1201
459
       Next = Next->NextColumnElement)
1202
459
    if (Next->HasSplit)
1203
0
      return true;
1204
243
  return false;
1205
243
}
1206
1207
WhitespaceManager::CellDescriptions WhitespaceManager::getCells(unsigned Start,
1208
157
                                                                unsigned End) {
1209
1210
157
  unsigned Depth = 0;
1211
157
  unsigned Cell = 0;
1212
157
  SmallVector<unsigned> CellCounts;
1213
157
  unsigned InitialSpaces = 0;
1214
157
  unsigned InitialTokenLength = 0;
1215
157
  unsigned EndSpaces = 0;
1216
157
  SmallVector<CellDescription> Cells;
1217
157
  const FormatToken *MatchingParen = nullptr;
1218
4.39k
  for (unsigned i = Start; i < End; 
++i4.23k
) {
1219
4.23k
    auto &C = Changes[i];
1220
4.23k
    if (C.Tok->is(tok::l_brace))
1221
667
      ++Depth;
1222
3.56k
    else if (C.Tok->is(tok::r_brace))
1223
667
      --Depth;
1224
4.23k
    if (Depth == 2) {
1225
2.76k
      if (C.Tok->is(tok::l_brace)) {
1226
432
        Cell = 0;
1227
432
        MatchingParen = C.Tok->MatchingParen;
1228
432
        if (InitialSpaces == 0) {
1229
157
          InitialSpaces = C.Spaces + C.TokenLength;
1230
157
          InitialTokenLength = C.TokenLength;
1231
157
          auto j = i - 1;
1232
157
          for (; Changes[j].NewlinesBefore == 0 && 
j > Start146
;
--j0
) {
1233
0
            InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1234
0
            InitialTokenLength += Changes[j].TokenLength;
1235
0
          }
1236
157
          if (C.NewlinesBefore == 0) {
1237
11
            InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1238
11
            InitialTokenLength += Changes[j].TokenLength;
1239
11
          }
1240
157
        }
1241
2.33k
      } else if (C.Tok->is(tok::comma)) {
1242
894
        if (!Cells.empty())
1243
894
          Cells.back().EndIndex = i;
1244
894
        if (C.Tok->getNextNonComment()->isNot(tok::r_brace)) // dangling comma
1245
885
          ++Cell;
1246
894
      }
1247
2.76k
    } else 
if (1.46k
Depth == 11.46k
) {
1248
1.00k
      if (C.Tok == MatchingParen) {
1249
432
        if (!Cells.empty())
1250
420
          Cells.back().EndIndex = i;
1251
432
        Cells.push_back(CellDescription{i, ++Cell, i + 1, false, nullptr});
1252
432
        CellCounts.push_back(C.Tok->Previous->isNot(tok::comma) ? 
Cell + 1429
1253
432
                                                                : 
Cell3
);
1254
        // Go to the next non-comment and ensure there is a break in front
1255
432
        const auto *NextNonComment = C.Tok->getNextNonComment();
1256
735
        while (NextNonComment->is(tok::comma))
1257
303
          NextNonComment = NextNonComment->getNextNonComment();
1258
432
        auto j = i;
1259
1.25k
        while (Changes[j].Tok != NextNonComment && 
j < End819
)
1260
819
          ++j;
1261
432
        if (j < End && Changes[j].NewlinesBefore == 0 &&
1262
432
            
Changes[j].Tok->isNot(tok::r_brace)243
) {
1263
138
          Changes[j].NewlinesBefore = 1;
1264
          // Account for the added token lengths
1265
138
          Changes[j].Spaces = InitialSpaces - InitialTokenLength;
1266
138
        }
1267
571
      } else if (C.Tok->is(tok::comment)) {
1268
        // Trailing comments stay at a space past the last token
1269
54
        C.Spaces = Changes[i - 1].Tok->is(tok::comma) ? 
130
:
224
;
1270
517
      } else if (C.Tok->is(tok::l_brace)) {
1271
        // We need to make sure that the ending braces is aligned to the
1272
        // start of our initializer
1273
157
        auto j = i - 1;
1274
863
        for (; j > 0 && 
!Changes[j].Tok->ArrayInitializerLineStart718
;
--j706
)
1275
706
          ; // Nothing the loop does the work
1276
157
        EndSpaces = Changes[j].Spaces;
1277
157
      }
1278
1.00k
    } else 
if (463
Depth == 0463
&&
C.Tok->is(tok::r_brace)157
) {
1279
157
      C.NewlinesBefore = 1;
1280
157
      C.Spaces = EndSpaces;
1281
157
    }
1282
4.23k
    if (C.Tok->StartsColumn) {
1283
      // This gets us past tokens that have been split over multiple
1284
      // lines
1285
1.32k
      bool HasSplit = false;
1286
1.32k
      if (Changes[i].NewlinesBefore > 0) {
1287
        // So if we split a line previously and the tail line + this token is
1288
        // less then the column limit we remove the split here and just put
1289
        // the column start at a space past the comma
1290
        //
1291
        // FIXME This if branch covers the cases where the column is not
1292
        // the first column. This leads to weird pathologies like the formatting
1293
        // auto foo = Items{
1294
        //     Section{
1295
        //             0, bar(),
1296
        //     }
1297
        // };
1298
        // Well if it doesn't lead to that it's indicative that the line
1299
        // breaking should be revisited. Unfortunately alot of other options
1300
        // interact with this
1301
45
        auto j = i - 1;
1302
45
        if ((j - 1) > Start && 
Changes[j].Tok->is(tok::comma)36
&&
1303
45
            
Changes[j - 1].NewlinesBefore > 031
) {
1304
4
          --j;
1305
4
          auto LineLimit = Changes[j].Spaces + Changes[j].TokenLength;
1306
4
          if (LineLimit < Style.ColumnLimit) {
1307
4
            Changes[i].NewlinesBefore = 0;
1308
4
            Changes[i].Spaces = 1;
1309
4
          }
1310
4
        }
1311
45
      }
1312
1.39k
      while (Changes[i].NewlinesBefore > 0 && 
Changes[i].Tok == C.Tok76
) {
1313
70
        Changes[i].Spaces = InitialSpaces;
1314
70
        ++i;
1315
70
        HasSplit = true;
1316
70
      }
1317
1.32k
      if (Changes[i].Tok != C.Tok)
1318
41
        --i;
1319
1.32k
      Cells.push_back(CellDescription{i, Cell, i, HasSplit, nullptr});
1320
1.32k
    }
1321
4.23k
  }
1322
1323
157
  return linkCells({Cells, CellCounts, InitialSpaces});
1324
157
}
1325
1326
unsigned WhitespaceManager::calculateCellWidth(unsigned Start, unsigned End,
1327
4.16k
                                               bool WithSpaces) const {
1328
4.16k
  unsigned CellWidth = 0;
1329
10.1k
  for (auto i = Start; i < End; 
i++6.00k
) {
1330
6.00k
    if (Changes[i].NewlinesBefore > 0)
1331
162
      CellWidth = 0;
1332
6.00k
    CellWidth += Changes[i].TokenLength;
1333
6.00k
    CellWidth += (WithSpaces ? Changes[i].Spaces : 
00
);
1334
6.00k
  }
1335
4.16k
  return CellWidth;
1336
4.16k
}
1337
1338
558
void WhitespaceManager::alignToStartOfCell(unsigned Start, unsigned End) {
1339
558
  if ((End - Start) <= 1)
1340
452
    return;
1341
  // If the line is broken anywhere in there make sure everything
1342
  // is aligned to the parent
1343
371
  
for (auto i = Start + 1; 106
i < End;
i++265
)
1344
265
    if (Changes[i].NewlinesBefore > 0)
1345
6
      Changes[i].Spaces = Changes[Start].Spaces;
1346
106
}
1347
1348
WhitespaceManager::CellDescriptions
1349
157
WhitespaceManager::linkCells(CellDescriptions &&CellDesc) {
1350
157
  auto &Cells = CellDesc.Cells;
1351
1.91k
  for (auto *CellIter = Cells.begin(); CellIter != Cells.end(); 
++CellIter1.75k
) {
1352
1.75k
    if (CellIter->NextColumnElement == nullptr &&
1353
1.75k
        ((CellIter + 1) != Cells.end())) {
1354
6.26k
      for (auto *NextIter = CellIter + 1; NextIter != Cells.end(); 
++NextIter4.66k
) {
1355
5.75k
        if (NextIter->Cell == CellIter->Cell) {
1356
1.09k
          CellIter->NextColumnElement = &(*NextIter);
1357
1.09k
          break;
1358
1.09k
        }
1359
5.75k
      }
1360
1.60k
    }
1361
1.75k
  }
1362
157
  return std::move(CellDesc);
1363
157
}
1364
1365
22.2k
void WhitespaceManager::generateChanges() {
1366
394k
  for (unsigned i = 0, e = Changes.size(); i != e; 
++i372k
) {
1367
372k
    const Change &C = Changes[i];
1368
372k
    if (i > 0 && Changes[i - 1].OriginalWhitespaceRange.getBegin() ==
1369
350k
                     C.OriginalWhitespaceRange.getBegin()) {
1370
      // Do not generate two replacements for the same location.
1371
0
      continue;
1372
0
    }
1373
372k
    if (C.CreateReplacement) {
1374
348k
      std::string ReplacementText = C.PreviousLinePostfix;
1375
348k
      if (C.ContinuesPPDirective)
1376
639
        appendEscapedNewlineText(ReplacementText, C.NewlinesBefore,
1377
639
                                 C.PreviousEndOfTokenColumn,
1378
639
                                 C.EscapedNewlineColumn);
1379
347k
      else
1380
347k
        appendNewlineText(ReplacementText, C.NewlinesBefore);
1381
      // FIXME: This assert should hold if we computed the column correctly.
1382
      // assert((int)C.StartOfTokenColumn >= C.Spaces);
1383
348k
      appendIndentText(
1384
348k
          ReplacementText, C.Tok->IndentLevel, std::max(0, C.Spaces),
1385
348k
          std::max((int)C.StartOfTokenColumn, C.Spaces) - std::max(0, C.Spaces),
1386
348k
          C.IsAligned);
1387
348k
      ReplacementText.append(C.CurrentLinePrefix);
1388
348k
      storeReplacement(C.OriginalWhitespaceRange, ReplacementText);
1389
348k
    }
1390
372k
  }
1391
22.2k
}
1392
1393
348k
void WhitespaceManager::storeReplacement(SourceRange Range, StringRef Text) {
1394
348k
  unsigned WhitespaceLength = SourceMgr.getFileOffset(Range.getEnd()) -
1395
348k
                              SourceMgr.getFileOffset(Range.getBegin());
1396
  // Don't create a replacement, if it does not change anything.
1397
348k
  if (StringRef(SourceMgr.getCharacterData(Range.getBegin()),
1398
348k
                WhitespaceLength) == Text)
1399
319k
    return;
1400
28.9k
  auto Err = Replaces.add(tooling::Replacement(
1401
28.9k
      SourceMgr, CharSourceRange::getCharRange(Range), Text));
1402
  // FIXME: better error handling. For now, just print an error message in the
1403
  // release version.
1404
28.9k
  if (Err) {
1405
0
    llvm::errs() << llvm::toString(std::move(Err)) << "\n";
1406
0
    assert(false);
1407
0
  }
1408
28.9k
}
1409
1410
void WhitespaceManager::appendNewlineText(std::string &Text,
1411
347k
                                          unsigned Newlines) {
1412
347k
  if (UseCRLF) {
1413
472
    Text.reserve(Text.size() + 2 * Newlines);
1414
661
    for (unsigned i = 0; i < Newlines; 
++i189
)
1415
189
      Text.append("\r\n");
1416
347k
  } else {
1417
347k
    Text.append(Newlines, '\n');
1418
347k
  }
1419
347k
}
1420
1421
void WhitespaceManager::appendEscapedNewlineText(
1422
    std::string &Text, unsigned Newlines, unsigned PreviousEndOfTokenColumn,
1423
639
    unsigned EscapedNewlineColumn) {
1424
639
  if (Newlines > 0) {
1425
636
    unsigned Spaces =
1426
636
        std::max<int>(1, EscapedNewlineColumn - PreviousEndOfTokenColumn - 1);
1427
1.27k
    for (unsigned i = 0; i < Newlines; 
++i641
) {
1428
641
      Text.append(Spaces, ' ');
1429
641
      Text.append(UseCRLF ? 
"\\\r\n"7
:
"\\\n"634
);
1430
641
      Spaces = std::max<int>(0, EscapedNewlineColumn - 1);
1431
641
    }
1432
636
  }
1433
639
}
1434
1435
void WhitespaceManager::appendIndentText(std::string &Text,
1436
                                         unsigned IndentLevel, unsigned Spaces,
1437
                                         unsigned WhitespaceStartColumn,
1438
348k
                                         bool IsAligned) {
1439
348k
  switch (Style.UseTab) {
1440
345k
  case FormatStyle::UT_Never:
1441
345k
    Text.append(Spaces, ' ');
1442
345k
    break;
1443
571
  case FormatStyle::UT_Always: {
1444
571
    if (Style.TabWidth) {
1445
553
      unsigned FirstTabWidth =
1446
553
          Style.TabWidth - WhitespaceStartColumn % Style.TabWidth;
1447
1448
      // Insert only spaces when we want to end up before the next tab.
1449
553
      if (Spaces < FirstTabWidth || 
Spaces == 1125
) {
1450
449
        Text.append(Spaces, ' ');
1451
449
        break;
1452
449
      }
1453
      // Align to the next tab.
1454
104
      Spaces -= FirstTabWidth;
1455
104
      Text.append("\t");
1456
1457
104
      Text.append(Spaces / Style.TabWidth, '\t');
1458
104
      Text.append(Spaces % Style.TabWidth, ' ');
1459
104
    } else 
if (18
Spaces == 118
) {
1460
2
      Text.append(Spaces, ' ');
1461
2
    }
1462
122
    break;
1463
571
  }
1464
565
  case FormatStyle::UT_ForIndentation:
1465
565
    if (WhitespaceStartColumn == 0) {
1466
237
      unsigned Indentation = IndentLevel * Style.IndentWidth;
1467
237
      Spaces = appendTabIndent(Text, Spaces, Indentation);
1468
237
    }
1469
565
    Text.append(Spaces, ' ');
1470
565
    break;
1471
738
  case FormatStyle::UT_ForContinuationAndIndentation:
1472
738
    if (WhitespaceStartColumn == 0)
1473
319
      Spaces = appendTabIndent(Text, Spaces, Spaces);
1474
738
    Text.append(Spaces, ' ');
1475
738
    break;
1476
840
  case FormatStyle::UT_AlignWithSpaces:
1477
840
    if (WhitespaceStartColumn == 0) {
1478
358
      unsigned Indentation =
1479
358
          IsAligned ? 
IndentLevel * Style.IndentWidth57
:
Spaces301
;
1480
358
      Spaces = appendTabIndent(Text, Spaces, Indentation);
1481
358
    }
1482
840
    Text.append(Spaces, ' ');
1483
840
    break;
1484
348k
  }
1485
348k
}
1486
1487
unsigned WhitespaceManager::appendTabIndent(std::string &Text, unsigned Spaces,
1488
914
                                            unsigned Indentation) {
1489
  // This happens, e.g. when a line in a block comment is indented less than the
1490
  // first one.
1491
914
  if (Indentation > Spaces)
1492
4
    Indentation = Spaces;
1493
914
  if (Style.TabWidth) {
1494
890
    unsigned Tabs = Indentation / Style.TabWidth;
1495
890
    Text.append(Tabs, '\t');
1496
890
    Spaces -= Tabs * Style.TabWidth;
1497
890
  }
1498
914
  return Spaces;
1499
914
}
1500
1501
} // namespace format
1502
} // namespace clang