Coverage Report

Created: 2022-07-16 07:03

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