[clang-format] Handle object instansiation in if-statements
[llvm-project.git] / clang / lib / Format / TokenAnnotator.cpp
blobdbfe88c531322eac44da825f5bafd794570e2e27
1 //===--- TokenAnnotator.cpp - Format C++ code -----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file implements a token annotator, i.e. creates
11 /// \c AnnotatedTokens out of \c FormatTokens with required extra information.
12 ///
13 //===----------------------------------------------------------------------===//
15 #include "TokenAnnotator.h"
16 #include "FormatToken.h"
17 #include "clang/Basic/SourceManager.h"
18 #include "clang/Basic/TokenKinds.h"
19 #include "llvm/ADT/SmallPtrSet.h"
20 #include "llvm/Support/Debug.h"
22 #define DEBUG_TYPE "format-token-annotator"
24 namespace clang {
25 namespace format {
27 namespace {
29 /// Returns \c true if the line starts with a token that can start a statement
30 /// with an initializer.
31 static bool startsWithInitStatement(const AnnotatedLine &Line) {
32 return Line.startsWith(tok::kw_for) || Line.startsWith(tok::kw_if) ||
33 Line.startsWith(tok::kw_switch);
36 /// Returns \c true if the token can be used as an identifier in
37 /// an Objective-C \c \@selector, \c false otherwise.
38 ///
39 /// Because getFormattingLangOpts() always lexes source code as
40 /// Objective-C++, C++ keywords like \c new and \c delete are
41 /// lexed as tok::kw_*, not tok::identifier, even for Objective-C.
42 ///
43 /// For Objective-C and Objective-C++, both identifiers and keywords
44 /// are valid inside @selector(...) (or a macro which
45 /// invokes @selector(...)). So, we allow treat any identifier or
46 /// keyword as a potential Objective-C selector component.
47 static bool canBeObjCSelectorComponent(const FormatToken &Tok) {
48 return Tok.Tok.getIdentifierInfo() != nullptr;
51 /// With `Left` being '(', check if we're at either `[...](` or
52 /// `[...]<...>(`, where the [ opens a lambda capture list.
53 static bool isLambdaParameterList(const FormatToken *Left) {
54 // Skip <...> if present.
55 if (Left->Previous && Left->Previous->is(tok::greater) &&
56 Left->Previous->MatchingParen &&
57 Left->Previous->MatchingParen->is(TT_TemplateOpener)) {
58 Left = Left->Previous->MatchingParen;
61 // Check for `[...]`.
62 return Left->Previous && Left->Previous->is(tok::r_square) &&
63 Left->Previous->MatchingParen &&
64 Left->Previous->MatchingParen->is(TT_LambdaLSquare);
67 /// Returns \c true if the token is followed by a boolean condition, \c false
68 /// otherwise.
69 static bool isKeywordWithCondition(const FormatToken &Tok) {
70 return Tok.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, tok::kw_switch,
71 tok::kw_constexpr, tok::kw_catch);
74 /// A parser that gathers additional information about tokens.
75 ///
76 /// The \c TokenAnnotator tries to match parenthesis and square brakets and
77 /// store a parenthesis levels. It also tries to resolve matching "<" and ">"
78 /// into template parameter lists.
79 class AnnotatingParser {
80 public:
81 AnnotatingParser(const FormatStyle &Style, AnnotatedLine &Line,
82 const AdditionalKeywords &Keywords)
83 : Style(Style), Line(Line), CurrentToken(Line.First), AutoFound(false),
84 Keywords(Keywords) {
85 Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false));
86 resetTokenMetadata();
89 private:
90 bool parseAngle() {
91 if (!CurrentToken || !CurrentToken->Previous)
92 return false;
93 if (NonTemplateLess.count(CurrentToken->Previous))
94 return false;
96 const FormatToken &Previous = *CurrentToken->Previous; // The '<'.
97 if (Previous.Previous) {
98 if (Previous.Previous->Tok.isLiteral())
99 return false;
100 if (Previous.Previous->is(tok::r_paren) && Contexts.size() > 1 &&
101 (!Previous.Previous->MatchingParen ||
102 !Previous.Previous->MatchingParen->is(
103 TT_OverloadedOperatorLParen))) {
104 return false;
108 FormatToken *Left = CurrentToken->Previous;
109 Left->ParentBracket = Contexts.back().ContextKind;
110 ScopedContextCreator ContextCreator(*this, tok::less, 12);
112 // If this angle is in the context of an expression, we need to be more
113 // hesitant to detect it as opening template parameters.
114 bool InExprContext = Contexts.back().IsExpression;
116 Contexts.back().IsExpression = false;
117 // If there's a template keyword before the opening angle bracket, this is a
118 // template parameter, not an argument.
119 if (Left->Previous && Left->Previous->isNot(tok::kw_template))
120 Contexts.back().ContextType = Context::TemplateArgument;
122 if (Style.Language == FormatStyle::LK_Java &&
123 CurrentToken->is(tok::question)) {
124 next();
127 while (CurrentToken) {
128 if (CurrentToken->is(tok::greater)) {
129 // Try to do a better job at looking for ">>" within the condition of
130 // a statement. Conservatively insert spaces between consecutive ">"
131 // tokens to prevent splitting right bitshift operators and potentially
132 // altering program semantics. This check is overly conservative and
133 // will prevent spaces from being inserted in select nested template
134 // parameter cases, but should not alter program semantics.
135 if (CurrentToken->Next && CurrentToken->Next->is(tok::greater) &&
136 Left->ParentBracket != tok::less &&
137 (isKeywordWithCondition(*Line.First) ||
138 CurrentToken->getStartOfNonWhitespace() ==
139 CurrentToken->Next->getStartOfNonWhitespace().getLocWithOffset(
140 -1))) {
141 return false;
143 Left->MatchingParen = CurrentToken;
144 CurrentToken->MatchingParen = Left;
145 // In TT_Proto, we must distignuish between:
146 // map<key, value>
147 // msg < item: data >
148 // msg: < item: data >
149 // In TT_TextProto, map<key, value> does not occur.
150 if (Style.Language == FormatStyle::LK_TextProto ||
151 (Style.Language == FormatStyle::LK_Proto && Left->Previous &&
152 Left->Previous->isOneOf(TT_SelectorName, TT_DictLiteral))) {
153 CurrentToken->setType(TT_DictLiteral);
154 } else {
155 CurrentToken->setType(TT_TemplateCloser);
157 next();
158 return true;
160 if (CurrentToken->is(tok::question) &&
161 Style.Language == FormatStyle::LK_Java) {
162 next();
163 continue;
165 if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace) ||
166 (CurrentToken->isOneOf(tok::colon, tok::question) && InExprContext &&
167 !Style.isCSharp() && Style.Language != FormatStyle::LK_Proto &&
168 Style.Language != FormatStyle::LK_TextProto)) {
169 return false;
171 // If a && or || is found and interpreted as a binary operator, this set
172 // of angles is likely part of something like "a < b && c > d". If the
173 // angles are inside an expression, the ||/&& might also be a binary
174 // operator that was misinterpreted because we are parsing template
175 // parameters.
176 // FIXME: This is getting out of hand, write a decent parser.
177 if (CurrentToken->Previous->isOneOf(tok::pipepipe, tok::ampamp) &&
178 CurrentToken->Previous->is(TT_BinaryOperator) &&
179 Contexts[Contexts.size() - 2].IsExpression &&
180 !Line.startsWith(tok::kw_template)) {
181 return false;
183 updateParameterCount(Left, CurrentToken);
184 if (Style.Language == FormatStyle::LK_Proto) {
185 if (FormatToken *Previous = CurrentToken->getPreviousNonComment()) {
186 if (CurrentToken->is(tok::colon) ||
187 (CurrentToken->isOneOf(tok::l_brace, tok::less) &&
188 Previous->isNot(tok::colon))) {
189 Previous->setType(TT_SelectorName);
193 if (!consumeToken())
194 return false;
196 return false;
199 bool parseUntouchableParens() {
200 while (CurrentToken) {
201 CurrentToken->Finalized = true;
202 switch (CurrentToken->Tok.getKind()) {
203 case tok::l_paren:
204 next();
205 if (!parseUntouchableParens())
206 return false;
207 continue;
208 case tok::r_paren:
209 next();
210 return true;
211 default:
212 // no-op
213 break;
215 next();
217 return false;
220 bool parseParens(bool LookForDecls = false) {
221 if (!CurrentToken)
222 return false;
223 assert(CurrentToken->Previous && "Unknown previous token");
224 FormatToken &OpeningParen = *CurrentToken->Previous;
225 assert(OpeningParen.is(tok::l_paren));
226 FormatToken *PrevNonComment = OpeningParen.getPreviousNonComment();
227 OpeningParen.ParentBracket = Contexts.back().ContextKind;
228 ScopedContextCreator ContextCreator(*this, tok::l_paren, 1);
230 // FIXME: This is a bit of a hack. Do better.
231 Contexts.back().ColonIsForRangeExpr =
232 Contexts.size() == 2 && Contexts[0].ColonIsForRangeExpr;
234 if (OpeningParen.Previous &&
235 OpeningParen.Previous->is(TT_UntouchableMacroFunc)) {
236 OpeningParen.Finalized = true;
237 return parseUntouchableParens();
240 bool StartsObjCMethodExpr = false;
241 if (!Style.isVerilog()) {
242 if (FormatToken *MaybeSel = OpeningParen.Previous) {
243 // @selector( starts a selector.
244 if (MaybeSel->isObjCAtKeyword(tok::objc_selector) &&
245 MaybeSel->Previous && MaybeSel->Previous->is(tok::at)) {
246 StartsObjCMethodExpr = true;
251 if (OpeningParen.is(TT_OverloadedOperatorLParen)) {
252 // Find the previous kw_operator token.
253 FormatToken *Prev = &OpeningParen;
254 while (!Prev->is(tok::kw_operator)) {
255 Prev = Prev->Previous;
256 assert(Prev && "Expect a kw_operator prior to the OperatorLParen!");
259 // If faced with "a.operator*(argument)" or "a->operator*(argument)",
260 // i.e. the operator is called as a member function,
261 // then the argument must be an expression.
262 bool OperatorCalledAsMemberFunction =
263 Prev->Previous && Prev->Previous->isOneOf(tok::period, tok::arrow);
264 Contexts.back().IsExpression = OperatorCalledAsMemberFunction;
265 } else if (Style.isJavaScript() &&
266 (Line.startsWith(Keywords.kw_type, tok::identifier) ||
267 Line.startsWith(tok::kw_export, Keywords.kw_type,
268 tok::identifier))) {
269 // type X = (...);
270 // export type X = (...);
271 Contexts.back().IsExpression = false;
272 } else if (OpeningParen.Previous &&
273 (OpeningParen.Previous->isOneOf(tok::kw_static_assert,
274 tok::kw_while, tok::l_paren,
275 tok::comma, TT_BinaryOperator) ||
276 OpeningParen.Previous->isIf())) {
277 // static_assert, if and while usually contain expressions.
278 Contexts.back().IsExpression = true;
279 } else if (Style.isJavaScript() && OpeningParen.Previous &&
280 (OpeningParen.Previous->is(Keywords.kw_function) ||
281 (OpeningParen.Previous->endsSequence(tok::identifier,
282 Keywords.kw_function)))) {
283 // function(...) or function f(...)
284 Contexts.back().IsExpression = false;
285 } else if (Style.isJavaScript() && OpeningParen.Previous &&
286 OpeningParen.Previous->is(TT_JsTypeColon)) {
287 // let x: (SomeType);
288 Contexts.back().IsExpression = false;
289 } else if (isLambdaParameterList(&OpeningParen)) {
290 // This is a parameter list of a lambda expression.
291 Contexts.back().IsExpression = false;
292 } else if (Line.InPPDirective &&
293 (!OpeningParen.Previous ||
294 !OpeningParen.Previous->is(tok::identifier))) {
295 Contexts.back().IsExpression = true;
296 } else if (Contexts[Contexts.size() - 2].CaretFound) {
297 // This is the parameter list of an ObjC block.
298 Contexts.back().IsExpression = false;
299 } else if (OpeningParen.Previous &&
300 OpeningParen.Previous->is(TT_ForEachMacro)) {
301 // The first argument to a foreach macro is a declaration.
302 Contexts.back().ContextType = Context::ForEachMacro;
303 Contexts.back().IsExpression = false;
304 } else if (OpeningParen.Previous && OpeningParen.Previous->MatchingParen &&
305 OpeningParen.Previous->MatchingParen->isOneOf(
306 TT_ObjCBlockLParen, TT_FunctionTypeLParen)) {
307 Contexts.back().IsExpression = false;
308 } else if (!Line.MustBeDeclaration && !Line.InPPDirective) {
309 bool IsForOrCatch =
310 OpeningParen.Previous &&
311 OpeningParen.Previous->isOneOf(tok::kw_for, tok::kw_catch);
312 Contexts.back().IsExpression = !IsForOrCatch;
315 // Infer the role of the l_paren based on the previous token if we haven't
316 // detected one one yet.
317 if (PrevNonComment && OpeningParen.is(TT_Unknown)) {
318 if (PrevNonComment->is(tok::kw___attribute)) {
319 OpeningParen.setType(TT_AttributeParen);
320 } else if (PrevNonComment->isOneOf(TT_TypenameMacro, tok::kw_decltype,
321 tok::kw_typeof,
322 #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait,
323 #include "clang/Basic/TransformTypeTraits.def"
324 tok::kw__Atomic)) {
325 OpeningParen.setType(TT_TypeDeclarationParen);
326 // decltype() and typeof() usually contain expressions.
327 if (PrevNonComment->isOneOf(tok::kw_decltype, tok::kw_typeof))
328 Contexts.back().IsExpression = true;
332 if (StartsObjCMethodExpr) {
333 Contexts.back().ColonIsObjCMethodExpr = true;
334 OpeningParen.setType(TT_ObjCMethodExpr);
337 // MightBeFunctionType and ProbablyFunctionType are used for
338 // function pointer and reference types as well as Objective-C
339 // block types:
341 // void (*FunctionPointer)(void);
342 // void (&FunctionReference)(void);
343 // void (&&FunctionReference)(void);
344 // void (^ObjCBlock)(void);
345 bool MightBeFunctionType = !Contexts[Contexts.size() - 2].IsExpression;
346 bool ProbablyFunctionType =
347 CurrentToken->isOneOf(tok::star, tok::amp, tok::ampamp, tok::caret);
348 bool HasMultipleLines = false;
349 bool HasMultipleParametersOnALine = false;
350 bool MightBeObjCForRangeLoop =
351 OpeningParen.Previous && OpeningParen.Previous->is(tok::kw_for);
352 FormatToken *PossibleObjCForInToken = nullptr;
353 while (CurrentToken) {
354 // LookForDecls is set when "if (" has been seen. Check for
355 // 'identifier' '*' 'identifier' followed by not '=' -- this
356 // '*' has to be a binary operator but determineStarAmpUsage() will
357 // categorize it as an unary operator, so set the right type here.
358 if (LookForDecls && CurrentToken->Next) {
359 FormatToken *Prev = CurrentToken->getPreviousNonComment();
360 if (Prev) {
361 FormatToken *PrevPrev = Prev->getPreviousNonComment();
362 FormatToken *Next = CurrentToken->Next;
363 if (PrevPrev && PrevPrev->is(tok::identifier) &&
364 Prev->isOneOf(tok::star, tok::amp, tok::ampamp) &&
365 CurrentToken->is(tok::identifier) &&
366 !Next->isOneOf(tok::equal, tok::l_brace)) {
367 Prev->setType(TT_BinaryOperator);
368 LookForDecls = false;
373 if (CurrentToken->Previous->is(TT_PointerOrReference) &&
374 CurrentToken->Previous->Previous->isOneOf(tok::l_paren,
375 tok::coloncolon)) {
376 ProbablyFunctionType = true;
378 if (CurrentToken->is(tok::comma))
379 MightBeFunctionType = false;
380 if (CurrentToken->Previous->is(TT_BinaryOperator))
381 Contexts.back().IsExpression = true;
382 if (CurrentToken->is(tok::r_paren)) {
383 if (OpeningParen.isNot(TT_CppCastLParen) && MightBeFunctionType &&
384 ProbablyFunctionType && CurrentToken->Next &&
385 (CurrentToken->Next->is(tok::l_paren) ||
386 (CurrentToken->Next->is(tok::l_square) &&
387 Line.MustBeDeclaration))) {
388 OpeningParen.setType(OpeningParen.Next->is(tok::caret)
389 ? TT_ObjCBlockLParen
390 : TT_FunctionTypeLParen);
392 OpeningParen.MatchingParen = CurrentToken;
393 CurrentToken->MatchingParen = &OpeningParen;
395 if (CurrentToken->Next && CurrentToken->Next->is(tok::l_brace) &&
396 OpeningParen.Previous && OpeningParen.Previous->is(tok::l_paren)) {
397 // Detect the case where macros are used to generate lambdas or
398 // function bodies, e.g.:
399 // auto my_lambda = MACRO((Type *type, int i) { .. body .. });
400 for (FormatToken *Tok = &OpeningParen; Tok != CurrentToken;
401 Tok = Tok->Next) {
402 if (Tok->is(TT_BinaryOperator) &&
403 Tok->isOneOf(tok::star, tok::amp, tok::ampamp)) {
404 Tok->setType(TT_PointerOrReference);
409 if (StartsObjCMethodExpr) {
410 CurrentToken->setType(TT_ObjCMethodExpr);
411 if (Contexts.back().FirstObjCSelectorName) {
412 Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
413 Contexts.back().LongestObjCSelectorName;
417 if (OpeningParen.is(TT_AttributeParen))
418 CurrentToken->setType(TT_AttributeParen);
419 if (OpeningParen.is(TT_TypeDeclarationParen))
420 CurrentToken->setType(TT_TypeDeclarationParen);
421 if (OpeningParen.Previous &&
422 OpeningParen.Previous->is(TT_JavaAnnotation)) {
423 CurrentToken->setType(TT_JavaAnnotation);
425 if (OpeningParen.Previous &&
426 OpeningParen.Previous->is(TT_LeadingJavaAnnotation)) {
427 CurrentToken->setType(TT_LeadingJavaAnnotation);
429 if (OpeningParen.Previous &&
430 OpeningParen.Previous->is(TT_AttributeSquare)) {
431 CurrentToken->setType(TT_AttributeSquare);
434 if (!HasMultipleLines)
435 OpeningParen.setPackingKind(PPK_Inconclusive);
436 else if (HasMultipleParametersOnALine)
437 OpeningParen.setPackingKind(PPK_BinPacked);
438 else
439 OpeningParen.setPackingKind(PPK_OnePerLine);
441 next();
442 return true;
444 if (CurrentToken->isOneOf(tok::r_square, tok::r_brace))
445 return false;
447 if (CurrentToken->is(tok::l_brace) && OpeningParen.is(TT_ObjCBlockLParen))
448 OpeningParen.setType(TT_Unknown);
449 if (CurrentToken->is(tok::comma) && CurrentToken->Next &&
450 !CurrentToken->Next->HasUnescapedNewline &&
451 !CurrentToken->Next->isTrailingComment()) {
452 HasMultipleParametersOnALine = true;
454 bool ProbablyFunctionTypeLParen =
455 (CurrentToken->is(tok::l_paren) && CurrentToken->Next &&
456 CurrentToken->Next->isOneOf(tok::star, tok::amp, tok::caret));
457 if ((CurrentToken->Previous->isOneOf(tok::kw_const, tok::kw_auto) ||
458 CurrentToken->Previous->isSimpleTypeSpecifier()) &&
459 !(CurrentToken->is(tok::l_brace) ||
460 (CurrentToken->is(tok::l_paren) && !ProbablyFunctionTypeLParen))) {
461 Contexts.back().IsExpression = false;
463 if (CurrentToken->isOneOf(tok::semi, tok::colon)) {
464 MightBeObjCForRangeLoop = false;
465 if (PossibleObjCForInToken) {
466 PossibleObjCForInToken->setType(TT_Unknown);
467 PossibleObjCForInToken = nullptr;
470 if (MightBeObjCForRangeLoop && CurrentToken->is(Keywords.kw_in)) {
471 PossibleObjCForInToken = CurrentToken;
472 PossibleObjCForInToken->setType(TT_ObjCForIn);
474 // When we discover a 'new', we set CanBeExpression to 'false' in order to
475 // parse the type correctly. Reset that after a comma.
476 if (CurrentToken->is(tok::comma))
477 Contexts.back().CanBeExpression = true;
479 FormatToken *Tok = CurrentToken;
480 if (!consumeToken())
481 return false;
482 updateParameterCount(&OpeningParen, Tok);
483 if (CurrentToken && CurrentToken->HasUnescapedNewline)
484 HasMultipleLines = true;
486 return false;
489 bool isCSharpAttributeSpecifier(const FormatToken &Tok) {
490 if (!Style.isCSharp())
491 return false;
493 // `identifier[i]` is not an attribute.
494 if (Tok.Previous && Tok.Previous->is(tok::identifier))
495 return false;
497 // Chains of [] in `identifier[i][j][k]` are not attributes.
498 if (Tok.Previous && Tok.Previous->is(tok::r_square)) {
499 auto *MatchingParen = Tok.Previous->MatchingParen;
500 if (!MatchingParen || MatchingParen->is(TT_ArraySubscriptLSquare))
501 return false;
504 const FormatToken *AttrTok = Tok.Next;
505 if (!AttrTok)
506 return false;
508 // Just an empty declaration e.g. string [].
509 if (AttrTok->is(tok::r_square))
510 return false;
512 // Move along the tokens inbetween the '[' and ']' e.g. [STAThread].
513 while (AttrTok && AttrTok->isNot(tok::r_square))
514 AttrTok = AttrTok->Next;
516 if (!AttrTok)
517 return false;
519 // Allow an attribute to be the only content of a file.
520 AttrTok = AttrTok->Next;
521 if (!AttrTok)
522 return true;
524 // Limit this to being an access modifier that follows.
525 if (AttrTok->isOneOf(tok::kw_public, tok::kw_private, tok::kw_protected,
526 tok::comment, tok::kw_class, tok::kw_static,
527 tok::l_square, Keywords.kw_internal)) {
528 return true;
531 // incase its a [XXX] retval func(....
532 if (AttrTok->Next &&
533 AttrTok->Next->startsSequence(tok::identifier, tok::l_paren)) {
534 return true;
537 return false;
540 bool isCpp11AttributeSpecifier(const FormatToken &Tok) {
541 if (!Style.isCpp() || !Tok.startsSequence(tok::l_square, tok::l_square))
542 return false;
543 // The first square bracket is part of an ObjC array literal
544 if (Tok.Previous && Tok.Previous->is(tok::at))
545 return false;
546 const FormatToken *AttrTok = Tok.Next->Next;
547 if (!AttrTok)
548 return false;
549 // C++17 '[[using ns: foo, bar(baz, blech)]]'
550 // We assume nobody will name an ObjC variable 'using'.
551 if (AttrTok->startsSequence(tok::kw_using, tok::identifier, tok::colon))
552 return true;
553 if (AttrTok->isNot(tok::identifier))
554 return false;
555 while (AttrTok && !AttrTok->startsSequence(tok::r_square, tok::r_square)) {
556 // ObjC message send. We assume nobody will use : in a C++11 attribute
557 // specifier parameter, although this is technically valid:
558 // [[foo(:)]].
559 if (AttrTok->is(tok::colon) ||
560 AttrTok->startsSequence(tok::identifier, tok::identifier) ||
561 AttrTok->startsSequence(tok::r_paren, tok::identifier)) {
562 return false;
564 if (AttrTok->is(tok::ellipsis))
565 return true;
566 AttrTok = AttrTok->Next;
568 return AttrTok && AttrTok->startsSequence(tok::r_square, tok::r_square);
571 bool parseSquare() {
572 if (!CurrentToken)
573 return false;
575 // A '[' could be an index subscript (after an identifier or after
576 // ')' or ']'), it could be the start of an Objective-C method
577 // expression, it could the start of an Objective-C array literal,
578 // or it could be a C++ attribute specifier [[foo::bar]].
579 FormatToken *Left = CurrentToken->Previous;
580 Left->ParentBracket = Contexts.back().ContextKind;
581 FormatToken *Parent = Left->getPreviousNonComment();
583 // Cases where '>' is followed by '['.
584 // In C++, this can happen either in array of templates (foo<int>[10])
585 // or when array is a nested template type (unique_ptr<type1<type2>[]>).
586 bool CppArrayTemplates =
587 Style.isCpp() && Parent && Parent->is(TT_TemplateCloser) &&
588 (Contexts.back().CanBeExpression || Contexts.back().IsExpression ||
589 Contexts.back().ContextType == Context::TemplateArgument);
591 bool IsCpp11AttributeSpecifier = isCpp11AttributeSpecifier(*Left) ||
592 Contexts.back().InCpp11AttributeSpecifier;
594 // Treat C# Attributes [STAThread] much like C++ attributes [[...]].
595 bool IsCSharpAttributeSpecifier =
596 isCSharpAttributeSpecifier(*Left) ||
597 Contexts.back().InCSharpAttributeSpecifier;
599 bool InsideInlineASM = Line.startsWith(tok::kw_asm);
600 bool IsCppStructuredBinding = Left->isCppStructuredBinding(Style);
601 bool StartsObjCMethodExpr =
602 !IsCppStructuredBinding && !InsideInlineASM && !CppArrayTemplates &&
603 Style.isCpp() && !IsCpp11AttributeSpecifier &&
604 !IsCSharpAttributeSpecifier && Contexts.back().CanBeExpression &&
605 Left->isNot(TT_LambdaLSquare) &&
606 !CurrentToken->isOneOf(tok::l_brace, tok::r_square) &&
607 (!Parent ||
608 Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren,
609 tok::kw_return, tok::kw_throw) ||
610 Parent->isUnaryOperator() ||
611 // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen.
612 Parent->isOneOf(TT_ObjCForIn, TT_CastRParen) ||
613 (getBinOpPrecedence(Parent->Tok.getKind(), true, true) >
614 prec::Unknown));
615 bool ColonFound = false;
617 unsigned BindingIncrease = 1;
618 if (IsCppStructuredBinding) {
619 Left->setType(TT_StructuredBindingLSquare);
620 } else if (Left->is(TT_Unknown)) {
621 if (StartsObjCMethodExpr) {
622 Left->setType(TT_ObjCMethodExpr);
623 } else if (InsideInlineASM) {
624 Left->setType(TT_InlineASMSymbolicNameLSquare);
625 } else if (IsCpp11AttributeSpecifier) {
626 Left->setType(TT_AttributeSquare);
627 } else if (Style.isJavaScript() && Parent &&
628 Contexts.back().ContextKind == tok::l_brace &&
629 Parent->isOneOf(tok::l_brace, tok::comma)) {
630 Left->setType(TT_JsComputedPropertyName);
631 } else if (Style.isCpp() && Contexts.back().ContextKind == tok::l_brace &&
632 Parent && Parent->isOneOf(tok::l_brace, tok::comma)) {
633 Left->setType(TT_DesignatedInitializerLSquare);
634 } else if (IsCSharpAttributeSpecifier) {
635 Left->setType(TT_AttributeSquare);
636 } else if (CurrentToken->is(tok::r_square) && Parent &&
637 Parent->is(TT_TemplateCloser)) {
638 Left->setType(TT_ArraySubscriptLSquare);
639 } else if (Style.Language == FormatStyle::LK_Proto ||
640 Style.Language == FormatStyle::LK_TextProto) {
641 // Square braces in LK_Proto can either be message field attributes:
643 // optional Aaa aaa = 1 [
644 // (aaa) = aaa
645 // ];
647 // extensions 123 [
648 // (aaa) = aaa
649 // ];
651 // or text proto extensions (in options):
653 // option (Aaa.options) = {
654 // [type.type/type] {
655 // key: value
656 // }
657 // }
659 // or repeated fields (in options):
661 // option (Aaa.options) = {
662 // keys: [ 1, 2, 3 ]
663 // }
665 // In the first and the third case we want to spread the contents inside
666 // the square braces; in the second we want to keep them inline.
667 Left->setType(TT_ArrayInitializerLSquare);
668 if (!Left->endsSequence(tok::l_square, tok::numeric_constant,
669 tok::equal) &&
670 !Left->endsSequence(tok::l_square, tok::numeric_constant,
671 tok::identifier) &&
672 !Left->endsSequence(tok::l_square, tok::colon, TT_SelectorName)) {
673 Left->setType(TT_ProtoExtensionLSquare);
674 BindingIncrease = 10;
676 } else if (!CppArrayTemplates && Parent &&
677 Parent->isOneOf(TT_BinaryOperator, TT_TemplateCloser, tok::at,
678 tok::comma, tok::l_paren, tok::l_square,
679 tok::question, tok::colon, tok::kw_return,
680 // Should only be relevant to JavaScript:
681 tok::kw_default)) {
682 Left->setType(TT_ArrayInitializerLSquare);
683 } else {
684 BindingIncrease = 10;
685 Left->setType(TT_ArraySubscriptLSquare);
689 ScopedContextCreator ContextCreator(*this, tok::l_square, BindingIncrease);
690 Contexts.back().IsExpression = true;
691 if (Style.isJavaScript() && Parent && Parent->is(TT_JsTypeColon))
692 Contexts.back().IsExpression = false;
694 Contexts.back().ColonIsObjCMethodExpr = StartsObjCMethodExpr;
695 Contexts.back().InCpp11AttributeSpecifier = IsCpp11AttributeSpecifier;
696 Contexts.back().InCSharpAttributeSpecifier = IsCSharpAttributeSpecifier;
698 while (CurrentToken) {
699 if (CurrentToken->is(tok::r_square)) {
700 if (IsCpp11AttributeSpecifier)
701 CurrentToken->setType(TT_AttributeSquare);
702 if (IsCSharpAttributeSpecifier) {
703 CurrentToken->setType(TT_AttributeSquare);
704 } else if (((CurrentToken->Next &&
705 CurrentToken->Next->is(tok::l_paren)) ||
706 (CurrentToken->Previous &&
707 CurrentToken->Previous->Previous == Left)) &&
708 Left->is(TT_ObjCMethodExpr)) {
709 // An ObjC method call is rarely followed by an open parenthesis. It
710 // also can't be composed of just one token, unless it's a macro that
711 // will be expanded to more tokens.
712 // FIXME: Do we incorrectly label ":" with this?
713 StartsObjCMethodExpr = false;
714 Left->setType(TT_Unknown);
716 if (StartsObjCMethodExpr && CurrentToken->Previous != Left) {
717 CurrentToken->setType(TT_ObjCMethodExpr);
718 // If we haven't seen a colon yet, make sure the last identifier
719 // before the r_square is tagged as a selector name component.
720 if (!ColonFound && CurrentToken->Previous &&
721 CurrentToken->Previous->is(TT_Unknown) &&
722 canBeObjCSelectorComponent(*CurrentToken->Previous)) {
723 CurrentToken->Previous->setType(TT_SelectorName);
725 // determineStarAmpUsage() thinks that '*' '[' is allocating an
726 // array of pointers, but if '[' starts a selector then '*' is a
727 // binary operator.
728 if (Parent && Parent->is(TT_PointerOrReference))
729 Parent->overwriteFixedType(TT_BinaryOperator);
731 // An arrow after an ObjC method expression is not a lambda arrow.
732 if (CurrentToken->getType() == TT_ObjCMethodExpr &&
733 CurrentToken->Next && CurrentToken->Next->is(TT_LambdaArrow)) {
734 CurrentToken->Next->overwriteFixedType(TT_Unknown);
736 Left->MatchingParen = CurrentToken;
737 CurrentToken->MatchingParen = Left;
738 // FirstObjCSelectorName is set when a colon is found. This does
739 // not work, however, when the method has no parameters.
740 // Here, we set FirstObjCSelectorName when the end of the method call is
741 // reached, in case it was not set already.
742 if (!Contexts.back().FirstObjCSelectorName) {
743 FormatToken *Previous = CurrentToken->getPreviousNonComment();
744 if (Previous && Previous->is(TT_SelectorName)) {
745 Previous->ObjCSelectorNameParts = 1;
746 Contexts.back().FirstObjCSelectorName = Previous;
748 } else {
749 Left->ParameterCount =
750 Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts;
752 if (Contexts.back().FirstObjCSelectorName) {
753 Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
754 Contexts.back().LongestObjCSelectorName;
755 if (Left->BlockParameterCount > 1)
756 Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = 0;
758 next();
759 return true;
761 if (CurrentToken->isOneOf(tok::r_paren, tok::r_brace))
762 return false;
763 if (CurrentToken->is(tok::colon)) {
764 if (IsCpp11AttributeSpecifier &&
765 CurrentToken->endsSequence(tok::colon, tok::identifier,
766 tok::kw_using)) {
767 // Remember that this is a [[using ns: foo]] C++ attribute, so we
768 // don't add a space before the colon (unlike other colons).
769 CurrentToken->setType(TT_AttributeColon);
770 } else if (!Style.isVerilog() && !Line.InPragmaDirective &&
771 Left->isOneOf(TT_ArraySubscriptLSquare,
772 TT_DesignatedInitializerLSquare)) {
773 Left->setType(TT_ObjCMethodExpr);
774 StartsObjCMethodExpr = true;
775 Contexts.back().ColonIsObjCMethodExpr = true;
776 if (Parent && Parent->is(tok::r_paren)) {
777 // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen.
778 Parent->setType(TT_CastRParen);
781 ColonFound = true;
783 if (CurrentToken->is(tok::comma) && Left->is(TT_ObjCMethodExpr) &&
784 !ColonFound) {
785 Left->setType(TT_ArrayInitializerLSquare);
787 FormatToken *Tok = CurrentToken;
788 if (!consumeToken())
789 return false;
790 updateParameterCount(Left, Tok);
792 return false;
795 bool couldBeInStructArrayInitializer() const {
796 if (Contexts.size() < 2)
797 return false;
798 // We want to back up no more then 2 context levels i.e.
799 // . { { <-
800 const auto End = std::next(Contexts.rbegin(), 2);
801 auto Last = Contexts.rbegin();
802 unsigned Depth = 0;
803 for (; Last != End; ++Last)
804 if (Last->ContextKind == tok::l_brace)
805 ++Depth;
806 return Depth == 2 && Last->ContextKind != tok::l_brace;
809 bool parseBrace() {
810 if (!CurrentToken)
811 return true;
813 assert(CurrentToken->Previous);
814 FormatToken &OpeningBrace = *CurrentToken->Previous;
815 assert(OpeningBrace.is(tok::l_brace));
816 OpeningBrace.ParentBracket = Contexts.back().ContextKind;
818 if (Contexts.back().CaretFound)
819 OpeningBrace.overwriteFixedType(TT_ObjCBlockLBrace);
820 Contexts.back().CaretFound = false;
822 ScopedContextCreator ContextCreator(*this, tok::l_brace, 1);
823 Contexts.back().ColonIsDictLiteral = true;
824 if (OpeningBrace.is(BK_BracedInit))
825 Contexts.back().IsExpression = true;
826 if (Style.isJavaScript() && OpeningBrace.Previous &&
827 OpeningBrace.Previous->is(TT_JsTypeColon)) {
828 Contexts.back().IsExpression = false;
831 unsigned CommaCount = 0;
832 while (CurrentToken) {
833 if (CurrentToken->is(tok::r_brace)) {
834 assert(OpeningBrace.Optional == CurrentToken->Optional);
835 OpeningBrace.MatchingParen = CurrentToken;
836 CurrentToken->MatchingParen = &OpeningBrace;
837 if (Style.AlignArrayOfStructures != FormatStyle::AIAS_None) {
838 if (OpeningBrace.ParentBracket == tok::l_brace &&
839 couldBeInStructArrayInitializer() && CommaCount > 0) {
840 Contexts.back().ContextType = Context::StructArrayInitializer;
843 next();
844 return true;
846 if (CurrentToken->isOneOf(tok::r_paren, tok::r_square))
847 return false;
848 updateParameterCount(&OpeningBrace, CurrentToken);
849 if (CurrentToken->isOneOf(tok::colon, tok::l_brace, tok::less)) {
850 FormatToken *Previous = CurrentToken->getPreviousNonComment();
851 if (Previous->is(TT_JsTypeOptionalQuestion))
852 Previous = Previous->getPreviousNonComment();
853 if ((CurrentToken->is(tok::colon) &&
854 (!Contexts.back().ColonIsDictLiteral || !Style.isCpp())) ||
855 Style.Language == FormatStyle::LK_Proto ||
856 Style.Language == FormatStyle::LK_TextProto) {
857 OpeningBrace.setType(TT_DictLiteral);
858 if (Previous->Tok.getIdentifierInfo() ||
859 Previous->is(tok::string_literal)) {
860 Previous->setType(TT_SelectorName);
863 if (CurrentToken->is(tok::colon) && OpeningBrace.is(TT_Unknown))
864 OpeningBrace.setType(TT_DictLiteral);
865 else if (Style.isJavaScript())
866 OpeningBrace.overwriteFixedType(TT_DictLiteral);
868 if (CurrentToken->is(tok::comma)) {
869 if (Style.isJavaScript())
870 OpeningBrace.overwriteFixedType(TT_DictLiteral);
871 ++CommaCount;
873 if (!consumeToken())
874 return false;
876 return true;
879 void updateParameterCount(FormatToken *Left, FormatToken *Current) {
880 // For ObjC methods, the number of parameters is calculated differently as
881 // method declarations have a different structure (the parameters are not
882 // inside a bracket scope).
883 if (Current->is(tok::l_brace) && Current->is(BK_Block))
884 ++Left->BlockParameterCount;
885 if (Current->is(tok::comma)) {
886 ++Left->ParameterCount;
887 if (!Left->Role)
888 Left->Role.reset(new CommaSeparatedList(Style));
889 Left->Role->CommaFound(Current);
890 } else if (Left->ParameterCount == 0 && Current->isNot(tok::comment)) {
891 Left->ParameterCount = 1;
895 bool parseConditional() {
896 while (CurrentToken) {
897 if (CurrentToken->is(tok::colon)) {
898 CurrentToken->setType(TT_ConditionalExpr);
899 next();
900 return true;
902 if (!consumeToken())
903 return false;
905 return false;
908 bool parseTemplateDeclaration() {
909 if (CurrentToken && CurrentToken->is(tok::less)) {
910 CurrentToken->setType(TT_TemplateOpener);
911 next();
912 if (!parseAngle())
913 return false;
914 if (CurrentToken)
915 CurrentToken->Previous->ClosesTemplateDeclaration = true;
916 return true;
918 return false;
921 bool consumeToken() {
922 FormatToken *Tok = CurrentToken;
923 next();
924 // In Verilog primitives' state tables, `:`, `?`, and `-` aren't normal
925 // operators.
926 if (Tok->is(TT_VerilogTableItem))
927 return true;
928 switch (Tok->Tok.getKind()) {
929 case tok::plus:
930 case tok::minus:
931 if (!Tok->Previous && Line.MustBeDeclaration)
932 Tok->setType(TT_ObjCMethodSpecifier);
933 break;
934 case tok::colon:
935 if (!Tok->Previous)
936 return false;
937 // Colons from ?: are handled in parseConditional().
938 if (Style.isJavaScript()) {
939 if (Contexts.back().ColonIsForRangeExpr || // colon in for loop
940 (Contexts.size() == 1 && // switch/case labels
941 !Line.First->isOneOf(tok::kw_enum, tok::kw_case)) ||
942 Contexts.back().ContextKind == tok::l_paren || // function params
943 Contexts.back().ContextKind == tok::l_square || // array type
944 (!Contexts.back().IsExpression &&
945 Contexts.back().ContextKind == tok::l_brace) || // object type
946 (Contexts.size() == 1 &&
947 Line.MustBeDeclaration)) { // method/property declaration
948 Contexts.back().IsExpression = false;
949 Tok->setType(TT_JsTypeColon);
950 break;
952 } else if (Style.isCSharp()) {
953 if (Contexts.back().InCSharpAttributeSpecifier) {
954 Tok->setType(TT_AttributeColon);
955 break;
957 if (Contexts.back().ContextKind == tok::l_paren) {
958 Tok->setType(TT_CSharpNamedArgumentColon);
959 break;
961 } else if (Style.isVerilog() && Tok->isNot(TT_BinaryOperator)) {
962 // The distribution weight operators are labeled
963 // TT_BinaryOperator by the lexer.
964 if (Keywords.isVerilogEnd(*Tok->Previous) ||
965 Keywords.isVerilogBegin(*Tok->Previous)) {
966 Tok->setType(TT_VerilogBlockLabelColon);
967 } else if (Contexts.back().ContextKind == tok::l_square) {
968 Tok->setType(TT_BitFieldColon);
969 } else if (Contexts.back().ColonIsDictLiteral) {
970 Tok->setType(TT_DictLiteral);
971 } else if (Contexts.size() == 1) {
972 // In Verilog a case label doesn't have the case keyword. We
973 // assume a colon following an expression is a case label.
974 // Colons from ?: are annotated in parseConditional().
975 Tok->setType(TT_GotoLabelColon);
976 if (Line.Level > 1 || (!Line.InPPDirective && Line.Level > 0))
977 --Line.Level;
979 break;
981 if (Line.First->isOneOf(Keywords.kw_module, Keywords.kw_import) ||
982 Line.First->startsSequence(tok::kw_export, Keywords.kw_module) ||
983 Line.First->startsSequence(tok::kw_export, Keywords.kw_import)) {
984 Tok->setType(TT_ModulePartitionColon);
985 } else if (Contexts.back().ColonIsDictLiteral ||
986 Style.Language == FormatStyle::LK_Proto ||
987 Style.Language == FormatStyle::LK_TextProto) {
988 Tok->setType(TT_DictLiteral);
989 if (Style.Language == FormatStyle::LK_TextProto) {
990 if (FormatToken *Previous = Tok->getPreviousNonComment())
991 Previous->setType(TT_SelectorName);
993 } else if (Contexts.back().ColonIsObjCMethodExpr ||
994 Line.startsWith(TT_ObjCMethodSpecifier)) {
995 Tok->setType(TT_ObjCMethodExpr);
996 const FormatToken *BeforePrevious = Tok->Previous->Previous;
997 // Ensure we tag all identifiers in method declarations as
998 // TT_SelectorName.
999 bool UnknownIdentifierInMethodDeclaration =
1000 Line.startsWith(TT_ObjCMethodSpecifier) &&
1001 Tok->Previous->is(tok::identifier) && Tok->Previous->is(TT_Unknown);
1002 if (!BeforePrevious ||
1003 // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen.
1004 !(BeforePrevious->is(TT_CastRParen) ||
1005 (BeforePrevious->is(TT_ObjCMethodExpr) &&
1006 BeforePrevious->is(tok::colon))) ||
1007 BeforePrevious->is(tok::r_square) ||
1008 Contexts.back().LongestObjCSelectorName == 0 ||
1009 UnknownIdentifierInMethodDeclaration) {
1010 Tok->Previous->setType(TT_SelectorName);
1011 if (!Contexts.back().FirstObjCSelectorName) {
1012 Contexts.back().FirstObjCSelectorName = Tok->Previous;
1013 } else if (Tok->Previous->ColumnWidth >
1014 Contexts.back().LongestObjCSelectorName) {
1015 Contexts.back().LongestObjCSelectorName =
1016 Tok->Previous->ColumnWidth;
1018 Tok->Previous->ParameterIndex =
1019 Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts;
1020 ++Contexts.back().FirstObjCSelectorName->ObjCSelectorNameParts;
1022 } else if (Contexts.back().ColonIsForRangeExpr) {
1023 Tok->setType(TT_RangeBasedForLoopColon);
1024 } else if (CurrentToken && CurrentToken->is(tok::numeric_constant)) {
1025 Tok->setType(TT_BitFieldColon);
1026 } else if (Contexts.size() == 1 &&
1027 !Line.First->isOneOf(tok::kw_enum, tok::kw_case,
1028 tok::kw_default)) {
1029 FormatToken *Prev = Tok->getPreviousNonComment();
1030 if (!Prev)
1031 break;
1032 if (Prev->isOneOf(tok::r_paren, tok::kw_noexcept) ||
1033 Prev->ClosesRequiresClause) {
1034 Tok->setType(TT_CtorInitializerColon);
1035 } else if (Prev->is(tok::kw_try)) {
1036 // Member initializer list within function try block.
1037 FormatToken *PrevPrev = Prev->getPreviousNonComment();
1038 if (!PrevPrev)
1039 break;
1040 if (PrevPrev && PrevPrev->isOneOf(tok::r_paren, tok::kw_noexcept))
1041 Tok->setType(TT_CtorInitializerColon);
1042 } else {
1043 Tok->setType(TT_InheritanceColon);
1045 } else if (canBeObjCSelectorComponent(*Tok->Previous) && Tok->Next &&
1046 (Tok->Next->isOneOf(tok::r_paren, tok::comma) ||
1047 (canBeObjCSelectorComponent(*Tok->Next) && Tok->Next->Next &&
1048 Tok->Next->Next->is(tok::colon)))) {
1049 // This handles a special macro in ObjC code where selectors including
1050 // the colon are passed as macro arguments.
1051 Tok->setType(TT_ObjCMethodExpr);
1052 } else if (Contexts.back().ContextKind == tok::l_paren &&
1053 !Line.InPragmaDirective) {
1054 Tok->setType(TT_InlineASMColon);
1056 break;
1057 case tok::pipe:
1058 case tok::amp:
1059 // | and & in declarations/type expressions represent union and
1060 // intersection types, respectively.
1061 if (Style.isJavaScript() && !Contexts.back().IsExpression)
1062 Tok->setType(TT_JsTypeOperator);
1063 break;
1064 case tok::kw_if:
1065 if (CurrentToken &&
1066 CurrentToken->isOneOf(tok::kw_constexpr, tok::identifier)) {
1067 next();
1069 [[fallthrough]];
1070 case tok::kw_while:
1071 if (CurrentToken && CurrentToken->is(tok::l_paren)) {
1072 next();
1073 if (!parseParens(/*LookForDecls=*/true))
1074 return false;
1076 break;
1077 case tok::kw_for:
1078 if (Style.isJavaScript()) {
1079 // x.for and {for: ...}
1080 if ((Tok->Previous && Tok->Previous->is(tok::period)) ||
1081 (Tok->Next && Tok->Next->is(tok::colon))) {
1082 break;
1084 // JS' for await ( ...
1085 if (CurrentToken && CurrentToken->is(Keywords.kw_await))
1086 next();
1088 if (Style.isCpp() && CurrentToken && CurrentToken->is(tok::kw_co_await))
1089 next();
1090 Contexts.back().ColonIsForRangeExpr = true;
1091 if (!CurrentToken || CurrentToken->isNot(tok::l_paren))
1092 return false;
1093 next();
1094 if (!parseParens())
1095 return false;
1096 break;
1097 case tok::l_paren:
1098 // When faced with 'operator()()', the kw_operator handler incorrectly
1099 // marks the first l_paren as a OverloadedOperatorLParen. Here, we make
1100 // the first two parens OverloadedOperators and the second l_paren an
1101 // OverloadedOperatorLParen.
1102 if (Tok->Previous && Tok->Previous->is(tok::r_paren) &&
1103 Tok->Previous->MatchingParen &&
1104 Tok->Previous->MatchingParen->is(TT_OverloadedOperatorLParen)) {
1105 Tok->Previous->setType(TT_OverloadedOperator);
1106 Tok->Previous->MatchingParen->setType(TT_OverloadedOperator);
1107 Tok->setType(TT_OverloadedOperatorLParen);
1110 if (!parseParens())
1111 return false;
1112 if (Line.MustBeDeclaration && Contexts.size() == 1 &&
1113 !Contexts.back().IsExpression && !Line.startsWith(TT_ObjCProperty) &&
1114 !Tok->isOneOf(TT_TypeDeclarationParen, TT_RequiresExpressionLParen) &&
1115 (!Tok->Previous ||
1116 !Tok->Previous->isOneOf(tok::kw___attribute, TT_RequiresClause,
1117 TT_LeadingJavaAnnotation))) {
1118 Line.MightBeFunctionDecl = true;
1120 break;
1121 case tok::l_square:
1122 if (!parseSquare())
1123 return false;
1124 break;
1125 case tok::l_brace:
1126 if (Style.Language == FormatStyle::LK_TextProto) {
1127 FormatToken *Previous = Tok->getPreviousNonComment();
1128 if (Previous && Previous->getType() != TT_DictLiteral)
1129 Previous->setType(TT_SelectorName);
1131 if (!parseBrace())
1132 return false;
1133 break;
1134 case tok::less:
1135 if (parseAngle()) {
1136 Tok->setType(TT_TemplateOpener);
1137 // In TT_Proto, we must distignuish between:
1138 // map<key, value>
1139 // msg < item: data >
1140 // msg: < item: data >
1141 // In TT_TextProto, map<key, value> does not occur.
1142 if (Style.Language == FormatStyle::LK_TextProto ||
1143 (Style.Language == FormatStyle::LK_Proto && Tok->Previous &&
1144 Tok->Previous->isOneOf(TT_SelectorName, TT_DictLiteral))) {
1145 Tok->setType(TT_DictLiteral);
1146 FormatToken *Previous = Tok->getPreviousNonComment();
1147 if (Previous && Previous->getType() != TT_DictLiteral)
1148 Previous->setType(TT_SelectorName);
1150 } else {
1151 Tok->setType(TT_BinaryOperator);
1152 NonTemplateLess.insert(Tok);
1153 CurrentToken = Tok;
1154 next();
1156 break;
1157 case tok::r_paren:
1158 case tok::r_square:
1159 return false;
1160 case tok::r_brace:
1161 // Lines can start with '}'.
1162 if (Tok->Previous)
1163 return false;
1164 break;
1165 case tok::greater:
1166 if (Style.Language != FormatStyle::LK_TextProto)
1167 Tok->setType(TT_BinaryOperator);
1168 if (Tok->Previous && Tok->Previous->is(TT_TemplateCloser))
1169 Tok->SpacesRequiredBefore = 1;
1170 break;
1171 case tok::kw_operator:
1172 if (Style.Language == FormatStyle::LK_TextProto ||
1173 Style.Language == FormatStyle::LK_Proto) {
1174 break;
1176 while (CurrentToken &&
1177 !CurrentToken->isOneOf(tok::l_paren, tok::semi, tok::r_paren)) {
1178 if (CurrentToken->isOneOf(tok::star, tok::amp))
1179 CurrentToken->setType(TT_PointerOrReference);
1180 consumeToken();
1181 if (!CurrentToken)
1182 continue;
1183 if (CurrentToken->is(tok::comma) &&
1184 CurrentToken->Previous->isNot(tok::kw_operator)) {
1185 break;
1187 if (CurrentToken->Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator,
1188 tok::comma, tok::star, tok::arrow,
1189 tok::amp, tok::ampamp) ||
1190 // User defined literal.
1191 CurrentToken->Previous->TokenText.startswith("\"\"")) {
1192 CurrentToken->Previous->setType(TT_OverloadedOperator);
1195 if (CurrentToken && CurrentToken->is(tok::l_paren))
1196 CurrentToken->setType(TT_OverloadedOperatorLParen);
1197 if (CurrentToken && CurrentToken->Previous->is(TT_BinaryOperator))
1198 CurrentToken->Previous->setType(TT_OverloadedOperator);
1199 break;
1200 case tok::question:
1201 if (Style.isJavaScript() && Tok->Next &&
1202 Tok->Next->isOneOf(tok::semi, tok::comma, tok::colon, tok::r_paren,
1203 tok::r_brace)) {
1204 // Question marks before semicolons, colons, etc. indicate optional
1205 // types (fields, parameters), e.g.
1206 // function(x?: string, y?) {...}
1207 // class X { y?; }
1208 Tok->setType(TT_JsTypeOptionalQuestion);
1209 break;
1211 // Declarations cannot be conditional expressions, this can only be part
1212 // of a type declaration.
1213 if (Line.MustBeDeclaration && !Contexts.back().IsExpression &&
1214 Style.isJavaScript()) {
1215 break;
1217 if (Style.isCSharp()) {
1218 // `Type?)`, `Type?>`, `Type? name;` and `Type? name =` can only be
1219 // nullable types.
1220 // Line.MustBeDeclaration will be true for `Type? name;`.
1221 if ((!Contexts.back().IsExpression && Line.MustBeDeclaration) ||
1222 (Tok->Next && Tok->Next->isOneOf(tok::r_paren, tok::greater)) ||
1223 (Tok->Next && Tok->Next->is(tok::identifier) && Tok->Next->Next &&
1224 Tok->Next->Next->is(tok::equal))) {
1225 Tok->setType(TT_CSharpNullable);
1226 break;
1229 parseConditional();
1230 break;
1231 case tok::kw_template:
1232 parseTemplateDeclaration();
1233 break;
1234 case tok::comma:
1235 switch (Contexts.back().ContextType) {
1236 case Context::CtorInitializer:
1237 Tok->setType(TT_CtorInitializerComma);
1238 break;
1239 case Context::InheritanceList:
1240 Tok->setType(TT_InheritanceComma);
1241 break;
1242 default:
1243 if (Contexts.back().FirstStartOfName &&
1244 (Contexts.size() == 1 || startsWithInitStatement(Line))) {
1245 Contexts.back().FirstStartOfName->PartOfMultiVariableDeclStmt = true;
1246 Line.IsMultiVariableDeclStmt = true;
1248 break;
1250 if (Contexts.back().ContextType == Context::ForEachMacro)
1251 Contexts.back().IsExpression = true;
1252 break;
1253 case tok::kw_default:
1254 // Unindent case labels.
1255 if (Style.isVerilog() && Keywords.isVerilogEndOfLabel(*Tok) &&
1256 (Line.Level > 1 || (!Line.InPPDirective && Line.Level > 0))) {
1257 --Line.Level;
1259 break;
1260 case tok::identifier:
1261 if (Tok->isOneOf(Keywords.kw___has_include,
1262 Keywords.kw___has_include_next)) {
1263 parseHasInclude();
1265 if (Style.isCSharp() && Tok->is(Keywords.kw_where) && Tok->Next &&
1266 Tok->Next->isNot(tok::l_paren)) {
1267 Tok->setType(TT_CSharpGenericTypeConstraint);
1268 parseCSharpGenericTypeConstraint();
1269 if (Tok->getPreviousNonComment() == nullptr)
1270 Line.IsContinuation = true;
1272 break;
1273 case tok::arrow:
1274 if (Tok->isNot(TT_LambdaArrow) && Tok->Previous &&
1275 Tok->Previous->is(tok::kw_noexcept)) {
1276 Tok->setType(TT_TrailingReturnArrow);
1278 break;
1279 default:
1280 break;
1282 return true;
1285 void parseCSharpGenericTypeConstraint() {
1286 int OpenAngleBracketsCount = 0;
1287 while (CurrentToken) {
1288 if (CurrentToken->is(tok::less)) {
1289 // parseAngle is too greedy and will consume the whole line.
1290 CurrentToken->setType(TT_TemplateOpener);
1291 ++OpenAngleBracketsCount;
1292 next();
1293 } else if (CurrentToken->is(tok::greater)) {
1294 CurrentToken->setType(TT_TemplateCloser);
1295 --OpenAngleBracketsCount;
1296 next();
1297 } else if (CurrentToken->is(tok::comma) && OpenAngleBracketsCount == 0) {
1298 // We allow line breaks after GenericTypeConstraintComma's
1299 // so do not flag commas in Generics as GenericTypeConstraintComma's.
1300 CurrentToken->setType(TT_CSharpGenericTypeConstraintComma);
1301 next();
1302 } else if (CurrentToken->is(Keywords.kw_where)) {
1303 CurrentToken->setType(TT_CSharpGenericTypeConstraint);
1304 next();
1305 } else if (CurrentToken->is(tok::colon)) {
1306 CurrentToken->setType(TT_CSharpGenericTypeConstraintColon);
1307 next();
1308 } else {
1309 next();
1314 void parseIncludeDirective() {
1315 if (CurrentToken && CurrentToken->is(tok::less)) {
1316 next();
1317 while (CurrentToken) {
1318 // Mark tokens up to the trailing line comments as implicit string
1319 // literals.
1320 if (CurrentToken->isNot(tok::comment) &&
1321 !CurrentToken->TokenText.startswith("//")) {
1322 CurrentToken->setType(TT_ImplicitStringLiteral);
1324 next();
1329 void parseWarningOrError() {
1330 next();
1331 // We still want to format the whitespace left of the first token of the
1332 // warning or error.
1333 next();
1334 while (CurrentToken) {
1335 CurrentToken->setType(TT_ImplicitStringLiteral);
1336 next();
1340 void parsePragma() {
1341 next(); // Consume "pragma".
1342 if (CurrentToken &&
1343 CurrentToken->isOneOf(Keywords.kw_mark, Keywords.kw_option,
1344 Keywords.kw_region)) {
1345 bool IsMarkOrRegion =
1346 CurrentToken->isOneOf(Keywords.kw_mark, Keywords.kw_region);
1347 next();
1348 next(); // Consume first token (so we fix leading whitespace).
1349 while (CurrentToken) {
1350 if (IsMarkOrRegion || CurrentToken->Previous->is(TT_BinaryOperator)) {
1351 CurrentToken->setType(TT_ImplicitStringLiteral);
1353 next();
1358 void parseHasInclude() {
1359 if (!CurrentToken || !CurrentToken->is(tok::l_paren))
1360 return;
1361 next(); // '('
1362 parseIncludeDirective();
1363 next(); // ')'
1366 LineType parsePreprocessorDirective() {
1367 bool IsFirstToken = CurrentToken->IsFirst;
1368 LineType Type = LT_PreprocessorDirective;
1369 next();
1370 if (!CurrentToken)
1371 return Type;
1373 if (Style.isJavaScript() && IsFirstToken) {
1374 // JavaScript files can contain shebang lines of the form:
1375 // #!/usr/bin/env node
1376 // Treat these like C++ #include directives.
1377 while (CurrentToken) {
1378 // Tokens cannot be comments here.
1379 CurrentToken->setType(TT_ImplicitStringLiteral);
1380 next();
1382 return LT_ImportStatement;
1385 if (CurrentToken->is(tok::numeric_constant)) {
1386 CurrentToken->SpacesRequiredBefore = 1;
1387 return Type;
1389 // Hashes in the middle of a line can lead to any strange token
1390 // sequence.
1391 if (!CurrentToken->Tok.getIdentifierInfo())
1392 return Type;
1393 // In Verilog macro expansions start with a backtick just like preprocessor
1394 // directives. Thus we stop if the word is not a preprocessor directive.
1395 if (Style.isVerilog() && !Keywords.isVerilogPPDirective(*CurrentToken))
1396 return LT_Invalid;
1397 switch (CurrentToken->Tok.getIdentifierInfo()->getPPKeywordID()) {
1398 case tok::pp_include:
1399 case tok::pp_include_next:
1400 case tok::pp_import:
1401 next();
1402 parseIncludeDirective();
1403 Type = LT_ImportStatement;
1404 break;
1405 case tok::pp_error:
1406 case tok::pp_warning:
1407 parseWarningOrError();
1408 break;
1409 case tok::pp_pragma:
1410 parsePragma();
1411 break;
1412 case tok::pp_if:
1413 case tok::pp_elif:
1414 Contexts.back().IsExpression = true;
1415 next();
1416 parseLine();
1417 break;
1418 default:
1419 break;
1421 while (CurrentToken) {
1422 FormatToken *Tok = CurrentToken;
1423 next();
1424 if (Tok->is(tok::l_paren)) {
1425 parseParens();
1426 } else if (Tok->isOneOf(Keywords.kw___has_include,
1427 Keywords.kw___has_include_next)) {
1428 parseHasInclude();
1431 return Type;
1434 public:
1435 LineType parseLine() {
1436 if (!CurrentToken)
1437 return LT_Invalid;
1438 NonTemplateLess.clear();
1439 if (!Line.InMacroBody && CurrentToken->is(tok::hash)) {
1440 // We were not yet allowed to use C++17 optional when this was being
1441 // written. So we used LT_Invalid to mark that the line is not a
1442 // preprocessor directive.
1443 auto Type = parsePreprocessorDirective();
1444 if (Type != LT_Invalid)
1445 return Type;
1448 // Directly allow to 'import <string-literal>' to support protocol buffer
1449 // definitions (github.com/google/protobuf) or missing "#" (either way we
1450 // should not break the line).
1451 IdentifierInfo *Info = CurrentToken->Tok.getIdentifierInfo();
1452 if ((Style.Language == FormatStyle::LK_Java &&
1453 CurrentToken->is(Keywords.kw_package)) ||
1454 (!Style.isVerilog() && Info &&
1455 Info->getPPKeywordID() == tok::pp_import && CurrentToken->Next &&
1456 CurrentToken->Next->isOneOf(tok::string_literal, tok::identifier,
1457 tok::kw_static))) {
1458 next();
1459 parseIncludeDirective();
1460 return LT_ImportStatement;
1463 // If this line starts and ends in '<' and '>', respectively, it is likely
1464 // part of "#define <a/b.h>".
1465 if (CurrentToken->is(tok::less) && Line.Last->is(tok::greater)) {
1466 parseIncludeDirective();
1467 return LT_ImportStatement;
1470 // In .proto files, top-level options and package statements are very
1471 // similar to import statements and should not be line-wrapped.
1472 if (Style.Language == FormatStyle::LK_Proto && Line.Level == 0 &&
1473 CurrentToken->isOneOf(Keywords.kw_option, Keywords.kw_package)) {
1474 next();
1475 if (CurrentToken && CurrentToken->is(tok::identifier)) {
1476 while (CurrentToken)
1477 next();
1478 return LT_ImportStatement;
1482 bool KeywordVirtualFound = false;
1483 bool ImportStatement = false;
1485 // import {...} from '...';
1486 if (Style.isJavaScript() && CurrentToken->is(Keywords.kw_import))
1487 ImportStatement = true;
1489 while (CurrentToken) {
1490 if (CurrentToken->is(tok::kw_virtual))
1491 KeywordVirtualFound = true;
1492 if (Style.isJavaScript()) {
1493 // export {...} from '...';
1494 // An export followed by "from 'some string';" is a re-export from
1495 // another module identified by a URI and is treated as a
1496 // LT_ImportStatement (i.e. prevent wraps on it for long URIs).
1497 // Just "export {...};" or "export class ..." should not be treated as
1498 // an import in this sense.
1499 if (Line.First->is(tok::kw_export) &&
1500 CurrentToken->is(Keywords.kw_from) && CurrentToken->Next &&
1501 CurrentToken->Next->isStringLiteral()) {
1502 ImportStatement = true;
1504 if (isClosureImportStatement(*CurrentToken))
1505 ImportStatement = true;
1507 if (!consumeToken())
1508 return LT_Invalid;
1510 if (KeywordVirtualFound)
1511 return LT_VirtualFunctionDecl;
1512 if (ImportStatement)
1513 return LT_ImportStatement;
1515 if (Line.startsWith(TT_ObjCMethodSpecifier)) {
1516 if (Contexts.back().FirstObjCSelectorName) {
1517 Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
1518 Contexts.back().LongestObjCSelectorName;
1520 return LT_ObjCMethodDecl;
1523 for (const auto &ctx : Contexts)
1524 if (ctx.ContextType == Context::StructArrayInitializer)
1525 return LT_ArrayOfStructInitializer;
1527 return LT_Other;
1530 private:
1531 bool isClosureImportStatement(const FormatToken &Tok) {
1532 // FIXME: Closure-library specific stuff should not be hard-coded but be
1533 // configurable.
1534 return Tok.TokenText == "goog" && Tok.Next && Tok.Next->is(tok::period) &&
1535 Tok.Next->Next &&
1536 (Tok.Next->Next->TokenText == "module" ||
1537 Tok.Next->Next->TokenText == "provide" ||
1538 Tok.Next->Next->TokenText == "require" ||
1539 Tok.Next->Next->TokenText == "requireType" ||
1540 Tok.Next->Next->TokenText == "forwardDeclare") &&
1541 Tok.Next->Next->Next && Tok.Next->Next->Next->is(tok::l_paren);
1544 void resetTokenMetadata() {
1545 if (!CurrentToken)
1546 return;
1548 // Reset token type in case we have already looked at it and then
1549 // recovered from an error (e.g. failure to find the matching >).
1550 if (!CurrentToken->isTypeFinalized() &&
1551 !CurrentToken->isOneOf(
1552 TT_LambdaLSquare, TT_LambdaLBrace, TT_AttributeMacro, TT_IfMacro,
1553 TT_ForEachMacro, TT_TypenameMacro, TT_FunctionLBrace,
1554 TT_ImplicitStringLiteral, TT_InlineASMBrace, TT_FatArrow,
1555 TT_LambdaArrow, TT_NamespaceMacro, TT_OverloadedOperator,
1556 TT_RegexLiteral, TT_TemplateString, TT_ObjCStringLiteral,
1557 TT_UntouchableMacroFunc, TT_StatementAttributeLikeMacro,
1558 TT_FunctionLikeOrFreestandingMacro, TT_ClassLBrace, TT_EnumLBrace,
1559 TT_RecordLBrace, TT_StructLBrace, TT_UnionLBrace, TT_RequiresClause,
1560 TT_RequiresClauseInARequiresExpression, TT_RequiresExpression,
1561 TT_RequiresExpressionLParen, TT_RequiresExpressionLBrace,
1562 TT_CompoundRequirementLBrace, TT_BracedListLBrace)) {
1563 CurrentToken->setType(TT_Unknown);
1565 CurrentToken->Role.reset();
1566 CurrentToken->MatchingParen = nullptr;
1567 CurrentToken->FakeLParens.clear();
1568 CurrentToken->FakeRParens = 0;
1571 void next() {
1572 if (!CurrentToken)
1573 return;
1575 CurrentToken->NestingLevel = Contexts.size() - 1;
1576 CurrentToken->BindingStrength = Contexts.back().BindingStrength;
1577 modifyContext(*CurrentToken);
1578 determineTokenType(*CurrentToken);
1579 CurrentToken = CurrentToken->Next;
1581 resetTokenMetadata();
1584 /// A struct to hold information valid in a specific context, e.g.
1585 /// a pair of parenthesis.
1586 struct Context {
1587 Context(tok::TokenKind ContextKind, unsigned BindingStrength,
1588 bool IsExpression)
1589 : ContextKind(ContextKind), BindingStrength(BindingStrength),
1590 IsExpression(IsExpression) {}
1592 tok::TokenKind ContextKind;
1593 unsigned BindingStrength;
1594 bool IsExpression;
1595 unsigned LongestObjCSelectorName = 0;
1596 bool ColonIsForRangeExpr = false;
1597 bool ColonIsDictLiteral = false;
1598 bool ColonIsObjCMethodExpr = false;
1599 FormatToken *FirstObjCSelectorName = nullptr;
1600 FormatToken *FirstStartOfName = nullptr;
1601 bool CanBeExpression = true;
1602 bool CaretFound = false;
1603 bool InCpp11AttributeSpecifier = false;
1604 bool InCSharpAttributeSpecifier = false;
1605 enum {
1606 Unknown,
1607 // Like the part after `:` in a constructor.
1608 // Context(...) : IsExpression(IsExpression)
1609 CtorInitializer,
1610 // Like in the parentheses in a foreach.
1611 ForEachMacro,
1612 // Like the inheritance list in a class declaration.
1613 // class Input : public IO
1614 InheritanceList,
1615 // Like in the braced list.
1616 // int x[] = {};
1617 StructArrayInitializer,
1618 // Like in `static_cast<int>`.
1619 TemplateArgument,
1620 } ContextType = Unknown;
1623 /// Puts a new \c Context onto the stack \c Contexts for the lifetime
1624 /// of each instance.
1625 struct ScopedContextCreator {
1626 AnnotatingParser &P;
1628 ScopedContextCreator(AnnotatingParser &P, tok::TokenKind ContextKind,
1629 unsigned Increase)
1630 : P(P) {
1631 P.Contexts.push_back(Context(ContextKind,
1632 P.Contexts.back().BindingStrength + Increase,
1633 P.Contexts.back().IsExpression));
1636 ~ScopedContextCreator() {
1637 if (P.Style.AlignArrayOfStructures != FormatStyle::AIAS_None) {
1638 if (P.Contexts.back().ContextType == Context::StructArrayInitializer) {
1639 P.Contexts.pop_back();
1640 P.Contexts.back().ContextType = Context::StructArrayInitializer;
1641 return;
1644 P.Contexts.pop_back();
1648 void modifyContext(const FormatToken &Current) {
1649 auto AssignmentStartsExpression = [&]() {
1650 if (Current.getPrecedence() != prec::Assignment)
1651 return false;
1653 if (Line.First->isOneOf(tok::kw_using, tok::kw_return))
1654 return false;
1655 if (Line.First->is(tok::kw_template)) {
1656 assert(Current.Previous);
1657 if (Current.Previous->is(tok::kw_operator)) {
1658 // `template ... operator=` cannot be an expression.
1659 return false;
1662 // `template` keyword can start a variable template.
1663 const FormatToken *Tok = Line.First->getNextNonComment();
1664 assert(Tok); // Current token is on the same line.
1665 if (Tok->isNot(TT_TemplateOpener)) {
1666 // Explicit template instantiations do not have `<>`.
1667 return false;
1670 Tok = Tok->MatchingParen;
1671 if (!Tok)
1672 return false;
1673 Tok = Tok->getNextNonComment();
1674 if (!Tok)
1675 return false;
1677 if (Tok->isOneOf(tok::kw_class, tok::kw_enum, tok::kw_concept,
1678 tok::kw_struct, tok::kw_using)) {
1679 return false;
1682 return true;
1685 // Type aliases use `type X = ...;` in TypeScript and can be exported
1686 // using `export type ...`.
1687 if (Style.isJavaScript() &&
1688 (Line.startsWith(Keywords.kw_type, tok::identifier) ||
1689 Line.startsWith(tok::kw_export, Keywords.kw_type,
1690 tok::identifier))) {
1691 return false;
1694 return !Current.Previous || Current.Previous->isNot(tok::kw_operator);
1697 if (AssignmentStartsExpression()) {
1698 Contexts.back().IsExpression = true;
1699 if (!Line.startsWith(TT_UnaryOperator)) {
1700 for (FormatToken *Previous = Current.Previous;
1701 Previous && Previous->Previous &&
1702 !Previous->Previous->isOneOf(tok::comma, tok::semi);
1703 Previous = Previous->Previous) {
1704 if (Previous->isOneOf(tok::r_square, tok::r_paren)) {
1705 Previous = Previous->MatchingParen;
1706 if (!Previous)
1707 break;
1709 if (Previous->opensScope())
1710 break;
1711 if (Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator) &&
1712 Previous->isOneOf(tok::star, tok::amp, tok::ampamp) &&
1713 Previous->Previous && Previous->Previous->isNot(tok::equal)) {
1714 Previous->setType(TT_PointerOrReference);
1718 } else if (Current.is(tok::lessless) &&
1719 (!Current.Previous || !Current.Previous->is(tok::kw_operator))) {
1720 Contexts.back().IsExpression = true;
1721 } else if (Current.isOneOf(tok::kw_return, tok::kw_throw)) {
1722 Contexts.back().IsExpression = true;
1723 } else if (Current.is(TT_TrailingReturnArrow)) {
1724 Contexts.back().IsExpression = false;
1725 } else if (Current.is(TT_LambdaArrow) || Current.is(Keywords.kw_assert)) {
1726 Contexts.back().IsExpression = Style.Language == FormatStyle::LK_Java;
1727 } else if (Current.Previous &&
1728 Current.Previous->is(TT_CtorInitializerColon)) {
1729 Contexts.back().IsExpression = true;
1730 Contexts.back().ContextType = Context::CtorInitializer;
1731 } else if (Current.Previous && Current.Previous->is(TT_InheritanceColon)) {
1732 Contexts.back().ContextType = Context::InheritanceList;
1733 } else if (Current.isOneOf(tok::r_paren, tok::greater, tok::comma)) {
1734 for (FormatToken *Previous = Current.Previous;
1735 Previous && Previous->isOneOf(tok::star, tok::amp);
1736 Previous = Previous->Previous) {
1737 Previous->setType(TT_PointerOrReference);
1739 if (Line.MustBeDeclaration &&
1740 Contexts.front().ContextType != Context::CtorInitializer) {
1741 Contexts.back().IsExpression = false;
1743 } else if (Current.is(tok::kw_new)) {
1744 Contexts.back().CanBeExpression = false;
1745 } else if (Current.is(tok::semi) ||
1746 (Current.is(tok::exclaim) && Current.Previous &&
1747 !Current.Previous->is(tok::kw_operator))) {
1748 // This should be the condition or increment in a for-loop.
1749 // But not operator !() (can't use TT_OverloadedOperator here as its not
1750 // been annotated yet).
1751 Contexts.back().IsExpression = true;
1755 static FormatToken *untilMatchingParen(FormatToken *Current) {
1756 // Used when `MatchingParen` is not yet established.
1757 int ParenLevel = 0;
1758 while (Current) {
1759 if (Current->is(tok::l_paren))
1760 ++ParenLevel;
1761 if (Current->is(tok::r_paren))
1762 --ParenLevel;
1763 if (ParenLevel < 1)
1764 break;
1765 Current = Current->Next;
1767 return Current;
1770 static bool isDeductionGuide(FormatToken &Current) {
1771 // Look for a deduction guide template<T> A(...) -> A<...>;
1772 if (Current.Previous && Current.Previous->is(tok::r_paren) &&
1773 Current.startsSequence(tok::arrow, tok::identifier, tok::less)) {
1774 // Find the TemplateCloser.
1775 FormatToken *TemplateCloser = Current.Next->Next;
1776 int NestingLevel = 0;
1777 while (TemplateCloser) {
1778 // Skip over an expressions in parens A<(3 < 2)>;
1779 if (TemplateCloser->is(tok::l_paren)) {
1780 // No Matching Paren yet so skip to matching paren
1781 TemplateCloser = untilMatchingParen(TemplateCloser);
1782 if (!TemplateCloser)
1783 break;
1785 if (TemplateCloser->is(tok::less))
1786 ++NestingLevel;
1787 if (TemplateCloser->is(tok::greater))
1788 --NestingLevel;
1789 if (NestingLevel < 1)
1790 break;
1791 TemplateCloser = TemplateCloser->Next;
1793 // Assuming we have found the end of the template ensure its followed
1794 // with a semi-colon.
1795 if (TemplateCloser && TemplateCloser->Next &&
1796 TemplateCloser->Next->is(tok::semi) &&
1797 Current.Previous->MatchingParen) {
1798 // Determine if the identifier `A` prior to the A<..>; is the same as
1799 // prior to the A(..)
1800 FormatToken *LeadingIdentifier =
1801 Current.Previous->MatchingParen->Previous;
1803 // Differentiate a deduction guide by seeing the
1804 // > of the template prior to the leading identifier.
1805 if (LeadingIdentifier) {
1806 FormatToken *PriorLeadingIdentifier = LeadingIdentifier->Previous;
1807 // Skip back past explicit decoration
1808 if (PriorLeadingIdentifier &&
1809 PriorLeadingIdentifier->is(tok::kw_explicit)) {
1810 PriorLeadingIdentifier = PriorLeadingIdentifier->Previous;
1813 return PriorLeadingIdentifier &&
1814 (PriorLeadingIdentifier->is(TT_TemplateCloser) ||
1815 PriorLeadingIdentifier->ClosesRequiresClause) &&
1816 LeadingIdentifier->TokenText == Current.Next->TokenText;
1820 return false;
1823 void determineTokenType(FormatToken &Current) {
1824 if (!Current.is(TT_Unknown)) {
1825 // The token type is already known.
1826 return;
1829 if ((Style.isJavaScript() || Style.isCSharp()) &&
1830 Current.is(tok::exclaim)) {
1831 if (Current.Previous) {
1832 bool IsIdentifier =
1833 Style.isJavaScript()
1834 ? Keywords.IsJavaScriptIdentifier(
1835 *Current.Previous, /* AcceptIdentifierName= */ true)
1836 : Current.Previous->is(tok::identifier);
1837 if (IsIdentifier ||
1838 Current.Previous->isOneOf(
1839 tok::kw_default, tok::kw_namespace, tok::r_paren, tok::r_square,
1840 tok::r_brace, tok::kw_false, tok::kw_true, Keywords.kw_type,
1841 Keywords.kw_get, Keywords.kw_init, Keywords.kw_set) ||
1842 Current.Previous->Tok.isLiteral()) {
1843 Current.setType(TT_NonNullAssertion);
1844 return;
1847 if (Current.Next &&
1848 Current.Next->isOneOf(TT_BinaryOperator, Keywords.kw_as)) {
1849 Current.setType(TT_NonNullAssertion);
1850 return;
1854 // Line.MightBeFunctionDecl can only be true after the parentheses of a
1855 // function declaration have been found. In this case, 'Current' is a
1856 // trailing token of this declaration and thus cannot be a name.
1857 if (Current.is(Keywords.kw_instanceof)) {
1858 Current.setType(TT_BinaryOperator);
1859 } else if (isStartOfName(Current) &&
1860 (!Line.MightBeFunctionDecl || Current.NestingLevel != 0)) {
1861 Contexts.back().FirstStartOfName = &Current;
1862 Current.setType(TT_StartOfName);
1863 } else if (Current.is(tok::semi)) {
1864 // Reset FirstStartOfName after finding a semicolon so that a for loop
1865 // with multiple increment statements is not confused with a for loop
1866 // having multiple variable declarations.
1867 Contexts.back().FirstStartOfName = nullptr;
1868 } else if (Current.isOneOf(tok::kw_auto, tok::kw___auto_type)) {
1869 AutoFound = true;
1870 } else if (Current.is(tok::arrow) &&
1871 Style.Language == FormatStyle::LK_Java) {
1872 Current.setType(TT_LambdaArrow);
1873 } else if (Current.is(tok::arrow) && AutoFound && Line.MustBeDeclaration &&
1874 Current.NestingLevel == 0 &&
1875 !Current.Previous->isOneOf(tok::kw_operator, tok::identifier)) {
1876 // not auto operator->() -> xxx;
1877 Current.setType(TT_TrailingReturnArrow);
1878 } else if (Current.is(tok::arrow) && Current.Previous &&
1879 Current.Previous->is(tok::r_brace)) {
1880 // Concept implicit conversion constraint needs to be treated like
1881 // a trailing return type ... } -> <type>.
1882 Current.setType(TT_TrailingReturnArrow);
1883 } else if (isDeductionGuide(Current)) {
1884 // Deduction guides trailing arrow " A(...) -> A<T>;".
1885 Current.setType(TT_TrailingReturnArrow);
1886 } else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) {
1887 Current.setType(determineStarAmpUsage(
1888 Current,
1889 Contexts.back().CanBeExpression && Contexts.back().IsExpression,
1890 Contexts.back().ContextType == Context::TemplateArgument));
1891 } else if (Current.isOneOf(tok::minus, tok::plus, tok::caret) ||
1892 (Style.isVerilog() && Current.is(tok::pipe))) {
1893 Current.setType(determinePlusMinusCaretUsage(Current));
1894 if (Current.is(TT_UnaryOperator) && Current.is(tok::caret))
1895 Contexts.back().CaretFound = true;
1896 } else if (Current.isOneOf(tok::minusminus, tok::plusplus)) {
1897 Current.setType(determineIncrementUsage(Current));
1898 } else if (Current.isOneOf(tok::exclaim, tok::tilde)) {
1899 Current.setType(TT_UnaryOperator);
1900 } else if (Current.is(tok::question)) {
1901 if (Style.isJavaScript() && Line.MustBeDeclaration &&
1902 !Contexts.back().IsExpression) {
1903 // In JavaScript, `interface X { foo?(): bar; }` is an optional method
1904 // on the interface, not a ternary expression.
1905 Current.setType(TT_JsTypeOptionalQuestion);
1906 } else {
1907 Current.setType(TT_ConditionalExpr);
1909 } else if (Current.isBinaryOperator() &&
1910 (!Current.Previous || Current.Previous->isNot(tok::l_square)) &&
1911 (!Current.is(tok::greater) &&
1912 Style.Language != FormatStyle::LK_TextProto)) {
1913 Current.setType(TT_BinaryOperator);
1914 } else if (Current.is(tok::comment)) {
1915 if (Current.TokenText.startswith("/*")) {
1916 if (Current.TokenText.endswith("*/")) {
1917 Current.setType(TT_BlockComment);
1918 } else {
1919 // The lexer has for some reason determined a comment here. But we
1920 // cannot really handle it, if it isn't properly terminated.
1921 Current.Tok.setKind(tok::unknown);
1923 } else {
1924 Current.setType(TT_LineComment);
1926 } else if (Current.is(tok::l_paren)) {
1927 if (lParenStartsCppCast(Current))
1928 Current.setType(TT_CppCastLParen);
1929 } else if (Current.is(tok::r_paren)) {
1930 if (rParenEndsCast(Current))
1931 Current.setType(TT_CastRParen);
1932 if (Current.MatchingParen && Current.Next &&
1933 !Current.Next->isBinaryOperator() &&
1934 !Current.Next->isOneOf(tok::semi, tok::colon, tok::l_brace,
1935 tok::comma, tok::period, tok::arrow,
1936 tok::coloncolon, tok::kw_noexcept)) {
1937 if (FormatToken *AfterParen = Current.MatchingParen->Next) {
1938 // Make sure this isn't the return type of an Obj-C block declaration
1939 if (AfterParen->isNot(tok::caret)) {
1940 if (FormatToken *BeforeParen = Current.MatchingParen->Previous) {
1941 if (BeforeParen->is(tok::identifier) &&
1942 !BeforeParen->is(TT_TypenameMacro) &&
1943 BeforeParen->TokenText == BeforeParen->TokenText.upper() &&
1944 (!BeforeParen->Previous ||
1945 BeforeParen->Previous->ClosesTemplateDeclaration)) {
1946 Current.setType(TT_FunctionAnnotationRParen);
1952 } else if (Current.is(tok::at) && Current.Next && !Style.isJavaScript() &&
1953 Style.Language != FormatStyle::LK_Java) {
1954 // In Java & JavaScript, "@..." is a decorator or annotation. In ObjC, it
1955 // marks declarations and properties that need special formatting.
1956 switch (Current.Next->Tok.getObjCKeywordID()) {
1957 case tok::objc_interface:
1958 case tok::objc_implementation:
1959 case tok::objc_protocol:
1960 Current.setType(TT_ObjCDecl);
1961 break;
1962 case tok::objc_property:
1963 Current.setType(TT_ObjCProperty);
1964 break;
1965 default:
1966 break;
1968 } else if (Current.is(tok::period)) {
1969 FormatToken *PreviousNoComment = Current.getPreviousNonComment();
1970 if (PreviousNoComment &&
1971 PreviousNoComment->isOneOf(tok::comma, tok::l_brace)) {
1972 Current.setType(TT_DesignatedInitializerPeriod);
1973 } else if (Style.Language == FormatStyle::LK_Java && Current.Previous &&
1974 Current.Previous->isOneOf(TT_JavaAnnotation,
1975 TT_LeadingJavaAnnotation)) {
1976 Current.setType(Current.Previous->getType());
1978 } else if (canBeObjCSelectorComponent(Current) &&
1979 // FIXME(bug 36976): ObjC return types shouldn't use
1980 // TT_CastRParen.
1981 Current.Previous && Current.Previous->is(TT_CastRParen) &&
1982 Current.Previous->MatchingParen &&
1983 Current.Previous->MatchingParen->Previous &&
1984 Current.Previous->MatchingParen->Previous->is(
1985 TT_ObjCMethodSpecifier)) {
1986 // This is the first part of an Objective-C selector name. (If there's no
1987 // colon after this, this is the only place which annotates the identifier
1988 // as a selector.)
1989 Current.setType(TT_SelectorName);
1990 } else if (Current.isOneOf(tok::identifier, tok::kw_const, tok::kw_noexcept,
1991 tok::kw_requires) &&
1992 Current.Previous &&
1993 !Current.Previous->isOneOf(tok::equal, tok::at,
1994 TT_CtorInitializerComma,
1995 TT_CtorInitializerColon) &&
1996 Line.MightBeFunctionDecl && Contexts.size() == 1) {
1997 // Line.MightBeFunctionDecl can only be true after the parentheses of a
1998 // function declaration have been found.
1999 Current.setType(TT_TrailingAnnotation);
2000 } else if ((Style.Language == FormatStyle::LK_Java ||
2001 Style.isJavaScript()) &&
2002 Current.Previous) {
2003 if (Current.Previous->is(tok::at) &&
2004 Current.isNot(Keywords.kw_interface)) {
2005 const FormatToken &AtToken = *Current.Previous;
2006 const FormatToken *Previous = AtToken.getPreviousNonComment();
2007 if (!Previous || Previous->is(TT_LeadingJavaAnnotation))
2008 Current.setType(TT_LeadingJavaAnnotation);
2009 else
2010 Current.setType(TT_JavaAnnotation);
2011 } else if (Current.Previous->is(tok::period) &&
2012 Current.Previous->isOneOf(TT_JavaAnnotation,
2013 TT_LeadingJavaAnnotation)) {
2014 Current.setType(Current.Previous->getType());
2019 /// Take a guess at whether \p Tok starts a name of a function or
2020 /// variable declaration.
2022 /// This is a heuristic based on whether \p Tok is an identifier following
2023 /// something that is likely a type.
2024 bool isStartOfName(const FormatToken &Tok) {
2025 if (Tok.isNot(tok::identifier) || !Tok.Previous)
2026 return false;
2028 if (Tok.Previous->isOneOf(TT_LeadingJavaAnnotation, Keywords.kw_instanceof,
2029 Keywords.kw_as)) {
2030 return false;
2032 if (Style.isJavaScript() && Tok.Previous->is(Keywords.kw_in))
2033 return false;
2035 // Skip "const" as it does not have an influence on whether this is a name.
2036 FormatToken *PreviousNotConst = Tok.getPreviousNonComment();
2038 // For javascript const can be like "let" or "var"
2039 if (!Style.isJavaScript())
2040 while (PreviousNotConst && PreviousNotConst->is(tok::kw_const))
2041 PreviousNotConst = PreviousNotConst->getPreviousNonComment();
2043 if (!PreviousNotConst)
2044 return false;
2046 if (PreviousNotConst->ClosesRequiresClause)
2047 return false;
2049 bool IsPPKeyword = PreviousNotConst->is(tok::identifier) &&
2050 PreviousNotConst->Previous &&
2051 PreviousNotConst->Previous->is(tok::hash);
2053 if (PreviousNotConst->is(TT_TemplateCloser)) {
2054 return PreviousNotConst && PreviousNotConst->MatchingParen &&
2055 PreviousNotConst->MatchingParen->Previous &&
2056 PreviousNotConst->MatchingParen->Previous->isNot(tok::period) &&
2057 PreviousNotConst->MatchingParen->Previous->isNot(tok::kw_template);
2060 if (PreviousNotConst->is(tok::r_paren) &&
2061 PreviousNotConst->is(TT_TypeDeclarationParen)) {
2062 return true;
2065 // If is a preprocess keyword like #define.
2066 if (IsPPKeyword)
2067 return false;
2069 // int a or auto a.
2070 if (PreviousNotConst->isOneOf(tok::identifier, tok::kw_auto))
2071 return true;
2073 // *a or &a or &&a.
2074 if (PreviousNotConst->is(TT_PointerOrReference))
2075 return true;
2077 // MyClass a;
2078 if (PreviousNotConst->isSimpleTypeSpecifier())
2079 return true;
2081 // type[] a in Java
2082 if (Style.Language == FormatStyle::LK_Java &&
2083 PreviousNotConst->is(tok::r_square)) {
2084 return true;
2087 // const a = in JavaScript.
2088 return Style.isJavaScript() && PreviousNotConst->is(tok::kw_const);
2091 /// Determine whether '(' is starting a C++ cast.
2092 bool lParenStartsCppCast(const FormatToken &Tok) {
2093 // C-style casts are only used in C++.
2094 if (!Style.isCpp())
2095 return false;
2097 FormatToken *LeftOfParens = Tok.getPreviousNonComment();
2098 if (LeftOfParens && LeftOfParens->is(TT_TemplateCloser) &&
2099 LeftOfParens->MatchingParen) {
2100 auto *Prev = LeftOfParens->MatchingParen->getPreviousNonComment();
2101 if (Prev &&
2102 Prev->isOneOf(tok::kw_const_cast, tok::kw_dynamic_cast,
2103 tok::kw_reinterpret_cast, tok::kw_static_cast)) {
2104 // FIXME: Maybe we should handle identifiers ending with "_cast",
2105 // e.g. any_cast?
2106 return true;
2109 return false;
2112 /// Determine whether ')' is ending a cast.
2113 bool rParenEndsCast(const FormatToken &Tok) {
2114 // C-style casts are only used in C++, C# and Java.
2115 if (!Style.isCSharp() && !Style.isCpp() &&
2116 Style.Language != FormatStyle::LK_Java) {
2117 return false;
2120 // Empty parens aren't casts and there are no casts at the end of the line.
2121 if (Tok.Previous == Tok.MatchingParen || !Tok.Next || !Tok.MatchingParen)
2122 return false;
2124 if (Tok.MatchingParen->is(TT_OverloadedOperatorLParen))
2125 return false;
2127 FormatToken *LeftOfParens = Tok.MatchingParen->getPreviousNonComment();
2128 if (LeftOfParens) {
2129 // If there is a closing parenthesis left of the current
2130 // parentheses, look past it as these might be chained casts.
2131 if (LeftOfParens->is(tok::r_paren) &&
2132 LeftOfParens->isNot(TT_CastRParen)) {
2133 if (!LeftOfParens->MatchingParen ||
2134 !LeftOfParens->MatchingParen->Previous) {
2135 return false;
2137 LeftOfParens = LeftOfParens->MatchingParen->Previous;
2140 if (LeftOfParens->is(tok::r_square)) {
2141 // delete[] (void *)ptr;
2142 auto MayBeArrayDelete = [](FormatToken *Tok) -> FormatToken * {
2143 if (Tok->isNot(tok::r_square))
2144 return nullptr;
2146 Tok = Tok->getPreviousNonComment();
2147 if (!Tok || Tok->isNot(tok::l_square))
2148 return nullptr;
2150 Tok = Tok->getPreviousNonComment();
2151 if (!Tok || Tok->isNot(tok::kw_delete))
2152 return nullptr;
2153 return Tok;
2155 if (FormatToken *MaybeDelete = MayBeArrayDelete(LeftOfParens))
2156 LeftOfParens = MaybeDelete;
2159 // The Condition directly below this one will see the operator arguments
2160 // as a (void *foo) cast.
2161 // void operator delete(void *foo) ATTRIB;
2162 if (LeftOfParens->Tok.getIdentifierInfo() && LeftOfParens->Previous &&
2163 LeftOfParens->Previous->is(tok::kw_operator)) {
2164 return false;
2167 // If there is an identifier (or with a few exceptions a keyword) right
2168 // before the parentheses, this is unlikely to be a cast.
2169 if (LeftOfParens->Tok.getIdentifierInfo() &&
2170 !LeftOfParens->isOneOf(Keywords.kw_in, tok::kw_return, tok::kw_case,
2171 tok::kw_delete, tok::kw_throw)) {
2172 return false;
2175 // Certain other tokens right before the parentheses are also signals that
2176 // this cannot be a cast.
2177 if (LeftOfParens->isOneOf(tok::at, tok::r_square, TT_OverloadedOperator,
2178 TT_TemplateCloser, tok::ellipsis)) {
2179 return false;
2183 if (Tok.Next->is(tok::question))
2184 return false;
2186 // `foreach((A a, B b) in someList)` should not be seen as a cast.
2187 if (Tok.Next->is(Keywords.kw_in) && Style.isCSharp())
2188 return false;
2190 // Functions which end with decorations like volatile, noexcept are unlikely
2191 // to be casts.
2192 if (Tok.Next->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const,
2193 tok::kw_requires, tok::kw_throw, tok::arrow,
2194 Keywords.kw_override, Keywords.kw_final) ||
2195 isCpp11AttributeSpecifier(*Tok.Next)) {
2196 return false;
2199 // As Java has no function types, a "(" after the ")" likely means that this
2200 // is a cast.
2201 if (Style.Language == FormatStyle::LK_Java && Tok.Next->is(tok::l_paren))
2202 return true;
2204 // If a (non-string) literal follows, this is likely a cast.
2205 if (Tok.Next->isNot(tok::string_literal) &&
2206 (Tok.Next->Tok.isLiteral() ||
2207 Tok.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof))) {
2208 return true;
2211 // Heuristically try to determine whether the parentheses contain a type.
2212 auto IsQualifiedPointerOrReference = [](FormatToken *T) {
2213 // This is used to handle cases such as x = (foo *const)&y;
2214 assert(!T->isSimpleTypeSpecifier() && "Should have already been checked");
2215 // Strip trailing qualifiers such as const or volatile when checking
2216 // whether the parens could be a cast to a pointer/reference type.
2217 while (T) {
2218 if (T->is(TT_AttributeParen)) {
2219 // Handle `x = (foo *__attribute__((foo)))&v;`:
2220 if (T->MatchingParen && T->MatchingParen->Previous &&
2221 T->MatchingParen->Previous->is(tok::kw___attribute)) {
2222 T = T->MatchingParen->Previous->Previous;
2223 continue;
2225 } else if (T->is(TT_AttributeSquare)) {
2226 // Handle `x = (foo *[[clang::foo]])&v;`:
2227 if (T->MatchingParen && T->MatchingParen->Previous) {
2228 T = T->MatchingParen->Previous;
2229 continue;
2231 } else if (T->canBePointerOrReferenceQualifier()) {
2232 T = T->Previous;
2233 continue;
2235 break;
2237 return T && T->is(TT_PointerOrReference);
2239 bool ParensAreType =
2240 !Tok.Previous ||
2241 Tok.Previous->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) ||
2242 Tok.Previous->isSimpleTypeSpecifier() ||
2243 IsQualifiedPointerOrReference(Tok.Previous);
2244 bool ParensCouldEndDecl =
2245 Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater);
2246 if (ParensAreType && !ParensCouldEndDecl)
2247 return true;
2249 // At this point, we heuristically assume that there are no casts at the
2250 // start of the line. We assume that we have found most cases where there
2251 // are by the logic above, e.g. "(void)x;".
2252 if (!LeftOfParens)
2253 return false;
2255 // Certain token types inside the parentheses mean that this can't be a
2256 // cast.
2257 for (const FormatToken *Token = Tok.MatchingParen->Next; Token != &Tok;
2258 Token = Token->Next) {
2259 if (Token->is(TT_BinaryOperator))
2260 return false;
2263 // If the following token is an identifier or 'this', this is a cast. All
2264 // cases where this can be something else are handled above.
2265 if (Tok.Next->isOneOf(tok::identifier, tok::kw_this))
2266 return true;
2268 // Look for a cast `( x ) (`.
2269 if (Tok.Next->is(tok::l_paren) && Tok.Previous && Tok.Previous->Previous) {
2270 if (Tok.Previous->is(tok::identifier) &&
2271 Tok.Previous->Previous->is(tok::l_paren)) {
2272 return true;
2276 if (!Tok.Next->Next)
2277 return false;
2279 // If the next token after the parenthesis is a unary operator, assume
2280 // that this is cast, unless there are unexpected tokens inside the
2281 // parenthesis.
2282 bool NextIsUnary =
2283 Tok.Next->isUnaryOperator() || Tok.Next->isOneOf(tok::amp, tok::star);
2284 if (!NextIsUnary || Tok.Next->is(tok::plus) ||
2285 !Tok.Next->Next->isOneOf(tok::identifier, tok::numeric_constant)) {
2286 return false;
2288 // Search for unexpected tokens.
2289 for (FormatToken *Prev = Tok.Previous; Prev != Tok.MatchingParen;
2290 Prev = Prev->Previous) {
2291 if (!Prev->isOneOf(tok::kw_const, tok::identifier, tok::coloncolon))
2292 return false;
2294 return true;
2297 /// Returns true if the token is used as a unary operator.
2298 bool determineUnaryOperatorByUsage(const FormatToken &Tok) {
2299 const FormatToken *PrevToken = Tok.getPreviousNonComment();
2300 if (!PrevToken)
2301 return true;
2303 // These keywords are deliberately not included here because they may
2304 // precede only one of unary star/amp and plus/minus but not both. They are
2305 // either included in determineStarAmpUsage or determinePlusMinusCaretUsage.
2307 // @ - It may be followed by a unary `-` in Objective-C literals. We don't
2308 // know how they can be followed by a star or amp.
2309 if (PrevToken->isOneOf(
2310 TT_ConditionalExpr, tok::l_paren, tok::comma, tok::colon, tok::semi,
2311 tok::equal, tok::question, tok::l_square, tok::l_brace,
2312 tok::kw_case, tok::kw_co_await, tok::kw_co_return, tok::kw_co_yield,
2313 tok::kw_delete, tok::kw_return, tok::kw_throw)) {
2314 return true;
2317 // We put sizeof here instead of only in determineStarAmpUsage. In the cases
2318 // where the unary `+` operator is overloaded, it is reasonable to write
2319 // things like `sizeof +x`. Like commit 446d6ec996c6c3.
2320 if (PrevToken->is(tok::kw_sizeof))
2321 return true;
2323 // A sequence of leading unary operators.
2324 if (PrevToken->isOneOf(TT_CastRParen, TT_UnaryOperator))
2325 return true;
2327 // There can't be two consecutive binary operators.
2328 if (PrevToken->is(TT_BinaryOperator))
2329 return true;
2331 return false;
2334 /// Return the type of the given token assuming it is * or &.
2335 TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression,
2336 bool InTemplateArgument) {
2337 if (Style.isJavaScript())
2338 return TT_BinaryOperator;
2340 // && in C# must be a binary operator.
2341 if (Style.isCSharp() && Tok.is(tok::ampamp))
2342 return TT_BinaryOperator;
2344 const FormatToken *PrevToken = Tok.getPreviousNonComment();
2345 if (!PrevToken)
2346 return TT_UnaryOperator;
2348 const FormatToken *NextToken = Tok.getNextNonComment();
2350 if (InTemplateArgument && NextToken && NextToken->is(tok::kw_noexcept))
2351 return TT_BinaryOperator;
2353 if (!NextToken ||
2354 NextToken->isOneOf(tok::arrow, tok::equal, tok::kw_noexcept) ||
2355 NextToken->canBePointerOrReferenceQualifier() ||
2356 (NextToken->is(tok::l_brace) && !NextToken->getNextNonComment())) {
2357 return TT_PointerOrReference;
2360 if (PrevToken->is(tok::coloncolon))
2361 return TT_PointerOrReference;
2363 if (PrevToken->is(tok::r_paren) && PrevToken->is(TT_TypeDeclarationParen))
2364 return TT_PointerOrReference;
2366 if (determineUnaryOperatorByUsage(Tok))
2367 return TT_UnaryOperator;
2369 if (NextToken->is(tok::l_square) && NextToken->isNot(TT_LambdaLSquare))
2370 return TT_PointerOrReference;
2371 if (NextToken->is(tok::kw_operator) && !IsExpression)
2372 return TT_PointerOrReference;
2373 if (NextToken->isOneOf(tok::comma, tok::semi))
2374 return TT_PointerOrReference;
2376 // After right braces, star tokens are likely to be pointers to struct,
2377 // union, or class.
2378 // struct {} *ptr;
2379 // This by itself is not sufficient to distinguish from multiplication
2380 // following a brace-initialized expression, as in:
2381 // int i = int{42} * 2;
2382 // In the struct case, the part of the struct declaration until the `{` and
2383 // the `}` are put on separate unwrapped lines; in the brace-initialized
2384 // case, the matching `{` is on the same unwrapped line, so check for the
2385 // presence of the matching brace to distinguish between those.
2386 if (PrevToken->is(tok::r_brace) && Tok.is(tok::star) &&
2387 !PrevToken->MatchingParen) {
2388 return TT_PointerOrReference;
2391 // if (Class* obj { function() })
2392 if (PrevToken->Tok.isAnyIdentifier() && NextToken->Tok.isAnyIdentifier() &&
2393 NextToken->Next && NextToken->Next->is(tok::l_brace)) {
2394 return TT_PointerOrReference;
2397 if (PrevToken->endsSequence(tok::r_square, tok::l_square, tok::kw_delete))
2398 return TT_UnaryOperator;
2400 if (PrevToken->Tok.isLiteral() ||
2401 PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::kw_true,
2402 tok::kw_false, tok::r_brace)) {
2403 return TT_BinaryOperator;
2406 const FormatToken *NextNonParen = NextToken;
2407 while (NextNonParen && NextNonParen->is(tok::l_paren))
2408 NextNonParen = NextNonParen->getNextNonComment();
2409 if (NextNonParen && (NextNonParen->Tok.isLiteral() ||
2410 NextNonParen->isOneOf(tok::kw_true, tok::kw_false) ||
2411 NextNonParen->isUnaryOperator())) {
2412 return TT_BinaryOperator;
2415 // If we know we're in a template argument, there are no named declarations.
2416 // Thus, having an identifier on the right-hand side indicates a binary
2417 // operator.
2418 if (InTemplateArgument && NextToken->Tok.isAnyIdentifier())
2419 return TT_BinaryOperator;
2421 // "&&(" is quite unlikely to be two successive unary "&".
2422 if (Tok.is(tok::ampamp) && NextToken->is(tok::l_paren))
2423 return TT_BinaryOperator;
2425 // This catches some cases where evaluation order is used as control flow:
2426 // aaa && aaa->f();
2427 if (NextToken->Tok.isAnyIdentifier()) {
2428 const FormatToken *NextNextToken = NextToken->getNextNonComment();
2429 if (NextNextToken && NextNextToken->is(tok::arrow))
2430 return TT_BinaryOperator;
2433 // It is very unlikely that we are going to find a pointer or reference type
2434 // definition on the RHS of an assignment.
2435 if (IsExpression && !Contexts.back().CaretFound)
2436 return TT_BinaryOperator;
2438 return TT_PointerOrReference;
2441 TokenType determinePlusMinusCaretUsage(const FormatToken &Tok) {
2442 if (determineUnaryOperatorByUsage(Tok))
2443 return TT_UnaryOperator;
2445 const FormatToken *PrevToken = Tok.getPreviousNonComment();
2446 if (!PrevToken)
2447 return TT_UnaryOperator;
2449 if (PrevToken->is(tok::at))
2450 return TT_UnaryOperator;
2452 // Fall back to marking the token as binary operator.
2453 return TT_BinaryOperator;
2456 /// Determine whether ++/-- are pre- or post-increments/-decrements.
2457 TokenType determineIncrementUsage(const FormatToken &Tok) {
2458 const FormatToken *PrevToken = Tok.getPreviousNonComment();
2459 if (!PrevToken || PrevToken->is(TT_CastRParen))
2460 return TT_UnaryOperator;
2461 if (PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::identifier))
2462 return TT_TrailingUnaryOperator;
2464 return TT_UnaryOperator;
2467 SmallVector<Context, 8> Contexts;
2469 const FormatStyle &Style;
2470 AnnotatedLine &Line;
2471 FormatToken *CurrentToken;
2472 bool AutoFound;
2473 const AdditionalKeywords &Keywords;
2475 // Set of "<" tokens that do not open a template parameter list. If parseAngle
2476 // determines that a specific token can't be a template opener, it will make
2477 // same decision irrespective of the decisions for tokens leading up to it.
2478 // Store this information to prevent this from causing exponential runtime.
2479 llvm::SmallPtrSet<FormatToken *, 16> NonTemplateLess;
2482 static const int PrecedenceUnaryOperator = prec::PointerToMember + 1;
2483 static const int PrecedenceArrowAndPeriod = prec::PointerToMember + 2;
2485 /// Parses binary expressions by inserting fake parenthesis based on
2486 /// operator precedence.
2487 class ExpressionParser {
2488 public:
2489 ExpressionParser(const FormatStyle &Style, const AdditionalKeywords &Keywords,
2490 AnnotatedLine &Line)
2491 : Style(Style), Keywords(Keywords), Line(Line), Current(Line.First) {}
2493 /// Parse expressions with the given operator precedence.
2494 void parse(int Precedence = 0) {
2495 // Skip 'return' and ObjC selector colons as they are not part of a binary
2496 // expression.
2497 while (Current && (Current->is(tok::kw_return) ||
2498 (Current->is(tok::colon) &&
2499 Current->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral)))) {
2500 next();
2503 if (!Current || Precedence > PrecedenceArrowAndPeriod)
2504 return;
2506 // Conditional expressions need to be parsed separately for proper nesting.
2507 if (Precedence == prec::Conditional) {
2508 parseConditionalExpr();
2509 return;
2512 // Parse unary operators, which all have a higher precedence than binary
2513 // operators.
2514 if (Precedence == PrecedenceUnaryOperator) {
2515 parseUnaryOperator();
2516 return;
2519 FormatToken *Start = Current;
2520 FormatToken *LatestOperator = nullptr;
2521 unsigned OperatorIndex = 0;
2523 while (Current) {
2524 // Consume operators with higher precedence.
2525 parse(Precedence + 1);
2527 int CurrentPrecedence = getCurrentPrecedence();
2529 if (Precedence == CurrentPrecedence && Current &&
2530 Current->is(TT_SelectorName)) {
2531 if (LatestOperator)
2532 addFakeParenthesis(Start, prec::Level(Precedence));
2533 Start = Current;
2536 // At the end of the line or when an operator with higher precedence is
2537 // found, insert fake parenthesis and return.
2538 if (!Current ||
2539 (Current->closesScope() &&
2540 (Current->MatchingParen || Current->is(TT_TemplateString))) ||
2541 (CurrentPrecedence != -1 && CurrentPrecedence < Precedence) ||
2542 (CurrentPrecedence == prec::Conditional &&
2543 Precedence == prec::Assignment && Current->is(tok::colon))) {
2544 break;
2547 // Consume scopes: (), [], <> and {}
2548 // In addition to that we handle require clauses as scope, so that the
2549 // constraints in that are correctly indented.
2550 if (Current->opensScope() ||
2551 Current->isOneOf(TT_RequiresClause,
2552 TT_RequiresClauseInARequiresExpression)) {
2553 // In fragment of a JavaScript template string can look like '}..${' and
2554 // thus close a scope and open a new one at the same time.
2555 while (Current && (!Current->closesScope() || Current->opensScope())) {
2556 next();
2557 parse();
2559 next();
2560 } else {
2561 // Operator found.
2562 if (CurrentPrecedence == Precedence) {
2563 if (LatestOperator)
2564 LatestOperator->NextOperator = Current;
2565 LatestOperator = Current;
2566 Current->OperatorIndex = OperatorIndex;
2567 ++OperatorIndex;
2569 next(/*SkipPastLeadingComments=*/Precedence > 0);
2573 if (LatestOperator && (Current || Precedence > 0)) {
2574 // The requires clauses do not neccessarily end in a semicolon or a brace,
2575 // but just go over to struct/class or a function declaration, we need to
2576 // intervene so that the fake right paren is inserted correctly.
2577 auto End =
2578 (Start->Previous &&
2579 Start->Previous->isOneOf(TT_RequiresClause,
2580 TT_RequiresClauseInARequiresExpression))
2581 ? [this](){
2582 auto Ret = Current ? Current : Line.Last;
2583 while (!Ret->ClosesRequiresClause && Ret->Previous)
2584 Ret = Ret->Previous;
2585 return Ret;
2587 : nullptr;
2589 if (Precedence == PrecedenceArrowAndPeriod) {
2590 // Call expressions don't have a binary operator precedence.
2591 addFakeParenthesis(Start, prec::Unknown, End);
2592 } else {
2593 addFakeParenthesis(Start, prec::Level(Precedence), End);
2598 private:
2599 /// Gets the precedence (+1) of the given token for binary operators
2600 /// and other tokens that we treat like binary operators.
2601 int getCurrentPrecedence() {
2602 if (Current) {
2603 const FormatToken *NextNonComment = Current->getNextNonComment();
2604 if (Current->is(TT_ConditionalExpr))
2605 return prec::Conditional;
2606 if (NextNonComment && Current->is(TT_SelectorName) &&
2607 (NextNonComment->isOneOf(TT_DictLiteral, TT_JsTypeColon) ||
2608 ((Style.Language == FormatStyle::LK_Proto ||
2609 Style.Language == FormatStyle::LK_TextProto) &&
2610 NextNonComment->is(tok::less)))) {
2611 return prec::Assignment;
2613 if (Current->is(TT_JsComputedPropertyName))
2614 return prec::Assignment;
2615 if (Current->is(TT_LambdaArrow))
2616 return prec::Comma;
2617 if (Current->is(TT_FatArrow))
2618 return prec::Assignment;
2619 if (Current->isOneOf(tok::semi, TT_InlineASMColon, TT_SelectorName) ||
2620 (Current->is(tok::comment) && NextNonComment &&
2621 NextNonComment->is(TT_SelectorName))) {
2622 return 0;
2624 if (Current->is(TT_RangeBasedForLoopColon))
2625 return prec::Comma;
2626 if ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&
2627 Current->is(Keywords.kw_instanceof)) {
2628 return prec::Relational;
2630 if (Style.isJavaScript() &&
2631 Current->isOneOf(Keywords.kw_in, Keywords.kw_as)) {
2632 return prec::Relational;
2634 if (Current->is(TT_BinaryOperator) || Current->is(tok::comma))
2635 return Current->getPrecedence();
2636 if (Current->isOneOf(tok::period, tok::arrow) &&
2637 Current->isNot(TT_TrailingReturnArrow)) {
2638 return PrecedenceArrowAndPeriod;
2640 if ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&
2641 Current->isOneOf(Keywords.kw_extends, Keywords.kw_implements,
2642 Keywords.kw_throws)) {
2643 return 0;
2645 // In Verilog case labels are not on separate lines straight out of
2646 // UnwrappedLineParser. The colon is not part of an expression.
2647 if (Style.isVerilog() && Current->is(tok::colon))
2648 return 0;
2650 return -1;
2653 void addFakeParenthesis(FormatToken *Start, prec::Level Precedence,
2654 FormatToken *End = nullptr) {
2655 Start->FakeLParens.push_back(Precedence);
2656 if (Precedence > prec::Unknown)
2657 Start->StartsBinaryExpression = true;
2658 if (!End && Current)
2659 End = Current->getPreviousNonComment();
2660 if (End) {
2661 ++End->FakeRParens;
2662 if (Precedence > prec::Unknown)
2663 End->EndsBinaryExpression = true;
2667 /// Parse unary operator expressions and surround them with fake
2668 /// parentheses if appropriate.
2669 void parseUnaryOperator() {
2670 llvm::SmallVector<FormatToken *, 2> Tokens;
2671 while (Current && Current->is(TT_UnaryOperator)) {
2672 Tokens.push_back(Current);
2673 next();
2675 parse(PrecedenceArrowAndPeriod);
2676 for (FormatToken *Token : llvm::reverse(Tokens)) {
2677 // The actual precedence doesn't matter.
2678 addFakeParenthesis(Token, prec::Unknown);
2682 void parseConditionalExpr() {
2683 while (Current && Current->isTrailingComment())
2684 next();
2685 FormatToken *Start = Current;
2686 parse(prec::LogicalOr);
2687 if (!Current || !Current->is(tok::question))
2688 return;
2689 next();
2690 parse(prec::Assignment);
2691 if (!Current || Current->isNot(TT_ConditionalExpr))
2692 return;
2693 next();
2694 parse(prec::Assignment);
2695 addFakeParenthesis(Start, prec::Conditional);
2698 void next(bool SkipPastLeadingComments = true) {
2699 if (Current)
2700 Current = Current->Next;
2701 while (Current &&
2702 (Current->NewlinesBefore == 0 || SkipPastLeadingComments) &&
2703 Current->isTrailingComment()) {
2704 Current = Current->Next;
2708 const FormatStyle &Style;
2709 const AdditionalKeywords &Keywords;
2710 const AnnotatedLine &Line;
2711 FormatToken *Current;
2714 } // end anonymous namespace
2716 void TokenAnnotator::setCommentLineLevels(
2717 SmallVectorImpl<AnnotatedLine *> &Lines) const {
2718 const AnnotatedLine *NextNonCommentLine = nullptr;
2719 for (AnnotatedLine *Line : llvm::reverse(Lines)) {
2720 assert(Line->First);
2722 // If the comment is currently aligned with the line immediately following
2723 // it, that's probably intentional and we should keep it.
2724 if (NextNonCommentLine && Line->isComment() &&
2725 NextNonCommentLine->First->NewlinesBefore <= 1 &&
2726 NextNonCommentLine->First->OriginalColumn ==
2727 Line->First->OriginalColumn) {
2728 const bool PPDirectiveOrImportStmt =
2729 NextNonCommentLine->Type == LT_PreprocessorDirective ||
2730 NextNonCommentLine->Type == LT_ImportStatement;
2731 if (PPDirectiveOrImportStmt)
2732 Line->Type = LT_CommentAbovePPDirective;
2733 // Align comments for preprocessor lines with the # in column 0 if
2734 // preprocessor lines are not indented. Otherwise, align with the next
2735 // line.
2736 Line->Level = Style.IndentPPDirectives != FormatStyle::PPDIS_BeforeHash &&
2737 PPDirectiveOrImportStmt
2739 : NextNonCommentLine->Level;
2740 } else {
2741 NextNonCommentLine = Line->First->isNot(tok::r_brace) ? Line : nullptr;
2744 setCommentLineLevels(Line->Children);
2748 static unsigned maxNestingDepth(const AnnotatedLine &Line) {
2749 unsigned Result = 0;
2750 for (const auto *Tok = Line.First; Tok != nullptr; Tok = Tok->Next)
2751 Result = std::max(Result, Tok->NestingLevel);
2752 return Result;
2755 void TokenAnnotator::annotate(AnnotatedLine &Line) const {
2756 for (auto &Child : Line.Children)
2757 annotate(*Child);
2759 AnnotatingParser Parser(Style, Line, Keywords);
2760 Line.Type = Parser.parseLine();
2762 // With very deep nesting, ExpressionParser uses lots of stack and the
2763 // formatting algorithm is very slow. We're not going to do a good job here
2764 // anyway - it's probably generated code being formatted by mistake.
2765 // Just skip the whole line.
2766 if (maxNestingDepth(Line) > 50)
2767 Line.Type = LT_Invalid;
2769 if (Line.Type == LT_Invalid)
2770 return;
2772 ExpressionParser ExprParser(Style, Keywords, Line);
2773 ExprParser.parse();
2775 if (Line.startsWith(TT_ObjCMethodSpecifier))
2776 Line.Type = LT_ObjCMethodDecl;
2777 else if (Line.startsWith(TT_ObjCDecl))
2778 Line.Type = LT_ObjCDecl;
2779 else if (Line.startsWith(TT_ObjCProperty))
2780 Line.Type = LT_ObjCProperty;
2782 Line.First->SpacesRequiredBefore = 1;
2783 Line.First->CanBreakBefore = Line.First->MustBreakBefore;
2786 // This function heuristically determines whether 'Current' starts the name of a
2787 // function declaration.
2788 static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
2789 const AnnotatedLine &Line) {
2790 auto skipOperatorName = [](const FormatToken *Next) -> const FormatToken * {
2791 for (; Next; Next = Next->Next) {
2792 if (Next->is(TT_OverloadedOperatorLParen))
2793 return Next;
2794 if (Next->is(TT_OverloadedOperator))
2795 continue;
2796 if (Next->isOneOf(tok::kw_new, tok::kw_delete)) {
2797 // For 'new[]' and 'delete[]'.
2798 if (Next->Next &&
2799 Next->Next->startsSequence(tok::l_square, tok::r_square)) {
2800 Next = Next->Next->Next;
2802 continue;
2804 if (Next->startsSequence(tok::l_square, tok::r_square)) {
2805 // For operator[]().
2806 Next = Next->Next;
2807 continue;
2809 if ((Next->isSimpleTypeSpecifier() || Next->is(tok::identifier)) &&
2810 Next->Next && Next->Next->isOneOf(tok::star, tok::amp, tok::ampamp)) {
2811 // For operator void*(), operator char*(), operator Foo*().
2812 Next = Next->Next;
2813 continue;
2815 if (Next->is(TT_TemplateOpener) && Next->MatchingParen) {
2816 Next = Next->MatchingParen;
2817 continue;
2820 break;
2822 return nullptr;
2825 // Find parentheses of parameter list.
2826 const FormatToken *Next = Current.Next;
2827 if (Current.is(tok::kw_operator)) {
2828 if (Current.Previous && Current.Previous->is(tok::coloncolon))
2829 return false;
2830 Next = skipOperatorName(Next);
2831 } else {
2832 if (!Current.is(TT_StartOfName) || Current.NestingLevel != 0)
2833 return false;
2834 for (; Next; Next = Next->Next) {
2835 if (Next->is(TT_TemplateOpener)) {
2836 Next = Next->MatchingParen;
2837 } else if (Next->is(tok::coloncolon)) {
2838 Next = Next->Next;
2839 if (!Next)
2840 return false;
2841 if (Next->is(tok::kw_operator)) {
2842 Next = skipOperatorName(Next->Next);
2843 break;
2845 if (!Next->is(tok::identifier))
2846 return false;
2847 } else if (Next->is(tok::l_paren)) {
2848 break;
2849 } else {
2850 return false;
2855 // Check whether parameter list can belong to a function declaration.
2856 if (!Next || !Next->is(tok::l_paren) || !Next->MatchingParen)
2857 return false;
2858 // If the lines ends with "{", this is likely a function definition.
2859 if (Line.Last->is(tok::l_brace))
2860 return true;
2861 if (Next->Next == Next->MatchingParen)
2862 return true; // Empty parentheses.
2863 // If there is an &/&& after the r_paren, this is likely a function.
2864 if (Next->MatchingParen->Next &&
2865 Next->MatchingParen->Next->is(TT_PointerOrReference)) {
2866 return true;
2869 // Check for K&R C function definitions (and C++ function definitions with
2870 // unnamed parameters), e.g.:
2871 // int f(i)
2872 // {
2873 // return i + 1;
2874 // }
2875 // bool g(size_t = 0, bool b = false)
2876 // {
2877 // return !b;
2878 // }
2879 if (IsCpp && Next->Next && Next->Next->is(tok::identifier) &&
2880 !Line.endsWith(tok::semi)) {
2881 return true;
2884 for (const FormatToken *Tok = Next->Next; Tok && Tok != Next->MatchingParen;
2885 Tok = Tok->Next) {
2886 if (Tok->is(TT_TypeDeclarationParen))
2887 return true;
2888 if (Tok->isOneOf(tok::l_paren, TT_TemplateOpener) && Tok->MatchingParen) {
2889 Tok = Tok->MatchingParen;
2890 continue;
2892 if (Tok->is(tok::kw_const) || Tok->isSimpleTypeSpecifier() ||
2893 Tok->isOneOf(TT_PointerOrReference, TT_StartOfName, tok::ellipsis)) {
2894 return true;
2896 if (Tok->isOneOf(tok::l_brace, tok::string_literal, TT_ObjCMethodExpr) ||
2897 Tok->Tok.isLiteral()) {
2898 return false;
2901 return false;
2904 bool TokenAnnotator::mustBreakForReturnType(const AnnotatedLine &Line) const {
2905 assert(Line.MightBeFunctionDecl);
2907 if ((Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_TopLevel ||
2908 Style.AlwaysBreakAfterReturnType ==
2909 FormatStyle::RTBS_TopLevelDefinitions) &&
2910 Line.Level > 0) {
2911 return false;
2914 switch (Style.AlwaysBreakAfterReturnType) {
2915 case FormatStyle::RTBS_None:
2916 return false;
2917 case FormatStyle::RTBS_All:
2918 case FormatStyle::RTBS_TopLevel:
2919 return true;
2920 case FormatStyle::RTBS_AllDefinitions:
2921 case FormatStyle::RTBS_TopLevelDefinitions:
2922 return Line.mightBeFunctionDefinition();
2925 return false;
2928 void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
2929 for (AnnotatedLine *ChildLine : Line.Children)
2930 calculateFormattingInformation(*ChildLine);
2932 Line.First->TotalLength =
2933 Line.First->IsMultiline ? Style.ColumnLimit
2934 : Line.FirstStartColumn + Line.First->ColumnWidth;
2935 FormatToken *Current = Line.First->Next;
2936 bool InFunctionDecl = Line.MightBeFunctionDecl;
2937 bool AlignArrayOfStructures =
2938 (Style.AlignArrayOfStructures != FormatStyle::AIAS_None &&
2939 Line.Type == LT_ArrayOfStructInitializer);
2940 if (AlignArrayOfStructures)
2941 calculateArrayInitializerColumnList(Line);
2943 while (Current) {
2944 if (isFunctionDeclarationName(Style.isCpp(), *Current, Line))
2945 Current->setType(TT_FunctionDeclarationName);
2946 const FormatToken *Prev = Current->Previous;
2947 if (Current->is(TT_LineComment)) {
2948 if (Prev->is(BK_BracedInit) && Prev->opensScope()) {
2949 Current->SpacesRequiredBefore =
2950 (Style.Cpp11BracedListStyle && !Style.SpacesInParentheses) ? 0 : 1;
2951 } else {
2952 Current->SpacesRequiredBefore = Style.SpacesBeforeTrailingComments;
2955 // If we find a trailing comment, iterate backwards to determine whether
2956 // it seems to relate to a specific parameter. If so, break before that
2957 // parameter to avoid changing the comment's meaning. E.g. don't move 'b'
2958 // to the previous line in:
2959 // SomeFunction(a,
2960 // b, // comment
2961 // c);
2962 if (!Current->HasUnescapedNewline) {
2963 for (FormatToken *Parameter = Current->Previous; Parameter;
2964 Parameter = Parameter->Previous) {
2965 if (Parameter->isOneOf(tok::comment, tok::r_brace))
2966 break;
2967 if (Parameter->Previous && Parameter->Previous->is(tok::comma)) {
2968 if (!Parameter->Previous->is(TT_CtorInitializerComma) &&
2969 Parameter->HasUnescapedNewline) {
2970 Parameter->MustBreakBefore = true;
2972 break;
2976 } else if (Current->SpacesRequiredBefore == 0 &&
2977 spaceRequiredBefore(Line, *Current)) {
2978 Current->SpacesRequiredBefore = 1;
2981 const auto &Children = Prev->Children;
2982 if (!Children.empty() && Children.back()->Last->is(TT_LineComment)) {
2983 Current->MustBreakBefore = true;
2984 } else {
2985 Current->MustBreakBefore =
2986 Current->MustBreakBefore || mustBreakBefore(Line, *Current);
2987 if (!Current->MustBreakBefore && InFunctionDecl &&
2988 Current->is(TT_FunctionDeclarationName)) {
2989 Current->MustBreakBefore = mustBreakForReturnType(Line);
2993 Current->CanBreakBefore =
2994 Current->MustBreakBefore || canBreakBefore(Line, *Current);
2995 unsigned ChildSize = 0;
2996 if (Prev->Children.size() == 1) {
2997 FormatToken &LastOfChild = *Prev->Children[0]->Last;
2998 ChildSize = LastOfChild.isTrailingComment() ? Style.ColumnLimit
2999 : LastOfChild.TotalLength + 1;
3001 if (Current->MustBreakBefore || Prev->Children.size() > 1 ||
3002 (Prev->Children.size() == 1 &&
3003 Prev->Children[0]->First->MustBreakBefore) ||
3004 Current->IsMultiline) {
3005 Current->TotalLength = Prev->TotalLength + Style.ColumnLimit;
3006 } else {
3007 Current->TotalLength = Prev->TotalLength + Current->ColumnWidth +
3008 ChildSize + Current->SpacesRequiredBefore;
3011 if (Current->is(TT_CtorInitializerColon))
3012 InFunctionDecl = false;
3014 // FIXME: Only calculate this if CanBreakBefore is true once static
3015 // initializers etc. are sorted out.
3016 // FIXME: Move magic numbers to a better place.
3018 // Reduce penalty for aligning ObjC method arguments using the colon
3019 // alignment as this is the canonical way (still prefer fitting everything
3020 // into one line if possible). Trying to fit a whole expression into one
3021 // line should not force other line breaks (e.g. when ObjC method
3022 // expression is a part of other expression).
3023 Current->SplitPenalty = splitPenalty(Line, *Current, InFunctionDecl);
3024 if (Style.Language == FormatStyle::LK_ObjC &&
3025 Current->is(TT_SelectorName) && Current->ParameterIndex > 0) {
3026 if (Current->ParameterIndex == 1)
3027 Current->SplitPenalty += 5 * Current->BindingStrength;
3028 } else {
3029 Current->SplitPenalty += 20 * Current->BindingStrength;
3032 Current = Current->Next;
3035 calculateUnbreakableTailLengths(Line);
3036 unsigned IndentLevel = Line.Level;
3037 for (Current = Line.First; Current != nullptr; Current = Current->Next) {
3038 if (Current->Role)
3039 Current->Role->precomputeFormattingInfos(Current);
3040 if (Current->MatchingParen &&
3041 Current->MatchingParen->opensBlockOrBlockTypeList(Style) &&
3042 IndentLevel > 0) {
3043 --IndentLevel;
3045 Current->IndentLevel = IndentLevel;
3046 if (Current->opensBlockOrBlockTypeList(Style))
3047 ++IndentLevel;
3050 LLVM_DEBUG({ printDebugInfo(Line); });
3053 void TokenAnnotator::calculateUnbreakableTailLengths(
3054 AnnotatedLine &Line) const {
3055 unsigned UnbreakableTailLength = 0;
3056 FormatToken *Current = Line.Last;
3057 while (Current) {
3058 Current->UnbreakableTailLength = UnbreakableTailLength;
3059 if (Current->CanBreakBefore ||
3060 Current->isOneOf(tok::comment, tok::string_literal)) {
3061 UnbreakableTailLength = 0;
3062 } else {
3063 UnbreakableTailLength +=
3064 Current->ColumnWidth + Current->SpacesRequiredBefore;
3066 Current = Current->Previous;
3070 void TokenAnnotator::calculateArrayInitializerColumnList(
3071 AnnotatedLine &Line) const {
3072 if (Line.First == Line.Last)
3073 return;
3074 auto *CurrentToken = Line.First;
3075 CurrentToken->ArrayInitializerLineStart = true;
3076 unsigned Depth = 0;
3077 while (CurrentToken != nullptr && CurrentToken != Line.Last) {
3078 if (CurrentToken->is(tok::l_brace)) {
3079 CurrentToken->IsArrayInitializer = true;
3080 if (CurrentToken->Next != nullptr)
3081 CurrentToken->Next->MustBreakBefore = true;
3082 CurrentToken =
3083 calculateInitializerColumnList(Line, CurrentToken->Next, Depth + 1);
3084 } else {
3085 CurrentToken = CurrentToken->Next;
3090 FormatToken *TokenAnnotator::calculateInitializerColumnList(
3091 AnnotatedLine &Line, FormatToken *CurrentToken, unsigned Depth) const {
3092 while (CurrentToken != nullptr && CurrentToken != Line.Last) {
3093 if (CurrentToken->is(tok::l_brace))
3094 ++Depth;
3095 else if (CurrentToken->is(tok::r_brace))
3096 --Depth;
3097 if (Depth == 2 && CurrentToken->isOneOf(tok::l_brace, tok::comma)) {
3098 CurrentToken = CurrentToken->Next;
3099 if (CurrentToken == nullptr)
3100 break;
3101 CurrentToken->StartsColumn = true;
3102 CurrentToken = CurrentToken->Previous;
3104 CurrentToken = CurrentToken->Next;
3106 return CurrentToken;
3109 unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
3110 const FormatToken &Tok,
3111 bool InFunctionDecl) const {
3112 const FormatToken &Left = *Tok.Previous;
3113 const FormatToken &Right = Tok;
3115 if (Left.is(tok::semi))
3116 return 0;
3118 // Language specific handling.
3119 if (Style.Language == FormatStyle::LK_Java) {
3120 if (Right.isOneOf(Keywords.kw_extends, Keywords.kw_throws))
3121 return 1;
3122 if (Right.is(Keywords.kw_implements))
3123 return 2;
3124 if (Left.is(tok::comma) && Left.NestingLevel == 0)
3125 return 3;
3126 } else if (Style.isJavaScript()) {
3127 if (Right.is(Keywords.kw_function) && Left.isNot(tok::comma))
3128 return 100;
3129 if (Left.is(TT_JsTypeColon))
3130 return 35;
3131 if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
3132 (Right.is(TT_TemplateString) && Right.TokenText.startswith("}"))) {
3133 return 100;
3135 // Prefer breaking call chains (".foo") over empty "{}", "[]" or "()".
3136 if (Left.opensScope() && Right.closesScope())
3137 return 200;
3138 } else if (Style.isProto()) {
3139 if (Right.is(tok::l_square))
3140 return 1;
3141 if (Right.is(tok::period))
3142 return 500;
3145 if (Right.is(tok::identifier) && Right.Next && Right.Next->is(TT_DictLiteral))
3146 return 1;
3147 if (Right.is(tok::l_square)) {
3148 if (Left.is(tok::r_square))
3149 return 200;
3150 // Slightly prefer formatting local lambda definitions like functions.
3151 if (Right.is(TT_LambdaLSquare) && Left.is(tok::equal))
3152 return 35;
3153 if (!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,
3154 TT_ArrayInitializerLSquare,
3155 TT_DesignatedInitializerLSquare, TT_AttributeSquare)) {
3156 return 500;
3160 if (Left.is(tok::coloncolon))
3161 return 500;
3162 if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName) ||
3163 Right.is(tok::kw_operator)) {
3164 if (Line.startsWith(tok::kw_for) && Right.PartOfMultiVariableDeclStmt)
3165 return 3;
3166 if (Left.is(TT_StartOfName))
3167 return 110;
3168 if (InFunctionDecl && Right.NestingLevel == 0)
3169 return Style.PenaltyReturnTypeOnItsOwnLine;
3170 return 200;
3172 if (Right.is(TT_PointerOrReference))
3173 return 190;
3174 if (Right.is(TT_LambdaArrow))
3175 return 110;
3176 if (Left.is(tok::equal) && Right.is(tok::l_brace))
3177 return 160;
3178 if (Left.is(TT_CastRParen))
3179 return 100;
3180 if (Left.isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union))
3181 return 5000;
3182 if (Left.is(tok::comment))
3183 return 1000;
3185 if (Left.isOneOf(TT_RangeBasedForLoopColon, TT_InheritanceColon,
3186 TT_CtorInitializerColon)) {
3187 return 2;
3190 if (Right.isMemberAccess()) {
3191 // Breaking before the "./->" of a chained call/member access is reasonably
3192 // cheap, as formatting those with one call per line is generally
3193 // desirable. In particular, it should be cheaper to break before the call
3194 // than it is to break inside a call's parameters, which could lead to weird
3195 // "hanging" indents. The exception is the very last "./->" to support this
3196 // frequent pattern:
3198 // aaaaaaaa.aaaaaaaa.bbbbbbb().ccccccccccccccccccccc(
3199 // dddddddd);
3201 // which might otherwise be blown up onto many lines. Here, clang-format
3202 // won't produce "hanging" indents anyway as there is no other trailing
3203 // call.
3205 // Also apply higher penalty is not a call as that might lead to a wrapping
3206 // like:
3208 // aaaaaaa
3209 // .aaaaaaaaa.bbbbbbbb(cccccccc);
3210 return !Right.NextOperator || !Right.NextOperator->Previous->closesScope()
3211 ? 150
3212 : 35;
3215 if (Right.is(TT_TrailingAnnotation) &&
3216 (!Right.Next || Right.Next->isNot(tok::l_paren))) {
3217 // Moving trailing annotations to the next line is fine for ObjC method
3218 // declarations.
3219 if (Line.startsWith(TT_ObjCMethodSpecifier))
3220 return 10;
3221 // Generally, breaking before a trailing annotation is bad unless it is
3222 // function-like. It seems to be especially preferable to keep standard
3223 // annotations (i.e. "const", "final" and "override") on the same line.
3224 // Use a slightly higher penalty after ")" so that annotations like
3225 // "const override" are kept together.
3226 bool is_short_annotation = Right.TokenText.size() < 10;
3227 return (Left.is(tok::r_paren) ? 100 : 120) + (is_short_annotation ? 50 : 0);
3230 // In for-loops, prefer breaking at ',' and ';'.
3231 if (Line.startsWith(tok::kw_for) && Left.is(tok::equal))
3232 return 4;
3234 // In Objective-C method expressions, prefer breaking before "param:" over
3235 // breaking after it.
3236 if (Right.is(TT_SelectorName))
3237 return 0;
3238 if (Left.is(tok::colon) && Left.is(TT_ObjCMethodExpr))
3239 return Line.MightBeFunctionDecl ? 50 : 500;
3241 // In Objective-C type declarations, avoid breaking after the category's
3242 // open paren (we'll prefer breaking after the protocol list's opening
3243 // angle bracket, if present).
3244 if (Line.Type == LT_ObjCDecl && Left.is(tok::l_paren) && Left.Previous &&
3245 Left.Previous->isOneOf(tok::identifier, tok::greater)) {
3246 return 500;
3249 if (Left.is(tok::l_paren) && Style.PenaltyBreakOpenParenthesis != 0)
3250 return Style.PenaltyBreakOpenParenthesis;
3251 if (Left.is(tok::l_paren) && InFunctionDecl &&
3252 Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign) {
3253 return 100;
3255 if (Left.is(tok::l_paren) && Left.Previous &&
3256 (Left.Previous->is(tok::kw_for) || Left.Previous->isIf())) {
3257 return 1000;
3259 if (Left.is(tok::equal) && InFunctionDecl)
3260 return 110;
3261 if (Right.is(tok::r_brace))
3262 return 1;
3263 if (Left.is(TT_TemplateOpener))
3264 return 100;
3265 if (Left.opensScope()) {
3266 // If we aren't aligning after opening parens/braces we can always break
3267 // here unless the style does not want us to place all arguments on the
3268 // next line.
3269 if (Style.AlignAfterOpenBracket == FormatStyle::BAS_DontAlign &&
3270 (Left.ParameterCount <= 1 || Style.AllowAllArgumentsOnNextLine)) {
3271 return 0;
3273 if (Left.is(tok::l_brace) && !Style.Cpp11BracedListStyle)
3274 return 19;
3275 return Left.ParameterCount > 1 ? Style.PenaltyBreakBeforeFirstCallParameter
3276 : 19;
3278 if (Left.is(TT_JavaAnnotation))
3279 return 50;
3281 if (Left.is(TT_UnaryOperator))
3282 return 60;
3283 if (Left.isOneOf(tok::plus, tok::comma) && Left.Previous &&
3284 Left.Previous->isLabelString() &&
3285 (Left.NextOperator || Left.OperatorIndex != 0)) {
3286 return 50;
3288 if (Right.is(tok::plus) && Left.isLabelString() &&
3289 (Right.NextOperator || Right.OperatorIndex != 0)) {
3290 return 25;
3292 if (Left.is(tok::comma))
3293 return 1;
3294 if (Right.is(tok::lessless) && Left.isLabelString() &&
3295 (Right.NextOperator || Right.OperatorIndex != 1)) {
3296 return 25;
3298 if (Right.is(tok::lessless)) {
3299 // Breaking at a << is really cheap.
3300 if (!Left.is(tok::r_paren) || Right.OperatorIndex > 0) {
3301 // Slightly prefer to break before the first one in log-like statements.
3302 return 2;
3304 return 1;
3306 if (Left.ClosesTemplateDeclaration)
3307 return Style.PenaltyBreakTemplateDeclaration;
3308 if (Left.ClosesRequiresClause)
3309 return 0;
3310 if (Left.is(TT_ConditionalExpr))
3311 return prec::Conditional;
3312 prec::Level Level = Left.getPrecedence();
3313 if (Level == prec::Unknown)
3314 Level = Right.getPrecedence();
3315 if (Level == prec::Assignment)
3316 return Style.PenaltyBreakAssignment;
3317 if (Level != prec::Unknown)
3318 return Level;
3320 return 3;
3323 bool TokenAnnotator::spaceRequiredBeforeParens(const FormatToken &Right) const {
3324 if (Style.SpaceBeforeParens == FormatStyle::SBPO_Always)
3325 return true;
3326 if (Right.is(TT_OverloadedOperatorLParen) &&
3327 Style.SpaceBeforeParensOptions.AfterOverloadedOperator) {
3328 return true;
3330 if (Style.SpaceBeforeParensOptions.BeforeNonEmptyParentheses &&
3331 Right.ParameterCount > 0) {
3332 return true;
3334 return false;
3337 bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
3338 const FormatToken &Left,
3339 const FormatToken &Right) const {
3340 if (Left.is(tok::kw_return) &&
3341 !Right.isOneOf(tok::semi, tok::r_paren, tok::hashhash)) {
3342 return true;
3344 if (Left.is(tok::kw_throw) && Right.is(tok::l_paren) && Right.MatchingParen &&
3345 Right.MatchingParen->is(TT_CastRParen)) {
3346 return true;
3348 if (Style.isJson() && Left.is(tok::string_literal) && Right.is(tok::colon))
3349 return false;
3350 if (Left.is(Keywords.kw_assert) && Style.Language == FormatStyle::LK_Java)
3351 return true;
3352 if (Style.ObjCSpaceAfterProperty && Line.Type == LT_ObjCProperty &&
3353 Left.Tok.getObjCKeywordID() == tok::objc_property) {
3354 return true;
3356 if (Right.is(tok::hashhash))
3357 return Left.is(tok::hash);
3358 if (Left.isOneOf(tok::hashhash, tok::hash))
3359 return Right.is(tok::hash);
3360 if ((Left.is(tok::l_paren) && Right.is(tok::r_paren)) ||
3361 (Left.is(tok::l_brace) && Left.isNot(BK_Block) &&
3362 Right.is(tok::r_brace) && Right.isNot(BK_Block))) {
3363 return Style.SpaceInEmptyParentheses;
3365 if (Style.SpacesInConditionalStatement) {
3366 const FormatToken *LeftParen = nullptr;
3367 if (Left.is(tok::l_paren))
3368 LeftParen = &Left;
3369 else if (Right.is(tok::r_paren) && Right.MatchingParen)
3370 LeftParen = Right.MatchingParen;
3371 if (LeftParen && LeftParen->Previous &&
3372 isKeywordWithCondition(*LeftParen->Previous)) {
3373 return true;
3377 // trailing return type 'auto': []() -> auto {}, auto foo() -> auto {}
3378 if (Left.is(tok::kw_auto) && Right.isOneOf(TT_LambdaLBrace, TT_FunctionLBrace,
3379 // function return type 'auto'
3380 TT_FunctionTypeLParen)) {
3381 return true;
3384 // auto{x} auto(x)
3385 if (Left.is(tok::kw_auto) && Right.isOneOf(tok::l_paren, tok::l_brace))
3386 return false;
3388 // operator co_await(x)
3389 if (Right.is(tok::l_paren) && Left.is(tok::kw_co_await) && Left.Previous &&
3390 Left.Previous->is(tok::kw_operator)) {
3391 return false;
3393 // co_await (x), co_yield (x), co_return (x)
3394 if (Left.isOneOf(tok::kw_co_await, tok::kw_co_yield, tok::kw_co_return) &&
3395 !Right.isOneOf(tok::semi, tok::r_paren)) {
3396 return true;
3399 if (Left.is(tok::l_paren) || Right.is(tok::r_paren)) {
3400 return (Right.is(TT_CastRParen) ||
3401 (Left.MatchingParen && Left.MatchingParen->is(TT_CastRParen)))
3402 ? Style.SpacesInCStyleCastParentheses
3403 : Style.SpacesInParentheses;
3405 if (Right.isOneOf(tok::semi, tok::comma))
3406 return false;
3407 if (Right.is(tok::less) && Line.Type == LT_ObjCDecl) {
3408 bool IsLightweightGeneric = Right.MatchingParen &&
3409 Right.MatchingParen->Next &&
3410 Right.MatchingParen->Next->is(tok::colon);
3411 return !IsLightweightGeneric && Style.ObjCSpaceBeforeProtocolList;
3413 if (Right.is(tok::less) && Left.is(tok::kw_template))
3414 return Style.SpaceAfterTemplateKeyword;
3415 if (Left.isOneOf(tok::exclaim, tok::tilde))
3416 return false;
3417 if (Left.is(tok::at) &&
3418 Right.isOneOf(tok::identifier, tok::string_literal, tok::char_constant,
3419 tok::numeric_constant, tok::l_paren, tok::l_brace,
3420 tok::kw_true, tok::kw_false)) {
3421 return false;
3423 if (Left.is(tok::colon))
3424 return !Left.is(TT_ObjCMethodExpr);
3425 if (Left.is(tok::coloncolon))
3426 return false;
3427 if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less)) {
3428 if (Style.Language == FormatStyle::LK_TextProto ||
3429 (Style.Language == FormatStyle::LK_Proto &&
3430 (Left.is(TT_DictLiteral) || Right.is(TT_DictLiteral)))) {
3431 // Format empty list as `<>`.
3432 if (Left.is(tok::less) && Right.is(tok::greater))
3433 return false;
3434 return !Style.Cpp11BracedListStyle;
3436 return false;
3438 if (Right.is(tok::ellipsis)) {
3439 return Left.Tok.isLiteral() || (Left.is(tok::identifier) && Left.Previous &&
3440 Left.Previous->is(tok::kw_case));
3442 if (Left.is(tok::l_square) && Right.is(tok::amp))
3443 return Style.SpacesInSquareBrackets;
3444 if (Right.is(TT_PointerOrReference)) {
3445 if (Left.is(tok::r_paren) && Line.MightBeFunctionDecl) {
3446 if (!Left.MatchingParen)
3447 return true;
3448 FormatToken *TokenBeforeMatchingParen =
3449 Left.MatchingParen->getPreviousNonComment();
3450 if (!TokenBeforeMatchingParen || !Left.is(TT_TypeDeclarationParen))
3451 return true;
3453 // Add a space if the previous token is a pointer qualifier or the closing
3454 // parenthesis of __attribute__(()) expression and the style requires spaces
3455 // after pointer qualifiers.
3456 if ((Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_After ||
3457 Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both) &&
3458 (Left.is(TT_AttributeParen) ||
3459 Left.canBePointerOrReferenceQualifier())) {
3460 return true;
3462 if (Left.Tok.isLiteral())
3463 return true;
3464 // for (auto a = 0, b = 0; const auto & c : {1, 2, 3})
3465 if (Left.isTypeOrIdentifier() && Right.Next && Right.Next->Next &&
3466 Right.Next->Next->is(TT_RangeBasedForLoopColon)) {
3467 return getTokenPointerOrReferenceAlignment(Right) !=
3468 FormatStyle::PAS_Left;
3470 return !Left.isOneOf(TT_PointerOrReference, tok::l_paren) &&
3471 (getTokenPointerOrReferenceAlignment(Right) !=
3472 FormatStyle::PAS_Left ||
3473 (Line.IsMultiVariableDeclStmt &&
3474 (Left.NestingLevel == 0 ||
3475 (Left.NestingLevel == 1 && startsWithInitStatement(Line)))));
3477 if (Right.is(TT_FunctionTypeLParen) && Left.isNot(tok::l_paren) &&
3478 (!Left.is(TT_PointerOrReference) ||
3479 (getTokenPointerOrReferenceAlignment(Left) != FormatStyle::PAS_Right &&
3480 !Line.IsMultiVariableDeclStmt))) {
3481 return true;
3483 if (Left.is(TT_PointerOrReference)) {
3484 // Add a space if the next token is a pointer qualifier and the style
3485 // requires spaces before pointer qualifiers.
3486 if ((Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Before ||
3487 Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both) &&
3488 Right.canBePointerOrReferenceQualifier()) {
3489 return true;
3491 // & 1
3492 if (Right.Tok.isLiteral())
3493 return true;
3494 // & /* comment
3495 if (Right.is(TT_BlockComment))
3496 return true;
3497 // foo() -> const Bar * override/final
3498 if (Right.isOneOf(Keywords.kw_override, Keywords.kw_final) &&
3499 !Right.is(TT_StartOfName)) {
3500 return true;
3502 // & {
3503 if (Right.is(tok::l_brace) && Right.is(BK_Block))
3504 return true;
3505 // for (auto a = 0, b = 0; const auto& c : {1, 2, 3})
3506 if (Left.Previous && Left.Previous->isTypeOrIdentifier() && Right.Next &&
3507 Right.Next->is(TT_RangeBasedForLoopColon)) {
3508 return getTokenPointerOrReferenceAlignment(Left) !=
3509 FormatStyle::PAS_Right;
3511 if (Right.isOneOf(TT_PointerOrReference, TT_ArraySubscriptLSquare,
3512 tok::l_paren)) {
3513 return false;
3515 if (getTokenPointerOrReferenceAlignment(Left) == FormatStyle::PAS_Right)
3516 return false;
3517 // FIXME: Setting IsMultiVariableDeclStmt for the whole line is error-prone,
3518 // because it does not take into account nested scopes like lambdas.
3519 // In multi-variable declaration statements, attach */& to the variable
3520 // independently of the style. However, avoid doing it if we are in a nested
3521 // scope, e.g. lambda. We still need to special-case statements with
3522 // initializers.
3523 if (Line.IsMultiVariableDeclStmt &&
3524 (Left.NestingLevel == Line.First->NestingLevel ||
3525 ((Left.NestingLevel == Line.First->NestingLevel + 1) &&
3526 startsWithInitStatement(Line)))) {
3527 return false;
3529 return Left.Previous && !Left.Previous->isOneOf(
3530 tok::l_paren, tok::coloncolon, tok::l_square);
3532 // Ensure right pointer alignment with ellipsis e.g. int *...P
3533 if (Left.is(tok::ellipsis) && Left.Previous &&
3534 Left.Previous->isOneOf(tok::star, tok::amp, tok::ampamp)) {
3535 return Style.PointerAlignment != FormatStyle::PAS_Right;
3538 if (Right.is(tok::star) && Left.is(tok::l_paren))
3539 return false;
3540 if (Left.is(tok::star) && Right.isOneOf(tok::star, tok::amp, tok::ampamp))
3541 return false;
3542 if (Right.isOneOf(tok::star, tok::amp, tok::ampamp)) {
3543 const FormatToken *Previous = &Left;
3544 while (Previous && !Previous->is(tok::kw_operator)) {
3545 if (Previous->is(tok::identifier) || Previous->isSimpleTypeSpecifier()) {
3546 Previous = Previous->getPreviousNonComment();
3547 continue;
3549 if (Previous->is(TT_TemplateCloser) && Previous->MatchingParen) {
3550 Previous = Previous->MatchingParen->getPreviousNonComment();
3551 continue;
3553 if (Previous->is(tok::coloncolon)) {
3554 Previous = Previous->getPreviousNonComment();
3555 continue;
3557 break;
3559 // Space between the type and the * in:
3560 // operator void*()
3561 // operator char*()
3562 // operator void const*()
3563 // operator void volatile*()
3564 // operator /*comment*/ const char*()
3565 // operator volatile /*comment*/ char*()
3566 // operator Foo*()
3567 // operator C<T>*()
3568 // operator std::Foo*()
3569 // operator C<T>::D<U>*()
3570 // dependent on PointerAlignment style.
3571 if (Previous) {
3572 if (Previous->endsSequence(tok::kw_operator))
3573 return Style.PointerAlignment != FormatStyle::PAS_Left;
3574 if (Previous->is(tok::kw_const) || Previous->is(tok::kw_volatile)) {
3575 return (Style.PointerAlignment != FormatStyle::PAS_Left) ||
3576 (Style.SpaceAroundPointerQualifiers ==
3577 FormatStyle::SAPQ_After) ||
3578 (Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both);
3582 const auto SpaceRequiredForArrayInitializerLSquare =
3583 [](const FormatToken &LSquareTok, const FormatStyle &Style) {
3584 return Style.SpacesInContainerLiterals ||
3585 ((Style.Language == FormatStyle::LK_Proto ||
3586 Style.Language == FormatStyle::LK_TextProto) &&
3587 !Style.Cpp11BracedListStyle &&
3588 LSquareTok.endsSequence(tok::l_square, tok::colon,
3589 TT_SelectorName));
3591 if (Left.is(tok::l_square)) {
3592 return (Left.is(TT_ArrayInitializerLSquare) && Right.isNot(tok::r_square) &&
3593 SpaceRequiredForArrayInitializerLSquare(Left, Style)) ||
3594 (Left.isOneOf(TT_ArraySubscriptLSquare, TT_StructuredBindingLSquare,
3595 TT_LambdaLSquare) &&
3596 Style.SpacesInSquareBrackets && Right.isNot(tok::r_square));
3598 if (Right.is(tok::r_square)) {
3599 return Right.MatchingParen &&
3600 ((Right.MatchingParen->is(TT_ArrayInitializerLSquare) &&
3601 SpaceRequiredForArrayInitializerLSquare(*Right.MatchingParen,
3602 Style)) ||
3603 (Style.SpacesInSquareBrackets &&
3604 Right.MatchingParen->isOneOf(TT_ArraySubscriptLSquare,
3605 TT_StructuredBindingLSquare,
3606 TT_LambdaLSquare)) ||
3607 Right.MatchingParen->is(TT_AttributeParen));
3609 if (Right.is(tok::l_square) &&
3610 !Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,
3611 TT_DesignatedInitializerLSquare,
3612 TT_StructuredBindingLSquare, TT_AttributeSquare) &&
3613 !Left.isOneOf(tok::numeric_constant, TT_DictLiteral) &&
3614 !(!Left.is(tok::r_square) && Style.SpaceBeforeSquareBrackets &&
3615 Right.is(TT_ArraySubscriptLSquare))) {
3616 return false;
3618 if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
3619 return !Left.Children.empty(); // No spaces in "{}".
3620 if ((Left.is(tok::l_brace) && Left.isNot(BK_Block)) ||
3621 (Right.is(tok::r_brace) && Right.MatchingParen &&
3622 Right.MatchingParen->isNot(BK_Block))) {
3623 return Style.Cpp11BracedListStyle ? Style.SpacesInParentheses : true;
3625 if (Left.is(TT_BlockComment)) {
3626 // No whitespace in x(/*foo=*/1), except for JavaScript.
3627 return Style.isJavaScript() || !Left.TokenText.endswith("=*/");
3630 // Space between template and attribute.
3631 // e.g. template <typename T> [[nodiscard]] ...
3632 if (Left.is(TT_TemplateCloser) && Right.is(TT_AttributeSquare))
3633 return true;
3634 // Space before parentheses common for all languages
3635 if (Right.is(tok::l_paren)) {
3636 if (Left.is(TT_TemplateCloser) && Right.isNot(TT_FunctionTypeLParen))
3637 return spaceRequiredBeforeParens(Right);
3638 if (Left.isOneOf(TT_RequiresClause,
3639 TT_RequiresClauseInARequiresExpression)) {
3640 return Style.SpaceBeforeParensOptions.AfterRequiresInClause ||
3641 spaceRequiredBeforeParens(Right);
3643 if (Left.is(TT_RequiresExpression)) {
3644 return Style.SpaceBeforeParensOptions.AfterRequiresInExpression ||
3645 spaceRequiredBeforeParens(Right);
3647 if ((Left.is(tok::r_paren) && Left.is(TT_AttributeParen)) ||
3648 (Left.is(tok::r_square) && Left.is(TT_AttributeSquare))) {
3649 return true;
3651 if (Left.is(TT_ForEachMacro)) {
3652 return Style.SpaceBeforeParensOptions.AfterForeachMacros ||
3653 spaceRequiredBeforeParens(Right);
3655 if (Left.is(TT_IfMacro)) {
3656 return Style.SpaceBeforeParensOptions.AfterIfMacros ||
3657 spaceRequiredBeforeParens(Right);
3659 if (Line.Type == LT_ObjCDecl)
3660 return true;
3661 if (Left.is(tok::semi))
3662 return true;
3663 if (Left.isOneOf(tok::pp_elif, tok::kw_for, tok::kw_while, tok::kw_switch,
3664 tok::kw_case, TT_ForEachMacro, TT_ObjCForIn) ||
3665 Left.isIf(Line.Type != LT_PreprocessorDirective) ||
3666 Right.is(TT_ConditionLParen)) {
3667 return Style.SpaceBeforeParensOptions.AfterControlStatements ||
3668 spaceRequiredBeforeParens(Right);
3671 // TODO add Operator overloading specific Options to
3672 // SpaceBeforeParensOptions
3673 if (Right.is(TT_OverloadedOperatorLParen))
3674 return spaceRequiredBeforeParens(Right);
3675 // Function declaration or definition
3676 if (Line.MightBeFunctionDecl && (Left.is(TT_FunctionDeclarationName))) {
3677 if (Line.mightBeFunctionDefinition()) {
3678 return Style.SpaceBeforeParensOptions.AfterFunctionDefinitionName ||
3679 spaceRequiredBeforeParens(Right);
3680 } else {
3681 return Style.SpaceBeforeParensOptions.AfterFunctionDeclarationName ||
3682 spaceRequiredBeforeParens(Right);
3685 // Lambda
3686 if (Line.Type != LT_PreprocessorDirective && Left.is(tok::r_square) &&
3687 Left.MatchingParen && Left.MatchingParen->is(TT_LambdaLSquare)) {
3688 return Style.SpaceBeforeParensOptions.AfterFunctionDefinitionName ||
3689 spaceRequiredBeforeParens(Right);
3691 if (!Left.Previous || Left.Previous->isNot(tok::period)) {
3692 if (Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch)) {
3693 return Style.SpaceBeforeParensOptions.AfterControlStatements ||
3694 spaceRequiredBeforeParens(Right);
3696 if (Left.isOneOf(tok::kw_new, tok::kw_delete)) {
3697 return ((!Line.MightBeFunctionDecl || !Left.Previous) &&
3698 Style.SpaceBeforeParens != FormatStyle::SBPO_Never) ||
3699 spaceRequiredBeforeParens(Right);
3702 if (Left.is(tok::r_square) && Left.MatchingParen &&
3703 Left.MatchingParen->Previous &&
3704 Left.MatchingParen->Previous->is(tok::kw_delete)) {
3705 return (Style.SpaceBeforeParens != FormatStyle::SBPO_Never) ||
3706 spaceRequiredBeforeParens(Right);
3709 // Handle builtins like identifiers.
3710 if (Line.Type != LT_PreprocessorDirective &&
3711 (Left.Tok.getIdentifierInfo() || Left.is(tok::r_paren))) {
3712 return spaceRequiredBeforeParens(Right);
3714 return false;
3716 if (Left.is(tok::at) && Right.Tok.getObjCKeywordID() != tok::objc_not_keyword)
3717 return false;
3718 if (Right.is(TT_UnaryOperator)) {
3719 return !Left.isOneOf(tok::l_paren, tok::l_square, tok::at) &&
3720 (Left.isNot(tok::colon) || Left.isNot(TT_ObjCMethodExpr));
3722 if ((Left.isOneOf(tok::identifier, tok::greater, tok::r_square,
3723 tok::r_paren) ||
3724 Left.isSimpleTypeSpecifier()) &&
3725 Right.is(tok::l_brace) && Right.getNextNonComment() &&
3726 Right.isNot(BK_Block)) {
3727 return false;
3729 if (Left.is(tok::period) || Right.is(tok::period))
3730 return false;
3731 // u#str, U#str, L#str, u8#str
3732 // uR#str, UR#str, LR#str, u8R#str
3733 if (Right.is(tok::hash) && Left.is(tok::identifier) &&
3734 (Left.TokenText == "L" || Left.TokenText == "u" ||
3735 Left.TokenText == "U" || Left.TokenText == "u8" ||
3736 Left.TokenText == "LR" || Left.TokenText == "uR" ||
3737 Left.TokenText == "UR" || Left.TokenText == "u8R")) {
3738 return false;
3740 if (Left.is(TT_TemplateCloser) && Left.MatchingParen &&
3741 Left.MatchingParen->Previous &&
3742 (Left.MatchingParen->Previous->is(tok::period) ||
3743 Left.MatchingParen->Previous->is(tok::coloncolon))) {
3744 // Java call to generic function with explicit type:
3745 // A.<B<C<...>>>DoSomething();
3746 // A::<B<C<...>>>DoSomething(); // With a Java 8 method reference.
3747 return false;
3749 if (Left.is(TT_TemplateCloser) && Right.is(tok::l_square))
3750 return false;
3751 if (Left.is(tok::l_brace) && Left.endsSequence(TT_DictLiteral, tok::at)) {
3752 // Objective-C dictionary literal -> no space after opening brace.
3753 return false;
3755 if (Right.is(tok::r_brace) && Right.MatchingParen &&
3756 Right.MatchingParen->endsSequence(TT_DictLiteral, tok::at)) {
3757 // Objective-C dictionary literal -> no space before closing brace.
3758 return false;
3760 if (Right.getType() == TT_TrailingAnnotation &&
3761 Right.isOneOf(tok::amp, tok::ampamp) &&
3762 Left.isOneOf(tok::kw_const, tok::kw_volatile) &&
3763 (!Right.Next || Right.Next->is(tok::semi))) {
3764 // Match const and volatile ref-qualifiers without any additional
3765 // qualifiers such as
3766 // void Fn() const &;
3767 return getTokenReferenceAlignment(Right) != FormatStyle::PAS_Left;
3770 return true;
3773 bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
3774 const FormatToken &Right) const {
3775 const FormatToken &Left = *Right.Previous;
3777 // If the token is finalized don't touch it (as it could be in a
3778 // clang-format-off section).
3779 if (Left.Finalized)
3780 return Right.hasWhitespaceBefore();
3782 // Never ever merge two words.
3783 if (Keywords.isWordLike(Right) && Keywords.isWordLike(Left))
3784 return true;
3786 // Leave a space between * and /* to avoid C4138 `comment end` found outside
3787 // of comment.
3788 if (Left.is(tok::star) && Right.is(tok::comment))
3789 return true;
3791 if (Style.isCpp()) {
3792 // Space between import <iostream>.
3793 // or import .....;
3794 if (Left.is(Keywords.kw_import) && Right.isOneOf(tok::less, tok::ellipsis))
3795 return true;
3796 // Space between `module :` and `import :`.
3797 if (Left.isOneOf(Keywords.kw_module, Keywords.kw_import) &&
3798 Right.is(TT_ModulePartitionColon)) {
3799 return true;
3801 // No space between import foo:bar but keep a space between import :bar;
3802 if (Left.is(tok::identifier) && Right.is(TT_ModulePartitionColon))
3803 return false;
3804 // No space between :bar;
3805 if (Left.is(TT_ModulePartitionColon) &&
3806 Right.isOneOf(tok::identifier, tok::kw_private)) {
3807 return false;
3809 if (Left.is(tok::ellipsis) && Right.is(tok::identifier) &&
3810 Line.First->is(Keywords.kw_import)) {
3811 return false;
3813 // Space in __attribute__((attr)) ::type.
3814 if (Left.is(TT_AttributeParen) && Right.is(tok::coloncolon))
3815 return true;
3817 if (Left.is(tok::kw_operator))
3818 return Right.is(tok::coloncolon);
3819 if (Right.is(tok::l_brace) && Right.is(BK_BracedInit) &&
3820 !Left.opensScope() && Style.SpaceBeforeCpp11BracedList) {
3821 return true;
3823 if (Left.is(tok::less) && Left.is(TT_OverloadedOperator) &&
3824 Right.is(TT_TemplateOpener)) {
3825 return true;
3827 } else if (Style.Language == FormatStyle::LK_Proto ||
3828 Style.Language == FormatStyle::LK_TextProto) {
3829 if (Right.is(tok::period) &&
3830 Left.isOneOf(Keywords.kw_optional, Keywords.kw_required,
3831 Keywords.kw_repeated, Keywords.kw_extend)) {
3832 return true;
3834 if (Right.is(tok::l_paren) &&
3835 Left.isOneOf(Keywords.kw_returns, Keywords.kw_option)) {
3836 return true;
3838 if (Right.isOneOf(tok::l_brace, tok::less) && Left.is(TT_SelectorName))
3839 return true;
3840 // Slashes occur in text protocol extension syntax: [type/type] { ... }.
3841 if (Left.is(tok::slash) || Right.is(tok::slash))
3842 return false;
3843 if (Left.MatchingParen &&
3844 Left.MatchingParen->is(TT_ProtoExtensionLSquare) &&
3845 Right.isOneOf(tok::l_brace, tok::less)) {
3846 return !Style.Cpp11BracedListStyle;
3848 // A percent is probably part of a formatting specification, such as %lld.
3849 if (Left.is(tok::percent))
3850 return false;
3851 // Preserve the existence of a space before a percent for cases like 0x%04x
3852 // and "%d %d"
3853 if (Left.is(tok::numeric_constant) && Right.is(tok::percent))
3854 return Right.hasWhitespaceBefore();
3855 } else if (Style.isJson()) {
3856 if (Right.is(tok::colon))
3857 return false;
3858 } else if (Style.isCSharp()) {
3859 // Require spaces around '{' and before '}' unless they appear in
3860 // interpolated strings. Interpolated strings are merged into a single token
3861 // so cannot have spaces inserted by this function.
3863 // No space between 'this' and '['
3864 if (Left.is(tok::kw_this) && Right.is(tok::l_square))
3865 return false;
3867 // No space between 'new' and '('
3868 if (Left.is(tok::kw_new) && Right.is(tok::l_paren))
3869 return false;
3871 // Space before { (including space within '{ {').
3872 if (Right.is(tok::l_brace))
3873 return true;
3875 // Spaces inside braces.
3876 if (Left.is(tok::l_brace) && Right.isNot(tok::r_brace))
3877 return true;
3879 if (Left.isNot(tok::l_brace) && Right.is(tok::r_brace))
3880 return true;
3882 // Spaces around '=>'.
3883 if (Left.is(TT_FatArrow) || Right.is(TT_FatArrow))
3884 return true;
3886 // No spaces around attribute target colons
3887 if (Left.is(TT_AttributeColon) || Right.is(TT_AttributeColon))
3888 return false;
3890 // space between type and variable e.g. Dictionary<string,string> foo;
3891 if (Left.is(TT_TemplateCloser) && Right.is(TT_StartOfName))
3892 return true;
3894 // spaces inside square brackets.
3895 if (Left.is(tok::l_square) || Right.is(tok::r_square))
3896 return Style.SpacesInSquareBrackets;
3898 // No space before ? in nullable types.
3899 if (Right.is(TT_CSharpNullable))
3900 return false;
3902 // No space before null forgiving '!'.
3903 if (Right.is(TT_NonNullAssertion))
3904 return false;
3906 // No space between consecutive commas '[,,]'.
3907 if (Left.is(tok::comma) && Right.is(tok::comma))
3908 return false;
3910 // space after var in `var (key, value)`
3911 if (Left.is(Keywords.kw_var) && Right.is(tok::l_paren))
3912 return true;
3914 // space between keywords and paren e.g. "using ("
3915 if (Right.is(tok::l_paren)) {
3916 if (Left.isOneOf(tok::kw_using, Keywords.kw_async, Keywords.kw_when,
3917 Keywords.kw_lock)) {
3918 return Style.SpaceBeforeParensOptions.AfterControlStatements ||
3919 spaceRequiredBeforeParens(Right);
3923 // space between method modifier and opening parenthesis of a tuple return
3924 // type
3925 if (Left.isOneOf(tok::kw_public, tok::kw_private, tok::kw_protected,
3926 tok::kw_virtual, tok::kw_extern, tok::kw_static,
3927 Keywords.kw_internal, Keywords.kw_abstract,
3928 Keywords.kw_sealed, Keywords.kw_override,
3929 Keywords.kw_async, Keywords.kw_unsafe) &&
3930 Right.is(tok::l_paren)) {
3931 return true;
3933 } else if (Style.isJavaScript()) {
3934 if (Left.is(TT_FatArrow))
3935 return true;
3936 // for await ( ...
3937 if (Right.is(tok::l_paren) && Left.is(Keywords.kw_await) && Left.Previous &&
3938 Left.Previous->is(tok::kw_for)) {
3939 return true;
3941 if (Left.is(Keywords.kw_async) && Right.is(tok::l_paren) &&
3942 Right.MatchingParen) {
3943 const FormatToken *Next = Right.MatchingParen->getNextNonComment();
3944 // An async arrow function, for example: `x = async () => foo();`,
3945 // as opposed to calling a function called async: `x = async();`
3946 if (Next && Next->is(TT_FatArrow))
3947 return true;
3949 if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
3950 (Right.is(TT_TemplateString) && Right.TokenText.startswith("}"))) {
3951 return false;
3953 // In tagged template literals ("html`bar baz`"), there is no space between
3954 // the tag identifier and the template string.
3955 if (Keywords.IsJavaScriptIdentifier(Left,
3956 /* AcceptIdentifierName= */ false) &&
3957 Right.is(TT_TemplateString)) {
3958 return false;
3960 if (Right.is(tok::star) &&
3961 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield)) {
3962 return false;
3964 if (Right.isOneOf(tok::l_brace, tok::l_square) &&
3965 Left.isOneOf(Keywords.kw_function, Keywords.kw_yield,
3966 Keywords.kw_extends, Keywords.kw_implements)) {
3967 return true;
3969 if (Right.is(tok::l_paren)) {
3970 // JS methods can use some keywords as names (e.g. `delete()`).
3971 if (Line.MustBeDeclaration && Left.Tok.getIdentifierInfo())
3972 return false;
3973 // Valid JS method names can include keywords, e.g. `foo.delete()` or
3974 // `bar.instanceof()`. Recognize call positions by preceding period.
3975 if (Left.Previous && Left.Previous->is(tok::period) &&
3976 Left.Tok.getIdentifierInfo()) {
3977 return false;
3979 // Additional unary JavaScript operators that need a space after.
3980 if (Left.isOneOf(tok::kw_throw, Keywords.kw_await, Keywords.kw_typeof,
3981 tok::kw_void)) {
3982 return true;
3985 // `foo as const;` casts into a const type.
3986 if (Left.endsSequence(tok::kw_const, Keywords.kw_as))
3987 return false;
3988 if ((Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,
3989 tok::kw_const) ||
3990 // "of" is only a keyword if it appears after another identifier
3991 // (e.g. as "const x of y" in a for loop), or after a destructuring
3992 // operation (const [x, y] of z, const {a, b} of c).
3993 (Left.is(Keywords.kw_of) && Left.Previous &&
3994 (Left.Previous->is(tok::identifier) ||
3995 Left.Previous->isOneOf(tok::r_square, tok::r_brace)))) &&
3996 (!Left.Previous || !Left.Previous->is(tok::period))) {
3997 return true;
3999 if (Left.isOneOf(tok::kw_for, Keywords.kw_as) && Left.Previous &&
4000 Left.Previous->is(tok::period) && Right.is(tok::l_paren)) {
4001 return false;
4003 if (Left.is(Keywords.kw_as) &&
4004 Right.isOneOf(tok::l_square, tok::l_brace, tok::l_paren)) {
4005 return true;
4007 if (Left.is(tok::kw_default) && Left.Previous &&
4008 Left.Previous->is(tok::kw_export)) {
4009 return true;
4011 if (Left.is(Keywords.kw_is) && Right.is(tok::l_brace))
4012 return true;
4013 if (Right.isOneOf(TT_JsTypeColon, TT_JsTypeOptionalQuestion))
4014 return false;
4015 if (Left.is(TT_JsTypeOperator) || Right.is(TT_JsTypeOperator))
4016 return false;
4017 if ((Left.is(tok::l_brace) || Right.is(tok::r_brace)) &&
4018 Line.First->isOneOf(Keywords.kw_import, tok::kw_export)) {
4019 return false;
4021 if (Left.is(tok::ellipsis))
4022 return false;
4023 if (Left.is(TT_TemplateCloser) &&
4024 !Right.isOneOf(tok::equal, tok::l_brace, tok::comma, tok::l_square,
4025 Keywords.kw_implements, Keywords.kw_extends)) {
4026 // Type assertions ('<type>expr') are not followed by whitespace. Other
4027 // locations that should have whitespace following are identified by the
4028 // above set of follower tokens.
4029 return false;
4031 if (Right.is(TT_NonNullAssertion))
4032 return false;
4033 if (Left.is(TT_NonNullAssertion) &&
4034 Right.isOneOf(Keywords.kw_as, Keywords.kw_in)) {
4035 return true; // "x! as string", "x! in y"
4037 } else if (Style.Language == FormatStyle::LK_Java) {
4038 if (Left.is(tok::r_square) && Right.is(tok::l_brace))
4039 return true;
4040 if (Left.is(Keywords.kw_synchronized) && Right.is(tok::l_paren)) {
4041 return Style.SpaceBeforeParensOptions.AfterControlStatements ||
4042 spaceRequiredBeforeParens(Right);
4044 if ((Left.isOneOf(tok::kw_static, tok::kw_public, tok::kw_private,
4045 tok::kw_protected) ||
4046 Left.isOneOf(Keywords.kw_final, Keywords.kw_abstract,
4047 Keywords.kw_native)) &&
4048 Right.is(TT_TemplateOpener)) {
4049 return true;
4051 } else if (Style.isVerilog()) {
4052 // Add space between things in a primitive's state table unless in a
4053 // transition like `(0?)`.
4054 if ((Left.is(TT_VerilogTableItem) &&
4055 !Right.isOneOf(tok::r_paren, tok::semi)) ||
4056 (Right.is(TT_VerilogTableItem) && Left.isNot(tok::l_paren))) {
4057 const FormatToken *Next = Right.getNextNonComment();
4058 return !(Next && Next->is(tok::r_paren));
4060 // Don't add space within a delay like `#0`.
4061 if (Left.isNot(TT_BinaryOperator) &&
4062 Left.isOneOf(Keywords.kw_verilogHash, Keywords.kw_verilogHashHash)) {
4063 return false;
4065 // Add space after a delay.
4066 if (!Right.is(tok::semi) &&
4067 (Left.endsSequence(tok::numeric_constant, Keywords.kw_verilogHash) ||
4068 Left.endsSequence(tok::numeric_constant,
4069 Keywords.kw_verilogHashHash) ||
4070 (Left.is(tok::r_paren) && Left.MatchingParen &&
4071 Left.MatchingParen->endsSequence(tok::l_paren, tok::at)))) {
4072 return true;
4074 // Don't add embedded spaces in a number literal like `16'h1?ax` or an array
4075 // literal like `'{}`.
4076 if (Left.is(Keywords.kw_apostrophe) ||
4077 (Left.is(TT_VerilogNumberBase) && Right.is(tok::numeric_constant))) {
4078 return false;
4080 // Add space between the type name and dimension like `logic [1:0]`.
4081 if (Right.is(tok::l_square) &&
4082 Left.isOneOf(TT_VerilogDimensionedTypeName, Keywords.kw_function)) {
4083 return true;
4085 // Don't add spaces between a casting type and the quote or repetition count
4086 // and the brace.
4087 if ((Right.is(Keywords.kw_apostrophe) ||
4088 (Right.is(BK_BracedInit) && Right.is(tok::l_brace))) &&
4089 !(Left.isOneOf(Keywords.kw_assign, Keywords.kw_unique) ||
4090 Keywords.isVerilogWordOperator(Left)) &&
4091 (Left.isOneOf(tok::r_square, tok::r_paren, tok::r_brace,
4092 tok::numeric_constant) ||
4093 Keywords.isWordLike(Left))) {
4094 return false;
4096 // Add space in attribute like `(* ASYNC_REG = "TRUE" *)`.
4097 if (Left.endsSequence(tok::star, tok::l_paren) && Right.is(tok::identifier))
4098 return true;
4100 if (Left.is(TT_ImplicitStringLiteral))
4101 return Right.hasWhitespaceBefore();
4102 if (Line.Type == LT_ObjCMethodDecl) {
4103 if (Left.is(TT_ObjCMethodSpecifier))
4104 return true;
4105 if (Left.is(tok::r_paren) && canBeObjCSelectorComponent(Right)) {
4106 // Don't space between ')' and <id> or ')' and 'new'. 'new' is not a
4107 // keyword in Objective-C, and '+ (instancetype)new;' is a standard class
4108 // method declaration.
4109 return false;
4112 if (Line.Type == LT_ObjCProperty &&
4113 (Right.is(tok::equal) || Left.is(tok::equal))) {
4114 return false;
4117 if (Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow) ||
4118 Left.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow)) {
4119 return true;
4121 if (Left.is(tok::comma) && !Right.is(TT_OverloadedOperatorLParen))
4122 return true;
4123 if (Right.is(tok::comma))
4124 return false;
4125 if (Right.is(TT_ObjCBlockLParen))
4126 return true;
4127 if (Right.is(TT_CtorInitializerColon))
4128 return Style.SpaceBeforeCtorInitializerColon;
4129 if (Right.is(TT_InheritanceColon) && !Style.SpaceBeforeInheritanceColon)
4130 return false;
4131 if (Right.is(TT_RangeBasedForLoopColon) &&
4132 !Style.SpaceBeforeRangeBasedForLoopColon) {
4133 return false;
4135 if (Left.is(TT_BitFieldColon)) {
4136 return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both ||
4137 Style.BitFieldColonSpacing == FormatStyle::BFCS_After;
4139 if (Right.is(tok::colon)) {
4140 if (Right.is(TT_GotoLabelColon) ||
4141 (!Style.isVerilog() &&
4142 Line.First->isOneOf(tok::kw_default, tok::kw_case))) {
4143 return Style.SpaceBeforeCaseColon;
4145 if (Line.First->isOneOf(tok::kw_default, tok::kw_case))
4146 return Style.SpaceBeforeCaseColon;
4147 const FormatToken *Next = Right.getNextNonComment();
4148 if (!Next || Next->is(tok::semi))
4149 return false;
4150 if (Right.is(TT_ObjCMethodExpr))
4151 return false;
4152 if (Left.is(tok::question))
4153 return false;
4154 if (Right.is(TT_InlineASMColon) && Left.is(tok::coloncolon))
4155 return false;
4156 if (Right.is(TT_DictLiteral))
4157 return Style.SpacesInContainerLiterals;
4158 if (Right.is(TT_AttributeColon))
4159 return false;
4160 if (Right.is(TT_CSharpNamedArgumentColon))
4161 return false;
4162 if (Right.is(TT_BitFieldColon)) {
4163 return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both ||
4164 Style.BitFieldColonSpacing == FormatStyle::BFCS_Before;
4166 return true;
4168 // Do not merge "- -" into "--".
4169 if ((Left.isOneOf(tok::minus, tok::minusminus) &&
4170 Right.isOneOf(tok::minus, tok::minusminus)) ||
4171 (Left.isOneOf(tok::plus, tok::plusplus) &&
4172 Right.isOneOf(tok::plus, tok::plusplus))) {
4173 return true;
4175 if (Left.is(TT_UnaryOperator)) {
4176 if (!Right.is(tok::l_paren)) {
4177 // The alternative operators for ~ and ! are "compl" and "not".
4178 // If they are used instead, we do not want to combine them with
4179 // the token to the right, unless that is a left paren.
4180 if (Left.is(tok::exclaim) && Left.TokenText == "not")
4181 return true;
4182 if (Left.is(tok::tilde) && Left.TokenText == "compl")
4183 return true;
4184 // Lambda captures allow for a lone &, so "&]" needs to be properly
4185 // handled.
4186 if (Left.is(tok::amp) && Right.is(tok::r_square))
4187 return Style.SpacesInSquareBrackets;
4189 return (Style.SpaceAfterLogicalNot && Left.is(tok::exclaim)) ||
4190 Right.is(TT_BinaryOperator);
4193 // If the next token is a binary operator or a selector name, we have
4194 // incorrectly classified the parenthesis as a cast. FIXME: Detect correctly.
4195 if (Left.is(TT_CastRParen)) {
4196 return Style.SpaceAfterCStyleCast ||
4197 Right.isOneOf(TT_BinaryOperator, TT_SelectorName);
4200 auto ShouldAddSpacesInAngles = [this, &Right]() {
4201 if (this->Style.SpacesInAngles == FormatStyle::SIAS_Always)
4202 return true;
4203 if (this->Style.SpacesInAngles == FormatStyle::SIAS_Leave)
4204 return Right.hasWhitespaceBefore();
4205 return false;
4208 if (Left.is(tok::greater) && Right.is(tok::greater)) {
4209 if (Style.Language == FormatStyle::LK_TextProto ||
4210 (Style.Language == FormatStyle::LK_Proto && Left.is(TT_DictLiteral))) {
4211 return !Style.Cpp11BracedListStyle;
4213 return Right.is(TT_TemplateCloser) && Left.is(TT_TemplateCloser) &&
4214 ((Style.Standard < FormatStyle::LS_Cpp11) ||
4215 ShouldAddSpacesInAngles());
4217 if (Right.isOneOf(tok::arrow, tok::arrowstar, tok::periodstar) ||
4218 Left.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar) ||
4219 (Right.is(tok::period) && Right.isNot(TT_DesignatedInitializerPeriod))) {
4220 return false;
4222 if (!Style.SpaceBeforeAssignmentOperators && Left.isNot(TT_TemplateCloser) &&
4223 Right.getPrecedence() == prec::Assignment) {
4224 return false;
4226 if (Style.Language == FormatStyle::LK_Java && Right.is(tok::coloncolon) &&
4227 (Left.is(tok::identifier) || Left.is(tok::kw_this))) {
4228 return false;
4230 if (Right.is(tok::coloncolon) && Left.is(tok::identifier)) {
4231 // Generally don't remove existing spaces between an identifier and "::".
4232 // The identifier might actually be a macro name such as ALWAYS_INLINE. If
4233 // this turns out to be too lenient, add analysis of the identifier itself.
4234 return Right.hasWhitespaceBefore();
4236 if (Right.is(tok::coloncolon) &&
4237 !Left.isOneOf(tok::l_brace, tok::comment, tok::l_paren)) {
4238 // Put a space between < and :: in vector< ::std::string >
4239 return (Left.is(TT_TemplateOpener) &&
4240 ((Style.Standard < FormatStyle::LS_Cpp11) ||
4241 ShouldAddSpacesInAngles())) ||
4242 !(Left.isOneOf(tok::l_paren, tok::r_paren, tok::l_square,
4243 tok::kw___super, TT_TemplateOpener,
4244 TT_TemplateCloser)) ||
4245 (Left.is(tok::l_paren) && Style.SpacesInParentheses);
4247 if ((Left.is(TT_TemplateOpener)) != (Right.is(TT_TemplateCloser)))
4248 return ShouldAddSpacesInAngles();
4249 // Space before TT_StructuredBindingLSquare.
4250 if (Right.is(TT_StructuredBindingLSquare)) {
4251 return !Left.isOneOf(tok::amp, tok::ampamp) ||
4252 getTokenReferenceAlignment(Left) != FormatStyle::PAS_Right;
4254 // Space before & or && following a TT_StructuredBindingLSquare.
4255 if (Right.Next && Right.Next->is(TT_StructuredBindingLSquare) &&
4256 Right.isOneOf(tok::amp, tok::ampamp)) {
4257 return getTokenReferenceAlignment(Right) != FormatStyle::PAS_Left;
4259 if ((Right.is(TT_BinaryOperator) && !Left.is(tok::l_paren)) ||
4260 (Left.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) &&
4261 !Right.is(tok::r_paren))) {
4262 return true;
4264 if (Right.is(TT_TemplateOpener) && Left.is(tok::r_paren) &&
4265 Left.MatchingParen &&
4266 Left.MatchingParen->is(TT_OverloadedOperatorLParen)) {
4267 return false;
4269 if (Right.is(tok::less) && Left.isNot(tok::l_paren) &&
4270 Line.Type == LT_ImportStatement) {
4271 return true;
4273 if (Right.is(TT_TrailingUnaryOperator))
4274 return false;
4275 if (Left.is(TT_RegexLiteral))
4276 return false;
4277 return spaceRequiredBetween(Line, Left, Right);
4280 // Returns 'true' if 'Tok' is a brace we'd want to break before in Allman style.
4281 static bool isAllmanBrace(const FormatToken &Tok) {
4282 return Tok.is(tok::l_brace) && Tok.is(BK_Block) &&
4283 !Tok.isOneOf(TT_ObjCBlockLBrace, TT_LambdaLBrace, TT_DictLiteral);
4286 // Returns 'true' if 'Tok' is a function argument.
4287 static bool IsFunctionArgument(const FormatToken &Tok) {
4288 return Tok.MatchingParen && Tok.MatchingParen->Next &&
4289 Tok.MatchingParen->Next->isOneOf(tok::comma, tok::r_paren);
4292 static bool
4293 isItAnEmptyLambdaAllowed(const FormatToken &Tok,
4294 FormatStyle::ShortLambdaStyle ShortLambdaOption) {
4295 return Tok.Children.empty() && ShortLambdaOption != FormatStyle::SLS_None;
4298 static bool isAllmanLambdaBrace(const FormatToken &Tok) {
4299 return Tok.is(tok::l_brace) && Tok.is(BK_Block) &&
4300 !Tok.isOneOf(TT_ObjCBlockLBrace, TT_DictLiteral);
4303 // Returns the first token on the line that is not a comment.
4304 static const FormatToken *getFirstNonComment(const AnnotatedLine &Line) {
4305 const FormatToken *Next = Line.First;
4306 if (!Next)
4307 return Next;
4308 if (Next->is(tok::comment))
4309 Next = Next->getNextNonComment();
4310 return Next;
4313 bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
4314 const FormatToken &Right) const {
4315 const FormatToken &Left = *Right.Previous;
4316 if (Right.NewlinesBefore > 1 && Style.MaxEmptyLinesToKeep > 0)
4317 return true;
4319 if (Style.isCSharp()) {
4320 if (Left.is(TT_FatArrow) && Right.is(tok::l_brace) &&
4321 Style.BraceWrapping.AfterFunction) {
4322 return true;
4324 if (Right.is(TT_CSharpNamedArgumentColon) ||
4325 Left.is(TT_CSharpNamedArgumentColon)) {
4326 return false;
4328 if (Right.is(TT_CSharpGenericTypeConstraint))
4329 return true;
4330 if (Right.Next && Right.Next->is(TT_FatArrow) &&
4331 (Right.is(tok::numeric_constant) ||
4332 (Right.is(tok::identifier) && Right.TokenText == "_"))) {
4333 return true;
4336 // Break after C# [...] and before public/protected/private/internal.
4337 if (Left.is(TT_AttributeSquare) && Left.is(tok::r_square) &&
4338 (Right.isAccessSpecifier(/*ColonRequired=*/false) ||
4339 Right.is(Keywords.kw_internal))) {
4340 return true;
4342 // Break between ] and [ but only when there are really 2 attributes.
4343 if (Left.is(TT_AttributeSquare) && Right.is(TT_AttributeSquare) &&
4344 Left.is(tok::r_square) && Right.is(tok::l_square)) {
4345 return true;
4348 } else if (Style.isJavaScript()) {
4349 // FIXME: This might apply to other languages and token kinds.
4350 if (Right.is(tok::string_literal) && Left.is(tok::plus) && Left.Previous &&
4351 Left.Previous->is(tok::string_literal)) {
4352 return true;
4354 if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace) && Line.Level == 0 &&
4355 Left.Previous && Left.Previous->is(tok::equal) &&
4356 Line.First->isOneOf(tok::identifier, Keywords.kw_import, tok::kw_export,
4357 tok::kw_const) &&
4358 // kw_var/kw_let are pseudo-tokens that are tok::identifier, so match
4359 // above.
4360 !Line.First->isOneOf(Keywords.kw_var, Keywords.kw_let)) {
4361 // Object literals on the top level of a file are treated as "enum-style".
4362 // Each key/value pair is put on a separate line, instead of bin-packing.
4363 return true;
4365 if (Left.is(tok::l_brace) && Line.Level == 0 &&
4366 (Line.startsWith(tok::kw_enum) ||
4367 Line.startsWith(tok::kw_const, tok::kw_enum) ||
4368 Line.startsWith(tok::kw_export, tok::kw_enum) ||
4369 Line.startsWith(tok::kw_export, tok::kw_const, tok::kw_enum))) {
4370 // JavaScript top-level enum key/value pairs are put on separate lines
4371 // instead of bin-packing.
4372 return true;
4374 if (Right.is(tok::r_brace) && Left.is(tok::l_brace) && Left.Previous &&
4375 Left.Previous->is(TT_FatArrow)) {
4376 // JS arrow function (=> {...}).
4377 switch (Style.AllowShortLambdasOnASingleLine) {
4378 case FormatStyle::SLS_All:
4379 return false;
4380 case FormatStyle::SLS_None:
4381 return true;
4382 case FormatStyle::SLS_Empty:
4383 return !Left.Children.empty();
4384 case FormatStyle::SLS_Inline:
4385 // allow one-lining inline (e.g. in function call args) and empty arrow
4386 // functions.
4387 return (Left.NestingLevel == 0 && Line.Level == 0) &&
4388 !Left.Children.empty();
4390 llvm_unreachable("Unknown FormatStyle::ShortLambdaStyle enum");
4393 if (Right.is(tok::r_brace) && Left.is(tok::l_brace) &&
4394 !Left.Children.empty()) {
4395 // Support AllowShortFunctionsOnASingleLine for JavaScript.
4396 return Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None ||
4397 Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Empty ||
4398 (Left.NestingLevel == 0 && Line.Level == 0 &&
4399 Style.AllowShortFunctionsOnASingleLine &
4400 FormatStyle::SFS_InlineOnly);
4402 } else if (Style.Language == FormatStyle::LK_Java) {
4403 if (Right.is(tok::plus) && Left.is(tok::string_literal) && Right.Next &&
4404 Right.Next->is(tok::string_literal)) {
4405 return true;
4407 } else if (Style.isVerilog()) {
4408 // Break after labels. In Verilog labels don't have the 'case' keyword, so
4409 // it is hard to identify them in UnwrappedLineParser.
4410 if (!Keywords.isVerilogBegin(Right) && Keywords.isVerilogEndOfLabel(Left))
4411 return true;
4412 } else if (Style.Language == FormatStyle::LK_Cpp ||
4413 Style.Language == FormatStyle::LK_ObjC ||
4414 Style.Language == FormatStyle::LK_Proto ||
4415 Style.Language == FormatStyle::LK_TableGen ||
4416 Style.Language == FormatStyle::LK_TextProto) {
4417 if (Left.isStringLiteral() && Right.isStringLiteral())
4418 return true;
4421 // Basic JSON newline processing.
4422 if (Style.isJson()) {
4423 // Always break after a JSON record opener.
4424 // {
4425 // }
4426 if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace))
4427 return true;
4428 // Always break after a JSON array opener based on BreakArrays.
4429 if ((Left.is(TT_ArrayInitializerLSquare) && Left.is(tok::l_square) &&
4430 Right.isNot(tok::r_square)) ||
4431 Left.is(tok::comma)) {
4432 if (Right.is(tok::l_brace))
4433 return true;
4434 // scan to the right if an we see an object or an array inside
4435 // then break.
4436 for (const auto *Tok = &Right; Tok; Tok = Tok->Next) {
4437 if (Tok->isOneOf(tok::l_brace, tok::l_square))
4438 return true;
4439 if (Tok->isOneOf(tok::r_brace, tok::r_square))
4440 break;
4442 return Style.BreakArrays;
4446 // If the last token before a '}', ']', or ')' is a comma or a trailing
4447 // comment, the intention is to insert a line break after it in order to make
4448 // shuffling around entries easier. Import statements, especially in
4449 // JavaScript, can be an exception to this rule.
4450 if (Style.JavaScriptWrapImports || Line.Type != LT_ImportStatement) {
4451 const FormatToken *BeforeClosingBrace = nullptr;
4452 if ((Left.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
4453 (Style.isJavaScript() && Left.is(tok::l_paren))) &&
4454 Left.isNot(BK_Block) && Left.MatchingParen) {
4455 BeforeClosingBrace = Left.MatchingParen->Previous;
4456 } else if (Right.MatchingParen &&
4457 (Right.MatchingParen->isOneOf(tok::l_brace,
4458 TT_ArrayInitializerLSquare) ||
4459 (Style.isJavaScript() &&
4460 Right.MatchingParen->is(tok::l_paren)))) {
4461 BeforeClosingBrace = &Left;
4463 if (BeforeClosingBrace && (BeforeClosingBrace->is(tok::comma) ||
4464 BeforeClosingBrace->isTrailingComment())) {
4465 return true;
4469 if (Right.is(tok::comment)) {
4470 return Left.isNot(BK_BracedInit) && Left.isNot(TT_CtorInitializerColon) &&
4471 (Right.NewlinesBefore > 0 && Right.HasUnescapedNewline);
4473 if (Left.isTrailingComment())
4474 return true;
4475 if (Left.IsUnterminatedLiteral)
4476 return true;
4477 if (Right.is(tok::lessless) && Right.Next && Left.is(tok::string_literal) &&
4478 Right.Next->is(tok::string_literal)) {
4479 return true;
4481 if (Right.is(TT_RequiresClause)) {
4482 switch (Style.RequiresClausePosition) {
4483 case FormatStyle::RCPS_OwnLine:
4484 case FormatStyle::RCPS_WithFollowing:
4485 return true;
4486 default:
4487 break;
4490 // Can break after template<> declaration
4491 if (Left.ClosesTemplateDeclaration && Left.MatchingParen &&
4492 Left.MatchingParen->NestingLevel == 0) {
4493 // Put concepts on the next line e.g.
4494 // template<typename T>
4495 // concept ...
4496 if (Right.is(tok::kw_concept))
4497 return Style.BreakBeforeConceptDeclarations == FormatStyle::BBCDS_Always;
4498 return Style.AlwaysBreakTemplateDeclarations == FormatStyle::BTDS_Yes;
4500 if (Left.ClosesRequiresClause && Right.isNot(tok::semi)) {
4501 switch (Style.RequiresClausePosition) {
4502 case FormatStyle::RCPS_OwnLine:
4503 case FormatStyle::RCPS_WithPreceding:
4504 return true;
4505 default:
4506 break;
4509 if (Style.PackConstructorInitializers == FormatStyle::PCIS_Never) {
4510 if (Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon &&
4511 (Left.is(TT_CtorInitializerComma) ||
4512 Right.is(TT_CtorInitializerColon))) {
4513 return true;
4516 if (Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon &&
4517 Left.isOneOf(TT_CtorInitializerColon, TT_CtorInitializerComma)) {
4518 return true;
4521 if (Style.PackConstructorInitializers < FormatStyle::PCIS_CurrentLine &&
4522 Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma &&
4523 Right.isOneOf(TT_CtorInitializerComma, TT_CtorInitializerColon)) {
4524 return true;
4526 // Break only if we have multiple inheritance.
4527 if (Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma &&
4528 Right.is(TT_InheritanceComma)) {
4529 return true;
4531 if (Style.BreakInheritanceList == FormatStyle::BILS_AfterComma &&
4532 Left.is(TT_InheritanceComma)) {
4533 return true;
4535 if (Right.is(tok::string_literal) && Right.TokenText.startswith("R\"")) {
4536 // Multiline raw string literals are special wrt. line breaks. The author
4537 // has made a deliberate choice and might have aligned the contents of the
4538 // string literal accordingly. Thus, we try keep existing line breaks.
4539 return Right.IsMultiline && Right.NewlinesBefore > 0;
4541 if ((Left.is(tok::l_brace) || (Left.is(tok::less) && Left.Previous &&
4542 Left.Previous->is(tok::equal))) &&
4543 Right.NestingLevel == 1 && Style.Language == FormatStyle::LK_Proto) {
4544 // Don't put enums or option definitions onto single lines in protocol
4545 // buffers.
4546 return true;
4548 if (Right.is(TT_InlineASMBrace))
4549 return Right.HasUnescapedNewline;
4551 if (isAllmanBrace(Left) || isAllmanBrace(Right)) {
4552 auto FirstNonComment = getFirstNonComment(Line);
4553 bool AccessSpecifier =
4554 FirstNonComment &&
4555 FirstNonComment->isOneOf(Keywords.kw_internal, tok::kw_public,
4556 tok::kw_private, tok::kw_protected);
4558 if (Style.BraceWrapping.AfterEnum) {
4559 if (Line.startsWith(tok::kw_enum) ||
4560 Line.startsWith(tok::kw_typedef, tok::kw_enum)) {
4561 return true;
4563 // Ensure BraceWrapping for `public enum A {`.
4564 if (AccessSpecifier && FirstNonComment->Next &&
4565 FirstNonComment->Next->is(tok::kw_enum)) {
4566 return true;
4570 // Ensure BraceWrapping for `public interface A {`.
4571 if (Style.BraceWrapping.AfterClass &&
4572 ((AccessSpecifier && FirstNonComment->Next &&
4573 FirstNonComment->Next->is(Keywords.kw_interface)) ||
4574 Line.startsWith(Keywords.kw_interface))) {
4575 return true;
4578 return (Line.startsWith(tok::kw_class) && Style.BraceWrapping.AfterClass) ||
4579 (Line.startsWith(tok::kw_struct) && Style.BraceWrapping.AfterStruct);
4582 if (Left.is(TT_ObjCBlockLBrace) &&
4583 Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) {
4584 return true;
4587 // Ensure wrapping after __attribute__((XX)) and @interface etc.
4588 if (Left.is(TT_AttributeParen) && Right.is(TT_ObjCDecl))
4589 return true;
4591 if (Left.is(TT_LambdaLBrace)) {
4592 if (IsFunctionArgument(Left) &&
4593 Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Inline) {
4594 return false;
4597 if (Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_None ||
4598 Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Inline ||
4599 (!Left.Children.empty() &&
4600 Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Empty)) {
4601 return true;
4605 if (Style.BraceWrapping.BeforeLambdaBody && Right.is(TT_LambdaLBrace) &&
4606 Left.isOneOf(tok::star, tok::amp, tok::ampamp, TT_TemplateCloser)) {
4607 return true;
4610 // Put multiple Java annotation on a new line.
4611 if ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&
4612 Left.is(TT_LeadingJavaAnnotation) &&
4613 Right.isNot(TT_LeadingJavaAnnotation) && Right.isNot(tok::l_paren) &&
4614 (Line.Last->is(tok::l_brace) || Style.BreakAfterJavaFieldAnnotations)) {
4615 return true;
4618 if (Right.is(TT_ProtoExtensionLSquare))
4619 return true;
4621 // In text proto instances if a submessage contains at least 2 entries and at
4622 // least one of them is a submessage, like A { ... B { ... } ... },
4623 // put all of the entries of A on separate lines by forcing the selector of
4624 // the submessage B to be put on a newline.
4626 // Example: these can stay on one line:
4627 // a { scalar_1: 1 scalar_2: 2 }
4628 // a { b { key: value } }
4630 // and these entries need to be on a new line even if putting them all in one
4631 // line is under the column limit:
4632 // a {
4633 // scalar: 1
4634 // b { key: value }
4635 // }
4637 // We enforce this by breaking before a submessage field that has previous
4638 // siblings, *and* breaking before a field that follows a submessage field.
4640 // Be careful to exclude the case [proto.ext] { ... } since the `]` is
4641 // the TT_SelectorName there, but we don't want to break inside the brackets.
4643 // Another edge case is @submessage { key: value }, which is a common
4644 // substitution placeholder. In this case we want to keep `@` and `submessage`
4645 // together.
4647 // We ensure elsewhere that extensions are always on their own line.
4648 if ((Style.Language == FormatStyle::LK_Proto ||
4649 Style.Language == FormatStyle::LK_TextProto) &&
4650 Right.is(TT_SelectorName) && !Right.is(tok::r_square) && Right.Next) {
4651 // Keep `@submessage` together in:
4652 // @submessage { key: value }
4653 if (Left.is(tok::at))
4654 return false;
4655 // Look for the scope opener after selector in cases like:
4656 // selector { ...
4657 // selector: { ...
4658 // selector: @base { ...
4659 FormatToken *LBrace = Right.Next;
4660 if (LBrace && LBrace->is(tok::colon)) {
4661 LBrace = LBrace->Next;
4662 if (LBrace && LBrace->is(tok::at)) {
4663 LBrace = LBrace->Next;
4664 if (LBrace)
4665 LBrace = LBrace->Next;
4668 if (LBrace &&
4669 // The scope opener is one of {, [, <:
4670 // selector { ... }
4671 // selector [ ... ]
4672 // selector < ... >
4674 // In case of selector { ... }, the l_brace is TT_DictLiteral.
4675 // In case of an empty selector {}, the l_brace is not TT_DictLiteral,
4676 // so we check for immediately following r_brace.
4677 ((LBrace->is(tok::l_brace) &&
4678 (LBrace->is(TT_DictLiteral) ||
4679 (LBrace->Next && LBrace->Next->is(tok::r_brace)))) ||
4680 LBrace->is(TT_ArrayInitializerLSquare) || LBrace->is(tok::less))) {
4681 // If Left.ParameterCount is 0, then this submessage entry is not the
4682 // first in its parent submessage, and we want to break before this entry.
4683 // If Left.ParameterCount is greater than 0, then its parent submessage
4684 // might contain 1 or more entries and we want to break before this entry
4685 // if it contains at least 2 entries. We deal with this case later by
4686 // detecting and breaking before the next entry in the parent submessage.
4687 if (Left.ParameterCount == 0)
4688 return true;
4689 // However, if this submessage is the first entry in its parent
4690 // submessage, Left.ParameterCount might be 1 in some cases.
4691 // We deal with this case later by detecting an entry
4692 // following a closing paren of this submessage.
4695 // If this is an entry immediately following a submessage, it will be
4696 // preceded by a closing paren of that submessage, like in:
4697 // left---. .---right
4698 // v v
4699 // sub: { ... } key: value
4700 // If there was a comment between `}` an `key` above, then `key` would be
4701 // put on a new line anyways.
4702 if (Left.isOneOf(tok::r_brace, tok::greater, tok::r_square))
4703 return true;
4706 // Deal with lambda arguments in C++ - we want consistent line breaks whether
4707 // they happen to be at arg0, arg1 or argN. The selection is a bit nuanced
4708 // as aggressive line breaks are placed when the lambda is not the last arg.
4709 if ((Style.Language == FormatStyle::LK_Cpp ||
4710 Style.Language == FormatStyle::LK_ObjC) &&
4711 Left.is(tok::l_paren) && Left.BlockParameterCount > 0 &&
4712 !Right.isOneOf(tok::l_paren, TT_LambdaLSquare)) {
4713 // Multiple lambdas in the same function call force line breaks.
4714 if (Left.BlockParameterCount > 1)
4715 return true;
4717 // A lambda followed by another arg forces a line break.
4718 if (!Left.Role)
4719 return false;
4720 auto Comma = Left.Role->lastComma();
4721 if (!Comma)
4722 return false;
4723 auto Next = Comma->getNextNonComment();
4724 if (!Next)
4725 return false;
4726 if (!Next->isOneOf(TT_LambdaLSquare, tok::l_brace, tok::caret))
4727 return true;
4730 return false;
4733 bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
4734 const FormatToken &Right) const {
4735 const FormatToken &Left = *Right.Previous;
4736 // Language-specific stuff.
4737 if (Style.isCSharp()) {
4738 if (Left.isOneOf(TT_CSharpNamedArgumentColon, TT_AttributeColon) ||
4739 Right.isOneOf(TT_CSharpNamedArgumentColon, TT_AttributeColon)) {
4740 return false;
4742 // Only break after commas for generic type constraints.
4743 if (Line.First->is(TT_CSharpGenericTypeConstraint))
4744 return Left.is(TT_CSharpGenericTypeConstraintComma);
4745 // Keep nullable operators attached to their identifiers.
4746 if (Right.is(TT_CSharpNullable))
4747 return false;
4748 } else if (Style.Language == FormatStyle::LK_Java) {
4749 if (Left.isOneOf(Keywords.kw_throws, Keywords.kw_extends,
4750 Keywords.kw_implements)) {
4751 return false;
4753 if (Right.isOneOf(Keywords.kw_throws, Keywords.kw_extends,
4754 Keywords.kw_implements)) {
4755 return true;
4757 } else if (Style.isJavaScript()) {
4758 const FormatToken *NonComment = Right.getPreviousNonComment();
4759 if (NonComment &&
4760 NonComment->isOneOf(
4761 tok::kw_return, Keywords.kw_yield, tok::kw_continue, tok::kw_break,
4762 tok::kw_throw, Keywords.kw_interface, Keywords.kw_type,
4763 tok::kw_static, tok::kw_public, tok::kw_private, tok::kw_protected,
4764 Keywords.kw_readonly, Keywords.kw_override, Keywords.kw_abstract,
4765 Keywords.kw_get, Keywords.kw_set, Keywords.kw_async,
4766 Keywords.kw_await)) {
4767 return false; // Otherwise automatic semicolon insertion would trigger.
4769 if (Right.NestingLevel == 0 &&
4770 (Left.Tok.getIdentifierInfo() ||
4771 Left.isOneOf(tok::r_square, tok::r_paren)) &&
4772 Right.isOneOf(tok::l_square, tok::l_paren)) {
4773 return false; // Otherwise automatic semicolon insertion would trigger.
4775 if (NonComment && NonComment->is(tok::identifier) &&
4776 NonComment->TokenText == "asserts") {
4777 return false;
4779 if (Left.is(TT_FatArrow) && Right.is(tok::l_brace))
4780 return false;
4781 if (Left.is(TT_JsTypeColon))
4782 return true;
4783 // Don't wrap between ":" and "!" of a strict prop init ("field!: type;").
4784 if (Left.is(tok::exclaim) && Right.is(tok::colon))
4785 return false;
4786 // Look for is type annotations like:
4787 // function f(): a is B { ... }
4788 // Do not break before is in these cases.
4789 if (Right.is(Keywords.kw_is)) {
4790 const FormatToken *Next = Right.getNextNonComment();
4791 // If `is` is followed by a colon, it's likely that it's a dict key, so
4792 // ignore it for this check.
4793 // For example this is common in Polymer:
4794 // Polymer({
4795 // is: 'name',
4796 // ...
4797 // });
4798 if (!Next || !Next->is(tok::colon))
4799 return false;
4801 if (Left.is(Keywords.kw_in))
4802 return Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None;
4803 if (Right.is(Keywords.kw_in))
4804 return Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None;
4805 if (Right.is(Keywords.kw_as))
4806 return false; // must not break before as in 'x as type' casts
4807 if (Right.isOneOf(Keywords.kw_extends, Keywords.kw_infer)) {
4808 // extends and infer can appear as keywords in conditional types:
4809 // https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types
4810 // do not break before them, as the expressions are subject to ASI.
4811 return false;
4813 if (Left.is(Keywords.kw_as))
4814 return true;
4815 if (Left.is(TT_NonNullAssertion))
4816 return true;
4817 if (Left.is(Keywords.kw_declare) &&
4818 Right.isOneOf(Keywords.kw_module, tok::kw_namespace,
4819 Keywords.kw_function, tok::kw_class, tok::kw_enum,
4820 Keywords.kw_interface, Keywords.kw_type, Keywords.kw_var,
4821 Keywords.kw_let, tok::kw_const)) {
4822 // See grammar for 'declare' statements at:
4823 // https://github.com/Microsoft/TypeScript/blob/main/doc/spec-ARCHIVED.md#A.10
4824 return false;
4826 if (Left.isOneOf(Keywords.kw_module, tok::kw_namespace) &&
4827 Right.isOneOf(tok::identifier, tok::string_literal)) {
4828 return false; // must not break in "module foo { ...}"
4830 if (Right.is(TT_TemplateString) && Right.closesScope())
4831 return false;
4832 // Don't split tagged template literal so there is a break between the tag
4833 // identifier and template string.
4834 if (Left.is(tok::identifier) && Right.is(TT_TemplateString))
4835 return false;
4836 if (Left.is(TT_TemplateString) && Left.opensScope())
4837 return true;
4840 if (Left.is(tok::at))
4841 return false;
4842 if (Left.Tok.getObjCKeywordID() == tok::objc_interface)
4843 return false;
4844 if (Left.isOneOf(TT_JavaAnnotation, TT_LeadingJavaAnnotation))
4845 return !Right.is(tok::l_paren);
4846 if (Right.is(TT_PointerOrReference)) {
4847 return Line.IsMultiVariableDeclStmt ||
4848 (getTokenPointerOrReferenceAlignment(Right) ==
4849 FormatStyle::PAS_Right &&
4850 (!Right.Next || Right.Next->isNot(TT_FunctionDeclarationName)));
4852 if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName) ||
4853 Right.is(tok::kw_operator)) {
4854 return true;
4856 if (Left.is(TT_PointerOrReference))
4857 return false;
4858 if (Right.isTrailingComment()) {
4859 // We rely on MustBreakBefore being set correctly here as we should not
4860 // change the "binding" behavior of a comment.
4861 // The first comment in a braced lists is always interpreted as belonging to
4862 // the first list element. Otherwise, it should be placed outside of the
4863 // list.
4864 return Left.is(BK_BracedInit) ||
4865 (Left.is(TT_CtorInitializerColon) && Right.NewlinesBefore > 0 &&
4866 Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon);
4868 if (Left.is(tok::question) && Right.is(tok::colon))
4869 return false;
4870 if (Right.is(TT_ConditionalExpr) || Right.is(tok::question))
4871 return Style.BreakBeforeTernaryOperators;
4872 if (Left.is(TT_ConditionalExpr) || Left.is(tok::question))
4873 return !Style.BreakBeforeTernaryOperators;
4874 if (Left.is(TT_InheritanceColon))
4875 return Style.BreakInheritanceList == FormatStyle::BILS_AfterColon;
4876 if (Right.is(TT_InheritanceColon))
4877 return Style.BreakInheritanceList != FormatStyle::BILS_AfterColon;
4878 if (Right.is(TT_ObjCMethodExpr) && !Right.is(tok::r_square) &&
4879 Left.isNot(TT_SelectorName)) {
4880 return true;
4883 if (Right.is(tok::colon) &&
4884 !Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon)) {
4885 return false;
4887 if (Left.is(tok::colon) && Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) {
4888 if (Style.Language == FormatStyle::LK_Proto ||
4889 Style.Language == FormatStyle::LK_TextProto) {
4890 if (!Style.AlwaysBreakBeforeMultilineStrings && Right.isStringLiteral())
4891 return false;
4892 // Prevent cases like:
4894 // submessage:
4895 // { key: valueeeeeeeeeeee }
4897 // when the snippet does not fit into one line.
4898 // Prefer:
4900 // submessage: {
4901 // key: valueeeeeeeeeeee
4902 // }
4904 // instead, even if it is longer by one line.
4906 // Note that this allows allows the "{" to go over the column limit
4907 // when the column limit is just between ":" and "{", but that does
4908 // not happen too often and alternative formattings in this case are
4909 // not much better.
4911 // The code covers the cases:
4913 // submessage: { ... }
4914 // submessage: < ... >
4915 // repeated: [ ... ]
4916 if (((Right.is(tok::l_brace) || Right.is(tok::less)) &&
4917 Right.is(TT_DictLiteral)) ||
4918 Right.is(TT_ArrayInitializerLSquare)) {
4919 return false;
4922 return true;
4924 if (Right.is(tok::r_square) && Right.MatchingParen &&
4925 Right.MatchingParen->is(TT_ProtoExtensionLSquare)) {
4926 return false;
4928 if (Right.is(TT_SelectorName) || (Right.is(tok::identifier) && Right.Next &&
4929 Right.Next->is(TT_ObjCMethodExpr))) {
4930 return Left.isNot(tok::period); // FIXME: Properly parse ObjC calls.
4932 if (Left.is(tok::r_paren) && Line.Type == LT_ObjCProperty)
4933 return true;
4934 if (Right.is(tok::kw_concept))
4935 return Style.BreakBeforeConceptDeclarations != FormatStyle::BBCDS_Never;
4936 if (Right.is(TT_RequiresClause))
4937 return true;
4938 if (Left.ClosesTemplateDeclaration || Left.is(TT_FunctionAnnotationRParen))
4939 return true;
4940 if (Left.ClosesRequiresClause)
4941 return true;
4942 if (Right.isOneOf(TT_RangeBasedForLoopColon, TT_OverloadedOperatorLParen,
4943 TT_OverloadedOperator)) {
4944 return false;
4946 if (Left.is(TT_RangeBasedForLoopColon))
4947 return true;
4948 if (Right.is(TT_RangeBasedForLoopColon))
4949 return false;
4950 if (Left.is(TT_TemplateCloser) && Right.is(TT_TemplateOpener))
4951 return true;
4952 if ((Left.is(tok::greater) && Right.is(tok::greater)) ||
4953 (Left.is(tok::less) && Right.is(tok::less))) {
4954 return false;
4956 if (Right.is(TT_BinaryOperator) &&
4957 Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None &&
4958 (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_All ||
4959 Right.getPrecedence() != prec::Assignment)) {
4960 return true;
4962 if (Left.isOneOf(TT_TemplateCloser, TT_UnaryOperator) ||
4963 Left.is(tok::kw_operator)) {
4964 return false;
4966 if (Left.is(tok::equal) && !Right.isOneOf(tok::kw_default, tok::kw_delete) &&
4967 Line.Type == LT_VirtualFunctionDecl && Left.NestingLevel == 0) {
4968 return false;
4970 if (Left.is(tok::equal) && Right.is(tok::l_brace) &&
4971 !Style.Cpp11BracedListStyle) {
4972 return false;
4974 if (Left.is(tok::l_paren) &&
4975 Left.isOneOf(TT_AttributeParen, TT_TypeDeclarationParen)) {
4976 return false;
4978 if (Left.is(tok::l_paren) && Left.Previous &&
4979 (Left.Previous->isOneOf(TT_BinaryOperator, TT_CastRParen))) {
4980 return false;
4982 if (Right.is(TT_ImplicitStringLiteral))
4983 return false;
4985 if (Right.is(TT_TemplateCloser))
4986 return false;
4987 if (Right.is(tok::r_square) && Right.MatchingParen &&
4988 Right.MatchingParen->is(TT_LambdaLSquare)) {
4989 return false;
4992 // We only break before r_brace if there was a corresponding break before
4993 // the l_brace, which is tracked by BreakBeforeClosingBrace.
4994 if (Right.is(tok::r_brace))
4995 return Right.MatchingParen && Right.MatchingParen->is(BK_Block);
4997 // We only break before r_paren if we're in a block indented context.
4998 if (Right.is(tok::r_paren)) {
4999 if (Style.AlignAfterOpenBracket != FormatStyle::BAS_BlockIndent ||
5000 !Right.MatchingParen) {
5001 return false;
5003 const FormatToken *Previous = Right.MatchingParen->Previous;
5004 return !(Previous && (Previous->is(tok::kw_for) || Previous->isIf()));
5007 // Allow breaking after a trailing annotation, e.g. after a method
5008 // declaration.
5009 if (Left.is(TT_TrailingAnnotation)) {
5010 return !Right.isOneOf(tok::l_brace, tok::semi, tok::equal, tok::l_paren,
5011 tok::less, tok::coloncolon);
5014 if (Right.is(tok::kw___attribute) ||
5015 (Right.is(tok::l_square) && Right.is(TT_AttributeSquare))) {
5016 return !Left.is(TT_AttributeSquare);
5019 if (Left.is(tok::identifier) && Right.is(tok::string_literal))
5020 return true;
5022 if (Right.is(tok::identifier) && Right.Next && Right.Next->is(TT_DictLiteral))
5023 return true;
5025 if (Left.is(TT_CtorInitializerColon)) {
5026 return Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon &&
5027 (!Right.isTrailingComment() || Right.NewlinesBefore > 0);
5029 if (Right.is(TT_CtorInitializerColon))
5030 return Style.BreakConstructorInitializers != FormatStyle::BCIS_AfterColon;
5031 if (Left.is(TT_CtorInitializerComma) &&
5032 Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma) {
5033 return false;
5035 if (Right.is(TT_CtorInitializerComma) &&
5036 Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma) {
5037 return true;
5039 if (Left.is(TT_InheritanceComma) &&
5040 Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma) {
5041 return false;
5043 if (Right.is(TT_InheritanceComma) &&
5044 Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma) {
5045 return true;
5047 if (Left.is(TT_ArrayInitializerLSquare))
5048 return true;
5049 if (Right.is(tok::kw_typename) && Left.isNot(tok::kw_const))
5050 return true;
5051 if ((Left.isBinaryOperator() || Left.is(TT_BinaryOperator)) &&
5052 !Left.isOneOf(tok::arrowstar, tok::lessless) &&
5053 Style.BreakBeforeBinaryOperators != FormatStyle::BOS_All &&
5054 (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None ||
5055 Left.getPrecedence() == prec::Assignment)) {
5056 return true;
5058 if ((Left.is(TT_AttributeSquare) && Right.is(tok::l_square)) ||
5059 (Left.is(tok::r_square) && Right.is(TT_AttributeSquare))) {
5060 return false;
5063 auto ShortLambdaOption = Style.AllowShortLambdasOnASingleLine;
5064 if (Style.BraceWrapping.BeforeLambdaBody && Right.is(TT_LambdaLBrace)) {
5065 if (isAllmanLambdaBrace(Left))
5066 return !isItAnEmptyLambdaAllowed(Left, ShortLambdaOption);
5067 if (isAllmanLambdaBrace(Right))
5068 return !isItAnEmptyLambdaAllowed(Right, ShortLambdaOption);
5071 return Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,
5072 tok::kw_class, tok::kw_struct, tok::comment) ||
5073 Right.isMemberAccess() ||
5074 Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow, tok::lessless,
5075 tok::colon, tok::l_square, tok::at) ||
5076 (Left.is(tok::r_paren) &&
5077 Right.isOneOf(tok::identifier, tok::kw_const)) ||
5078 (Left.is(tok::l_paren) && !Right.is(tok::r_paren)) ||
5079 (Left.is(TT_TemplateOpener) && !Right.is(TT_TemplateCloser));
5082 void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) const {
5083 llvm::errs() << "AnnotatedTokens(L=" << Line.Level << ", T=" << Line.Type
5084 << ", C=" << Line.IsContinuation << "):\n";
5085 const FormatToken *Tok = Line.First;
5086 while (Tok) {
5087 llvm::errs() << " M=" << Tok->MustBreakBefore
5088 << " C=" << Tok->CanBreakBefore
5089 << " T=" << getTokenTypeName(Tok->getType())
5090 << " S=" << Tok->SpacesRequiredBefore
5091 << " F=" << Tok->Finalized << " B=" << Tok->BlockParameterCount
5092 << " BK=" << Tok->getBlockKind() << " P=" << Tok->SplitPenalty
5093 << " Name=" << Tok->Tok.getName() << " L=" << Tok->TotalLength
5094 << " PPK=" << Tok->getPackingKind() << " FakeLParens=";
5095 for (prec::Level LParen : Tok->FakeLParens)
5096 llvm::errs() << LParen << "/";
5097 llvm::errs() << " FakeRParens=" << Tok->FakeRParens;
5098 llvm::errs() << " II=" << Tok->Tok.getIdentifierInfo();
5099 llvm::errs() << " Text='" << Tok->TokenText << "'\n";
5100 if (!Tok->Next)
5101 assert(Tok == Line.Last);
5102 Tok = Tok->Next;
5104 llvm::errs() << "----\n";
5107 FormatStyle::PointerAlignmentStyle
5108 TokenAnnotator::getTokenReferenceAlignment(const FormatToken &Reference) const {
5109 assert(Reference.isOneOf(tok::amp, tok::ampamp));
5110 switch (Style.ReferenceAlignment) {
5111 case FormatStyle::RAS_Pointer:
5112 return Style.PointerAlignment;
5113 case FormatStyle::RAS_Left:
5114 return FormatStyle::PAS_Left;
5115 case FormatStyle::RAS_Right:
5116 return FormatStyle::PAS_Right;
5117 case FormatStyle::RAS_Middle:
5118 return FormatStyle::PAS_Middle;
5120 assert(0); //"Unhandled value of ReferenceAlignment"
5121 return Style.PointerAlignment;
5124 FormatStyle::PointerAlignmentStyle
5125 TokenAnnotator::getTokenPointerOrReferenceAlignment(
5126 const FormatToken &PointerOrReference) const {
5127 if (PointerOrReference.isOneOf(tok::amp, tok::ampamp)) {
5128 switch (Style.ReferenceAlignment) {
5129 case FormatStyle::RAS_Pointer:
5130 return Style.PointerAlignment;
5131 case FormatStyle::RAS_Left:
5132 return FormatStyle::PAS_Left;
5133 case FormatStyle::RAS_Right:
5134 return FormatStyle::PAS_Right;
5135 case FormatStyle::RAS_Middle:
5136 return FormatStyle::PAS_Middle;
5139 assert(PointerOrReference.is(tok::star));
5140 return Style.PointerAlignment;
5143 } // namespace format
5144 } // namespace clang