File: | tools/clang/lib/Format/TokenAnnotator.cpp |
Location: | line 1214, column 5 |
Description: | Called C++ object pointer is null |
1 | //===--- TokenAnnotator.cpp - Format C++ code -----------------------------===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | /// | |||
10 | /// \file | |||
11 | /// \brief This file implements a token annotator, i.e. creates | |||
12 | /// \c AnnotatedTokens out of \c FormatTokens with required extra information. | |||
13 | /// | |||
14 | //===----------------------------------------------------------------------===// | |||
15 | ||||
16 | #include "TokenAnnotator.h" | |||
17 | #include "clang/Basic/SourceManager.h" | |||
18 | #include "llvm/Support/Debug.h" | |||
19 | ||||
20 | #define DEBUG_TYPE"format-token-annotator" "format-token-annotator" | |||
21 | ||||
22 | namespace clang { | |||
23 | namespace format { | |||
24 | ||||
25 | namespace { | |||
26 | ||||
27 | /// \brief A parser that gathers additional information about tokens. | |||
28 | /// | |||
29 | /// The \c TokenAnnotator tries to match parenthesis and square brakets and | |||
30 | /// store a parenthesis levels. It also tries to resolve matching "<" and ">" | |||
31 | /// into template parameter lists. | |||
32 | class AnnotatingParser { | |||
33 | public: | |||
34 | AnnotatingParser(const FormatStyle &Style, AnnotatedLine &Line, | |||
35 | const AdditionalKeywords &Keywords) | |||
36 | : Style(Style), Line(Line), CurrentToken(Line.First), AutoFound(false), | |||
37 | Keywords(Keywords) { | |||
38 | Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false)); | |||
39 | resetTokenMetadata(CurrentToken); | |||
40 | } | |||
41 | ||||
42 | private: | |||
43 | bool parseAngle() { | |||
44 | if (!CurrentToken) | |||
45 | return false; | |||
46 | ScopedContextCreator ContextCreator(*this, tok::less, 10); | |||
47 | FormatToken *Left = CurrentToken->Previous; | |||
48 | Contexts.back().IsExpression = false; | |||
49 | // If there's a template keyword before the opening angle bracket, this is a | |||
50 | // template parameter, not an argument. | |||
51 | Contexts.back().InTemplateArgument = | |||
52 | Left->Previous && Left->Previous->Tok.isNot(tok::kw_template); | |||
53 | ||||
54 | if (Style.Language == FormatStyle::LK_Java && | |||
55 | CurrentToken->is(tok::question)) | |||
56 | next(); | |||
57 | ||||
58 | while (CurrentToken) { | |||
59 | if (CurrentToken->is(tok::greater)) { | |||
60 | Left->MatchingParen = CurrentToken; | |||
61 | CurrentToken->MatchingParen = Left; | |||
62 | CurrentToken->Type = TT_TemplateCloser; | |||
63 | next(); | |||
64 | return true; | |||
65 | } | |||
66 | if (CurrentToken->is(tok::question) && | |||
67 | Style.Language == FormatStyle::LK_Java) { | |||
68 | next(); | |||
69 | continue; | |||
70 | } | |||
71 | if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace, | |||
72 | tok::colon, tok::question)) | |||
73 | return false; | |||
74 | // If a && or || is found and interpreted as a binary operator, this set | |||
75 | // of angles is likely part of something like "a < b && c > d". If the | |||
76 | // angles are inside an expression, the ||/&& might also be a binary | |||
77 | // operator that was misinterpreted because we are parsing template | |||
78 | // parameters. | |||
79 | // FIXME: This is getting out of hand, write a decent parser. | |||
80 | if (CurrentToken->Previous->isOneOf(tok::pipepipe, tok::ampamp) && | |||
81 | CurrentToken->Previous->is(TT_BinaryOperator) && | |||
82 | Contexts[Contexts.size() - 2].IsExpression && | |||
83 | Line.First->isNot(tok::kw_template)) | |||
84 | return false; | |||
85 | updateParameterCount(Left, CurrentToken); | |||
86 | if (!consumeToken()) | |||
87 | return false; | |||
88 | } | |||
89 | return false; | |||
90 | } | |||
91 | ||||
92 | bool parseParens(bool LookForDecls = false) { | |||
93 | if (!CurrentToken) | |||
94 | return false; | |||
95 | ScopedContextCreator ContextCreator(*this, tok::l_paren, 1); | |||
96 | ||||
97 | // FIXME: This is a bit of a hack. Do better. | |||
98 | Contexts.back().ColonIsForRangeExpr = | |||
99 | Contexts.size() == 2 && Contexts[0].ColonIsForRangeExpr; | |||
100 | ||||
101 | bool StartsObjCMethodExpr = false; | |||
102 | FormatToken *Left = CurrentToken->Previous; | |||
103 | if (CurrentToken->is(tok::caret)) { | |||
104 | // (^ can start a block type. | |||
105 | Left->Type = TT_ObjCBlockLParen; | |||
106 | } else if (FormatToken *MaybeSel = Left->Previous) { | |||
107 | // @selector( starts a selector. | |||
108 | if (MaybeSel->isObjCAtKeyword(tok::objc_selector) && MaybeSel->Previous && | |||
109 | MaybeSel->Previous->is(tok::at)) { | |||
110 | StartsObjCMethodExpr = true; | |||
111 | } | |||
112 | } | |||
113 | ||||
114 | if (Left->Previous && | |||
115 | (Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_if, | |||
116 | tok::kw_while, tok::l_paren, tok::comma) || | |||
117 | Left->Previous->is(TT_BinaryOperator))) { | |||
118 | // static_assert, if and while usually contain expressions. | |||
119 | Contexts.back().IsExpression = true; | |||
120 | } else if (Line.InPPDirective && | |||
121 | (!Left->Previous || | |||
122 | !Left->Previous->isOneOf(tok::identifier, | |||
123 | TT_OverloadedOperator))) { | |||
124 | Contexts.back().IsExpression = true; | |||
125 | } else if (Left->Previous && Left->Previous->is(tok::r_square) && | |||
126 | Left->Previous->MatchingParen && | |||
127 | Left->Previous->MatchingParen->is(TT_LambdaLSquare)) { | |||
128 | // This is a parameter list of a lambda expression. | |||
129 | Contexts.back().IsExpression = false; | |||
130 | } else if (Contexts[Contexts.size() - 2].CaretFound) { | |||
131 | // This is the parameter list of an ObjC block. | |||
132 | Contexts.back().IsExpression = false; | |||
133 | } else if (Left->Previous && Left->Previous->is(tok::kw___attribute)) { | |||
134 | Left->Type = TT_AttributeParen; | |||
135 | } else if (Left->Previous && Left->Previous->IsForEachMacro) { | |||
136 | // The first argument to a foreach macro is a declaration. | |||
137 | Contexts.back().IsForEachMacro = true; | |||
138 | Contexts.back().IsExpression = false; | |||
139 | } else if (Left->Previous && Left->Previous->MatchingParen && | |||
140 | Left->Previous->MatchingParen->is(TT_ObjCBlockLParen)) { | |||
141 | Contexts.back().IsExpression = false; | |||
142 | } | |||
143 | ||||
144 | if (StartsObjCMethodExpr) { | |||
145 | Contexts.back().ColonIsObjCMethodExpr = true; | |||
146 | Left->Type = TT_ObjCMethodExpr; | |||
147 | } | |||
148 | ||||
149 | bool MightBeFunctionType = CurrentToken->is(tok::star); | |||
150 | bool HasMultipleLines = false; | |||
151 | bool HasMultipleParametersOnALine = false; | |||
152 | while (CurrentToken) { | |||
153 | // LookForDecls is set when "if (" has been seen. Check for | |||
154 | // 'identifier' '*' 'identifier' followed by not '=' -- this | |||
155 | // '*' has to be a binary operator but determineStarAmpUsage() will | |||
156 | // categorize it as an unary operator, so set the right type here. | |||
157 | if (LookForDecls && CurrentToken->Next) { | |||
158 | FormatToken *Prev = CurrentToken->getPreviousNonComment(); | |||
159 | if (Prev) { | |||
160 | FormatToken *PrevPrev = Prev->getPreviousNonComment(); | |||
161 | FormatToken *Next = CurrentToken->Next; | |||
162 | if (PrevPrev && PrevPrev->is(tok::identifier) && | |||
163 | Prev->isOneOf(tok::star, tok::amp, tok::ampamp) && | |||
164 | CurrentToken->is(tok::identifier) && Next->isNot(tok::equal)) { | |||
165 | Prev->Type = TT_BinaryOperator; | |||
166 | LookForDecls = false; | |||
167 | } | |||
168 | } | |||
169 | } | |||
170 | ||||
171 | if (CurrentToken->Previous->is(TT_PointerOrReference) && | |||
172 | CurrentToken->Previous->Previous->isOneOf(tok::l_paren, | |||
173 | tok::coloncolon)) | |||
174 | MightBeFunctionType = true; | |||
175 | if (CurrentToken->Previous->is(TT_BinaryOperator)) | |||
176 | Contexts.back().IsExpression = true; | |||
177 | if (CurrentToken->is(tok::r_paren)) { | |||
178 | if (MightBeFunctionType && CurrentToken->Next && | |||
179 | (CurrentToken->Next->is(tok::l_paren) || | |||
180 | (CurrentToken->Next->is(tok::l_square) && | |||
181 | !Contexts.back().IsExpression))) | |||
182 | Left->Type = TT_FunctionTypeLParen; | |||
183 | Left->MatchingParen = CurrentToken; | |||
184 | CurrentToken->MatchingParen = Left; | |||
185 | ||||
186 | if (StartsObjCMethodExpr) { | |||
187 | CurrentToken->Type = TT_ObjCMethodExpr; | |||
188 | if (Contexts.back().FirstObjCSelectorName) { | |||
189 | Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = | |||
190 | Contexts.back().LongestObjCSelectorName; | |||
191 | } | |||
192 | } | |||
193 | ||||
194 | if (Left->is(TT_AttributeParen)) | |||
195 | CurrentToken->Type = TT_AttributeParen; | |||
196 | if (Left->Previous && Left->Previous->is(TT_JavaAnnotation)) | |||
197 | CurrentToken->Type = TT_JavaAnnotation; | |||
198 | if (Left->Previous && Left->Previous->is(TT_LeadingJavaAnnotation)) | |||
199 | CurrentToken->Type = TT_LeadingJavaAnnotation; | |||
200 | ||||
201 | if (!HasMultipleLines) | |||
202 | Left->PackingKind = PPK_Inconclusive; | |||
203 | else if (HasMultipleParametersOnALine) | |||
204 | Left->PackingKind = PPK_BinPacked; | |||
205 | else | |||
206 | Left->PackingKind = PPK_OnePerLine; | |||
207 | ||||
208 | next(); | |||
209 | return true; | |||
210 | } | |||
211 | if (CurrentToken->isOneOf(tok::r_square, tok::r_brace)) | |||
212 | return false; | |||
213 | else if (CurrentToken->is(tok::l_brace)) | |||
214 | Left->Type = TT_Unknown; // Not TT_ObjCBlockLParen | |||
215 | if (CurrentToken->is(tok::comma) && CurrentToken->Next && | |||
216 | !CurrentToken->Next->HasUnescapedNewline && | |||
217 | !CurrentToken->Next->isTrailingComment()) | |||
218 | HasMultipleParametersOnALine = true; | |||
219 | if (CurrentToken->isOneOf(tok::kw_const, tok::kw_auto) || | |||
220 | CurrentToken->isSimpleTypeSpecifier()) | |||
221 | Contexts.back().IsExpression = false; | |||
222 | FormatToken *Tok = CurrentToken; | |||
223 | if (!consumeToken()) | |||
224 | return false; | |||
225 | updateParameterCount(Left, Tok); | |||
226 | if (CurrentToken && CurrentToken->HasUnescapedNewline) | |||
227 | HasMultipleLines = true; | |||
228 | } | |||
229 | return false; | |||
230 | } | |||
231 | ||||
232 | bool parseSquare() { | |||
233 | if (!CurrentToken) | |||
234 | return false; | |||
235 | ||||
236 | // A '[' could be an index subscript (after an identifier or after | |||
237 | // ')' or ']'), it could be the start of an Objective-C method | |||
238 | // expression, or it could the the start of an Objective-C array literal. | |||
239 | FormatToken *Left = CurrentToken->Previous; | |||
240 | FormatToken *Parent = Left->getPreviousNonComment(); | |||
241 | bool StartsObjCMethodExpr = | |||
242 | Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) && | |||
243 | CurrentToken->isNot(tok::l_brace) && | |||
244 | (!Parent || | |||
245 | Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren, | |||
246 | tok::kw_return, tok::kw_throw) || | |||
247 | Parent->isUnaryOperator() || | |||
248 | Parent->isOneOf(TT_ObjCForIn, TT_CastRParen) || | |||
249 | getBinOpPrecedence(Parent->Tok.getKind(), true, true) > prec::Unknown); | |||
250 | ScopedContextCreator ContextCreator(*this, tok::l_square, 10); | |||
251 | Contexts.back().IsExpression = true; | |||
252 | bool ColonFound = false; | |||
253 | ||||
254 | if (StartsObjCMethodExpr) { | |||
255 | Contexts.back().ColonIsObjCMethodExpr = true; | |||
256 | Left->Type = TT_ObjCMethodExpr; | |||
257 | } else if (Parent && Parent->is(tok::at)) { | |||
258 | Left->Type = TT_ArrayInitializerLSquare; | |||
259 | } else if (Left->is(TT_Unknown)) { | |||
260 | Left->Type = TT_ArraySubscriptLSquare; | |||
261 | } | |||
262 | ||||
263 | while (CurrentToken) { | |||
264 | if (CurrentToken->is(tok::r_square)) { | |||
265 | if (CurrentToken->Next && CurrentToken->Next->is(tok::l_paren) && | |||
266 | Left->is(TT_ObjCMethodExpr)) { | |||
267 | // An ObjC method call is rarely followed by an open parenthesis. | |||
268 | // FIXME: Do we incorrectly label ":" with this? | |||
269 | StartsObjCMethodExpr = false; | |||
270 | Left->Type = TT_Unknown; | |||
271 | } | |||
272 | if (StartsObjCMethodExpr && CurrentToken->Previous != Left) { | |||
273 | CurrentToken->Type = TT_ObjCMethodExpr; | |||
274 | // determineStarAmpUsage() thinks that '*' '[' is allocating an | |||
275 | // array of pointers, but if '[' starts a selector then '*' is a | |||
276 | // binary operator. | |||
277 | if (Parent && Parent->is(TT_PointerOrReference)) | |||
278 | Parent->Type = TT_BinaryOperator; | |||
279 | } | |||
280 | Left->MatchingParen = CurrentToken; | |||
281 | CurrentToken->MatchingParen = Left; | |||
282 | if (Contexts.back().FirstObjCSelectorName) { | |||
283 | Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = | |||
284 | Contexts.back().LongestObjCSelectorName; | |||
285 | if (Left->BlockParameterCount > 1) | |||
286 | Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = 0; | |||
287 | } | |||
288 | next(); | |||
289 | return true; | |||
290 | } | |||
291 | if (CurrentToken->isOneOf(tok::r_paren, tok::r_brace)) | |||
292 | return false; | |||
293 | if (CurrentToken->is(tok::colon)) { | |||
294 | if (Left->is(TT_ArraySubscriptLSquare)) { | |||
295 | Left->Type = TT_ObjCMethodExpr; | |||
296 | StartsObjCMethodExpr = true; | |||
297 | Contexts.back().ColonIsObjCMethodExpr = true; | |||
298 | if (Parent && Parent->is(tok::r_paren)) | |||
299 | Parent->Type = TT_CastRParen; | |||
300 | } | |||
301 | ColonFound = true; | |||
302 | } | |||
303 | if (CurrentToken->is(tok::comma) && | |||
304 | Style.Language != FormatStyle::LK_Proto && | |||
305 | (Left->is(TT_ArraySubscriptLSquare) || | |||
306 | (Left->is(TT_ObjCMethodExpr) && !ColonFound))) | |||
307 | Left->Type = TT_ArrayInitializerLSquare; | |||
308 | FormatToken* Tok = CurrentToken; | |||
309 | if (!consumeToken()) | |||
310 | return false; | |||
311 | updateParameterCount(Left, Tok); | |||
312 | } | |||
313 | return false; | |||
314 | } | |||
315 | ||||
316 | bool parseBrace() { | |||
317 | if (CurrentToken) { | |||
318 | FormatToken *Left = CurrentToken->Previous; | |||
319 | ||||
320 | if (Contexts.back().CaretFound) | |||
321 | Left->Type = TT_ObjCBlockLBrace; | |||
322 | Contexts.back().CaretFound = false; | |||
323 | ||||
324 | ScopedContextCreator ContextCreator(*this, tok::l_brace, 1); | |||
325 | Contexts.back().ColonIsDictLiteral = true; | |||
326 | if (Left->BlockKind == BK_BracedInit) | |||
327 | Contexts.back().IsExpression = true; | |||
328 | ||||
329 | while (CurrentToken) { | |||
330 | if (CurrentToken->is(tok::r_brace)) { | |||
331 | Left->MatchingParen = CurrentToken; | |||
332 | CurrentToken->MatchingParen = Left; | |||
333 | next(); | |||
334 | return true; | |||
335 | } | |||
336 | if (CurrentToken->isOneOf(tok::r_paren, tok::r_square)) | |||
337 | return false; | |||
338 | updateParameterCount(Left, CurrentToken); | |||
339 | if (CurrentToken->isOneOf(tok::colon, tok::l_brace)) { | |||
340 | FormatToken *Previous = CurrentToken->getPreviousNonComment(); | |||
341 | if ((CurrentToken->is(tok::colon) || | |||
342 | Style.Language == FormatStyle::LK_Proto) && | |||
343 | Previous->is(tok::identifier)) | |||
344 | Previous->Type = TT_SelectorName; | |||
345 | if (CurrentToken->is(tok::colon)) | |||
346 | Left->Type = TT_DictLiteral; | |||
347 | } | |||
348 | if (!consumeToken()) | |||
349 | return false; | |||
350 | } | |||
351 | } | |||
352 | return true; | |||
353 | } | |||
354 | ||||
355 | void updateParameterCount(FormatToken *Left, FormatToken *Current) { | |||
356 | if (Current->is(TT_LambdaLSquare) || | |||
357 | (Current->is(tok::caret) && Current->is(TT_UnaryOperator)) || | |||
358 | (Style.Language == FormatStyle::LK_JavaScript && | |||
359 | Current->is(Keywords.kw_function))) { | |||
360 | ++Left->BlockParameterCount; | |||
361 | } | |||
362 | if (Current->is(tok::comma)) { | |||
363 | ++Left->ParameterCount; | |||
364 | if (!Left->Role) | |||
365 | Left->Role.reset(new CommaSeparatedList(Style)); | |||
366 | Left->Role->CommaFound(Current); | |||
367 | } else if (Left->ParameterCount == 0 && Current->isNot(tok::comment)) { | |||
368 | Left->ParameterCount = 1; | |||
369 | } | |||
370 | } | |||
371 | ||||
372 | bool parseConditional() { | |||
373 | while (CurrentToken) { | |||
374 | if (CurrentToken->is(tok::colon)) { | |||
375 | CurrentToken->Type = TT_ConditionalExpr; | |||
376 | next(); | |||
377 | return true; | |||
378 | } | |||
379 | if (!consumeToken()) | |||
380 | return false; | |||
381 | } | |||
382 | return false; | |||
383 | } | |||
384 | ||||
385 | bool parseTemplateDeclaration() { | |||
386 | if (CurrentToken && CurrentToken->is(tok::less)) { | |||
387 | CurrentToken->Type = TT_TemplateOpener; | |||
388 | next(); | |||
389 | if (!parseAngle()) | |||
390 | return false; | |||
391 | if (CurrentToken) | |||
392 | CurrentToken->Previous->ClosesTemplateDeclaration = true; | |||
393 | return true; | |||
394 | } | |||
395 | return false; | |||
396 | } | |||
397 | ||||
398 | bool consumeToken() { | |||
399 | FormatToken *Tok = CurrentToken; | |||
400 | next(); | |||
401 | switch (Tok->Tok.getKind()) { | |||
402 | case tok::plus: | |||
403 | case tok::minus: | |||
404 | if (!Tok->Previous && Line.MustBeDeclaration) | |||
405 | Tok->Type = TT_ObjCMethodSpecifier; | |||
406 | break; | |||
407 | case tok::colon: | |||
408 | if (!Tok->Previous) | |||
409 | return false; | |||
410 | // Colons from ?: are handled in parseConditional(). | |||
411 | if (Tok->Previous->is(tok::r_paren) && Contexts.size() == 1 && | |||
412 | Line.First->isNot(tok::kw_case)) { | |||
413 | Tok->Type = TT_CtorInitializerColon; | |||
414 | } else if (Contexts.back().ColonIsDictLiteral) { | |||
415 | Tok->Type = TT_DictLiteral; | |||
416 | } else if (Contexts.back().ColonIsObjCMethodExpr || | |||
417 | Line.First->is(TT_ObjCMethodSpecifier)) { | |||
418 | Tok->Type = TT_ObjCMethodExpr; | |||
419 | Tok->Previous->Type = TT_SelectorName; | |||
420 | if (Tok->Previous->ColumnWidth > | |||
421 | Contexts.back().LongestObjCSelectorName) { | |||
422 | Contexts.back().LongestObjCSelectorName = Tok->Previous->ColumnWidth; | |||
423 | } | |||
424 | if (!Contexts.back().FirstObjCSelectorName) | |||
425 | Contexts.back().FirstObjCSelectorName = Tok->Previous; | |||
426 | } else if (Contexts.back().ColonIsForRangeExpr) { | |||
427 | Tok->Type = TT_RangeBasedForLoopColon; | |||
428 | } else if (CurrentToken && CurrentToken->is(tok::numeric_constant)) { | |||
429 | Tok->Type = TT_BitFieldColon; | |||
430 | } else if (Contexts.size() == 1 && | |||
431 | !Line.First->isOneOf(tok::kw_enum, tok::kw_case)) { | |||
432 | Tok->Type = TT_InheritanceColon; | |||
433 | } else if (Tok->Previous->is(tok::identifier) && Tok->Next && | |||
434 | Tok->Next->isOneOf(tok::r_paren, tok::comma)) { | |||
435 | // This handles a special macro in ObjC code where selectors including | |||
436 | // the colon are passed as macro arguments. | |||
437 | Tok->Type = TT_ObjCMethodExpr; | |||
438 | } else if (Contexts.back().ContextKind == tok::l_paren) { | |||
439 | Tok->Type = TT_InlineASMColon; | |||
440 | } | |||
441 | break; | |||
442 | case tok::kw_if: | |||
443 | case tok::kw_while: | |||
444 | if (CurrentToken && CurrentToken->is(tok::l_paren)) { | |||
445 | next(); | |||
446 | if (!parseParens(/*LookForDecls=*/true)) | |||
447 | return false; | |||
448 | } | |||
449 | break; | |||
450 | case tok::kw_for: | |||
451 | Contexts.back().ColonIsForRangeExpr = true; | |||
452 | next(); | |||
453 | if (!parseParens()) | |||
454 | return false; | |||
455 | break; | |||
456 | case tok::l_paren: | |||
457 | if (!parseParens()) | |||
458 | return false; | |||
459 | if (Line.MustBeDeclaration && Contexts.size() == 1 && | |||
460 | !Contexts.back().IsExpression && Line.First->isNot(TT_ObjCProperty) && | |||
461 | (!Tok->Previous || Tok->Previous->isNot(tok::kw_decltype))) | |||
462 | Line.MightBeFunctionDecl = true; | |||
463 | break; | |||
464 | case tok::l_square: | |||
465 | if (!parseSquare()) | |||
466 | return false; | |||
467 | break; | |||
468 | case tok::l_brace: | |||
469 | if (!parseBrace()) | |||
470 | return false; | |||
471 | break; | |||
472 | case tok::less: | |||
473 | if ((!Tok->Previous || !Tok->Previous->Tok.isLiteral()) && parseAngle()) | |||
474 | Tok->Type = TT_TemplateOpener; | |||
475 | else { | |||
476 | Tok->Type = TT_BinaryOperator; | |||
477 | CurrentToken = Tok; | |||
478 | next(); | |||
479 | } | |||
480 | break; | |||
481 | case tok::r_paren: | |||
482 | case tok::r_square: | |||
483 | return false; | |||
484 | case tok::r_brace: | |||
485 | // Lines can start with '}'. | |||
486 | if (Tok->Previous) | |||
487 | return false; | |||
488 | break; | |||
489 | case tok::greater: | |||
490 | Tok->Type = TT_BinaryOperator; | |||
491 | break; | |||
492 | case tok::kw_operator: | |||
493 | while (CurrentToken && | |||
494 | !CurrentToken->isOneOf(tok::l_paren, tok::semi, tok::r_paren)) { | |||
495 | if (CurrentToken->isOneOf(tok::star, tok::amp)) | |||
496 | CurrentToken->Type = TT_PointerOrReference; | |||
497 | consumeToken(); | |||
498 | if (CurrentToken && CurrentToken->Previous->is(TT_BinaryOperator)) | |||
499 | CurrentToken->Previous->Type = TT_OverloadedOperator; | |||
500 | } | |||
501 | if (CurrentToken) { | |||
502 | CurrentToken->Type = TT_OverloadedOperatorLParen; | |||
503 | if (CurrentToken->Previous->is(TT_BinaryOperator)) | |||
504 | CurrentToken->Previous->Type = TT_OverloadedOperator; | |||
505 | } | |||
506 | break; | |||
507 | case tok::question: | |||
508 | parseConditional(); | |||
509 | break; | |||
510 | case tok::kw_template: | |||
511 | parseTemplateDeclaration(); | |||
512 | break; | |||
513 | case tok::identifier: | |||
514 | if (Line.First->is(tok::kw_for) && Tok->is(Keywords.kw_in)) | |||
515 | Tok->Type = TT_ObjCForIn; | |||
516 | break; | |||
517 | case tok::comma: | |||
518 | if (Contexts.back().FirstStartOfName) | |||
519 | Contexts.back().FirstStartOfName->PartOfMultiVariableDeclStmt = true; | |||
520 | if (Contexts.back().InCtorInitializer) | |||
521 | Tok->Type = TT_CtorInitializerComma; | |||
522 | if (Contexts.back().IsForEachMacro) | |||
523 | Contexts.back().IsExpression = true; | |||
524 | break; | |||
525 | default: | |||
526 | break; | |||
527 | } | |||
528 | return true; | |||
529 | } | |||
530 | ||||
531 | void parseIncludeDirective() { | |||
532 | if (CurrentToken && CurrentToken->is(tok::less)) { | |||
533 | next(); | |||
534 | while (CurrentToken) { | |||
535 | if (CurrentToken->isNot(tok::comment) || CurrentToken->Next) | |||
536 | CurrentToken->Type = TT_ImplicitStringLiteral; | |||
537 | next(); | |||
538 | } | |||
539 | } | |||
540 | } | |||
541 | ||||
542 | void parseWarningOrError() { | |||
543 | next(); | |||
544 | // We still want to format the whitespace left of the first token of the | |||
545 | // warning or error. | |||
546 | next(); | |||
547 | while (CurrentToken) { | |||
548 | CurrentToken->Type = TT_ImplicitStringLiteral; | |||
549 | next(); | |||
550 | } | |||
551 | } | |||
552 | ||||
553 | void parsePragma() { | |||
554 | next(); // Consume "pragma". | |||
555 | if (CurrentToken && CurrentToken->TokenText == "mark") { | |||
556 | next(); // Consume "mark". | |||
557 | next(); // Consume first token (so we fix leading whitespace). | |||
558 | while (CurrentToken) { | |||
559 | CurrentToken->Type = TT_ImplicitStringLiteral; | |||
560 | next(); | |||
561 | } | |||
562 | } | |||
563 | } | |||
564 | ||||
565 | LineType parsePreprocessorDirective() { | |||
566 | LineType Type = LT_PreprocessorDirective; | |||
567 | next(); | |||
568 | if (!CurrentToken) | |||
569 | return Type; | |||
570 | if (CurrentToken->Tok.is(tok::numeric_constant)) { | |||
571 | CurrentToken->SpacesRequiredBefore = 1; | |||
572 | return Type; | |||
573 | } | |||
574 | // Hashes in the middle of a line can lead to any strange token | |||
575 | // sequence. | |||
576 | if (!CurrentToken->Tok.getIdentifierInfo()) | |||
577 | return Type; | |||
578 | switch (CurrentToken->Tok.getIdentifierInfo()->getPPKeywordID()) { | |||
579 | case tok::pp_include: | |||
580 | case tok::pp_import: | |||
581 | next(); | |||
582 | parseIncludeDirective(); | |||
583 | Type = LT_ImportStatement; | |||
584 | break; | |||
585 | case tok::pp_error: | |||
586 | case tok::pp_warning: | |||
587 | parseWarningOrError(); | |||
588 | break; | |||
589 | case tok::pp_pragma: | |||
590 | parsePragma(); | |||
591 | break; | |||
592 | case tok::pp_if: | |||
593 | case tok::pp_elif: | |||
594 | Contexts.back().IsExpression = true; | |||
595 | parseLine(); | |||
596 | break; | |||
597 | default: | |||
598 | break; | |||
599 | } | |||
600 | while (CurrentToken) | |||
601 | next(); | |||
602 | return Type; | |||
603 | } | |||
604 | ||||
605 | public: | |||
606 | LineType parseLine() { | |||
607 | if (CurrentToken->is(tok::hash)) { | |||
608 | return parsePreprocessorDirective(); | |||
609 | } | |||
610 | ||||
611 | // Directly allow to 'import <string-literal>' to support protocol buffer | |||
612 | // definitions (code.google.com/p/protobuf) or missing "#" (either way we | |||
613 | // should not break the line). | |||
614 | IdentifierInfo *Info = CurrentToken->Tok.getIdentifierInfo(); | |||
615 | if ((Style.Language == FormatStyle::LK_Java && | |||
616 | CurrentToken->is(Keywords.kw_package)) || | |||
617 | (Info && Info->getPPKeywordID() == tok::pp_import && | |||
618 | CurrentToken->Next)) { | |||
619 | next(); | |||
620 | parseIncludeDirective(); | |||
621 | return LT_ImportStatement; | |||
622 | } | |||
623 | ||||
624 | // If this line starts and ends in '<' and '>', respectively, it is likely | |||
625 | // part of "#define <a/b.h>". | |||
626 | if (CurrentToken->is(tok::less) && Line.Last->is(tok::greater)) { | |||
627 | parseIncludeDirective(); | |||
628 | return LT_ImportStatement; | |||
629 | } | |||
630 | ||||
631 | bool KeywordVirtualFound = false; | |||
632 | bool ImportStatement = false; | |||
633 | while (CurrentToken) { | |||
634 | if (CurrentToken->is(tok::kw_virtual)) | |||
635 | KeywordVirtualFound = true; | |||
636 | if (IsImportStatement(*CurrentToken)) | |||
637 | ImportStatement = true; | |||
638 | if (!consumeToken()) | |||
639 | return LT_Invalid; | |||
640 | } | |||
641 | if (KeywordVirtualFound) | |||
642 | return LT_VirtualFunctionDecl; | |||
643 | if (ImportStatement) | |||
644 | return LT_ImportStatement; | |||
645 | ||||
646 | if (Line.First->is(TT_ObjCMethodSpecifier)) { | |||
647 | if (Contexts.back().FirstObjCSelectorName) | |||
648 | Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName = | |||
649 | Contexts.back().LongestObjCSelectorName; | |||
650 | return LT_ObjCMethodDecl; | |||
651 | } | |||
652 | ||||
653 | return LT_Other; | |||
654 | } | |||
655 | ||||
656 | private: | |||
657 | bool IsImportStatement(const FormatToken &Tok) { | |||
658 | // FIXME: Closure-library specific stuff should not be hard-coded but be | |||
659 | // configurable. | |||
660 | return Style.Language == FormatStyle::LK_JavaScript && | |||
661 | Tok.TokenText == "goog" && Tok.Next && Tok.Next->is(tok::period) && | |||
662 | Tok.Next->Next && (Tok.Next->Next->TokenText == "module" || | |||
663 | Tok.Next->Next->TokenText == "require" || | |||
664 | Tok.Next->Next->TokenText == "provide") && | |||
665 | Tok.Next->Next->Next && Tok.Next->Next->Next->is(tok::l_paren); | |||
666 | } | |||
667 | ||||
668 | void resetTokenMetadata(FormatToken *Token) { | |||
669 | if (!Token) | |||
670 | return; | |||
671 | ||||
672 | // Reset token type in case we have already looked at it and then | |||
673 | // recovered from an error (e.g. failure to find the matching >). | |||
674 | if (!CurrentToken->isOneOf(TT_LambdaLSquare, TT_FunctionLBrace, | |||
675 | TT_ImplicitStringLiteral, TT_RegexLiteral, | |||
676 | TT_TrailingReturnArrow)) | |||
677 | CurrentToken->Type = TT_Unknown; | |||
678 | CurrentToken->Role.reset(); | |||
679 | CurrentToken->FakeLParens.clear(); | |||
680 | CurrentToken->FakeRParens = 0; | |||
681 | } | |||
682 | ||||
683 | void next() { | |||
684 | if (CurrentToken) { | |||
685 | CurrentToken->NestingLevel = Contexts.size() - 1; | |||
686 | CurrentToken->BindingStrength = Contexts.back().BindingStrength; | |||
687 | modifyContext(*CurrentToken); | |||
688 | determineTokenType(*CurrentToken); | |||
689 | CurrentToken = CurrentToken->Next; | |||
690 | } | |||
691 | ||||
692 | resetTokenMetadata(CurrentToken); | |||
693 | } | |||
694 | ||||
695 | /// \brief A struct to hold information valid in a specific context, e.g. | |||
696 | /// a pair of parenthesis. | |||
697 | struct Context { | |||
698 | Context(tok::TokenKind ContextKind, unsigned BindingStrength, | |||
699 | bool IsExpression) | |||
700 | : ContextKind(ContextKind), BindingStrength(BindingStrength), | |||
701 | LongestObjCSelectorName(0), ColonIsForRangeExpr(false), | |||
702 | ColonIsDictLiteral(false), ColonIsObjCMethodExpr(false), | |||
703 | FirstObjCSelectorName(nullptr), FirstStartOfName(nullptr), | |||
704 | IsExpression(IsExpression), CanBeExpression(true), | |||
705 | InTemplateArgument(false), InCtorInitializer(false), | |||
706 | CaretFound(false), IsForEachMacro(false) {} | |||
707 | ||||
708 | tok::TokenKind ContextKind; | |||
709 | unsigned BindingStrength; | |||
710 | unsigned LongestObjCSelectorName; | |||
711 | bool ColonIsForRangeExpr; | |||
712 | bool ColonIsDictLiteral; | |||
713 | bool ColonIsObjCMethodExpr; | |||
714 | FormatToken *FirstObjCSelectorName; | |||
715 | FormatToken *FirstStartOfName; | |||
716 | bool IsExpression; | |||
717 | bool CanBeExpression; | |||
718 | bool InTemplateArgument; | |||
719 | bool InCtorInitializer; | |||
720 | bool CaretFound; | |||
721 | bool IsForEachMacro; | |||
722 | }; | |||
723 | ||||
724 | /// \brief Puts a new \c Context onto the stack \c Contexts for the lifetime | |||
725 | /// of each instance. | |||
726 | struct ScopedContextCreator { | |||
727 | AnnotatingParser &P; | |||
728 | ||||
729 | ScopedContextCreator(AnnotatingParser &P, tok::TokenKind ContextKind, | |||
730 | unsigned Increase) | |||
731 | : P(P) { | |||
732 | P.Contexts.push_back(Context(ContextKind, | |||
733 | P.Contexts.back().BindingStrength + Increase, | |||
734 | P.Contexts.back().IsExpression)); | |||
735 | } | |||
736 | ||||
737 | ~ScopedContextCreator() { P.Contexts.pop_back(); } | |||
738 | }; | |||
739 | ||||
740 | void modifyContext(const FormatToken &Current) { | |||
741 | if (Current.getPrecedence() == prec::Assignment && | |||
742 | !Line.First->isOneOf(tok::kw_template, tok::kw_using) && | |||
743 | (!Current.Previous || Current.Previous->isNot(tok::kw_operator))) { | |||
744 | Contexts.back().IsExpression = true; | |||
745 | for (FormatToken *Previous = Current.Previous; | |||
746 | Previous && !Previous->isOneOf(tok::comma, tok::semi); | |||
747 | Previous = Previous->Previous) { | |||
748 | if (Previous->isOneOf(tok::r_square, tok::r_paren)) { | |||
749 | Previous = Previous->MatchingParen; | |||
750 | if (!Previous) | |||
751 | break; | |||
752 | } | |||
753 | if ((Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator)) && | |||
754 | Previous->isOneOf(tok::star, tok::amp) && Previous->Previous && | |||
755 | Previous->Previous->isNot(tok::equal)) { | |||
756 | Previous->Type = TT_PointerOrReference; | |||
757 | } | |||
758 | } | |||
759 | } else if (Current.isOneOf(tok::kw_return, tok::kw_throw)) { | |||
760 | Contexts.back().IsExpression = true; | |||
761 | } else if (Current.is(TT_TrailingReturnArrow)) { | |||
762 | Contexts.back().IsExpression = false; | |||
763 | } else if (Current.is(tok::l_paren) && !Line.MustBeDeclaration && | |||
764 | !Line.InPPDirective && | |||
765 | (!Current.Previous || | |||
766 | Current.Previous->isNot(tok::kw_decltype))) { | |||
767 | bool ParametersOfFunctionType = | |||
768 | Current.Previous && Current.Previous->is(tok::r_paren) && | |||
769 | Current.Previous->MatchingParen && | |||
770 | Current.Previous->MatchingParen->is(TT_FunctionTypeLParen); | |||
771 | bool IsForOrCatch = Current.Previous && | |||
772 | Current.Previous->isOneOf(tok::kw_for, tok::kw_catch); | |||
773 | Contexts.back().IsExpression = !ParametersOfFunctionType && !IsForOrCatch; | |||
774 | } else if (Current.isOneOf(tok::r_paren, tok::greater, tok::comma)) { | |||
775 | for (FormatToken *Previous = Current.Previous; | |||
776 | Previous && Previous->isOneOf(tok::star, tok::amp); | |||
777 | Previous = Previous->Previous) | |||
778 | Previous->Type = TT_PointerOrReference; | |||
779 | if (Line.MustBeDeclaration) | |||
780 | Contexts.back().IsExpression = Contexts.front().InCtorInitializer; | |||
781 | } else if (Current.Previous && | |||
782 | Current.Previous->is(TT_CtorInitializerColon)) { | |||
783 | Contexts.back().IsExpression = true; | |||
784 | Contexts.back().InCtorInitializer = true; | |||
785 | } else if (Current.is(tok::kw_new)) { | |||
786 | Contexts.back().CanBeExpression = false; | |||
787 | } else if (Current.is(tok::semi) || Current.is(tok::exclaim)) { | |||
788 | // This should be the condition or increment in a for-loop. | |||
789 | Contexts.back().IsExpression = true; | |||
790 | } | |||
791 | } | |||
792 | ||||
793 | void determineTokenType(FormatToken &Current) { | |||
794 | if (!Current.is(TT_Unknown)) | |||
795 | // The token type is already known. | |||
796 | return; | |||
797 | ||||
798 | // Line.MightBeFunctionDecl can only be true after the parentheses of a | |||
799 | // function declaration have been found. In this case, 'Current' is a | |||
800 | // trailing token of this declaration and thus cannot be a name. | |||
801 | if (Current.is(Keywords.kw_instanceof)) { | |||
802 | Current.Type = TT_BinaryOperator; | |||
803 | } else if (isStartOfName(Current) && | |||
804 | (!Line.MightBeFunctionDecl || Current.NestingLevel != 0)) { | |||
805 | Contexts.back().FirstStartOfName = &Current; | |||
806 | Current.Type = TT_StartOfName; | |||
807 | } else if (Current.is(tok::kw_auto)) { | |||
808 | AutoFound = true; | |||
809 | } else if (Current.is(tok::arrow) && | |||
810 | Style.Language == FormatStyle::LK_Java) { | |||
811 | Current.Type = TT_LambdaArrow; | |||
812 | } else if (Current.is(tok::arrow) && AutoFound && Line.MustBeDeclaration && | |||
813 | Current.NestingLevel == 0) { | |||
814 | Current.Type = TT_TrailingReturnArrow; | |||
815 | } else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) { | |||
816 | Current.Type = | |||
817 | determineStarAmpUsage(Current, Contexts.back().CanBeExpression && | |||
818 | Contexts.back().IsExpression, | |||
819 | Contexts.back().InTemplateArgument); | |||
820 | } else if (Current.isOneOf(tok::minus, tok::plus, tok::caret)) { | |||
821 | Current.Type = determinePlusMinusCaretUsage(Current); | |||
822 | if (Current.is(TT_UnaryOperator) && Current.is(tok::caret)) | |||
823 | Contexts.back().CaretFound = true; | |||
824 | } else if (Current.isOneOf(tok::minusminus, tok::plusplus)) { | |||
825 | Current.Type = determineIncrementUsage(Current); | |||
826 | } else if (Current.isOneOf(tok::exclaim, tok::tilde)) { | |||
827 | Current.Type = TT_UnaryOperator; | |||
828 | } else if (Current.is(tok::question)) { | |||
829 | Current.Type = TT_ConditionalExpr; | |||
830 | } else if (Current.isBinaryOperator() && | |||
831 | (!Current.Previous || Current.Previous->isNot(tok::l_square))) { | |||
832 | Current.Type = TT_BinaryOperator; | |||
833 | } else if (Current.is(tok::comment)) { | |||
834 | if (Current.TokenText.startswith("//")) | |||
835 | Current.Type = TT_LineComment; | |||
836 | else | |||
837 | Current.Type = TT_BlockComment; | |||
838 | } else if (Current.is(tok::r_paren)) { | |||
839 | if (rParenEndsCast(Current)) | |||
840 | Current.Type = TT_CastRParen; | |||
841 | } else if (Current.is(tok::at) && Current.Next) { | |||
842 | switch (Current.Next->Tok.getObjCKeywordID()) { | |||
843 | case tok::objc_interface: | |||
844 | case tok::objc_implementation: | |||
845 | case tok::objc_protocol: | |||
846 | Current.Type = TT_ObjCDecl; | |||
847 | break; | |||
848 | case tok::objc_property: | |||
849 | Current.Type = TT_ObjCProperty; | |||
850 | break; | |||
851 | default: | |||
852 | break; | |||
853 | } | |||
854 | } else if (Current.is(tok::period)) { | |||
855 | FormatToken *PreviousNoComment = Current.getPreviousNonComment(); | |||
856 | if (PreviousNoComment && | |||
857 | PreviousNoComment->isOneOf(tok::comma, tok::l_brace)) | |||
858 | Current.Type = TT_DesignatedInitializerPeriod; | |||
859 | } else if (Current.isOneOf(tok::identifier, tok::kw_const) && | |||
860 | Current.Previous && | |||
861 | !Current.Previous->isOneOf(tok::equal, tok::at) && | |||
862 | Line.MightBeFunctionDecl && Contexts.size() == 1) { | |||
863 | // Line.MightBeFunctionDecl can only be true after the parentheses of a | |||
864 | // function declaration have been found. | |||
865 | Current.Type = TT_TrailingAnnotation; | |||
866 | } else if (Style.Language == FormatStyle::LK_Java && Current.Previous && | |||
867 | Current.Previous->is(tok::at) && | |||
868 | Current.isNot(Keywords.kw_interface)) { | |||
869 | const FormatToken &AtToken = *Current.Previous; | |||
870 | const FormatToken *Previous = AtToken.getPreviousNonComment(); | |||
871 | if (!Previous || Previous->is(TT_LeadingJavaAnnotation)) | |||
872 | Current.Type = TT_LeadingJavaAnnotation; | |||
873 | else | |||
874 | Current.Type = TT_JavaAnnotation; | |||
875 | } | |||
876 | } | |||
877 | ||||
878 | /// \brief Take a guess at whether \p Tok starts a name of a function or | |||
879 | /// variable declaration. | |||
880 | /// | |||
881 | /// This is a heuristic based on whether \p Tok is an identifier following | |||
882 | /// something that is likely a type. | |||
883 | bool isStartOfName(const FormatToken &Tok) { | |||
884 | if (Tok.isNot(tok::identifier) || !Tok.Previous) | |||
885 | return false; | |||
886 | ||||
887 | // Skip "const" as it does not have an influence on whether this is a name. | |||
888 | FormatToken *PreviousNotConst = Tok.Previous; | |||
889 | while (PreviousNotConst && PreviousNotConst->is(tok::kw_const)) | |||
890 | PreviousNotConst = PreviousNotConst->Previous; | |||
891 | ||||
892 | if (!PreviousNotConst) | |||
893 | return false; | |||
894 | ||||
895 | bool IsPPKeyword = PreviousNotConst->is(tok::identifier) && | |||
896 | PreviousNotConst->Previous && | |||
897 | PreviousNotConst->Previous->is(tok::hash); | |||
898 | ||||
899 | if (PreviousNotConst->is(TT_TemplateCloser)) | |||
900 | return PreviousNotConst && PreviousNotConst->MatchingParen && | |||
901 | PreviousNotConst->MatchingParen->Previous && | |||
902 | PreviousNotConst->MatchingParen->Previous->isNot(tok::period) && | |||
903 | PreviousNotConst->MatchingParen->Previous->isNot(tok::kw_template); | |||
904 | ||||
905 | if (PreviousNotConst->is(tok::r_paren) && PreviousNotConst->MatchingParen && | |||
906 | PreviousNotConst->MatchingParen->Previous && | |||
907 | PreviousNotConst->MatchingParen->Previous->is(tok::kw_decltype)) | |||
908 | return true; | |||
909 | ||||
910 | return (!IsPPKeyword && PreviousNotConst->is(tok::identifier)) || | |||
911 | PreviousNotConst->is(TT_PointerOrReference) || | |||
912 | PreviousNotConst->isSimpleTypeSpecifier(); | |||
913 | } | |||
914 | ||||
915 | /// \brief Determine whether ')' is ending a cast. | |||
916 | bool rParenEndsCast(const FormatToken &Tok) { | |||
917 | FormatToken *LeftOfParens = nullptr; | |||
918 | if (Tok.MatchingParen) | |||
919 | LeftOfParens = Tok.MatchingParen->getPreviousNonComment(); | |||
920 | if (LeftOfParens && LeftOfParens->is(tok::r_paren) && | |||
921 | LeftOfParens->MatchingParen) | |||
922 | LeftOfParens = LeftOfParens->MatchingParen->Previous; | |||
923 | if (LeftOfParens && LeftOfParens->is(tok::r_square) && | |||
924 | LeftOfParens->MatchingParen && | |||
925 | LeftOfParens->MatchingParen->is(TT_LambdaLSquare)) | |||
926 | return false; | |||
927 | if (Tok.Next) { | |||
928 | if (Style.Language == FormatStyle::LK_JavaScript && | |||
929 | Tok.Next->is(Keywords.kw_in)) | |||
930 | return false; | |||
931 | if (Style.Language == FormatStyle::LK_Java && Tok.Next->is(tok::l_paren)) | |||
932 | return true; | |||
933 | } | |||
934 | bool IsCast = false; | |||
935 | bool ParensAreEmpty = Tok.Previous == Tok.MatchingParen; | |||
936 | bool ParensAreType = | |||
937 | !Tok.Previous || | |||
938 | Tok.Previous->isOneOf(TT_PointerOrReference, TT_TemplateCloser) || | |||
939 | Tok.Previous->isSimpleTypeSpecifier(); | |||
940 | bool ParensCouldEndDecl = | |||
941 | Tok.Next && Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace); | |||
942 | bool IsSizeOfOrAlignOf = | |||
943 | LeftOfParens && LeftOfParens->isOneOf(tok::kw_sizeof, tok::kw_alignof); | |||
944 | if (ParensAreType && !ParensCouldEndDecl && !IsSizeOfOrAlignOf && | |||
945 | ((Contexts.size() > 1 && Contexts[Contexts.size() - 2].IsExpression) || | |||
946 | (Tok.Next && Tok.Next->isBinaryOperator()))) | |||
947 | IsCast = true; | |||
948 | else if (Tok.Next && Tok.Next->isNot(tok::string_literal) && | |||
949 | (Tok.Next->Tok.isLiteral() || | |||
950 | Tok.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof))) | |||
951 | IsCast = true; | |||
952 | // If there is an identifier after the (), it is likely a cast, unless | |||
953 | // there is also an identifier before the (). | |||
954 | else if (LeftOfParens && Tok.Next && | |||
955 | (LeftOfParens->Tok.getIdentifierInfo() == nullptr || | |||
956 | LeftOfParens->is(tok::kw_return)) && | |||
957 | !LeftOfParens->isOneOf(TT_OverloadedOperator, tok::at, | |||
958 | TT_TemplateCloser)) { | |||
959 | if (Tok.Next->isOneOf(tok::identifier, tok::numeric_constant)) { | |||
960 | IsCast = true; | |||
961 | } else { | |||
962 | // Use heuristics to recognize c style casting. | |||
963 | FormatToken *Prev = Tok.Previous; | |||
964 | if (Prev && Prev->isOneOf(tok::amp, tok::star)) | |||
965 | Prev = Prev->Previous; | |||
966 | ||||
967 | if (Prev && Tok.Next && Tok.Next->Next) { | |||
968 | bool NextIsUnary = Tok.Next->isUnaryOperator() || | |||
969 | Tok.Next->isOneOf(tok::amp, tok::star); | |||
970 | IsCast = | |||
971 | NextIsUnary && !Tok.Next->is(tok::plus) && | |||
972 | Tok.Next->Next->isOneOf(tok::identifier, tok::numeric_constant); | |||
973 | } | |||
974 | ||||
975 | for (; Prev != Tok.MatchingParen; Prev = Prev->Previous) { | |||
976 | if (!Prev || !Prev->isOneOf(tok::kw_const, tok::identifier)) { | |||
977 | IsCast = false; | |||
978 | break; | |||
979 | } | |||
980 | } | |||
981 | } | |||
982 | } | |||
983 | return IsCast && !ParensAreEmpty; | |||
984 | } | |||
985 | ||||
986 | /// \brief Return the type of the given token assuming it is * or &. | |||
987 | TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression, | |||
988 | bool InTemplateArgument) { | |||
989 | if (Style.Language == FormatStyle::LK_JavaScript) | |||
990 | return TT_BinaryOperator; | |||
991 | ||||
992 | const FormatToken *PrevToken = Tok.getPreviousNonComment(); | |||
993 | if (!PrevToken) | |||
994 | return TT_UnaryOperator; | |||
995 | ||||
996 | const FormatToken *NextToken = Tok.getNextNonComment(); | |||
997 | if (!NextToken || | |||
998 | (NextToken->is(tok::l_brace) && !NextToken->getNextNonComment())) | |||
999 | return TT_Unknown; | |||
1000 | ||||
1001 | if (PrevToken->is(tok::coloncolon)) | |||
1002 | return TT_PointerOrReference; | |||
1003 | ||||
1004 | if (PrevToken->isOneOf(tok::l_paren, tok::l_square, tok::l_brace, | |||
1005 | tok::comma, tok::semi, tok::kw_return, tok::colon, | |||
1006 | tok::equal, tok::kw_delete, tok::kw_sizeof) || | |||
1007 | PrevToken->isOneOf(TT_BinaryOperator, TT_ConditionalExpr, | |||
1008 | TT_UnaryOperator, TT_CastRParen)) | |||
1009 | return TT_UnaryOperator; | |||
1010 | ||||
1011 | if (NextToken->is(tok::l_square) && NextToken->isNot(TT_LambdaLSquare)) | |||
1012 | return TT_PointerOrReference; | |||
1013 | if (NextToken->isOneOf(tok::kw_operator, tok::comma)) | |||
1014 | return TT_PointerOrReference; | |||
1015 | ||||
1016 | if (PrevToken->is(tok::r_paren) && PrevToken->MatchingParen && | |||
1017 | PrevToken->MatchingParen->Previous && | |||
1018 | PrevToken->MatchingParen->Previous->isOneOf(tok::kw_typeof, | |||
1019 | tok::kw_decltype)) | |||
1020 | return TT_PointerOrReference; | |||
1021 | ||||
1022 | if (PrevToken->Tok.isLiteral() || | |||
1023 | PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::kw_true, | |||
1024 | tok::kw_false, tok::r_brace) || | |||
1025 | NextToken->Tok.isLiteral() || | |||
1026 | NextToken->isOneOf(tok::kw_true, tok::kw_false) || | |||
1027 | NextToken->isUnaryOperator() || | |||
1028 | // If we know we're in a template argument, there are no named | |||
1029 | // declarations. Thus, having an identifier on the right-hand side | |||
1030 | // indicates a binary operator. | |||
1031 | (InTemplateArgument && NextToken->Tok.isAnyIdentifier())) | |||
1032 | return TT_BinaryOperator; | |||
1033 | ||||
1034 | // "&&(" is quite unlikely to be two successive unary "&". | |||
1035 | if (Tok.is(tok::ampamp) && NextToken && NextToken->is(tok::l_paren)) | |||
1036 | return TT_BinaryOperator; | |||
1037 | ||||
1038 | // This catches some cases where evaluation order is used as control flow: | |||
1039 | // aaa && aaa->f(); | |||
1040 | const FormatToken *NextNextToken = NextToken->getNextNonComment(); | |||
1041 | if (NextNextToken && NextNextToken->is(tok::arrow)) | |||
1042 | return TT_BinaryOperator; | |||
1043 | ||||
1044 | // It is very unlikely that we are going to find a pointer or reference type | |||
1045 | // definition on the RHS of an assignment. | |||
1046 | if (IsExpression && !Contexts.back().CaretFound) | |||
1047 | return TT_BinaryOperator; | |||
1048 | ||||
1049 | return TT_PointerOrReference; | |||
1050 | } | |||
1051 | ||||
1052 | TokenType determinePlusMinusCaretUsage(const FormatToken &Tok) { | |||
1053 | const FormatToken *PrevToken = Tok.getPreviousNonComment(); | |||
1054 | if (!PrevToken || PrevToken->is(TT_CastRParen)) | |||
1055 | return TT_UnaryOperator; | |||
1056 | ||||
1057 | // Use heuristics to recognize unary operators. | |||
1058 | if (PrevToken->isOneOf(tok::equal, tok::l_paren, tok::comma, tok::l_square, | |||
1059 | tok::question, tok::colon, tok::kw_return, | |||
1060 | tok::kw_case, tok::at, tok::l_brace)) | |||
1061 | return TT_UnaryOperator; | |||
1062 | ||||
1063 | // There can't be two consecutive binary operators. | |||
1064 | if (PrevToken->is(TT_BinaryOperator)) | |||
1065 | return TT_UnaryOperator; | |||
1066 | ||||
1067 | // Fall back to marking the token as binary operator. | |||
1068 | return TT_BinaryOperator; | |||
1069 | } | |||
1070 | ||||
1071 | /// \brief Determine whether ++/-- are pre- or post-increments/-decrements. | |||
1072 | TokenType determineIncrementUsage(const FormatToken &Tok) { | |||
1073 | const FormatToken *PrevToken = Tok.getPreviousNonComment(); | |||
1074 | if (!PrevToken || PrevToken->is(TT_CastRParen)) | |||
1075 | return TT_UnaryOperator; | |||
1076 | if (PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::identifier)) | |||
1077 | return TT_TrailingUnaryOperator; | |||
1078 | ||||
1079 | return TT_UnaryOperator; | |||
1080 | } | |||
1081 | ||||
1082 | SmallVector<Context, 8> Contexts; | |||
1083 | ||||
1084 | const FormatStyle &Style; | |||
1085 | AnnotatedLine &Line; | |||
1086 | FormatToken *CurrentToken; | |||
1087 | bool AutoFound; | |||
1088 | const AdditionalKeywords &Keywords; | |||
1089 | }; | |||
1090 | ||||
1091 | static int PrecedenceUnaryOperator = prec::PointerToMember + 1; | |||
1092 | static int PrecedenceArrowAndPeriod = prec::PointerToMember + 2; | |||
1093 | ||||
1094 | /// \brief Parses binary expressions by inserting fake parenthesis based on | |||
1095 | /// operator precedence. | |||
1096 | class ExpressionParser { | |||
1097 | public: | |||
1098 | ExpressionParser(const FormatStyle &Style, const AdditionalKeywords &Keywords, | |||
1099 | AnnotatedLine &Line) | |||
1100 | : Style(Style), Keywords(Keywords), Current(Line.First) {} | |||
1101 | ||||
1102 | /// \brief Parse expressions with the given operatore precedence. | |||
1103 | void parse(int Precedence = 0) { | |||
1104 | // Skip 'return' and ObjC selector colons as they are not part of a binary | |||
1105 | // expression. | |||
1106 | while (Current && (Current->is(tok::kw_return) || | |||
1107 | (Current->is(tok::colon) && | |||
1108 | Current->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral)))) | |||
1109 | next(); | |||
1110 | ||||
1111 | if (!Current || Precedence > PrecedenceArrowAndPeriod) | |||
1112 | return; | |||
1113 | ||||
1114 | // Conditional expressions need to be parsed separately for proper nesting. | |||
1115 | if (Precedence == prec::Conditional) { | |||
1116 | parseConditionalExpr(); | |||
1117 | return; | |||
1118 | } | |||
1119 | ||||
1120 | // Parse unary operators, which all have a higher precedence than binary | |||
1121 | // operators. | |||
1122 | if (Precedence == PrecedenceUnaryOperator) { | |||
1123 | parseUnaryOperator(); | |||
1124 | return; | |||
1125 | } | |||
1126 | ||||
1127 | FormatToken *Start = Current; | |||
1128 | FormatToken *LatestOperator = nullptr; | |||
1129 | unsigned OperatorIndex = 0; | |||
1130 | ||||
1131 | while (Current) { | |||
1132 | // Consume operators with higher precedence. | |||
1133 | parse(Precedence + 1); | |||
1134 | ||||
1135 | int CurrentPrecedence = getCurrentPrecedence(); | |||
1136 | ||||
1137 | if (Current && Current->is(TT_SelectorName) && | |||
1138 | Precedence == CurrentPrecedence) { | |||
1139 | if (LatestOperator) | |||
1140 | addFakeParenthesis(Start, prec::Level(Precedence)); | |||
1141 | Start = Current; | |||
1142 | } | |||
1143 | ||||
1144 | // At the end of the line or when an operator with higher precedence is | |||
1145 | // found, insert fake parenthesis and return. | |||
1146 | if (!Current || (Current->closesScope() && Current->MatchingParen) || | |||
1147 | (CurrentPrecedence != -1 && CurrentPrecedence < Precedence) || | |||
1148 | (CurrentPrecedence == prec::Conditional && | |||
1149 | Precedence == prec::Assignment && Current->is(tok::colon))) { | |||
1150 | if (LatestOperator) { | |||
1151 | LatestOperator->LastOperator = true; | |||
1152 | if (Precedence == PrecedenceArrowAndPeriod) { | |||
1153 | // Call expressions don't have a binary operator precedence. | |||
1154 | addFakeParenthesis(Start, prec::Unknown); | |||
1155 | } else { | |||
1156 | addFakeParenthesis(Start, prec::Level(Precedence)); | |||
1157 | } | |||
1158 | } | |||
1159 | return; | |||
1160 | } | |||
1161 | ||||
1162 | // Consume scopes: (), [], <> and {} | |||
1163 | if (Current->opensScope()) { | |||
1164 | while (Current && !Current->closesScope()) { | |||
1165 | next(); | |||
1166 | parse(); | |||
1167 | } | |||
1168 | next(); | |||
1169 | } else { | |||
1170 | // Operator found. | |||
1171 | if (CurrentPrecedence == Precedence) { | |||
1172 | LatestOperator = Current; | |||
1173 | Current->OperatorIndex = OperatorIndex; | |||
1174 | ++OperatorIndex; | |||
1175 | } | |||
1176 | next(/*SkipPastLeadingComments=*/Precedence > 0); | |||
1177 | } | |||
1178 | } | |||
1179 | } | |||
1180 | ||||
1181 | private: | |||
1182 | /// \brief Gets the precedence (+1) of the given token for binary operators | |||
1183 | /// and other tokens that we treat like binary operators. | |||
1184 | int getCurrentPrecedence() { | |||
1185 | if (Current) { | |||
1186 | const FormatToken *NextNonComment = Current->getNextNonComment(); | |||
1187 | if (Current->is(TT_ConditionalExpr)) | |||
1188 | return prec::Conditional; | |||
1189 | else if (NextNonComment && NextNonComment->is(tok::colon) && | |||
1190 | NextNonComment->is(TT_DictLiteral)) | |||
1191 | return prec::Comma; | |||
1192 | else if (Current->is(TT_LambdaArrow)) | |||
1193 | return prec::Comma; | |||
1194 | else if (Current->isOneOf(tok::semi, TT_InlineASMColon, | |||
1195 | TT_SelectorName) || | |||
1196 | (Current->is(tok::comment) && NextNonComment && | |||
1197 | NextNonComment->is(TT_SelectorName))) | |||
1198 | return 0; | |||
1199 | else if (Current->is(TT_RangeBasedForLoopColon)) | |||
1200 | return prec::Comma; | |||
1201 | else if (Current->is(TT_BinaryOperator) || Current->is(tok::comma)) | |||
1202 | return Current->getPrecedence(); | |||
1203 | else if (Current->isOneOf(tok::period, tok::arrow)) | |||
1204 | return PrecedenceArrowAndPeriod; | |||
1205 | else if (Style.Language == FormatStyle::LK_Java && | |||
1206 | Current->isOneOf(Keywords.kw_extends, Keywords.kw_implements, | |||
1207 | Keywords.kw_throws)) | |||
1208 | return 0; | |||
1209 | } | |||
1210 | return -1; | |||
1211 | } | |||
1212 | ||||
1213 | void addFakeParenthesis(FormatToken *Start, prec::Level Precedence) { | |||
1214 | Start->FakeLParens.push_back(Precedence); | |||
| ||||
1215 | if (Precedence > prec::Unknown) | |||
1216 | Start->StartsBinaryExpression = true; | |||
1217 | if (Current) { | |||
1218 | FormatToken *Previous = Current->Previous; | |||
1219 | if (Previous->is(tok::comment) && Previous->Previous) | |||
1220 | Previous = Previous->Previous; | |||
1221 | ++Previous->FakeRParens; | |||
1222 | if (Precedence > prec::Unknown) | |||
1223 | Previous->EndsBinaryExpression = true; | |||
1224 | } | |||
1225 | } | |||
1226 | ||||
1227 | /// \brief Parse unary operator expressions and surround them with fake | |||
1228 | /// parentheses if appropriate. | |||
1229 | void parseUnaryOperator() { | |||
1230 | if (!Current || Current->isNot(TT_UnaryOperator)) { | |||
1231 | parse(PrecedenceArrowAndPeriod); | |||
1232 | return; | |||
1233 | } | |||
1234 | ||||
1235 | FormatToken *Start = Current; | |||
1236 | next(); | |||
1237 | parseUnaryOperator(); | |||
1238 | ||||
1239 | // The actual precedence doesn't matter. | |||
1240 | addFakeParenthesis(Start, prec::Unknown); | |||
1241 | } | |||
1242 | ||||
1243 | void parseConditionalExpr() { | |||
1244 | while (Current && Current->isTrailingComment()) { | |||
| ||||
1245 | next(); | |||
1246 | } | |||
1247 | FormatToken *Start = Current; | |||
1248 | parse(prec::LogicalOr); | |||
1249 | if (!Current || !Current->is(tok::question)) | |||
1250 | return; | |||
1251 | next(); | |||
1252 | parse(prec::Assignment); | |||
1253 | if (!Current || Current->isNot(TT_ConditionalExpr)) | |||
1254 | return; | |||
1255 | next(); | |||
1256 | parse(prec::Assignment); | |||
1257 | addFakeParenthesis(Start, prec::Conditional); | |||
1258 | } | |||
1259 | ||||
1260 | void next(bool SkipPastLeadingComments = true) { | |||
1261 | if (Current) | |||
1262 | Current = Current->Next; | |||
1263 | while (Current && | |||
1264 | (Current->NewlinesBefore == 0 || SkipPastLeadingComments) && | |||
1265 | Current->isTrailingComment()) | |||
1266 | Current = Current->Next; | |||
1267 | } | |||
1268 | ||||
1269 | const FormatStyle &Style; | |||
1270 | const AdditionalKeywords &Keywords; | |||
1271 | FormatToken *Current; | |||
1272 | }; | |||
1273 | ||||
1274 | } // end anonymous namespace | |||
1275 | ||||
1276 | void | |||
1277 | TokenAnnotator::setCommentLineLevels(SmallVectorImpl<AnnotatedLine *> &Lines) { | |||
1278 | const AnnotatedLine *NextNonCommentLine = nullptr; | |||
1279 | for (SmallVectorImpl<AnnotatedLine *>::reverse_iterator I = Lines.rbegin(), | |||
1280 | E = Lines.rend(); | |||
1281 | I != E; ++I) { | |||
1282 | if (NextNonCommentLine && (*I)->First->is(tok::comment) && | |||
1283 | (*I)->First->Next == nullptr) | |||
1284 | (*I)->Level = NextNonCommentLine->Level; | |||
1285 | else | |||
1286 | NextNonCommentLine = (*I)->First->isNot(tok::r_brace) ? (*I) : nullptr; | |||
1287 | ||||
1288 | setCommentLineLevels((*I)->Children); | |||
1289 | } | |||
1290 | } | |||
1291 | ||||
1292 | void TokenAnnotator::annotate(AnnotatedLine &Line) { | |||
1293 | for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(), | |||
1294 | E = Line.Children.end(); | |||
1295 | I != E; ++I) { | |||
1296 | annotate(**I); | |||
1297 | } | |||
1298 | AnnotatingParser Parser(Style, Line, Keywords); | |||
1299 | Line.Type = Parser.parseLine(); | |||
1300 | if (Line.Type == LT_Invalid) | |||
1301 | return; | |||
1302 | ||||
1303 | ExpressionParser ExprParser(Style, Keywords, Line); | |||
1304 | ExprParser.parse(); | |||
1305 | ||||
1306 | if (Line.First->is(TT_ObjCMethodSpecifier)) | |||
1307 | Line.Type = LT_ObjCMethodDecl; | |||
1308 | else if (Line.First->is(TT_ObjCDecl)) | |||
1309 | Line.Type = LT_ObjCDecl; | |||
1310 | else if (Line.First->is(TT_ObjCProperty)) | |||
1311 | Line.Type = LT_ObjCProperty; | |||
1312 | ||||
1313 | Line.First->SpacesRequiredBefore = 1; | |||
1314 | Line.First->CanBreakBefore = Line.First->MustBreakBefore; | |||
1315 | } | |||
1316 | ||||
1317 | // This function heuristically determines whether 'Current' starts the name of a | |||
1318 | // function declaration. | |||
1319 | static bool isFunctionDeclarationName(const FormatToken &Current) { | |||
1320 | if (!Current.is(TT_StartOfName) || Current.NestingLevel != 0) | |||
1321 | return false; | |||
1322 | const FormatToken *Next = Current.Next; | |||
1323 | for (; Next; Next = Next->Next) { | |||
1324 | if (Next->is(TT_TemplateOpener)) { | |||
1325 | Next = Next->MatchingParen; | |||
1326 | } else if (Next->is(tok::coloncolon)) { | |||
1327 | Next = Next->Next; | |||
1328 | if (!Next || !Next->is(tok::identifier)) | |||
1329 | return false; | |||
1330 | } else if (Next->is(tok::l_paren)) { | |||
1331 | break; | |||
1332 | } else { | |||
1333 | return false; | |||
1334 | } | |||
1335 | } | |||
1336 | if (!Next) | |||
1337 | return false; | |||
1338 | assert(Next->is(tok::l_paren))((Next->is(tok::l_paren)) ? static_cast<void> (0) : __assert_fail ("Next->is(tok::l_paren)", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn223220/tools/clang/lib/Format/TokenAnnotator.cpp" , 1338, __PRETTY_FUNCTION__)); | |||
1339 | if (Next->Next == Next->MatchingParen) | |||
1340 | return true; | |||
1341 | for (const FormatToken *Tok = Next->Next; Tok != Next->MatchingParen; | |||
1342 | Tok = Tok->Next) { | |||
1343 | if (Tok->is(tok::kw_const) || Tok->isSimpleTypeSpecifier() || | |||
1344 | Tok->isOneOf(TT_PointerOrReference, TT_StartOfName)) | |||
1345 | return true; | |||
1346 | if (Tok->isOneOf(tok::l_brace, tok::string_literal) || Tok->Tok.isLiteral()) | |||
1347 | return false; | |||
1348 | } | |||
1349 | return false; | |||
1350 | } | |||
1351 | ||||
1352 | void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) { | |||
1353 | for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(), | |||
1354 | E = Line.Children.end(); | |||
1355 | I != E; ++I) { | |||
1356 | calculateFormattingInformation(**I); | |||
1357 | } | |||
1358 | ||||
1359 | Line.First->TotalLength = | |||
1360 | Line.First->IsMultiline ? Style.ColumnLimit : Line.First->ColumnWidth; | |||
1361 | if (!Line.First->Next) | |||
1362 | return; | |||
1363 | FormatToken *Current = Line.First->Next; | |||
1364 | bool InFunctionDecl = Line.MightBeFunctionDecl; | |||
1365 | while (Current) { | |||
1366 | if (isFunctionDeclarationName(*Current)) | |||
1367 | Current->Type = TT_FunctionDeclarationName; | |||
1368 | if (Current->is(TT_LineComment)) { | |||
1369 | if (Current->Previous->BlockKind == BK_BracedInit && | |||
1370 | Current->Previous->opensScope()) | |||
1371 | Current->SpacesRequiredBefore = Style.Cpp11BracedListStyle ? 0 : 1; | |||
1372 | else | |||
1373 | Current->SpacesRequiredBefore = Style.SpacesBeforeTrailingComments; | |||
1374 | ||||
1375 | // If we find a trailing comment, iterate backwards to determine whether | |||
1376 | // it seems to relate to a specific parameter. If so, break before that | |||
1377 | // parameter to avoid changing the comment's meaning. E.g. don't move 'b' | |||
1378 | // to the previous line in: | |||
1379 | // SomeFunction(a, | |||
1380 | // b, // comment | |||
1381 | // c); | |||
1382 | if (!Current->HasUnescapedNewline) { | |||
1383 | for (FormatToken *Parameter = Current->Previous; Parameter; | |||
1384 | Parameter = Parameter->Previous) { | |||
1385 | if (Parameter->isOneOf(tok::comment, tok::r_brace)) | |||
1386 | break; | |||
1387 | if (Parameter->Previous && Parameter->Previous->is(tok::comma)) { | |||
1388 | if (!Parameter->Previous->is(TT_CtorInitializerComma) && | |||
1389 | Parameter->HasUnescapedNewline) | |||
1390 | Parameter->MustBreakBefore = true; | |||
1391 | break; | |||
1392 | } | |||
1393 | } | |||
1394 | } | |||
1395 | } else if (Current->SpacesRequiredBefore == 0 && | |||
1396 | spaceRequiredBefore(Line, *Current)) { | |||
1397 | Current->SpacesRequiredBefore = 1; | |||
1398 | } | |||
1399 | ||||
1400 | Current->MustBreakBefore = | |||
1401 | Current->MustBreakBefore || mustBreakBefore(Line, *Current); | |||
1402 | ||||
1403 | if (Style.AlwaysBreakAfterDefinitionReturnType && | |||
1404 | InFunctionDecl && Current->is(TT_FunctionDeclarationName) && | |||
1405 | !Line.Last->isOneOf(tok::semi, tok::comment)) // Only for definitions. | |||
1406 | // FIXME: Line.Last points to other characters than tok::semi | |||
1407 | // and tok::lbrace. | |||
1408 | Current->MustBreakBefore = true; | |||
1409 | ||||
1410 | Current->CanBreakBefore = | |||
1411 | Current->MustBreakBefore || canBreakBefore(Line, *Current); | |||
1412 | unsigned ChildSize = 0; | |||
1413 | if (Current->Previous->Children.size() == 1) { | |||
1414 | FormatToken &LastOfChild = *Current->Previous->Children[0]->Last; | |||
1415 | ChildSize = LastOfChild.isTrailingComment() ? Style.ColumnLimit | |||
1416 | : LastOfChild.TotalLength + 1; | |||
1417 | } | |||
1418 | const FormatToken *Prev= Current->Previous; | |||
1419 | if (Current->MustBreakBefore || Prev->Children.size() > 1 || | |||
1420 | (Prev->Children.size() == 1 && | |||
1421 | Prev->Children[0]->First->MustBreakBefore) || | |||
1422 | Current->IsMultiline) | |||
1423 | Current->TotalLength = Prev->TotalLength + Style.ColumnLimit; | |||
1424 | else | |||
1425 | Current->TotalLength = Prev->TotalLength + Current->ColumnWidth + | |||
1426 | ChildSize + Current->SpacesRequiredBefore; | |||
1427 | ||||
1428 | if (Current->is(TT_CtorInitializerColon)) | |||
1429 | InFunctionDecl = false; | |||
1430 | ||||
1431 | // FIXME: Only calculate this if CanBreakBefore is true once static | |||
1432 | // initializers etc. are sorted out. | |||
1433 | // FIXME: Move magic numbers to a better place. | |||
1434 | Current->SplitPenalty = 20 * Current->BindingStrength + | |||
1435 | splitPenalty(Line, *Current, InFunctionDecl); | |||
1436 | ||||
1437 | Current = Current->Next; | |||
1438 | } | |||
1439 | ||||
1440 | calculateUnbreakableTailLengths(Line); | |||
1441 | for (Current = Line.First; Current != nullptr; Current = Current->Next) { | |||
1442 | if (Current->Role) | |||
1443 | Current->Role->precomputeFormattingInfos(Current); | |||
1444 | } | |||
1445 | ||||
1446 | DEBUG({ printDebugInfo(Line); })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("format-token-annotator")) { { printDebugInfo(Line); }; } } while (0); | |||
1447 | } | |||
1448 | ||||
1449 | void TokenAnnotator::calculateUnbreakableTailLengths(AnnotatedLine &Line) { | |||
1450 | unsigned UnbreakableTailLength = 0; | |||
1451 | FormatToken *Current = Line.Last; | |||
1452 | while (Current) { | |||
1453 | Current->UnbreakableTailLength = UnbreakableTailLength; | |||
1454 | if (Current->CanBreakBefore || | |||
1455 | Current->isOneOf(tok::comment, tok::string_literal)) { | |||
1456 | UnbreakableTailLength = 0; | |||
1457 | } else { | |||
1458 | UnbreakableTailLength += | |||
1459 | Current->ColumnWidth + Current->SpacesRequiredBefore; | |||
1460 | } | |||
1461 | Current = Current->Previous; | |||
1462 | } | |||
1463 | } | |||
1464 | ||||
1465 | unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line, | |||
1466 | const FormatToken &Tok, | |||
1467 | bool InFunctionDecl) { | |||
1468 | const FormatToken &Left = *Tok.Previous; | |||
1469 | const FormatToken &Right = Tok; | |||
1470 | ||||
1471 | if (Left.is(tok::semi)) | |||
1472 | return 0; | |||
1473 | ||||
1474 | if (Style.Language == FormatStyle::LK_Java) { | |||
1475 | if (Left.is(TT_LeadingJavaAnnotation)) | |||
1476 | return 1; | |||
1477 | if (Right.isOneOf(Keywords.kw_extends, Keywords.kw_throws)) | |||
1478 | return 1; | |||
1479 | if (Right.is(Keywords.kw_implements)) | |||
1480 | return 2; | |||
1481 | if (Left.is(tok::comma) && Left.NestingLevel == 0) | |||
1482 | return 3; | |||
1483 | } else if (Style.Language == FormatStyle::LK_JavaScript) { | |||
1484 | if (Right.is(Keywords.kw_function)) | |||
1485 | return 100; | |||
1486 | } | |||
1487 | ||||
1488 | if (Left.is(tok::comma) || (Right.is(tok::identifier) && Right.Next && | |||
1489 | Right.Next->is(TT_DictLiteral))) | |||
1490 | return 1; | |||
1491 | if (Right.is(tok::l_square)) { | |||
1492 | if (Style.Language == FormatStyle::LK_Proto) | |||
1493 | return 1; | |||
1494 | if (!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare)) | |||
1495 | return 500; | |||
1496 | } | |||
1497 | ||||
1498 | if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName) || | |||
1499 | Right.is(tok::kw_operator)) { | |||
1500 | if (Line.First->is(tok::kw_for) && Right.PartOfMultiVariableDeclStmt) | |||
1501 | return 3; | |||
1502 | if (Left.is(TT_StartOfName)) | |||
1503 | return 20; | |||
1504 | if (InFunctionDecl && Right.NestingLevel == 0) | |||
1505 | return Style.PenaltyReturnTypeOnItsOwnLine; | |||
1506 | return 200; | |||
1507 | } | |||
1508 | if (Left.is(tok::equal) && Right.is(tok::l_brace)) | |||
1509 | return 150; | |||
1510 | if (Left.is(TT_CastRParen)) | |||
1511 | return 100; | |||
1512 | if (Left.is(tok::coloncolon) || | |||
1513 | (Right.is(tok::period) && Style.Language == FormatStyle::LK_Proto)) | |||
1514 | return 500; | |||
1515 | if (Left.isOneOf(tok::kw_class, tok::kw_struct)) | |||
1516 | return 5000; | |||
1517 | ||||
1518 | if (Left.isOneOf(TT_RangeBasedForLoopColon, TT_InheritanceColon)) | |||
1519 | return 2; | |||
1520 | ||||
1521 | if (Right.isMemberAccess()) { | |||
1522 | if (Left.is(tok::r_paren) && Left.MatchingParen && | |||
1523 | Left.MatchingParen->ParameterCount > 0) | |||
1524 | return 20; // Should be smaller than breaking at a nested comma. | |||
1525 | return 150; | |||
1526 | } | |||
1527 | ||||
1528 | if (Right.is(TT_TrailingAnnotation) && | |||
1529 | (!Right.Next || Right.Next->isNot(tok::l_paren))) { | |||
1530 | // Moving trailing annotations to the next line is fine for ObjC method | |||
1531 | // declarations. | |||
1532 | if (Line.First->is(TT_ObjCMethodSpecifier)) | |||
1533 | ||||
1534 | return 10; | |||
1535 | // Generally, breaking before a trailing annotation is bad unless it is | |||
1536 | // function-like. It seems to be especially preferable to keep standard | |||
1537 | // annotations (i.e. "const", "final" and "override") on the same line. | |||
1538 | // Use a slightly higher penalty after ")" so that annotations like | |||
1539 | // "const override" are kept together. | |||
1540 | bool is_short_annotation = Right.TokenText.size() < 10; | |||
1541 | return (Left.is(tok::r_paren) ? 100 : 120) + (is_short_annotation ? 50 : 0); | |||
1542 | } | |||
1543 | ||||
1544 | // In for-loops, prefer breaking at ',' and ';'. | |||
1545 | if (Line.First->is(tok::kw_for) && Left.is(tok::equal)) | |||
1546 | return 4; | |||
1547 | ||||
1548 | // In Objective-C method expressions, prefer breaking before "param:" over | |||
1549 | // breaking after it. | |||
1550 | if (Right.is(TT_SelectorName)) | |||
1551 | return 0; | |||
1552 | if (Left.is(tok::colon) && Left.is(TT_ObjCMethodExpr)) | |||
1553 | return Line.MightBeFunctionDecl ? 50 : 500; | |||
1554 | ||||
1555 | if (Left.is(tok::l_paren) && InFunctionDecl && Style.AlignAfterOpenBracket) | |||
1556 | return 100; | |||
1557 | if (Left.is(tok::equal) && InFunctionDecl) | |||
1558 | return 110; | |||
1559 | if (Right.is(tok::r_brace)) | |||
1560 | return 1; | |||
1561 | if (Left.is(TT_TemplateOpener)) | |||
1562 | return 100; | |||
1563 | if (Left.opensScope()) { | |||
1564 | if (!Style.AlignAfterOpenBracket) | |||
1565 | return 0; | |||
1566 | return Left.ParameterCount > 1 ? Style.PenaltyBreakBeforeFirstCallParameter | |||
1567 | : 19; | |||
1568 | } | |||
1569 | ||||
1570 | if (Right.is(tok::lessless)) { | |||
1571 | if (Left.is(tok::string_literal)) { | |||
1572 | StringRef Content = Left.TokenText; | |||
1573 | if (Content.startswith("\"")) | |||
1574 | Content = Content.drop_front(1); | |||
1575 | if (Content.endswith("\"")) | |||
1576 | Content = Content.drop_back(1); | |||
1577 | Content = Content.trim(); | |||
1578 | if (Content.size() > 1 && | |||
1579 | (Content.back() == ':' || Content.back() == '=')) | |||
1580 | return 25; | |||
1581 | } | |||
1582 | return 1; // Breaking at a << is really cheap. | |||
1583 | } | |||
1584 | if (Left.is(TT_ConditionalExpr)) | |||
1585 | return prec::Conditional; | |||
1586 | prec::Level Level = Left.getPrecedence(); | |||
1587 | ||||
1588 | if (Level != prec::Unknown) | |||
1589 | return Level; | |||
1590 | ||||
1591 | return 3; | |||
1592 | } | |||
1593 | ||||
1594 | bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, | |||
1595 | const FormatToken &Left, | |||
1596 | const FormatToken &Right) { | |||
1597 | if (Left.is(tok::kw_return) && Right.isNot(tok::semi)) | |||
1598 | return true; | |||
1599 | if (Style.ObjCSpaceAfterProperty && Line.Type == LT_ObjCProperty && | |||
1600 | Left.Tok.getObjCKeywordID() == tok::objc_property) | |||
1601 | return true; | |||
1602 | if (Right.is(tok::hashhash)) | |||
1603 | return Left.is(tok::hash); | |||
1604 | if (Left.isOneOf(tok::hashhash, tok::hash)) | |||
1605 | return Right.is(tok::hash); | |||
1606 | if (Left.is(tok::l_paren) && Right.is(tok::r_paren)) | |||
1607 | return Style.SpaceInEmptyParentheses; | |||
1608 | if (Left.is(tok::l_paren) || Right.is(tok::r_paren)) | |||
1609 | return (Right.is(TT_CastRParen )|| | |||
1610 | (Left.MatchingParen && Left.MatchingParen->is(TT_CastRParen))) | |||
1611 | ? Style.SpacesInCStyleCastParentheses | |||
1612 | : Style.SpacesInParentheses; | |||
1613 | if (Right.isOneOf(tok::semi, tok::comma)) | |||
1614 | return false; | |||
1615 | if (Right.is(tok::less) && | |||
1616 | (Left.isOneOf(tok::kw_template, tok::r_paren) || | |||
1617 | (Line.Type == LT_ObjCDecl && Style.ObjCSpaceBeforeProtocolList))) | |||
1618 | return true; | |||
1619 | if (Left.isOneOf(tok::exclaim, tok::tilde)) | |||
1620 | return false; | |||
1621 | if (Left.is(tok::at) && | |||
1622 | Right.isOneOf(tok::identifier, tok::string_literal, tok::char_constant, | |||
1623 | tok::numeric_constant, tok::l_paren, tok::l_brace, | |||
1624 | tok::kw_true, tok::kw_false)) | |||
1625 | return false; | |||
1626 | if (Left.is(tok::coloncolon)) | |||
1627 | return false; | |||
1628 | if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less)) | |||
1629 | return false; | |||
1630 | if (Right.is(tok::ellipsis)) | |||
1631 | return Left.Tok.isLiteral(); | |||
1632 | if (Left.is(tok::l_square) && Right.is(tok::amp)) | |||
1633 | return false; | |||
1634 | if (Right.is(TT_PointerOrReference)) | |||
1635 | return Left.Tok.isLiteral() || | |||
1636 | (!Left.isOneOf(TT_PointerOrReference, tok::l_paren) && | |||
1637 | Style.PointerAlignment != FormatStyle::PAS_Left); | |||
1638 | if (Right.is(TT_FunctionTypeLParen) && Left.isNot(tok::l_paren) && | |||
1639 | (!Left.is(TT_PointerOrReference) || | |||
1640 | Style.PointerAlignment != FormatStyle::PAS_Right)) | |||
1641 | return true; | |||
1642 | if (Left.is(TT_PointerOrReference)) | |||
1643 | return Right.Tok.isLiteral() || Right.is(TT_BlockComment) || | |||
1644 | (!Right.isOneOf(TT_PointerOrReference, tok::l_paren) && | |||
1645 | Style.PointerAlignment != FormatStyle::PAS_Right && Left.Previous && | |||
1646 | !Left.Previous->isOneOf(tok::l_paren, tok::coloncolon)); | |||
1647 | if (Right.is(tok::star) && Left.is(tok::l_paren)) | |||
1648 | return false; | |||
1649 | if (Left.is(tok::l_square)) | |||
1650 | return (Left.is(TT_ArrayInitializerLSquare) && | |||
1651 | Style.SpacesInContainerLiterals && Right.isNot(tok::r_square)) || | |||
1652 | (Left.is(TT_ArraySubscriptLSquare) && Style.SpacesInSquareBrackets && | |||
1653 | Right.isNot(tok::r_square)); | |||
1654 | if (Right.is(tok::r_square)) | |||
1655 | return Right.MatchingParen && | |||
1656 | ((Style.SpacesInContainerLiterals && | |||
1657 | Right.MatchingParen->is(TT_ArrayInitializerLSquare)) || | |||
1658 | (Style.SpacesInSquareBrackets && | |||
1659 | Right.MatchingParen->is(TT_ArraySubscriptLSquare))); | |||
1660 | if (Right.is(tok::l_square) && | |||
1661 | !Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare) && | |||
1662 | !Left.isOneOf(tok::numeric_constant, TT_DictLiteral)) | |||
1663 | return false; | |||
1664 | if (Left.is(tok::colon)) | |||
1665 | return !Left.is(TT_ObjCMethodExpr); | |||
1666 | if (Left.is(tok::l_brace) && Right.is(tok::r_brace)) | |||
1667 | return !Left.Children.empty(); // No spaces in "{}". | |||
1668 | if ((Left.is(tok::l_brace) && Left.BlockKind != BK_Block) || | |||
1669 | (Right.is(tok::r_brace) && Right.MatchingParen && | |||
1670 | Right.MatchingParen->BlockKind != BK_Block)) | |||
1671 | return !Style.Cpp11BracedListStyle; | |||
1672 | if (Left.is(TT_BlockComment)) | |||
1673 | return !Left.TokenText.endswith("=*/"); | |||
1674 | if (Right.is(tok::l_paren)) { | |||
1675 | if (Left.is(tok::r_paren) && Left.is(TT_AttributeParen)) | |||
1676 | return true; | |||
1677 | return Line.Type == LT_ObjCDecl || Left.is(tok::semi) || | |||
1678 | (Style.SpaceBeforeParens != FormatStyle::SBPO_Never && | |||
1679 | (Left.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, | |||
1680 | tok::kw_switch, tok::kw_case) || | |||
1681 | (Left.isOneOf(tok::kw_catch, tok::kw_new, tok::kw_delete) && | |||
1682 | (!Left.Previous || Left.Previous->isNot(tok::period))) || | |||
1683 | Left.IsForEachMacro)) || | |||
1684 | (Style.SpaceBeforeParens == FormatStyle::SBPO_Always && | |||
1685 | (Left.is(tok::identifier) || Left.isFunctionLikeKeyword()) && | |||
1686 | Line.Type != LT_PreprocessorDirective); | |||
1687 | } | |||
1688 | if (Left.is(tok::at) && Right.Tok.getObjCKeywordID() != tok::objc_not_keyword) | |||
1689 | return false; | |||
1690 | if (Right.is(TT_UnaryOperator)) | |||
1691 | return !Left.isOneOf(tok::l_paren, tok::l_square, tok::at) && | |||
1692 | (Left.isNot(tok::colon) || Left.isNot(TT_ObjCMethodExpr)); | |||
1693 | if ((Left.isOneOf(tok::identifier, tok::greater, tok::r_square, | |||
1694 | tok::r_paren) || | |||
1695 | Left.isSimpleTypeSpecifier()) && | |||
1696 | Right.is(tok::l_brace) && Right.getNextNonComment() && | |||
1697 | Right.BlockKind != BK_Block) | |||
1698 | return false; | |||
1699 | if (Left.is(tok::period) || Right.is(tok::period)) | |||
1700 | return false; | |||
1701 | if (Right.is(tok::hash) && Left.is(tok::identifier) && Left.TokenText == "L") | |||
1702 | return false; | |||
1703 | if (Left.is(TT_TemplateCloser) && Left.MatchingParen && | |||
1704 | Left.MatchingParen->Previous && | |||
1705 | Left.MatchingParen->Previous->is(tok::period)) | |||
1706 | // A.<B>DoSomething(); | |||
1707 | return false; | |||
1708 | if (Left.is(TT_TemplateCloser) && Right.is(tok::l_square)) | |||
1709 | return false; | |||
1710 | return true; | |||
1711 | } | |||
1712 | ||||
1713 | bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, | |||
1714 | const FormatToken &Right) { | |||
1715 | const FormatToken &Left = *Right.Previous; | |||
1716 | if (Style.Language == FormatStyle::LK_Proto) { | |||
1717 | if (Right.is(tok::period) && | |||
1718 | Left.isOneOf(Keywords.kw_optional, Keywords.kw_required, | |||
1719 | Keywords.kw_repeated)) | |||
1720 | return true; | |||
1721 | if (Right.is(tok::l_paren) && | |||
1722 | Left.isOneOf(Keywords.kw_returns, Keywords.kw_option)) | |||
1723 | return true; | |||
1724 | } else if (Style.Language == FormatStyle::LK_JavaScript) { | |||
1725 | if (Left.is(Keywords.kw_var)) | |||
1726 | return true; | |||
1727 | } else if (Style.Language == FormatStyle::LK_Java) { | |||
1728 | if (Left.is(tok::r_square) && Right.is(tok::l_brace)) | |||
1729 | return true; | |||
1730 | if (Left.is(TT_LambdaArrow) || Right.is(TT_LambdaArrow)) | |||
1731 | return true; | |||
1732 | if (Left.is(Keywords.kw_synchronized) && Right.is(tok::l_paren)) | |||
1733 | return Style.SpaceBeforeParens != FormatStyle::SBPO_Never; | |||
1734 | if ((Left.isOneOf(tok::kw_static, tok::kw_public, tok::kw_private, | |||
1735 | tok::kw_protected) || | |||
1736 | Left.isOneOf(Keywords.kw_final, Keywords.kw_abstract)) && | |||
1737 | Right.is(TT_TemplateOpener)) | |||
1738 | return true; | |||
1739 | } | |||
1740 | if (Right.Tok.getIdentifierInfo() && Left.Tok.getIdentifierInfo()) | |||
1741 | return true; // Never ever merge two identifiers. | |||
1742 | if (Left.is(TT_ImplicitStringLiteral)) | |||
1743 | return Right.WhitespaceRange.getBegin() != Right.WhitespaceRange.getEnd(); | |||
1744 | if (Line.Type == LT_ObjCMethodDecl) { | |||
1745 | if (Left.is(TT_ObjCMethodSpecifier)) | |||
1746 | return true; | |||
1747 | if (Left.is(tok::r_paren) && Right.is(tok::identifier)) | |||
1748 | // Don't space between ')' and <id> | |||
1749 | return false; | |||
1750 | } | |||
1751 | if (Line.Type == LT_ObjCProperty && | |||
1752 | (Right.is(tok::equal) || Left.is(tok::equal))) | |||
1753 | return false; | |||
1754 | ||||
1755 | if (Right.is(TT_TrailingReturnArrow) || Left.is(TT_TrailingReturnArrow)) | |||
1756 | return true; | |||
1757 | if (Left.is(tok::comma)) | |||
1758 | return true; | |||
1759 | if (Right.is(tok::comma)) | |||
1760 | return false; | |||
1761 | if (Right.isOneOf(TT_CtorInitializerColon, TT_ObjCBlockLParen)) | |||
1762 | return true; | |||
1763 | if (Left.is(tok::kw_operator)) | |||
1764 | return Right.is(tok::coloncolon); | |||
1765 | if (Right.is(TT_OverloadedOperatorLParen)) | |||
1766 | return false; | |||
1767 | if (Right.is(tok::colon)) | |||
1768 | return !Line.First->isOneOf(tok::kw_case, tok::kw_default) && | |||
1769 | Right.getNextNonComment() && Right.isNot(TT_ObjCMethodExpr) && | |||
1770 | !Left.is(tok::question) && | |||
1771 | !(Right.is(TT_InlineASMColon) && Left.is(tok::coloncolon)) && | |||
1772 | (Right.isNot(TT_DictLiteral) || Style.SpacesInContainerLiterals); | |||
1773 | if (Left.is(TT_UnaryOperator)) | |||
1774 | return Right.is(TT_BinaryOperator); | |||
1775 | if (Left.is(TT_CastRParen)) | |||
1776 | return Style.SpaceAfterCStyleCast || Right.is(TT_BinaryOperator); | |||
1777 | if (Left.is(tok::greater) && Right.is(tok::greater)) { | |||
1778 | return Right.is(TT_TemplateCloser) && Left.is(TT_TemplateCloser) && | |||
1779 | (Style.Standard != FormatStyle::LS_Cpp11 || Style.SpacesInAngles); | |||
1780 | } | |||
1781 | if (Right.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar) || | |||
1782 | Left.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar)) | |||
1783 | return false; | |||
1784 | if (!Style.SpaceBeforeAssignmentOperators && | |||
1785 | Right.getPrecedence() == prec::Assignment) | |||
1786 | return false; | |||
1787 | if (Right.is(tok::coloncolon) && Left.isNot(tok::l_brace)) | |||
1788 | return (Left.is(TT_TemplateOpener) && | |||
1789 | Style.Standard == FormatStyle::LS_Cpp03) || | |||
1790 | !(Left.isOneOf(tok::identifier, tok::l_paren, tok::r_paren) || | |||
1791 | Left.isOneOf(TT_TemplateCloser, TT_TemplateOpener)); | |||
1792 | if ((Left.is(TT_TemplateOpener)) != (Right.is(TT_TemplateCloser))) | |||
1793 | return Style.SpacesInAngles; | |||
1794 | if ((Right.is(TT_BinaryOperator) && !Left.is(tok::l_paren)) || | |||
1795 | Left.isOneOf(TT_BinaryOperator, TT_ConditionalExpr)) | |||
1796 | return true; | |||
1797 | if (Left.is(TT_TemplateCloser) && Right.is(tok::l_paren)) | |||
1798 | return Style.SpaceBeforeParens == FormatStyle::SBPO_Always; | |||
1799 | if (Right.is(TT_TemplateOpener) && Left.is(tok::r_paren) && | |||
1800 | Left.MatchingParen && Left.MatchingParen->is(TT_OverloadedOperatorLParen)) | |||
1801 | return false; | |||
1802 | if (Right.is(tok::less) && Left.isNot(tok::l_paren) && | |||
1803 | Line.First->is(tok::hash)) | |||
1804 | return true; | |||
1805 | if (Right.is(TT_TrailingUnaryOperator)) | |||
1806 | return false; | |||
1807 | if (Left.is(TT_RegexLiteral)) | |||
1808 | return false; | |||
1809 | return spaceRequiredBetween(Line, Left, Right); | |||
1810 | } | |||
1811 | ||||
1812 | // Returns 'true' if 'Tok' is a brace we'd want to break before in Allman style. | |||
1813 | static bool isAllmanBrace(const FormatToken &Tok) { | |||
1814 | return Tok.is(tok::l_brace) && Tok.BlockKind == BK_Block && | |||
1815 | !Tok.isOneOf(TT_ObjCBlockLBrace, TT_DictLiteral); | |||
1816 | } | |||
1817 | ||||
1818 | bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, | |||
1819 | const FormatToken &Right) { | |||
1820 | const FormatToken &Left = *Right.Previous; | |||
1821 | if (Right.NewlinesBefore > 1) | |||
1822 | return true; | |||
1823 | ||||
1824 | // If the last token before a '}' is a comma or a trailing comment, the | |||
1825 | // intention is to insert a line break after it in order to make shuffling | |||
1826 | // around entries easier. | |||
1827 | const FormatToken *BeforeClosingBrace = nullptr; | |||
1828 | if (Left.is(tok::l_brace) && Left.BlockKind != BK_Block && Left.MatchingParen) | |||
1829 | BeforeClosingBrace = Left.MatchingParen->Previous; | |||
1830 | else if (Right.is(tok::r_brace) && Right.BlockKind != BK_Block) | |||
1831 | BeforeClosingBrace = &Left; | |||
1832 | if (BeforeClosingBrace && (BeforeClosingBrace->is(tok::comma) || | |||
1833 | BeforeClosingBrace->isTrailingComment())) | |||
1834 | return true; | |||
1835 | ||||
1836 | if (Right.is(tok::comment)) { | |||
1837 | return Left.BlockKind != BK_BracedInit && | |||
1838 | Left.isNot(TT_CtorInitializerColon) && | |||
1839 | (Right.NewlinesBefore > 0 && Right.HasUnescapedNewline); | |||
1840 | } else if (Right.Previous->isTrailingComment() || | |||
1841 | (Right.isStringLiteral() && Right.Previous->isStringLiteral())) { | |||
1842 | return true; | |||
1843 | } else if (Right.Previous->IsUnterminatedLiteral) { | |||
1844 | return true; | |||
1845 | } else if (Right.is(tok::lessless) && Right.Next && | |||
1846 | Right.Previous->is(tok::string_literal) && | |||
1847 | Right.Next->is(tok::string_literal)) { | |||
1848 | return true; | |||
1849 | } else if (Right.Previous->ClosesTemplateDeclaration && | |||
1850 | Right.Previous->MatchingParen && | |||
1851 | Right.Previous->MatchingParen->NestingLevel == 0 && | |||
1852 | Style.AlwaysBreakTemplateDeclarations) { | |||
1853 | return true; | |||
1854 | } else if ((Right.isOneOf(TT_CtorInitializerComma, | |||
1855 | TT_CtorInitializerColon)) && | |||
1856 | Style.BreakConstructorInitializersBeforeComma && | |||
1857 | !Style.ConstructorInitializerAllOnOneLineOrOnePerLine) { | |||
1858 | return true; | |||
1859 | } else if (Right.is(tok::string_literal) && | |||
1860 | Right.TokenText.startswith("R\"")) { | |||
1861 | // Raw string literals are special wrt. line breaks. The author has made a | |||
1862 | // deliberate choice and might have aligned the contents of the string | |||
1863 | // literal accordingly. Thus, we try keep existing line breaks. | |||
1864 | return Right.NewlinesBefore > 0; | |||
1865 | } else if (Right.Previous->is(tok::l_brace) && Right.NestingLevel == 1 && | |||
1866 | Style.Language == FormatStyle::LK_Proto) { | |||
1867 | // Don't put enums onto single lines in protocol buffers. | |||
1868 | return true; | |||
1869 | } else if (Style.Language == FormatStyle::LK_JavaScript && | |||
1870 | Right.is(tok::r_brace) && Left.is(tok::l_brace) && | |||
1871 | !Left.Children.empty()) { | |||
1872 | // Support AllowShortFunctionsOnASingleLine for JavaScript. | |||
1873 | return Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None || | |||
1874 | (Left.NestingLevel == 0 && Line.Level == 0 && | |||
1875 | Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline); | |||
1876 | } else if (isAllmanBrace(Left) || isAllmanBrace(Right)) { | |||
1877 | return Style.BreakBeforeBraces == FormatStyle::BS_Allman || | |||
1878 | Style.BreakBeforeBraces == FormatStyle::BS_GNU; | |||
1879 | } else if (Style.Language == FormatStyle::LK_Proto && | |||
1880 | Left.isNot(tok::l_brace) && Right.is(TT_SelectorName)) { | |||
1881 | return true; | |||
1882 | } else if (Left.is(TT_ObjCBlockLBrace) && | |||
1883 | !Style.AllowShortBlocksOnASingleLine) { | |||
1884 | return true; | |||
1885 | } | |||
1886 | ||||
1887 | if (Style.Language == FormatStyle::LK_JavaScript) { | |||
1888 | // FIXME: This might apply to other languages and token kinds. | |||
1889 | if (Right.is(tok::char_constant) && Left.is(tok::plus) && Left.Previous && | |||
1890 | Left.Previous->is(tok::char_constant)) | |||
1891 | return true; | |||
1892 | } else if (Style.Language == FormatStyle::LK_Java) { | |||
1893 | if (Left.is(TT_LeadingJavaAnnotation) && Right.isNot(tok::l_paren) && | |||
1894 | Line.Last->is(tok::l_brace)) | |||
1895 | return true; | |||
1896 | if (Right.is(tok::plus) && Left.is(tok::string_literal) && Right.Next && | |||
1897 | Right.Next->is(tok::string_literal)) | |||
1898 | return true; | |||
1899 | } | |||
1900 | ||||
1901 | return false; | |||
1902 | } | |||
1903 | ||||
1904 | bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, | |||
1905 | const FormatToken &Right) { | |||
1906 | const FormatToken &Left = *Right.Previous; | |||
1907 | ||||
1908 | if (Style.Language == FormatStyle::LK_Java) { | |||
1909 | if (Left.isOneOf(Keywords.kw_throws, Keywords.kw_extends, | |||
1910 | Keywords.kw_implements)) | |||
1911 | return false; | |||
1912 | if (Right.isOneOf(Keywords.kw_throws, Keywords.kw_extends, | |||
1913 | Keywords.kw_implements)) | |||
1914 | return true; | |||
1915 | } | |||
1916 | ||||
1917 | if (Left.is(tok::at)) | |||
1918 | return false; | |||
1919 | if (Left.Tok.getObjCKeywordID() == tok::objc_interface) | |||
1920 | return false; | |||
1921 | if (Left.isOneOf(TT_JavaAnnotation, TT_LeadingJavaAnnotation)) | |||
1922 | return true; | |||
1923 | if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName) || | |||
1924 | Right.is(tok::kw_operator)) | |||
1925 | return true; | |||
1926 | if (Right.isTrailingComment()) | |||
1927 | // We rely on MustBreakBefore being set correctly here as we should not | |||
1928 | // change the "binding" behavior of a comment. | |||
1929 | // The first comment in a braced lists is always interpreted as belonging to | |||
1930 | // the first list element. Otherwise, it should be placed outside of the | |||
1931 | // list. | |||
1932 | return Left.BlockKind == BK_BracedInit; | |||
1933 | if (Left.is(tok::question) && Right.is(tok::colon)) | |||
1934 | return false; | |||
1935 | if (Right.is(TT_ConditionalExpr) || Right.is(tok::question)) | |||
1936 | return Style.BreakBeforeTernaryOperators; | |||
1937 | if (Left.is(TT_ConditionalExpr) || Left.is(tok::question)) | |||
1938 | return !Style.BreakBeforeTernaryOperators; | |||
1939 | if (Right.is(TT_InheritanceColon)) | |||
1940 | return true; | |||
1941 | if (Right.is(tok::colon) && | |||
1942 | !Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon)) | |||
1943 | return false; | |||
1944 | if (Left.is(tok::colon) && (Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr))) | |||
1945 | return true; | |||
1946 | if (Right.is(TT_SelectorName)) | |||
1947 | return true; | |||
1948 | if (Left.is(tok::r_paren) && Line.Type == LT_ObjCProperty) | |||
1949 | return true; | |||
1950 | if (Left.ClosesTemplateDeclaration) | |||
1951 | return true; | |||
1952 | if (Right.isOneOf(TT_RangeBasedForLoopColon, TT_OverloadedOperatorLParen, | |||
1953 | TT_OverloadedOperator)) | |||
1954 | return false; | |||
1955 | if (Left.is(TT_RangeBasedForLoopColon)) | |||
1956 | return true; | |||
1957 | if (Right.is(TT_RangeBasedForLoopColon)) | |||
1958 | return false; | |||
1959 | if (Left.isOneOf(TT_PointerOrReference, TT_TemplateCloser, | |||
1960 | TT_UnaryOperator) || | |||
1961 | Left.is(tok::kw_operator)) | |||
1962 | return false; | |||
1963 | if (Left.is(tok::equal) && Line.Type == LT_VirtualFunctionDecl) | |||
1964 | return false; | |||
1965 | if (Left.is(tok::l_paren) && Left.is(TT_AttributeParen)) | |||
1966 | return false; | |||
1967 | if (Left.is(tok::l_paren) && Left.Previous && | |||
1968 | (Left.Previous->isOneOf(TT_BinaryOperator, TT_CastRParen) || | |||
1969 | Left.Previous->is(tok::kw_if))) | |||
1970 | return false; | |||
1971 | if (Right.is(TT_ImplicitStringLiteral)) | |||
1972 | return false; | |||
1973 | ||||
1974 | if (Right.is(tok::r_paren) || Right.is(TT_TemplateCloser)) | |||
1975 | return false; | |||
1976 | ||||
1977 | // We only break before r_brace if there was a corresponding break before | |||
1978 | // the l_brace, which is tracked by BreakBeforeClosingBrace. | |||
1979 | if (Right.is(tok::r_brace)) | |||
1980 | return Right.MatchingParen && Right.MatchingParen->BlockKind == BK_Block; | |||
1981 | ||||
1982 | // Allow breaking after a trailing annotation, e.g. after a method | |||
1983 | // declaration. | |||
1984 | if (Left.is(TT_TrailingAnnotation)) | |||
1985 | return !Right.isOneOf(tok::l_brace, tok::semi, tok::equal, tok::l_paren, | |||
1986 | tok::less, tok::coloncolon); | |||
1987 | ||||
1988 | if (Right.is(tok::kw___attribute)) | |||
1989 | return true; | |||
1990 | ||||
1991 | if (Left.is(tok::identifier) && Right.is(tok::string_literal)) | |||
1992 | return true; | |||
1993 | ||||
1994 | if (Right.is(tok::identifier) && Right.Next && Right.Next->is(TT_DictLiteral)) | |||
1995 | return true; | |||
1996 | ||||
1997 | if (Left.is(TT_CtorInitializerComma) && | |||
1998 | Style.BreakConstructorInitializersBeforeComma) | |||
1999 | return false; | |||
2000 | if (Right.is(TT_CtorInitializerComma) && | |||
2001 | Style.BreakConstructorInitializersBeforeComma) | |||
2002 | return true; | |||
2003 | if (Left.is(tok::greater) && Right.is(tok::greater) && | |||
2004 | Left.isNot(TT_TemplateCloser)) | |||
2005 | return false; | |||
2006 | if (Right.is(TT_BinaryOperator) && | |||
2007 | Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None && | |||
2008 | (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_All || | |||
2009 | Right.getPrecedence() != prec::Assignment)) | |||
2010 | return true; | |||
2011 | if (Left.is(TT_ArrayInitializerLSquare)) | |||
2012 | return true; | |||
2013 | if (Right.is(tok::kw_typename) && Left.isNot(tok::kw_const)) | |||
2014 | return true; | |||
2015 | if (Left.isBinaryOperator() && !Left.isOneOf(tok::arrowstar, tok::lessless) && | |||
2016 | Style.BreakBeforeBinaryOperators != FormatStyle::BOS_All && | |||
2017 | (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None || | |||
2018 | Left.getPrecedence() == prec::Assignment)) | |||
2019 | return true; | |||
2020 | return Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace, | |||
2021 | tok::kw_class, tok::kw_struct) || | |||
2022 | Right.isMemberAccess() || Right.is(TT_TrailingReturnArrow) || | |||
2023 | Right.isOneOf(tok::lessless, tok::colon, tok::l_square, tok::at) || | |||
2024 | (Left.is(tok::r_paren) && | |||
2025 | Right.isOneOf(tok::identifier, tok::kw_const)) || | |||
2026 | (Left.is(tok::l_paren) && !Right.is(tok::r_paren)); | |||
2027 | } | |||
2028 | ||||
2029 | void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) { | |||
2030 | llvm::errs() << "AnnotatedTokens:\n"; | |||
2031 | const FormatToken *Tok = Line.First; | |||
2032 | while (Tok) { | |||
2033 | llvm::errs() << " M=" << Tok->MustBreakBefore | |||
2034 | << " C=" << Tok->CanBreakBefore << " T=" << Tok->Type | |||
2035 | << " S=" << Tok->SpacesRequiredBefore | |||
2036 | << " B=" << Tok->BlockParameterCount | |||
2037 | << " P=" << Tok->SplitPenalty << " Name=" << Tok->Tok.getName() | |||
2038 | << " L=" << Tok->TotalLength << " PPK=" << Tok->PackingKind | |||
2039 | << " FakeLParens="; | |||
2040 | for (unsigned i = 0, e = Tok->FakeLParens.size(); i != e; ++i) | |||
2041 | llvm::errs() << Tok->FakeLParens[i] << "/"; | |||
2042 | llvm::errs() << " FakeRParens=" << Tok->FakeRParens << "\n"; | |||
2043 | if (!Tok->Next) | |||
2044 | assert(Tok == Line.Last)((Tok == Line.Last) ? static_cast<void> (0) : __assert_fail ("Tok == Line.Last", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn223220/tools/clang/lib/Format/TokenAnnotator.cpp" , 2044, __PRETTY_FUNCTION__)); | |||
2045 | Tok = Tok->Next; | |||
2046 | } | |||
2047 | llvm::errs() << "----\n"; | |||
2048 | } | |||
2049 | ||||
2050 | } // namespace format | |||
2051 | } // namespace clang |