/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Format/UnwrappedLineFormatter.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- UnwrappedLineFormatter.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 | | #include "UnwrappedLineFormatter.h" |
10 | | #include "NamespaceEndCommentsFixer.h" |
11 | | #include "WhitespaceManager.h" |
12 | | #include "llvm/Support/Debug.h" |
13 | | #include <queue> |
14 | | |
15 | | #define DEBUG_TYPE "format-formatter" |
16 | | |
17 | | namespace clang { |
18 | | namespace format { |
19 | | |
20 | | namespace { |
21 | | |
22 | 5.73k | bool startsExternCBlock(const AnnotatedLine &Line) { |
23 | 5.73k | const FormatToken *Next = Line.First->getNextNonComment(); |
24 | 5.73k | const FormatToken *NextNext = Next ? Next->getNextNonComment()4.77k : nullptr960 ; |
25 | 5.73k | return Line.startsWith(tok::kw_extern) && Next46 && Next->isStringLiteral()46 && |
26 | 5.73k | NextNext46 && NextNext->is(tok::l_brace)46 ; |
27 | 5.73k | } |
28 | | |
29 | 5.13k | bool isRecordLBrace(const FormatToken &Tok) { |
30 | 5.13k | return Tok.isOneOf(TT_ClassLBrace, TT_EnumLBrace, TT_RecordLBrace, |
31 | 5.13k | TT_StructLBrace, TT_UnionLBrace); |
32 | 5.13k | } |
33 | | |
34 | | /// Tracks the indent level of \c AnnotatedLines across levels. |
35 | | /// |
36 | | /// \c nextLine must be called for each \c AnnotatedLine, after which \c |
37 | | /// getIndent() will return the indent for the last line \c nextLine was called |
38 | | /// with. |
39 | | /// If the line is not formatted (and thus the indent does not change), calling |
40 | | /// \c adjustToUnmodifiedLine after the call to \c nextLine will cause |
41 | | /// subsequent lines on the same level to be indented at the same level as the |
42 | | /// given line. |
43 | | class LevelIndentTracker { |
44 | | public: |
45 | | LevelIndentTracker(const FormatStyle &Style, |
46 | | const AdditionalKeywords &Keywords, unsigned StartLevel, |
47 | | int AdditionalIndent) |
48 | 24.5k | : Style(Style), Keywords(Keywords), AdditionalIndent(AdditionalIndent) { |
49 | 27.2k | for (unsigned i = 0; i != StartLevel; ++i2.64k ) |
50 | 2.64k | IndentForLevel.push_back(Style.IndentWidth * i + AdditionalIndent); |
51 | 24.5k | } |
52 | | |
53 | | /// Returns the indent for the current line. |
54 | 159k | unsigned getIndent() const { return Indent; } |
55 | | |
56 | | /// Update the indent state given that \p Line is going to be formatted |
57 | | /// next. |
58 | 80.0k | void nextLine(const AnnotatedLine &Line) { |
59 | 80.0k | Offset = getIndentOffset(*Line.First); |
60 | | // Update the indent level cache size so that we can rely on it |
61 | | // having the right size in adjustToUnmodifiedline. |
62 | 111k | while (IndentForLevel.size() <= Line.Level) |
63 | 31.9k | IndentForLevel.push_back(-1); |
64 | 80.0k | if (Line.InPPDirective) { |
65 | 4.61k | unsigned IndentWidth = |
66 | 4.61k | (Style.PPIndentWidth >= 0) ? Style.PPIndentWidth27 : Style.IndentWidth4.58k ; |
67 | 4.61k | Indent = Line.Level * IndentWidth + AdditionalIndent; |
68 | 75.4k | } else { |
69 | 75.4k | IndentForLevel.resize(Line.Level + 1); |
70 | 75.4k | Indent = getIndent(Line.Level); |
71 | 75.4k | } |
72 | 80.0k | if (static_cast<int>(Indent) + Offset >= 0) |
73 | 79.9k | Indent += Offset; |
74 | 80.0k | if (Line.First->is(TT_CSharpGenericTypeConstraint)) |
75 | 12 | Indent = Line.Level * Style.IndentWidth + Style.ContinuationIndentWidth; |
76 | 80.0k | } |
77 | | |
78 | | /// Update the indent state given that \p Line indent should be |
79 | | /// skipped. |
80 | 23 | void skipLine(const AnnotatedLine &Line) { |
81 | 26 | while (IndentForLevel.size() <= Line.Level) |
82 | 3 | IndentForLevel.push_back(Indent); |
83 | 23 | } |
84 | | |
85 | | /// Update the level indent to adapt to the given \p Line. |
86 | | /// |
87 | | /// When a line is not formatted, we move the subsequent lines on the same |
88 | | /// level to the same indent. |
89 | | /// Note that \c nextLine must have been called before this method. |
90 | 5.20k | void adjustToUnmodifiedLine(const AnnotatedLine &Line) { |
91 | 5.20k | unsigned LevelIndent = Line.First->OriginalColumn; |
92 | 5.20k | if (static_cast<int>(LevelIndent) - Offset >= 0) |
93 | 5.20k | LevelIndent -= Offset; |
94 | 5.20k | if ((!Line.First->is(tok::comment) || IndentForLevel[Line.Level] == -19 ) && |
95 | 5.20k | !Line.InPPDirective5.19k ) |
96 | 4.78k | IndentForLevel[Line.Level] = LevelIndent; |
97 | 5.20k | } |
98 | | |
99 | | private: |
100 | | /// Get the offset of the line relatively to the level. |
101 | | /// |
102 | | /// For example, 'public:' labels in classes are offset by 1 or 2 |
103 | | /// characters to the left from their level. |
104 | 80.0k | int getIndentOffset(const FormatToken &RootToken) { |
105 | 80.0k | if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript()79.0k || |
106 | 80.0k | Style.isCSharp()74.4k ) |
107 | 8.20k | return 0; |
108 | | |
109 | 71.8k | auto IsAccessModifier = [this, &RootToken]() { |
110 | 71.8k | if (RootToken.isAccessSpecifier(Style.isCpp())) |
111 | 642 | return true; |
112 | 71.1k | else if (RootToken.isObjCAccessSpecifier()) |
113 | 49 | return true; |
114 | | // Handle Qt signals. |
115 | 71.1k | else if ((RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) && |
116 | 71.1k | RootToken.Next15 && RootToken.Next->is(tok::colon)15 )) |
117 | 6 | return true; |
118 | 71.1k | else if (RootToken.Next && |
119 | 71.1k | RootToken.Next->isOneOf(Keywords.kw_slots, Keywords.kw_qslots)43.8k && |
120 | 71.1k | RootToken.Next->Next18 && RootToken.Next->Next->is(tok::colon)18 ) |
121 | 18 | return true; |
122 | | // Handle malformed access specifier e.g. 'private' without trailing ':'. |
123 | 71.1k | else if (!RootToken.Next && RootToken.isAccessSpecifier(false)27.3k ) |
124 | 15 | return true; |
125 | 71.0k | return false; |
126 | 71.8k | }; |
127 | | |
128 | 71.8k | if (IsAccessModifier()) { |
129 | | // The AccessModifierOffset may be overridden by IndentAccessModifiers, |
130 | | // in which case we take a negative value of the IndentWidth to simulate |
131 | | // the upper indent level. |
132 | 730 | return Style.IndentAccessModifiers ? -Style.IndentWidth15 |
133 | 730 | : Style.AccessModifierOffset715 ; |
134 | 730 | } |
135 | 71.0k | return 0; |
136 | 71.8k | } |
137 | | |
138 | | /// Get the indent of \p Level from \p IndentForLevel. |
139 | | /// |
140 | | /// \p IndentForLevel must contain the indent for the level \c l |
141 | | /// at \p IndentForLevel[l], or a value < 0 if the indent for |
142 | | /// that level is unknown. |
143 | 93.6k | unsigned getIndent(unsigned Level) const { |
144 | 93.6k | if (IndentForLevel[Level] != -1) |
145 | 10.1k | return IndentForLevel[Level]; |
146 | 83.5k | if (Level == 0) |
147 | 65.2k | return 0; |
148 | 18.2k | return getIndent(Level - 1) + Style.IndentWidth; |
149 | 83.5k | } |
150 | | |
151 | | const FormatStyle &Style; |
152 | | const AdditionalKeywords &Keywords; |
153 | | const unsigned AdditionalIndent; |
154 | | |
155 | | /// The indent in characters for each level. |
156 | | std::vector<int> IndentForLevel; |
157 | | |
158 | | /// Offset of the current line relative to the indent level. |
159 | | /// |
160 | | /// For example, the 'public' keywords is often indented with a negative |
161 | | /// offset. |
162 | | int Offset = 0; |
163 | | |
164 | | /// The current line's indent. |
165 | | unsigned Indent = 0; |
166 | | }; |
167 | | |
168 | | const FormatToken *getMatchingNamespaceToken( |
169 | | const AnnotatedLine *Line, |
170 | 77 | const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { |
171 | 77 | if (!Line->startsWith(tok::r_brace)) |
172 | 30 | return nullptr; |
173 | 47 | size_t StartLineIndex = Line->MatchingOpeningBlockLineIndex; |
174 | 47 | if (StartLineIndex == UnwrappedLine::kInvalidIndex) |
175 | 0 | return nullptr; |
176 | 47 | assert(StartLineIndex < AnnotatedLines.size()); |
177 | 0 | return AnnotatedLines[StartLineIndex]->First->getNamespaceToken(); |
178 | 47 | } |
179 | | |
180 | 59 | StringRef getNamespaceTokenText(const AnnotatedLine *Line) { |
181 | 59 | const FormatToken *NamespaceToken = Line->First->getNamespaceToken(); |
182 | 59 | return NamespaceToken ? NamespaceToken->TokenText30 : StringRef()29 ; |
183 | 59 | } |
184 | | |
185 | | StringRef getMatchingNamespaceTokenText( |
186 | | const AnnotatedLine *Line, |
187 | 47 | const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { |
188 | 47 | const FormatToken *NamespaceToken = |
189 | 47 | getMatchingNamespaceToken(Line, AnnotatedLines); |
190 | 47 | return NamespaceToken ? NamespaceToken->TokenText25 : StringRef()22 ; |
191 | 47 | } |
192 | | |
193 | | class LineJoiner { |
194 | | public: |
195 | | LineJoiner(const FormatStyle &Style, const AdditionalKeywords &Keywords, |
196 | | const SmallVectorImpl<AnnotatedLine *> &Lines) |
197 | | : Style(Style), Keywords(Keywords), End(Lines.end()), Next(Lines.begin()), |
198 | 25.2k | AnnotatedLines(Lines) {} |
199 | | |
200 | | /// Returns the next line, merging multiple lines into one if possible. |
201 | | const AnnotatedLine *getNextMergedLine(bool DryRun, |
202 | 104k | LevelIndentTracker &IndentTracker) { |
203 | 104k | if (Next == End) |
204 | 24.5k | return nullptr; |
205 | 79.9k | const AnnotatedLine *Current = *Next; |
206 | 79.9k | IndentTracker.nextLine(*Current); |
207 | 79.9k | unsigned MergedLines = tryFitMultipleLinesInOne(IndentTracker, Next, End); |
208 | 79.9k | if (MergedLines > 0 && Style.ColumnLimit == 05.96k ) |
209 | | // Disallow line merging if there is a break at the start of one of the |
210 | | // input lines. |
211 | 97 | for (unsigned i = 0; 42 i < MergedLines; ++i55 ) |
212 | 55 | if (Next[i + 1]->First->NewlinesBefore > 0) |
213 | 2 | MergedLines = 0; |
214 | 79.9k | if (!DryRun) |
215 | 84.3k | for (unsigned i = 0; 77.0k i < MergedLines; ++i7.31k ) |
216 | 7.31k | join(*Next[0], *Next[i + 1]); |
217 | 79.9k | Next = Next + MergedLines + 1; |
218 | 79.9k | return Current; |
219 | 104k | } |
220 | | |
221 | | private: |
222 | | /// Calculates how many lines can be merged into 1 starting at \p I. |
223 | | unsigned |
224 | | tryFitMultipleLinesInOne(LevelIndentTracker &IndentTracker, |
225 | | SmallVectorImpl<AnnotatedLine *>::const_iterator I, |
226 | 79.9k | SmallVectorImpl<AnnotatedLine *>::const_iterator E) { |
227 | 79.9k | const unsigned Indent = IndentTracker.getIndent(); |
228 | | |
229 | | // Can't join the last line with anything. |
230 | 79.9k | if (I + 1 == E) |
231 | 24.4k | return 0; |
232 | | // We can never merge stuff if there are trailing line comments. |
233 | 55.5k | const AnnotatedLine *TheLine = *I; |
234 | 55.5k | if (TheLine->Last->is(TT_LineComment)) |
235 | 2.68k | return 0; |
236 | 52.9k | const auto &NextLine = *I[1]; |
237 | 52.9k | if (NextLine.Type == LT_Invalid || NextLine.First->MustBreakBefore52.8k ) |
238 | 1.24k | return 0; |
239 | 51.6k | if (TheLine->InPPDirective && |
240 | 51.6k | (3.43k !NextLine.InPPDirective3.43k || NextLine.First->HasUnescapedNewline1.98k )) |
241 | 2.16k | return 0; |
242 | | |
243 | 49.4k | if (Style.ColumnLimit > 0 && Indent > Style.ColumnLimit48.2k ) |
244 | 0 | return 0; |
245 | | |
246 | 49.4k | unsigned Limit = |
247 | 49.4k | Style.ColumnLimit == 0 ? UINT_MAX : Style.ColumnLimit - Indent48.2k ; |
248 | | // If we already exceed the column limit, we set 'Limit' to 0. The different |
249 | | // tryMerge..() functions can then decide whether to still do merging. |
250 | 49.4k | Limit = TheLine->Last->TotalLength > Limit |
251 | 49.4k | ? 06.27k |
252 | 49.4k | : Limit - TheLine->Last->TotalLength43.2k ; |
253 | | |
254 | 49.4k | if (TheLine->Last->is(TT_FunctionLBrace) && |
255 | 49.4k | TheLine->First == TheLine->Last4.83k && |
256 | 49.4k | !Style.BraceWrapping.SplitEmptyFunction455 && |
257 | 49.4k | NextLine.First->is(tok::r_brace)27 ) |
258 | 12 | return tryMergeSimpleBlock(I, E, Limit); |
259 | | |
260 | 49.4k | const auto *PreviousLine = I != AnnotatedLines.begin() ? I[-1]27.9k : nullptr21.5k ; |
261 | | // Handle empty record blocks where the brace has already been wrapped. |
262 | 49.4k | if (PreviousLine && TheLine->Last->is(tok::l_brace)27.9k && |
263 | 49.4k | TheLine->First == TheLine->Last6.86k ) { |
264 | 1.53k | bool EmptyBlock = NextLine.First->is(tok::r_brace); |
265 | | |
266 | 1.53k | const FormatToken *Tok = PreviousLine->First; |
267 | 1.53k | if (Tok && Tok->is(tok::comment)) |
268 | 33 | Tok = Tok->getNextNonComment(); |
269 | | |
270 | 1.53k | if (Tok && Tok->getNamespaceToken()1.52k ) |
271 | 80 | return !Style.BraceWrapping.SplitEmptyNamespace && EmptyBlock18 |
272 | 80 | ? tryMergeSimpleBlock(I, E, Limit)15 |
273 | 80 | : 065 ; |
274 | | |
275 | 1.45k | if (Tok && Tok->is(tok::kw_typedef)1.44k ) |
276 | 21 | Tok = Tok->getNextNonComment(); |
277 | 1.45k | if (Tok && Tok->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union, |
278 | 1.44k | tok::kw_extern, Keywords.kw_interface)) |
279 | 174 | return !Style.BraceWrapping.SplitEmptyRecord && EmptyBlock60 |
280 | 174 | ? tryMergeSimpleBlock(I, E, Limit)30 |
281 | 174 | : 0144 ; |
282 | | |
283 | 1.27k | if (Tok && Tok->is(tok::kw_template)1.27k && |
284 | 1.27k | Style.BraceWrapping.SplitEmptyRecord36 && EmptyBlock30 ) |
285 | 9 | return 0; |
286 | 1.27k | } |
287 | | |
288 | 49.2k | auto ShouldMergeShortFunctions = [this, &I, &NextLine, PreviousLine, |
289 | 49.2k | TheLine]() { |
290 | 49.2k | if (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All) |
291 | 41.5k | return true; |
292 | 7.66k | if (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty && |
293 | 7.66k | NextLine.First->is(tok::r_brace)6.21k ) |
294 | 1.19k | return true; |
295 | | |
296 | 6.46k | if (Style.AllowShortFunctionsOnASingleLine & |
297 | 6.46k | FormatStyle::SFS_InlineOnly) { |
298 | | // Just checking TheLine->Level != 0 is not enough, because it |
299 | | // provokes treating functions inside indented namespaces as short. |
300 | 540 | if (Style.isJavaScript() && TheLine->Last->is(TT_FunctionLBrace)20 ) |
301 | 4 | return true; |
302 | | |
303 | 536 | if (TheLine->Level != 0) { |
304 | 167 | if (!PreviousLine) |
305 | 0 | return false; |
306 | | |
307 | | // TODO: Use IndentTracker to avoid loop? |
308 | | // Find the last line with lower level. |
309 | 167 | const AnnotatedLine *Line = nullptr; |
310 | 200 | for (auto J = I - 1; J >= AnnotatedLines.begin(); --J33 ) { |
311 | 191 | assert(*J); |
312 | 191 | if (!(*J)->InPPDirective && !(*J)->isComment()182 && |
313 | 191 | (*J)->Level < TheLine->Level170 ) { |
314 | 158 | Line = *J; |
315 | 158 | break; |
316 | 158 | } |
317 | 191 | } |
318 | | |
319 | 167 | if (!Line) |
320 | 9 | return false; |
321 | | |
322 | | // Check if the found line starts a record. |
323 | 158 | const FormatToken *LastNonComment = Line->Last; |
324 | 158 | assert(LastNonComment); |
325 | 158 | if (LastNonComment->is(tok::comment)) { |
326 | 12 | LastNonComment = LastNonComment->getPreviousNonComment(); |
327 | | // There must be another token (usually `{`), because we chose a |
328 | | // non-PPDirective and non-comment line that has a smaller level. |
329 | 12 | assert(LastNonComment); |
330 | 12 | } |
331 | 0 | return isRecordLBrace(*LastNonComment); |
332 | 167 | } |
333 | 536 | } |
334 | | |
335 | 6.29k | return false; |
336 | 6.46k | }; |
337 | | |
338 | 49.2k | bool MergeShortFunctions = ShouldMergeShortFunctions(); |
339 | | |
340 | 49.2k | const FormatToken *FirstNonComment = TheLine->First; |
341 | 49.2k | if (FirstNonComment->is(tok::comment)) { |
342 | 467 | FirstNonComment = FirstNonComment->getNextNonComment(); |
343 | 467 | if (!FirstNonComment) |
344 | 371 | return 0; |
345 | 467 | } |
346 | | // FIXME: There are probably cases where we should use FirstNonComment |
347 | | // instead of TheLine->First. |
348 | | |
349 | 48.8k | if (Style.CompactNamespaces) { |
350 | 66 | if (auto nsToken = TheLine->First->getNamespaceToken()) { |
351 | 36 | int i = 0; |
352 | 36 | unsigned closingLine = TheLine->MatchingClosingBlockLineIndex - 1; |
353 | 59 | for (; I + 1 + i != E && |
354 | 59 | nsToken->TokenText == getNamespaceTokenText(I[i + 1]) && |
355 | 59 | closingLine == I[i + 1]->MatchingClosingBlockLineIndex27 && |
356 | 59 | I[i + 1]->Last->TotalLength < Limit25 ; |
357 | 36 | i++, --closingLine23 ) { |
358 | | // No extra indent for compacted namespaces. |
359 | 23 | IndentTracker.skipLine(*I[i + 1]); |
360 | | |
361 | 23 | Limit -= I[i + 1]->Last->TotalLength; |
362 | 23 | } |
363 | 36 | return i; |
364 | 36 | } |
365 | | |
366 | 30 | if (auto nsToken = getMatchingNamespaceToken(TheLine, AnnotatedLines)) { |
367 | 22 | int i = 0; |
368 | 22 | unsigned openingLine = TheLine->MatchingOpeningBlockLineIndex - 1; |
369 | 47 | for (; I + 1 + i != E && |
370 | 47 | nsToken->TokenText == |
371 | 47 | getMatchingNamespaceTokenText(I[i + 1], AnnotatedLines) && |
372 | 47 | openingLine == I[i + 1]->MatchingOpeningBlockLineIndex25 ; |
373 | 25 | i++, --openingLine) { |
374 | | // No space between consecutive braces. |
375 | 25 | I[i + 1]->First->SpacesRequiredBefore = !I[i]->Last->is(tok::r_brace); |
376 | | |
377 | | // Indent like the outer-most namespace. |
378 | 25 | IndentTracker.nextLine(*I[i + 1]); |
379 | 25 | } |
380 | 22 | return i; |
381 | 22 | } |
382 | 30 | } |
383 | | |
384 | | // Try to merge a function block with left brace unwrapped. |
385 | 48.7k | if (TheLine->Last->is(TT_FunctionLBrace) && TheLine->First != TheLine->Last4.81k ) |
386 | 4.37k | return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit)4.06k : 0315 ; |
387 | | // Try to merge a control statement block with left brace unwrapped. |
388 | 44.4k | if (TheLine->Last->is(tok::l_brace) && FirstNonComment != TheLine->Last7.94k && |
389 | 44.4k | FirstNonComment->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for, |
390 | 6.37k | TT_ForEachMacro)) { |
391 | 1.24k | return Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never |
392 | 1.24k | ? tryMergeSimpleBlock(I, E, Limit)164 |
393 | 1.24k | : 01.08k ; |
394 | 1.24k | } |
395 | | // Try to merge a control statement block with left brace wrapped. |
396 | 43.1k | if (NextLine.First->is(tok::l_brace)) { |
397 | 1.62k | if ((TheLine->First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while, |
398 | 1.62k | tok::kw_for, tok::kw_switch, tok::kw_try, |
399 | 1.62k | tok::kw_do, TT_ForEachMacro) || |
400 | 1.62k | (1.28k TheLine->First->is(tok::r_brace)1.28k && TheLine->First->Next31 && |
401 | 1.28k | TheLine->First->Next->isOneOf(tok::kw_else, tok::kw_catch)31 )) && |
402 | 1.62k | Style.BraceWrapping.AfterControlStatement == |
403 | 377 | FormatStyle::BWACS_MultiLine) { |
404 | | // If possible, merge the next line's wrapped left brace with the |
405 | | // current line. Otherwise, leave it on the next line, as this is a |
406 | | // multi-line control statement. |
407 | 34 | return (Style.ColumnLimit == 0 || |
408 | 34 | TheLine->Last->TotalLength <= Style.ColumnLimit) |
409 | 34 | ? 124 |
410 | 34 | : 010 ; |
411 | 34 | } |
412 | 1.59k | if (TheLine->First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while, |
413 | 1.59k | tok::kw_for, TT_ForEachMacro)) { |
414 | 262 | return (Style.BraceWrapping.AfterControlStatement == |
415 | 262 | FormatStyle::BWACS_Always) |
416 | 262 | ? tryMergeSimpleBlock(I, E, Limit) |
417 | 262 | : 00 ; |
418 | 262 | } |
419 | 1.33k | if (TheLine->First->isOneOf(tok::kw_else, tok::kw_catch) && |
420 | 1.33k | Style.BraceWrapping.AfterControlStatement == |
421 | 14 | FormatStyle::BWACS_MultiLine) { |
422 | | // This case if different from the upper BWACS_MultiLine processing |
423 | | // in that a preceding r_brace is not on the same line as else/catch |
424 | | // most likely because of BeforeElse/BeforeCatch set to true. |
425 | | // If the line length doesn't fit ColumnLimit, leave l_brace on the |
426 | | // next line to respect the BWACS_MultiLine. |
427 | 1 | return (Style.ColumnLimit == 0 || |
428 | 1 | TheLine->Last->TotalLength <= Style.ColumnLimit) |
429 | 1 | ? 1 |
430 | 1 | : 00 ; |
431 | 1 | } |
432 | 1.33k | } |
433 | 42.8k | if (PreviousLine && TheLine->First->is(tok::l_brace)25.0k ) { |
434 | 1.28k | switch (PreviousLine->First->Tok.getKind()) { |
435 | 17 | case tok::at: |
436 | | // Don't merge block with left brace wrapped after ObjC special blocks. |
437 | 17 | if (PreviousLine->First->Next) { |
438 | 17 | tok::ObjCKeywordKind kwId = |
439 | 17 | PreviousLine->First->Next->Tok.getObjCKeywordID(); |
440 | 17 | if (kwId == tok::objc_autoreleasepool || |
441 | 17 | kwId == tok::objc_synchronized13 ) |
442 | 8 | return 0; |
443 | 17 | } |
444 | 9 | break; |
445 | | |
446 | 40 | case tok::kw_case: |
447 | 50 | case tok::kw_default: |
448 | | // Don't merge block with left brace wrapped after case labels. |
449 | 50 | return 0; |
450 | | |
451 | 1.21k | default: |
452 | 1.21k | break; |
453 | 1.28k | } |
454 | 1.28k | } |
455 | | |
456 | | // Don't merge an empty template class or struct if SplitEmptyRecords |
457 | | // is defined. |
458 | 42.8k | if (PreviousLine && Style.BraceWrapping.SplitEmptyRecord25.0k && |
459 | 42.8k | TheLine->Last->is(tok::l_brace)24.5k && PreviousLine->Last4.21k ) { |
460 | 4.21k | const FormatToken *Previous = PreviousLine->Last; |
461 | 4.21k | if (Previous) { |
462 | 4.21k | if (Previous->is(tok::comment)) |
463 | 313 | Previous = Previous->getPreviousNonComment(); |
464 | 4.21k | if (Previous) { |
465 | 4.13k | if (Previous->is(tok::greater) && !PreviousLine->InPPDirective21 ) |
466 | 14 | return 0; |
467 | 4.11k | if (Previous->is(tok::identifier)) { |
468 | 333 | const FormatToken *PreviousPrevious = |
469 | 333 | Previous->getPreviousNonComment(); |
470 | 333 | if (PreviousPrevious && |
471 | 333 | PreviousPrevious->isOneOf(tok::kw_class, tok::kw_struct)330 ) |
472 | 40 | return 0; |
473 | 333 | } |
474 | 4.11k | } |
475 | 4.21k | } |
476 | 4.21k | } |
477 | | |
478 | 42.7k | if (TheLine->Last->is(tok::l_brace)) { |
479 | 6.58k | bool ShouldMerge = false; |
480 | | // Try to merge records. |
481 | 6.58k | if (TheLine->Last->is(TT_EnumLBrace)) { |
482 | 76 | ShouldMerge = Style.AllowShortEnumsOnASingleLine; |
483 | 6.50k | } else if (TheLine->Last->isOneOf(TT_ClassLBrace, TT_StructLBrace)) { |
484 | | // NOTE: We use AfterClass (whereas AfterStruct exists) for both classes |
485 | | // and structs, but it seems that wrapping is still handled correctly |
486 | | // elsewhere. |
487 | 2.46k | ShouldMerge = !Style.BraceWrapping.AfterClass || |
488 | 2.46k | (16 NextLine.First->is(tok::r_brace)16 && |
489 | 16 | !Style.BraceWrapping.SplitEmptyRecord5 ); |
490 | 4.04k | } else { |
491 | | // Try to merge a block with left brace unwrapped that wasn't yet |
492 | | // covered. |
493 | 4.04k | assert(TheLine->InPPDirective || |
494 | 4.04k | !TheLine->First->isOneOf(tok::kw_class, tok::kw_enum, |
495 | 4.04k | tok::kw_struct)); |
496 | 4.04k | ShouldMerge = !Style.BraceWrapping.AfterFunction || |
497 | 4.04k | (848 NextLine.First->is(tok::r_brace)848 && |
498 | 848 | !Style.BraceWrapping.SplitEmptyFunction129 ); |
499 | 4.04k | } |
500 | 6.58k | return ShouldMerge ? tryMergeSimpleBlock(I, E, Limit)5.66k : 0917 ; |
501 | 6.58k | } |
502 | | |
503 | | // Try to merge a function block with left brace wrapped. |
504 | 36.1k | if (NextLine.First->is(TT_FunctionLBrace) && |
505 | 36.1k | Style.BraceWrapping.AfterFunction560 ) { |
506 | 558 | if (NextLine.Last->is(TT_LineComment)) |
507 | 6 | return 0; |
508 | | |
509 | | // Check for Limit <= 2 to account for the " {". |
510 | 552 | if (Limit <= 2 || (484 Style.ColumnLimit == 0484 && containsMustBreak(TheLine)97 )) |
511 | 87 | return 0; |
512 | 465 | Limit -= 2; |
513 | | |
514 | 465 | unsigned MergedLines = 0; |
515 | 465 | if (MergeShortFunctions || |
516 | 465 | (242 Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty242 && |
517 | 242 | NextLine.First == NextLine.Last96 && I + 2 != E96 && |
518 | 244 | I[2]->First->is(tok::r_brace)96 )) { |
519 | 244 | MergedLines = tryMergeSimpleBlock(I + 1, E, Limit); |
520 | | // If we managed to merge the block, count the function header, which is |
521 | | // on a separate line. |
522 | 244 | if (MergedLines > 0) |
523 | 150 | ++MergedLines; |
524 | 244 | } |
525 | 465 | return MergedLines; |
526 | 552 | } |
527 | 35.6k | auto IsElseLine = [&TheLine]() -> bool { |
528 | 34.7k | const FormatToken *First = TheLine->First; |
529 | 34.7k | if (First->is(tok::kw_else)) |
530 | 322 | return true; |
531 | | |
532 | 34.4k | return First->is(tok::r_brace) && First->Next6.59k && |
533 | 34.4k | First->Next->is(tok::kw_else)1.98k ; |
534 | 34.7k | }; |
535 | 35.6k | if (TheLine->First->is(tok::kw_if) || |
536 | 35.6k | (34.7k IsElseLine()34.7k && (Style.AllowShortIfStatementsOnASingleLine == |
537 | 952 | FormatStyle::SIS_AllIfsAndElse))) { |
538 | 952 | return Style.AllowShortIfStatementsOnASingleLine |
539 | 952 | ? tryMergeSimpleControlStatement(I, E, Limit)539 |
540 | 952 | : 0413 ; |
541 | 952 | } |
542 | 34.6k | if (TheLine->First->isOneOf(tok::kw_for, tok::kw_while, tok::kw_do, |
543 | 34.6k | TT_ForEachMacro)) { |
544 | 430 | return Style.AllowShortLoopsOnASingleLine |
545 | 430 | ? tryMergeSimpleControlStatement(I, E, Limit)91 |
546 | 430 | : 0339 ; |
547 | 430 | } |
548 | 34.2k | if (TheLine->First->isOneOf(tok::kw_case, tok::kw_default)) { |
549 | 376 | return Style.AllowShortCaseLabelsOnASingleLine |
550 | 376 | ? tryMergeShortCaseLabels(I, E, Limit)87 |
551 | 376 | : 0289 ; |
552 | 376 | } |
553 | 33.8k | if (TheLine->InPPDirective && |
554 | 33.8k | (1.17k TheLine->First->HasUnescapedNewline1.17k || TheLine->First->IsFirst688 )) |
555 | 958 | return tryMergeSimplePPDirective(I, E, Limit); |
556 | 32.9k | return 0; |
557 | 33.8k | } |
558 | | |
559 | | unsigned |
560 | | tryMergeSimplePPDirective(SmallVectorImpl<AnnotatedLine *>::const_iterator I, |
561 | | SmallVectorImpl<AnnotatedLine *>::const_iterator E, |
562 | 958 | unsigned Limit) { |
563 | 958 | if (Limit == 0) |
564 | 3 | return 0; |
565 | 955 | if (I + 2 != E && I[2]->InPPDirective && !I[2]->First->HasUnescapedNewline410 ) |
566 | 169 | return 0; |
567 | 786 | if (1 + I[1]->Last->TotalLength > Limit) |
568 | 70 | return 0; |
569 | 716 | return 1; |
570 | 786 | } |
571 | | |
572 | | unsigned tryMergeSimpleControlStatement( |
573 | | SmallVectorImpl<AnnotatedLine *>::const_iterator I, |
574 | 630 | SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned Limit) { |
575 | 630 | if (Limit == 0) |
576 | 10 | return 0; |
577 | 620 | if (Style.BraceWrapping.AfterControlStatement == |
578 | 620 | FormatStyle::BWACS_Always && |
579 | 620 | I[1]->First->is(tok::l_brace)12 && |
580 | 620 | Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never0 ) |
581 | 0 | return 0; |
582 | 620 | if (I[1]->InPPDirective != (*I)->InPPDirective || |
583 | 620 | (617 I[1]->InPPDirective617 && I[1]->First->HasUnescapedNewline21 )) |
584 | 3 | return 0; |
585 | 617 | Limit = limitConsideringMacros(I + 1, E, Limit); |
586 | 617 | AnnotatedLine &Line = **I; |
587 | 617 | if (!Line.First->is(tok::kw_do) && !Line.First->is(tok::kw_else)608 && |
588 | 617 | !Line.Last->is(tok::kw_else)518 && Line.Last->isNot(tok::r_paren)491 ) |
589 | 34 | return 0; |
590 | | // Only merge `do while` if `do` is the only statement on the line. |
591 | 583 | if (Line.First->is(tok::kw_do) && !Line.Last->is(tok::kw_do)9 ) |
592 | 3 | return 0; |
593 | 580 | if (1 + I[1]->Last->TotalLength > Limit) |
594 | 15 | return 0; |
595 | | // Don't merge with loops, ifs, a single semicolon or a line comment. |
596 | 565 | if (I[1]->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for, tok::kw_while, |
597 | 565 | TT_ForEachMacro, TT_LineComment)) |
598 | 78 | return 0; |
599 | | // Only inline simple if's (no nested if or else), unless specified |
600 | 487 | if (Style.AllowShortIfStatementsOnASingleLine == |
601 | 487 | FormatStyle::SIS_WithoutElse) { |
602 | 154 | if (I + 2 != E && Line.startsWith(tok::kw_if)142 && |
603 | 154 | I[2]->First->is(tok::kw_else)138 ) |
604 | 62 | return 0; |
605 | 154 | } |
606 | 425 | return 1; |
607 | 487 | } |
608 | | |
609 | | unsigned |
610 | | tryMergeShortCaseLabels(SmallVectorImpl<AnnotatedLine *>::const_iterator I, |
611 | | SmallVectorImpl<AnnotatedLine *>::const_iterator E, |
612 | 87 | unsigned Limit) { |
613 | 87 | if (Limit == 0 || I + 1 == E || |
614 | 87 | I[1]->First->isOneOf(tok::kw_case, tok::kw_default)) |
615 | 12 | return 0; |
616 | 75 | if (I[0]->Last->is(tok::l_brace) || I[1]->First->is(tok::l_brace)) |
617 | 2 | return 0; |
618 | 73 | unsigned NumStmts = 0; |
619 | 73 | unsigned Length = 0; |
620 | 73 | bool EndsWithComment = false; |
621 | 73 | bool InPPDirective = I[0]->InPPDirective; |
622 | 73 | const unsigned Level = I[0]->Level; |
623 | 155 | for (; NumStmts < 3; ++NumStmts82 ) { |
624 | 155 | if (I + 1 + NumStmts == E) |
625 | 0 | break; |
626 | 155 | const AnnotatedLine *Line = I[1 + NumStmts]; |
627 | 155 | if (Line->InPPDirective != InPPDirective) |
628 | 4 | break; |
629 | 151 | if (Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace)) |
630 | 43 | break; |
631 | 108 | if (Line->First->isOneOf(tok::kw_if, tok::kw_for, tok::kw_switch, |
632 | 108 | tok::kw_while) || |
633 | 108 | EndsWithComment105 ) |
634 | 11 | return 0; |
635 | 97 | if (Line->First->is(tok::comment)) { |
636 | 15 | if (Level != Line->Level) |
637 | 7 | return 0; |
638 | 8 | SmallVectorImpl<AnnotatedLine *>::const_iterator J = I + 2 + NumStmts; |
639 | 8 | for (; J != E; ++J0 ) { |
640 | 8 | Line = *J; |
641 | 8 | if (Line->InPPDirective != InPPDirective) |
642 | 1 | break; |
643 | 7 | if (Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace)) |
644 | 7 | break; |
645 | 0 | if (Line->First->isNot(tok::comment) || Level != Line->Level) |
646 | 0 | return 0; |
647 | 0 | } |
648 | 8 | break; |
649 | 8 | } |
650 | 82 | if (Line->Last->is(tok::comment)) |
651 | 21 | EndsWithComment = true; |
652 | 82 | Length += I[1 + NumStmts]->Last->TotalLength + 1; // 1 for the space. |
653 | 82 | } |
654 | 55 | if (NumStmts == 0 || NumStmts == 3 || Length > Limit) |
655 | 7 | return 0; |
656 | 48 | return NumStmts; |
657 | 55 | } |
658 | | |
659 | | unsigned |
660 | | tryMergeSimpleBlock(SmallVectorImpl<AnnotatedLine *>::const_iterator I, |
661 | | SmallVectorImpl<AnnotatedLine *>::const_iterator E, |
662 | 10.5k | unsigned Limit) { |
663 | | // Don't merge with a preprocessor directive. |
664 | 10.5k | if (I[1]->Type == LT_PreprocessorDirective) |
665 | 86 | return 0; |
666 | | |
667 | 10.4k | AnnotatedLine &Line = **I; |
668 | | |
669 | | // Don't merge ObjC @ keywords and methods. |
670 | | // FIXME: If an option to allow short exception handling clauses on a single |
671 | | // line is added, change this to not return for @try and friends. |
672 | 10.4k | if (Style.Language != FormatStyle::LK_Java && |
673 | 10.4k | Line.First->isOneOf(tok::at, tok::minus, tok::plus)10.2k ) |
674 | 153 | return 0; |
675 | | |
676 | | // Check that the current line allows merging. This depends on whether we |
677 | | // are in a control flow statements as well as several style flags. |
678 | 10.3k | if (Line.First->is(tok::kw_case) || |
679 | 10.3k | (10.2k Line.First->Next10.2k && Line.First->Next->is(tok::kw_else)9.13k )) |
680 | 364 | return 0; |
681 | | // default: in switch statement |
682 | 9.94k | if (Line.First->is(tok::kw_default)) { |
683 | 28 | const FormatToken *Tok = Line.First->getNextNonComment(); |
684 | 28 | if (Tok && Tok->is(tok::colon)) |
685 | 26 | return 0; |
686 | 28 | } |
687 | 9.91k | if (Line.First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while, tok::kw_do, |
688 | 9.91k | tok::kw_try, tok::kw___try, tok::kw_catch, |
689 | 9.91k | tok::kw___finally, tok::kw_for, TT_ForEachMacro, |
690 | 9.91k | tok::r_brace, Keywords.kw___except)) { |
691 | 830 | if (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) |
692 | 516 | return 0; |
693 | 314 | if (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Empty && |
694 | 314 | !I[1]->First->is(tok::r_brace)46 ) |
695 | 24 | return 0; |
696 | | // Don't merge when we can't except the case when |
697 | | // the control statement block is empty |
698 | 290 | if (!Style.AllowShortIfStatementsOnASingleLine && |
699 | 290 | Line.First->isOneOf(tok::kw_if, tok::kw_else)103 && |
700 | 290 | !Style.BraceWrapping.AfterControlStatement48 && |
701 | 290 | !I[1]->First->is(tok::r_brace)30 ) |
702 | 12 | return 0; |
703 | 278 | if (!Style.AllowShortIfStatementsOnASingleLine && |
704 | 278 | Line.First->isOneOf(tok::kw_if, tok::kw_else)91 && |
705 | 278 | Style.BraceWrapping.AfterControlStatement == |
706 | 36 | FormatStyle::BWACS_Always && |
707 | 278 | I + 2 != E18 && !I[2]->First->is(tok::r_brace)18 ) |
708 | 12 | return 0; |
709 | 266 | if (!Style.AllowShortLoopsOnASingleLine && |
710 | 266 | Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for, |
711 | 65 | TT_ForEachMacro) && |
712 | 266 | !Style.BraceWrapping.AfterControlStatement44 && |
713 | 266 | !I[1]->First->is(tok::r_brace)26 ) |
714 | 15 | return 0; |
715 | 251 | if (!Style.AllowShortLoopsOnASingleLine && |
716 | 251 | Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for, |
717 | 50 | TT_ForEachMacro) && |
718 | 251 | Style.BraceWrapping.AfterControlStatement == |
719 | 29 | FormatStyle::BWACS_Always && |
720 | 251 | I + 2 != E18 && !I[2]->First->is(tok::r_brace)18 ) |
721 | 9 | return 0; |
722 | | // FIXME: Consider an option to allow short exception handling clauses on |
723 | | // a single line. |
724 | | // FIXME: This isn't covered by tests. |
725 | | // FIXME: For catch, __except, __finally the first token on the line |
726 | | // is '}', so this isn't correct here. |
727 | 242 | if (Line.First->isOneOf(tok::kw_try, tok::kw___try, tok::kw_catch, |
728 | 242 | Keywords.kw___except, tok::kw___finally)) |
729 | 0 | return 0; |
730 | 242 | } |
731 | | |
732 | 9.32k | if (Line.Last->is(tok::l_brace)) { |
733 | 9.22k | FormatToken *Tok = I[1]->First; |
734 | 9.22k | auto ShouldMerge = [Tok]() { |
735 | 9.22k | if (Tok->isNot(tok::r_brace) || Tok->MustBreakBefore3.05k ) |
736 | 6.17k | return false; |
737 | 3.05k | const FormatToken *Next = Tok->getNextNonComment(); |
738 | 3.05k | return !Next || Next->is(tok::semi)798 ; |
739 | 9.22k | }; |
740 | | |
741 | 9.22k | if (ShouldMerge()) { |
742 | | // We merge empty blocks even if the line exceeds the column limit. |
743 | 2.94k | Tok->SpacesRequiredBefore = Style.SpaceInEmptyBlock ? 116 : 02.93k ; |
744 | 2.94k | Tok->CanBreakBefore = true; |
745 | 2.94k | return 1; |
746 | 6.28k | } else if (Limit != 0 && !Line.startsWithNamespace()6.18k && |
747 | 6.28k | !startsExternCBlock(Line)5.00k ) { |
748 | | // We don't merge short records. |
749 | 4.97k | if (isRecordLBrace(*Line.Last)) |
750 | 1.70k | return 0; |
751 | | |
752 | | // Check that we still have three lines and they fit into the limit. |
753 | 3.26k | if (I + 2 == E || I[2]->Type == LT_Invalid3.23k ) |
754 | 31 | return 0; |
755 | 3.23k | Limit = limitConsideringMacros(I + 2, E, Limit); |
756 | | |
757 | 3.23k | if (!nextTwoLinesFitInto(I, Limit)) |
758 | 549 | return 0; |
759 | | |
760 | | // Second, check that the next line does not contain any braces - if it |
761 | | // does, readability declines when putting it into a single line. |
762 | 2.68k | if (I[1]->Last->is(TT_LineComment)) |
763 | 84 | return 0; |
764 | 15.1k | do 2.60k { |
765 | 15.1k | if (Tok->is(tok::l_brace) && Tok->isNot(BK_BracedInit)209 ) |
766 | 170 | return 0; |
767 | 14.9k | Tok = Tok->Next; |
768 | 14.9k | } while (Tok); |
769 | | |
770 | | // Last, check that the third line starts with a closing brace. |
771 | 2.43k | Tok = I[2]->First; |
772 | 2.43k | if (Tok->isNot(tok::r_brace)) |
773 | 650 | return 0; |
774 | | |
775 | | // Don't merge "if (a) { .. } else {". |
776 | 1.78k | if (Tok->Next && Tok->Next->is(tok::kw_else)511 ) |
777 | 13 | return 0; |
778 | | |
779 | | // Don't merge a trailing multi-line control statement block like: |
780 | | // } else if (foo && |
781 | | // bar) |
782 | | // { <-- current Line |
783 | | // baz(); |
784 | | // } |
785 | 1.76k | if (Line.First == Line.Last && Line.First->isNot(TT_FunctionLBrace)582 && |
786 | 1.76k | Style.BraceWrapping.AfterControlStatement == |
787 | 498 | FormatStyle::BWACS_MultiLine) |
788 | 8 | return 0; |
789 | | |
790 | 1.76k | return 2; |
791 | 1.76k | } |
792 | 9.22k | } else if (100 I[1]->First->is(tok::l_brace)100 ) { |
793 | 100 | if (I[1]->Last->is(TT_LineComment)) |
794 | 6 | return 0; |
795 | | |
796 | | // Check for Limit <= 2 to account for the " {". |
797 | 94 | if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(*I)0 )) |
798 | 0 | return 0; |
799 | 94 | Limit -= 2; |
800 | 94 | unsigned MergedLines = 0; |
801 | 94 | if (Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never || |
802 | 94 | (0 I[1]->First == I[1]->Last0 && I + 2 != E0 && |
803 | 94 | I[2]->First->is(tok::r_brace)0 )) { |
804 | 94 | MergedLines = tryMergeSimpleBlock(I + 1, E, Limit); |
805 | | // If we managed to merge the block, count the statement header, which |
806 | | // is on a separate line. |
807 | 94 | if (MergedLines > 0) |
808 | 69 | ++MergedLines; |
809 | 94 | } |
810 | 94 | return MergedLines; |
811 | 94 | } |
812 | 1.30k | return 0; |
813 | 9.32k | } |
814 | | |
815 | | /// Returns the modified column limit for \p I if it is inside a macro and |
816 | | /// needs a trailing '\'. |
817 | | unsigned |
818 | | limitConsideringMacros(SmallVectorImpl<AnnotatedLine *>::const_iterator I, |
819 | | SmallVectorImpl<AnnotatedLine *>::const_iterator E, |
820 | 3.85k | unsigned Limit) { |
821 | 3.85k | if (I[0]->InPPDirective && I + 1 != E81 && |
822 | 3.85k | !I[1]->First->HasUnescapedNewline81 && !I[1]->First->is(tok::eof)63 ) |
823 | 34 | return Limit < 2 ? 00 : Limit - 2; |
824 | 3.81k | return Limit; |
825 | 3.85k | } |
826 | | |
827 | | bool nextTwoLinesFitInto(SmallVectorImpl<AnnotatedLine *>::const_iterator I, |
828 | 3.23k | unsigned Limit) { |
829 | 3.23k | if (I[1]->First->MustBreakBefore || I[2]->First->MustBreakBefore) |
830 | 39 | return false; |
831 | 3.19k | return 1 + I[1]->Last->TotalLength + 1 + I[2]->Last->TotalLength <= Limit; |
832 | 3.23k | } |
833 | | |
834 | 97 | bool containsMustBreak(const AnnotatedLine *Line) { |
835 | 522 | for (const FormatToken *Tok = Line->First; Tok; Tok = Tok->Next425 ) |
836 | 444 | if (Tok->MustBreakBefore) |
837 | 19 | return true; |
838 | 78 | return false; |
839 | 97 | } |
840 | | |
841 | 7.31k | void join(AnnotatedLine &A, const AnnotatedLine &B) { |
842 | 7.31k | assert(!A.Last->Next); |
843 | 0 | assert(!B.First->Previous); |
844 | 7.31k | if (B.Affected) |
845 | 6.40k | A.Affected = true; |
846 | 7.31k | A.Last->Next = B.First; |
847 | 7.31k | B.First->Previous = A.Last; |
848 | 7.31k | B.First->CanBreakBefore = true; |
849 | 7.31k | unsigned LengthA = A.Last->TotalLength + B.First->SpacesRequiredBefore; |
850 | 26.3k | for (FormatToken *Tok = B.First; Tok; Tok = Tok->Next19.0k ) { |
851 | 19.0k | Tok->TotalLength += LengthA; |
852 | 19.0k | A.Last = Tok; |
853 | 19.0k | } |
854 | 7.31k | } |
855 | | |
856 | | const FormatStyle &Style; |
857 | | const AdditionalKeywords &Keywords; |
858 | | const SmallVectorImpl<AnnotatedLine *>::const_iterator End; |
859 | | |
860 | | SmallVectorImpl<AnnotatedLine *>::const_iterator Next; |
861 | | const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines; |
862 | | }; |
863 | | |
864 | 79.4k | static void markFinalized(FormatToken *Tok) { |
865 | 464k | for (; Tok; Tok = Tok->Next385k ) { |
866 | 385k | Tok->Finalized = true; |
867 | 385k | for (AnnotatedLine *Child : Tok->Children) |
868 | 2.41k | markFinalized(Child->First); |
869 | 385k | } |
870 | 79.4k | } |
871 | | |
872 | | #ifndef NDEBUG |
873 | 0 | static void printLineState(const LineState &State) { |
874 | 0 | llvm::dbgs() << "State: "; |
875 | 0 | for (const ParenState &P : State.Stack) { |
876 | 0 | llvm::dbgs() << (P.Tok ? P.Tok->TokenText : "F") << "|" << P.Indent << "|" |
877 | 0 | << P.LastSpace << "|" << P.NestedBlockIndent << " "; |
878 | 0 | } |
879 | 0 | llvm::dbgs() << State.NextToken->TokenText << "\n"; |
880 | 0 | } |
881 | | #endif |
882 | | |
883 | | /// Base class for classes that format one \c AnnotatedLine. |
884 | | class LineFormatter { |
885 | | public: |
886 | | LineFormatter(ContinuationIndenter *Indenter, WhitespaceManager *Whitespaces, |
887 | | const FormatStyle &Style, |
888 | | UnwrappedLineFormatter *BlockFormatter) |
889 | | : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style), |
890 | 74.5k | BlockFormatter(BlockFormatter) {} |
891 | 74.5k | virtual ~LineFormatter() {} |
892 | | |
893 | | /// Formats an \c AnnotatedLine and returns the penalty. |
894 | | /// |
895 | | /// If \p DryRun is \c false, directly applies the changes. |
896 | | virtual unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent, |
897 | | unsigned FirstStartColumn, bool DryRun) = 0; |
898 | | |
899 | | protected: |
900 | | /// If the \p State's next token is an r_brace closing a nested block, |
901 | | /// format the nested block before it. |
902 | | /// |
903 | | /// Returns \c true if all children could be placed successfully and adapts |
904 | | /// \p Penalty as well as \p State. If \p DryRun is false, also directly |
905 | | /// creates changes using \c Whitespaces. |
906 | | /// |
907 | | /// The crucial idea here is that children always get formatted upon |
908 | | /// encountering the closing brace right after the nested block. Now, if we |
909 | | /// are currently trying to keep the "}" on the same line (i.e. \p NewLine is |
910 | | /// \c false), the entire block has to be kept on the same line (which is only |
911 | | /// possible if it fits on the line, only contains a single statement, etc. |
912 | | /// |
913 | | /// If \p NewLine is true, we format the nested block on separate lines, i.e. |
914 | | /// break after the "{", format all lines with correct indentation and the put |
915 | | /// the closing "}" on yet another new line. |
916 | | /// |
917 | | /// This enables us to keep the simple structure of the |
918 | | /// \c UnwrappedLineFormatter, where we only have two options for each token: |
919 | | /// break or don't break. |
920 | | bool formatChildren(LineState &State, bool NewLine, bool DryRun, |
921 | 1.11M | unsigned &Penalty) { |
922 | 1.11M | const FormatToken *LBrace = State.NextToken->getPreviousNonComment(); |
923 | 1.11M | FormatToken &Previous = *State.NextToken->Previous; |
924 | 1.11M | if (!LBrace || LBrace->isNot(tok::l_brace)1.11M || LBrace->isNot(BK_Block)30.7k || |
925 | 1.11M | Previous.Children.size() == 011.7k ) |
926 | | // The previous token does not open a block. Nothing to do. We don't |
927 | | // assert so that we can simply call this function for all tokens. |
928 | 1.11M | return true; |
929 | | |
930 | 4.68k | if (NewLine) { |
931 | 2.98k | const ParenState &P = State.Stack.back(); |
932 | | |
933 | 2.98k | int AdditionalIndent = |
934 | 2.98k | P.Indent - Previous.Children[0]->Level * Style.IndentWidth; |
935 | | |
936 | 2.98k | if (Style.LambdaBodyIndentation == FormatStyle::LBI_OuterScope && |
937 | 2.98k | P.NestedBlockIndent == P.LastSpace76 ) { |
938 | 19 | if (State.NextToken->MatchingParen && |
939 | 19 | State.NextToken->MatchingParen->is(TT_LambdaLBrace)) |
940 | 19 | State.Stack.pop_back(); |
941 | 19 | if (LBrace->is(TT_LambdaLBrace)) |
942 | 19 | AdditionalIndent = 0; |
943 | 19 | } |
944 | | |
945 | 2.98k | Penalty += |
946 | 2.98k | BlockFormatter->format(Previous.Children, DryRun, AdditionalIndent, |
947 | 2.98k | /*FixBadIndentation=*/true); |
948 | 2.98k | return true; |
949 | 2.98k | } |
950 | | |
951 | 1.70k | if (Previous.Children[0]->First->MustBreakBefore) |
952 | 1 | return false; |
953 | | |
954 | | // Cannot merge into one line if this line ends on a comment. |
955 | 1.70k | if (Previous.is(tok::comment)) |
956 | 0 | return false; |
957 | | |
958 | | // Cannot merge multiple statements into a single line. |
959 | 1.70k | if (Previous.Children.size() > 1) |
960 | 686 | return false; |
961 | | |
962 | 1.01k | const AnnotatedLine *Child = Previous.Children[0]; |
963 | | // We can't put the closing "}" on a line with a trailing comment. |
964 | 1.01k | if (Child->Last->isTrailingComment()) |
965 | 0 | return false; |
966 | | |
967 | | // If the child line exceeds the column limit, we wouldn't want to merge it. |
968 | | // We add +2 for the trailing " }". |
969 | 1.01k | if (Style.ColumnLimit > 0 && |
970 | 1.01k | Child->Last->TotalLength + State.Column + 2 > Style.ColumnLimit1.01k ) |
971 | 127 | return false; |
972 | | |
973 | 889 | if (!DryRun) { |
974 | 602 | Whitespaces->replaceWhitespace( |
975 | 602 | *Child->First, /*Newlines=*/0, /*Spaces=*/1, |
976 | 602 | /*StartOfTokenColumn=*/State.Column, /*IsAligned=*/false, |
977 | 602 | State.Line->InPPDirective); |
978 | 602 | } |
979 | 889 | Penalty += |
980 | 889 | formatLine(*Child, State.Column + 1, /*FirstStartColumn=*/0, DryRun); |
981 | | |
982 | 889 | State.Column += 1 + Child->Last->TotalLength; |
983 | 889 | return true; |
984 | 1.01k | } |
985 | | |
986 | | ContinuationIndenter *Indenter; |
987 | | |
988 | | private: |
989 | | WhitespaceManager *Whitespaces; |
990 | | const FormatStyle &Style; |
991 | | UnwrappedLineFormatter *BlockFormatter; |
992 | | }; |
993 | | |
994 | | /// Formatter that keeps the existing line breaks. |
995 | | class NoColumnLimitLineFormatter : public LineFormatter { |
996 | | public: |
997 | | NoColumnLimitLineFormatter(ContinuationIndenter *Indenter, |
998 | | WhitespaceManager *Whitespaces, |
999 | | const FormatStyle &Style, |
1000 | | UnwrappedLineFormatter *BlockFormatter) |
1001 | 1.81k | : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {} |
1002 | | |
1003 | | /// Formats the line, simply keeping all of the input's line breaking |
1004 | | /// decisions. |
1005 | | unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent, |
1006 | 1.81k | unsigned FirstStartColumn, bool DryRun) override { |
1007 | 1.81k | assert(!DryRun); |
1008 | 0 | LineState State = Indenter->getInitialState(FirstIndent, FirstStartColumn, |
1009 | 1.81k | &Line, /*DryRun=*/false); |
1010 | 6.23k | while (State.NextToken) { |
1011 | 4.41k | bool Newline = |
1012 | 4.41k | Indenter->mustBreak(State) || |
1013 | 4.41k | (4.05k Indenter->canBreak(State)4.05k && State.NextToken->NewlinesBefore > 01.12k ); |
1014 | 4.41k | unsigned Penalty = 0; |
1015 | 4.41k | formatChildren(State, Newline, /*DryRun=*/false, Penalty); |
1016 | 4.41k | Indenter->addTokenToState(State, Newline, /*DryRun=*/false); |
1017 | 4.41k | } |
1018 | 1.81k | return 0; |
1019 | 1.81k | } |
1020 | | }; |
1021 | | |
1022 | | /// Formatter that puts all tokens into a single line without breaks. |
1023 | | class NoLineBreakFormatter : public LineFormatter { |
1024 | | public: |
1025 | | NoLineBreakFormatter(ContinuationIndenter *Indenter, |
1026 | | WhitespaceManager *Whitespaces, const FormatStyle &Style, |
1027 | | UnwrappedLineFormatter *BlockFormatter) |
1028 | 65.9k | : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {} |
1029 | | |
1030 | | /// Puts all tokens into a single line. |
1031 | | unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent, |
1032 | 66.3k | unsigned FirstStartColumn, bool DryRun) override { |
1033 | 66.3k | unsigned Penalty = 0; |
1034 | 66.3k | LineState State = |
1035 | 66.3k | Indenter->getInitialState(FirstIndent, FirstStartColumn, &Line, DryRun); |
1036 | 255k | while (State.NextToken) { |
1037 | 189k | formatChildren(State, /*NewLine=*/false, DryRun, Penalty); |
1038 | 189k | Indenter->addTokenToState( |
1039 | 189k | State, /*Newline=*/State.NextToken->MustBreakBefore, DryRun); |
1040 | 189k | } |
1041 | 66.3k | return Penalty; |
1042 | 66.3k | } |
1043 | | }; |
1044 | | |
1045 | | /// Finds the best way to break lines. |
1046 | | class OptimizingLineFormatter : public LineFormatter { |
1047 | | public: |
1048 | | OptimizingLineFormatter(ContinuationIndenter *Indenter, |
1049 | | WhitespaceManager *Whitespaces, |
1050 | | const FormatStyle &Style, |
1051 | | UnwrappedLineFormatter *BlockFormatter) |
1052 | 6.80k | : LineFormatter(Indenter, Whitespaces, Style, BlockFormatter) {} |
1053 | | |
1054 | | /// Formats the line by finding the best line breaks with line lengths |
1055 | | /// below the column limit. |
1056 | | unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent, |
1057 | 7.27k | unsigned FirstStartColumn, bool DryRun) override { |
1058 | 7.27k | LineState State = |
1059 | 7.27k | Indenter->getInitialState(FirstIndent, FirstStartColumn, &Line, DryRun); |
1060 | | |
1061 | | // If the ObjC method declaration does not fit on a line, we should format |
1062 | | // it with one arg per line. |
1063 | 7.27k | if (State.Line->Type == LT_ObjCMethodDecl) |
1064 | 42 | State.Stack.back().BreakBeforeParameter = true; |
1065 | | |
1066 | | // Find best solution in solution space. |
1067 | 7.27k | return analyzeSolutionSpace(State, DryRun); |
1068 | 7.27k | } |
1069 | | |
1070 | | private: |
1071 | | struct CompareLineStatePointers { |
1072 | 14.9M | bool operator()(LineState *obj1, LineState *obj2) const { |
1073 | 14.9M | return *obj1 < *obj2; |
1074 | 14.9M | } |
1075 | | }; |
1076 | | |
1077 | | /// A pair of <penalty, count> that is used to prioritize the BFS on. |
1078 | | /// |
1079 | | /// In case of equal penalties, we want to prefer states that were inserted |
1080 | | /// first. During state generation we make sure that we insert states first |
1081 | | /// that break the line as late as possible. |
1082 | | typedef std::pair<unsigned, unsigned> OrderedPenalty; |
1083 | | |
1084 | | /// An edge in the solution space from \c Previous->State to \c State, |
1085 | | /// inserting a newline dependent on the \c NewLine. |
1086 | | struct StateNode { |
1087 | | StateNode(const LineState &State, bool NewLine, StateNode *Previous) |
1088 | 840k | : State(State), NewLine(NewLine), Previous(Previous) {} |
1089 | | LineState State; |
1090 | | bool NewLine; |
1091 | | StateNode *Previous; |
1092 | | }; |
1093 | | |
1094 | | /// An item in the prioritized BFS search queue. The \c StateNode's |
1095 | | /// \c State has the given \c OrderedPenalty. |
1096 | | typedef std::pair<OrderedPenalty, StateNode *> QueueItem; |
1097 | | |
1098 | | /// The BFS queue type. |
1099 | | typedef std::priority_queue<QueueItem, std::vector<QueueItem>, |
1100 | | std::greater<QueueItem>> |
1101 | | QueueType; |
1102 | | |
1103 | | /// Analyze the entire solution space starting from \p InitialState. |
1104 | | /// |
1105 | | /// This implements a variant of Dijkstra's algorithm on the graph that spans |
1106 | | /// the solution space (\c LineStates are the nodes). The algorithm tries to |
1107 | | /// find the shortest path (the one with lowest penalty) from \p InitialState |
1108 | | /// to a state where all tokens are placed. Returns the penalty. |
1109 | | /// |
1110 | | /// If \p DryRun is \c false, directly applies the changes. |
1111 | 7.27k | unsigned analyzeSolutionSpace(LineState &InitialState, bool DryRun) { |
1112 | 7.27k | std::set<LineState *, CompareLineStatePointers> Seen; |
1113 | | |
1114 | | // Increasing count of \c StateNode items we have created. This is used to |
1115 | | // create a deterministic order independent of the container. |
1116 | 7.27k | unsigned Count = 0; |
1117 | 7.27k | QueueType Queue; |
1118 | | |
1119 | | // Insert start element into queue. |
1120 | 7.27k | StateNode *RootNode = |
1121 | 7.27k | new (Allocator.Allocate()) StateNode(InitialState, false, nullptr); |
1122 | 7.27k | Queue.push(QueueItem(OrderedPenalty(0, Count), RootNode)); |
1123 | 7.27k | ++Count; |
1124 | | |
1125 | 7.27k | unsigned Penalty = 0; |
1126 | | |
1127 | | // While not empty, take first element and follow edges. |
1128 | 761k | while (!Queue.empty()) { |
1129 | 761k | Penalty = Queue.top().first.first; |
1130 | 761k | StateNode *Node = Queue.top().second; |
1131 | 761k | if (!Node->State.NextToken) { |
1132 | 7.27k | LLVM_DEBUG(llvm::dbgs() |
1133 | 7.27k | << "\n---\nPenalty for line: " << Penalty << "\n"); |
1134 | 7.27k | break; |
1135 | 7.27k | } |
1136 | 754k | Queue.pop(); |
1137 | | |
1138 | | // Cut off the analysis of certain solutions if the analysis gets too |
1139 | | // complex. See description of IgnoreStackForComparison. |
1140 | 754k | if (Count > 50000) |
1141 | 134k | Node->State.IgnoreStackForComparison = true; |
1142 | | |
1143 | 754k | if (!Seen.insert(&Node->State).second) |
1144 | | // State already examined with lower penalty. |
1145 | 139k | continue; |
1146 | | |
1147 | 615k | FormatDecision LastFormat = Node->State.NextToken->getDecision(); |
1148 | 615k | if (LastFormat == FD_Unformatted || LastFormat == FD_Continue594 ) |
1149 | 614k | addNextStateToQueue(Penalty, Node, /*NewLine=*/false, &Count, &Queue); |
1150 | 615k | if (LastFormat == FD_Unformatted || LastFormat == FD_Break594 ) |
1151 | 614k | addNextStateToQueue(Penalty, Node, /*NewLine=*/true, &Count, &Queue); |
1152 | 615k | } |
1153 | | |
1154 | 7.27k | if (Queue.empty()) { |
1155 | | // We were unable to find a solution, do nothing. |
1156 | | // FIXME: Add diagnostic? |
1157 | 0 | LLVM_DEBUG(llvm::dbgs() << "Could not find a solution.\n"); |
1158 | 0 | return 0; |
1159 | 0 | } |
1160 | | |
1161 | | // Reconstruct the solution. |
1162 | 7.27k | if (!DryRun) |
1163 | 6.82k | reconstructPath(InitialState, Queue.top().second); |
1164 | | |
1165 | 7.27k | LLVM_DEBUG(llvm::dbgs() |
1166 | 7.27k | << "Total number of analyzed states: " << Count << "\n"); |
1167 | 7.27k | LLVM_DEBUG(llvm::dbgs() << "---\n"); |
1168 | | |
1169 | 7.27k | return Penalty; |
1170 | 7.27k | } |
1171 | | |
1172 | | /// Add the following state to the analysis queue \c Queue. |
1173 | | /// |
1174 | | /// Assume the current state is \p PreviousNode and has been reached with a |
1175 | | /// penalty of \p Penalty. Insert a line break if \p NewLine is \c true. |
1176 | | void addNextStateToQueue(unsigned Penalty, StateNode *PreviousNode, |
1177 | 1.22M | bool NewLine, unsigned *Count, QueueType *Queue) { |
1178 | 1.22M | if (NewLine && !Indenter->canBreak(PreviousNode->State)614k ) |
1179 | 356k | return; |
1180 | 872k | if (!NewLine && Indenter->mustBreak(PreviousNode->State)614k ) |
1181 | 39.7k | return; |
1182 | | |
1183 | 832k | StateNode *Node = new (Allocator.Allocate()) |
1184 | 832k | StateNode(PreviousNode->State, NewLine, PreviousNode); |
1185 | 832k | if (!formatChildren(Node->State, NewLine, /*DryRun=*/true, Penalty)) |
1186 | 814 | return; |
1187 | | |
1188 | 832k | Penalty += Indenter->addTokenToState(Node->State, NewLine, true); |
1189 | | |
1190 | 832k | Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node)); |
1191 | 832k | ++(*Count); |
1192 | 832k | } |
1193 | | |
1194 | | /// Applies the best formatting by reconstructing the path in the |
1195 | | /// solution space that leads to \c Best. |
1196 | 6.82k | void reconstructPath(LineState &State, StateNode *Best) { |
1197 | 6.82k | llvm::SmallVector<StateNode *> Path; |
1198 | | // We do not need a break before the initial token. |
1199 | 97.7k | while (Best->Previous) { |
1200 | 90.9k | Path.push_back(Best); |
1201 | 90.9k | Best = Best->Previous; |
1202 | 90.9k | } |
1203 | 90.9k | for (const auto &Node : llvm::reverse(Path)) { |
1204 | 90.9k | unsigned Penalty = 0; |
1205 | 90.9k | formatChildren(State, Node->NewLine, /*DryRun=*/false, Penalty); |
1206 | 90.9k | Penalty += Indenter->addTokenToState(State, Node->NewLine, false); |
1207 | | |
1208 | 90.9k | LLVM_DEBUG({ |
1209 | 90.9k | printLineState(Node->Previous->State); |
1210 | 90.9k | if (Node->NewLine) |
1211 | 90.9k | llvm::dbgs() << "Penalty for placing " |
1212 | 90.9k | << Node->Previous->State.NextToken->Tok.getName() |
1213 | 90.9k | << " on a new line: " << Penalty << "\n"; |
1214 | 90.9k | }); |
1215 | 90.9k | } |
1216 | 6.82k | } |
1217 | | |
1218 | | llvm::SpecificBumpPtrAllocator<StateNode> Allocator; |
1219 | | }; |
1220 | | |
1221 | | } // anonymous namespace |
1222 | | |
1223 | | unsigned UnwrappedLineFormatter::format( |
1224 | | const SmallVectorImpl<AnnotatedLine *> &Lines, bool DryRun, |
1225 | | int AdditionalIndent, bool FixBadIndentation, unsigned FirstStartColumn, |
1226 | 25.2k | unsigned NextStartColumn, unsigned LastStartColumn) { |
1227 | 25.2k | LineJoiner Joiner(Style, Keywords, Lines); |
1228 | | |
1229 | | // Try to look up already computed penalty in DryRun-mode. |
1230 | 25.2k | std::pair<const SmallVectorImpl<AnnotatedLine *> *, unsigned> CacheKey( |
1231 | 25.2k | &Lines, AdditionalIndent); |
1232 | 25.2k | auto CacheIt = PenaltyCache.find(CacheKey); |
1233 | 25.2k | if (DryRun && CacheIt != PenaltyCache.end()2.18k ) |
1234 | 623 | return CacheIt->second; |
1235 | | |
1236 | 24.5k | assert(!Lines.empty()); |
1237 | 0 | unsigned Penalty = 0; |
1238 | 24.5k | LevelIndentTracker IndentTracker(Style, Keywords, Lines[0]->Level, |
1239 | 24.5k | AdditionalIndent); |
1240 | 24.5k | const AnnotatedLine *PrevPrevLine = nullptr; |
1241 | 24.5k | const AnnotatedLine *PreviousLine = nullptr; |
1242 | 24.5k | const AnnotatedLine *NextLine = nullptr; |
1243 | | |
1244 | | // The minimum level of consecutive lines that have been formatted. |
1245 | 24.5k | unsigned RangeMinLevel = UINT_MAX; |
1246 | | |
1247 | 24.5k | bool FirstLine = true; |
1248 | 24.5k | for (const AnnotatedLine *Line = |
1249 | 24.5k | Joiner.getNextMergedLine(DryRun, IndentTracker); |
1250 | 104k | Line; PrevPrevLine = PreviousLine, PreviousLine = Line, Line = NextLine, |
1251 | 79.9k | FirstLine = false) { |
1252 | 79.9k | assert(Line->First); |
1253 | 0 | const AnnotatedLine &TheLine = *Line; |
1254 | 79.9k | unsigned Indent = IndentTracker.getIndent(); |
1255 | | |
1256 | | // We continue formatting unchanged lines to adjust their indent, e.g. if a |
1257 | | // scope was added. However, we need to carefully stop doing this when we |
1258 | | // exit the scope of affected lines to prevent indenting a the entire |
1259 | | // remaining file if it currently missing a closing brace. |
1260 | 79.9k | bool PreviousRBrace = |
1261 | 79.9k | PreviousLine && PreviousLine->startsWith(tok::r_brace)55.4k ; |
1262 | 79.9k | bool ContinueFormatting = |
1263 | 79.9k | TheLine.Level > RangeMinLevel || |
1264 | 79.9k | (68.3k TheLine.Level == RangeMinLevel68.3k && !PreviousRBrace38.5k && |
1265 | 68.3k | !TheLine.startsWith(tok::r_brace)32.5k ); |
1266 | | |
1267 | 79.9k | bool FixIndentation = (FixBadIndentation || ContinueFormatting75.5k ) && |
1268 | 79.9k | Indent != TheLine.First->OriginalColumn41.5k ; |
1269 | 79.9k | bool ShouldFormat = TheLine.Affected || FixIndentation5.83k ; |
1270 | | // We cannot format this line; if the reason is that the line had a |
1271 | | // parsing error, remember that. |
1272 | 79.9k | if (ShouldFormat && TheLine.Type == LT_Invalid74.5k && Status26 ) { |
1273 | 20 | Status->FormatComplete = false; |
1274 | 20 | Status->Line = |
1275 | 20 | SourceMgr.getSpellingLineNumber(TheLine.First->Tok.getLocation()); |
1276 | 20 | } |
1277 | | |
1278 | 79.9k | if (ShouldFormat && TheLine.Type != LT_Invalid74.5k ) { |
1279 | 74.5k | if (!DryRun) { |
1280 | 71.5k | bool LastLine = TheLine.First->is(tok::eof); |
1281 | 71.5k | formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines, Indent, |
1282 | 71.5k | LastLine ? LastStartColumn21.8k : NextStartColumn + Indent49.7k ); |
1283 | 71.5k | } |
1284 | | |
1285 | 74.5k | NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker); |
1286 | 74.5k | unsigned ColumnLimit = getColumnLimit(TheLine.InPPDirective, NextLine); |
1287 | 74.5k | bool FitsIntoOneLine = |
1288 | 74.5k | TheLine.Last->TotalLength + Indent <= ColumnLimit || |
1289 | 74.5k | (8.38k TheLine.Type == LT_ImportStatement8.38k && |
1290 | 8.38k | (65 !Style.isJavaScript()65 || !Style.JavaScriptWrapImports26 )) || |
1291 | 74.5k | (8.32k Style.isCSharp()8.32k && |
1292 | 8.32k | TheLine.InPPDirective94 ); // don't split #regions in C# |
1293 | 74.5k | if (Style.ColumnLimit == 0) |
1294 | 1.81k | NoColumnLimitLineFormatter(Indenter, Whitespaces, Style, this) |
1295 | 1.81k | .formatLine(TheLine, NextStartColumn + Indent, |
1296 | 1.81k | FirstLine ? FirstStartColumn341 : 01.47k , DryRun); |
1297 | 72.7k | else if (FitsIntoOneLine) |
1298 | 65.9k | Penalty += NoLineBreakFormatter(Indenter, Whitespaces, Style, this) |
1299 | 65.9k | .formatLine(TheLine, NextStartColumn + Indent, |
1300 | 65.9k | FirstLine ? FirstStartColumn18.3k : 047.5k , DryRun); |
1301 | 6.80k | else |
1302 | 6.80k | Penalty += OptimizingLineFormatter(Indenter, Whitespaces, Style, this) |
1303 | 6.80k | .formatLine(TheLine, NextStartColumn + Indent, |
1304 | 6.80k | FirstLine ? FirstStartColumn5.36k : 01.44k , DryRun); |
1305 | 74.5k | RangeMinLevel = std::min(RangeMinLevel, TheLine.Level); |
1306 | 74.5k | } else { |
1307 | | // If no token in the current line is affected, we still need to format |
1308 | | // affected children. |
1309 | 5.45k | if (TheLine.ChildrenAffected) |
1310 | 93 | for (const FormatToken *Tok = TheLine.First; 11 Tok; Tok = Tok->Next82 ) |
1311 | 82 | if (!Tok->Children.empty()) |
1312 | 12 | format(Tok->Children, DryRun); |
1313 | | |
1314 | | // Adapt following lines on the current indent level to the same level |
1315 | | // unless the current \c AnnotatedLine is not at the beginning of a line. |
1316 | 5.45k | bool StartsNewLine = |
1317 | 5.45k | TheLine.First->NewlinesBefore > 0 || TheLine.First->IsFirst564 ; |
1318 | 5.45k | if (StartsNewLine) |
1319 | 5.20k | IndentTracker.adjustToUnmodifiedLine(TheLine); |
1320 | 5.45k | if (!DryRun) { |
1321 | 5.45k | bool ReformatLeadingWhitespace = |
1322 | 5.45k | StartsNewLine && (5.19k (5.19k PreviousLine5.19k && PreviousLine->Affected4.65k ) || |
1323 | 5.19k | TheLine.LeadingEmptyLinesAffected4.76k ); |
1324 | | // Format the first token. |
1325 | 5.45k | if (ReformatLeadingWhitespace) |
1326 | 449 | formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines, |
1327 | 449 | TheLine.First->OriginalColumn, |
1328 | 449 | TheLine.First->OriginalColumn); |
1329 | 5.00k | else |
1330 | 5.00k | Whitespaces->addUntouchableToken(*TheLine.First, |
1331 | 5.00k | TheLine.InPPDirective); |
1332 | | |
1333 | | // Notify the WhitespaceManager about the unchanged whitespace. |
1334 | 24.6k | for (FormatToken *Tok = TheLine.First->Next; Tok; Tok = Tok->Next19.1k ) |
1335 | 19.1k | Whitespaces->addUntouchableToken(*Tok, TheLine.InPPDirective); |
1336 | 5.45k | } |
1337 | 5.45k | NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker); |
1338 | 5.45k | RangeMinLevel = UINT_MAX; |
1339 | 5.45k | } |
1340 | 79.9k | if (!DryRun) |
1341 | 77.0k | markFinalized(TheLine.First); |
1342 | 79.9k | } |
1343 | 24.5k | PenaltyCache[CacheKey] = Penalty; |
1344 | 24.5k | return Penalty; |
1345 | 25.2k | } |
1346 | | |
1347 | | void UnwrappedLineFormatter::formatFirstToken( |
1348 | | const AnnotatedLine &Line, const AnnotatedLine *PreviousLine, |
1349 | | const AnnotatedLine *PrevPrevLine, |
1350 | | const SmallVectorImpl<AnnotatedLine *> &Lines, unsigned Indent, |
1351 | 72.0k | unsigned NewlineIndent) { |
1352 | 72.0k | FormatToken &RootToken = *Line.First; |
1353 | 72.0k | if (RootToken.is(tok::eof)) { |
1354 | 21.9k | unsigned Newlines = std::min(RootToken.NewlinesBefore, 1u); |
1355 | 21.9k | unsigned TokenIndent = Newlines ? NewlineIndent1.73k : 020.1k ; |
1356 | 21.9k | Whitespaces->replaceWhitespace(RootToken, Newlines, TokenIndent, |
1357 | 21.9k | TokenIndent); |
1358 | 21.9k | return; |
1359 | 21.9k | } |
1360 | 50.1k | unsigned Newlines = |
1361 | 50.1k | std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1); |
1362 | | // Remove empty lines before "}" where applicable. |
1363 | 50.1k | if (RootToken.is(tok::r_brace) && |
1364 | 50.1k | (7.08k !RootToken.Next7.08k || |
1365 | 7.08k | (2.49k RootToken.Next->is(tok::semi)2.49k && !RootToken.Next->Next1.09k )) && |
1366 | | // Do not remove empty lines before namespace closing "}". |
1367 | 50.1k | !getNamespaceToken(&Line, Lines)5.68k ) |
1368 | 5.48k | Newlines = std::min(Newlines, 1u); |
1369 | | // Remove empty lines at the start of nested blocks (lambdas/arrow functions) |
1370 | 50.1k | if (PreviousLine == nullptr && Line.Level > 022.4k ) |
1371 | 783 | Newlines = std::min(Newlines, 1u); |
1372 | 50.1k | if (Newlines == 0 && !RootToken.IsFirst33.2k ) |
1373 | 11.8k | Newlines = 1; |
1374 | 50.1k | if (RootToken.IsFirst && !RootToken.HasUnescapedNewline21.6k ) |
1375 | 21.4k | Newlines = 0; |
1376 | | |
1377 | | // Remove empty lines after "{". |
1378 | 50.1k | if (!Style.KeepEmptyLinesAtTheStartOfBlocks && PreviousLine6.37k && |
1379 | 50.1k | PreviousLine->Last->is(tok::l_brace)2.56k && |
1380 | 50.1k | !PreviousLine->startsWithNamespace()748 && |
1381 | 50.1k | !(741 PrevPrevLine741 && PrevPrevLine->startsWithNamespace()269 && |
1382 | 741 | PreviousLine->startsWith(tok::l_brace)9 ) && |
1383 | 50.1k | !startsExternCBlock(*PreviousLine)732 ) |
1384 | 725 | Newlines = 1; |
1385 | | |
1386 | | // Insert or remove empty line before access specifiers. |
1387 | 50.1k | if (PreviousLine && RootToken.isAccessSpecifier()27.6k ) { |
1388 | 523 | switch (Style.EmptyLineBeforeAccessModifier) { |
1389 | 64 | case FormatStyle::ELBAMS_Never: |
1390 | 64 | if (Newlines > 1) |
1391 | 13 | Newlines = 1; |
1392 | 64 | break; |
1393 | 38 | case FormatStyle::ELBAMS_Leave: |
1394 | 38 | Newlines = std::max(RootToken.NewlinesBefore, 1u); |
1395 | 38 | break; |
1396 | 369 | case FormatStyle::ELBAMS_LogicalBlock: |
1397 | 369 | if (PreviousLine->Last->isOneOf(tok::semi, tok::r_brace) && Newlines <= 1101 ) |
1398 | 49 | Newlines = 2; |
1399 | 369 | if (PreviousLine->First->isAccessSpecifier()) |
1400 | 44 | Newlines = 1; // Previous is an access modifier remove all new lines. |
1401 | 369 | break; |
1402 | 52 | case FormatStyle::ELBAMS_Always: { |
1403 | 52 | const FormatToken *previousToken; |
1404 | 52 | if (PreviousLine->Last->is(tok::comment)) |
1405 | 6 | previousToken = PreviousLine->Last->getPreviousNonComment(); |
1406 | 46 | else |
1407 | 46 | previousToken = PreviousLine->Last; |
1408 | 52 | if ((!previousToken || !previousToken->is(tok::l_brace)49 ) && Newlines <= 135 ) |
1409 | 24 | Newlines = 2; |
1410 | 52 | } break; |
1411 | 523 | } |
1412 | 523 | } |
1413 | | |
1414 | | // Insert or remove empty line after access specifiers. |
1415 | 50.1k | if (PreviousLine && PreviousLine->First->isAccessSpecifier()27.6k && |
1416 | 50.1k | (525 !PreviousLine->InPPDirective525 || !RootToken.HasUnescapedNewline5 )) { |
1417 | | // EmptyLineBeforeAccessModifier is handling the case when two access |
1418 | | // modifiers follow each other. |
1419 | 525 | if (!RootToken.isAccessSpecifier()) { |
1420 | 456 | switch (Style.EmptyLineAfterAccessModifier) { |
1421 | 376 | case FormatStyle::ELAAMS_Never: |
1422 | 376 | Newlines = 1; |
1423 | 376 | break; |
1424 | 34 | case FormatStyle::ELAAMS_Leave: |
1425 | 34 | Newlines = std::max(Newlines, 1u); |
1426 | 34 | break; |
1427 | 46 | case FormatStyle::ELAAMS_Always: |
1428 | 46 | if (RootToken.is(tok::r_brace)) // Do not add at end of class. |
1429 | 10 | Newlines = 1u; |
1430 | 36 | else |
1431 | 36 | Newlines = std::max(Newlines, 2u); |
1432 | 46 | break; |
1433 | 456 | } |
1434 | 456 | } |
1435 | 525 | } |
1436 | | |
1437 | 50.1k | if (Newlines) |
1438 | 28.6k | Indent = NewlineIndent; |
1439 | | |
1440 | | // Preprocessor directives get indented before the hash only if specified. In |
1441 | | // Javascript import statements are indented like normal statements. |
1442 | 50.1k | if (!Style.isJavaScript() && |
1443 | 50.1k | Style.IndentPPDirectives != FormatStyle::PPDIS_BeforeHash47.5k && |
1444 | 50.1k | (47.3k Line.Type == LT_PreprocessorDirective47.3k || |
1445 | 47.3k | Line.Type == LT_ImportStatement44.8k )) |
1446 | 3.63k | Indent = 0; |
1447 | | |
1448 | 50.1k | Whitespaces->replaceWhitespace(RootToken, Newlines, Indent, Indent, |
1449 | 50.1k | /*IsAligned=*/false, |
1450 | 50.1k | Line.InPPDirective && |
1451 | 50.1k | !RootToken.HasUnescapedNewline4.18k ); |
1452 | 50.1k | } |
1453 | | |
1454 | | unsigned |
1455 | | UnwrappedLineFormatter::getColumnLimit(bool InPPDirective, |
1456 | 74.5k | const AnnotatedLine *NextLine) const { |
1457 | | // In preprocessor directives reserve two chars for trailing " \" if the |
1458 | | // next line continues the preprocessor directive. |
1459 | 74.5k | bool ContinuesPPDirective = |
1460 | 74.5k | InPPDirective && |
1461 | | // If there is no next line, this is likely a child line and the parent |
1462 | | // continues the preprocessor directive. |
1463 | 74.5k | (4.19k !NextLine4.19k || |
1464 | 4.19k | (4.18k NextLine->InPPDirective4.18k && |
1465 | | // If there is an unescaped newline between this line and the next, the |
1466 | | // next line starts a new preprocessor directive. |
1467 | 4.18k | !NextLine->First->HasUnescapedNewline2.07k )); |
1468 | 74.5k | return Style.ColumnLimit - (ContinuesPPDirective ? 2561 : 073.9k ); |
1469 | 74.5k | } |
1470 | | |
1471 | | } // namespace format |
1472 | | } // namespace clang |