blob: 005eec82b7bb0237b05a31632fcb86ad1fdcf028 [file] [log] [blame]
Daniel Jasperde0328a2013-08-16 11:20:30 +00001//===--- ContinuationIndenter.cpp - Format C++ code -----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief This file implements the continuation indenter.
12///
13//===----------------------------------------------------------------------===//
14
15#define DEBUG_TYPE "format-formatter"
16
17#include "BreakableToken.h"
18#include "ContinuationIndenter.h"
19#include "WhitespaceManager.h"
20#include "clang/Basic/OperatorPrecedence.h"
21#include "clang/Basic/SourceManager.h"
22#include "clang/Format/Format.h"
23#include "llvm/Support/Debug.h"
24#include <string>
25
26namespace clang {
27namespace format {
28
29// Returns the length of everything up to the first possible line break after
30// the ), ], } or > matching \c Tok.
31static unsigned getLengthToMatchingParen(const FormatToken &Tok) {
32 if (Tok.MatchingParen == NULL)
33 return 0;
34 FormatToken *End = Tok.MatchingParen;
35 while (End->Next && !End->Next->CanBreakBefore) {
36 End = End->Next;
37 }
38 return End->TotalLength - Tok.TotalLength + 1;
39}
40
41ContinuationIndenter::ContinuationIndenter(const FormatStyle &Style,
42 SourceManager &SourceMgr,
43 const AnnotatedLine &Line,
44 unsigned FirstIndent,
45 WhitespaceManager &Whitespaces,
46 encoding::Encoding Encoding,
47 bool BinPackInconclusiveFunctions)
48 : Style(Style), SourceMgr(SourceMgr), Line(Line), FirstIndent(FirstIndent),
49 Whitespaces(Whitespaces), Encoding(Encoding),
50 BinPackInconclusiveFunctions(BinPackInconclusiveFunctions) {}
51
52LineState ContinuationIndenter::getInitialState() {
53 // Initialize state dependent on indent.
54 LineState State;
55 State.Column = FirstIndent;
56 State.NextToken = Line.First;
57 State.Stack.push_back(ParenState(FirstIndent, FirstIndent,
58 /*AvoidBinPacking=*/false,
59 /*NoLineBreak=*/false));
60 State.LineContainsContinuedForLoopSection = false;
61 State.ParenLevel = 0;
62 State.StartOfStringLiteral = 0;
63 State.StartOfLineLevel = State.ParenLevel;
64 State.LowestLevelOnLine = State.ParenLevel;
65 State.IgnoreStackForComparison = false;
66
67 // The first token has already been indented and thus consumed.
68 moveStateToNextToken(State, /*DryRun=*/false,
69 /*Newline=*/false);
70 return State;
71}
72
73bool ContinuationIndenter::canBreak(const LineState &State) {
74 const FormatToken &Current = *State.NextToken;
75 const FormatToken &Previous = *Current.Previous;
76 assert(&Previous == Current.Previous);
77 if (!Current.CanBreakBefore &&
78 !(Current.is(tok::r_brace) && State.Stack.back().BreakBeforeClosingBrace))
79 return false;
80 // The opening "{" of a braced list has to be on the same line as the first
81 // element if it is nested in another braced init list or function call.
82 if (!Current.MustBreakBefore && Previous.is(tok::l_brace) &&
83 Previous.Previous &&
84 Previous.Previous->isOneOf(tok::l_brace, tok::l_paren, tok::comma))
85 return false;
86 // This prevents breaks like:
87 // ...
88 // SomeParameter, OtherParameter).DoSomething(
89 // ...
90 // As they hide "DoSomething" and are generally bad for readability.
91 if (Previous.opensScope() && State.LowestLevelOnLine < State.StartOfLineLevel)
92 return false;
93 return !State.Stack.back().NoLineBreak;
94}
95
96bool ContinuationIndenter::mustBreak(const LineState &State) {
97 const FormatToken &Current = *State.NextToken;
98 const FormatToken &Previous = *Current.Previous;
99 if (Current.MustBreakBefore || Current.Type == TT_InlineASMColon)
100 return true;
101 if (!Style.Cpp11BracedListStyle && Current.is(tok::r_brace) &&
102 State.Stack.back().BreakBeforeClosingBrace)
103 return true;
104 if (Previous.is(tok::semi) && State.LineContainsContinuedForLoopSection)
105 return true;
106 if (Style.BreakConstructorInitializersBeforeComma) {
107 if (Previous.Type == TT_CtorInitializerComma)
108 return false;
109 if (Current.Type == TT_CtorInitializerComma)
110 return true;
111 }
112 if ((Previous.isOneOf(tok::comma, tok::semi) || Current.is(tok::question) ||
113 (Current.Type == TT_ConditionalExpr &&
114 !(Current.is(tok::colon) && Previous.is(tok::question)))) &&
115 State.Stack.back().BreakBeforeParameter && !Current.isTrailingComment() &&
116 !Current.isOneOf(tok::r_paren, tok::r_brace))
117 return true;
118 if (Style.AlwaysBreakBeforeMultilineStrings &&
119 State.Column > State.Stack.back().Indent &&
120 Current.is(tok::string_literal) && Previous.isNot(tok::lessless) &&
121 Previous.Type != TT_InlineASMColon &&
122 ((Current.getNextNonComment() &&
123 Current.getNextNonComment()->is(tok::string_literal)) ||
124 (Current.TokenText.find("\\\n") != StringRef::npos)))
125 return true;
126
127 if (!Style.BreakBeforeBinaryOperators) {
128 // If we need to break somewhere inside the LHS of a binary expression, we
129 // should also break after the operator. Otherwise, the formatting would
130 // hide the operator precedence, e.g. in:
131 // if (aaaaaaaaaaaaaa ==
132 // bbbbbbbbbbbbbb && c) {..
133 // For comparisons, we only apply this rule, if the LHS is a binary
134 // expression itself as otherwise, the line breaks seem superfluous.
135 // We need special cases for ">>" which we have split into two ">" while
136 // lexing in order to make template parsing easier.
137 //
138 // FIXME: We'll need something similar for styles that break before binary
139 // operators.
140 bool IsComparison = (Previous.getPrecedence() == prec::Relational ||
141 Previous.getPrecedence() == prec::Equality) &&
142 Previous.Previous &&
143 Previous.Previous->Type != TT_BinaryOperator; // For >>.
144 bool LHSIsBinaryExpr =
145 Previous.Previous && Previous.Previous->FakeRParens > 0;
146 if (Previous.Type == TT_BinaryOperator &&
147 (!IsComparison || LHSIsBinaryExpr) &&
148 Current.Type != TT_BinaryOperator && // For >>.
149 !Current.isTrailingComment() &&
150 !Previous.isOneOf(tok::lessless, tok::question) &&
151 Previous.getPrecedence() != prec::Assignment &&
152 State.Stack.back().BreakBeforeParameter)
153 return true;
154 }
155
156 // Same as above, but for the first "<<" operator.
157 if (Current.is(tok::lessless) && State.Stack.back().BreakBeforeParameter &&
158 State.Stack.back().FirstLessLess == 0)
159 return true;
160
161 // FIXME: Comparing LongestObjCSelectorName to 0 is a hacky way of finding
162 // out whether it is the first parameter. Clean this up.
163 if (Current.Type == TT_ObjCSelectorName &&
164 Current.LongestObjCSelectorName == 0 &&
165 State.Stack.back().BreakBeforeParameter)
166 return true;
167 if ((Current.Type == TT_CtorInitializerColon ||
168 (Previous.ClosesTemplateDeclaration && State.ParenLevel == 0)))
169 return true;
170
171 if ((Current.Type == TT_StartOfName || Current.is(tok::kw_operator)) &&
172 Line.MightBeFunctionDecl && State.Stack.back().BreakBeforeParameter &&
173 State.ParenLevel == 0)
174 return true;
175 return false;
176}
177
178unsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline,
Daniel Jasper8de9ed02013-08-22 15:00:41 +0000179 bool DryRun,
180 unsigned ExtraSpaces) {
Daniel Jasperde0328a2013-08-16 11:20:30 +0000181 const FormatToken &Current = *State.NextToken;
182 const FormatToken &Previous = *State.NextToken->Previous;
183
184 // Extra penalty that needs to be added because of the way certain line
185 // breaks are chosen.
Daniel Jasper8de9ed02013-08-22 15:00:41 +0000186 unsigned Penalty = 0;
Daniel Jasperde0328a2013-08-16 11:20:30 +0000187
188 if (State.Stack.size() == 0 || Current.Type == TT_ImplicitStringLiteral) {
189 // FIXME: Is this correct?
190 int WhitespaceLength = SourceMgr.getSpellingColumnNumber(
191 State.NextToken->WhitespaceRange.getEnd()) -
192 SourceMgr.getSpellingColumnNumber(
193 State.NextToken->WhitespaceRange.getBegin());
194 State.Column += WhitespaceLength + State.NextToken->CodePointCount;
195 State.NextToken = State.NextToken->Next;
196 return 0;
197 }
198
199 // If we are continuing an expression, we want to indent an extra 4 spaces.
200 unsigned ContinuationIndent =
201 std::max(State.Stack.back().LastSpace, State.Stack.back().Indent) + 4;
202 if (Newline) {
Daniel Jasper8de9ed02013-08-22 15:00:41 +0000203 // The first line break on any ParenLevel causes an extra penalty in order
204 // prefer similar line breaks.
205 if (!State.Stack.back().ContainsLineBreak)
206 Penalty += 15;
207 State.Stack.back().ContainsLineBreak = true;
208
209 Penalty += State.NextToken->SplitPenalty;
210
Daniel Jasperde0328a2013-08-16 11:20:30 +0000211 // Breaking before the first "<<" is generally not desirable if the LHS is
212 // short.
213 if (Current.is(tok::lessless) && State.Stack.back().FirstLessLess == 0 &&
214 State.Column <= Style.ColumnLimit / 2)
Daniel Jasper8de9ed02013-08-22 15:00:41 +0000215 Penalty += Style.PenaltyBreakFirstLessLess;
Daniel Jasperde0328a2013-08-16 11:20:30 +0000216
Daniel Jasperde0328a2013-08-16 11:20:30 +0000217 if (Current.is(tok::r_brace)) {
218 if (Current.BlockKind == BK_BracedInit)
219 State.Column = State.Stack[State.Stack.size() - 2].LastSpace;
220 else
221 State.Column = FirstIndent;
222 } else if (Current.is(tok::string_literal) &&
223 State.StartOfStringLiteral != 0) {
224 State.Column = State.StartOfStringLiteral;
225 State.Stack.back().BreakBeforeParameter = true;
226 } else if (Current.is(tok::lessless) &&
227 State.Stack.back().FirstLessLess != 0) {
228 State.Column = State.Stack.back().FirstLessLess;
229 } else if (Current.isOneOf(tok::period, tok::arrow) &&
230 Current.Type != TT_DesignatedInitializerPeriod) {
231 if (State.Stack.back().CallContinuation == 0) {
232 State.Column = ContinuationIndent;
233 State.Stack.back().CallContinuation = State.Column;
234 } else {
235 State.Column = State.Stack.back().CallContinuation;
236 }
237 } else if (Current.Type == TT_ConditionalExpr) {
238 State.Column = State.Stack.back().QuestionColumn;
239 } else if (Previous.is(tok::comma) && State.Stack.back().VariablePos != 0) {
240 State.Column = State.Stack.back().VariablePos;
241 } else if (Previous.ClosesTemplateDeclaration ||
242 ((Current.Type == TT_StartOfName ||
243 Current.is(tok::kw_operator)) &&
244 State.ParenLevel == 0 &&
245 (!Style.IndentFunctionDeclarationAfterType ||
246 Line.StartsDefinition))) {
247 State.Column = State.Stack.back().Indent;
248 } else if (Current.Type == TT_ObjCSelectorName) {
249 if (State.Stack.back().ColonPos > Current.CodePointCount) {
250 State.Column = State.Stack.back().ColonPos - Current.CodePointCount;
251 } else {
252 State.Column = State.Stack.back().Indent;
253 State.Stack.back().ColonPos = State.Column + Current.CodePointCount;
254 }
255 } else if (Current.is(tok::l_square) && Current.Type != TT_ObjCMethodExpr) {
256 if (State.Stack.back().StartOfArraySubscripts != 0)
257 State.Column = State.Stack.back().StartOfArraySubscripts;
258 else
259 State.Column = ContinuationIndent;
260 } else if (Current.Type == TT_StartOfName ||
261 Previous.isOneOf(tok::coloncolon, tok::equal) ||
262 Previous.Type == TT_ObjCMethodExpr) {
263 State.Column = ContinuationIndent;
264 } else if (Current.Type == TT_CtorInitializerColon) {
265 State.Column = FirstIndent + Style.ConstructorInitializerIndentWidth;
266 } else if (Current.Type == TT_CtorInitializerComma) {
267 State.Column = State.Stack.back().Indent;
268 } else {
269 State.Column = State.Stack.back().Indent;
270 // Ensure that we fall back to indenting 4 spaces instead of just
271 // flushing continuations left.
272 if (State.Column == FirstIndent)
273 State.Column += 4;
274 }
275
276 if (Current.is(tok::question))
277 State.Stack.back().BreakBeforeParameter = true;
278 if ((Previous.isOneOf(tok::comma, tok::semi) &&
279 !State.Stack.back().AvoidBinPacking) ||
280 Previous.Type == TT_BinaryOperator)
281 State.Stack.back().BreakBeforeParameter = false;
282 if (Previous.Type == TT_TemplateCloser && State.ParenLevel == 0)
283 State.Stack.back().BreakBeforeParameter = false;
284
285 if (!DryRun) {
286 unsigned NewLines = 1;
287 if (Current.is(tok::comment))
288 NewLines = std::max(NewLines, std::min(Current.NewlinesBefore,
289 Style.MaxEmptyLinesToKeep + 1));
290 Whitespaces.replaceWhitespace(Current, NewLines, State.Column,
291 State.Column, Line.InPPDirective);
292 }
293
294 if (!Current.isTrailingComment())
295 State.Stack.back().LastSpace = State.Column;
296 if (Current.isOneOf(tok::arrow, tok::period) &&
297 Current.Type != TT_DesignatedInitializerPeriod)
298 State.Stack.back().LastSpace += Current.CodePointCount;
299 State.StartOfLineLevel = State.ParenLevel;
300 State.LowestLevelOnLine = State.ParenLevel;
301
302 // Any break on this level means that the parent level has been broken
303 // and we need to avoid bin packing there.
304 for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) {
305 State.Stack[i].BreakBeforeParameter = true;
306 }
307 const FormatToken *TokenBefore = Current.getPreviousNonComment();
308 if (TokenBefore && !TokenBefore->isOneOf(tok::comma, tok::semi) &&
309 TokenBefore->Type != TT_TemplateCloser &&
310 TokenBefore->Type != TT_BinaryOperator && !TokenBefore->opensScope())
311 State.Stack.back().BreakBeforeParameter = true;
312
313 // If we break after {, we should also break before the corresponding }.
314 if (Previous.is(tok::l_brace))
315 State.Stack.back().BreakBeforeClosingBrace = true;
316
317 if (State.Stack.back().AvoidBinPacking) {
318 // If we are breaking after '(', '{', '<', this is not bin packing
319 // unless AllowAllParametersOfDeclarationOnNextLine is false.
320 if (!(Previous.isOneOf(tok::l_paren, tok::l_brace) ||
321 Previous.Type == TT_BinaryOperator) ||
322 (!Style.AllowAllParametersOfDeclarationOnNextLine &&
323 Line.MustBeDeclaration))
324 State.Stack.back().BreakBeforeParameter = true;
325 }
326
327 } else {
328 if (Current.is(tok::equal) &&
329 (Line.First->is(tok::kw_for) || State.ParenLevel == 0) &&
330 State.Stack.back().VariablePos == 0) {
331 State.Stack.back().VariablePos = State.Column;
332 // Move over * and & if they are bound to the variable name.
333 const FormatToken *Tok = &Previous;
334 while (Tok && State.Stack.back().VariablePos >= Tok->CodePointCount) {
335 State.Stack.back().VariablePos -= Tok->CodePointCount;
336 if (Tok->SpacesRequiredBefore != 0)
337 break;
338 Tok = Tok->Previous;
339 }
340 if (Previous.PartOfMultiVariableDeclStmt)
341 State.Stack.back().LastSpace = State.Stack.back().VariablePos;
342 }
343
Daniel Jasper8de9ed02013-08-22 15:00:41 +0000344 unsigned Spaces = State.NextToken->SpacesRequiredBefore + ExtraSpaces;
Daniel Jasperde0328a2013-08-16 11:20:30 +0000345
346 if (!DryRun)
347 Whitespaces.replaceWhitespace(Current, 0, Spaces, State.Column + Spaces);
348
349 if (Current.Type == TT_ObjCSelectorName &&
350 State.Stack.back().ColonPos == 0) {
351 if (State.Stack.back().Indent + Current.LongestObjCSelectorName >
352 State.Column + Spaces + Current.CodePointCount)
353 State.Stack.back().ColonPos =
354 State.Stack.back().Indent + Current.LongestObjCSelectorName;
355 else
356 State.Stack.back().ColonPos =
357 State.Column + Spaces + Current.CodePointCount;
358 }
359
360 if (Previous.opensScope() && Previous.Type != TT_ObjCMethodExpr &&
361 Current.Type != TT_LineComment)
362 State.Stack.back().Indent = State.Column + Spaces;
363 if (Previous.is(tok::comma) && !Current.isTrailingComment() &&
364 State.Stack.back().AvoidBinPacking)
365 State.Stack.back().NoLineBreak = true;
366
367 State.Column += Spaces;
368 if (Current.is(tok::l_paren) && Previous.isOneOf(tok::kw_if, tok::kw_for))
369 // Treat the condition inside an if as if it was a second function
370 // parameter, i.e. let nested calls have an indent of 4.
371 State.Stack.back().LastSpace = State.Column + 1; // 1 is length of "(".
372 else if (Previous.is(tok::comma))
373 State.Stack.back().LastSpace = State.Column;
374 else if ((Previous.Type == TT_BinaryOperator ||
375 Previous.Type == TT_ConditionalExpr ||
Daniel Jasperf110e202013-08-21 08:39:01 +0000376 Previous.Type == TT_UnaryOperator ||
Daniel Jasperde0328a2013-08-16 11:20:30 +0000377 Previous.Type == TT_CtorInitializerColon) &&
378 !(Previous.getPrecedence() == prec::Assignment &&
379 Current.FakeLParens.empty()))
380 // Always indent relative to the RHS of the expression unless this is a
Daniel Jasperf110e202013-08-21 08:39:01 +0000381 // simple assignment without binary expression on the RHS. Also indent
382 // relative to unary operators and the colons of constructor initializers.
Daniel Jasperde0328a2013-08-16 11:20:30 +0000383 State.Stack.back().LastSpace = State.Column;
384 else if (Previous.Type == TT_InheritanceColon)
385 State.Stack.back().Indent = State.Column;
386 else if (Previous.opensScope()) {
387 // If a function has multiple parameters (including a single parameter
388 // that is a binary expression) or a trailing call, indent all
389 // parameters from the opening parenthesis. This avoids confusing
390 // indents like:
391 // OuterFunction(InnerFunctionCall(
392 // ParameterToInnerFunction),
393 // SecondParameterToOuterFunction);
394 bool HasMultipleParameters = !Current.FakeLParens.empty();
395 bool HasTrailingCall = false;
396 if (Previous.MatchingParen) {
397 const FormatToken *Next = Previous.MatchingParen->getNextNonComment();
398 if (Next && Next->isOneOf(tok::period, tok::arrow))
399 HasTrailingCall = true;
400 }
401 if (HasMultipleParameters || HasTrailingCall)
402 State.Stack.back().LastSpace = State.Column;
403 }
404 }
405
Daniel Jasper8de9ed02013-08-22 15:00:41 +0000406 return moveStateToNextToken(State, DryRun, Newline) + Penalty;
Daniel Jasperde0328a2013-08-16 11:20:30 +0000407}
408
409unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
410 bool DryRun, bool Newline) {
411 const FormatToken &Current = *State.NextToken;
412 assert(State.Stack.size());
413
414 if (Current.Type == TT_InheritanceColon)
415 State.Stack.back().AvoidBinPacking = true;
416 if (Current.is(tok::lessless) && State.Stack.back().FirstLessLess == 0)
417 State.Stack.back().FirstLessLess = State.Column;
418 if (Current.is(tok::l_square) &&
419 State.Stack.back().StartOfArraySubscripts == 0)
420 State.Stack.back().StartOfArraySubscripts = State.Column;
421 if (Current.is(tok::question))
422 State.Stack.back().QuestionColumn = State.Column;
423 if (!Current.opensScope() && !Current.closesScope())
424 State.LowestLevelOnLine =
425 std::min(State.LowestLevelOnLine, State.ParenLevel);
426 if (Current.isOneOf(tok::period, tok::arrow) &&
427 Line.Type == LT_BuilderTypeCall && State.ParenLevel == 0)
428 State.Stack.back().StartOfFunctionCall =
429 Current.LastInChainOfCalls ? 0 : State.Column + Current.CodePointCount;
430 if (Current.Type == TT_CtorInitializerColon) {
431 // Indent 2 from the column, so:
432 // SomeClass::SomeClass()
433 // : First(...), ...
434 // Next(...)
435 // ^ line up here.
436 State.Stack.back().Indent =
437 State.Column + (Style.BreakConstructorInitializersBeforeComma ? 0 : 2);
438 if (Style.ConstructorInitializerAllOnOneLineOrOnePerLine)
439 State.Stack.back().AvoidBinPacking = true;
440 State.Stack.back().BreakBeforeParameter = false;
441 }
442
443 // If return returns a binary expression, align after it.
444 if (Current.is(tok::kw_return) && !Current.FakeLParens.empty())
445 State.Stack.back().LastSpace = State.Column + 7;
446
447 // In ObjC method declaration we align on the ":" of parameters, but we need
448 // to ensure that we indent parameters on subsequent lines by at least 4.
449 if (Current.Type == TT_ObjCMethodSpecifier)
450 State.Stack.back().Indent += 4;
451
452 // Insert scopes created by fake parenthesis.
453 const FormatToken *Previous = Current.getPreviousNonComment();
454 // Don't add extra indentation for the first fake parenthesis after
455 // 'return', assignements or opening <({[. The indentation for these cases
456 // is special cased.
457 bool SkipFirstExtraIndent =
458 Current.is(tok::kw_return) ||
459 (Previous && (Previous->opensScope() ||
460 Previous->getPrecedence() == prec::Assignment));
461 for (SmallVectorImpl<prec::Level>::const_reverse_iterator
462 I = Current.FakeLParens.rbegin(),
463 E = Current.FakeLParens.rend();
464 I != E; ++I) {
465 ParenState NewParenState = State.Stack.back();
466 NewParenState.ContainsLineBreak = false;
467 NewParenState.Indent =
468 std::max(std::max(State.Column, NewParenState.Indent),
469 State.Stack.back().LastSpace);
470
471 // Always indent conditional expressions. Never indent expression where
472 // the 'operator' is ',', ';' or an assignment (i.e. *I <=
473 // prec::Assignment) as those have different indentation rules. Indent
474 // other expression, unless the indentation needs to be skipped.
475 if (*I == prec::Conditional ||
476 (!SkipFirstExtraIndent && *I > prec::Assignment &&
477 !Style.BreakBeforeBinaryOperators))
478 NewParenState.Indent += 4;
479 if (Previous && !Previous->opensScope())
480 NewParenState.BreakBeforeParameter = false;
481 State.Stack.push_back(NewParenState);
482 SkipFirstExtraIndent = false;
483 }
484
485 // If we encounter an opening (, [, { or <, we add a level to our stacks to
486 // prepare for the following tokens.
487 if (Current.opensScope()) {
488 unsigned NewIndent;
489 unsigned LastSpace = State.Stack.back().LastSpace;
490 bool AvoidBinPacking;
491 if (Current.is(tok::l_brace)) {
492 NewIndent =
493 LastSpace + (Style.Cpp11BracedListStyle ? 4 : Style.IndentWidth);
494 const FormatToken *NextNoComment = Current.getNextNonComment();
495 AvoidBinPacking = NextNoComment &&
496 NextNoComment->Type == TT_DesignatedInitializerPeriod;
497 } else {
498 NewIndent =
499 4 + std::max(LastSpace, State.Stack.back().StartOfFunctionCall);
500 AvoidBinPacking = !Style.BinPackParameters ||
501 (Style.ExperimentalAutoDetectBinPacking &&
502 (Current.PackingKind == PPK_OnePerLine ||
503 (!BinPackInconclusiveFunctions &&
504 Current.PackingKind == PPK_Inconclusive)));
505 }
506
507 State.Stack.push_back(ParenState(NewIndent, LastSpace, AvoidBinPacking,
508 State.Stack.back().NoLineBreak));
509 ++State.ParenLevel;
510 }
511
512 // If this '[' opens an ObjC call, determine whether all parameters fit into
513 // one line and put one per line if they don't.
514 if (Current.is(tok::l_square) && Current.Type == TT_ObjCMethodExpr &&
515 Current.MatchingParen != NULL) {
516 if (getLengthToMatchingParen(Current) + State.Column > getColumnLimit())
517 State.Stack.back().BreakBeforeParameter = true;
518 }
519
520 // If we encounter a closing ), ], } or >, we can remove a level from our
521 // stacks.
522 if (Current.isOneOf(tok::r_paren, tok::r_square) ||
523 (Current.is(tok::r_brace) && State.NextToken != Line.First) ||
524 State.NextToken->Type == TT_TemplateCloser) {
525 State.Stack.pop_back();
526 --State.ParenLevel;
527 }
528 if (Current.is(tok::r_square)) {
529 // If this ends the array subscript expr, reset the corresponding value.
530 const FormatToken *NextNonComment = Current.getNextNonComment();
531 if (NextNonComment && NextNonComment->isNot(tok::l_square))
532 State.Stack.back().StartOfArraySubscripts = 0;
533 }
534
535 // Remove scopes created by fake parenthesis.
536 for (unsigned i = 0, e = Current.FakeRParens; i != e; ++i) {
537 unsigned VariablePos = State.Stack.back().VariablePos;
538 State.Stack.pop_back();
539 State.Stack.back().VariablePos = VariablePos;
540 }
541
542 if (Current.is(tok::string_literal) && State.StartOfStringLiteral == 0) {
543 State.StartOfStringLiteral = State.Column;
544 } else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash,
545 tok::string_literal)) {
546 State.StartOfStringLiteral = 0;
547 }
548
549 State.Column += Current.CodePointCount;
550
551 State.NextToken = State.NextToken->Next;
552
Daniel Jasper8de9ed02013-08-22 15:00:41 +0000553 unsigned Penalty = 0;
554 if (Newline || !Style.AlwaysBreakBeforeMultilineStrings ||
555 Current.isNot(tok::string_literal) || !Current.CanBreakBefore)
556 Penalty += breakProtrudingToken(Current, State, DryRun);
Daniel Jasperde0328a2013-08-16 11:20:30 +0000557
Daniel Jasper8de9ed02013-08-22 15:00:41 +0000558 // If the previous has a special role, let it consume tokens as appropriate.
559 // It is necessary to start at the previous token for the only implemented
560 // role (comma separated list). That way, the decision whether or not to break
561 // after the "{" is already done and both options are tried and evaluated.
562 // FIXME: This is ugly, find a better way.
563 if (Previous && Previous->Role)
564 Penalty += Previous->Role->format(State, this, DryRun);
565
566 return Penalty;
Daniel Jasperde0328a2013-08-16 11:20:30 +0000567}
568
569unsigned ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
570 LineState &State,
571 bool DryRun) {
Daniel Jasperf93551c2013-08-23 10:05:49 +0000572 if (!Current.isOneOf(tok::string_literal, tok::comment))
573 return 0;
574
Daniel Jasperde0328a2013-08-16 11:20:30 +0000575 llvm::OwningPtr<BreakableToken> Token;
576 unsigned StartColumn = State.Column - Current.CodePointCount;
577 unsigned OriginalStartColumn =
578 SourceMgr.getSpellingColumnNumber(Current.getStartOfNonWhitespace()) - 1;
579
580 if (Current.is(tok::string_literal) &&
581 Current.Type != TT_ImplicitStringLiteral) {
582 // Only break up default narrow strings.
583 if (!Current.TokenText.startswith("\""))
584 return 0;
585 // Don't break string literals with escaped newlines. As clang-format must
586 // not change the string's content, it is unlikely that we'll end up with
587 // a better format.
588 if (Current.TokenText.find("\\\n") != StringRef::npos)
589 return 0;
590 // Exempts unterminated string literals from line breaking. The user will
591 // likely want to terminate the string before any line breaking is done.
592 if (Current.IsUnterminatedLiteral)
593 return 0;
594
595 Token.reset(new BreakableStringLiteral(Current, StartColumn,
596 Line.InPPDirective, Encoding));
597 } else if (Current.Type == TT_BlockComment && Current.isTrailingComment()) {
598 Token.reset(new BreakableBlockComment(
599 Style, Current, StartColumn, OriginalStartColumn, !Current.Previous,
600 Line.InPPDirective, Encoding));
601 } else if (Current.Type == TT_LineComment &&
602 (Current.Previous == NULL ||
603 Current.Previous->Type != TT_ImplicitStringLiteral)) {
604 // Don't break line comments with escaped newlines. These look like
605 // separate line comments, but in fact contain a single line comment with
606 // multiple lines including leading whitespace and the '//' markers.
607 //
608 // FIXME: If we want to handle them correctly, we'll need to adjust
609 // leading whitespace in consecutive lines when changing indentation of
610 // the first line similar to what we do with block comments.
611 StringRef::size_type EscapedNewlinePos = Current.TokenText.find("\\\n");
612 if (EscapedNewlinePos != StringRef::npos) {
613 State.Column =
614 StartColumn +
615 encoding::getCodePointCount(
616 Current.TokenText.substr(0, EscapedNewlinePos), Encoding) +
617 1;
618 return 0;
619 }
620
621 Token.reset(new BreakableLineComment(Current, StartColumn,
622 Line.InPPDirective, Encoding));
623 } else {
624 return 0;
625 }
626 if (Current.UnbreakableTailLength >= getColumnLimit())
627 return 0;
628
629 unsigned RemainingSpace = getColumnLimit() - Current.UnbreakableTailLength;
630 bool BreakInserted = false;
631 unsigned Penalty = 0;
632 unsigned RemainingTokenColumns = 0;
633 for (unsigned LineIndex = 0, EndIndex = Token->getLineCount();
634 LineIndex != EndIndex; ++LineIndex) {
635 if (!DryRun)
636 Token->replaceWhitespaceBefore(LineIndex, Whitespaces);
637 unsigned TailOffset = 0;
638 RemainingTokenColumns =
639 Token->getLineLengthAfterSplit(LineIndex, TailOffset, StringRef::npos);
640 while (RemainingTokenColumns > RemainingSpace) {
641 BreakableToken::Split Split =
642 Token->getSplit(LineIndex, TailOffset, getColumnLimit());
643 if (Split.first == StringRef::npos) {
644 // The last line's penalty is handled in addNextStateToQueue().
645 if (LineIndex < EndIndex - 1)
646 Penalty += Style.PenaltyExcessCharacter *
647 (RemainingTokenColumns - RemainingSpace);
648 break;
649 }
650 assert(Split.first != 0);
651 unsigned NewRemainingTokenColumns = Token->getLineLengthAfterSplit(
652 LineIndex, TailOffset + Split.first + Split.second, StringRef::npos);
653 assert(NewRemainingTokenColumns < RemainingTokenColumns);
654 if (!DryRun)
655 Token->insertBreak(LineIndex, TailOffset, Split, Whitespaces);
656 Penalty += Current.is(tok::string_literal) ? Style.PenaltyBreakString
657 : Style.PenaltyBreakComment;
658 unsigned ColumnsUsed =
659 Token->getLineLengthAfterSplit(LineIndex, TailOffset, Split.first);
660 if (ColumnsUsed > getColumnLimit()) {
661 Penalty +=
662 Style.PenaltyExcessCharacter * (ColumnsUsed - getColumnLimit());
663 }
664 TailOffset += Split.first + Split.second;
665 RemainingTokenColumns = NewRemainingTokenColumns;
666 BreakInserted = true;
667 }
668 }
669
670 State.Column = RemainingTokenColumns;
671
672 if (BreakInserted) {
673 // If we break the token inside a parameter list, we need to break before
674 // the next parameter on all levels, so that the next parameter is clearly
675 // visible. Line comments already introduce a break.
676 if (Current.Type != TT_LineComment) {
677 for (unsigned i = 0, e = State.Stack.size(); i != e; ++i)
678 State.Stack[i].BreakBeforeParameter = true;
679 }
680
681 State.Stack.back().LastSpace = StartColumn;
682 }
683 return Penalty;
684}
685
686unsigned ContinuationIndenter::getColumnLimit() const {
687 // In preprocessor directives reserve two chars for trailing " \"
688 return Style.ColumnLimit - (Line.InPPDirective ? 2 : 0);
689}
690
691} // namespace format
692} // namespace clang