blob: c8dc7bf55c1c913eb5db05de653fd831ac4bc7f6 [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"
Alexander Kornienko3048aea2013-01-10 15:05:09 +000021#include "clang/Basic/Diagnostic.h"
Daniel Jasper675d2e32012-12-21 10:20:02 +000022#include "clang/Basic/OperatorPrecedence.h"
Chandler Carruthb99083e2013-01-02 10:28:36 +000023#include "clang/Basic/SourceManager.h"
Alexander Kornienko3048aea2013-01-10 15:05:09 +000024#include "clang/Frontend/TextDiagnosticPrinter.h"
Daniel Jasperbac016b2012-12-03 18:12:45 +000025#include "clang/Lex/Lexer.h"
Daniel Jasper8822d3a2012-12-04 13:02:32 +000026#include <string>
27
Daniel Jasperbac016b2012-12-03 18:12:45 +000028namespace clang {
29namespace format {
30
Daniel Jasper71607512013-01-07 10:48:50 +000031enum TokenType {
Daniel Jasper71607512013-01-07 10:48:50 +000032 TT_BinaryOperator,
Daniel Jasper5cf7cf32013-01-10 11:14:08 +000033 TT_BlockComment,
34 TT_CastRParen,
Daniel Jasper71607512013-01-07 10:48:50 +000035 TT_ConditionalExpr,
36 TT_CtorInitializerColon,
Daniel Jasper8134e1e2013-01-13 08:12:18 +000037 TT_IncludePath,
Daniel Jasper5cf7cf32013-01-10 11:14:08 +000038 TT_LineComment,
Daniel Jasper46ef8522013-01-10 13:08:12 +000039 TT_ObjCBlockLParen,
Nico Webered91bba2013-01-10 19:19:14 +000040 TT_ObjCDecl,
Daniel Jasper5cf7cf32013-01-10 11:14:08 +000041 TT_ObjCMethodSpecifier,
Nico Weberbcfdd262013-01-12 06:18:40 +000042 TT_ObjCMethodExpr,
Nico Webercd52bda2013-01-10 23:11:41 +000043 TT_ObjCSelectorStart,
Nico Weber70848232013-01-10 21:30:42 +000044 TT_ObjCProperty,
Daniel Jasper5cf7cf32013-01-10 11:14:08 +000045 TT_OverloadedOperator,
46 TT_PointerOrReference,
Daniel Jasper71607512013-01-07 10:48:50 +000047 TT_PureVirtualSpecifier,
Daniel Jasper5cf7cf32013-01-10 11:14:08 +000048 TT_TemplateCloser,
49 TT_TemplateOpener,
50 TT_TrailingUnaryOperator,
51 TT_UnaryOperator,
52 TT_Unknown
Daniel Jasper71607512013-01-07 10:48:50 +000053};
54
55enum LineType {
56 LT_Invalid,
57 LT_Other,
58 LT_PreprocessorDirective,
59 LT_VirtualFunctionDecl,
Nico Webered91bba2013-01-10 19:19:14 +000060 LT_ObjCDecl, // An @interface, @implementation, or @protocol line.
Nico Weber70848232013-01-10 21:30:42 +000061 LT_ObjCMethodDecl,
62 LT_ObjCProperty // An @property line.
Daniel Jasper71607512013-01-07 10:48:50 +000063};
64
Daniel Jasper26f7e782013-01-08 14:56:18 +000065class AnnotatedToken {
66public:
67 AnnotatedToken(const FormatToken &FormatTok)
Manuel Klimek94fc6f12013-01-10 19:17:33 +000068 : FormatTok(FormatTok), Type(TT_Unknown), SpaceRequiredBefore(false),
69 CanBreakBefore(false), MustBreakBefore(false),
70 ClosesTemplateDeclaration(false), Parent(NULL) {}
Daniel Jasper26f7e782013-01-08 14:56:18 +000071
Daniel Jasperfeb18f52013-01-14 14:14:23 +000072 bool is(tok::TokenKind Kind) const { return FormatTok.Tok.is(Kind); }
73 bool isNot(tok::TokenKind Kind) const { return FormatTok.Tok.isNot(Kind); }
74
Daniel Jasper26f7e782013-01-08 14:56:18 +000075 bool isObjCAtKeyword(tok::ObjCKeywordKind Kind) const {
76 return FormatTok.Tok.isObjCAtKeyword(Kind);
77 }
78
79 FormatToken FormatTok;
80
Daniel Jasperbac016b2012-12-03 18:12:45 +000081 TokenType Type;
82
Daniel Jasperbac016b2012-12-03 18:12:45 +000083 bool SpaceRequiredBefore;
84 bool CanBreakBefore;
85 bool MustBreakBefore;
Daniel Jasper9a64fb52013-01-02 15:08:56 +000086
87 bool ClosesTemplateDeclaration;
Daniel Jasper26f7e782013-01-08 14:56:18 +000088
89 std::vector<AnnotatedToken> Children;
90 AnnotatedToken *Parent;
Daniel Jasperbac016b2012-12-03 18:12:45 +000091};
92
Daniel Jasper995e8202013-01-14 13:08:07 +000093class AnnotatedLine {
94public:
95 AnnotatedLine(const FormatToken &FormatTok, unsigned Level,
96 bool InPPDirective)
97 : First(FormatTok), Level(Level), InPPDirective(InPPDirective) {}
98 AnnotatedToken First;
99 AnnotatedToken *Last;
100
101 LineType Type;
102 unsigned Level;
103 bool InPPDirective;
104};
105
Daniel Jasper26f7e782013-01-08 14:56:18 +0000106static prec::Level getPrecedence(const AnnotatedToken &Tok) {
107 return getBinOpPrecedence(Tok.FormatTok.Tok.getKind(), true, true);
Daniel Jaspercf225b62012-12-24 13:43:52 +0000108}
109
Daniel Jasperbac016b2012-12-03 18:12:45 +0000110FormatStyle getLLVMStyle() {
111 FormatStyle LLVMStyle;
112 LLVMStyle.ColumnLimit = 80;
113 LLVMStyle.MaxEmptyLinesToKeep = 1;
114 LLVMStyle.PointerAndReferenceBindToType = false;
115 LLVMStyle.AccessModifierOffset = -2;
116 LLVMStyle.SplitTemplateClosingGreater = true;
Alexander Kornienko15757312012-12-06 18:03:27 +0000117 LLVMStyle.IndentCaseLabels = false;
Daniel Jasper7ad4eff2013-01-07 11:09:06 +0000118 LLVMStyle.SpacesBeforeTrailingComments = 1;
Daniel Jasper7e9bf8c2013-01-11 11:37:55 +0000119 LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false;
Nico Weber5f500df2013-01-10 20:12:55 +0000120 LLVMStyle.ObjCSpaceBeforeProtocolList = true;
Nico Webercd52bda2013-01-10 23:11:41 +0000121 LLVMStyle.ObjCSpaceBeforeReturnType = true;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000122 return LLVMStyle;
123}
124
125FormatStyle getGoogleStyle() {
126 FormatStyle GoogleStyle;
127 GoogleStyle.ColumnLimit = 80;
128 GoogleStyle.MaxEmptyLinesToKeep = 1;
129 GoogleStyle.PointerAndReferenceBindToType = true;
130 GoogleStyle.AccessModifierOffset = -1;
131 GoogleStyle.SplitTemplateClosingGreater = false;
Alexander Kornienko15757312012-12-06 18:03:27 +0000132 GoogleStyle.IndentCaseLabels = true;
Daniel Jasper7ad4eff2013-01-07 11:09:06 +0000133 GoogleStyle.SpacesBeforeTrailingComments = 2;
Daniel Jasper7e9bf8c2013-01-11 11:37:55 +0000134 GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
Nico Weber5f500df2013-01-10 20:12:55 +0000135 GoogleStyle.ObjCSpaceBeforeProtocolList = false;
Nico Webercd52bda2013-01-10 23:11:41 +0000136 GoogleStyle.ObjCSpaceBeforeReturnType = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000137 return GoogleStyle;
138}
139
140struct OptimizationParameters {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000141 unsigned PenaltyIndentLevel;
Daniel Jaspera4974cf2012-12-24 16:43:00 +0000142 unsigned PenaltyLevelDecrease;
Daniel Jasperceb99ab2013-01-09 10:16:05 +0000143 unsigned PenaltyExcessCharacter;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000144};
145
Manuel Klimek3f8c7f32013-01-10 18:45:26 +0000146/// \brief Replaces the whitespace in front of \p Tok. Only call once for
147/// each \c FormatToken.
148static void replaceWhitespace(const AnnotatedToken &Tok, unsigned NewLines,
149 unsigned Spaces, const FormatStyle &Style,
150 SourceManager &SourceMgr,
151 tooling::Replacements &Replaces) {
152 Replaces.insert(tooling::Replacement(
153 SourceMgr, Tok.FormatTok.WhiteSpaceStart, Tok.FormatTok.WhiteSpaceLength,
154 std::string(NewLines, '\n') + std::string(Spaces, ' ')));
155}
156
157/// \brief Like \c replaceWhitespace, but additionally adds right-aligned
158/// backslashes to escape newlines inside a preprocessor directive.
159///
160/// This function and \c replaceWhitespace have the same behavior if
161/// \c Newlines == 0.
162static void replacePPWhitespace(
163 const AnnotatedToken &Tok, unsigned NewLines, unsigned Spaces,
164 unsigned WhitespaceStartColumn, const FormatStyle &Style,
165 SourceManager &SourceMgr, tooling::Replacements &Replaces) {
166 std::string NewLineText;
167 if (NewLines > 0) {
168 unsigned Offset = std::min<int>(Style.ColumnLimit - 1,
169 WhitespaceStartColumn);
170 for (unsigned i = 0; i < NewLines; ++i) {
171 NewLineText += std::string(Style.ColumnLimit - Offset - 1, ' ');
172 NewLineText += "\\\n";
173 Offset = 0;
174 }
175 }
176 Replaces.insert(tooling::Replacement(SourceMgr, Tok.FormatTok.WhiteSpaceStart,
177 Tok.FormatTok.WhiteSpaceLength,
178 NewLineText + std::string(Spaces, ' ')));
179}
180
Daniel Jasper995e8202013-01-14 13:08:07 +0000181/// \brief Calculates whether the (remaining) \c AnnotatedLine starting with
182/// \p RootToken fits into \p Limit columns on a single line.
183///
184/// If true, sets \p Length to the required length.
Daniel Jasperfeb18f52013-01-14 14:14:23 +0000185static bool fitsIntoLimit(const AnnotatedToken &RootToken, unsigned Limit,
186 unsigned *Length = 0) {
Daniel Jasper7e9bf8c2013-01-11 11:37:55 +0000187 unsigned Columns = RootToken.FormatTok.TokenLength;
Daniel Jaspere0b15ea2013-01-14 15:40:57 +0000188 if (Columns > Limit) return false;
Daniel Jasper7e9bf8c2013-01-11 11:37:55 +0000189 const AnnotatedToken *Tok = &RootToken;
190 while (!Tok->Children.empty()) {
191 Tok = &Tok->Children[0];
192 Columns += (Tok->SpaceRequiredBefore ? 1 : 0) + Tok->FormatTok.TokenLength;
193 // A special case for the colon of a constructor initializer as this only
194 // needs to be put on a new line if the line needs to be split.
195 if (Columns > Limit ||
196 (Tok->MustBreakBefore && Tok->Type != TT_CtorInitializerColon)) {
Daniel Jasper995e8202013-01-14 13:08:07 +0000197 // FIXME: Remove this hack.
198 return false;
Daniel Jasper7e9bf8c2013-01-11 11:37:55 +0000199 }
Daniel Jasper7d19bc22013-01-11 14:23:32 +0000200 }
Daniel Jasper995e8202013-01-14 13:08:07 +0000201 if (Length != 0)
202 *Length = Columns;
203 return true;
Daniel Jasper7e9bf8c2013-01-11 11:37:55 +0000204}
205
Nico Webere8ccc812013-01-12 22:48:47 +0000206/// \brief Returns if a token is an Objective-C selector name.
207///
Nico Weberea865632013-01-12 22:51:13 +0000208/// For example, "bar" is a selector name in [foo bar:(4 + 5)].
Nico Webere8ccc812013-01-12 22:48:47 +0000209static bool isObjCSelectorName(const AnnotatedToken &Tok) {
210 return Tok.is(tok::identifier) && !Tok.Children.empty() &&
211 Tok.Children[0].is(tok::colon) &&
212 Tok.Children[0].Type == TT_ObjCMethodExpr;
213}
214
Daniel Jasperbac016b2012-12-03 18:12:45 +0000215class UnwrappedLineFormatter {
216public:
Manuel Klimek94fc6f12013-01-10 19:17:33 +0000217 UnwrappedLineFormatter(const FormatStyle &Style, SourceManager &SourceMgr,
Daniel Jasper995e8202013-01-14 13:08:07 +0000218 const AnnotatedLine &Line, unsigned FirstIndent,
Rafael Espindolab14d1ca2013-01-12 14:22:42 +0000219 bool FitsOnALine, const AnnotatedToken &RootToken,
Manuel Klimek94fc6f12013-01-10 19:17:33 +0000220 tooling::Replacements &Replaces, bool StructuralError)
Daniel Jasper1321eb52012-12-18 21:05:13 +0000221 : Style(Style), SourceMgr(SourceMgr), Line(Line),
Manuel Klimek94fc6f12013-01-10 19:17:33 +0000222 FirstIndent(FirstIndent), FitsOnALine(FitsOnALine),
Rafael Espindolab14d1ca2013-01-12 14:22:42 +0000223 RootToken(RootToken), Replaces(Replaces) {
Daniel Jaspere2c7acf2012-12-24 00:13:23 +0000224 Parameters.PenaltyIndentLevel = 15;
Daniel Jasper46a46a22013-01-07 07:13:20 +0000225 Parameters.PenaltyLevelDecrease = 30;
Daniel Jasperceb99ab2013-01-09 10:16:05 +0000226 Parameters.PenaltyExcessCharacter = 1000000;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000227 }
228
Manuel Klimekd4397b92013-01-04 23:34:14 +0000229 /// \brief Formats an \c UnwrappedLine.
230 ///
231 /// \returns The column after the last token in the last line of the
232 /// \c UnwrappedLine.
233 unsigned format() {
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000234 // Initialize state dependent on indent.
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000235 LineState State;
Manuel Klimek3f8c7f32013-01-10 18:45:26 +0000236 State.Column = FirstIndent;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000237 State.NextToken = &RootToken;
Daniel Jasper7e9bf8c2013-01-11 11:37:55 +0000238 State.Stack.push_back(ParenState(FirstIndent + 4, FirstIndent));
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000239 State.ForLoopVariablePos = 0;
240 State.LineContainsContinuedForLoopSection = false;
Daniel Jaspera4974cf2012-12-24 16:43:00 +0000241 State.StartOfLineLevel = 1;
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000242
243 // The first token has already been indented and thus consumed.
244 moveStateToNextToken(State);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000245
246 // Start iterating at 1 as we have correctly formatted of Token #0 above.
Daniel Jasper26f7e782013-01-08 14:56:18 +0000247 while (State.NextToken != NULL) {
Daniel Jasper1321eb52012-12-18 21:05:13 +0000248 if (FitsOnALine) {
249 addTokenToState(false, false, State);
250 } else {
251 unsigned NoBreak = calcPenalty(State, false, UINT_MAX);
252 unsigned Break = calcPenalty(State, true, NoBreak);
253 addTokenToState(Break < NoBreak, false, State);
Daniel Jasper7e9bf8c2013-01-11 11:37:55 +0000254 if (State.NextToken != NULL &&
255 State.NextToken->Parent->Type == TT_CtorInitializerColon) {
256 if (Style.ConstructorInitializerAllOnOneLineOrOnePerLine &&
257 !fitsIntoLimit(*State.NextToken,
258 getColumnLimit() - State.Column - 1))
259 State.Stack.back().BreakAfterComma = true;
260 }
Daniel Jasper1321eb52012-12-18 21:05:13 +0000261 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000262 }
Manuel Klimekd4397b92013-01-04 23:34:14 +0000263 return State.Column;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000264 }
265
266private:
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000267 struct ParenState {
Daniel Jasper7e9bf8c2013-01-11 11:37:55 +0000268 ParenState(unsigned Indent, unsigned LastSpace)
269 : Indent(Indent), LastSpace(LastSpace), FirstLessLess(0),
270 BreakBeforeClosingBrace(false), BreakAfterComma(false) {}
Daniel Jaspera4974cf2012-12-24 16:43:00 +0000271
Daniel Jasperbac016b2012-12-03 18:12:45 +0000272 /// \brief The position to which a specific parenthesis level needs to be
273 /// indented.
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000274 unsigned Indent;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000275
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000276 /// \brief The position of the last space on each level.
277 ///
278 /// Used e.g. to break like:
279 /// functionCall(Parameter, otherCall(
280 /// OtherParameter));
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000281 unsigned LastSpace;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000282
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000283 /// \brief The position the first "<<" operator encountered on each level.
284 ///
285 /// Used to align "<<" operators. 0 if no such operator has been encountered
286 /// on a level.
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000287 unsigned FirstLessLess;
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000288
Manuel Klimekc8c8a472013-01-10 15:58:26 +0000289 /// \brief Whether a newline needs to be inserted before the block's closing
290 /// brace.
291 ///
292 /// We only want to insert a newline before the closing brace if there also
293 /// was a newline after the beginning left brace.
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000294 bool BreakBeforeClosingBrace;
295
Daniel Jasper7e9bf8c2013-01-11 11:37:55 +0000296 bool BreakAfterComma;
297
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000298 bool operator<(const ParenState &Other) const {
299 if (Indent != Other.Indent)
Daniel Jasper7d19bc22013-01-11 14:23:32 +0000300 return Indent < Other.Indent;
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000301 if (LastSpace != Other.LastSpace)
302 return LastSpace < Other.LastSpace;
303 if (FirstLessLess != Other.FirstLessLess)
304 return FirstLessLess < Other.FirstLessLess;
Daniel Jasper7e9bf8c2013-01-11 11:37:55 +0000305 if (BreakBeforeClosingBrace != Other.BreakBeforeClosingBrace)
306 return BreakBeforeClosingBrace;
Daniel Jasperb3123142013-01-12 07:36:22 +0000307 if (BreakAfterComma != Other.BreakAfterComma)
308 return BreakAfterComma;
309 return false;
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000310 }
311 };
312
313 /// \brief The current state when indenting a unwrapped line.
314 ///
315 /// As the indenting tries different combinations this is copied by value.
316 struct LineState {
317 /// \brief The number of used columns in the current line.
318 unsigned Column;
319
320 /// \brief The token that needs to be next formatted.
321 const AnnotatedToken *NextToken;
322
323 /// \brief The parenthesis level of the first token on the current line.
324 unsigned StartOfLineLevel;
Manuel Klimekc8c8a472013-01-10 15:58:26 +0000325
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000326 /// \brief The column of the first variable in a for-loop declaration.
327 ///
328 /// Used to align the second variable if necessary.
329 unsigned ForLoopVariablePos;
330
331 /// \brief \c true if this line contains a continued for-loop section.
332 bool LineContainsContinuedForLoopSection;
333
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000334 /// \brief A stack keeping track of properties applying to parenthesis
335 /// levels.
336 std::vector<ParenState> Stack;
337
338 /// \brief Comparison operator to be able to used \c LineState in \c map.
339 bool operator<(const LineState &Other) const {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000340 if (Other.NextToken != NextToken)
341 return Other.NextToken > NextToken;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000342 if (Other.Column != Column)
343 return Other.Column > Column;
Daniel Jaspera4974cf2012-12-24 16:43:00 +0000344 if (Other.StartOfLineLevel != StartOfLineLevel)
345 return Other.StartOfLineLevel > StartOfLineLevel;
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000346 if (Other.ForLoopVariablePos != ForLoopVariablePos)
347 return Other.ForLoopVariablePos < ForLoopVariablePos;
348 if (Other.LineContainsContinuedForLoopSection !=
349 LineContainsContinuedForLoopSection)
350 return LineContainsContinuedForLoopSection;
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000351 return Other.Stack < Stack;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000352 }
353 };
354
Daniel Jasper20409152012-12-04 14:54:30 +0000355 /// \brief Appends the next token to \p State and updates information
356 /// necessary for indentation.
357 ///
358 /// Puts the token on the current line if \p Newline is \c true and adds a
359 /// line break and necessary indentation otherwise.
360 ///
361 /// If \p DryRun is \c false, also creates and stores the required
362 /// \c Replacement.
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000363 void addTokenToState(bool Newline, bool DryRun, LineState &State) {
Daniel Jasper9c837d02013-01-09 07:06:56 +0000364 const AnnotatedToken &Current = *State.NextToken;
365 const AnnotatedToken &Previous = *State.NextToken->Parent;
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000366 assert(State.Stack.size());
367 unsigned ParenLevel = State.Stack.size() - 1;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000368
369 if (Newline) {
Manuel Klimek060143e2013-01-02 18:33:23 +0000370 unsigned WhitespaceStartColumn = State.Column;
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000371 if (Current.is(tok::r_brace)) {
372 State.Column = Line.Level * 2;
Daniel Jasper9c837d02013-01-09 07:06:56 +0000373 } else if (Current.is(tok::string_literal) &&
374 Previous.is(tok::string_literal)) {
375 State.Column = State.Column - Previous.FormatTok.TokenLength;
376 } else if (Current.is(tok::lessless) &&
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000377 State.Stack[ParenLevel].FirstLessLess != 0) {
378 State.Column = State.Stack[ParenLevel].FirstLessLess;
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000379 } else if (ParenLevel != 0 &&
Daniel Jasper9c837d02013-01-09 07:06:56 +0000380 (Previous.is(tok::equal) || Current.is(tok::arrow) ||
381 Current.is(tok::period) || Previous.is(tok::question) ||
382 Previous.Type == TT_ConditionalExpr)) {
383 // Indent and extra 4 spaces after if we know the current expression is
384 // continued. Don't do that on the top level, as we already indent 4
385 // there.
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000386 State.Column = State.Stack[ParenLevel].Indent + 4;
Daniel Jasper9c837d02013-01-09 07:06:56 +0000387 } else if (RootToken.is(tok::kw_for) && Previous.is(tok::comma)) {
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000388 State.Column = State.ForLoopVariablePos;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000389 } else if (State.NextToken->Parent->ClosesTemplateDeclaration) {
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000390 State.Column = State.Stack[ParenLevel].Indent - 4;
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000391 } else {
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000392 State.Column = State.Stack[ParenLevel].Indent;
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000393 }
394
Manuel Klimek2851c162013-01-10 14:36:46 +0000395 // A line starting with a closing brace is assumed to be correct for the
396 // same level as before the opening brace.
397 State.StartOfLineLevel = ParenLevel + (Current.is(tok::r_brace) ? 0 : 1);
Daniel Jaspera4974cf2012-12-24 16:43:00 +0000398
Daniel Jasper26f7e782013-01-08 14:56:18 +0000399 if (RootToken.is(tok::kw_for))
Daniel Jasper9c837d02013-01-09 07:06:56 +0000400 State.LineContainsContinuedForLoopSection = Previous.isNot(tok::semi);
Daniel Jasper20409152012-12-04 14:54:30 +0000401
Manuel Klimek060143e2013-01-02 18:33:23 +0000402 if (!DryRun) {
403 if (!Line.InPPDirective)
Manuel Klimek3f8c7f32013-01-10 18:45:26 +0000404 replaceWhitespace(Current.FormatTok, 1, State.Column, Style,
405 SourceMgr, Replaces);
Manuel Klimek060143e2013-01-02 18:33:23 +0000406 else
Daniel Jasper9c837d02013-01-09 07:06:56 +0000407 replacePPWhitespace(Current.FormatTok, 1, State.Column,
Manuel Klimek3f8c7f32013-01-10 18:45:26 +0000408 WhitespaceStartColumn, Style, SourceMgr,
409 Replaces);
Manuel Klimek060143e2013-01-02 18:33:23 +0000410 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000411
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000412 State.Stack[ParenLevel].LastSpace = State.Column;
Nico Weberf681fa82013-01-12 07:05:25 +0000413 if (Current.is(tok::colon) && State.NextToken->Type != TT_ConditionalExpr)
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000414 State.Stack[ParenLevel].Indent += 2;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000415 } else {
Daniel Jasper9c837d02013-01-09 07:06:56 +0000416 if (Current.is(tok::equal) && RootToken.is(tok::kw_for))
417 State.ForLoopVariablePos = State.Column -
418 Previous.FormatTok.TokenLength;
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000419
Daniel Jasper26f7e782013-01-08 14:56:18 +0000420 unsigned Spaces = State.NextToken->SpaceRequiredBefore ? 1 : 0;
421 if (State.NextToken->Type == TT_LineComment)
Daniel Jasper7ad4eff2013-01-07 11:09:06 +0000422 Spaces = Style.SpacesBeforeTrailingComments;
Daniel Jasper20409152012-12-04 14:54:30 +0000423
Daniel Jasperbac016b2012-12-03 18:12:45 +0000424 if (!DryRun)
Manuel Klimek3f8c7f32013-01-10 18:45:26 +0000425 replaceWhitespace(Current, 0, Spaces, Style, SourceMgr, Replaces);
Daniel Jasper20409152012-12-04 14:54:30 +0000426
Daniel Jasper3fc0bb72013-01-09 10:40:23 +0000427 // FIXME: Do we need to do this for assignments nested in other
428 // expressions?
429 if (RootToken.isNot(tok::kw_for) && ParenLevel == 0 &&
Daniel Jasper9cda8002013-01-07 13:08:40 +0000430 (getPrecedence(Previous) == prec::Assignment ||
Daniel Jasper9c837d02013-01-09 07:06:56 +0000431 Previous.is(tok::kw_return)))
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000432 State.Stack[ParenLevel].Indent = State.Column + Spaces;
Daniel Jasper7d19bc22013-01-11 14:23:32 +0000433 if (Previous.is(tok::l_paren) || Previous.is(tok::l_brace) ||
Daniel Jasper26f7e782013-01-08 14:56:18 +0000434 State.NextToken->Parent->Type == TT_TemplateOpener)
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000435 State.Stack[ParenLevel].Indent = State.Column + Spaces;
Daniel Jasper1321eb52012-12-18 21:05:13 +0000436
Daniel Jasper9cda8002013-01-07 13:08:40 +0000437 // Top-level spaces that are not part of assignments are exempt as that
438 // mostly leads to better results.
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000439 State.Column += Spaces;
Daniel Jasper9cda8002013-01-07 13:08:40 +0000440 if (Spaces > 0 &&
441 (ParenLevel != 0 || getPrecedence(Previous) == prec::Assignment))
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000442 State.Stack[ParenLevel].LastSpace = State.Column;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000443 }
Daniel Jasper20409152012-12-04 14:54:30 +0000444 moveStateToNextToken(State);
Manuel Klimekc8c8a472013-01-10 15:58:26 +0000445 if (Newline && Previous.is(tok::l_brace)) {
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000446 State.Stack.back().BreakBeforeClosingBrace = true;
Manuel Klimekc8c8a472013-01-10 15:58:26 +0000447 }
Daniel Jasper20409152012-12-04 14:54:30 +0000448 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000449
Daniel Jasper20409152012-12-04 14:54:30 +0000450 /// \brief Mark the next token as consumed in \p State and modify its stacks
451 /// accordingly.
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000452 void moveStateToNextToken(LineState &State) {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000453 const AnnotatedToken &Current = *State.NextToken;
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000454 assert(State.Stack.size());
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000455
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000456 if (Current.is(tok::lessless) && State.Stack.back().FirstLessLess == 0)
457 State.Stack.back().FirstLessLess = State.Column;
Daniel Jasper3b5943f2012-12-06 09:56:08 +0000458
Daniel Jaspercf225b62012-12-24 13:43:52 +0000459 // If we encounter an opening (, [, { or <, we add a level to our stacks to
Daniel Jasper20409152012-12-04 14:54:30 +0000460 // prepare for the following tokens.
Daniel Jasper26f7e782013-01-08 14:56:18 +0000461 if (Current.is(tok::l_paren) || Current.is(tok::l_square) ||
462 Current.is(tok::l_brace) ||
463 State.NextToken->Type == TT_TemplateOpener) {
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000464 unsigned NewIndent;
Manuel Klimek2851c162013-01-10 14:36:46 +0000465 if (Current.is(tok::l_brace)) {
466 // FIXME: This does not work with nested static initializers.
467 // Implement a better handling for static initializers and similar
468 // constructs.
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000469 NewIndent = Line.Level * 2 + 2;
Manuel Klimek2851c162013-01-10 14:36:46 +0000470 } else {
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000471 NewIndent = 4 + State.Stack.back().LastSpace;
Manuel Klimek2851c162013-01-10 14:36:46 +0000472 }
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000473 State.Stack.push_back(
Daniel Jasper7e9bf8c2013-01-11 11:37:55 +0000474 ParenState(NewIndent, State.Stack.back().LastSpace));
Daniel Jasper20409152012-12-04 14:54:30 +0000475 }
476
Daniel Jaspercf225b62012-12-24 13:43:52 +0000477 // If we encounter a closing ), ], } or >, we can remove a level from our
Daniel Jasper20409152012-12-04 14:54:30 +0000478 // stacks.
Daniel Jasper26f7e782013-01-08 14:56:18 +0000479 if (Current.is(tok::r_paren) || Current.is(tok::r_square) ||
480 (Current.is(tok::r_brace) && State.NextToken != &RootToken) ||
481 State.NextToken->Type == TT_TemplateCloser) {
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000482 State.Stack.pop_back();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000483 }
Manuel Klimek2851c162013-01-10 14:36:46 +0000484
Daniel Jasper26f7e782013-01-08 14:56:18 +0000485 if (State.NextToken->Children.empty())
486 State.NextToken = NULL;
487 else
488 State.NextToken = &State.NextToken->Children[0];
Manuel Klimek2851c162013-01-10 14:36:46 +0000489
490 State.Column += Current.FormatTok.TokenLength;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000491 }
492
Nico Weberdecf7bc2013-01-07 15:15:29 +0000493 /// \brief Calculate the penalty for splitting after the token at \p Index.
Daniel Jasper26f7e782013-01-08 14:56:18 +0000494 unsigned splitPenalty(const AnnotatedToken &Tok) {
495 const AnnotatedToken &Left = Tok;
496 const AnnotatedToken &Right = Tok.Children[0];
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000497
498 // In for-loops, prefer breaking at ',' and ';'.
Daniel Jasper26f7e782013-01-08 14:56:18 +0000499 if (RootToken.is(tok::kw_for) &&
500 (Left.isNot(tok::comma) && Left.isNot(tok::semi)))
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000501 return 20;
502
Daniel Jasper26f7e782013-01-08 14:56:18 +0000503 if (Left.is(tok::semi) || Left.is(tok::comma) ||
504 Left.ClosesTemplateDeclaration)
Daniel Jasperbac016b2012-12-03 18:12:45 +0000505 return 0;
Nico Webere8ccc812013-01-12 22:48:47 +0000506
507 // In Objective-C method expressions, prefer breaking before "param:" over
508 // breaking after it.
509 if (isObjCSelectorName(Right))
510 return 0;
511 if (Right.is(tok::colon) && Right.Type == TT_ObjCMethodExpr)
512 return 20;
513
Daniel Jasper26f7e782013-01-08 14:56:18 +0000514 if (Left.is(tok::l_paren))
Daniel Jasper723f0302013-01-02 14:40:02 +0000515 return 20;
Daniel Jasper9a0b4942012-12-17 14:34:14 +0000516
Daniel Jasper9c837d02013-01-09 07:06:56 +0000517 if (Left.is(tok::question) || Left.Type == TT_ConditionalExpr)
518 return prec::Assignment;
Daniel Jasper9cda8002013-01-07 13:08:40 +0000519 prec::Level Level = getPrecedence(Left);
520
521 // Breaking after an assignment leads to a bad result as the two sides of
522 // the assignment are visually very close together.
523 if (Level == prec::Assignment)
524 return 50;
525
Daniel Jaspere2c7acf2012-12-24 00:13:23 +0000526 if (Level != prec::Unknown)
527 return Level;
528
Daniel Jasper26f7e782013-01-08 14:56:18 +0000529 if (Right.is(tok::arrow) || Right.is(tok::period))
Daniel Jasper46a46a22013-01-07 07:13:20 +0000530 return 150;
Daniel Jasper9a0b4942012-12-17 14:34:14 +0000531
Daniel Jasperbac016b2012-12-03 18:12:45 +0000532 return 3;
533 }
534
Daniel Jasperceb99ab2013-01-09 10:16:05 +0000535 unsigned getColumnLimit() {
536 return Style.ColumnLimit - (Line.InPPDirective ? 1 : 0);
537 }
538
Daniel Jasperbac016b2012-12-03 18:12:45 +0000539 /// \brief Calculate the number of lines needed to format the remaining part
540 /// of the unwrapped line.
541 ///
542 /// Assumes the formatting so far has led to
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000543 /// the \c LineSta \p State. If \p NewLine is set, a new line will be
Daniel Jasperbac016b2012-12-03 18:12:45 +0000544 /// added after the previous token.
545 ///
546 /// \param StopAt is used for optimization. If we can determine that we'll
547 /// definitely need at least \p StopAt additional lines, we already know of a
548 /// better solution.
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000549 unsigned calcPenalty(LineState State, bool NewLine, unsigned StopAt) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000550 // We are at the end of the unwrapped line, so we don't need any more lines.
Daniel Jasper26f7e782013-01-08 14:56:18 +0000551 if (State.NextToken == NULL)
Daniel Jasperbac016b2012-12-03 18:12:45 +0000552 return 0;
553
Daniel Jasper26f7e782013-01-08 14:56:18 +0000554 if (!NewLine && State.NextToken->MustBreakBefore)
Daniel Jasperbac016b2012-12-03 18:12:45 +0000555 return UINT_MAX;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000556 if (NewLine && !State.NextToken->CanBreakBefore)
Daniel Jasperbac016b2012-12-03 18:12:45 +0000557 return UINT_MAX;
Manuel Klimekc8c8a472013-01-10 15:58:26 +0000558 if (!NewLine && State.NextToken->is(tok::r_brace) &&
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000559 State.Stack.back().BreakBeforeClosingBrace)
Manuel Klimekc8c8a472013-01-10 15:58:26 +0000560 return UINT_MAX;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000561 if (!NewLine && State.NextToken->Parent->is(tok::semi) &&
Daniel Jaspera324a0e2012-12-21 14:37:20 +0000562 State.LineContainsContinuedForLoopSection)
563 return UINT_MAX;
Daniel Jasper7e9bf8c2013-01-11 11:37:55 +0000564 if (!NewLine && State.NextToken->Parent->is(tok::comma) &&
565 State.NextToken->Type != TT_LineComment &&
566 State.Stack.back().BreakAfterComma)
567 return UINT_MAX;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000568
Daniel Jasper33182dd2012-12-05 14:57:28 +0000569 unsigned CurrentPenalty = 0;
570 if (NewLine) {
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000571 CurrentPenalty += Parameters.PenaltyIndentLevel * State.Stack.size() +
Daniel Jasper26f7e782013-01-08 14:56:18 +0000572 splitPenalty(*State.NextToken->Parent);
Daniel Jaspera4974cf2012-12-24 16:43:00 +0000573 } else {
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000574 if (State.Stack.size() < State.StartOfLineLevel)
Daniel Jaspera4974cf2012-12-24 16:43:00 +0000575 CurrentPenalty += Parameters.PenaltyLevelDecrease *
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000576 (State.StartOfLineLevel - State.Stack.size());
Daniel Jasper33182dd2012-12-05 14:57:28 +0000577 }
578
Daniel Jasper20409152012-12-04 14:54:30 +0000579 addTokenToState(NewLine, true, State);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000580
Daniel Jasperceb99ab2013-01-09 10:16:05 +0000581 // Exceeding column limit is bad, assign penalty.
582 if (State.Column > getColumnLimit()) {
583 unsigned ExcessCharacters = State.Column - getColumnLimit();
584 CurrentPenalty += Parameters.PenaltyExcessCharacter * ExcessCharacters;
585 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000586
Daniel Jasperbac016b2012-12-03 18:12:45 +0000587 if (StopAt <= CurrentPenalty)
588 return UINT_MAX;
589 StopAt -= CurrentPenalty;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000590 StateMap::iterator I = Memory.find(State);
Daniel Jasper33182dd2012-12-05 14:57:28 +0000591 if (I != Memory.end()) {
592 // If this state has already been examined, we can safely return the
593 // previous result if we
594 // - have not hit the optimatization (and thus returned UINT_MAX) OR
595 // - are now computing for a smaller or equal StopAt.
596 unsigned SavedResult = I->second.first;
597 unsigned SavedStopAt = I->second.second;
Daniel Jasper9a0b4942012-12-17 14:34:14 +0000598 if (SavedResult != UINT_MAX)
599 return SavedResult + CurrentPenalty;
600 else if (StopAt <= SavedStopAt)
601 return UINT_MAX;
Daniel Jasper33182dd2012-12-05 14:57:28 +0000602 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000603
604 unsigned NoBreak = calcPenalty(State, false, StopAt);
605 unsigned WithBreak = calcPenalty(State, true, std::min(StopAt, NoBreak));
606 unsigned Result = std::min(NoBreak, WithBreak);
Daniel Jasper9a0b4942012-12-17 14:34:14 +0000607
608 // We have to store 'Result' without adding 'CurrentPenalty' as the latter
609 // can depend on 'NewLine'.
Daniel Jasper33182dd2012-12-05 14:57:28 +0000610 Memory[State] = std::pair<unsigned, unsigned>(Result, StopAt);
Daniel Jasper9a0b4942012-12-17 14:34:14 +0000611
612 return Result == UINT_MAX ? UINT_MAX : Result + CurrentPenalty;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000613 }
614
Daniel Jasperbac016b2012-12-03 18:12:45 +0000615 FormatStyle Style;
616 SourceManager &SourceMgr;
Daniel Jasper995e8202013-01-14 13:08:07 +0000617 const AnnotatedLine &Line;
Manuel Klimek3f8c7f32013-01-10 18:45:26 +0000618 const unsigned FirstIndent;
Manuel Klimek94fc6f12013-01-10 19:17:33 +0000619 const bool FitsOnALine;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000620 const AnnotatedToken &RootToken;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000621 tooling::Replacements &Replaces;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000622
Daniel Jasper33182dd2012-12-05 14:57:28 +0000623 // A map from an indent state to a pair (Result, Used-StopAt).
Daniel Jasper604eb4c2013-01-11 10:22:12 +0000624 typedef std::map<LineState, std::pair<unsigned, unsigned> > StateMap;
Daniel Jasper33182dd2012-12-05 14:57:28 +0000625 StateMap Memory;
626
Daniel Jasperbac016b2012-12-03 18:12:45 +0000627 OptimizationParameters Parameters;
628};
629
630/// \brief Determines extra information about the tokens comprising an
631/// \c UnwrappedLine.
632class TokenAnnotator {
633public:
Daniel Jasper995e8202013-01-14 13:08:07 +0000634 TokenAnnotator(const FormatStyle &Style, SourceManager &SourceMgr, Lexer &Lex,
635 AnnotatedLine &Line)
636 : Style(Style), SourceMgr(SourceMgr), Lex(Lex), Line(Line) {}
Daniel Jasperbac016b2012-12-03 18:12:45 +0000637
638 /// \brief A parser that gathers additional information about tokens.
639 ///
640 /// The \c TokenAnnotator tries to matches parenthesis and square brakets and
641 /// store a parenthesis levels. It also tries to resolve matching "<" and ">"
642 /// into template parameter lists.
643 class AnnotatingParser {
644 public:
Daniel Jasper26f7e782013-01-08 14:56:18 +0000645 AnnotatingParser(AnnotatedToken &RootToken)
Nico Weberbcfdd262013-01-12 06:18:40 +0000646 : CurrentToken(&RootToken), KeywordVirtualFound(false),
647 ColonIsObjCMethodExpr(false) {}
Daniel Jasperbac016b2012-12-03 18:12:45 +0000648
Daniel Jasper20409152012-12-04 14:54:30 +0000649 bool parseAngle() {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000650 while (CurrentToken != NULL) {
651 if (CurrentToken->is(tok::greater)) {
652 CurrentToken->Type = TT_TemplateCloser;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000653 next();
654 return true;
655 }
Daniel Jasper26f7e782013-01-08 14:56:18 +0000656 if (CurrentToken->is(tok::r_paren) || CurrentToken->is(tok::r_square) ||
657 CurrentToken->is(tok::r_brace))
Daniel Jasperbac016b2012-12-03 18:12:45 +0000658 return false;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000659 if (CurrentToken->is(tok::pipepipe) || CurrentToken->is(tok::ampamp) ||
660 CurrentToken->is(tok::question) || CurrentToken->is(tok::colon))
Daniel Jasperbac016b2012-12-03 18:12:45 +0000661 return false;
Daniel Jasper1f42f112013-01-04 18:52:56 +0000662 if (!consumeToken())
663 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000664 }
665 return false;
666 }
667
Daniel Jasper20409152012-12-04 14:54:30 +0000668 bool parseParens() {
Daniel Jasper46ef8522013-01-10 13:08:12 +0000669 if (CurrentToken != NULL && CurrentToken->is(tok::caret))
670 CurrentToken->Parent->Type = TT_ObjCBlockLParen;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000671 while (CurrentToken != NULL) {
672 if (CurrentToken->is(tok::r_paren)) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000673 next();
674 return true;
675 }
Daniel Jasper26f7e782013-01-08 14:56:18 +0000676 if (CurrentToken->is(tok::r_square) || CurrentToken->is(tok::r_brace))
Daniel Jasperbac016b2012-12-03 18:12:45 +0000677 return false;
Daniel Jasper1f42f112013-01-04 18:52:56 +0000678 if (!consumeToken())
679 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000680 }
681 return false;
682 }
683
Daniel Jasper20409152012-12-04 14:54:30 +0000684 bool parseSquare() {
Nico Weberbcfdd262013-01-12 06:18:40 +0000685 if (!CurrentToken)
686 return false;
687
688 // A '[' could be an index subscript (after an indentifier or after
689 // ')' or ']'), or it could be the start of an Objective-C method
690 // expression.
691 AnnotatedToken *LSquare = CurrentToken->Parent;
692 bool StartsObjCMethodExpr =
693 !LSquare->Parent || LSquare->Parent->is(tok::colon) ||
694 LSquare->Parent->is(tok::l_square) ||
695 LSquare->Parent->is(tok::l_paren) ||
696 LSquare->Parent->is(tok::kw_return) ||
697 LSquare->Parent->is(tok::kw_throw) ||
698 getBinOpPrecedence(LSquare->Parent->FormatTok.Tok.getKind(),
699 true, true) > prec::Unknown;
700
701 bool ColonWasObjCMethodExpr = ColonIsObjCMethodExpr;
702 if (StartsObjCMethodExpr) {
703 ColonIsObjCMethodExpr = true;
704 LSquare->Type = TT_ObjCMethodExpr;
705 }
706
Daniel Jasper26f7e782013-01-08 14:56:18 +0000707 while (CurrentToken != NULL) {
708 if (CurrentToken->is(tok::r_square)) {
Nico Weberbcfdd262013-01-12 06:18:40 +0000709 if (StartsObjCMethodExpr) {
710 ColonIsObjCMethodExpr = ColonWasObjCMethodExpr;
711 CurrentToken->Type = TT_ObjCMethodExpr;
712 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000713 next();
714 return true;
715 }
Daniel Jasper26f7e782013-01-08 14:56:18 +0000716 if (CurrentToken->is(tok::r_paren) || CurrentToken->is(tok::r_brace))
Daniel Jasperbac016b2012-12-03 18:12:45 +0000717 return false;
Daniel Jasper1f42f112013-01-04 18:52:56 +0000718 if (!consumeToken())
719 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000720 }
721 return false;
722 }
723
Daniel Jasper700e7102013-01-10 09:26:47 +0000724 bool parseBrace() {
725 while (CurrentToken != NULL) {
726 if (CurrentToken->is(tok::r_brace)) {
727 next();
728 return true;
729 }
730 if (CurrentToken->is(tok::r_paren) || CurrentToken->is(tok::r_square))
731 return false;
732 if (!consumeToken())
733 return false;
734 }
735 // Lines can currently end with '{'.
736 return true;
737 }
738
Daniel Jasper20409152012-12-04 14:54:30 +0000739 bool parseConditional() {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000740 while (CurrentToken != NULL) {
741 if (CurrentToken->is(tok::colon)) {
742 CurrentToken->Type = TT_ConditionalExpr;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000743 next();
744 return true;
745 }
Daniel Jasper1f42f112013-01-04 18:52:56 +0000746 if (!consumeToken())
747 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000748 }
749 return false;
750 }
751
Daniel Jasper9a64fb52013-01-02 15:08:56 +0000752 bool parseTemplateDeclaration() {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000753 if (CurrentToken != NULL && CurrentToken->is(tok::less)) {
754 CurrentToken->Type = TT_TemplateOpener;
Daniel Jasper9a64fb52013-01-02 15:08:56 +0000755 next();
756 if (!parseAngle())
757 return false;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000758 CurrentToken->Parent->ClosesTemplateDeclaration = true;
Daniel Jasper9a64fb52013-01-02 15:08:56 +0000759 parseLine();
760 return true;
761 }
762 return false;
763 }
764
Daniel Jasper1f42f112013-01-04 18:52:56 +0000765 bool consumeToken() {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000766 AnnotatedToken *Tok = CurrentToken;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000767 next();
Daniel Jasper26f7e782013-01-08 14:56:18 +0000768 switch (Tok->FormatTok.Tok.getKind()) {
Nico Webercd52bda2013-01-10 23:11:41 +0000769 case tok::plus:
770 case tok::minus:
771 // At the start of the line, +/- specific ObjectiveC method
772 // declarations.
773 if (Tok->Parent == NULL)
774 Tok->Type = TT_ObjCMethodSpecifier;
775 break;
Nico Weberbcfdd262013-01-12 06:18:40 +0000776 case tok::colon:
777 // Colons from ?: are handled in parseConditional().
778 if (ColonIsObjCMethodExpr)
779 Tok->Type = TT_ObjCMethodExpr;
780 break;
Nico Webercd52bda2013-01-10 23:11:41 +0000781 case tok::l_paren: {
Daniel Jasperfeb18f52013-01-14 14:14:23 +0000782 bool ParensWereObjCReturnType = Tok->Parent && Tok->Parent->Type ==
783 TT_ObjCMethodSpecifier;
Daniel Jasper1f42f112013-01-04 18:52:56 +0000784 if (!parseParens())
785 return false;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000786 if (CurrentToken != NULL && CurrentToken->is(tok::colon)) {
787 CurrentToken->Type = TT_CtorInitializerColon;
Daniel Jasper1321eb52012-12-18 21:05:13 +0000788 next();
Nico Webercd52bda2013-01-10 23:11:41 +0000789 } else if (CurrentToken != NULL && ParensWereObjCReturnType) {
790 CurrentToken->Type = TT_ObjCSelectorStart;
791 next();
Daniel Jasper1321eb52012-12-18 21:05:13 +0000792 }
Nico Webercd52bda2013-01-10 23:11:41 +0000793 } break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000794 case tok::l_square:
Daniel Jasper1f42f112013-01-04 18:52:56 +0000795 if (!parseSquare())
796 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000797 break;
Daniel Jasper700e7102013-01-10 09:26:47 +0000798 case tok::l_brace:
799 if (!parseBrace())
800 return false;
801 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000802 case tok::less:
Daniel Jasper20409152012-12-04 14:54:30 +0000803 if (parseAngle())
Daniel Jasper26f7e782013-01-08 14:56:18 +0000804 Tok->Type = TT_TemplateOpener;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000805 else {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000806 Tok->Type = TT_BinaryOperator;
807 CurrentToken = Tok;
808 next();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000809 }
810 break;
Daniel Jasper1f42f112013-01-04 18:52:56 +0000811 case tok::r_paren:
812 case tok::r_square:
813 return false;
Daniel Jasper700e7102013-01-10 09:26:47 +0000814 case tok::r_brace:
815 // Lines can start with '}'.
816 if (Tok->Parent != NULL)
817 return false;
818 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000819 case tok::greater:
Daniel Jasper26f7e782013-01-08 14:56:18 +0000820 Tok->Type = TT_BinaryOperator;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000821 break;
822 case tok::kw_operator:
Daniel Jasper26f7e782013-01-08 14:56:18 +0000823 if (CurrentToken->is(tok::l_paren)) {
824 CurrentToken->Type = TT_OverloadedOperator;
Daniel Jasperf6aef6a2012-12-24 10:56:04 +0000825 next();
Daniel Jasper26f7e782013-01-08 14:56:18 +0000826 if (CurrentToken != NULL && CurrentToken->is(tok::r_paren)) {
827 CurrentToken->Type = TT_OverloadedOperator;
Daniel Jasperf6aef6a2012-12-24 10:56:04 +0000828 next();
829 }
830 } else {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000831 while (CurrentToken != NULL && CurrentToken->isNot(tok::l_paren)) {
832 CurrentToken->Type = TT_OverloadedOperator;
Daniel Jasperf6aef6a2012-12-24 10:56:04 +0000833 next();
834 }
835 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000836 break;
837 case tok::question:
Daniel Jasper20409152012-12-04 14:54:30 +0000838 parseConditional();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000839 break;
Daniel Jasper9a64fb52013-01-02 15:08:56 +0000840 case tok::kw_template:
841 parseTemplateDeclaration();
842 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000843 default:
844 break;
845 }
Daniel Jasper1f42f112013-01-04 18:52:56 +0000846 return true;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000847 }
848
Daniel Jaspercd1a32b2012-12-21 17:58:39 +0000849 void parseIncludeDirective() {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000850 while (CurrentToken != NULL) {
Daniel Jasper8134e1e2013-01-13 08:12:18 +0000851 CurrentToken->Type = TT_IncludePath;
Daniel Jaspercd1a32b2012-12-21 17:58:39 +0000852 next();
853 }
854 }
855
856 void parsePreprocessorDirective() {
857 next();
Daniel Jasper26f7e782013-01-08 14:56:18 +0000858 if (CurrentToken == NULL)
Daniel Jaspercd1a32b2012-12-21 17:58:39 +0000859 return;
Manuel Klimekf6fd00b2013-01-05 22:56:06 +0000860 // Hashes in the middle of a line can lead to any strange token
861 // sequence.
Daniel Jasper26f7e782013-01-08 14:56:18 +0000862 if (CurrentToken->FormatTok.Tok.getIdentifierInfo() == NULL)
Manuel Klimekf6fd00b2013-01-05 22:56:06 +0000863 return;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000864 switch (
865 CurrentToken->FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
Daniel Jaspercd1a32b2012-12-21 17:58:39 +0000866 case tok::pp_include:
Nico Weberb23ae0c2012-12-21 18:21:56 +0000867 case tok::pp_import:
Daniel Jaspercd1a32b2012-12-21 17:58:39 +0000868 parseIncludeDirective();
869 break;
870 default:
871 break;
872 }
873 }
874
Daniel Jasper71607512013-01-07 10:48:50 +0000875 LineType parseLine() {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000876 if (CurrentToken->is(tok::hash)) {
Daniel Jaspercd1a32b2012-12-21 17:58:39 +0000877 parsePreprocessorDirective();
Daniel Jasper71607512013-01-07 10:48:50 +0000878 return LT_PreprocessorDirective;
Daniel Jaspercd1a32b2012-12-21 17:58:39 +0000879 }
Daniel Jasper26f7e782013-01-08 14:56:18 +0000880 while (CurrentToken != NULL) {
881 if (CurrentToken->is(tok::kw_virtual))
Daniel Jasper71607512013-01-07 10:48:50 +0000882 KeywordVirtualFound = true;
Daniel Jasper1f42f112013-01-04 18:52:56 +0000883 if (!consumeToken())
Daniel Jasper71607512013-01-07 10:48:50 +0000884 return LT_Invalid;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000885 }
Daniel Jasper71607512013-01-07 10:48:50 +0000886 if (KeywordVirtualFound)
887 return LT_VirtualFunctionDecl;
888 return LT_Other;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000889 }
890
891 void next() {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000892 if (CurrentToken != NULL && !CurrentToken->Children.empty())
893 CurrentToken = &CurrentToken->Children[0];
894 else
895 CurrentToken = NULL;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000896 }
897
898 private:
Daniel Jasper26f7e782013-01-08 14:56:18 +0000899 AnnotatedToken *CurrentToken;
Daniel Jasper71607512013-01-07 10:48:50 +0000900 bool KeywordVirtualFound;
Nico Weberbcfdd262013-01-12 06:18:40 +0000901 bool ColonIsObjCMethodExpr;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000902 };
903
Daniel Jasper26f7e782013-01-08 14:56:18 +0000904 void createAnnotatedTokens(AnnotatedToken &Current) {
Daniel Jasper995e8202013-01-14 13:08:07 +0000905 if (Current.FormatTok.Children.empty()) {
906 Line.Last = &Current;
907 } else {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000908 Current.Children.push_back(AnnotatedToken(Current.FormatTok.Children[0]));
909 Current.Children.back().Parent = &Current;
910 createAnnotatedTokens(Current.Children.back());
911 }
912 }
Daniel Jasper71607512013-01-07 10:48:50 +0000913
Daniel Jasper26f7e782013-01-08 14:56:18 +0000914 void calculateExtraInformation(AnnotatedToken &Current) {
915 Current.SpaceRequiredBefore = spaceRequiredBefore(Current);
916
Manuel Klimek526ed112013-01-09 15:25:02 +0000917 if (Current.FormatTok.MustBreakBefore) {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000918 Current.MustBreakBefore = true;
919 } else {
Daniel Jasper487f64b2013-01-13 16:10:20 +0000920 if (Current.Type == TT_LineComment) {
921 Current.MustBreakBefore = Current.FormatTok.NewlinesBefore > 0;
922 } else if (Current.Type == TT_CtorInitializerColon ||
923 Current.Parent->Type == TT_LineComment ||
924 (Current.is(tok::string_literal) &&
925 Current.Parent->is(tok::string_literal))) {
Manuel Klimek526ed112013-01-09 15:25:02 +0000926 Current.MustBreakBefore = true;
Manuel Klimek526ed112013-01-09 15:25:02 +0000927 } else {
928 Current.MustBreakBefore = false;
929 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000930 }
Daniel Jasper26f7e782013-01-08 14:56:18 +0000931 Current.CanBreakBefore = Current.MustBreakBefore || canBreakBefore(Current);
Daniel Jasper26f7e782013-01-08 14:56:18 +0000932 if (!Current.Children.empty())
933 calculateExtraInformation(Current.Children[0]);
934 }
935
Daniel Jasper995e8202013-01-14 13:08:07 +0000936 void annotate() {
937 Line.Last = &Line.First;
938 createAnnotatedTokens(Line.First);
Daniel Jasper26f7e782013-01-08 14:56:18 +0000939
Daniel Jasper995e8202013-01-14 13:08:07 +0000940 AnnotatingParser Parser(Line.First);
941 Line.Type = Parser.parseLine();
942 if (Line.Type == LT_Invalid)
943 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000944
Daniel Jasper995e8202013-01-14 13:08:07 +0000945 determineTokenTypes(Line.First, /*IsRHS=*/false);
Daniel Jasper71607512013-01-07 10:48:50 +0000946
Daniel Jasper995e8202013-01-14 13:08:07 +0000947 if (Line.First.Type == TT_ObjCMethodSpecifier)
948 Line.Type = LT_ObjCMethodDecl;
949 else if (Line.First.Type == TT_ObjCDecl)
950 Line.Type = LT_ObjCDecl;
951 else if (Line.First.Type == TT_ObjCProperty)
952 Line.Type = LT_ObjCProperty;
Daniel Jasper71607512013-01-07 10:48:50 +0000953
Daniel Jasper995e8202013-01-14 13:08:07 +0000954 Line.First.SpaceRequiredBefore = true;
955 Line.First.MustBreakBefore = Line.First.FormatTok.MustBreakBefore;
956 Line.First.CanBreakBefore = Line.First.MustBreakBefore;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000957
Daniel Jasper995e8202013-01-14 13:08:07 +0000958 if (!Line.First.Children.empty())
959 calculateExtraInformation(Line.First.Children[0]);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000960 }
961
962private:
Daniel Jasper26f7e782013-01-08 14:56:18 +0000963 void determineTokenTypes(AnnotatedToken &Current, bool IsRHS) {
964 if (getPrecedence(Current) == prec::Assignment ||
965 Current.is(tok::kw_return) || Current.is(tok::kw_throw))
966 IsRHS = true;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000967
Daniel Jasper26f7e782013-01-08 14:56:18 +0000968 if (Current.Type == TT_Unknown) {
969 if (Current.is(tok::star) || Current.is(tok::amp)) {
970 Current.Type = determineStarAmpUsage(Current, IsRHS);
Daniel Jasper886568d2013-01-09 08:36:49 +0000971 } else if (Current.is(tok::minus) || Current.is(tok::plus) ||
972 Current.is(tok::caret)) {
973 Current.Type = determinePlusMinusCaretUsage(Current);
Daniel Jasper26f7e782013-01-08 14:56:18 +0000974 } else if (Current.is(tok::minusminus) || Current.is(tok::plusplus)) {
975 Current.Type = determineIncrementUsage(Current);
976 } else if (Current.is(tok::exclaim)) {
977 Current.Type = TT_UnaryOperator;
978 } else if (isBinaryOperator(Current)) {
979 Current.Type = TT_BinaryOperator;
980 } else if (Current.is(tok::comment)) {
981 std::string Data(Lexer::getSpelling(Current.FormatTok.Tok, SourceMgr,
982 Lex.getLangOpts()));
Manuel Klimek6cf58142013-01-07 08:54:53 +0000983 if (StringRef(Data).startswith("//"))
Daniel Jasper26f7e782013-01-08 14:56:18 +0000984 Current.Type = TT_LineComment;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000985 else
Daniel Jasper26f7e782013-01-08 14:56:18 +0000986 Current.Type = TT_BlockComment;
Daniel Jasper5cf7cf32013-01-10 11:14:08 +0000987 } else if (Current.is(tok::r_paren) &&
988 (Current.Parent->Type == TT_PointerOrReference ||
Daniel Jasper4981bd02013-01-13 08:01:36 +0000989 Current.Parent->Type == TT_TemplateCloser) &&
990 (Current.Children.empty() ||
991 (Current.Children[0].isNot(tok::equal) &&
992 Current.Children[0].isNot(tok::semi) &&
993 Current.Children[0].isNot(tok::l_brace)))) {
Daniel Jasper5cf7cf32013-01-10 11:14:08 +0000994 // FIXME: We need to get smarter and understand more cases of casts.
995 Current.Type = TT_CastRParen;
Nico Webered91bba2013-01-10 19:19:14 +0000996 } else if (Current.is(tok::at) && Current.Children.size()) {
997 switch (Current.Children[0].FormatTok.Tok.getObjCKeywordID()) {
998 case tok::objc_interface:
999 case tok::objc_implementation:
1000 case tok::objc_protocol:
1001 Current.Type = TT_ObjCDecl;
Nico Weber70848232013-01-10 21:30:42 +00001002 break;
1003 case tok::objc_property:
1004 Current.Type = TT_ObjCProperty;
1005 break;
Nico Webered91bba2013-01-10 19:19:14 +00001006 default:
1007 break;
1008 }
Daniel Jasperbac016b2012-12-03 18:12:45 +00001009 }
1010 }
Daniel Jasper26f7e782013-01-08 14:56:18 +00001011
1012 if (!Current.Children.empty())
1013 determineTokenTypes(Current.Children[0], IsRHS);
Daniel Jasperbac016b2012-12-03 18:12:45 +00001014 }
1015
Daniel Jasper26f7e782013-01-08 14:56:18 +00001016 bool isBinaryOperator(const AnnotatedToken &Tok) {
Daniel Jaspercd1a32b2012-12-21 17:58:39 +00001017 // Comma is a binary operator, but does not behave as such wrt. formatting.
Daniel Jaspercf225b62012-12-24 13:43:52 +00001018 return getPrecedence(Tok) > prec::Comma;
Daniel Jasperbac016b2012-12-03 18:12:45 +00001019 }
1020
Daniel Jasper26f7e782013-01-08 14:56:18 +00001021 TokenType determineStarAmpUsage(const AnnotatedToken &Tok, bool IsRHS) {
1022 if (Tok.Parent == NULL)
Daniel Jasper71607512013-01-07 10:48:50 +00001023 return TT_UnaryOperator;
Daniel Jasper26f7e782013-01-08 14:56:18 +00001024 if (Tok.Children.size() == 0)
Daniel Jasper71607512013-01-07 10:48:50 +00001025 return TT_Unknown;
Daniel Jasper26f7e782013-01-08 14:56:18 +00001026 const FormatToken &PrevToken = Tok.Parent->FormatTok;
1027 const FormatToken &NextToken = Tok.Children[0].FormatTok;
Daniel Jasperbac016b2012-12-03 18:12:45 +00001028
Daniel Jasper9bb0d282013-01-04 20:46:38 +00001029 if (PrevToken.Tok.is(tok::l_paren) || PrevToken.Tok.is(tok::l_square) ||
1030 PrevToken.Tok.is(tok::comma) || PrevToken.Tok.is(tok::kw_return) ||
Daniel Jasper5cf7cf32013-01-10 11:14:08 +00001031 PrevToken.Tok.is(tok::colon) || Tok.Parent->Type == TT_BinaryOperator ||
1032 Tok.Parent->Type == TT_CastRParen)
Daniel Jasper71607512013-01-07 10:48:50 +00001033 return TT_UnaryOperator;
Daniel Jasperbac016b2012-12-03 18:12:45 +00001034
Nico Weber2355ceb2013-01-12 05:47:16 +00001035 if (PrevToken.Tok.isLiteral() || PrevToken.Tok.is(tok::r_paren) ||
1036 PrevToken.Tok.is(tok::r_square) || NextToken.Tok.isLiteral() ||
Daniel Jasperba3d3072013-01-02 17:21:36 +00001037 NextToken.Tok.is(tok::plus) || NextToken.Tok.is(tok::minus) ||
1038 NextToken.Tok.is(tok::plusplus) || NextToken.Tok.is(tok::minusminus) ||
1039 NextToken.Tok.is(tok::tilde) || NextToken.Tok.is(tok::exclaim) ||
Nico Weber5e9f91c2013-01-12 05:50:48 +00001040 NextToken.Tok.is(tok::l_paren) || NextToken.Tok.is(tok::l_square) ||
Daniel Jasperba3d3072013-01-02 17:21:36 +00001041 NextToken.Tok.is(tok::kw_alignof) || NextToken.Tok.is(tok::kw_sizeof))
Daniel Jasper71607512013-01-07 10:48:50 +00001042 return TT_BinaryOperator;
Daniel Jasperbac016b2012-12-03 18:12:45 +00001043
Daniel Jasperef5b9c32013-01-02 15:46:59 +00001044 if (NextToken.Tok.is(tok::comma) || NextToken.Tok.is(tok::r_paren) ||
1045 NextToken.Tok.is(tok::greater))
Daniel Jasper71607512013-01-07 10:48:50 +00001046 return TT_PointerOrReference;
Daniel Jasperef5b9c32013-01-02 15:46:59 +00001047
Daniel Jasper112fb272012-12-05 07:51:39 +00001048 // It is very unlikely that we are going to find a pointer or reference type
1049 // definition on the RHS of an assignment.
Nico Weber00d5a042012-12-23 01:07:46 +00001050 if (IsRHS)
Daniel Jasper71607512013-01-07 10:48:50 +00001051 return TT_BinaryOperator;
Daniel Jasper112fb272012-12-05 07:51:39 +00001052
Daniel Jasper71607512013-01-07 10:48:50 +00001053 return TT_PointerOrReference;
Daniel Jasperbac016b2012-12-03 18:12:45 +00001054 }
1055
Daniel Jasper886568d2013-01-09 08:36:49 +00001056 TokenType determinePlusMinusCaretUsage(const AnnotatedToken &Tok) {
Daniel Jasper98e6b4a2012-12-21 09:41:31 +00001057 // Use heuristics to recognize unary operators.
Daniel Jasper26f7e782013-01-08 14:56:18 +00001058 if (Tok.Parent->is(tok::equal) || Tok.Parent->is(tok::l_paren) ||
1059 Tok.Parent->is(tok::comma) || Tok.Parent->is(tok::l_square) ||
1060 Tok.Parent->is(tok::question) || Tok.Parent->is(tok::colon) ||
Nico Weber81ed2f12013-01-10 19:36:35 +00001061 Tok.Parent->is(tok::kw_return) || Tok.Parent->is(tok::kw_case) ||
Nico Webercc191d12013-01-12 05:41:23 +00001062 Tok.Parent->is(tok::at) || Tok.Parent->is(tok::l_brace))
Daniel Jasper71607512013-01-07 10:48:50 +00001063 return TT_UnaryOperator;
Daniel Jasper98e6b4a2012-12-21 09:41:31 +00001064
1065 // There can't be to consecutive binary operators.
Daniel Jasper26f7e782013-01-08 14:56:18 +00001066 if (Tok.Parent->Type == TT_BinaryOperator)
Daniel Jasper71607512013-01-07 10:48:50 +00001067 return TT_UnaryOperator;
Daniel Jasper98e6b4a2012-12-21 09:41:31 +00001068
1069 // Fall back to marking the token as binary operator.
Daniel Jasper71607512013-01-07 10:48:50 +00001070 return TT_BinaryOperator;
Daniel Jasper98e6b4a2012-12-21 09:41:31 +00001071 }
1072
1073 /// \brief Determine whether ++/-- are pre- or post-increments/-decrements.
Daniel Jasper26f7e782013-01-08 14:56:18 +00001074 TokenType determineIncrementUsage(const AnnotatedToken &Tok) {
Daniel Jasper4abbb532013-01-14 12:18:19 +00001075 if (Tok.Parent == NULL)
1076 return TT_UnaryOperator;
1077 if (Tok.Parent->is(tok::r_paren) || Tok.Parent->is(tok::r_square) ||
1078 Tok.Parent->is(tok::identifier))
Daniel Jasper71607512013-01-07 10:48:50 +00001079 return TT_TrailingUnaryOperator;
Daniel Jasper98e6b4a2012-12-21 09:41:31 +00001080
Daniel Jasper71607512013-01-07 10:48:50 +00001081 return TT_UnaryOperator;
Daniel Jasperbac016b2012-12-03 18:12:45 +00001082 }
1083
Daniel Jasper26f7e782013-01-08 14:56:18 +00001084 bool spaceRequiredBetween(const AnnotatedToken &Left,
1085 const AnnotatedToken &Right) {
Daniel Jasper765561f2013-01-08 16:17:54 +00001086 if (Right.is(tok::hashhash))
1087 return Left.is(tok::hash);
1088 if (Left.is(tok::hashhash) || Left.is(tok::hash))
1089 return Right.is(tok::hash);
Daniel Jasper8b39c662012-12-10 18:59:13 +00001090 if (Right.is(tok::r_paren) || Right.is(tok::semi) || Right.is(tok::comma))
1091 return false;
Nico Weber5f500df2013-01-10 20:12:55 +00001092 if (Right.is(tok::less) &&
1093 (Left.is(tok::kw_template) ||
Daniel Jasper995e8202013-01-14 13:08:07 +00001094 (Line.Type == LT_ObjCDecl && Style.ObjCSpaceBeforeProtocolList)))
Daniel Jasperbac016b2012-12-03 18:12:45 +00001095 return true;
1096 if (Left.is(tok::arrow) || Right.is(tok::arrow))
1097 return false;
1098 if (Left.is(tok::exclaim) || Left.is(tok::tilde))
1099 return false;
Nico Webercb4d6902013-01-08 19:40:21 +00001100 if (Left.is(tok::at) &&
1101 (Right.is(tok::identifier) || Right.is(tok::string_literal) ||
1102 Right.is(tok::char_constant) || Right.is(tok::numeric_constant) ||
Daniel Jasper46ef8522013-01-10 13:08:12 +00001103 Right.is(tok::l_paren) || Right.is(tok::l_brace) ||
1104 Right.is(tok::kw_true) || Right.is(tok::kw_false)))
Fariborz Jahanian154120c2012-12-20 19:54:13 +00001105 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +00001106 if (Left.is(tok::less) || Right.is(tok::greater) || Right.is(tok::less))
1107 return false;
Daniel Jasperc74e2792012-12-07 09:52:15 +00001108 if (Right.is(tok::amp) || Right.is(tok::star))
Daniel Jasper26f7e782013-01-08 14:56:18 +00001109 return Left.FormatTok.Tok.isLiteral() ||
Daniel Jasperd7610b82012-12-24 16:51:15 +00001110 (Left.isNot(tok::star) && Left.isNot(tok::amp) &&
1111 !Style.PointerAndReferenceBindToType);
Daniel Jasperbac016b2012-12-03 18:12:45 +00001112 if (Left.is(tok::amp) || Left.is(tok::star))
Daniel Jasper26f7e782013-01-08 14:56:18 +00001113 return Right.FormatTok.Tok.isLiteral() ||
1114 Style.PointerAndReferenceBindToType;
Daniel Jasperbac016b2012-12-03 18:12:45 +00001115 if (Right.is(tok::star) && Left.is(tok::l_paren))
1116 return false;
Nico Weberbcfdd262013-01-12 06:18:40 +00001117 if (Left.is(tok::l_square) || Right.is(tok::r_square))
1118 return false;
1119 if (Right.is(tok::l_square) && Right.Type != TT_ObjCMethodExpr)
Daniel Jasperbac016b2012-12-03 18:12:45 +00001120 return false;
Daniel Jasperc74e2792012-12-07 09:52:15 +00001121 if (Left.is(tok::coloncolon) ||
1122 (Right.is(tok::coloncolon) &&
1123 (Left.is(tok::identifier) || Left.is(tok::greater))))
Daniel Jasperbac016b2012-12-03 18:12:45 +00001124 return false;
1125 if (Left.is(tok::period) || Right.is(tok::period))
1126 return false;
Nico Weberbcfdd262013-01-12 06:18:40 +00001127 if (Left.is(tok::colon))
1128 return Left.Type != TT_ObjCMethodExpr;
1129 if (Right.is(tok::colon))
1130 return Right.Type != TT_ObjCMethodExpr;
Daniel Jasperbac016b2012-12-03 18:12:45 +00001131 if (Left.is(tok::l_paren))
1132 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +00001133 if (Right.is(tok::l_paren)) {
Daniel Jasper995e8202013-01-14 13:08:07 +00001134 return Line.Type == LT_ObjCDecl || Left.is(tok::kw_if) ||
Nico Webered91bba2013-01-10 19:19:14 +00001135 Left.is(tok::kw_for) || Left.is(tok::kw_while) ||
Daniel Jasper7d19bc22013-01-11 14:23:32 +00001136 Left.is(tok::kw_switch) || Left.is(tok::kw_return) ||
Daniel Jasper088dab52013-01-11 16:09:04 +00001137 Left.is(tok::kw_catch) || Left.is(tok::kw_new) ||
1138 Left.is(tok::kw_delete);
Daniel Jasperbac016b2012-12-03 18:12:45 +00001139 }
Daniel Jasper26f7e782013-01-08 14:56:18 +00001140 if (Left.is(tok::at) &&
1141 Right.FormatTok.Tok.getObjCKeywordID() != tok::objc_not_keyword)
Nico Weberd0af4b42013-01-07 16:14:28 +00001142 return false;
Manuel Klimek36fab8d2013-01-10 13:24:24 +00001143 if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
1144 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +00001145 return true;
1146 }
1147
Daniel Jasper26f7e782013-01-08 14:56:18 +00001148 bool spaceRequiredBefore(const AnnotatedToken &Tok) {
Daniel Jasper995e8202013-01-14 13:08:07 +00001149 if (Line.Type == LT_ObjCMethodDecl) {
Daniel Jasper26f7e782013-01-08 14:56:18 +00001150 if (Tok.is(tok::identifier) && !Tok.Children.empty() &&
1151 Tok.Children[0].is(tok::colon) && Tok.Parent->is(tok::identifier))
Daniel Jasperda927712013-01-07 15:36:15 +00001152 return true;
Daniel Jasper26f7e782013-01-08 14:56:18 +00001153 if (Tok.is(tok::colon))
Daniel Jasperda927712013-01-07 15:36:15 +00001154 return false;
Daniel Jasper26f7e782013-01-08 14:56:18 +00001155 if (Tok.Parent->Type == TT_ObjCMethodSpecifier)
Nico Webercd52bda2013-01-10 23:11:41 +00001156 return Style.ObjCSpaceBeforeReturnType || Tok.isNot(tok::l_paren);
1157 if (Tok.Type == TT_ObjCSelectorStart)
1158 return !Style.ObjCSpaceBeforeReturnType;
Daniel Jasper26f7e782013-01-08 14:56:18 +00001159 if (Tok.Parent->is(tok::r_paren) && Tok.is(tok::identifier))
Daniel Jasperda927712013-01-07 15:36:15 +00001160 // Don't space between ')' and <id>
1161 return false;
Daniel Jasper26f7e782013-01-08 14:56:18 +00001162 if (Tok.Parent->is(tok::colon) && Tok.is(tok::l_paren))
Daniel Jasperda927712013-01-07 15:36:15 +00001163 // Don't space between ':' and '('
1164 return false;
1165 }
Daniel Jasper995e8202013-01-14 13:08:07 +00001166 if (Line.Type == LT_ObjCProperty &&
Nico Weber70848232013-01-10 21:30:42 +00001167 (Tok.is(tok::equal) || Tok.Parent->is(tok::equal)))
1168 return false;
Daniel Jasperda927712013-01-07 15:36:15 +00001169
Daniel Jasper4e9008a2013-01-13 08:19:51 +00001170 if (Tok.Parent->is(tok::comma))
1171 return true;
Daniel Jasper8134e1e2013-01-13 08:12:18 +00001172 if (Tok.Type == TT_IncludePath)
1173 return Tok.is(tok::less) || Tok.is(tok::string_literal);
Daniel Jasper46ef8522013-01-10 13:08:12 +00001174 if (Tok.Type == TT_CtorInitializerColon || Tok.Type == TT_ObjCBlockLParen)
Daniel Jasperda927712013-01-07 15:36:15 +00001175 return true;
Daniel Jasper26f7e782013-01-08 14:56:18 +00001176 if (Tok.Type == TT_OverloadedOperator)
1177 return Tok.is(tok::identifier) || Tok.is(tok::kw_new) ||
Daniel Jasper46ef8522013-01-10 13:08:12 +00001178 Tok.is(tok::kw_delete) || Tok.is(tok::kw_bool);
Daniel Jasper26f7e782013-01-08 14:56:18 +00001179 if (Tok.Parent->Type == TT_OverloadedOperator)
Daniel Jasperda927712013-01-07 15:36:15 +00001180 return false;
Daniel Jasper26f7e782013-01-08 14:56:18 +00001181 if (Tok.is(tok::colon))
Daniel Jasper995e8202013-01-14 13:08:07 +00001182 return Line.First.isNot(tok::kw_case) && !Tok.Children.empty() &&
Nico Weberbcfdd262013-01-12 06:18:40 +00001183 Tok.Type != TT_ObjCMethodExpr;
Daniel Jasper5cf7cf32013-01-10 11:14:08 +00001184 if (Tok.Parent->Type == TT_UnaryOperator ||
1185 Tok.Parent->Type == TT_CastRParen)
Daniel Jasperda927712013-01-07 15:36:15 +00001186 return false;
Daniel Jasper26f7e782013-01-08 14:56:18 +00001187 if (Tok.Type == TT_UnaryOperator)
1188 return Tok.Parent->isNot(tok::l_paren) &&
Nico Webercd458332013-01-12 23:48:49 +00001189 Tok.Parent->isNot(tok::l_square) && Tok.Parent->isNot(tok::at) &&
1190 (Tok.Parent->isNot(tok::colon) ||
1191 Tok.Parent->Type != TT_ObjCMethodExpr);
Daniel Jasper26f7e782013-01-08 14:56:18 +00001192 if (Tok.Parent->is(tok::greater) && Tok.is(tok::greater)) {
1193 return Tok.Type == TT_TemplateCloser && Tok.Parent->Type ==
Daniel Jasperda927712013-01-07 15:36:15 +00001194 TT_TemplateCloser && Style.SplitTemplateClosingGreater;
1195 }
Daniel Jasper26f7e782013-01-08 14:56:18 +00001196 if (Tok.Type == TT_BinaryOperator || Tok.Parent->Type == TT_BinaryOperator)
Daniel Jasperda927712013-01-07 15:36:15 +00001197 return true;
Daniel Jasper26f7e782013-01-08 14:56:18 +00001198 if (Tok.Parent->Type == TT_TemplateCloser && Tok.is(tok::l_paren))
Daniel Jasperda927712013-01-07 15:36:15 +00001199 return false;
Daniel Jasper995e8202013-01-14 13:08:07 +00001200 if (Tok.is(tok::less) && Line.First.is(tok::hash))
Daniel Jasperda927712013-01-07 15:36:15 +00001201 return true;
Daniel Jasper26f7e782013-01-08 14:56:18 +00001202 if (Tok.Type == TT_TrailingUnaryOperator)
Daniel Jasperda927712013-01-07 15:36:15 +00001203 return false;
Daniel Jasper26f7e782013-01-08 14:56:18 +00001204 return spaceRequiredBetween(*Tok.Parent, Tok);
Daniel Jasperda927712013-01-07 15:36:15 +00001205 }
1206
Daniel Jasper26f7e782013-01-08 14:56:18 +00001207 bool canBreakBefore(const AnnotatedToken &Right) {
1208 const AnnotatedToken &Left = *Right.Parent;
Daniel Jasper995e8202013-01-14 13:08:07 +00001209 if (Line.Type == LT_ObjCMethodDecl) {
Daniel Jasper26f7e782013-01-08 14:56:18 +00001210 if (Right.is(tok::identifier) && !Right.Children.empty() &&
1211 Right.Children[0].is(tok::colon) && Left.is(tok::identifier))
Daniel Jasperda927712013-01-07 15:36:15 +00001212 return true;
Nico Weber774b9732013-01-12 07:00:16 +00001213 if (Right.is(tok::identifier) && Left.is(tok::l_paren) &&
1214 Left.Parent->is(tok::colon))
Daniel Jasperda927712013-01-07 15:36:15 +00001215 // Don't break this identifier as ':' or identifier
1216 // before it will break.
1217 return false;
Daniel Jasper26f7e782013-01-08 14:56:18 +00001218 if (Right.is(tok::colon) && Left.is(tok::identifier) &&
1219 Left.CanBreakBefore)
Daniel Jasperda927712013-01-07 15:36:15 +00001220 // Don't break at ':' if identifier before it can beak.
1221 return false;
1222 }
Daniel Jasper8134e1e2013-01-13 08:12:18 +00001223 if (Right.Type == TT_IncludePath)
1224 return false;
Nico Weberbcfdd262013-01-12 06:18:40 +00001225 if (Right.is(tok::colon) && Right.Type == TT_ObjCMethodExpr)
1226 return false;
1227 if (Left.is(tok::colon) && Left.Type == TT_ObjCMethodExpr)
1228 return true;
Nico Webere8ccc812013-01-12 22:48:47 +00001229 if (isObjCSelectorName(Right))
1230 return true;
Daniel Jasper26f7e782013-01-08 14:56:18 +00001231 if (Left.ClosesTemplateDeclaration)
Daniel Jasper5eda31e2013-01-02 18:30:06 +00001232 return true;
Daniel Jasper26f7e782013-01-08 14:56:18 +00001233 if (Left.Type == TT_PointerOrReference || Left.Type == TT_TemplateCloser ||
Daniel Jasper2db356d2013-01-08 20:03:18 +00001234 Left.Type == TT_UnaryOperator || Right.Type == TT_ConditionalExpr)
Daniel Jasper4dc41de2013-01-02 08:44:14 +00001235 return false;
Daniel Jasper995e8202013-01-14 13:08:07 +00001236 if (Left.is(tok::equal) && Line.Type == LT_VirtualFunctionDecl)
Daniel Jasper71607512013-01-07 10:48:50 +00001237 return false;
1238
Daniel Jasper043835a2013-01-09 09:33:39 +00001239 if (Right.is(tok::comment))
Daniel Jasper487f64b2013-01-13 16:10:20 +00001240 // We rely on MustBreakBefore being set correctly here as we should not
1241 // change the "binding" behavior of a comment.
1242 return false;
1243
Daniel Jasper26f7e782013-01-08 14:56:18 +00001244 if (Right.is(tok::r_paren) || Right.is(tok::l_brace) ||
Daniel Jasper043835a2013-01-09 09:33:39 +00001245 Right.is(tok::greater))
Daniel Jasperbac016b2012-12-03 18:12:45 +00001246 return false;
Daniel Jasper26f7e782013-01-08 14:56:18 +00001247 return (isBinaryOperator(Left) && Left.isNot(tok::lessless)) ||
1248 Left.is(tok::comma) || Right.is(tok::lessless) ||
1249 Right.is(tok::arrow) || Right.is(tok::period) ||
1250 Right.is(tok::colon) || Left.is(tok::semi) ||
Daniel Jasper9c837d02013-01-09 07:06:56 +00001251 Left.is(tok::l_brace) || Left.is(tok::question) ||
Manuel Klimekc8c8a472013-01-10 15:58:26 +00001252 Right.is(tok::r_brace) || Left.Type == TT_ConditionalExpr ||
Daniel Jasper7d19bc22013-01-11 14:23:32 +00001253 (Left.is(tok::r_paren) && Left.Type != TT_CastRParen &&
1254 Right.is(tok::identifier)) ||
Daniel Jasper26f7e782013-01-08 14:56:18 +00001255 (Left.is(tok::l_paren) && !Right.is(tok::r_paren));
Daniel Jasperbac016b2012-12-03 18:12:45 +00001256 }
1257
Daniel Jasperbac016b2012-12-03 18:12:45 +00001258 FormatStyle Style;
1259 SourceManager &SourceMgr;
Manuel Klimek6cf58142013-01-07 08:54:53 +00001260 Lexer &Lex;
Daniel Jasper995e8202013-01-14 13:08:07 +00001261 AnnotatedLine &Line;
Daniel Jasperbac016b2012-12-03 18:12:45 +00001262};
1263
Alexander Kornienko469a21b2012-12-07 16:15:44 +00001264class LexerBasedFormatTokenSource : public FormatTokenSource {
1265public:
1266 LexerBasedFormatTokenSource(Lexer &Lex, SourceManager &SourceMgr)
Daniel Jasper1321eb52012-12-18 21:05:13 +00001267 : GreaterStashed(false), Lex(Lex), SourceMgr(SourceMgr),
Alexander Kornienko469a21b2012-12-07 16:15:44 +00001268 IdentTable(Lex.getLangOpts()) {
1269 Lex.SetKeepWhitespaceMode(true);
1270 }
1271
1272 virtual FormatToken getNextToken() {
1273 if (GreaterStashed) {
1274 FormatTok.NewlinesBefore = 0;
1275 FormatTok.WhiteSpaceStart =
1276 FormatTok.Tok.getLocation().getLocWithOffset(1);
1277 FormatTok.WhiteSpaceLength = 0;
1278 GreaterStashed = false;
1279 return FormatTok;
1280 }
1281
1282 FormatTok = FormatToken();
1283 Lex.LexFromRawLexer(FormatTok.Tok);
Manuel Klimek95419382013-01-07 07:56:50 +00001284 StringRef Text = rawTokenText(FormatTok.Tok);
Alexander Kornienko469a21b2012-12-07 16:15:44 +00001285 FormatTok.WhiteSpaceStart = FormatTok.Tok.getLocation();
Manuel Klimekf6fd00b2013-01-05 22:56:06 +00001286 if (SourceMgr.getFileOffset(FormatTok.WhiteSpaceStart) == 0)
1287 FormatTok.IsFirst = true;
Alexander Kornienko469a21b2012-12-07 16:15:44 +00001288
1289 // Consume and record whitespace until we find a significant token.
1290 while (FormatTok.Tok.is(tok::unknown)) {
Manuel Klimeka080a182013-01-02 16:30:12 +00001291 FormatTok.NewlinesBefore += Text.count('\n');
Daniel Jaspercd162382013-01-07 13:26:07 +00001292 FormatTok.HasUnescapedNewline = Text.count("\\\n") !=
1293 FormatTok.NewlinesBefore;
Alexander Kornienko469a21b2012-12-07 16:15:44 +00001294 FormatTok.WhiteSpaceLength += FormatTok.Tok.getLength();
1295
1296 if (FormatTok.Tok.is(tok::eof))
1297 return FormatTok;
1298 Lex.LexFromRawLexer(FormatTok.Tok);
Manuel Klimek95419382013-01-07 07:56:50 +00001299 Text = rawTokenText(FormatTok.Tok);
Manuel Klimekd4397b92013-01-04 23:34:14 +00001300 }
Manuel Klimek95419382013-01-07 07:56:50 +00001301
1302 // Now FormatTok is the next non-whitespace token.
1303 FormatTok.TokenLength = Text.size();
1304
Manuel Klimekd4397b92013-01-04 23:34:14 +00001305 // In case the token starts with escaped newlines, we want to
1306 // take them into account as whitespace - this pattern is quite frequent
1307 // in macro definitions.
1308 // FIXME: What do we want to do with other escaped spaces, and escaped
1309 // spaces or newlines in the middle of tokens?
1310 // FIXME: Add a more explicit test.
1311 unsigned i = 0;
Daniel Jasper71607512013-01-07 10:48:50 +00001312 while (i + 1 < Text.size() && Text[i] == '\\' && Text[i + 1] == '\n') {
Manuel Klimekd4397b92013-01-04 23:34:14 +00001313 FormatTok.WhiteSpaceLength += 2;
Manuel Klimek95419382013-01-07 07:56:50 +00001314 FormatTok.TokenLength -= 2;
Manuel Klimekd4397b92013-01-04 23:34:14 +00001315 i += 2;
Alexander Kornienko469a21b2012-12-07 16:15:44 +00001316 }
1317
1318 if (FormatTok.Tok.is(tok::raw_identifier)) {
Manuel Klimekd4397b92013-01-04 23:34:14 +00001319 IdentifierInfo &Info = IdentTable.get(Text);
Daniel Jaspercd1a32b2012-12-21 17:58:39 +00001320 FormatTok.Tok.setIdentifierInfo(&Info);
Alexander Kornienko469a21b2012-12-07 16:15:44 +00001321 FormatTok.Tok.setKind(Info.getTokenID());
1322 }
1323
1324 if (FormatTok.Tok.is(tok::greatergreater)) {
1325 FormatTok.Tok.setKind(tok::greater);
1326 GreaterStashed = true;
1327 }
1328
1329 return FormatTok;
1330 }
1331
1332private:
1333 FormatToken FormatTok;
1334 bool GreaterStashed;
1335 Lexer &Lex;
1336 SourceManager &SourceMgr;
1337 IdentifierTable IdentTable;
1338
1339 /// Returns the text of \c FormatTok.
Manuel Klimek95419382013-01-07 07:56:50 +00001340 StringRef rawTokenText(Token &Tok) {
Alexander Kornienko469a21b2012-12-07 16:15:44 +00001341 return StringRef(SourceMgr.getCharacterData(Tok.getLocation()),
1342 Tok.getLength());
1343 }
1344};
1345
Daniel Jasperbac016b2012-12-03 18:12:45 +00001346class Formatter : public UnwrappedLineConsumer {
1347public:
Daniel Jasperfeb18f52013-01-14 14:14:23 +00001348 Formatter(DiagnosticsEngine &Diag, const FormatStyle &Style, Lexer &Lex,
1349 SourceManager &SourceMgr,
Daniel Jasperbac016b2012-12-03 18:12:45 +00001350 const std::vector<CharSourceRange> &Ranges)
Alexander Kornienko3048aea2013-01-10 15:05:09 +00001351 : Diag(Diag), Style(Style), Lex(Lex), SourceMgr(SourceMgr),
Manuel Klimek3f8c7f32013-01-10 18:45:26 +00001352 Ranges(Ranges) {}
Daniel Jasperbac016b2012-12-03 18:12:45 +00001353
Daniel Jasper7d19bc22013-01-11 14:23:32 +00001354 virtual ~Formatter() {}
Daniel Jasperaccb0b02012-12-04 21:05:31 +00001355
Daniel Jasperbac016b2012-12-03 18:12:45 +00001356 tooling::Replacements format() {
Alexander Kornienko469a21b2012-12-07 16:15:44 +00001357 LexerBasedFormatTokenSource Tokens(Lex, SourceMgr);
Alexander Kornienko3048aea2013-01-10 15:05:09 +00001358 UnwrappedLineParser Parser(Diag, Style, Tokens, *this);
Alexander Kornienkocff563c2012-12-04 17:27:50 +00001359 StructuralError = Parser.parse();
Manuel Klimekd4397b92013-01-04 23:34:14 +00001360 unsigned PreviousEndOfLineColumn = 0;
Daniel Jasper995e8202013-01-14 13:08:07 +00001361 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
1362 TokenAnnotator Annotator(Style, SourceMgr, Lex, AnnotatedLines[i]);
1363 Annotator.annotate();
1364 }
1365 for (std::vector<AnnotatedLine>::iterator I = AnnotatedLines.begin(),
1366 E = AnnotatedLines.end();
Manuel Klimekf9ea2ed2013-01-10 19:49:59 +00001367 I != E; ++I) {
Daniel Jasper995e8202013-01-14 13:08:07 +00001368 const AnnotatedLine &TheLine = *I;
1369 if (touchesRanges(TheLine) && TheLine.Type != LT_Invalid) {
1370 unsigned Indent = formatFirstToken(TheLine.First, TheLine.Level,
1371 TheLine.InPPDirective,
Manuel Klimekf9ea2ed2013-01-10 19:49:59 +00001372 PreviousEndOfLineColumn);
Daniel Jasper995e8202013-01-14 13:08:07 +00001373 bool FitsOnALine = tryFitMultipleLinesInOne(Indent, I, E);
1374 UnwrappedLineFormatter Formatter(Style, SourceMgr, TheLine, Indent,
1375 FitsOnALine, TheLine.First, Replaces,
1376 StructuralError);
Manuel Klimekf9ea2ed2013-01-10 19:49:59 +00001377 PreviousEndOfLineColumn = Formatter.format();
1378 } else {
1379 // If we did not reformat this unwrapped line, the column at the end of
1380 // the last token is unchanged - thus, we can calculate the end of the
1381 // last token, and return the result.
Manuel Klimekf9ea2ed2013-01-10 19:49:59 +00001382 PreviousEndOfLineColumn =
Daniel Jasper995e8202013-01-14 13:08:07 +00001383 SourceMgr.getSpellingColumnNumber(
1384 TheLine.Last->FormatTok.Tok.getLocation()) +
1385 Lex.MeasureTokenLength(TheLine.Last->FormatTok.Tok.getLocation(),
1386 SourceMgr, Lex.getLangOpts()) -
Manuel Klimekf9ea2ed2013-01-10 19:49:59 +00001387 1;
1388 }
1389 }
Daniel Jasperbac016b2012-12-03 18:12:45 +00001390 return Replaces;
1391 }
1392
1393private:
Manuel Klimek517e8942013-01-11 17:54:10 +00001394 /// \brief Tries to merge lines into one.
1395 ///
1396 /// This will change \c Line and \c AnnotatedLine to contain the merged line,
1397 /// if possible; note that \c I will be incremented when lines are merged.
1398 ///
1399 /// Returns whether the resulting \c Line can fit in a single line.
Daniel Jasper995e8202013-01-14 13:08:07 +00001400 bool tryFitMultipleLinesInOne(unsigned Indent,
1401 std::vector<AnnotatedLine>::iterator &I,
1402 std::vector<AnnotatedLine>::iterator E) {
Manuel Klimek517e8942013-01-11 17:54:10 +00001403 unsigned Limit = Style.ColumnLimit - (I->InPPDirective ? 1 : 0) - Indent;
1404
1405 // Check whether the UnwrappedLine can be put onto a single line. If
1406 // so, this is bound to be the optimal solution (by definition) and we
1407 // don't need to analyze the entire solution space.
Daniel Jasperfeb18f52013-01-14 14:14:23 +00001408 unsigned Length = 0;
1409 if (!fitsIntoLimit(I->First, Limit, &Length))
Daniel Jasper995e8202013-01-14 13:08:07 +00001410 return false;
Daniel Jasperfeb18f52013-01-14 14:14:23 +00001411 Limit -= Length + 1; // One space.
1412 if (I + 1 == E)
1413 return true;
Manuel Klimek517e8942013-01-11 17:54:10 +00001414
Daniel Jasperfeb18f52013-01-14 14:14:23 +00001415 if (I->Last->is(tok::l_brace)) {
1416 tryMergeSimpleBlock(I, E, Limit);
1417 } else if (I->First.is(tok::kw_if)) {
1418 tryMergeSimpleIf(I, E, Limit);
Daniel Jaspere0b15ea2013-01-14 15:40:57 +00001419 } else if (I->InPPDirective && (I->First.FormatTok.HasUnescapedNewline ||
1420 I->First.FormatTok.IsFirst)) {
1421 tryMergeSimplePPDirective(I, E, Limit);
Daniel Jasperfeb18f52013-01-14 14:14:23 +00001422 }
1423 return true;
1424 }
1425
Daniel Jaspere0b15ea2013-01-14 15:40:57 +00001426 void tryMergeSimplePPDirective(std::vector<AnnotatedLine>::iterator &I,
1427 std::vector<AnnotatedLine>::iterator E,
1428 unsigned Limit) {
1429 AnnotatedLine &Line = *I;
1430 if (!(I + 1)->InPPDirective) return;
1431 if (I + 2 != E && (I + 2)->InPPDirective &&
1432 !(I + 2)->First.FormatTok.HasUnescapedNewline)
1433 return;
1434 if (!fitsIntoLimit((I + 1)->First, Limit)) return;
1435 join(Line, *(++I));
1436 }
1437
Daniel Jasperfeb18f52013-01-14 14:14:23 +00001438 void tryMergeSimpleIf(std::vector<AnnotatedLine>::iterator &I,
1439 std::vector<AnnotatedLine>::iterator E,
1440 unsigned Limit) {
1441 AnnotatedLine &Line = *I;
1442 if (!fitsIntoLimit((I + 1)->First, Limit))
1443 return;
1444 if ((I + 1)->First.is(tok::kw_if) || (I + 1)->First.Type == TT_LineComment)
1445 return;
1446 // Only inline simple if's (no nested if or else).
1447 if (I + 2 != E && (I + 2)->First.is(tok::kw_else))
1448 return;
1449 join(Line, *(++I));
1450 }
1451
1452 void tryMergeSimpleBlock(std::vector<AnnotatedLine>::iterator &I,
1453 std::vector<AnnotatedLine>::iterator E,
1454 unsigned Limit){
Daniel Jasper995e8202013-01-14 13:08:07 +00001455 // Check that we still have three lines and they fit into the limit.
Daniel Jasperfeb18f52013-01-14 14:14:23 +00001456 if (I + 2 == E || !nextTwoLinesFitInto(I, Limit))
1457 return;
Manuel Klimek517e8942013-01-11 17:54:10 +00001458
1459 // First, check that the current line allows merging. This is the case if
1460 // we're not in a control flow statement and the last token is an opening
1461 // brace.
Daniel Jasperfeb18f52013-01-14 14:14:23 +00001462 AnnotatedLine &Line = *I;
Manuel Klimek517e8942013-01-11 17:54:10 +00001463 bool AllowedTokens =
Daniel Jasper995e8202013-01-14 13:08:07 +00001464 Line.First.isNot(tok::kw_if) && Line.First.isNot(tok::kw_while) &&
1465 Line.First.isNot(tok::kw_do) && Line.First.isNot(tok::r_brace) &&
1466 Line.First.isNot(tok::kw_else) && Line.First.isNot(tok::kw_try) &&
1467 Line.First.isNot(tok::kw_catch) && Line.First.isNot(tok::kw_for) &&
Nico Weber67015ed2013-01-11 21:14:08 +00001468 // This gets rid of all ObjC @ keywords and methods.
Daniel Jasper995e8202013-01-14 13:08:07 +00001469 Line.First.isNot(tok::at) && Line.First.isNot(tok::minus) &&
1470 Line.First.isNot(tok::plus);
Daniel Jasperfeb18f52013-01-14 14:14:23 +00001471 if (!AllowedTokens)
1472 return;
Manuel Klimek517e8942013-01-11 17:54:10 +00001473
1474 // Second, check that the next line does not contain any braces - if it
1475 // does, readability declines when putting it into a single line.
Daniel Jasper995e8202013-01-14 13:08:07 +00001476 const AnnotatedToken *Tok = &(I + 1)->First;
1477 if ((I + 1)->Last->Type == TT_LineComment || Tok->MustBreakBefore)
Daniel Jasperfeb18f52013-01-14 14:14:23 +00001478 return;
Daniel Jasper995e8202013-01-14 13:08:07 +00001479 do {
1480 if (Tok->is(tok::l_brace) || Tok->is(tok::r_brace))
Daniel Jasperfeb18f52013-01-14 14:14:23 +00001481 return;
Daniel Jasper995e8202013-01-14 13:08:07 +00001482 Tok = Tok->Children.empty() ? NULL : &Tok->Children.back();
1483 } while (Tok != NULL);
Manuel Klimek517e8942013-01-11 17:54:10 +00001484
1485 // Last, check that the third line contains a single closing brace.
Daniel Jasper995e8202013-01-14 13:08:07 +00001486 Tok = &(I + 2)->First;
1487 if (!Tok->Children.empty() || Tok->isNot(tok::r_brace) ||
1488 Tok->MustBreakBefore)
Daniel Jasperfeb18f52013-01-14 14:14:23 +00001489 return;
Manuel Klimek517e8942013-01-11 17:54:10 +00001490
Daniel Jasper995e8202013-01-14 13:08:07 +00001491 // If the merged line fits, we use that instead and skip the next two lines.
1492 Line.Last->Children.push_back((I + 1)->First);
1493 while (!Line.Last->Children.empty()) {
1494 Line.Last->Children[0].Parent = Line.Last;
1495 Line.Last = &Line.Last->Children[0];
Manuel Klimek517e8942013-01-11 17:54:10 +00001496 }
Daniel Jasper995e8202013-01-14 13:08:07 +00001497
1498 join(Line, *(I + 1));
1499 join(Line, *(I + 2));
1500 I += 2;
Daniel Jasperfeb18f52013-01-14 14:14:23 +00001501 }
1502
1503 bool nextTwoLinesFitInto(std::vector<AnnotatedLine>::iterator I,
1504 unsigned Limit) {
1505 unsigned LengthLine1 = 0;
1506 unsigned LengthLine2 = 0;
1507 if (!fitsIntoLimit((I + 1)->First, Limit, &LengthLine1) ||
1508 !fitsIntoLimit((I + 2)->First, Limit, &LengthLine2))
1509 return false;
1510 return LengthLine1 + LengthLine2 + 1 <= Limit; // One space.
Manuel Klimek517e8942013-01-11 17:54:10 +00001511 }
1512
Daniel Jasper995e8202013-01-14 13:08:07 +00001513 void join(AnnotatedLine &A, const AnnotatedLine &B) {
1514 A.Last->Children.push_back(B.First);
1515 while (!A.Last->Children.empty()) {
1516 A.Last->Children[0].Parent = A.Last;
1517 A.Last = &A.Last->Children[0];
1518 }
Manuel Klimekf9ea2ed2013-01-10 19:49:59 +00001519 }
1520
Daniel Jasper995e8202013-01-14 13:08:07 +00001521 bool touchesRanges(const AnnotatedLine &TheLine) {
1522 const FormatToken *First = &TheLine.First.FormatTok;
1523 const FormatToken *Last = &TheLine.Last->FormatTok;
Daniel Jaspercd162382013-01-07 13:26:07 +00001524 CharSourceRange LineRange = CharSourceRange::getTokenRange(
Daniel Jasper26f7e782013-01-08 14:56:18 +00001525 First->Tok.getLocation(),
1526 Last->Tok.getLocation());
Daniel Jasperbac016b2012-12-03 18:12:45 +00001527 for (unsigned i = 0, e = Ranges.size(); i != e; ++i) {
Manuel Klimekf9ea2ed2013-01-10 19:49:59 +00001528 if (!SourceMgr.isBeforeInTranslationUnit(LineRange.getEnd(),
1529 Ranges[i].getBegin()) &&
1530 !SourceMgr.isBeforeInTranslationUnit(Ranges[i].getEnd(),
1531 LineRange.getBegin()))
1532 return true;
Daniel Jasperbac016b2012-12-03 18:12:45 +00001533 }
Manuel Klimekf9ea2ed2013-01-10 19:49:59 +00001534 return false;
1535 }
1536
1537 virtual void consumeUnwrappedLine(const UnwrappedLine &TheLine) {
Daniel Jasper995e8202013-01-14 13:08:07 +00001538 AnnotatedLines.push_back(
1539 AnnotatedLine(TheLine.RootToken, TheLine.Level, TheLine.InPPDirective));
Daniel Jasperbac016b2012-12-03 18:12:45 +00001540 }
1541
Manuel Klimek3f8c7f32013-01-10 18:45:26 +00001542 /// \brief Add a new line and the required indent before the first Token
1543 /// of the \c UnwrappedLine if there was no structural parsing error.
1544 /// Returns the indent level of the \c UnwrappedLine.
1545 unsigned formatFirstToken(const AnnotatedToken &RootToken, unsigned Level,
1546 bool InPPDirective,
1547 unsigned PreviousEndOfLineColumn) {
Daniel Jasper7d19bc22013-01-11 14:23:32 +00001548 const FormatToken &Tok = RootToken.FormatTok;
Manuel Klimek3f8c7f32013-01-10 18:45:26 +00001549 if (!Tok.WhiteSpaceStart.isValid() || StructuralError)
1550 return SourceMgr.getSpellingColumnNumber(Tok.Tok.getLocation()) - 1;
1551
1552 unsigned Newlines = std::min(Tok.NewlinesBefore,
1553 Style.MaxEmptyLinesToKeep + 1);
1554 if (Newlines == 0 && !Tok.IsFirst)
1555 Newlines = 1;
1556 unsigned Indent = Level * 2;
1557
1558 bool IsAccessModifier = false;
1559 if (RootToken.is(tok::kw_public) || RootToken.is(tok::kw_protected) ||
1560 RootToken.is(tok::kw_private))
1561 IsAccessModifier = true;
1562 else if (RootToken.is(tok::at) && !RootToken.Children.empty() &&
1563 (RootToken.Children[0].isObjCAtKeyword(tok::objc_public) ||
1564 RootToken.Children[0].isObjCAtKeyword(tok::objc_protected) ||
1565 RootToken.Children[0].isObjCAtKeyword(tok::objc_package) ||
1566 RootToken.Children[0].isObjCAtKeyword(tok::objc_private)))
1567 IsAccessModifier = true;
1568
1569 if (IsAccessModifier &&
1570 static_cast<int>(Indent) + Style.AccessModifierOffset >= 0)
1571 Indent += Style.AccessModifierOffset;
1572 if (!InPPDirective || Tok.HasUnescapedNewline) {
1573 replaceWhitespace(Tok, Newlines, Indent, Style, SourceMgr, Replaces);
1574 } else {
1575 replacePPWhitespace(Tok, Newlines, Indent, PreviousEndOfLineColumn, Style,
1576 SourceMgr, Replaces);
1577 }
1578 return Indent;
1579 }
1580
Alexander Kornienkoa4ae9f32013-01-14 11:34:14 +00001581 DiagnosticsEngine &Diag;
Daniel Jasperbac016b2012-12-03 18:12:45 +00001582 FormatStyle Style;
1583 Lexer &Lex;
1584 SourceManager &SourceMgr;
1585 tooling::Replacements Replaces;
1586 std::vector<CharSourceRange> Ranges;
Daniel Jasper995e8202013-01-14 13:08:07 +00001587 std::vector<AnnotatedLine> AnnotatedLines;
Alexander Kornienkocff563c2012-12-04 17:27:50 +00001588 bool StructuralError;
Daniel Jasperbac016b2012-12-03 18:12:45 +00001589};
1590
1591tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
1592 SourceManager &SourceMgr,
Alexander Kornienkoa4ae9f32013-01-14 11:34:14 +00001593 std::vector<CharSourceRange> Ranges,
1594 DiagnosticConsumer *DiagClient) {
Alexander Kornienko3048aea2013-01-10 15:05:09 +00001595 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
Alexander Kornienkoa4ae9f32013-01-14 11:34:14 +00001596 OwningPtr<DiagnosticConsumer> DiagPrinter;
1597 if (DiagClient == 0) {
1598 DiagPrinter.reset(new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts));
1599 DiagPrinter->BeginSourceFile(Lex.getLangOpts(), Lex.getPP());
1600 DiagClient = DiagPrinter.get();
1601 }
Alexander Kornienko3048aea2013-01-10 15:05:09 +00001602 DiagnosticsEngine Diagnostics(
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +00001603 IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
Alexander Kornienkoa4ae9f32013-01-14 11:34:14 +00001604 DiagClient, false);
Alexander Kornienko3048aea2013-01-10 15:05:09 +00001605 Diagnostics.setSourceManager(&SourceMgr);
1606 Formatter formatter(Diagnostics, Style, Lex, SourceMgr, Ranges);
Daniel Jasperbac016b2012-12-03 18:12:45 +00001607 return formatter.format();
1608}
1609
Daniel Jasper46ef8522013-01-10 13:08:12 +00001610LangOptions getFormattingLangOpts() {
1611 LangOptions LangOpts;
1612 LangOpts.CPlusPlus = 1;
1613 LangOpts.CPlusPlus11 = 1;
1614 LangOpts.Bool = 1;
1615 LangOpts.ObjC1 = 1;
1616 LangOpts.ObjC2 = 1;
1617 return LangOpts;
1618}
1619
Daniel Jaspercd162382013-01-07 13:26:07 +00001620} // namespace format
1621} // namespace clang