blob: 8f77c77a8ecbad5e3ecc1d9de8b9265c3f05b780 [file] [log] [blame]
Daniel Jasperbac016b2012-12-03 18:12:45 +00001//===--- Format.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 functions declared in Format.h. This will be
12/// split into separate files as we go.
13///
14/// This is EXPERIMENTAL code under heavy development. It is not in a state yet,
15/// where it can be used to format real code.
16///
17//===----------------------------------------------------------------------===//
18
19#include "clang/Format/Format.h"
Chandler Carruth55fc8732012-12-04 09:13:33 +000020#include "UnwrappedLineParser.h"
Daniel Jasper675d2e32012-12-21 10:20:02 +000021#include "clang/Basic/OperatorPrecedence.h"
Chandler Carruthb99083e2013-01-02 10:28:36 +000022#include "clang/Basic/SourceManager.h"
Daniel Jasperbac016b2012-12-03 18:12:45 +000023#include "clang/Lex/Lexer.h"
Daniel Jasper8822d3a2012-12-04 13:02:32 +000024#include <string>
25
Daniel Jasperbac016b2012-12-03 18:12:45 +000026namespace clang {
27namespace format {
28
29// FIXME: Move somewhere sane.
30struct TokenAnnotation {
Daniel Jasper33182dd2012-12-05 14:57:28 +000031 enum TokenType {
32 TT_Unknown,
33 TT_TemplateOpener,
34 TT_TemplateCloser,
35 TT_BinaryOperator,
36 TT_UnaryOperator,
Daniel Jasper98e6b4a2012-12-21 09:41:31 +000037 TT_TrailingUnaryOperator,
Daniel Jasper33182dd2012-12-05 14:57:28 +000038 TT_OverloadedOperator,
39 TT_PointerOrReference,
40 TT_ConditionalExpr,
Daniel Jasper1321eb52012-12-18 21:05:13 +000041 TT_CtorInitializerColon,
Daniel Jasper33182dd2012-12-05 14:57:28 +000042 TT_LineComment,
Fariborz Jahanian154120c2012-12-20 19:54:13 +000043 TT_BlockComment,
Daniel Jaspercd1a32b2012-12-21 17:58:39 +000044 TT_DirectorySeparator,
Fariborz Jahanian154120c2012-12-20 19:54:13 +000045 TT_ObjCMethodSpecifier
Daniel Jasper33182dd2012-12-05 14:57:28 +000046 };
Daniel Jasperbac016b2012-12-03 18:12:45 +000047
48 TokenType Type;
49
Daniel Jasperbac016b2012-12-03 18:12:45 +000050 bool SpaceRequiredBefore;
51 bool CanBreakBefore;
52 bool MustBreakBefore;
53};
54
Daniel Jaspercf225b62012-12-24 13:43:52 +000055static prec::Level getPrecedence(const FormatToken &Tok) {
56 return getBinOpPrecedence(Tok.Tok.getKind(), true, true);
57}
58
Daniel Jasperbac016b2012-12-03 18:12:45 +000059using llvm::MutableArrayRef;
60
61FormatStyle getLLVMStyle() {
62 FormatStyle LLVMStyle;
63 LLVMStyle.ColumnLimit = 80;
64 LLVMStyle.MaxEmptyLinesToKeep = 1;
65 LLVMStyle.PointerAndReferenceBindToType = false;
66 LLVMStyle.AccessModifierOffset = -2;
67 LLVMStyle.SplitTemplateClosingGreater = true;
Alexander Kornienko15757312012-12-06 18:03:27 +000068 LLVMStyle.IndentCaseLabels = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +000069 return LLVMStyle;
70}
71
72FormatStyle getGoogleStyle() {
73 FormatStyle GoogleStyle;
74 GoogleStyle.ColumnLimit = 80;
75 GoogleStyle.MaxEmptyLinesToKeep = 1;
76 GoogleStyle.PointerAndReferenceBindToType = true;
77 GoogleStyle.AccessModifierOffset = -1;
78 GoogleStyle.SplitTemplateClosingGreater = false;
Alexander Kornienko15757312012-12-06 18:03:27 +000079 GoogleStyle.IndentCaseLabels = true;
Daniel Jasperbac016b2012-12-03 18:12:45 +000080 return GoogleStyle;
81}
82
83struct OptimizationParameters {
Daniel Jasperbac016b2012-12-03 18:12:45 +000084 unsigned PenaltyIndentLevel;
Daniel Jaspera4974cf2012-12-24 16:43:00 +000085 unsigned PenaltyLevelDecrease;
Daniel Jasperbac016b2012-12-03 18:12:45 +000086};
87
88class UnwrappedLineFormatter {
89public:
90 UnwrappedLineFormatter(const FormatStyle &Style, SourceManager &SourceMgr,
91 const UnwrappedLine &Line,
92 const std::vector<TokenAnnotation> &Annotations,
Alexander Kornienkocff563c2012-12-04 17:27:50 +000093 tooling::Replacements &Replaces, bool StructuralError)
Daniel Jasper1321eb52012-12-18 21:05:13 +000094 : Style(Style), SourceMgr(SourceMgr), Line(Line),
95 Annotations(Annotations), Replaces(Replaces),
Alexander Kornienkocff563c2012-12-04 17:27:50 +000096 StructuralError(StructuralError) {
Daniel Jaspere2c7acf2012-12-24 00:13:23 +000097 Parameters.PenaltyIndentLevel = 15;
Daniel Jaspera4974cf2012-12-24 16:43:00 +000098 Parameters.PenaltyLevelDecrease = 10;
Daniel Jasperbac016b2012-12-03 18:12:45 +000099 }
100
101 void format() {
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000102 // Format first token and initialize indent.
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000103 unsigned Indent = formatFirstToken();
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000104
105 // Initialize state dependent on indent.
Daniel Jasperbac016b2012-12-03 18:12:45 +0000106 IndentState State;
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000107 State.Column = Indent;
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000108 State.ConsumedTokens = 0;
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000109 State.Indent.push_back(Indent + 4);
110 State.LastSpace.push_back(Indent);
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000111 State.FirstLessLess.push_back(0);
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000112 State.ForLoopVariablePos = 0;
113 State.LineContainsContinuedForLoopSection = false;
Daniel Jaspera4974cf2012-12-24 16:43:00 +0000114 State.StartOfLineLevel = 1;
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000115
116 // The first token has already been indented and thus consumed.
117 moveStateToNextToken(State);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000118
Daniel Jasper1321eb52012-12-18 21:05:13 +0000119 // Check whether the UnwrappedLine can be put onto a single line. If so,
120 // this is bound to be the optimal solution (by definition) and we don't
121 // need to analyze the entire solution space.
122 unsigned Columns = State.Column;
123 bool FitsOnALine = true;
124 for (unsigned i = 1, n = Line.Tokens.size(); i != n; ++i) {
125 Columns += (Annotations[i].SpaceRequiredBefore ? 1 : 0) +
Daniel Jasperd7610b82012-12-24 16:51:15 +0000126 Line.Tokens[i].Tok.getLength();
Daniel Jasper1321eb52012-12-18 21:05:13 +0000127 // A special case for the colon of a constructor initializer as this only
128 // needs to be put on a new line if the line needs to be split.
129 if (Columns > Style.ColumnLimit ||
130 (Annotations[i].MustBreakBefore &&
131 Annotations[i].Type != TokenAnnotation::TT_CtorInitializerColon)) {
132 FitsOnALine = false;
133 break;
134 }
135 }
136
Daniel Jasperbac016b2012-12-03 18:12:45 +0000137 // Start iterating at 1 as we have correctly formatted of Token #0 above.
138 for (unsigned i = 1, n = Line.Tokens.size(); i != n; ++i) {
Daniel Jasper1321eb52012-12-18 21:05:13 +0000139 if (FitsOnALine) {
140 addTokenToState(false, false, State);
141 } else {
142 unsigned NoBreak = calcPenalty(State, false, UINT_MAX);
143 unsigned Break = calcPenalty(State, true, NoBreak);
144 addTokenToState(Break < NoBreak, false, State);
145 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000146 }
147 }
148
149private:
150 /// \brief The current state when indenting a unwrapped line.
151 ///
152 /// As the indenting tries different combinations this is copied by value.
153 struct IndentState {
154 /// \brief The number of used columns in the current line.
155 unsigned Column;
156
157 /// \brief The number of tokens already consumed.
158 unsigned ConsumedTokens;
159
Daniel Jaspera4974cf2012-12-24 16:43:00 +0000160 /// \brief The parenthesis level of the first token on the current line.
161 unsigned StartOfLineLevel;
162
Daniel Jasperbac016b2012-12-03 18:12:45 +0000163 /// \brief The position to which a specific parenthesis level needs to be
164 /// indented.
165 std::vector<unsigned> Indent;
166
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000167 /// \brief The position of the last space on each level.
168 ///
169 /// Used e.g. to break like:
170 /// functionCall(Parameter, otherCall(
171 /// OtherParameter));
Daniel Jasperbac016b2012-12-03 18:12:45 +0000172 std::vector<unsigned> LastSpace;
173
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000174 /// \brief The position the first "<<" operator encountered on each level.
175 ///
176 /// Used to align "<<" operators. 0 if no such operator has been encountered
177 /// on a level.
178 std::vector<unsigned> FirstLessLess;
179
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000180 /// \brief The column of the first variable in a for-loop declaration.
181 ///
182 /// Used to align the second variable if necessary.
183 unsigned ForLoopVariablePos;
184
185 /// \brief \c true if this line contains a continued for-loop section.
186 bool LineContainsContinuedForLoopSection;
187
Daniel Jasperbac016b2012-12-03 18:12:45 +0000188 /// \brief Comparison operator to be able to used \c IndentState in \c map.
189 bool operator<(const IndentState &Other) const {
190 if (Other.ConsumedTokens != ConsumedTokens)
191 return Other.ConsumedTokens > ConsumedTokens;
192 if (Other.Column != Column)
193 return Other.Column > Column;
Daniel Jaspera4974cf2012-12-24 16:43:00 +0000194 if (Other.StartOfLineLevel != StartOfLineLevel)
195 return Other.StartOfLineLevel > StartOfLineLevel;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000196 if (Other.Indent.size() != Indent.size())
197 return Other.Indent.size() > Indent.size();
198 for (int i = 0, e = Indent.size(); i != e; ++i) {
199 if (Other.Indent[i] != Indent[i])
200 return Other.Indent[i] > Indent[i];
201 }
202 if (Other.LastSpace.size() != LastSpace.size())
203 return Other.LastSpace.size() > LastSpace.size();
204 for (int i = 0, e = LastSpace.size(); i != e; ++i) {
205 if (Other.LastSpace[i] != LastSpace[i])
206 return Other.LastSpace[i] > LastSpace[i];
207 }
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000208 if (Other.FirstLessLess.size() != FirstLessLess.size())
209 return Other.FirstLessLess.size() > FirstLessLess.size();
210 for (int i = 0, e = FirstLessLess.size(); i != e; ++i) {
211 if (Other.FirstLessLess[i] != FirstLessLess[i])
212 return Other.FirstLessLess[i] > FirstLessLess[i];
213 }
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000214 if (Other.ForLoopVariablePos != ForLoopVariablePos)
215 return Other.ForLoopVariablePos < ForLoopVariablePos;
216 if (Other.LineContainsContinuedForLoopSection !=
217 LineContainsContinuedForLoopSection)
218 return LineContainsContinuedForLoopSection;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000219 return false;
220 }
221 };
222
Daniel Jasper20409152012-12-04 14:54:30 +0000223 /// \brief Appends the next token to \p State and updates information
224 /// necessary for indentation.
225 ///
226 /// Puts the token on the current line if \p Newline is \c true and adds a
227 /// line break and necessary indentation otherwise.
228 ///
229 /// If \p DryRun is \c false, also creates and stores the required
230 /// \c Replacement.
231 void addTokenToState(bool Newline, bool DryRun, IndentState &State) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000232 unsigned Index = State.ConsumedTokens;
233 const FormatToken &Current = Line.Tokens[Index];
234 const FormatToken &Previous = Line.Tokens[Index - 1];
Daniel Jasper20409152012-12-04 14:54:30 +0000235 unsigned ParenLevel = State.Indent.size() - 1;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000236
237 if (Newline) {
238 if (Current.Tok.is(tok::string_literal) &&
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000239 Previous.Tok.is(tok::string_literal)) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000240 State.Column = State.Column - Previous.Tok.getLength();
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000241 } else if (Current.Tok.is(tok::lessless) &&
242 State.FirstLessLess[ParenLevel] != 0) {
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000243 State.Column = State.FirstLessLess[ParenLevel];
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000244 } else if (ParenLevel != 0 &&
245 (Previous.Tok.is(tok::equal) || Current.Tok.is(tok::arrow) ||
246 Current.Tok.is(tok::period))) {
Daniel Jasper20409152012-12-04 14:54:30 +0000247 // Indent and extra 4 spaces after '=' as it continues an expression.
248 // Don't do that on the top level, as we already indent 4 there.
Daniel Jasperbac016b2012-12-03 18:12:45 +0000249 State.Column = State.Indent[ParenLevel] + 4;
Daniel Jasperd7610b82012-12-24 16:51:15 +0000250 } else if (
251 Line.Tokens[0].Tok.is(tok::kw_for) && Previous.Tok.is(tok::comma)) {
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000252 State.Column = State.ForLoopVariablePos;
253 } else {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000254 State.Column = State.Indent[ParenLevel];
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000255 }
256
Daniel Jaspera4974cf2012-12-24 16:43:00 +0000257 State.StartOfLineLevel = ParenLevel + 1;
258
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000259 if (Line.Tokens[0].Tok.is(tok::kw_for))
260 State.LineContainsContinuedForLoopSection =
261 Previous.Tok.isNot(tok::semi);
Daniel Jasper20409152012-12-04 14:54:30 +0000262
Daniel Jasperbac016b2012-12-03 18:12:45 +0000263 if (!DryRun)
264 replaceWhitespace(Current, 1, State.Column);
265
Daniel Jaspera88bb452012-12-04 10:50:12 +0000266 State.LastSpace[ParenLevel] = State.Indent[ParenLevel];
Daniel Jasperbac016b2012-12-03 18:12:45 +0000267 if (Current.Tok.is(tok::colon) &&
Fariborz Jahanian154120c2012-12-20 19:54:13 +0000268 Annotations[Index].Type != TokenAnnotation::TT_ConditionalExpr &&
269 Annotations[0].Type != TokenAnnotation::TT_ObjCMethodSpecifier)
Daniel Jasperbac016b2012-12-03 18:12:45 +0000270 State.Indent[ParenLevel] += 2;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000271 } else {
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000272 if (Current.Tok.is(tok::equal) && Line.Tokens[0].Tok.is(tok::kw_for))
273 State.ForLoopVariablePos = State.Column - Previous.Tok.getLength();
274
Daniel Jasperbac016b2012-12-03 18:12:45 +0000275 unsigned Spaces = Annotations[Index].SpaceRequiredBefore ? 1 : 0;
276 if (Annotations[Index].Type == TokenAnnotation::TT_LineComment)
277 Spaces = 2;
Daniel Jasper20409152012-12-04 14:54:30 +0000278
Daniel Jasperbac016b2012-12-03 18:12:45 +0000279 if (!DryRun)
280 replaceWhitespace(Current, 0, Spaces);
Daniel Jasper20409152012-12-04 14:54:30 +0000281
Daniel Jaspercf225b62012-12-24 13:43:52 +0000282 // FIXME: Look into using this alignment at other ParenLevels.
283 if (ParenLevel == 0 && (getPrecedence(Previous) == prec::Assignment ||
284 Previous.Tok.is(tok::kw_return)))
285 State.Indent[ParenLevel] = State.Column + Spaces;
Daniel Jasper20409152012-12-04 14:54:30 +0000286 if (Previous.Tok.is(tok::l_paren) ||
287 Annotations[Index - 1].Type == TokenAnnotation::TT_TemplateOpener)
Daniel Jasperbac016b2012-12-03 18:12:45 +0000288 State.Indent[ParenLevel] = State.Column;
Daniel Jasper1321eb52012-12-18 21:05:13 +0000289
Daniel Jasperbac016b2012-12-03 18:12:45 +0000290 // Top-level spaces are exempt as that mostly leads to better results.
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000291 State.Column += Spaces;
Daniel Jaspera88bb452012-12-04 10:50:12 +0000292 if (Spaces > 0 && ParenLevel != 0)
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000293 State.LastSpace[ParenLevel] = State.Column;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000294 }
Daniel Jasper20409152012-12-04 14:54:30 +0000295 moveStateToNextToken(State);
296 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000297
Daniel Jasper20409152012-12-04 14:54:30 +0000298 /// \brief Mark the next token as consumed in \p State and modify its stacks
299 /// accordingly.
300 void moveStateToNextToken(IndentState &State) {
301 unsigned Index = State.ConsumedTokens;
302 const FormatToken &Current = Line.Tokens[Index];
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000303 unsigned ParenLevel = State.Indent.size() - 1;
304
305 if (Current.Tok.is(tok::lessless) && State.FirstLessLess[ParenLevel] == 0)
306 State.FirstLessLess[ParenLevel] = State.Column;
307
308 State.Column += Current.Tok.getLength();
Daniel Jasper20409152012-12-04 14:54:30 +0000309
Daniel Jaspercf225b62012-12-24 13:43:52 +0000310 // If we encounter an opening (, [, { or <, we add a level to our stacks to
Daniel Jasper20409152012-12-04 14:54:30 +0000311 // prepare for the following tokens.
312 if (Current.Tok.is(tok::l_paren) || Current.Tok.is(tok::l_square) ||
Daniel Jaspercf225b62012-12-24 13:43:52 +0000313 Current.Tok.is(tok::l_brace) ||
Daniel Jasper20409152012-12-04 14:54:30 +0000314 Annotations[Index].Type == TokenAnnotation::TT_TemplateOpener) {
315 State.Indent.push_back(4 + State.LastSpace.back());
316 State.LastSpace.push_back(State.LastSpace.back());
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000317 State.FirstLessLess.push_back(0);
Daniel Jasper20409152012-12-04 14:54:30 +0000318 }
319
Daniel Jaspercf225b62012-12-24 13:43:52 +0000320 // If we encounter a closing ), ], } or >, we can remove a level from our
Daniel Jasper20409152012-12-04 14:54:30 +0000321 // stacks.
Daniel Jaspera88bb452012-12-04 10:50:12 +0000322 if (Current.Tok.is(tok::r_paren) || Current.Tok.is(tok::r_square) ||
Daniel Jaspercf225b62012-12-24 13:43:52 +0000323 (Current.Tok.is(tok::r_brace) && State.ConsumedTokens > 0) ||
Daniel Jaspera88bb452012-12-04 10:50:12 +0000324 Annotations[Index].Type == TokenAnnotation::TT_TemplateCloser) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000325 State.Indent.pop_back();
326 State.LastSpace.pop_back();
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000327 State.FirstLessLess.pop_back();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000328 }
329
330 ++State.ConsumedTokens;
331 }
332
Daniel Jasper9a0b4942012-12-17 14:34:14 +0000333 /// \brief Calculate the panelty for splitting after the token at \p Index.
334 unsigned splitPenalty(unsigned Index) {
335 assert(Index < Line.Tokens.size() &&
336 "Tried to calculate penalty for splitting after the last token");
337 const FormatToken &Left = Line.Tokens[Index];
338 const FormatToken &Right = Line.Tokens[Index + 1];
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000339
340 // In for-loops, prefer breaking at ',' and ';'.
341 if (Line.Tokens[0].Tok.is(tok::kw_for) &&
342 (Left.Tok.isNot(tok::comma) && Left.Tok.isNot(tok::semi)))
343 return 20;
344
Daniel Jasper1321eb52012-12-18 21:05:13 +0000345 if (Left.Tok.is(tok::semi) || Left.Tok.is(tok::comma))
Daniel Jasperbac016b2012-12-03 18:12:45 +0000346 return 0;
Daniel Jaspere2c7acf2012-12-24 00:13:23 +0000347 if (Left.Tok.is(tok::l_paren))
Daniel Jasper723f0302013-01-02 14:40:02 +0000348 return 20;
Daniel Jasper9a0b4942012-12-17 14:34:14 +0000349
Daniel Jaspercf225b62012-12-24 13:43:52 +0000350 prec::Level Level = getPrecedence(Line.Tokens[Index]);
Daniel Jaspere2c7acf2012-12-24 00:13:23 +0000351 if (Level != prec::Unknown)
352 return Level;
353
Daniel Jasper9a0b4942012-12-17 14:34:14 +0000354 if (Right.Tok.is(tok::arrow) || Right.Tok.is(tok::period))
Daniel Jaspera4974cf2012-12-24 16:43:00 +0000355 return 50;
Daniel Jasper9a0b4942012-12-17 14:34:14 +0000356
Daniel Jasperbac016b2012-12-03 18:12:45 +0000357 return 3;
358 }
359
360 /// \brief Calculate the number of lines needed to format the remaining part
361 /// of the unwrapped line.
362 ///
363 /// Assumes the formatting so far has led to
364 /// the \c IndentState \p State. If \p NewLine is set, a new line will be
365 /// added after the previous token.
366 ///
367 /// \param StopAt is used for optimization. If we can determine that we'll
368 /// definitely need at least \p StopAt additional lines, we already know of a
369 /// better solution.
370 unsigned calcPenalty(IndentState State, bool NewLine, unsigned StopAt) {
371 // We are at the end of the unwrapped line, so we don't need any more lines.
372 if (State.ConsumedTokens >= Line.Tokens.size())
373 return 0;
374
375 if (!NewLine && Annotations[State.ConsumedTokens].MustBreakBefore)
376 return UINT_MAX;
377 if (NewLine && !Annotations[State.ConsumedTokens].CanBreakBefore)
378 return UINT_MAX;
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000379 if (!NewLine && Line.Tokens[State.ConsumedTokens - 1].Tok.is(tok::semi) &&
380 State.LineContainsContinuedForLoopSection)
381 return UINT_MAX;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000382
Daniel Jasper33182dd2012-12-05 14:57:28 +0000383 unsigned CurrentPenalty = 0;
384 if (NewLine) {
385 CurrentPenalty += Parameters.PenaltyIndentLevel * State.Indent.size() +
Daniel Jasperd7610b82012-12-24 16:51:15 +0000386 splitPenalty(State.ConsumedTokens - 1);
Daniel Jaspera4974cf2012-12-24 16:43:00 +0000387 } else {
388 if (State.Indent.size() < State.StartOfLineLevel)
389 CurrentPenalty += Parameters.PenaltyLevelDecrease *
390 (State.StartOfLineLevel - State.Indent.size());
Daniel Jasper33182dd2012-12-05 14:57:28 +0000391 }
392
Daniel Jasper20409152012-12-04 14:54:30 +0000393 addTokenToState(NewLine, true, State);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000394
395 // Exceeding column limit is bad.
396 if (State.Column > Style.ColumnLimit)
397 return UINT_MAX;
398
Daniel Jasperbac016b2012-12-03 18:12:45 +0000399 if (StopAt <= CurrentPenalty)
400 return UINT_MAX;
401 StopAt -= CurrentPenalty;
402
Daniel Jasperbac016b2012-12-03 18:12:45 +0000403 StateMap::iterator I = Memory.find(State);
Daniel Jasper33182dd2012-12-05 14:57:28 +0000404 if (I != Memory.end()) {
405 // If this state has already been examined, we can safely return the
406 // previous result if we
407 // - have not hit the optimatization (and thus returned UINT_MAX) OR
408 // - are now computing for a smaller or equal StopAt.
409 unsigned SavedResult = I->second.first;
410 unsigned SavedStopAt = I->second.second;
Daniel Jasper9a0b4942012-12-17 14:34:14 +0000411 if (SavedResult != UINT_MAX)
412 return SavedResult + CurrentPenalty;
413 else if (StopAt <= SavedStopAt)
414 return UINT_MAX;
Daniel Jasper33182dd2012-12-05 14:57:28 +0000415 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000416
417 unsigned NoBreak = calcPenalty(State, false, StopAt);
418 unsigned WithBreak = calcPenalty(State, true, std::min(StopAt, NoBreak));
419 unsigned Result = std::min(NoBreak, WithBreak);
Daniel Jasper9a0b4942012-12-17 14:34:14 +0000420
421 // We have to store 'Result' without adding 'CurrentPenalty' as the latter
422 // can depend on 'NewLine'.
Daniel Jasper33182dd2012-12-05 14:57:28 +0000423 Memory[State] = std::pair<unsigned, unsigned>(Result, StopAt);
Daniel Jasper9a0b4942012-12-17 14:34:14 +0000424
425 return Result == UINT_MAX ? UINT_MAX : Result + CurrentPenalty;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000426 }
427
428 /// \brief Replaces the whitespace in front of \p Tok. Only call once for
429 /// each \c FormatToken.
430 void replaceWhitespace(const FormatToken &Tok, unsigned NewLines,
431 unsigned Spaces) {
432 Replaces.insert(tooling::Replacement(
433 SourceMgr, Tok.WhiteSpaceStart, Tok.WhiteSpaceLength,
434 std::string(NewLines, '\n') + std::string(Spaces, ' ')));
435 }
436
437 /// \brief Add a new line and the required indent before the first Token
Alexander Kornienko720ffb62012-12-05 13:56:52 +0000438 /// of the \c UnwrappedLine if there was no structural parsing error.
439 /// Returns the indent level of the \c UnwrappedLine.
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000440 unsigned formatFirstToken() {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000441 const FormatToken &Token = Line.Tokens[0];
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000442 if (!Token.WhiteSpaceStart.isValid() || StructuralError)
443 return SourceMgr.getSpellingColumnNumber(Token.Tok.getLocation()) - 1;
444
445 unsigned Newlines =
446 std::min(Token.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
447 unsigned Offset = SourceMgr.getFileOffset(Token.WhiteSpaceStart);
448 if (Newlines == 0 && Offset != 0)
449 Newlines = 1;
450 unsigned Indent = Line.Level * 2;
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000451 if ((Token.Tok.is(tok::kw_public) || Token.Tok.is(tok::kw_protected) ||
452 Token.Tok.is(tok::kw_private)) &&
453 static_cast<int>(Indent) + Style.AccessModifierOffset >= 0)
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000454 Indent += Style.AccessModifierOffset;
455 replaceWhitespace(Token, Newlines, Indent);
456 return Indent;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000457 }
458
459 FormatStyle Style;
460 SourceManager &SourceMgr;
461 const UnwrappedLine &Line;
462 const std::vector<TokenAnnotation> &Annotations;
463 tooling::Replacements &Replaces;
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000464 bool StructuralError;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000465
Daniel Jasper33182dd2012-12-05 14:57:28 +0000466 // A map from an indent state to a pair (Result, Used-StopAt).
467 typedef std::map<IndentState, std::pair<unsigned, unsigned> > StateMap;
468 StateMap Memory;
469
Daniel Jasperbac016b2012-12-03 18:12:45 +0000470 OptimizationParameters Parameters;
471};
472
473/// \brief Determines extra information about the tokens comprising an
474/// \c UnwrappedLine.
475class TokenAnnotator {
476public:
477 TokenAnnotator(const UnwrappedLine &Line, const FormatStyle &Style,
478 SourceManager &SourceMgr)
Daniel Jasper1321eb52012-12-18 21:05:13 +0000479 : Line(Line), Style(Style), SourceMgr(SourceMgr) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000480 }
481
482 /// \brief A parser that gathers additional information about tokens.
483 ///
484 /// The \c TokenAnnotator tries to matches parenthesis and square brakets and
485 /// store a parenthesis levels. It also tries to resolve matching "<" and ">"
486 /// into template parameter lists.
487 class AnnotatingParser {
488 public:
Manuel Klimek0be4b362012-12-03 20:55:42 +0000489 AnnotatingParser(const SmallVector<FormatToken, 16> &Tokens,
Daniel Jasperbac016b2012-12-03 18:12:45 +0000490 std::vector<TokenAnnotation> &Annotations)
Daniel Jasper1321eb52012-12-18 21:05:13 +0000491 : Tokens(Tokens), Annotations(Annotations), Index(0) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000492 }
493
Daniel Jasper20409152012-12-04 14:54:30 +0000494 bool parseAngle() {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000495 while (Index < Tokens.size()) {
496 if (Tokens[Index].Tok.is(tok::greater)) {
Daniel Jaspera88bb452012-12-04 10:50:12 +0000497 Annotations[Index].Type = TokenAnnotation::TT_TemplateCloser;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000498 next();
499 return true;
500 }
501 if (Tokens[Index].Tok.is(tok::r_paren) ||
502 Tokens[Index].Tok.is(tok::r_square))
503 return false;
504 if (Tokens[Index].Tok.is(tok::pipepipe) ||
505 Tokens[Index].Tok.is(tok::ampamp) ||
506 Tokens[Index].Tok.is(tok::question) ||
507 Tokens[Index].Tok.is(tok::colon))
508 return false;
Daniel Jasper20409152012-12-04 14:54:30 +0000509 consumeToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000510 }
511 return false;
512 }
513
Daniel Jasper20409152012-12-04 14:54:30 +0000514 bool parseParens() {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000515 while (Index < Tokens.size()) {
516 if (Tokens[Index].Tok.is(tok::r_paren)) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000517 next();
518 return true;
519 }
520 if (Tokens[Index].Tok.is(tok::r_square))
521 return false;
Daniel Jasper20409152012-12-04 14:54:30 +0000522 consumeToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000523 }
524 return false;
525 }
526
Daniel Jasper20409152012-12-04 14:54:30 +0000527 bool parseSquare() {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000528 while (Index < Tokens.size()) {
529 if (Tokens[Index].Tok.is(tok::r_square)) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000530 next();
531 return true;
532 }
533 if (Tokens[Index].Tok.is(tok::r_paren))
534 return false;
Daniel Jasper20409152012-12-04 14:54:30 +0000535 consumeToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000536 }
537 return false;
538 }
539
Daniel Jasper20409152012-12-04 14:54:30 +0000540 bool parseConditional() {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000541 while (Index < Tokens.size()) {
542 if (Tokens[Index].Tok.is(tok::colon)) {
543 Annotations[Index].Type = TokenAnnotation::TT_ConditionalExpr;
544 next();
545 return true;
546 }
Daniel Jasper20409152012-12-04 14:54:30 +0000547 consumeToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000548 }
549 return false;
550 }
551
Daniel Jasper20409152012-12-04 14:54:30 +0000552 void consumeToken() {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000553 unsigned CurrentIndex = Index;
554 next();
555 switch (Tokens[CurrentIndex].Tok.getKind()) {
556 case tok::l_paren:
Daniel Jasper20409152012-12-04 14:54:30 +0000557 parseParens();
Daniel Jasper1321eb52012-12-18 21:05:13 +0000558 if (Index < Tokens.size() && Tokens[Index].Tok.is(tok::colon)) {
559 Annotations[Index].Type = TokenAnnotation::TT_CtorInitializerColon;
560 next();
561 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000562 break;
563 case tok::l_square:
Daniel Jasper20409152012-12-04 14:54:30 +0000564 parseSquare();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000565 break;
566 case tok::less:
Daniel Jasper20409152012-12-04 14:54:30 +0000567 if (parseAngle())
Daniel Jasperbac016b2012-12-03 18:12:45 +0000568 Annotations[CurrentIndex].Type = TokenAnnotation::TT_TemplateOpener;
569 else {
570 Annotations[CurrentIndex].Type = TokenAnnotation::TT_BinaryOperator;
571 Index = CurrentIndex + 1;
572 }
573 break;
574 case tok::greater:
575 Annotations[CurrentIndex].Type = TokenAnnotation::TT_BinaryOperator;
576 break;
577 case tok::kw_operator:
Daniel Jasperf6aef6a2012-12-24 10:56:04 +0000578 if (Tokens[Index].Tok.is(tok::l_paren)) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000579 Annotations[Index].Type = TokenAnnotation::TT_OverloadedOperator;
Daniel Jasperf6aef6a2012-12-24 10:56:04 +0000580 next();
581 if (Index < Tokens.size() && Tokens[Index].Tok.is(tok::r_paren)) {
582 Annotations[Index].Type = TokenAnnotation::TT_OverloadedOperator;
583 next();
584 }
585 } else {
586 while (Index < Tokens.size() && !Tokens[Index].Tok.is(tok::l_paren)) {
587 Annotations[Index].Type = TokenAnnotation::TT_OverloadedOperator;
588 next();
589 }
590 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000591 break;
592 case tok::question:
Daniel Jasper20409152012-12-04 14:54:30 +0000593 parseConditional();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000594 break;
595 default:
596 break;
597 }
598 }
599
Daniel Jaspercd1a32b2012-12-21 17:58:39 +0000600 void parseIncludeDirective() {
601 while (Index < Tokens.size()) {
602 if (Tokens[Index].Tok.is(tok::slash))
603 Annotations[Index].Type = TokenAnnotation::TT_DirectorySeparator;
604 else if (Tokens[Index].Tok.is(tok::less))
605 Annotations[Index].Type = TokenAnnotation::TT_TemplateOpener;
606 else if (Tokens[Index].Tok.is(tok::greater))
607 Annotations[Index].Type = TokenAnnotation::TT_TemplateCloser;
608 next();
609 }
610 }
611
612 void parsePreprocessorDirective() {
613 next();
614 if (Index >= Tokens.size())
615 return;
616 switch (Tokens[Index].Tok.getIdentifierInfo()->getPPKeywordID()) {
617 case tok::pp_include:
Nico Weberb23ae0c2012-12-21 18:21:56 +0000618 case tok::pp_import:
Daniel Jaspercd1a32b2012-12-21 17:58:39 +0000619 parseIncludeDirective();
620 break;
621 default:
622 break;
623 }
624 }
625
Daniel Jasperbac016b2012-12-03 18:12:45 +0000626 void parseLine() {
Daniel Jaspercd1a32b2012-12-21 17:58:39 +0000627 if (Tokens[Index].Tok.is(tok::hash)) {
628 parsePreprocessorDirective();
629 return;
630 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000631 while (Index < Tokens.size()) {
Daniel Jasper20409152012-12-04 14:54:30 +0000632 consumeToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000633 }
634 }
635
636 void next() {
637 ++Index;
638 }
639
640 private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000641 const SmallVector<FormatToken, 16> &Tokens;
642 std::vector<TokenAnnotation> &Annotations;
643 unsigned Index;
644 };
645
646 void annotate() {
647 Annotations.clear();
648 for (int i = 0, e = Line.Tokens.size(); i != e; ++i) {
649 Annotations.push_back(TokenAnnotation());
650 }
651
Manuel Klimek0be4b362012-12-03 20:55:42 +0000652 AnnotatingParser Parser(Line.Tokens, Annotations);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000653 Parser.parseLine();
654
655 determineTokenTypes();
Fariborz Jahanian154120c2012-12-20 19:54:13 +0000656 bool IsObjCMethodDecl =
Daniel Jasper98e6b4a2012-12-21 09:41:31 +0000657 (Line.Tokens.size() > 0 &&
658 (Annotations[0].Type == TokenAnnotation::TT_ObjCMethodSpecifier));
Daniel Jasperbac016b2012-12-03 18:12:45 +0000659 for (int i = 1, e = Line.Tokens.size(); i != e; ++i) {
660 TokenAnnotation &Annotation = Annotations[i];
661
Daniel Jasper4dc41de2013-01-02 08:44:14 +0000662 Annotation.CanBreakBefore = canBreakBefore(i);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000663
Daniel Jasper1321eb52012-12-18 21:05:13 +0000664 if (Annotation.Type == TokenAnnotation::TT_CtorInitializerColon) {
665 Annotation.MustBreakBefore = true;
666 Annotation.SpaceRequiredBefore = true;
Daniel Jasperf6aef6a2012-12-24 10:56:04 +0000667 } else if (Annotation.Type == TokenAnnotation::TT_OverloadedOperator) {
668 Annotation.SpaceRequiredBefore =
Daniel Jasperd7610b82012-12-24 16:51:15 +0000669 Line.Tokens[i].Tok.is(tok::identifier) ||
670 Line.Tokens[i].Tok.is(tok::kw_new) ||
671 Line.Tokens[i].Tok.is(tok::kw_delete);
Daniel Jasperf6aef6a2012-12-24 10:56:04 +0000672 } else if (
673 Annotations[i - 1].Type == TokenAnnotation::TT_OverloadedOperator) {
674 Annotation.SpaceRequiredBefore = false;
Daniel Jasper98e6b4a2012-12-21 09:41:31 +0000675 } else if (IsObjCMethodDecl && Line.Tokens[i].Tok.is(tok::identifier) &&
676 (i != e - 1) && Line.Tokens[i + 1].Tok.is(tok::colon) &&
677 Line.Tokens[i - 1].Tok.is(tok::identifier)) {
Fariborz Jahanian154120c2012-12-20 19:54:13 +0000678 Annotation.CanBreakBefore = true;
679 Annotation.SpaceRequiredBefore = true;
Daniel Jasper98e6b4a2012-12-21 09:41:31 +0000680 } else if (IsObjCMethodDecl && Line.Tokens[i].Tok.is(tok::identifier) &&
681 Line.Tokens[i - 1].Tok.is(tok::l_paren) &&
682 Line.Tokens[i - 2].Tok.is(tok::colon)) {
Fariborz Jahanian154120c2012-12-20 19:54:13 +0000683 // Don't break this identifier as ':' or identifier
684 // before it will break.
685 Annotation.CanBreakBefore = false;
686 } else if (Line.Tokens[i].Tok.is(tok::at) &&
Daniel Jasper98e6b4a2012-12-21 09:41:31 +0000687 Line.Tokens[i - 2].Tok.is(tok::at)) {
Fariborz Jahanian154120c2012-12-20 19:54:13 +0000688 // Don't put two objc's '@' on the same line. This could happen,
Fariborz Jahanian5f04ef52012-12-21 17:14:23 +0000689 // as in, @optional @property ...
Fariborz Jahanian154120c2012-12-20 19:54:13 +0000690 Annotation.MustBreakBefore = true;
Daniel Jasper1321eb52012-12-18 21:05:13 +0000691 } else if (Line.Tokens[i].Tok.is(tok::colon)) {
Daniel Jasperdfbb3192012-12-05 16:24:48 +0000692 Annotation.SpaceRequiredBefore =
Daniel Jasperd7610b82012-12-24 16:51:15 +0000693 Line.Tokens[0].Tok.isNot(tok::kw_case) && !IsObjCMethodDecl &&
694 (i != e - 1);
Fariborz Jahanian154120c2012-12-20 19:54:13 +0000695 // Don't break at ':' if identifier before it can beak.
Daniel Jasper98e6b4a2012-12-21 09:41:31 +0000696 if (IsObjCMethodDecl && Line.Tokens[i - 1].Tok.is(tok::identifier) &&
697 Annotations[i - 1].CanBreakBefore)
Fariborz Jahanian154120c2012-12-20 19:54:13 +0000698 Annotation.CanBreakBefore = false;
Daniel Jasper98e6b4a2012-12-21 09:41:31 +0000699 } else if (
700 Annotations[i - 1].Type == TokenAnnotation::TT_ObjCMethodSpecifier) {
Fariborz Jahanian154120c2012-12-20 19:54:13 +0000701 Annotation.SpaceRequiredBefore = true;
Daniel Jasper98e6b4a2012-12-21 09:41:31 +0000702 } else if (Annotations[i - 1].Type == TokenAnnotation::TT_UnaryOperator) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000703 Annotation.SpaceRequiredBefore = false;
704 } else if (Annotation.Type == TokenAnnotation::TT_UnaryOperator) {
705 Annotation.SpaceRequiredBefore =
Daniel Jasper8822d3a2012-12-04 13:02:32 +0000706 Line.Tokens[i - 1].Tok.isNot(tok::l_paren) &&
707 Line.Tokens[i - 1].Tok.isNot(tok::l_square);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000708 } else if (Line.Tokens[i - 1].Tok.is(tok::greater) &&
709 Line.Tokens[i].Tok.is(tok::greater)) {
Daniel Jasper8822d3a2012-12-04 13:02:32 +0000710 if (Annotation.Type == TokenAnnotation::TT_TemplateCloser &&
Daniel Jasper20409152012-12-04 14:54:30 +0000711 Annotations[i - 1].Type == TokenAnnotation::TT_TemplateCloser)
Daniel Jaspera88bb452012-12-04 10:50:12 +0000712 Annotation.SpaceRequiredBefore = Style.SplitTemplateClosingGreater;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000713 else
714 Annotation.SpaceRequiredBefore = false;
715 } else if (
Daniel Jaspercd1a32b2012-12-21 17:58:39 +0000716 Annotation.Type == TokenAnnotation::TT_DirectorySeparator ||
717 Annotations[i - 1].Type == TokenAnnotation::TT_DirectorySeparator) {
718 Annotation.SpaceRequiredBefore = false;
719 } else if (
Daniel Jasperbac016b2012-12-03 18:12:45 +0000720 Annotation.Type == TokenAnnotation::TT_BinaryOperator ||
721 Annotations[i - 1].Type == TokenAnnotation::TT_BinaryOperator) {
722 Annotation.SpaceRequiredBefore = true;
723 } else if (
Daniel Jaspera88bb452012-12-04 10:50:12 +0000724 Annotations[i - 1].Type == TokenAnnotation::TT_TemplateCloser &&
Daniel Jasperbac016b2012-12-03 18:12:45 +0000725 Line.Tokens[i].Tok.is(tok::l_paren)) {
726 Annotation.SpaceRequiredBefore = false;
Daniel Jasper8822d3a2012-12-04 13:02:32 +0000727 } else if (Line.Tokens[i].Tok.is(tok::less) &&
728 Line.Tokens[0].Tok.is(tok::hash)) {
729 Annotation.SpaceRequiredBefore = true;
Daniel Jasper98e6b4a2012-12-21 09:41:31 +0000730 } else if (IsObjCMethodDecl && Line.Tokens[i - 1].Tok.is(tok::r_paren) &&
731 Line.Tokens[i].Tok.is(tok::identifier)) {
Fariborz Jahanian154120c2012-12-20 19:54:13 +0000732 // Don't space between ')' and <id>
733 Annotation.SpaceRequiredBefore = false;
Daniel Jasper98e6b4a2012-12-21 09:41:31 +0000734 } else if (IsObjCMethodDecl && Line.Tokens[i - 1].Tok.is(tok::colon) &&
735 Line.Tokens[i].Tok.is(tok::l_paren)) {
Fariborz Jahanian154120c2012-12-20 19:54:13 +0000736 // Don't space between ':' and '('
737 Annotation.SpaceRequiredBefore = false;
Daniel Jasper98e6b4a2012-12-21 09:41:31 +0000738 } else if (Annotation.Type == TokenAnnotation::TT_TrailingUnaryOperator) {
739 Annotation.SpaceRequiredBefore = false;
740 } else {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000741 Annotation.SpaceRequiredBefore =
742 spaceRequiredBetween(Line.Tokens[i - 1].Tok, Line.Tokens[i].Tok);
743 }
744
745 if (Annotations[i - 1].Type == TokenAnnotation::TT_LineComment ||
746 (Line.Tokens[i].Tok.is(tok::string_literal) &&
747 Line.Tokens[i - 1].Tok.is(tok::string_literal))) {
748 Annotation.MustBreakBefore = true;
749 }
750
751 if (Annotation.MustBreakBefore)
752 Annotation.CanBreakBefore = true;
753 }
754 }
755
756 const std::vector<TokenAnnotation> &getAnnotations() {
757 return Annotations;
758 }
759
760private:
761 void determineTokenTypes() {
Nico Weber00d5a042012-12-23 01:07:46 +0000762 bool IsRHS = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000763 for (int i = 0, e = Line.Tokens.size(); i != e; ++i) {
764 TokenAnnotation &Annotation = Annotations[i];
765 const FormatToken &Tok = Line.Tokens[i];
766
Daniel Jaspercf225b62012-12-24 13:43:52 +0000767 if (getPrecedence(Tok) == prec::Assignment)
Nico Weber00d5a042012-12-23 01:07:46 +0000768 IsRHS = true;
769 else if (Tok.Tok.is(tok::kw_return))
770 IsRHS = true;
Daniel Jasper112fb272012-12-05 07:51:39 +0000771
Daniel Jasper675d2e32012-12-21 10:20:02 +0000772 if (Annotation.Type != TokenAnnotation::TT_Unknown)
773 continue;
774
Daniel Jasper98e6b4a2012-12-21 09:41:31 +0000775 if (Tok.Tok.is(tok::star) || Tok.Tok.is(tok::amp)) {
Nico Weber00d5a042012-12-23 01:07:46 +0000776 Annotation.Type = determineStarAmpUsage(i, IsRHS);
Daniel Jasper98e6b4a2012-12-21 09:41:31 +0000777 } else if (Tok.Tok.is(tok::minus) || Tok.Tok.is(tok::plus)) {
778 Annotation.Type = determinePlusMinusUsage(i);
779 } else if (Tok.Tok.is(tok::minusminus) || Tok.Tok.is(tok::plusplus)) {
780 Annotation.Type = determineIncrementUsage(i);
781 } else if (Tok.Tok.is(tok::exclaim)) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000782 Annotation.Type = TokenAnnotation::TT_UnaryOperator;
Daniel Jasper675d2e32012-12-21 10:20:02 +0000783 } else if (isBinaryOperator(Line.Tokens[i])) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000784 Annotation.Type = TokenAnnotation::TT_BinaryOperator;
Daniel Jasper675d2e32012-12-21 10:20:02 +0000785 } else if (Tok.Tok.is(tok::comment)) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000786 StringRef Data(SourceMgr.getCharacterData(Tok.Tok.getLocation()),
787 Tok.Tok.getLength());
788 if (Data.startswith("//"))
789 Annotation.Type = TokenAnnotation::TT_LineComment;
790 else
791 Annotation.Type = TokenAnnotation::TT_BlockComment;
792 }
793 }
794 }
795
Daniel Jasperbac016b2012-12-03 18:12:45 +0000796 bool isBinaryOperator(const FormatToken &Tok) {
Daniel Jaspercd1a32b2012-12-21 17:58:39 +0000797 // Comma is a binary operator, but does not behave as such wrt. formatting.
Daniel Jaspercf225b62012-12-24 13:43:52 +0000798 return getPrecedence(Tok) > prec::Comma;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000799 }
800
Daniel Jasperd7610b82012-12-24 16:51:15 +0000801 TokenAnnotation::TokenType determineStarAmpUsage(unsigned Index, bool IsRHS) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000802 if (Index == Annotations.size())
803 return TokenAnnotation::TT_Unknown;
804
805 if (Index == 0 || Line.Tokens[Index - 1].Tok.is(tok::l_paren) ||
806 Line.Tokens[Index - 1].Tok.is(tok::comma) ||
Nico Weber00d5a042012-12-23 01:07:46 +0000807 Line.Tokens[Index - 1].Tok.is(tok::kw_return) ||
Daniel Jasper5d334402013-01-02 08:57:10 +0000808 Line.Tokens[Index - 1].Tok.is(tok::colon) ||
Daniel Jasperbac016b2012-12-03 18:12:45 +0000809 Annotations[Index - 1].Type == TokenAnnotation::TT_BinaryOperator)
810 return TokenAnnotation::TT_UnaryOperator;
811
812 if (Line.Tokens[Index - 1].Tok.isLiteral() ||
Daniel Jasper98e6b4a2012-12-21 09:41:31 +0000813 Line.Tokens[Index + 1].Tok.isLiteral() ||
814 Line.Tokens[Index + 1].Tok.is(tok::kw_sizeof))
Daniel Jasperbac016b2012-12-03 18:12:45 +0000815 return TokenAnnotation::TT_BinaryOperator;
816
Daniel Jasper112fb272012-12-05 07:51:39 +0000817 // It is very unlikely that we are going to find a pointer or reference type
818 // definition on the RHS of an assignment.
Nico Weber00d5a042012-12-23 01:07:46 +0000819 if (IsRHS)
Daniel Jasper112fb272012-12-05 07:51:39 +0000820 return TokenAnnotation::TT_BinaryOperator;
821
Daniel Jasperbac016b2012-12-03 18:12:45 +0000822 return TokenAnnotation::TT_PointerOrReference;
823 }
824
Daniel Jasper98e6b4a2012-12-21 09:41:31 +0000825 TokenAnnotation::TokenType determinePlusMinusUsage(unsigned Index) {
826 // At the start of the line, +/- specific ObjectiveC method declarations.
827 if (Index == 0)
828 return TokenAnnotation::TT_ObjCMethodSpecifier;
829
830 // Use heuristics to recognize unary operators.
831 const Token &PreviousTok = Line.Tokens[Index - 1].Tok;
832 if (PreviousTok.is(tok::equal) || PreviousTok.is(tok::l_paren) ||
833 PreviousTok.is(tok::comma) || PreviousTok.is(tok::l_square) ||
834 PreviousTok.is(tok::question) || PreviousTok.is(tok::colon))
835 return TokenAnnotation::TT_UnaryOperator;
836
837 // There can't be to consecutive binary operators.
838 if (Annotations[Index - 1].Type == TokenAnnotation::TT_BinaryOperator)
839 return TokenAnnotation::TT_UnaryOperator;
840
841 // Fall back to marking the token as binary operator.
842 return TokenAnnotation::TT_BinaryOperator;
843 }
844
845 /// \brief Determine whether ++/-- are pre- or post-increments/-decrements.
846 TokenAnnotation::TokenType determineIncrementUsage(unsigned Index) {
847 if (Index != 0 && Line.Tokens[Index - 1].Tok.is(tok::identifier))
848 return TokenAnnotation::TT_TrailingUnaryOperator;
849
850 return TokenAnnotation::TT_UnaryOperator;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000851 }
852
853 bool spaceRequiredBetween(Token Left, Token Right) {
Daniel Jasper8b39c662012-12-10 18:59:13 +0000854 if (Right.is(tok::r_paren) || Right.is(tok::semi) || Right.is(tok::comma))
855 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000856 if (Left.is(tok::kw_template) && Right.is(tok::less))
857 return true;
858 if (Left.is(tok::arrow) || Right.is(tok::arrow))
859 return false;
860 if (Left.is(tok::exclaim) || Left.is(tok::tilde))
861 return false;
Fariborz Jahanian154120c2012-12-20 19:54:13 +0000862 if (Left.is(tok::at) && Right.is(tok::identifier))
863 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000864 if (Left.is(tok::less) || Right.is(tok::greater) || Right.is(tok::less))
865 return false;
Daniel Jasperc74e2792012-12-07 09:52:15 +0000866 if (Right.is(tok::amp) || Right.is(tok::star))
867 return Left.isLiteral() ||
Daniel Jasperd7610b82012-12-24 16:51:15 +0000868 (Left.isNot(tok::star) && Left.isNot(tok::amp) &&
869 !Style.PointerAndReferenceBindToType);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000870 if (Left.is(tok::amp) || Left.is(tok::star))
871 return Right.isLiteral() || Style.PointerAndReferenceBindToType;
872 if (Right.is(tok::star) && Left.is(tok::l_paren))
873 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000874 if (Left.is(tok::l_square) || Right.is(tok::l_square) ||
875 Right.is(tok::r_square))
876 return false;
Daniel Jasperc74e2792012-12-07 09:52:15 +0000877 if (Left.is(tok::coloncolon) ||
878 (Right.is(tok::coloncolon) &&
879 (Left.is(tok::identifier) || Left.is(tok::greater))))
Daniel Jasperbac016b2012-12-03 18:12:45 +0000880 return false;
881 if (Left.is(tok::period) || Right.is(tok::period))
882 return false;
883 if (Left.is(tok::colon) || Right.is(tok::colon))
884 return true;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000885 if (Left.is(tok::l_paren))
886 return false;
887 if (Left.is(tok::hash))
888 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000889 if (Right.is(tok::l_paren)) {
Daniel Jasper98e6b4a2012-12-21 09:41:31 +0000890 return Left.is(tok::kw_if) || Left.is(tok::kw_for) ||
Daniel Jasperd7610b82012-12-24 16:51:15 +0000891 Left.is(tok::kw_while) || Left.is(tok::kw_switch) ||
892 (Left.isNot(tok::identifier) && Left.isNot(tok::kw_sizeof) &&
893 Left.isNot(tok::kw_typeof));
Daniel Jasperbac016b2012-12-03 18:12:45 +0000894 }
895 return true;
896 }
897
Daniel Jasper4dc41de2013-01-02 08:44:14 +0000898 bool canBreakBefore(unsigned i) {
899 if (Annotations[i - 1].Type == TokenAnnotation::TT_PointerOrReference ||
900 Annotations[i].Type == TokenAnnotation::TT_ConditionalExpr) {
901 return false;
902 }
903 const FormatToken &Left = Line.Tokens[i - 1];
904 const FormatToken &Right = Line.Tokens[i];
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000905 if (Right.Tok.is(tok::r_paren) || Right.Tok.is(tok::l_brace) ||
906 Right.Tok.is(tok::comment) || Right.Tok.is(tok::greater))
Daniel Jasperbac016b2012-12-03 18:12:45 +0000907 return false;
Daniel Jasper675d2e32012-12-21 10:20:02 +0000908 return (isBinaryOperator(Left) && Left.Tok.isNot(tok::lessless)) ||
Daniel Jasperd7610b82012-12-24 16:51:15 +0000909 Left.Tok.is(tok::comma) || Right.Tok.is(tok::lessless) ||
910 Right.Tok.is(tok::arrow) || Right.Tok.is(tok::period) ||
911 Right.Tok.is(tok::colon) || Left.Tok.is(tok::semi) ||
912 Left.Tok.is(tok::l_brace) ||
913 (Left.Tok.is(tok::l_paren) && !Right.Tok.is(tok::r_paren));
Daniel Jasperbac016b2012-12-03 18:12:45 +0000914 }
915
916 const UnwrappedLine &Line;
917 FormatStyle Style;
918 SourceManager &SourceMgr;
919 std::vector<TokenAnnotation> Annotations;
920};
921
Alexander Kornienko469a21b2012-12-07 16:15:44 +0000922class LexerBasedFormatTokenSource : public FormatTokenSource {
923public:
924 LexerBasedFormatTokenSource(Lexer &Lex, SourceManager &SourceMgr)
Daniel Jasper1321eb52012-12-18 21:05:13 +0000925 : GreaterStashed(false), Lex(Lex), SourceMgr(SourceMgr),
Alexander Kornienko469a21b2012-12-07 16:15:44 +0000926 IdentTable(Lex.getLangOpts()) {
927 Lex.SetKeepWhitespaceMode(true);
928 }
929
930 virtual FormatToken getNextToken() {
931 if (GreaterStashed) {
932 FormatTok.NewlinesBefore = 0;
933 FormatTok.WhiteSpaceStart =
934 FormatTok.Tok.getLocation().getLocWithOffset(1);
935 FormatTok.WhiteSpaceLength = 0;
936 GreaterStashed = false;
937 return FormatTok;
938 }
939
940 FormatTok = FormatToken();
941 Lex.LexFromRawLexer(FormatTok.Tok);
942 FormatTok.WhiteSpaceStart = FormatTok.Tok.getLocation();
943
944 // Consume and record whitespace until we find a significant token.
945 while (FormatTok.Tok.is(tok::unknown)) {
946 FormatTok.NewlinesBefore += tokenText(FormatTok.Tok).count('\n');
947 FormatTok.WhiteSpaceLength += FormatTok.Tok.getLength();
948
949 if (FormatTok.Tok.is(tok::eof))
950 return FormatTok;
951 Lex.LexFromRawLexer(FormatTok.Tok);
952 }
953
954 if (FormatTok.Tok.is(tok::raw_identifier)) {
Daniel Jaspercd1a32b2012-12-21 17:58:39 +0000955 IdentifierInfo &Info = IdentTable.get(tokenText(FormatTok.Tok));
956 FormatTok.Tok.setIdentifierInfo(&Info);
Alexander Kornienko469a21b2012-12-07 16:15:44 +0000957 FormatTok.Tok.setKind(Info.getTokenID());
958 }
959
960 if (FormatTok.Tok.is(tok::greatergreater)) {
961 FormatTok.Tok.setKind(tok::greater);
962 GreaterStashed = true;
963 }
964
965 return FormatTok;
966 }
967
968private:
969 FormatToken FormatTok;
970 bool GreaterStashed;
971 Lexer &Lex;
972 SourceManager &SourceMgr;
973 IdentifierTable IdentTable;
974
975 /// Returns the text of \c FormatTok.
976 StringRef tokenText(Token &Tok) {
977 return StringRef(SourceMgr.getCharacterData(Tok.getLocation()),
978 Tok.getLength());
979 }
980};
981
Daniel Jasperbac016b2012-12-03 18:12:45 +0000982class Formatter : public UnwrappedLineConsumer {
983public:
984 Formatter(const FormatStyle &Style, Lexer &Lex, SourceManager &SourceMgr,
985 const std::vector<CharSourceRange> &Ranges)
Daniel Jasper1321eb52012-12-18 21:05:13 +0000986 : Style(Style), Lex(Lex), SourceMgr(SourceMgr), Ranges(Ranges),
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000987 StructuralError(false) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000988 }
989
Daniel Jasperaccb0b02012-12-04 21:05:31 +0000990 virtual ~Formatter() {
991 }
992
Daniel Jasperbac016b2012-12-03 18:12:45 +0000993 tooling::Replacements format() {
Alexander Kornienko469a21b2012-12-07 16:15:44 +0000994 LexerBasedFormatTokenSource Tokens(Lex, SourceMgr);
995 UnwrappedLineParser Parser(Style, Tokens, *this);
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000996 StructuralError = Parser.parse();
997 for (std::vector<UnwrappedLine>::iterator I = UnwrappedLines.begin(),
998 E = UnwrappedLines.end();
999 I != E; ++I)
Alexander Kornienko720ffb62012-12-05 13:56:52 +00001000 formatUnwrappedLine(*I);
Daniel Jasperbac016b2012-12-03 18:12:45 +00001001 return Replaces;
1002 }
1003
1004private:
Alexander Kornienko720ffb62012-12-05 13:56:52 +00001005 virtual void consumeUnwrappedLine(const UnwrappedLine &TheLine) {
Alexander Kornienkocff563c2012-12-04 17:27:50 +00001006 UnwrappedLines.push_back(TheLine);
1007 }
1008
Alexander Kornienko720ffb62012-12-05 13:56:52 +00001009 void formatUnwrappedLine(const UnwrappedLine &TheLine) {
Daniel Jasperbac016b2012-12-03 18:12:45 +00001010 if (TheLine.Tokens.size() == 0)
1011 return;
1012
1013 CharSourceRange LineRange =
1014 CharSourceRange::getTokenRange(TheLine.Tokens.front().Tok.getLocation(),
1015 TheLine.Tokens.back().Tok.getLocation());
1016
1017 for (unsigned i = 0, e = Ranges.size(); i != e; ++i) {
1018 if (SourceMgr.isBeforeInTranslationUnit(LineRange.getEnd(),
1019 Ranges[i].getBegin()) ||
1020 SourceMgr.isBeforeInTranslationUnit(Ranges[i].getEnd(),
1021 LineRange.getBegin()))
1022 continue;
1023
1024 TokenAnnotator Annotator(TheLine, Style, SourceMgr);
1025 Annotator.annotate();
1026 UnwrappedLineFormatter Formatter(Style, SourceMgr, TheLine,
Alexander Kornienkocff563c2012-12-04 17:27:50 +00001027 Annotator.getAnnotations(), Replaces,
1028 StructuralError);
Daniel Jasperbac016b2012-12-03 18:12:45 +00001029 Formatter.format();
1030 return;
1031 }
1032 }
1033
1034 FormatStyle Style;
1035 Lexer &Lex;
1036 SourceManager &SourceMgr;
1037 tooling::Replacements Replaces;
1038 std::vector<CharSourceRange> Ranges;
Alexander Kornienkocff563c2012-12-04 17:27:50 +00001039 std::vector<UnwrappedLine> UnwrappedLines;
1040 bool StructuralError;
Daniel Jasperbac016b2012-12-03 18:12:45 +00001041};
1042
1043tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
1044 SourceManager &SourceMgr,
1045 std::vector<CharSourceRange> Ranges) {
1046 Formatter formatter(Style, Lex, SourceMgr, Ranges);
1047 return formatter.format();
1048}
1049
1050} // namespace format
1051} // namespace clang