blob: ad3baae00d49ebfadea0fcc61a26ec6e683e7122 [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
Nico Weberee0feec2013-02-05 16:21:00 +000023static bool isUnaryOperator(const AnnotatedToken &Tok) {
24 switch (Tok.FormatTok.Tok.getKind()) {
25 case tok::plus:
26 case tok::plusplus:
27 case tok::minus:
28 case tok::minusminus:
29 case tok::exclaim:
30 case tok::tilde:
31 case tok::kw_sizeof:
32 case tok::kw_alignof:
33 return true;
34 default:
35 return false;
36 }
37}
38
Daniel Jasper32d28ee2013-01-29 21:01:14 +000039static bool isBinaryOperator(const AnnotatedToken &Tok) {
40 // Comma is a binary operator, but does not behave as such wrt. formatting.
41 return getPrecedence(Tok) > prec::Comma;
42}
43
Daniel Jasper01786732013-02-04 07:21:18 +000044// Returns the previous token ignoring comments.
Nico Weber4ed7f3e2013-02-06 16:54:35 +000045static AnnotatedToken *getPreviousToken(AnnotatedToken &Tok) {
46 AnnotatedToken *PrevToken = Tok.Parent;
Daniel Jasper01786732013-02-04 07:21:18 +000047 while (PrevToken != NULL && PrevToken->is(tok::comment))
48 PrevToken = PrevToken->Parent;
49 return PrevToken;
50}
Nico Weber4ed7f3e2013-02-06 16:54:35 +000051static const AnnotatedToken *getPreviousToken(const AnnotatedToken &Tok) {
52 return getPreviousToken(const_cast<AnnotatedToken &>(Tok));
53}
Daniel Jasper01786732013-02-04 07:21:18 +000054
55// Returns the next token ignoring comments.
56static const AnnotatedToken *getNextToken(const AnnotatedToken &Tok) {
57 if (Tok.Children.empty())
58 return NULL;
59 const AnnotatedToken *NextToken = &Tok.Children[0];
60 while (NextToken->is(tok::comment)) {
61 if (NextToken->Children.empty())
62 return NULL;
63 NextToken = &NextToken->Children[0];
64 }
65 return NextToken;
66}
67
Daniel Jasper32d28ee2013-01-29 21:01:14 +000068/// \brief A parser that gathers additional information about tokens.
69///
70/// The \c TokenAnnotator tries to matches parenthesis and square brakets and
71/// store a parenthesis levels. It also tries to resolve matching "<" and ">"
72/// into template parameter lists.
73class AnnotatingParser {
74public:
Daniel Jasper01786732013-02-04 07:21:18 +000075 AnnotatingParser(SourceManager &SourceMgr, Lexer &Lex, AnnotatedLine &Line)
76 : SourceMgr(SourceMgr), Lex(Lex), Line(Line), CurrentToken(&Line.First),
Daniel Jasper4e778092013-02-06 10:05:46 +000077 KeywordVirtualFound(false) {
78 Contexts.push_back(Context(1, /*IsExpression=*/ false));
79 Contexts.back().LookForFunctionName = Line.MustBeDeclaration;
Daniel Jasper32d28ee2013-01-29 21:01:14 +000080 }
81
Daniel Jasper32d28ee2013-01-29 21:01:14 +000082 bool parseAngle() {
83 if (CurrentToken == NULL)
84 return false;
Daniel Jasper4e778092013-02-06 10:05:46 +000085 ScopedContextCreator ContextCreator(*this, 10);
Daniel Jasper32d28ee2013-01-29 21:01:14 +000086 AnnotatedToken *Left = CurrentToken->Parent;
Daniel Jasper4e778092013-02-06 10:05:46 +000087 Contexts.back().IsExpression = false;
Daniel Jasper32d28ee2013-01-29 21:01:14 +000088 while (CurrentToken != NULL) {
89 if (CurrentToken->is(tok::greater)) {
90 Left->MatchingParen = CurrentToken;
91 CurrentToken->MatchingParen = Left;
92 CurrentToken->Type = TT_TemplateCloser;
93 next();
94 return true;
95 }
96 if (CurrentToken->is(tok::r_paren) || CurrentToken->is(tok::r_square) ||
97 CurrentToken->is(tok::r_brace))
98 return false;
99 if (CurrentToken->is(tok::pipepipe) || CurrentToken->is(tok::ampamp) ||
100 CurrentToken->is(tok::question) || CurrentToken->is(tok::colon))
101 return false;
102 if (CurrentToken->is(tok::comma))
103 ++Left->ParameterCount;
104 if (!consumeToken())
105 return false;
106 }
107 return false;
108 }
109
110 bool parseParens(bool LookForDecls = false) {
111 if (CurrentToken == NULL)
112 return false;
Daniel Jasper4e778092013-02-06 10:05:46 +0000113 ScopedContextCreator ContextCreator(*this, 1);
114
115 // FIXME: This is a bit of a hack. Do better.
116 Contexts.back().ColonIsForRangeExpr =
117 Contexts.size() == 2 && Contexts[0].ColonIsForRangeExpr;
118
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000119 bool StartsObjCMethodExpr = false;
120 AnnotatedToken *Left = CurrentToken->Parent;
121 if (CurrentToken->is(tok::caret)) {
122 // ^( starts a block.
123 Left->Type = TT_ObjCBlockLParen;
124 } else if (AnnotatedToken *MaybeSel = Left->Parent) {
125 // @selector( starts a selector.
126 if (MaybeSel->isObjCAtKeyword(tok::objc_selector) && MaybeSel->Parent &&
127 MaybeSel->Parent->is(tok::at)) {
128 StartsObjCMethodExpr = true;
129 }
130 }
131
Daniel Jasper4e778092013-02-06 10:05:46 +0000132 if (StartsObjCMethodExpr) {
133 Contexts.back().ColonIsObjCMethodExpr = true;
134 Left->Type = TT_ObjCMethodExpr;
135 }
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000136
137 while (CurrentToken != NULL) {
138 // LookForDecls is set when "if (" has been seen. Check for
139 // 'identifier' '*' 'identifier' followed by not '=' -- this
140 // '*' has to be a binary operator but determineStarAmpUsage() will
141 // categorize it as an unary operator, so set the right type here.
142 if (LookForDecls && !CurrentToken->Children.empty()) {
143 AnnotatedToken &Prev = *CurrentToken->Parent;
144 AnnotatedToken &Next = CurrentToken->Children[0];
145 if (Prev.Parent->is(tok::identifier) &&
146 (Prev.is(tok::star) || Prev.is(tok::amp)) &&
147 CurrentToken->is(tok::identifier) && Next.isNot(tok::equal)) {
148 Prev.Type = TT_BinaryOperator;
149 LookForDecls = false;
150 }
151 }
152
153 if (CurrentToken->is(tok::r_paren)) {
154 Left->MatchingParen = CurrentToken;
155 CurrentToken->MatchingParen = Left;
156
Daniel Jasper63d7ced2013-02-05 10:07:47 +0000157 if (StartsObjCMethodExpr) {
Daniel Jasper4e778092013-02-06 10:05:46 +0000158 CurrentToken->Type = TT_ObjCMethodExpr;
159 if (Contexts.back().FirstObjCSelectorName != NULL) {
160 Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
161 Contexts.back().LongestObjCSelectorName;
Daniel Jasper63d7ced2013-02-05 10:07:47 +0000162 }
163 }
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000164
165 next();
166 return true;
167 }
168 if (CurrentToken->is(tok::r_square) || CurrentToken->is(tok::r_brace))
169 return false;
170 if (CurrentToken->is(tok::comma))
171 ++Left->ParameterCount;
172 if (!consumeToken())
173 return false;
174 }
175 return false;
176 }
177
178 bool parseSquare() {
179 if (!CurrentToken)
180 return false;
Daniel Jasper4e778092013-02-06 10:05:46 +0000181 ScopedContextCreator ContextCreator(*this, 10);
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000182
183 // A '[' could be an index subscript (after an indentifier or after
184 // ')' or ']'), or it could be the start of an Objective-C method
185 // expression.
186 AnnotatedToken *Left = CurrentToken->Parent;
Nico Weber4ed7f3e2013-02-06 16:54:35 +0000187 AnnotatedToken *Parent = getPreviousToken(*Left);
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000188 bool StartsObjCMethodExpr =
Nico Weber4ed7f3e2013-02-06 16:54:35 +0000189 !Parent || Parent->is(tok::colon) || Parent->is(tok::l_square) ||
190 Parent->is(tok::l_paren) || Parent->is(tok::kw_return) ||
191 Parent->is(tok::kw_throw) || isUnaryOperator(*Parent) ||
192 getBinOpPrecedence(Parent->FormatTok.Tok.getKind(), true, true) >
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000193 prec::Unknown;
194
Daniel Jasper4e778092013-02-06 10:05:46 +0000195 if (StartsObjCMethodExpr) {
196 Contexts.back().ColonIsObjCMethodExpr = true;
197 Left->Type = TT_ObjCMethodExpr;
198 }
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000199
200 while (CurrentToken != NULL) {
201 if (CurrentToken->is(tok::r_square)) {
202 if (!CurrentToken->Children.empty() &&
203 CurrentToken->Children[0].is(tok::l_paren)) {
Nico Webere8a97982013-02-06 06:20:11 +0000204 // An ObjC method call is rarely followed by an open parenthesis.
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000205 // FIXME: Do we incorrectly label ":" with this?
206 StartsObjCMethodExpr = false;
207 Left->Type = TT_Unknown;
208 }
Daniel Jasper01786732013-02-04 07:21:18 +0000209 if (StartsObjCMethodExpr) {
Daniel Jasper4e778092013-02-06 10:05:46 +0000210 CurrentToken->Type = TT_ObjCMethodExpr;
Nico Webere8a97982013-02-06 06:20:11 +0000211 // determineStarAmpUsage() thinks that '*' '[' is allocating an
212 // array of pointers, but if '[' starts a selector then '*' is a
213 // binary operator.
Nico Weber4ed7f3e2013-02-06 16:54:35 +0000214 if (Parent != NULL &&
215 (Parent->is(tok::star) || Parent->is(tok::amp)) &&
216 Parent->Type == TT_PointerOrReference)
217 Parent->Type = TT_BinaryOperator;
Daniel Jasper01786732013-02-04 07:21:18 +0000218 }
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000219 Left->MatchingParen = CurrentToken;
220 CurrentToken->MatchingParen = Left;
Daniel Jasper4e778092013-02-06 10:05:46 +0000221 if (Contexts.back().FirstObjCSelectorName != NULL)
222 Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
223 Contexts.back().LongestObjCSelectorName;
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000224 next();
225 return true;
226 }
227 if (CurrentToken->is(tok::r_paren) || CurrentToken->is(tok::r_brace))
228 return false;
229 if (CurrentToken->is(tok::comma))
230 ++Left->ParameterCount;
231 if (!consumeToken())
232 return false;
233 }
234 return false;
235 }
236
237 bool parseBrace() {
238 // Lines are fine to end with '{'.
239 if (CurrentToken == NULL)
240 return true;
Daniel Jasper4e778092013-02-06 10:05:46 +0000241 ScopedContextCreator ContextCreator(*this, 1);
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000242 AnnotatedToken *Left = CurrentToken->Parent;
243 while (CurrentToken != NULL) {
244 if (CurrentToken->is(tok::r_brace)) {
245 Left->MatchingParen = CurrentToken;
246 CurrentToken->MatchingParen = Left;
247 next();
248 return true;
249 }
250 if (CurrentToken->is(tok::r_paren) || CurrentToken->is(tok::r_square))
251 return false;
Daniel Jasperf343cab2013-01-31 14:59:26 +0000252 if (CurrentToken->is(tok::comma))
253 ++Left->ParameterCount;
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000254 if (!consumeToken())
255 return false;
256 }
257 return true;
258 }
259
260 bool parseConditional() {
261 while (CurrentToken != NULL) {
262 if (CurrentToken->is(tok::colon)) {
263 CurrentToken->Type = TT_ConditionalExpr;
264 next();
265 return true;
266 }
267 if (!consumeToken())
268 return false;
269 }
270 return false;
271 }
272
273 bool parseTemplateDeclaration() {
274 if (CurrentToken != NULL && CurrentToken->is(tok::less)) {
275 CurrentToken->Type = TT_TemplateOpener;
276 next();
277 if (!parseAngle())
278 return false;
279 CurrentToken->Parent->ClosesTemplateDeclaration = true;
280 return true;
281 }
282 return false;
283 }
284
285 bool consumeToken() {
286 AnnotatedToken *Tok = CurrentToken;
287 next();
288 switch (Tok->FormatTok.Tok.getKind()) {
289 case tok::plus:
290 case tok::minus:
291 // At the start of the line, +/- specific ObjectiveC method
292 // declarations.
293 if (Tok->Parent == NULL)
294 Tok->Type = TT_ObjCMethodSpecifier;
295 break;
296 case tok::colon:
297 // Colons from ?: are handled in parseConditional().
Daniel Jasper63d7ced2013-02-05 10:07:47 +0000298 if (Tok->Parent->is(tok::r_paren)) {
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000299 Tok->Type = TT_CtorInitializerColon;
Daniel Jasper4e778092013-02-06 10:05:46 +0000300 } else if (Contexts.back().ColonIsObjCMethodExpr ||
Daniel Jasper63d7ced2013-02-05 10:07:47 +0000301 Line.First.Type == TT_ObjCMethodSpecifier) {
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000302 Tok->Type = TT_ObjCMethodExpr;
Daniel Jasper63d7ced2013-02-05 10:07:47 +0000303 Tok->Parent->Type = TT_ObjCSelectorName;
Daniel Jasper4e778092013-02-06 10:05:46 +0000304 if (Tok->Parent->FormatTok.TokenLength >
305 Contexts.back().LongestObjCSelectorName)
306 Contexts.back().LongestObjCSelectorName =
307 Tok->Parent->FormatTok.TokenLength;
308 if (Contexts.back().FirstObjCSelectorName == NULL)
309 Contexts.back().FirstObjCSelectorName = Tok->Parent;
310 } else if (Contexts.back().ColonIsForRangeExpr) {
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000311 Tok->Type = TT_RangeBasedForLoopColon;
Daniel Jasper63d7ced2013-02-05 10:07:47 +0000312 }
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000313 break;
314 case tok::kw_if:
315 case tok::kw_while:
316 if (CurrentToken != NULL && CurrentToken->is(tok::l_paren)) {
317 next();
318 if (!parseParens(/*LookForDecls=*/ true))
319 return false;
320 }
321 break;
322 case tok::kw_for:
Daniel Jasper4e778092013-02-06 10:05:46 +0000323 Contexts.back().ColonIsForRangeExpr = true;
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000324 next();
325 if (!parseParens())
326 return false;
327 break;
328 case tok::l_paren:
329 if (!parseParens())
330 return false;
331 break;
332 case tok::l_square:
333 if (!parseSquare())
334 return false;
335 break;
336 case tok::l_brace:
337 if (!parseBrace())
338 return false;
339 break;
340 case tok::less:
341 if (parseAngle())
342 Tok->Type = TT_TemplateOpener;
343 else {
344 Tok->Type = TT_BinaryOperator;
345 CurrentToken = Tok;
346 next();
347 }
348 break;
349 case tok::r_paren:
350 case tok::r_square:
351 return false;
352 case tok::r_brace:
353 // Lines can start with '}'.
354 if (Tok->Parent != NULL)
355 return false;
356 break;
357 case tok::greater:
358 Tok->Type = TT_BinaryOperator;
359 break;
360 case tok::kw_operator:
361 if (CurrentToken != NULL && CurrentToken->is(tok::l_paren)) {
362 CurrentToken->Type = TT_OverloadedOperator;
363 next();
364 if (CurrentToken != NULL && CurrentToken->is(tok::r_paren)) {
365 CurrentToken->Type = TT_OverloadedOperator;
366 next();
367 }
368 } else {
369 while (CurrentToken != NULL && CurrentToken->isNot(tok::l_paren)) {
370 CurrentToken->Type = TT_OverloadedOperator;
371 next();
372 }
373 }
374 break;
375 case tok::question:
376 parseConditional();
377 break;
378 case tok::kw_template:
379 parseTemplateDeclaration();
380 break;
381 default:
382 break;
383 }
384 return true;
385 }
386
387 void parseIncludeDirective() {
388 next();
389 if (CurrentToken != NULL && CurrentToken->is(tok::less)) {
390 next();
391 while (CurrentToken != NULL) {
392 if (CurrentToken->isNot(tok::comment) ||
393 !CurrentToken->Children.empty())
394 CurrentToken->Type = TT_ImplicitStringLiteral;
395 next();
396 }
397 } else {
398 while (CurrentToken != NULL) {
399 next();
400 }
401 }
402 }
403
404 void parseWarningOrError() {
405 next();
406 // We still want to format the whitespace left of the first token of the
407 // warning or error.
408 next();
409 while (CurrentToken != NULL) {
410 CurrentToken->Type = TT_ImplicitStringLiteral;
411 next();
412 }
413 }
414
415 void parsePreprocessorDirective() {
416 next();
417 if (CurrentToken == NULL)
418 return;
419 // Hashes in the middle of a line can lead to any strange token
420 // sequence.
421 if (CurrentToken->FormatTok.Tok.getIdentifierInfo() == NULL)
422 return;
423 switch (CurrentToken->FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
424 case tok::pp_include:
425 case tok::pp_import:
426 parseIncludeDirective();
427 break;
428 case tok::pp_error:
429 case tok::pp_warning:
430 parseWarningOrError();
431 break;
432 default:
433 break;
434 }
Daniel Jasper5b7e7b02013-02-05 09:34:14 +0000435 while (CurrentToken != NULL)
436 next();
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000437 }
438
439 LineType parseLine() {
440 int PeriodsAndArrows = 0;
441 bool CanBeBuilderTypeStmt = true;
442 if (CurrentToken->is(tok::hash)) {
443 parsePreprocessorDirective();
444 return LT_PreprocessorDirective;
445 }
446 while (CurrentToken != NULL) {
447 if (CurrentToken->is(tok::kw_virtual))
448 KeywordVirtualFound = true;
449 if (CurrentToken->is(tok::period) || CurrentToken->is(tok::arrow))
450 ++PeriodsAndArrows;
451 if (getPrecedence(*CurrentToken) > prec::Assignment &&
452 CurrentToken->isNot(tok::less) && CurrentToken->isNot(tok::greater))
453 CanBeBuilderTypeStmt = false;
454 if (!consumeToken())
455 return LT_Invalid;
456 }
457 if (KeywordVirtualFound)
458 return LT_VirtualFunctionDecl;
459
460 // Assume a builder-type call if there are 2 or more "." and "->".
461 if (PeriodsAndArrows >= 2 && CanBeBuilderTypeStmt)
462 return LT_BuilderTypeCall;
463
Daniel Jasper63d7ced2013-02-05 10:07:47 +0000464 if (Line.First.Type == TT_ObjCMethodSpecifier) {
Daniel Jasper4e778092013-02-06 10:05:46 +0000465 if (Contexts.back().FirstObjCSelectorName != NULL)
466 Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
467 Contexts.back().LongestObjCSelectorName;
Daniel Jasper63d7ced2013-02-05 10:07:47 +0000468 return LT_ObjCMethodDecl;
469 }
470
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000471 return LT_Other;
472 }
473
474 void next() {
Daniel Jasper01786732013-02-04 07:21:18 +0000475 if (CurrentToken != NULL) {
476 determineTokenType(*CurrentToken);
Daniel Jasper4e778092013-02-06 10:05:46 +0000477 CurrentToken->BindingStrength = Contexts.back().BindingStrength;
Daniel Jasper01786732013-02-04 07:21:18 +0000478 }
479
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000480 if (CurrentToken != NULL && !CurrentToken->Children.empty())
481 CurrentToken = &CurrentToken->Children[0];
482 else
483 CurrentToken = NULL;
484 }
485
486private:
Daniel Jasper4e778092013-02-06 10:05:46 +0000487 /// \brief A struct to hold information valid in a specific context, e.g.
488 /// a pair of parenthesis.
489 struct Context {
490 Context(unsigned BindingStrength, bool IsExpression)
491 : BindingStrength(BindingStrength), LongestObjCSelectorName(0),
492 ColonIsForRangeExpr(false), ColonIsObjCMethodExpr(false),
493 FirstObjCSelectorName(NULL), IsExpression(IsExpression),
494 LookForFunctionName(false) {
495 }
Daniel Jasper01786732013-02-04 07:21:18 +0000496
Daniel Jasper4e778092013-02-06 10:05:46 +0000497 unsigned BindingStrength;
498 unsigned LongestObjCSelectorName;
499 bool ColonIsForRangeExpr;
500 bool ColonIsObjCMethodExpr;
501 AnnotatedToken *FirstObjCSelectorName;
502 bool IsExpression;
503 bool LookForFunctionName;
504 };
505
506 /// \brief Puts a new \c Context onto the stack \c Contexts for the lifetime
507 /// of each instance.
508 struct ScopedContextCreator {
509 AnnotatingParser &P;
510
511 ScopedContextCreator(AnnotatingParser &P, unsigned Increase)
512 : P(P) {
513 P.Contexts.push_back(Context(
514 P.Contexts.back().BindingStrength + Increase,
515 P.Contexts.back().IsExpression));
516 }
517
518 ~ScopedContextCreator() { P.Contexts.pop_back(); }
519 };
Daniel Jasper01786732013-02-04 07:21:18 +0000520
521 void determineTokenType(AnnotatedToken &Current) {
522 if (getPrecedence(Current) == prec::Assignment) {
Daniel Jasper4e778092013-02-06 10:05:46 +0000523 Contexts.back().IsExpression = true;
Daniel Jasper01786732013-02-04 07:21:18 +0000524 AnnotatedToken *Previous = Current.Parent;
Daniel Jasper6b5ba8b2013-02-06 10:57:42 +0000525 while (Previous != NULL && Previous->isNot(tok::comma)) {
Daniel Jasper01786732013-02-04 07:21:18 +0000526 if (Previous->Type == TT_BinaryOperator &&
527 (Previous->is(tok::star) || Previous->is(tok::amp))) {
528 Previous->Type = TT_PointerOrReference;
529 }
530 Previous = Previous->Parent;
531 }
532 }
533 if (Current.is(tok::kw_return) || Current.is(tok::kw_throw) ||
534 (Current.is(tok::l_paren) && !Line.MustBeDeclaration &&
535 (Current.Parent == NULL || Current.Parent->isNot(tok::kw_for))))
Daniel Jasper4e778092013-02-06 10:05:46 +0000536 Contexts.back().IsExpression = true;
Daniel Jasper01786732013-02-04 07:21:18 +0000537
538 if (Current.Type == TT_Unknown) {
Daniel Jasper4e778092013-02-06 10:05:46 +0000539 if (Contexts.back().LookForFunctionName && Current.is(tok::l_paren)) {
Daniel Jasper01786732013-02-04 07:21:18 +0000540 findFunctionName(&Current);
Daniel Jasper4e778092013-02-06 10:05:46 +0000541 Contexts.back().LookForFunctionName = false;
Daniel Jasper01786732013-02-04 07:21:18 +0000542 } else if (Current.is(tok::star) || Current.is(tok::amp)) {
Daniel Jasper4e778092013-02-06 10:05:46 +0000543 Current.Type =
544 determineStarAmpUsage(Current, Contexts.back().IsExpression);
Daniel Jasper01786732013-02-04 07:21:18 +0000545 } else if (Current.is(tok::minus) || Current.is(tok::plus) ||
546 Current.is(tok::caret)) {
547 Current.Type = determinePlusMinusCaretUsage(Current);
548 } else if (Current.is(tok::minusminus) || Current.is(tok::plusplus)) {
549 Current.Type = determineIncrementUsage(Current);
550 } else if (Current.is(tok::exclaim)) {
551 Current.Type = TT_UnaryOperator;
552 } else if (isBinaryOperator(Current)) {
553 Current.Type = TT_BinaryOperator;
554 } else if (Current.is(tok::comment)) {
555 std::string Data(Lexer::getSpelling(Current.FormatTok.Tok, SourceMgr,
556 Lex.getLangOpts()));
557 if (StringRef(Data).startswith("//"))
558 Current.Type = TT_LineComment;
559 else
560 Current.Type = TT_BlockComment;
561 } else if (Current.is(tok::r_paren) &&
562 (Current.Parent->Type == TT_PointerOrReference ||
563 Current.Parent->Type == TT_TemplateCloser) &&
564 (Current.Children.empty() ||
565 (Current.Children[0].isNot(tok::equal) &&
566 Current.Children[0].isNot(tok::semi) &&
567 Current.Children[0].isNot(tok::l_brace)))) {
568 // FIXME: We need to get smarter and understand more cases of casts.
569 Current.Type = TT_CastRParen;
570 } else if (Current.is(tok::at) && Current.Children.size()) {
571 switch (Current.Children[0].FormatTok.Tok.getObjCKeywordID()) {
572 case tok::objc_interface:
573 case tok::objc_implementation:
574 case tok::objc_protocol:
575 Current.Type = TT_ObjCDecl;
576 break;
577 case tok::objc_property:
578 Current.Type = TT_ObjCProperty;
579 break;
580 default:
581 break;
582 }
583 }
584 }
585 }
586
587 /// \brief Starting from \p Current, this searches backwards for an
588 /// identifier which could be the start of a function name and marks it.
589 void findFunctionName(AnnotatedToken *Current) {
590 AnnotatedToken *Parent = Current->Parent;
591 while (Parent != NULL && Parent->Parent != NULL) {
592 if (Parent->is(tok::identifier) &&
593 (Parent->Parent->is(tok::identifier) ||
594 Parent->Parent->Type == TT_PointerOrReference ||
595 Parent->Parent->Type == TT_TemplateCloser)) {
596 Parent->Type = TT_StartOfName;
597 break;
598 }
599 Parent = Parent->Parent;
600 }
601 }
602
603 /// \brief Return the type of the given token assuming it is * or &.
604 TokenType
605 determineStarAmpUsage(const AnnotatedToken &Tok, bool IsExpression) {
606 const AnnotatedToken *PrevToken = getPreviousToken(Tok);
607 if (PrevToken == NULL)
608 return TT_UnaryOperator;
609
610 const AnnotatedToken *NextToken = getNextToken(Tok);
611 if (NextToken == NULL)
612 return TT_Unknown;
613
Daniel Jasper01786732013-02-04 07:21:18 +0000614 if (PrevToken->is(tok::l_paren) || PrevToken->is(tok::l_square) ||
615 PrevToken->is(tok::l_brace) || PrevToken->is(tok::comma) ||
616 PrevToken->is(tok::kw_return) || PrevToken->is(tok::colon) ||
Nico Webere8a97982013-02-06 06:20:11 +0000617 PrevToken->is(tok::equal) || PrevToken->Type == TT_BinaryOperator ||
Daniel Jasper01786732013-02-04 07:21:18 +0000618 PrevToken->Type == TT_UnaryOperator || PrevToken->Type == TT_CastRParen)
619 return TT_UnaryOperator;
620
Nico Webere8a97982013-02-06 06:20:11 +0000621 if (NextToken->is(tok::l_square))
622 return TT_PointerOrReference;
623
Daniel Jasper01786732013-02-04 07:21:18 +0000624 if (PrevToken->FormatTok.Tok.isLiteral() || PrevToken->is(tok::r_paren) ||
625 PrevToken->is(tok::r_square) || NextToken->FormatTok.Tok.isLiteral() ||
Nico Weberee0feec2013-02-05 16:21:00 +0000626 isUnaryOperator(*NextToken) || NextToken->is(tok::l_paren) ||
627 NextToken->is(tok::l_square))
Daniel Jasper01786732013-02-04 07:21:18 +0000628 return TT_BinaryOperator;
629
630 if (NextToken->is(tok::comma) || NextToken->is(tok::r_paren) ||
631 NextToken->is(tok::greater))
632 return TT_PointerOrReference;
633
634 // It is very unlikely that we are going to find a pointer or reference type
635 // definition on the RHS of an assignment.
636 if (IsExpression)
637 return TT_BinaryOperator;
638
639 return TT_PointerOrReference;
640 }
641
642 TokenType determinePlusMinusCaretUsage(const AnnotatedToken &Tok) {
643 const AnnotatedToken *PrevToken = getPreviousToken(Tok);
644 if (PrevToken == NULL)
645 return TT_UnaryOperator;
646
647 // Use heuristics to recognize unary operators.
648 if (PrevToken->is(tok::equal) || PrevToken->is(tok::l_paren) ||
649 PrevToken->is(tok::comma) || PrevToken->is(tok::l_square) ||
650 PrevToken->is(tok::question) || PrevToken->is(tok::colon) ||
651 PrevToken->is(tok::kw_return) || PrevToken->is(tok::kw_case) ||
652 PrevToken->is(tok::at) || PrevToken->is(tok::l_brace))
653 return TT_UnaryOperator;
654
Nico Weberee0feec2013-02-05 16:21:00 +0000655 // There can't be two consecutive binary operators.
Daniel Jasper01786732013-02-04 07:21:18 +0000656 if (PrevToken->Type == TT_BinaryOperator)
657 return TT_UnaryOperator;
658
659 // Fall back to marking the token as binary operator.
660 return TT_BinaryOperator;
661 }
662
663 /// \brief Determine whether ++/-- are pre- or post-increments/-decrements.
664 TokenType determineIncrementUsage(const AnnotatedToken &Tok) {
665 const AnnotatedToken *PrevToken = getPreviousToken(Tok);
666 if (PrevToken == NULL)
667 return TT_UnaryOperator;
668 if (PrevToken->is(tok::r_paren) || PrevToken->is(tok::r_square) ||
669 PrevToken->is(tok::identifier))
670 return TT_TrailingUnaryOperator;
671
672 return TT_UnaryOperator;
673 }
Daniel Jasper4e778092013-02-06 10:05:46 +0000674
675 SmallVector<Context, 8> Contexts;
676
677 SourceManager &SourceMgr;
678 Lexer &Lex;
679 AnnotatedLine &Line;
680 AnnotatedToken *CurrentToken;
681 bool KeywordVirtualFound;
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000682};
683
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000684void TokenAnnotator::annotate(AnnotatedLine &Line) {
Daniel Jasper01786732013-02-04 07:21:18 +0000685 AnnotatingParser Parser(SourceMgr, Lex, Line);
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000686 Line.Type = Parser.parseLine();
687 if (Line.Type == LT_Invalid)
688 return;
689
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000690 if (Line.First.Type == TT_ObjCMethodSpecifier)
691 Line.Type = LT_ObjCMethodDecl;
692 else if (Line.First.Type == TT_ObjCDecl)
693 Line.Type = LT_ObjCDecl;
694 else if (Line.First.Type == TT_ObjCProperty)
695 Line.Type = LT_ObjCProperty;
696
697 Line.First.SpaceRequiredBefore = true;
698 Line.First.MustBreakBefore = Line.First.FormatTok.MustBreakBefore;
699 Line.First.CanBreakBefore = Line.First.MustBreakBefore;
700
701 Line.First.TotalLength = Line.First.FormatTok.TokenLength;
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000702}
703
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000704void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
705 if (Line.First.Children.empty())
706 return;
707 AnnotatedToken *Current = &Line.First.Children[0];
708 while (Current != NULL) {
709 Current->SpaceRequiredBefore = spaceRequiredBefore(Line, *Current);
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000710
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000711 if (Current->FormatTok.MustBreakBefore) {
712 Current->MustBreakBefore = true;
713 } else if (Current->Type == TT_LineComment) {
714 Current->MustBreakBefore = Current->FormatTok.NewlinesBefore > 0;
715 } else if ((Current->Parent->is(tok::comment) &&
716 Current->FormatTok.NewlinesBefore > 0) ||
717 (Current->is(tok::string_literal) &&
718 Current->Parent->is(tok::string_literal))) {
719 Current->MustBreakBefore = true;
720 } else if (Current->is(tok::lessless) && !Current->Children.empty() &&
721 Current->Parent->is(tok::string_literal) &&
722 Current->Children[0].is(tok::string_literal)) {
723 Current->MustBreakBefore = true;
724 } else {
725 Current->MustBreakBefore = false;
726 }
727 Current->CanBreakBefore =
728 Current->MustBreakBefore || canBreakBefore(Line, *Current);
729 if (Current->MustBreakBefore)
730 Current->TotalLength = Current->Parent->TotalLength + Style.ColumnLimit;
731 else
732 Current->TotalLength =
733 Current->Parent->TotalLength + Current->FormatTok.TokenLength +
734 (Current->SpaceRequiredBefore ? 1 : 0);
735 // FIXME: Only calculate this if CanBreakBefore is true once static
736 // initializers etc. are sorted out.
737 // FIXME: Move magic numbers to a better place.
738 Current->SplitPenalty =
739 20 * Current->BindingStrength + splitPenalty(Line, *Current);
740
741 Current = Current->Children.empty() ? NULL : &Current->Children[0];
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000742 }
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000743}
744
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000745unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
746 const AnnotatedToken &Tok) {
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000747 const AnnotatedToken &Left = *Tok.Parent;
748 const AnnotatedToken &Right = Tok;
749
750 if (Left.is(tok::l_brace) && Right.isNot(tok::l_brace))
751 return 50;
752 if (Left.is(tok::equal) && Right.is(tok::l_brace))
753 return 150;
754 if (Left.is(tok::coloncolon))
755 return 500;
756
757 if (Left.Type == TT_RangeBasedForLoopColon)
758 return 5;
759
760 if (Right.is(tok::arrow) || Right.is(tok::period)) {
761 if (Left.is(tok::r_paren) && Line.Type == LT_BuilderTypeCall)
762 return 5; // Should be smaller than breaking at a nested comma.
763 return 150;
764 }
765
766 // In for-loops, prefer breaking at ',' and ';'.
767 if (Line.First.is(tok::kw_for) &&
768 (Left.isNot(tok::comma) && Left.isNot(tok::semi)))
769 return 20;
770
Daniel Jasper8159d2f2013-02-04 07:30:30 +0000771 if (Left.is(tok::semi))
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000772 return 0;
Daniel Jasper8159d2f2013-02-04 07:30:30 +0000773 if (Left.is(tok::comma))
774 return 1;
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000775
776 // In Objective-C method expressions, prefer breaking before "param:" over
777 // breaking after it.
Daniel Jasper63d7ced2013-02-05 10:07:47 +0000778 if (Right.Type == TT_ObjCSelectorName)
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000779 return 0;
Daniel Jasper63d7ced2013-02-05 10:07:47 +0000780 if (Left.is(tok::colon) && Left.Type == TT_ObjCMethodExpr)
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000781 return 20;
782
Daniel Jasper01786732013-02-04 07:21:18 +0000783 if (Left.is(tok::l_paren) || Left.is(tok::l_square) ||
784 Left.Type == TT_TemplateOpener)
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000785 return 20;
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000786
Daniel Jasper4e8a7b42013-02-06 21:04:05 +0000787 if (Right.is(tok::lessless)) {
788 if (Left.is(tok::string_literal)) {
789 char LastChar =
790 StringRef(Left.FormatTok.Tok.getLiteralData(),
791 Left.FormatTok.TokenLength).drop_back(1).rtrim().back();
792 if (LastChar == ':' || LastChar == '=')
793 return 100;
794 }
Daniel Jasper01786732013-02-04 07:21:18 +0000795 return prec::Shift;
Daniel Jasper4e8a7b42013-02-06 21:04:05 +0000796 }
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000797 if (Left.Type == TT_ConditionalExpr)
798 return prec::Assignment;
799 prec::Level Level = getPrecedence(Left);
800
801 if (Level != prec::Unknown)
802 return Level;
803
804 return 3;
805}
806
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000807bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
808 const AnnotatedToken &Left,
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000809 const AnnotatedToken &Right) {
810 if (Right.is(tok::hashhash))
811 return Left.is(tok::hash);
812 if (Left.is(tok::hashhash) || Left.is(tok::hash))
813 return Right.is(tok::hash);
814 if (Right.is(tok::r_paren) || Right.is(tok::semi) || Right.is(tok::comma))
815 return false;
816 if (Right.is(tok::less) &&
817 (Left.is(tok::kw_template) ||
818 (Line.Type == LT_ObjCDecl && Style.ObjCSpaceBeforeProtocolList)))
819 return true;
820 if (Left.is(tok::arrow) || Right.is(tok::arrow))
821 return false;
822 if (Left.is(tok::exclaim) || Left.is(tok::tilde))
823 return false;
824 if (Left.is(tok::at) &&
825 (Right.is(tok::identifier) || Right.is(tok::string_literal) ||
826 Right.is(tok::char_constant) || Right.is(tok::numeric_constant) ||
827 Right.is(tok::l_paren) || Right.is(tok::l_brace) ||
828 Right.is(tok::kw_true) || Right.is(tok::kw_false)))
829 return false;
830 if (Left.is(tok::coloncolon))
831 return false;
832 if (Right.is(tok::coloncolon))
833 return Left.isNot(tok::identifier) && Left.isNot(tok::greater);
834 if (Left.is(tok::less) || Right.is(tok::greater) || Right.is(tok::less))
835 return false;
836 if (Right.is(tok::amp) || Right.is(tok::star))
837 return Left.FormatTok.Tok.isLiteral() ||
838 (Left.isNot(tok::star) && Left.isNot(tok::amp) &&
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000839 !Style.PointerBindsToType);
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000840 if (Left.is(tok::amp) || Left.is(tok::star))
841 return Right.FormatTok.Tok.isLiteral() ||
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000842 Style.PointerBindsToType;
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000843 if (Right.is(tok::star) && Left.is(tok::l_paren))
844 return false;
845 if (Left.is(tok::l_square) || Right.is(tok::r_square))
846 return false;
847 if (Right.is(tok::l_square) && Right.Type != TT_ObjCMethodExpr)
848 return false;
849 if (Left.is(tok::period) || Right.is(tok::period))
850 return false;
851 if (Left.is(tok::colon))
852 return Left.Type != TT_ObjCMethodExpr;
853 if (Right.is(tok::colon))
854 return Right.Type != TT_ObjCMethodExpr;
855 if (Left.is(tok::l_paren))
856 return false;
857 if (Right.is(tok::l_paren)) {
858 return Line.Type == LT_ObjCDecl || Left.is(tok::kw_if) ||
859 Left.is(tok::kw_for) || Left.is(tok::kw_while) ||
860 Left.is(tok::kw_switch) || Left.is(tok::kw_return) ||
861 Left.is(tok::kw_catch) || Left.is(tok::kw_new) ||
862 Left.is(tok::kw_delete);
863 }
864 if (Left.is(tok::at) &&
865 Right.FormatTok.Tok.getObjCKeywordID() != tok::objc_not_keyword)
866 return false;
867 if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
868 return false;
869 return true;
870}
871
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000872bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
873 const AnnotatedToken &Tok) {
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000874 if (Line.Type == LT_ObjCMethodDecl) {
875 if (Tok.is(tok::identifier) && !Tok.Children.empty() &&
876 Tok.Children[0].is(tok::colon) && Tok.Parent->is(tok::identifier))
877 return true;
878 if (Tok.is(tok::colon))
879 return false;
880 if (Tok.Parent->Type == TT_ObjCMethodSpecifier)
881 return true;
882 if (Tok.Parent->is(tok::r_paren) && Tok.is(tok::identifier))
883 // Don't space between ')' and <id>
884 return false;
885 if (Tok.Parent->is(tok::colon) && Tok.is(tok::l_paren))
886 // Don't space between ':' and '('
887 return false;
888 }
889 if (Line.Type == LT_ObjCProperty &&
890 (Tok.is(tok::equal) || Tok.Parent->is(tok::equal)))
891 return false;
892
893 if (Tok.Parent->is(tok::comma))
894 return true;
895 if (Tok.Type == TT_CtorInitializerColon || Tok.Type == TT_ObjCBlockLParen)
896 return true;
897 if (Tok.Type == TT_OverloadedOperator)
898 return Tok.is(tok::identifier) || Tok.is(tok::kw_new) ||
899 Tok.is(tok::kw_delete) || Tok.is(tok::kw_bool);
900 if (Tok.Parent->Type == TT_OverloadedOperator)
901 return false;
902 if (Tok.is(tok::colon))
903 return Line.First.isNot(tok::kw_case) && !Tok.Children.empty() &&
904 Tok.Type != TT_ObjCMethodExpr;
905 if (Tok.Parent->Type == TT_UnaryOperator || Tok.Parent->Type == TT_CastRParen)
906 return false;
907 if (Tok.Type == TT_UnaryOperator)
908 return Tok.Parent->isNot(tok::l_paren) &&
909 Tok.Parent->isNot(tok::l_square) && Tok.Parent->isNot(tok::at) &&
910 (Tok.Parent->isNot(tok::colon) ||
911 Tok.Parent->Type != TT_ObjCMethodExpr);
912 if (Tok.Parent->is(tok::greater) && Tok.is(tok::greater)) {
913 return Tok.Type == TT_TemplateCloser && Tok.Parent->Type ==
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000914 TT_TemplateCloser && Style.Standard != FormatStyle::LS_Cpp11;
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000915 }
916 if (Tok.Type == TT_BinaryOperator || Tok.Parent->Type == TT_BinaryOperator)
917 return true;
918 if (Tok.Parent->Type == TT_TemplateCloser && Tok.is(tok::l_paren))
919 return false;
920 if (Tok.is(tok::less) && Line.First.is(tok::hash))
921 return true;
922 if (Tok.Type == TT_TrailingUnaryOperator)
923 return false;
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000924 return spaceRequiredBetween(Line, *Tok.Parent, Tok);
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000925}
926
Daniel Jasper8ff690a2013-02-06 14:22:40 +0000927bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
928 const AnnotatedToken &Right) {
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000929 const AnnotatedToken &Left = *Right.Parent;
930 if (Line.Type == LT_ObjCMethodDecl) {
931 if (Right.is(tok::identifier) && !Right.Children.empty() &&
932 Right.Children[0].is(tok::colon) && Left.is(tok::identifier))
933 return true;
934 if (Right.is(tok::identifier) && Left.is(tok::l_paren) &&
935 Left.Parent->is(tok::colon))
936 // Don't break this identifier as ':' or identifier
937 // before it will break.
938 return false;
939 if (Right.is(tok::colon) && Left.is(tok::identifier) && Left.CanBreakBefore)
940 // Don't break at ':' if identifier before it can beak.
941 return false;
942 }
943 if (Right.Type == TT_StartOfName && Style.AllowReturnTypeOnItsOwnLine)
944 return true;
945 if (Right.is(tok::colon) && Right.Type == TT_ObjCMethodExpr)
946 return false;
947 if (Left.is(tok::colon) && Left.Type == TT_ObjCMethodExpr)
948 return true;
Daniel Jasper63d7ced2013-02-05 10:07:47 +0000949 if (Right.Type == TT_ObjCSelectorName)
Daniel Jasper32d28ee2013-01-29 21:01:14 +0000950 return true;
951 if (Left.ClosesTemplateDeclaration)
952 return true;
953 if (Right.Type == TT_ConditionalExpr || Right.is(tok::question))
954 return true;
955 if (Left.Type == TT_RangeBasedForLoopColon)
956 return true;
957 if (Left.Type == TT_PointerOrReference || Left.Type == TT_TemplateCloser ||
958 Left.Type == TT_UnaryOperator || Left.Type == TT_ConditionalExpr ||
959 Left.is(tok::question))
960 return false;
961 if (Left.is(tok::equal) && Line.Type == LT_VirtualFunctionDecl)
962 return false;
963
964 if (Right.Type == TT_LineComment)
965 // We rely on MustBreakBefore being set correctly here as we should not
966 // change the "binding" behavior of a comment.
967 return false;
968
969 // Allow breaking after a trailing 'const', e.g. after a method declaration,
970 // unless it is follow by ';', '{' or '='.
971 if (Left.is(tok::kw_const) && Left.Parent != NULL &&
972 Left.Parent->is(tok::r_paren))
973 return Right.isNot(tok::l_brace) && Right.isNot(tok::semi) &&
974 Right.isNot(tok::equal);
975
976 // We only break before r_brace if there was a corresponding break before
977 // the l_brace, which is tracked by BreakBeforeClosingBrace.
978 if (Right.is(tok::r_brace))
979 return false;
980
981 if (Right.is(tok::r_paren) || Right.is(tok::greater))
982 return false;
983 return (isBinaryOperator(Left) && Left.isNot(tok::lessless)) ||
984 Left.is(tok::comma) || Right.is(tok::lessless) ||
985 Right.is(tok::arrow) || Right.is(tok::period) ||
986 Right.is(tok::colon) || Left.is(tok::coloncolon) ||
987 Left.is(tok::semi) || Left.is(tok::l_brace) ||
988 (Left.is(tok::r_paren) && Left.Type != TT_CastRParen &&
989 Right.is(tok::identifier)) ||
990 (Left.is(tok::l_paren) && !Right.is(tok::r_paren)) ||
991 (Left.is(tok::l_square) && !Right.is(tok::r_square));
992}
993
994} // namespace format
995} // namespace clang