blob: eabc8cff285bcf6fd8d92d04ffcce6671d3f798f [file] [log] [blame]
Daniel Jasper32d28ee2013-01-29 21:01:14 +00001//===--- TokenAnnotator.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 a token annotator, i.e. creates
12/// \c AnnotatedTokens out of \c FormatTokens with required extra information.
13///
14//===----------------------------------------------------------------------===//
15
16#include "TokenAnnotator.h"
17#include "clang/Basic/SourceManager.h"
18#include "clang/Lex/Lexer.h"
19
20namespace clang {
21namespace format {
22
23/// \brief Returns if a token is an Objective-C selector name.
24///
25/// For example, "bar" is a selector name in [foo bar:(4 + 5)].
26static bool isObjCSelectorName(const AnnotatedToken &Tok) {
27 return Tok.is(tok::identifier) && !Tok.Children.empty() &&
28 Tok.Children[0].is(tok::colon) &&
29 Tok.Children[0].Type == TT_ObjCMethodExpr;
30}
31
32static bool isBinaryOperator(const AnnotatedToken &Tok) {
33 // Comma is a binary operator, but does not behave as such wrt. formatting.
34 return getPrecedence(Tok) > prec::Comma;
35}
36
37/// \brief A parser that gathers additional information about tokens.
38///
39/// The \c TokenAnnotator tries to matches parenthesis and square brakets and
40/// store a parenthesis levels. It also tries to resolve matching "<" and ">"
41/// into template parameter lists.
42class AnnotatingParser {
43public:
44 AnnotatingParser(AnnotatedToken &RootToken)
45 : CurrentToken(&RootToken), KeywordVirtualFound(false),
46 ColonIsObjCMethodExpr(false), ColonIsForRangeExpr(false) {
47 }
48
49 /// \brief A helper class to manage AnnotatingParser::ColonIsObjCMethodExpr.
50 struct ObjCSelectorRAII {
51 AnnotatingParser &P;
52 bool ColonWasObjCMethodExpr;
53
54 ObjCSelectorRAII(AnnotatingParser &P)
55 : P(P), ColonWasObjCMethodExpr(P.ColonIsObjCMethodExpr) {
56 }
57
58 ~ObjCSelectorRAII() { P.ColonIsObjCMethodExpr = ColonWasObjCMethodExpr; }
59
60 void markStart(AnnotatedToken &Left) {
61 P.ColonIsObjCMethodExpr = true;
62 Left.Type = TT_ObjCMethodExpr;
63 }
64
65 void markEnd(AnnotatedToken &Right) { Right.Type = TT_ObjCMethodExpr; }
66 };
67
68 bool parseAngle() {
69 if (CurrentToken == NULL)
70 return false;
71 AnnotatedToken *Left = CurrentToken->Parent;
72 while (CurrentToken != NULL) {
73 if (CurrentToken->is(tok::greater)) {
74 Left->MatchingParen = CurrentToken;
75 CurrentToken->MatchingParen = Left;
76 CurrentToken->Type = TT_TemplateCloser;
77 next();
78 return true;
79 }
80 if (CurrentToken->is(tok::r_paren) || CurrentToken->is(tok::r_square) ||
81 CurrentToken->is(tok::r_brace))
82 return false;
83 if (CurrentToken->is(tok::pipepipe) || CurrentToken->is(tok::ampamp) ||
84 CurrentToken->is(tok::question) || CurrentToken->is(tok::colon))
85 return false;
86 if (CurrentToken->is(tok::comma))
87 ++Left->ParameterCount;
88 if (!consumeToken())
89 return false;
90 }
91 return false;
92 }
93
94 bool parseParens(bool LookForDecls = false) {
95 if (CurrentToken == NULL)
96 return false;
97 bool StartsObjCMethodExpr = false;
98 AnnotatedToken *Left = CurrentToken->Parent;
99 if (CurrentToken->is(tok::caret)) {
100 // ^( starts a block.
101 Left->Type = TT_ObjCBlockLParen;
102 } else if (AnnotatedToken *MaybeSel = Left->Parent) {
103 // @selector( starts a selector.
104 if (MaybeSel->isObjCAtKeyword(tok::objc_selector) && MaybeSel->Parent &&
105 MaybeSel->Parent->is(tok::at)) {
106 StartsObjCMethodExpr = true;
107 }
108 }
109
110 ObjCSelectorRAII objCSelector(*this);
111 if (StartsObjCMethodExpr)
112 objCSelector.markStart(*Left);
113
114 while (CurrentToken != NULL) {
115 // LookForDecls is set when "if (" has been seen. Check for
116 // 'identifier' '*' 'identifier' followed by not '=' -- this
117 // '*' has to be a binary operator but determineStarAmpUsage() will
118 // categorize it as an unary operator, so set the right type here.
119 if (LookForDecls && !CurrentToken->Children.empty()) {
120 AnnotatedToken &Prev = *CurrentToken->Parent;
121 AnnotatedToken &Next = CurrentToken->Children[0];
122 if (Prev.Parent->is(tok::identifier) &&
123 (Prev.is(tok::star) || Prev.is(tok::amp)) &&
124 CurrentToken->is(tok::identifier) && Next.isNot(tok::equal)) {
125 Prev.Type = TT_BinaryOperator;
126 LookForDecls = false;
127 }
128 }
129
130 if (CurrentToken->is(tok::r_paren)) {
131 Left->MatchingParen = CurrentToken;
132 CurrentToken->MatchingParen = Left;
133
134 if (StartsObjCMethodExpr)
135 objCSelector.markEnd(*CurrentToken);
136
137 next();
138 return true;
139 }
140 if (CurrentToken->is(tok::r_square) || CurrentToken->is(tok::r_brace))
141 return false;
142 if (CurrentToken->is(tok::comma))
143 ++Left->ParameterCount;
144 if (!consumeToken())
145 return false;
146 }
147 return false;
148 }
149
150 bool parseSquare() {
151 if (!CurrentToken)
152 return false;
153
154 // A '[' could be an index subscript (after an indentifier or after
155 // ')' or ']'), or it could be the start of an Objective-C method
156 // expression.
157 AnnotatedToken *Left = CurrentToken->Parent;
158 bool StartsObjCMethodExpr =
159 !Left->Parent || Left->Parent->is(tok::colon) ||
160 Left->Parent->is(tok::l_square) || Left->Parent->is(tok::l_paren) ||
161 Left->Parent->is(tok::kw_return) || Left->Parent->is(tok::kw_throw) ||
162 getBinOpPrecedence(Left->Parent->FormatTok.Tok.getKind(), true, true) >
163 prec::Unknown;
164
165 ObjCSelectorRAII objCSelector(*this);
166 if (StartsObjCMethodExpr)
167 objCSelector.markStart(*Left);
168
169 while (CurrentToken != NULL) {
170 if (CurrentToken->is(tok::r_square)) {
171 if (!CurrentToken->Children.empty() &&
172 CurrentToken->Children[0].is(tok::l_paren)) {
173 // An ObjC method call can't be followed by an open parenthesis.
174 // FIXME: Do we incorrectly label ":" with this?
175 StartsObjCMethodExpr = false;
176 Left->Type = TT_Unknown;
177 }
178 if (StartsObjCMethodExpr)
179 objCSelector.markEnd(*CurrentToken);
180 Left->MatchingParen = CurrentToken;
181 CurrentToken->MatchingParen = Left;
182 next();
183 return true;
184 }
185 if (CurrentToken->is(tok::r_paren) || CurrentToken->is(tok::r_brace))
186 return false;
187 if (CurrentToken->is(tok::comma))
188 ++Left->ParameterCount;
189 if (!consumeToken())
190 return false;
191 }
192 return false;
193 }
194
195 bool parseBrace() {
196 // Lines are fine to end with '{'.
197 if (CurrentToken == NULL)
198 return true;
199 AnnotatedToken *Left = CurrentToken->Parent;
200 while (CurrentToken != NULL) {
201 if (CurrentToken->is(tok::r_brace)) {
202 Left->MatchingParen = CurrentToken;
203 CurrentToken->MatchingParen = Left;
204 next();
205 return true;
206 }
207 if (CurrentToken->is(tok::r_paren) || CurrentToken->is(tok::r_square))
208 return false;
209 if (!consumeToken())
210 return false;
211 }
212 return true;
213 }
214
215 bool parseConditional() {
216 while (CurrentToken != NULL) {
217 if (CurrentToken->is(tok::colon)) {
218 CurrentToken->Type = TT_ConditionalExpr;
219 next();
220 return true;
221 }
222 if (!consumeToken())
223 return false;
224 }
225 return false;
226 }
227
228 bool parseTemplateDeclaration() {
229 if (CurrentToken != NULL && CurrentToken->is(tok::less)) {
230 CurrentToken->Type = TT_TemplateOpener;
231 next();
232 if (!parseAngle())
233 return false;
234 CurrentToken->Parent->ClosesTemplateDeclaration = true;
235 return true;
236 }
237 return false;
238 }
239
240 bool consumeToken() {
241 AnnotatedToken *Tok = CurrentToken;
242 next();
243 switch (Tok->FormatTok.Tok.getKind()) {
244 case tok::plus:
245 case tok::minus:
246 // At the start of the line, +/- specific ObjectiveC method
247 // declarations.
248 if (Tok->Parent == NULL)
249 Tok->Type = TT_ObjCMethodSpecifier;
250 break;
251 case tok::colon:
252 // Colons from ?: are handled in parseConditional().
253 if (Tok->Parent->is(tok::r_paren))
254 Tok->Type = TT_CtorInitializerColon;
255 else if (ColonIsObjCMethodExpr)
256 Tok->Type = TT_ObjCMethodExpr;
257 else if (ColonIsForRangeExpr)
258 Tok->Type = TT_RangeBasedForLoopColon;
259 break;
260 case tok::kw_if:
261 case tok::kw_while:
262 if (CurrentToken != NULL && CurrentToken->is(tok::l_paren)) {
263 next();
264 if (!parseParens(/*LookForDecls=*/ true))
265 return false;
266 }
267 break;
268 case tok::kw_for:
269 ColonIsForRangeExpr = true;
270 next();
271 if (!parseParens())
272 return false;
273 break;
274 case tok::l_paren:
275 if (!parseParens())
276 return false;
277 break;
278 case tok::l_square:
279 if (!parseSquare())
280 return false;
281 break;
282 case tok::l_brace:
283 if (!parseBrace())
284 return false;
285 break;
286 case tok::less:
287 if (parseAngle())
288 Tok->Type = TT_TemplateOpener;
289 else {
290 Tok->Type = TT_BinaryOperator;
291 CurrentToken = Tok;
292 next();
293 }
294 break;
295 case tok::r_paren:
296 case tok::r_square:
297 return false;
298 case tok::r_brace:
299 // Lines can start with '}'.
300 if (Tok->Parent != NULL)
301 return false;
302 break;
303 case tok::greater:
304 Tok->Type = TT_BinaryOperator;
305 break;
306 case tok::kw_operator:
307 if (CurrentToken != NULL && CurrentToken->is(tok::l_paren)) {
308 CurrentToken->Type = TT_OverloadedOperator;
309 next();
310 if (CurrentToken != NULL && CurrentToken->is(tok::r_paren)) {
311 CurrentToken->Type = TT_OverloadedOperator;
312 next();
313 }
314 } else {
315 while (CurrentToken != NULL && CurrentToken->isNot(tok::l_paren)) {
316 CurrentToken->Type = TT_OverloadedOperator;
317 next();
318 }
319 }
320 break;
321 case tok::question:
322 parseConditional();
323 break;
324 case tok::kw_template:
325 parseTemplateDeclaration();
326 break;
327 default:
328 break;
329 }
330 return true;
331 }
332
333 void parseIncludeDirective() {
334 next();
335 if (CurrentToken != NULL && CurrentToken->is(tok::less)) {
336 next();
337 while (CurrentToken != NULL) {
338 if (CurrentToken->isNot(tok::comment) ||
339 !CurrentToken->Children.empty())
340 CurrentToken->Type = TT_ImplicitStringLiteral;
341 next();
342 }
343 } else {
344 while (CurrentToken != NULL) {
345 next();
346 }
347 }
348 }
349
350 void parseWarningOrError() {
351 next();
352 // We still want to format the whitespace left of the first token of the
353 // warning or error.
354 next();
355 while (CurrentToken != NULL) {
356 CurrentToken->Type = TT_ImplicitStringLiteral;
357 next();
358 }
359 }
360
361 void parsePreprocessorDirective() {
362 next();
363 if (CurrentToken == NULL)
364 return;
365 // Hashes in the middle of a line can lead to any strange token
366 // sequence.
367 if (CurrentToken->FormatTok.Tok.getIdentifierInfo() == NULL)
368 return;
369 switch (CurrentToken->FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
370 case tok::pp_include:
371 case tok::pp_import:
372 parseIncludeDirective();
373 break;
374 case tok::pp_error:
375 case tok::pp_warning:
376 parseWarningOrError();
377 break;
378 default:
379 break;
380 }
381 }
382
383 LineType parseLine() {
384 int PeriodsAndArrows = 0;
385 bool CanBeBuilderTypeStmt = true;
386 if (CurrentToken->is(tok::hash)) {
387 parsePreprocessorDirective();
388 return LT_PreprocessorDirective;
389 }
390 while (CurrentToken != NULL) {
391 if (CurrentToken->is(tok::kw_virtual))
392 KeywordVirtualFound = true;
393 if (CurrentToken->is(tok::period) || CurrentToken->is(tok::arrow))
394 ++PeriodsAndArrows;
395 if (getPrecedence(*CurrentToken) > prec::Assignment &&
396 CurrentToken->isNot(tok::less) && CurrentToken->isNot(tok::greater))
397 CanBeBuilderTypeStmt = false;
398 if (!consumeToken())
399 return LT_Invalid;
400 }
401 if (KeywordVirtualFound)
402 return LT_VirtualFunctionDecl;
403
404 // Assume a builder-type call if there are 2 or more "." and "->".
405 if (PeriodsAndArrows >= 2 && CanBeBuilderTypeStmt)
406 return LT_BuilderTypeCall;
407
408 return LT_Other;
409 }
410
411 void next() {
412 if (CurrentToken != NULL && !CurrentToken->Children.empty())
413 CurrentToken = &CurrentToken->Children[0];
414 else
415 CurrentToken = NULL;
416 }
417
418private:
419 AnnotatedToken *CurrentToken;
420 bool KeywordVirtualFound;
421 bool ColonIsObjCMethodExpr;
422 bool ColonIsForRangeExpr;
423};
424
425void TokenAnnotator::annotate() {
426 AnnotatingParser Parser(Line.First);
427 Line.Type = Parser.parseLine();
428 if (Line.Type == LT_Invalid)
429 return;
430
431 bool LookForFunctionName = Line.MustBeDeclaration;
432 determineTokenTypes(Line.First, /*IsExpression=*/ false, LookForFunctionName);
433
434 if (Line.First.Type == TT_ObjCMethodSpecifier)
435 Line.Type = LT_ObjCMethodDecl;
436 else if (Line.First.Type == TT_ObjCDecl)
437 Line.Type = LT_ObjCDecl;
438 else if (Line.First.Type == TT_ObjCProperty)
439 Line.Type = LT_ObjCProperty;
440
441 Line.First.SpaceRequiredBefore = true;
442 Line.First.MustBreakBefore = Line.First.FormatTok.MustBreakBefore;
443 Line.First.CanBreakBefore = Line.First.MustBreakBefore;
444
445 Line.First.TotalLength = Line.First.FormatTok.TokenLength;
446 if (!Line.First.Children.empty())
447 calculateExtraInformation(Line.First.Children[0]);
448}
449
450void TokenAnnotator::calculateExtraInformation(AnnotatedToken &Current) {
451 Current.SpaceRequiredBefore = spaceRequiredBefore(Current);
452
453 if (Current.FormatTok.MustBreakBefore) {
454 Current.MustBreakBefore = true;
455 } else {
456 if (Current.Type == TT_LineComment) {
457 Current.MustBreakBefore = Current.FormatTok.NewlinesBefore > 0;
458 } else if ((Current.Parent->is(tok::comment) &&
459 Current.FormatTok.NewlinesBefore > 0) ||
460 (Current.is(tok::string_literal) &&
461 Current.Parent->is(tok::string_literal))) {
462 Current.MustBreakBefore = true;
463 } else {
464 Current.MustBreakBefore = false;
465 }
466 }
467 Current.CanBreakBefore = Current.MustBreakBefore || canBreakBefore(Current);
468 if (Current.MustBreakBefore)
469 Current.TotalLength = Current.Parent->TotalLength + Style.ColumnLimit;
470 else
471 Current.TotalLength =
472 Current.Parent->TotalLength + Current.FormatTok.TokenLength +
473 (Current.SpaceRequiredBefore ? 1 : 0);
474 // FIXME: Only calculate this if CanBreakBefore is true once static
475 // initializers etc. are sorted out.
476 Current.SplitPenalty = splitPenalty(Current);
477 if (!Current.Children.empty())
478 calculateExtraInformation(Current.Children[0]);
479}
480
481unsigned TokenAnnotator::splitPenalty(const AnnotatedToken &Tok) {
482 const AnnotatedToken &Left = *Tok.Parent;
483 const AnnotatedToken &Right = Tok;
484
485 if (Left.is(tok::l_brace) && Right.isNot(tok::l_brace))
486 return 50;
487 if (Left.is(tok::equal) && Right.is(tok::l_brace))
488 return 150;
489 if (Left.is(tok::coloncolon))
490 return 500;
491
492 if (Left.Type == TT_RangeBasedForLoopColon)
493 return 5;
494
495 if (Right.is(tok::arrow) || Right.is(tok::period)) {
496 if (Left.is(tok::r_paren) && Line.Type == LT_BuilderTypeCall)
497 return 5; // Should be smaller than breaking at a nested comma.
498 return 150;
499 }
500
501 // In for-loops, prefer breaking at ',' and ';'.
502 if (Line.First.is(tok::kw_for) &&
503 (Left.isNot(tok::comma) && Left.isNot(tok::semi)))
504 return 20;
505
506 if (Left.is(tok::semi) || Left.is(tok::comma))
507 return 0;
508
509 // In Objective-C method expressions, prefer breaking before "param:" over
510 // breaking after it.
511 if (isObjCSelectorName(Right))
512 return 0;
513 if (Right.is(tok::colon) && Right.Type == TT_ObjCMethodExpr)
514 return 20;
515
516 if (Left.is(tok::l_paren))
517 return 20;
518 // FIXME: The penalty for a trailing "<" or "[" being higher than the
519 // penalty for a trainling "(" is a temporary workaround until we can
520 // properly avoid breaking in array subscripts or template parameters.
521 if (Left.is(tok::l_square) || Left.Type == TT_TemplateOpener)
522 return 50;
523
524 if (Left.Type == TT_ConditionalExpr)
525 return prec::Assignment;
526 prec::Level Level = getPrecedence(Left);
527
528 if (Level != prec::Unknown)
529 return Level;
530
531 return 3;
532}
533
534void TokenAnnotator::determineTokenTypes(
535 AnnotatedToken &Current, bool IsExpression, bool LookForFunctionName) {
536 if (getPrecedence(Current) == prec::Assignment) {
537 IsExpression = true;
538 AnnotatedToken *Previous = Current.Parent;
539 while (Previous != NULL) {
540 if (Previous->Type == TT_BinaryOperator &&
541 (Previous->is(tok::star) || Previous->is(tok::amp))) {
542 Previous->Type = TT_PointerOrReference;
543 }
544 Previous = Previous->Parent;
545 }
546 }
547 if (Current.is(tok::kw_return) || Current.is(tok::kw_throw) ||
548 (Current.is(tok::l_paren) && !Line.MustBeDeclaration &&
549 (Current.Parent == NULL || Current.Parent->isNot(tok::kw_for))))
550 IsExpression = true;
551
552 if (Current.Type == TT_Unknown) {
553 if (LookForFunctionName && Current.is(tok::l_paren)) {
554 findFunctionName(&Current);
555 LookForFunctionName = false;
556 } else if (Current.is(tok::star) || Current.is(tok::amp)) {
557 Current.Type = determineStarAmpUsage(Current, IsExpression);
558 } else if (Current.is(tok::minus) || Current.is(tok::plus) ||
559 Current.is(tok::caret)) {
560 Current.Type = determinePlusMinusCaretUsage(Current);
561 } else if (Current.is(tok::minusminus) || Current.is(tok::plusplus)) {
562 Current.Type = determineIncrementUsage(Current);
563 } else if (Current.is(tok::exclaim)) {
564 Current.Type = TT_UnaryOperator;
565 } else if (isBinaryOperator(Current)) {
566 Current.Type = TT_BinaryOperator;
567 } else if (Current.is(tok::comment)) {
568 std::string Data(Lexer::getSpelling(Current.FormatTok.Tok, SourceMgr,
569 Lex.getLangOpts()));
570 if (StringRef(Data).startswith("//"))
571 Current.Type = TT_LineComment;
572 else
573 Current.Type = TT_BlockComment;
574 } else if (Current.is(tok::r_paren) &&
575 (Current.Parent->Type == TT_PointerOrReference ||
576 Current.Parent->Type == TT_TemplateCloser) &&
577 (Current.Children.empty() ||
578 (Current.Children[0].isNot(tok::equal) &&
579 Current.Children[0].isNot(tok::semi) &&
580 Current.Children[0].isNot(tok::l_brace)))) {
581 // FIXME: We need to get smarter and understand more cases of casts.
582 Current.Type = TT_CastRParen;
583 } else if (Current.is(tok::at) && Current.Children.size()) {
584 switch (Current.Children[0].FormatTok.Tok.getObjCKeywordID()) {
585 case tok::objc_interface:
586 case tok::objc_implementation:
587 case tok::objc_protocol:
588 Current.Type = TT_ObjCDecl;
589 break;
590 case tok::objc_property:
591 Current.Type = TT_ObjCProperty;
592 break;
593 default:
594 break;
595 }
596 }
597 }
598
599 if (!Current.Children.empty())
600 determineTokenTypes(Current.Children[0], IsExpression, LookForFunctionName);
601}
602
603void TokenAnnotator::findFunctionName(AnnotatedToken *Current) {
604 AnnotatedToken *Parent = Current->Parent;
605 while (Parent != NULL && Parent->Parent != NULL) {
606 if (Parent->is(tok::identifier) &&
607 (Parent->Parent->is(tok::identifier) || Parent->Parent->Type ==
608 TT_PointerOrReference || Parent->Parent->Type == TT_TemplateCloser)) {
609 Parent->Type = TT_StartOfName;
610 break;
611 }
612 Parent = Parent->Parent;
613 }
614}
615
616TokenType TokenAnnotator::determineStarAmpUsage(const AnnotatedToken &Tok,
617 bool IsExpression) {
618 const AnnotatedToken *PrevToken = getPreviousToken(Tok);
619 if (PrevToken == NULL)
620 return TT_UnaryOperator;
621
622 const AnnotatedToken *NextToken = getNextToken(Tok);
623 if (NextToken == NULL)
624 return TT_Unknown;
625
626 if (NextToken->is(tok::l_square) && NextToken->Type != TT_ObjCMethodExpr)
627 return TT_PointerOrReference;
628
629 if (PrevToken->is(tok::l_paren) || PrevToken->is(tok::l_square) ||
630 PrevToken->is(tok::l_brace) || PrevToken->is(tok::comma) ||
631 PrevToken->is(tok::kw_return) || PrevToken->is(tok::colon) ||
632 PrevToken->Type == TT_BinaryOperator ||
633 PrevToken->Type == TT_UnaryOperator || PrevToken->Type == TT_CastRParen)
634 return TT_UnaryOperator;
635
636 if (PrevToken->FormatTok.Tok.isLiteral() || PrevToken->is(tok::r_paren) ||
637 PrevToken->is(tok::r_square) || NextToken->FormatTok.Tok.isLiteral() ||
638 NextToken->is(tok::plus) || NextToken->is(tok::minus) ||
639 NextToken->is(tok::plusplus) || NextToken->is(tok::minusminus) ||
640 NextToken->is(tok::tilde) || NextToken->is(tok::exclaim) ||
641 NextToken->is(tok::l_paren) || NextToken->is(tok::l_square) ||
642 NextToken->is(tok::kw_alignof) || NextToken->is(tok::kw_sizeof))
643 return TT_BinaryOperator;
644
645 if (NextToken->is(tok::comma) || NextToken->is(tok::r_paren) ||
646 NextToken->is(tok::greater))
647 return TT_PointerOrReference;
648
649 // It is very unlikely that we are going to find a pointer or reference type
650 // definition on the RHS of an assignment.
651 if (IsExpression)
652 return TT_BinaryOperator;
653
654 return TT_PointerOrReference;
655}
656
657TokenType
658TokenAnnotator::determinePlusMinusCaretUsage(const AnnotatedToken &Tok) {
659 const AnnotatedToken *PrevToken = getPreviousToken(Tok);
660 if (PrevToken == NULL)
661 return TT_UnaryOperator;
662
663 // Use heuristics to recognize unary operators.
664 if (PrevToken->is(tok::equal) || PrevToken->is(tok::l_paren) ||
665 PrevToken->is(tok::comma) || PrevToken->is(tok::l_square) ||
666 PrevToken->is(tok::question) || PrevToken->is(tok::colon) ||
667 PrevToken->is(tok::kw_return) || PrevToken->is(tok::kw_case) ||
668 PrevToken->is(tok::at) || PrevToken->is(tok::l_brace))
669 return TT_UnaryOperator;
670
671 // There can't be to consecutive binary operators.
672 if (PrevToken->Type == TT_BinaryOperator)
673 return TT_UnaryOperator;
674
675 // Fall back to marking the token as binary operator.
676 return TT_BinaryOperator;
677}
678
679TokenType TokenAnnotator::determineIncrementUsage(const AnnotatedToken &Tok) {
680 const AnnotatedToken *PrevToken = getPreviousToken(Tok);
681 if (PrevToken == NULL)
682 return TT_UnaryOperator;
683 if (PrevToken->is(tok::r_paren) || PrevToken->is(tok::r_square) ||
684 PrevToken->is(tok::identifier))
685 return TT_TrailingUnaryOperator;
686
687 return TT_UnaryOperator;
688}
689
690bool TokenAnnotator::spaceRequiredBetween(const AnnotatedToken &Left,
691 const AnnotatedToken &Right) {
692 if (Right.is(tok::hashhash))
693 return Left.is(tok::hash);
694 if (Left.is(tok::hashhash) || Left.is(tok::hash))
695 return Right.is(tok::hash);
696 if (Right.is(tok::r_paren) || Right.is(tok::semi) || Right.is(tok::comma))
697 return false;
698 if (Right.is(tok::less) &&
699 (Left.is(tok::kw_template) ||
700 (Line.Type == LT_ObjCDecl && Style.ObjCSpaceBeforeProtocolList)))
701 return true;
702 if (Left.is(tok::arrow) || Right.is(tok::arrow))
703 return false;
704 if (Left.is(tok::exclaim) || Left.is(tok::tilde))
705 return false;
706 if (Left.is(tok::at) &&
707 (Right.is(tok::identifier) || Right.is(tok::string_literal) ||
708 Right.is(tok::char_constant) || Right.is(tok::numeric_constant) ||
709 Right.is(tok::l_paren) || Right.is(tok::l_brace) ||
710 Right.is(tok::kw_true) || Right.is(tok::kw_false)))
711 return false;
712 if (Left.is(tok::coloncolon))
713 return false;
714 if (Right.is(tok::coloncolon))
715 return Left.isNot(tok::identifier) && Left.isNot(tok::greater);
716 if (Left.is(tok::less) || Right.is(tok::greater) || Right.is(tok::less))
717 return false;
718 if (Right.is(tok::amp) || Right.is(tok::star))
719 return Left.FormatTok.Tok.isLiteral() ||
720 (Left.isNot(tok::star) && Left.isNot(tok::amp) &&
721 !Style.PointerAndReferenceBindToType);
722 if (Left.is(tok::amp) || Left.is(tok::star))
723 return Right.FormatTok.Tok.isLiteral() ||
724 Style.PointerAndReferenceBindToType;
725 if (Right.is(tok::star) && Left.is(tok::l_paren))
726 return false;
727 if (Left.is(tok::l_square) || Right.is(tok::r_square))
728 return false;
729 if (Right.is(tok::l_square) && Right.Type != TT_ObjCMethodExpr)
730 return false;
731 if (Left.is(tok::period) || Right.is(tok::period))
732 return false;
733 if (Left.is(tok::colon))
734 return Left.Type != TT_ObjCMethodExpr;
735 if (Right.is(tok::colon))
736 return Right.Type != TT_ObjCMethodExpr;
737 if (Left.is(tok::l_paren))
738 return false;
739 if (Right.is(tok::l_paren)) {
740 return Line.Type == LT_ObjCDecl || Left.is(tok::kw_if) ||
741 Left.is(tok::kw_for) || Left.is(tok::kw_while) ||
742 Left.is(tok::kw_switch) || Left.is(tok::kw_return) ||
743 Left.is(tok::kw_catch) || Left.is(tok::kw_new) ||
744 Left.is(tok::kw_delete);
745 }
746 if (Left.is(tok::at) &&
747 Right.FormatTok.Tok.getObjCKeywordID() != tok::objc_not_keyword)
748 return false;
749 if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
750 return false;
751 return true;
752}
753
754bool TokenAnnotator::spaceRequiredBefore(const AnnotatedToken &Tok) {
755 if (Line.Type == LT_ObjCMethodDecl) {
756 if (Tok.is(tok::identifier) && !Tok.Children.empty() &&
757 Tok.Children[0].is(tok::colon) && Tok.Parent->is(tok::identifier))
758 return true;
759 if (Tok.is(tok::colon))
760 return false;
761 if (Tok.Parent->Type == TT_ObjCMethodSpecifier)
762 return true;
763 if (Tok.Parent->is(tok::r_paren) && Tok.is(tok::identifier))
764 // Don't space between ')' and <id>
765 return false;
766 if (Tok.Parent->is(tok::colon) && Tok.is(tok::l_paren))
767 // Don't space between ':' and '('
768 return false;
769 }
770 if (Line.Type == LT_ObjCProperty &&
771 (Tok.is(tok::equal) || Tok.Parent->is(tok::equal)))
772 return false;
773
774 if (Tok.Parent->is(tok::comma))
775 return true;
776 if (Tok.Type == TT_CtorInitializerColon || Tok.Type == TT_ObjCBlockLParen)
777 return true;
778 if (Tok.Type == TT_OverloadedOperator)
779 return Tok.is(tok::identifier) || Tok.is(tok::kw_new) ||
780 Tok.is(tok::kw_delete) || Tok.is(tok::kw_bool);
781 if (Tok.Parent->Type == TT_OverloadedOperator)
782 return false;
783 if (Tok.is(tok::colon))
784 return Line.First.isNot(tok::kw_case) && !Tok.Children.empty() &&
785 Tok.Type != TT_ObjCMethodExpr;
786 if (Tok.Parent->Type == TT_UnaryOperator || Tok.Parent->Type == TT_CastRParen)
787 return false;
788 if (Tok.Type == TT_UnaryOperator)
789 return Tok.Parent->isNot(tok::l_paren) &&
790 Tok.Parent->isNot(tok::l_square) && Tok.Parent->isNot(tok::at) &&
791 (Tok.Parent->isNot(tok::colon) ||
792 Tok.Parent->Type != TT_ObjCMethodExpr);
793 if (Tok.Parent->is(tok::greater) && Tok.is(tok::greater)) {
794 return Tok.Type == TT_TemplateCloser && Tok.Parent->Type ==
795 TT_TemplateCloser && Style.SplitTemplateClosingGreater;
796 }
797 if (Tok.Type == TT_BinaryOperator || Tok.Parent->Type == TT_BinaryOperator)
798 return true;
799 if (Tok.Parent->Type == TT_TemplateCloser && Tok.is(tok::l_paren))
800 return false;
801 if (Tok.is(tok::less) && Line.First.is(tok::hash))
802 return true;
803 if (Tok.Type == TT_TrailingUnaryOperator)
804 return false;
805 return spaceRequiredBetween(*Tok.Parent, Tok);
806}
807
808bool TokenAnnotator::canBreakBefore(const AnnotatedToken &Right) {
809 const AnnotatedToken &Left = *Right.Parent;
810 if (Line.Type == LT_ObjCMethodDecl) {
811 if (Right.is(tok::identifier) && !Right.Children.empty() &&
812 Right.Children[0].is(tok::colon) && Left.is(tok::identifier))
813 return true;
814 if (Right.is(tok::identifier) && Left.is(tok::l_paren) &&
815 Left.Parent->is(tok::colon))
816 // Don't break this identifier as ':' or identifier
817 // before it will break.
818 return false;
819 if (Right.is(tok::colon) && Left.is(tok::identifier) && Left.CanBreakBefore)
820 // Don't break at ':' if identifier before it can beak.
821 return false;
822 }
823 if (Right.Type == TT_StartOfName && Style.AllowReturnTypeOnItsOwnLine)
824 return true;
825 if (Right.is(tok::colon) && Right.Type == TT_ObjCMethodExpr)
826 return false;
827 if (Left.is(tok::colon) && Left.Type == TT_ObjCMethodExpr)
828 return true;
829 if (isObjCSelectorName(Right))
830 return true;
831 if (Left.ClosesTemplateDeclaration)
832 return true;
833 if (Right.Type == TT_ConditionalExpr || Right.is(tok::question))
834 return true;
835 if (Left.Type == TT_RangeBasedForLoopColon)
836 return true;
837 if (Left.Type == TT_PointerOrReference || Left.Type == TT_TemplateCloser ||
838 Left.Type == TT_UnaryOperator || Left.Type == TT_ConditionalExpr ||
839 Left.is(tok::question))
840 return false;
841 if (Left.is(tok::equal) && Line.Type == LT_VirtualFunctionDecl)
842 return false;
843
844 if (Right.Type == TT_LineComment)
845 // We rely on MustBreakBefore being set correctly here as we should not
846 // change the "binding" behavior of a comment.
847 return false;
848
849 // Allow breaking after a trailing 'const', e.g. after a method declaration,
850 // unless it is follow by ';', '{' or '='.
851 if (Left.is(tok::kw_const) && Left.Parent != NULL &&
852 Left.Parent->is(tok::r_paren))
853 return Right.isNot(tok::l_brace) && Right.isNot(tok::semi) &&
854 Right.isNot(tok::equal);
855
856 // We only break before r_brace if there was a corresponding break before
857 // the l_brace, which is tracked by BreakBeforeClosingBrace.
858 if (Right.is(tok::r_brace))
859 return false;
860
861 if (Right.is(tok::r_paren) || Right.is(tok::greater))
862 return false;
863 return (isBinaryOperator(Left) && Left.isNot(tok::lessless)) ||
864 Left.is(tok::comma) || Right.is(tok::lessless) ||
865 Right.is(tok::arrow) || Right.is(tok::period) ||
866 Right.is(tok::colon) || Left.is(tok::coloncolon) ||
867 Left.is(tok::semi) || Left.is(tok::l_brace) ||
868 (Left.is(tok::r_paren) && Left.Type != TT_CastRParen &&
869 Right.is(tok::identifier)) ||
870 (Left.is(tok::l_paren) && !Right.is(tok::r_paren)) ||
871 (Left.is(tok::l_square) && !Right.is(tok::r_square));
872}
873
874} // namespace format
875} // namespace clang