blob: d11e223b53c20fd5a9cabc17e1e149acf856f571 [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 Jasperbac016b2012-12-03 18:12:45 +000021#include "clang/Basic/SourceManager.h"
22#include "clang/Lex/Lexer.h"
23
Daniel Jasperbac016b2012-12-03 18:12:45 +000024namespace clang {
25namespace format {
26
27// FIXME: Move somewhere sane.
28struct TokenAnnotation {
Daniel Jaspera88bb452012-12-04 10:50:12 +000029 enum TokenType { TT_Unknown, TT_TemplateOpener, TT_TemplateCloser,
30 TT_BinaryOperator, TT_UnaryOperator, TT_OverloadedOperator,
31 TT_PointerOrReference, TT_ConditionalExpr, TT_LineComment,
32 TT_BlockComment };
Daniel Jasperbac016b2012-12-03 18:12:45 +000033
34 TokenType Type;
35
36 /// \brief The current parenthesis level, i.e. the number of opening minus
37 /// the number of closing parenthesis left of the current position.
38 unsigned ParenLevel;
39
40 bool SpaceRequiredBefore;
41 bool CanBreakBefore;
42 bool MustBreakBefore;
43};
44
45using llvm::MutableArrayRef;
46
47FormatStyle getLLVMStyle() {
48 FormatStyle LLVMStyle;
49 LLVMStyle.ColumnLimit = 80;
50 LLVMStyle.MaxEmptyLinesToKeep = 1;
51 LLVMStyle.PointerAndReferenceBindToType = false;
52 LLVMStyle.AccessModifierOffset = -2;
53 LLVMStyle.SplitTemplateClosingGreater = true;
54 return LLVMStyle;
55}
56
57FormatStyle getGoogleStyle() {
58 FormatStyle GoogleStyle;
59 GoogleStyle.ColumnLimit = 80;
60 GoogleStyle.MaxEmptyLinesToKeep = 1;
61 GoogleStyle.PointerAndReferenceBindToType = true;
62 GoogleStyle.AccessModifierOffset = -1;
63 GoogleStyle.SplitTemplateClosingGreater = false;
64 return GoogleStyle;
65}
66
67struct OptimizationParameters {
68 unsigned PenaltyExtraLine;
69 unsigned PenaltyIndentLevel;
70};
71
72class UnwrappedLineFormatter {
73public:
74 UnwrappedLineFormatter(const FormatStyle &Style, SourceManager &SourceMgr,
75 const UnwrappedLine &Line,
76 const std::vector<TokenAnnotation> &Annotations,
77 tooling::Replacements &Replaces)
78 : Style(Style),
79 SourceMgr(SourceMgr),
80 Line(Line),
81 Annotations(Annotations),
82 Replaces(Replaces) {
83 Parameters.PenaltyExtraLine = 100;
84 Parameters.PenaltyIndentLevel = 5;
85 }
86
87 void format() {
88 formatFirstToken();
89 count = 0;
90 IndentState State;
91 State.Column = Line.Level * 2 + Line.Tokens[0].Tok.getLength();
92 State.CtorInitializerOnNewLine = false;
93 State.InCtorInitializer = false;
94 State.ConsumedTokens = 1;
95
96 //State.UsedIndent.push_back(Line.Level * 2);
97 State.Indent.push_back(Line.Level * 2 + 4);
98 State.LastSpace.push_back(Line.Level * 2);
99
100 // Start iterating at 1 as we have correctly formatted of Token #0 above.
101 for (unsigned i = 1, n = Line.Tokens.size(); i != n; ++i) {
102 unsigned NoBreak = calcPenalty(State, false, UINT_MAX);
103 unsigned Break = calcPenalty(State, true, NoBreak);
104 addToken(Break < NoBreak, false, State);
105 }
106 }
107
108private:
109 /// \brief The current state when indenting a unwrapped line.
110 ///
111 /// As the indenting tries different combinations this is copied by value.
112 struct IndentState {
113 /// \brief The number of used columns in the current line.
114 unsigned Column;
115
116 /// \brief The number of tokens already consumed.
117 unsigned ConsumedTokens;
118
119 /// \brief The position to which a specific parenthesis level needs to be
120 /// indented.
121 std::vector<unsigned> Indent;
122
123 std::vector<unsigned> LastSpace;
124
125 bool CtorInitializerOnNewLine;
126 bool InCtorInitializer;
127
128 /// \brief Comparison operator to be able to used \c IndentState in \c map.
129 bool operator<(const IndentState &Other) const {
130 if (Other.ConsumedTokens != ConsumedTokens)
131 return Other.ConsumedTokens > ConsumedTokens;
132 if (Other.Column != Column)
133 return Other.Column > Column;
134 if (Other.Indent.size() != Indent.size())
135 return Other.Indent.size() > Indent.size();
136 for (int i = 0, e = Indent.size(); i != e; ++i) {
137 if (Other.Indent[i] != Indent[i])
138 return Other.Indent[i] > Indent[i];
139 }
140 if (Other.LastSpace.size() != LastSpace.size())
141 return Other.LastSpace.size() > LastSpace.size();
142 for (int i = 0, e = LastSpace.size(); i != e; ++i) {
143 if (Other.LastSpace[i] != LastSpace[i])
144 return Other.LastSpace[i] > LastSpace[i];
145 }
146 return false;
147 }
148 };
149
150 /// Append the next token to \p State.
151 void addToken(bool Newline, bool DryRun, IndentState &State) {
152 unsigned Index = State.ConsumedTokens;
153 const FormatToken &Current = Line.Tokens[Index];
154 const FormatToken &Previous = Line.Tokens[Index - 1];
155 unsigned ParenLevel = Annotations[Index].ParenLevel;
156
157 if (Current.Tok.is(tok::l_paren) || Current.Tok.is(tok::l_square) ||
158 Annotations[Index].Type == TokenAnnotation::TT_TemplateOpener) {
159 State.Indent.push_back(4 + State.LastSpace.back());
160 State.LastSpace.push_back(State.LastSpace.back());
161 }
162
163 if (Newline) {
164 if (Current.Tok.is(tok::string_literal) &&
165 Previous.Tok.is(tok::string_literal))
166 State.Column = State.Column - Previous.Tok.getLength();
167 else if (Previous.Tok.is(tok::equal) && ParenLevel != 0)
168 State.Column = State.Indent[ParenLevel] + 4;
Daniel Jaspera88bb452012-12-04 10:50:12 +0000169 else
Daniel Jasperbac016b2012-12-03 18:12:45 +0000170 State.Column = State.Indent[ParenLevel];
171 if (!DryRun)
172 replaceWhitespace(Current, 1, State.Column);
173
174 State.Column += Current.Tok.getLength();
Daniel Jaspera88bb452012-12-04 10:50:12 +0000175 State.LastSpace[ParenLevel] = State.Indent[ParenLevel];
Daniel Jasperbac016b2012-12-03 18:12:45 +0000176 if (Current.Tok.is(tok::colon) &&
177 Annotations[Index].Type != TokenAnnotation::TT_ConditionalExpr) {
178 State.Indent[ParenLevel] += 2;
179 State.CtorInitializerOnNewLine = true;
180 State.InCtorInitializer = true;
181 }
182 } else {
183 unsigned Spaces = Annotations[Index].SpaceRequiredBefore ? 1 : 0;
184 if (Annotations[Index].Type == TokenAnnotation::TT_LineComment)
185 Spaces = 2;
186 if (!DryRun)
187 replaceWhitespace(Current, 0, Spaces);
188 if (Previous.Tok.is(tok::l_paren))
189 State.Indent[ParenLevel] = State.Column;
Daniel Jaspera88bb452012-12-04 10:50:12 +0000190 if (Annotations[Index - 1].Type == TokenAnnotation::TT_TemplateOpener)
Daniel Jasperbac016b2012-12-03 18:12:45 +0000191 State.Indent[ParenLevel] = State.Column;
192 if (Current.Tok.is(tok::colon)) {
193 State.Indent[ParenLevel] = State.Column + 3;
194 State.InCtorInitializer = true;
195 }
196 // Top-level spaces are exempt as that mostly leads to better results.
Daniel Jaspera88bb452012-12-04 10:50:12 +0000197 if (Spaces > 0 && ParenLevel != 0)
Daniel Jasperbac016b2012-12-03 18:12:45 +0000198 State.LastSpace[ParenLevel] = State.Column + Spaces;
199 State.Column += Current.Tok.getLength() + Spaces;
200 }
201
Daniel Jaspera88bb452012-12-04 10:50:12 +0000202 if (Current.Tok.is(tok::r_paren) || Current.Tok.is(tok::r_square) ||
203 Annotations[Index].Type == TokenAnnotation::TT_TemplateCloser) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000204 State.Indent.pop_back();
205 State.LastSpace.pop_back();
206 }
207
208 ++State.ConsumedTokens;
209 }
210
211 typedef std::map<IndentState, unsigned> StateMap;
212 StateMap Memory;
213
214 unsigned splitPenalty(const FormatToken &Token) {
215 if (Token.Tok.is(tok::semi))
216 return 0;
217 if (Token.Tok.is(tok::comma))
218 return 1;
219 if (Token.Tok.is(tok::equal) || Token.Tok.is(tok::l_paren) ||
220 Token.Tok.is(tok::pipepipe) || Token.Tok.is(tok::ampamp))
221 return 2;
222 return 3;
223 }
224
225 /// \brief Calculate the number of lines needed to format the remaining part
226 /// of the unwrapped line.
227 ///
228 /// Assumes the formatting so far has led to
229 /// the \c IndentState \p State. If \p NewLine is set, a new line will be
230 /// added after the previous token.
231 ///
232 /// \param StopAt is used for optimization. If we can determine that we'll
233 /// definitely need at least \p StopAt additional lines, we already know of a
234 /// better solution.
235 unsigned calcPenalty(IndentState State, bool NewLine, unsigned StopAt) {
236 // We are at the end of the unwrapped line, so we don't need any more lines.
237 if (State.ConsumedTokens >= Line.Tokens.size())
238 return 0;
239
240 if (!NewLine && Annotations[State.ConsumedTokens].MustBreakBefore)
241 return UINT_MAX;
242 if (NewLine && !Annotations[State.ConsumedTokens].CanBreakBefore)
243 return UINT_MAX;
244
245 if (State.ConsumedTokens > 0 && !NewLine &&
246 State.CtorInitializerOnNewLine &&
247 Line.Tokens[State.ConsumedTokens - 1].Tok.is(tok::comma))
248 return UINT_MAX;
249
250 if (NewLine && State.InCtorInitializer && !State.CtorInitializerOnNewLine)
251 return UINT_MAX;
252
253 addToken(NewLine, true, State);
254
255 // Exceeding column limit is bad.
256 if (State.Column > Style.ColumnLimit)
257 return UINT_MAX;
258
259 unsigned CurrentPenalty = 0;
260 if (NewLine) {
261 CurrentPenalty += Parameters.PenaltyIndentLevel *
262 Annotations[State.ConsumedTokens - 1].ParenLevel +
263 Parameters.PenaltyExtraLine +
264 splitPenalty(Line.Tokens[State.ConsumedTokens - 2]);
265 }
266
267 if (StopAt <= CurrentPenalty)
268 return UINT_MAX;
269 StopAt -= CurrentPenalty;
270
271 // Has this state already been examined?
272 StateMap::iterator I = Memory.find(State);
273 if (I != Memory.end())
274 return I->second;
275 ++count;
276
277 unsigned NoBreak = calcPenalty(State, false, StopAt);
278 unsigned WithBreak = calcPenalty(State, true, std::min(StopAt, NoBreak));
279 unsigned Result = std::min(NoBreak, WithBreak);
280 if (Result != UINT_MAX)
281 Result += CurrentPenalty;
282 Memory[State] = Result;
283 assert(Memory.find(State) != Memory.end());
284 return Result;
285 }
286
287 /// \brief Replaces the whitespace in front of \p Tok. Only call once for
288 /// each \c FormatToken.
289 void replaceWhitespace(const FormatToken &Tok, unsigned NewLines,
290 unsigned Spaces) {
291 Replaces.insert(tooling::Replacement(
292 SourceMgr, Tok.WhiteSpaceStart, Tok.WhiteSpaceLength,
293 std::string(NewLines, '\n') + std::string(Spaces, ' ')));
294 }
295
296 /// \brief Add a new line and the required indent before the first Token
297 /// of the \c UnwrappedLine.
298 void formatFirstToken() {
299 const FormatToken &Token = Line.Tokens[0];
300 if (Token.WhiteSpaceStart.isValid()) {
301 unsigned Newlines =
302 std::min(Token.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
303 unsigned Offset = SourceMgr.getFileOffset(Token.WhiteSpaceStart);
304 if (Newlines == 0 && Offset != 0)
305 Newlines = 1;
306 unsigned Indent = Line.Level * 2;
307 if (Token.Tok.is(tok::kw_public) || Token.Tok.is(tok::kw_protected) ||
308 Token.Tok.is(tok::kw_private))
309 Indent += Style.AccessModifierOffset;
310 replaceWhitespace(Token, Newlines, Indent);
311 }
312 }
313
314 FormatStyle Style;
315 SourceManager &SourceMgr;
316 const UnwrappedLine &Line;
317 const std::vector<TokenAnnotation> &Annotations;
318 tooling::Replacements &Replaces;
319 unsigned int count;
320
321 OptimizationParameters Parameters;
322};
323
324/// \brief Determines extra information about the tokens comprising an
325/// \c UnwrappedLine.
326class TokenAnnotator {
327public:
328 TokenAnnotator(const UnwrappedLine &Line, const FormatStyle &Style,
329 SourceManager &SourceMgr)
330 : Line(Line),
331 Style(Style),
332 SourceMgr(SourceMgr) {
333 }
334
335 /// \brief A parser that gathers additional information about tokens.
336 ///
337 /// The \c TokenAnnotator tries to matches parenthesis and square brakets and
338 /// store a parenthesis levels. It also tries to resolve matching "<" and ">"
339 /// into template parameter lists.
340 class AnnotatingParser {
341 public:
Manuel Klimek0be4b362012-12-03 20:55:42 +0000342 AnnotatingParser(const SmallVector<FormatToken, 16> &Tokens,
Daniel Jasperbac016b2012-12-03 18:12:45 +0000343 std::vector<TokenAnnotation> &Annotations)
Manuel Klimek0be4b362012-12-03 20:55:42 +0000344 : Tokens(Tokens),
Daniel Jasperbac016b2012-12-03 18:12:45 +0000345 Annotations(Annotations),
346 Index(0) {
347 }
348
349 bool parseAngle(unsigned Level) {
350 while (Index < Tokens.size()) {
351 if (Tokens[Index].Tok.is(tok::greater)) {
Daniel Jaspera88bb452012-12-04 10:50:12 +0000352 Annotations[Index].Type = TokenAnnotation::TT_TemplateCloser;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000353 Annotations[Index].ParenLevel = Level;
354 next();
355 return true;
356 }
357 if (Tokens[Index].Tok.is(tok::r_paren) ||
358 Tokens[Index].Tok.is(tok::r_square))
359 return false;
360 if (Tokens[Index].Tok.is(tok::pipepipe) ||
361 Tokens[Index].Tok.is(tok::ampamp) ||
362 Tokens[Index].Tok.is(tok::question) ||
363 Tokens[Index].Tok.is(tok::colon))
364 return false;
365 consumeToken(Level);
366 }
367 return false;
368 }
369
370 bool parseParens(unsigned Level) {
371 while (Index < Tokens.size()) {
372 if (Tokens[Index].Tok.is(tok::r_paren)) {
373 Annotations[Index].ParenLevel = Level;
374 next();
375 return true;
376 }
377 if (Tokens[Index].Tok.is(tok::r_square))
378 return false;
379 consumeToken(Level);
380 }
381 return false;
382 }
383
384 bool parseSquare(unsigned Level) {
385 while (Index < Tokens.size()) {
386 if (Tokens[Index].Tok.is(tok::r_square)) {
387 Annotations[Index].ParenLevel = Level;
388 next();
389 return true;
390 }
391 if (Tokens[Index].Tok.is(tok::r_paren))
392 return false;
393 consumeToken(Level);
394 }
395 return false;
396 }
397
398 bool parseConditional(unsigned Level) {
399 while (Index < Tokens.size()) {
400 if (Tokens[Index].Tok.is(tok::colon)) {
401 Annotations[Index].Type = TokenAnnotation::TT_ConditionalExpr;
402 next();
403 return true;
404 }
405 consumeToken(Level);
406 }
407 return false;
408 }
409
410 void consumeToken(unsigned Level) {
411 Annotations[Index].ParenLevel = Level;
412 unsigned CurrentIndex = Index;
413 next();
414 switch (Tokens[CurrentIndex].Tok.getKind()) {
415 case tok::l_paren:
416 parseParens(Level + 1);
417 break;
418 case tok::l_square:
419 parseSquare(Level + 1);
420 break;
421 case tok::less:
422 if (parseAngle(Level + 1))
423 Annotations[CurrentIndex].Type = TokenAnnotation::TT_TemplateOpener;
424 else {
Daniel Jaspera88bb452012-12-04 10:50:12 +0000425 Annotations[CurrentIndex].ParenLevel = Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000426 Annotations[CurrentIndex].Type = TokenAnnotation::TT_BinaryOperator;
427 Index = CurrentIndex + 1;
428 }
429 break;
430 case tok::greater:
431 Annotations[CurrentIndex].Type = TokenAnnotation::TT_BinaryOperator;
432 break;
433 case tok::kw_operator:
434 if (!Tokens[Index].Tok.is(tok::l_paren))
435 Annotations[Index].Type = TokenAnnotation::TT_OverloadedOperator;
436 next();
437 break;
438 case tok::question:
439 parseConditional(Level);
440 break;
441 default:
442 break;
443 }
444 }
445
446 void parseLine() {
447 while (Index < Tokens.size()) {
448 consumeToken(0);
449 }
450 }
451
452 void next() {
453 ++Index;
454 }
455
456 private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000457 const SmallVector<FormatToken, 16> &Tokens;
458 std::vector<TokenAnnotation> &Annotations;
459 unsigned Index;
460 };
461
462 void annotate() {
463 Annotations.clear();
464 for (int i = 0, e = Line.Tokens.size(); i != e; ++i) {
465 Annotations.push_back(TokenAnnotation());
466 }
467
Manuel Klimek0be4b362012-12-03 20:55:42 +0000468 AnnotatingParser Parser(Line.Tokens, Annotations);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000469 Parser.parseLine();
470
471 determineTokenTypes();
472
473 for (int i = 1, e = Line.Tokens.size(); i != e; ++i) {
474 TokenAnnotation &Annotation = Annotations[i];
475
476 Annotation.CanBreakBefore =
477 canBreakBetween(Line.Tokens[i - 1], Line.Tokens[i]);
478
479 if (Line.Tokens[i].Tok.is(tok::colon)) {
480 if (Line.Tokens[0].Tok.is(tok::kw_case) || i == e - 1) {
481 Annotation.SpaceRequiredBefore = false;
482 } else {
483 Annotation.SpaceRequiredBefore = TokenAnnotation::TT_ConditionalExpr;
484 }
485 } else if (Annotations[i - 1].Type == TokenAnnotation::TT_UnaryOperator) {
486 Annotation.SpaceRequiredBefore = false;
487 } else if (Annotation.Type == TokenAnnotation::TT_UnaryOperator) {
488 Annotation.SpaceRequiredBefore =
489 Line.Tokens[i - 1].Tok.isNot(tok::l_paren);
490 } else if (Line.Tokens[i - 1].Tok.is(tok::greater) &&
491 Line.Tokens[i].Tok.is(tok::greater)) {
492 if (Annotation.Type == TokenAnnotation::TT_TemplateOpener &&
493 Annotations[i - 1].Type == TokenAnnotation::TT_TemplateOpener)
494 Annotation.SpaceRequiredBefore = Style.SplitTemplateClosingGreater;
Daniel Jaspera88bb452012-12-04 10:50:12 +0000495 else if (Annotation.Type == TokenAnnotation::TT_TemplateCloser &&
496 Annotations[i - 1].Type == TokenAnnotation::TT_TemplateCloser)
497 Annotation.SpaceRequiredBefore = Style.SplitTemplateClosingGreater;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000498 else
499 Annotation.SpaceRequiredBefore = false;
500 } else if (
501 Annotation.Type == TokenAnnotation::TT_BinaryOperator ||
502 Annotations[i - 1].Type == TokenAnnotation::TT_BinaryOperator) {
503 Annotation.SpaceRequiredBefore = true;
504 } else if (
Daniel Jaspera88bb452012-12-04 10:50:12 +0000505 Annotations[i - 1].Type == TokenAnnotation::TT_TemplateCloser &&
Daniel Jasperbac016b2012-12-03 18:12:45 +0000506 Line.Tokens[i].Tok.is(tok::l_paren)) {
507 Annotation.SpaceRequiredBefore = false;
508 } else {
509 Annotation.SpaceRequiredBefore =
510 spaceRequiredBetween(Line.Tokens[i - 1].Tok, Line.Tokens[i].Tok);
511 }
512
513 if (Annotations[i - 1].Type == TokenAnnotation::TT_LineComment ||
514 (Line.Tokens[i].Tok.is(tok::string_literal) &&
515 Line.Tokens[i - 1].Tok.is(tok::string_literal))) {
516 Annotation.MustBreakBefore = true;
517 }
518
519 if (Annotation.MustBreakBefore)
520 Annotation.CanBreakBefore = true;
521 }
522 }
523
524 const std::vector<TokenAnnotation> &getAnnotations() {
525 return Annotations;
526 }
527
528private:
529 void determineTokenTypes() {
530 for (int i = 0, e = Line.Tokens.size(); i != e; ++i) {
531 TokenAnnotation &Annotation = Annotations[i];
532 const FormatToken &Tok = Line.Tokens[i];
533
534 if (Tok.Tok.is(tok::star) || Tok.Tok.is(tok::amp))
535 Annotation.Type = determineStarAmpUsage(i);
536 else if (Tok.Tok.is(tok::minus) && Line.Tokens[i - 1].Tok.is(tok::equal))
537 Annotation.Type = TokenAnnotation::TT_UnaryOperator;
538 else if (isBinaryOperator(Line.Tokens[i]))
539 Annotation.Type = TokenAnnotation::TT_BinaryOperator;
540 else if (Tok.Tok.is(tok::comment)) {
541 StringRef Data(SourceMgr.getCharacterData(Tok.Tok.getLocation()),
542 Tok.Tok.getLength());
543 if (Data.startswith("//"))
544 Annotation.Type = TokenAnnotation::TT_LineComment;
545 else
546 Annotation.Type = TokenAnnotation::TT_BlockComment;
547 }
548 }
549 }
550
551 bool isBinaryOperator(const FormatToken &Tok) {
552 switch (Tok.Tok.getKind()) {
553 case tok::equal:
554 case tok::equalequal:
555 case tok::star:
556 //case tok::amp:
557 case tok::plus:
558 case tok::slash:
559 case tok::minus:
560 case tok::ampamp:
561 case tok::pipe:
562 case tok::pipepipe:
563 case tok::percent:
564 return true;
565 default:
566 return false;
567 }
568 }
569
570 TokenAnnotation::TokenType determineStarAmpUsage(unsigned Index) {
571 if (Index == Annotations.size())
572 return TokenAnnotation::TT_Unknown;
573
574 if (Index == 0 || Line.Tokens[Index - 1].Tok.is(tok::l_paren) ||
575 Line.Tokens[Index - 1].Tok.is(tok::comma) ||
576 Annotations[Index - 1].Type == TokenAnnotation::TT_BinaryOperator)
577 return TokenAnnotation::TT_UnaryOperator;
578
579 if (Line.Tokens[Index - 1].Tok.isLiteral() ||
580 Line.Tokens[Index + 1].Tok.isLiteral())
581 return TokenAnnotation::TT_BinaryOperator;
582
583 return TokenAnnotation::TT_PointerOrReference;
584 }
585
586 bool isIfForOrWhile(Token Tok) {
587 return Tok.is(tok::kw_if) || Tok.is(tok::kw_for) || Tok.is(tok::kw_while);
588 }
589
590 bool spaceRequiredBetween(Token Left, Token Right) {
591 if (Left.is(tok::kw_template) && Right.is(tok::less))
592 return true;
593 if (Left.is(tok::arrow) || Right.is(tok::arrow))
594 return false;
595 if (Left.is(tok::exclaim) || Left.is(tok::tilde))
596 return false;
597 if (Left.is(tok::less) || Right.is(tok::greater) || Right.is(tok::less))
598 return false;
599 if (Left.is(tok::amp) || Left.is(tok::star))
600 return Right.isLiteral() || Style.PointerAndReferenceBindToType;
601 if (Right.is(tok::star) && Left.is(tok::l_paren))
602 return false;
603 if (Right.is(tok::amp) || Right.is(tok::star))
604 return Left.isLiteral() || !Style.PointerAndReferenceBindToType;
605 if (Left.is(tok::l_square) || Right.is(tok::l_square) ||
606 Right.is(tok::r_square))
607 return false;
608 if (Left.is(tok::coloncolon) || Right.is(tok::coloncolon))
609 return false;
610 if (Left.is(tok::period) || Right.is(tok::period))
611 return false;
612 if (Left.is(tok::colon) || Right.is(tok::colon))
613 return true;
614 if ((Left.is(tok::plusplus) && Right.isAnyIdentifier()) ||
615 (Left.isAnyIdentifier() && Right.is(tok::plusplus)) ||
616 (Left.is(tok::minusminus) && Right.isAnyIdentifier()) ||
617 (Left.isAnyIdentifier() && Right.is(tok::minusminus)))
618 return false;
619 if (Left.is(tok::l_paren))
620 return false;
621 if (Left.is(tok::hash))
622 return false;
623 if (Right.is(tok::r_paren) || Right.is(tok::semi) || Right.is(tok::comma))
624 return false;
625 if (Right.is(tok::l_paren)) {
626 return !Left.isAnyIdentifier() || isIfForOrWhile(Left);
627 }
628 return true;
629 }
630
631 bool canBreakBetween(const FormatToken &Left, const FormatToken &Right) {
632 if (Right.Tok.is(tok::r_paren))
633 return false;
634 if (isBinaryOperator(Left))
635 return true;
636 return Right.Tok.is(tok::colon) || Left.Tok.is(tok::comma) || Left.Tok.is(
637 tok::semi) || Left.Tok.is(tok::equal) || Left.Tok.is(tok::ampamp) ||
638 (Left.Tok.is(tok::l_paren) && !Right.Tok.is(tok::r_paren));
639 }
640
641 const UnwrappedLine &Line;
642 FormatStyle Style;
643 SourceManager &SourceMgr;
644 std::vector<TokenAnnotation> Annotations;
645};
646
647class Formatter : public UnwrappedLineConsumer {
648public:
649 Formatter(const FormatStyle &Style, Lexer &Lex, SourceManager &SourceMgr,
650 const std::vector<CharSourceRange> &Ranges)
651 : Style(Style),
652 Lex(Lex),
653 SourceMgr(SourceMgr),
654 Ranges(Ranges) {
655 }
656
657 tooling::Replacements format() {
658 UnwrappedLineParser Parser(Lex, SourceMgr, *this);
659 Parser.parse();
660 return Replaces;
661 }
662
663private:
664 virtual void formatUnwrappedLine(const UnwrappedLine &TheLine) {
665 if (TheLine.Tokens.size() == 0)
666 return;
667
668 CharSourceRange LineRange =
669 CharSourceRange::getTokenRange(TheLine.Tokens.front().Tok.getLocation(),
670 TheLine.Tokens.back().Tok.getLocation());
671
672 for (unsigned i = 0, e = Ranges.size(); i != e; ++i) {
673 if (SourceMgr.isBeforeInTranslationUnit(LineRange.getEnd(),
674 Ranges[i].getBegin()) ||
675 SourceMgr.isBeforeInTranslationUnit(Ranges[i].getEnd(),
676 LineRange.getBegin()))
677 continue;
678
679 TokenAnnotator Annotator(TheLine, Style, SourceMgr);
680 Annotator.annotate();
681 UnwrappedLineFormatter Formatter(Style, SourceMgr, TheLine,
682 Annotator.getAnnotations(), Replaces);
683 Formatter.format();
684 return;
685 }
686 }
687
688 FormatStyle Style;
689 Lexer &Lex;
690 SourceManager &SourceMgr;
691 tooling::Replacements Replaces;
692 std::vector<CharSourceRange> Ranges;
693};
694
695tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
696 SourceManager &SourceMgr,
697 std::vector<CharSourceRange> Ranges) {
698 Formatter formatter(Style, Lex, SourceMgr, Ranges);
699 return formatter.format();
700}
701
702} // namespace format
703} // namespace clang