blob: 14e0da0e697c7c461746c24815f17afab5065cc1 [file] [log] [blame]
Daniel Jasper6b2afe42013-08-16 11:20:30 +00001//===--- ContinuationIndenter.h - Format C++ code ---------------*- C++ -*-===//
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 an indenter that manages the indentation of
12/// continuations.
13///
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_CLANG_FORMAT_CONTINUATION_INDENTER_H
17#define LLVM_CLANG_FORMAT_CONTINUATION_INDENTER_H
18
19#include "Encoding.h"
20#include "clang/Format/Format.h"
21
22namespace clang {
23class SourceManager;
24
25namespace format {
26
27class AnnotatedLine;
28struct FormatToken;
29struct LineState;
30struct ParenState;
31class WhitespaceManager;
32
33class ContinuationIndenter {
34public:
35 /// \brief Constructs a \c ContinuationIndenter to format \p Line starting in
36 /// column \p FirstIndent.
37 ContinuationIndenter(const FormatStyle &Style, SourceManager &SourceMgr,
38 const AnnotatedLine &Line, unsigned FirstIndent,
39 WhitespaceManager &Whitespaces,
40 encoding::Encoding Encoding,
41 bool BinPackInconclusiveFunctions);
42
43 /// \brief Get the initial state, i.e. the state after placing the line's
44 /// first token.
45 LineState getInitialState();
46
47 // FIXME: canBreak and mustBreak aren't strictly indentation-related. Find a
48 // better home.
49 /// \brief Returns \c true, if a line break after \p State is allowed.
50 bool canBreak(const LineState &State);
51
52 /// \brief Returns \c true, if a line break after \p State is mandatory.
53 bool mustBreak(const LineState &State);
54
55 /// \brief Appends the next token to \p State and updates information
56 /// necessary for indentation.
57 ///
58 /// Puts the token on the current line if \p Newline is \c false and adds a
59 /// line break and necessary indentation otherwise.
60 ///
61 /// If \p DryRun is \c false, also creates and stores the required
62 /// \c Replacement.
63 unsigned addTokenToState(LineState &State, bool Newline, bool DryRun);
64
65 /// \brief Get the column limit for this line. This is the style's column
66 /// limit, potentially reduced for preprocessor definitions.
67 unsigned getColumnLimit() const;
68
69private:
70 /// \brief Mark the next token as consumed in \p State and modify its stacks
71 /// accordingly.
72 unsigned moveStateToNextToken(LineState &State, bool DryRun, bool Newline);
73
74 /// \brief If the current token sticks out over the end of the line, break
75 /// it if possible.
76 ///
77 /// \returns An extra penalty if a token was broken, otherwise 0.
78 ///
79 /// The returned penalty will cover the cost of the additional line breaks and
80 /// column limit violation in all lines except for the last one. The penalty
81 /// for the column limit violation in the last line (and in single line
82 /// tokens) is handled in \c addNextStateToQueue.
83 unsigned breakProtrudingToken(const FormatToken &Current, LineState &State,
84 bool DryRun);
85
86 FormatStyle Style;
87 SourceManager &SourceMgr;
88 const AnnotatedLine &Line;
89 const unsigned FirstIndent;
90 WhitespaceManager &Whitespaces;
91 encoding::Encoding Encoding;
92 bool BinPackInconclusiveFunctions;
93};
94
95struct ParenState {
96 ParenState(unsigned Indent, unsigned LastSpace, bool AvoidBinPacking,
97 bool NoLineBreak)
98 : Indent(Indent), LastSpace(LastSpace), FirstLessLess(0),
99 BreakBeforeClosingBrace(false), QuestionColumn(0),
100 AvoidBinPacking(AvoidBinPacking), BreakBeforeParameter(false),
101 NoLineBreak(NoLineBreak), ColonPos(0), StartOfFunctionCall(0),
102 StartOfArraySubscripts(0), NestedNameSpecifierContinuation(0),
103 CallContinuation(0), VariablePos(0), ContainsLineBreak(false) {}
104
105 /// \brief The position to which a specific parenthesis level needs to be
106 /// indented.
107 unsigned Indent;
108
109 /// \brief The position of the last space on each level.
110 ///
111 /// Used e.g. to break like:
112 /// functionCall(Parameter, otherCall(
113 /// OtherParameter));
114 unsigned LastSpace;
115
116 /// \brief The position the first "<<" operator encountered on each level.
117 ///
118 /// Used to align "<<" operators. 0 if no such operator has been encountered
119 /// on a level.
120 unsigned FirstLessLess;
121
122 /// \brief Whether a newline needs to be inserted before the block's closing
123 /// brace.
124 ///
125 /// We only want to insert a newline before the closing brace if there also
126 /// was a newline after the beginning left brace.
127 bool BreakBeforeClosingBrace;
128
129 /// \brief The column of a \c ? in a conditional expression;
130 unsigned QuestionColumn;
131
132 /// \brief Avoid bin packing, i.e. multiple parameters/elements on multiple
133 /// lines, in this context.
134 bool AvoidBinPacking;
135
136 /// \brief Break after the next comma (or all the commas in this context if
137 /// \c AvoidBinPacking is \c true).
138 bool BreakBeforeParameter;
139
140 /// \brief Line breaking in this context would break a formatting rule.
141 bool NoLineBreak;
142
143 /// \brief The position of the colon in an ObjC method declaration/call.
144 unsigned ColonPos;
145
146 /// \brief The start of the most recent function in a builder-type call.
147 unsigned StartOfFunctionCall;
148
149 /// \brief Contains the start of array subscript expressions, so that they
150 /// can be aligned.
151 unsigned StartOfArraySubscripts;
152
153 /// \brief If a nested name specifier was broken over multiple lines, this
154 /// contains the start column of the second line. Otherwise 0.
155 unsigned NestedNameSpecifierContinuation;
156
157 /// \brief If a call expression was broken over multiple lines, this
158 /// contains the start column of the second line. Otherwise 0.
159 unsigned CallContinuation;
160
161 /// \brief The column of the first variable name in a variable declaration.
162 ///
163 /// Used to align further variables if necessary.
164 unsigned VariablePos;
165
166 /// \brief \c true if this \c ParenState already contains a line-break.
167 ///
168 /// The first line break in a certain \c ParenState causes extra penalty so
169 /// that clang-format prefers similar breaks, i.e. breaks in the same
170 /// parenthesis.
171 bool ContainsLineBreak;
172
173 bool operator<(const ParenState &Other) const {
174 if (Indent != Other.Indent)
175 return Indent < Other.Indent;
176 if (LastSpace != Other.LastSpace)
177 return LastSpace < Other.LastSpace;
178 if (FirstLessLess != Other.FirstLessLess)
179 return FirstLessLess < Other.FirstLessLess;
180 if (BreakBeforeClosingBrace != Other.BreakBeforeClosingBrace)
181 return BreakBeforeClosingBrace;
182 if (QuestionColumn != Other.QuestionColumn)
183 return QuestionColumn < Other.QuestionColumn;
184 if (AvoidBinPacking != Other.AvoidBinPacking)
185 return AvoidBinPacking;
186 if (BreakBeforeParameter != Other.BreakBeforeParameter)
187 return BreakBeforeParameter;
188 if (NoLineBreak != Other.NoLineBreak)
189 return NoLineBreak;
190 if (ColonPos != Other.ColonPos)
191 return ColonPos < Other.ColonPos;
192 if (StartOfFunctionCall != Other.StartOfFunctionCall)
193 return StartOfFunctionCall < Other.StartOfFunctionCall;
194 if (StartOfArraySubscripts != Other.StartOfArraySubscripts)
195 return StartOfArraySubscripts < Other.StartOfArraySubscripts;
196 if (CallContinuation != Other.CallContinuation)
197 return CallContinuation < Other.CallContinuation;
198 if (VariablePos != Other.VariablePos)
199 return VariablePos < Other.VariablePos;
200 if (ContainsLineBreak != Other.ContainsLineBreak)
201 return ContainsLineBreak < Other.ContainsLineBreak;
202 return false;
203 }
204};
205
206/// \brief The current state when indenting a unwrapped line.
207///
208/// As the indenting tries different combinations this is copied by value.
209struct LineState {
210 /// \brief The number of used columns in the current line.
211 unsigned Column;
212
213 /// \brief The token that needs to be next formatted.
214 const FormatToken *NextToken;
215
216 /// \brief \c true if this line contains a continued for-loop section.
217 bool LineContainsContinuedForLoopSection;
218
219 /// \brief The level of nesting inside (), [], <> and {}.
220 unsigned ParenLevel;
221
222 /// \brief The \c ParenLevel at the start of this line.
223 unsigned StartOfLineLevel;
224
225 /// \brief The lowest \c ParenLevel on the current line.
226 unsigned LowestLevelOnLine;
227
228 /// \brief The start column of the string literal, if we're in a string
229 /// literal sequence, 0 otherwise.
230 unsigned StartOfStringLiteral;
231
232 /// \brief A stack keeping track of properties applying to parenthesis
233 /// levels.
234 std::vector<ParenState> Stack;
235
236 /// \brief Ignore the stack of \c ParenStates for state comparison.
237 ///
238 /// In long and deeply nested unwrapped lines, the current algorithm can
239 /// be insufficient for finding the best formatting with a reasonable amount
240 /// of time and memory. Setting this flag will effectively lead to the
241 /// algorithm not analyzing some combinations. However, these combinations
242 /// rarely contain the optimal solution: In short, accepting a higher
243 /// penalty early would need to lead to different values in the \c
244 /// ParenState stack (in an otherwise identical state) and these different
245 /// values would need to lead to a significant amount of avoided penalty
246 /// later.
247 ///
248 /// FIXME: Come up with a better algorithm instead.
249 bool IgnoreStackForComparison;
250
251 /// \brief Comparison operator to be able to used \c LineState in \c map.
252 bool operator<(const LineState &Other) const {
253 if (NextToken != Other.NextToken)
254 return NextToken < Other.NextToken;
255 if (Column != Other.Column)
256 return Column < Other.Column;
257 if (LineContainsContinuedForLoopSection !=
258 Other.LineContainsContinuedForLoopSection)
259 return LineContainsContinuedForLoopSection;
260 if (ParenLevel != Other.ParenLevel)
261 return ParenLevel < Other.ParenLevel;
262 if (StartOfLineLevel != Other.StartOfLineLevel)
263 return StartOfLineLevel < Other.StartOfLineLevel;
264 if (LowestLevelOnLine != Other.LowestLevelOnLine)
265 return LowestLevelOnLine < Other.LowestLevelOnLine;
266 if (StartOfStringLiteral != Other.StartOfStringLiteral)
267 return StartOfStringLiteral < Other.StartOfStringLiteral;
268 if (IgnoreStackForComparison || Other.IgnoreStackForComparison)
269 return false;
270 return Stack < Other.Stack;
271 }
272};
273
274} // end namespace format
275} // end namespace clang
276
277#endif // LLVM_CLANG_FORMAT_CONTINUATION_INDENTER_H