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