blob: 131d982906b6f907bdee82222f8d8010c6238d93 [file] [log] [blame]
Daniel Jasperbac016b2012-12-03 18:12:45 +00001//===--- UnwrappedLineParser.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 contains the implementation of the UnwrappedLineParser,
12/// which turns a stream of tokens into UnwrappedLines.
13///
14/// This is EXPERIMENTAL code under heavy development. It is not in a state yet,
15/// where it can be used to format real code.
16///
17//===----------------------------------------------------------------------===//
18
19#include "UnwrappedLineParser.h"
Daniel Jasperbac016b2012-12-03 18:12:45 +000020#include "llvm/Support/raw_ostream.h"
21
22namespace clang {
23namespace format {
24
Manuel Klimekd4397b92013-01-04 23:34:14 +000025class ScopedMacroState : public FormatTokenSource {
26public:
27 ScopedMacroState(UnwrappedLine &Line, FormatTokenSource *&TokenSource,
28 FormatToken &ResetToken)
29 : Line(Line), TokenSource(TokenSource), ResetToken(ResetToken),
Manuel Klimekc37b4d62013-01-05 22:14:16 +000030 PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource) {
Manuel Klimekd4397b92013-01-04 23:34:14 +000031 TokenSource = this;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000032 Line.Level = 0;
Manuel Klimekd4397b92013-01-04 23:34:14 +000033 Line.InPPDirective = true;
34 }
35
36 ~ScopedMacroState() {
37 TokenSource = PreviousTokenSource;
38 ResetToken = Token;
39 Line.InPPDirective = false;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000040 Line.Level = PreviousLineLevel;
Manuel Klimekd4397b92013-01-04 23:34:14 +000041 }
42
43 virtual FormatToken getNextToken() {
Manuel Klimekdd5b1012013-01-07 10:03:37 +000044 // The \c UnwrappedLineParser guards against this by never calling
45 // \c getNextToken() after it has encountered the first eof token.
46 assert(!eof());
Manuel Klimekd4397b92013-01-04 23:34:14 +000047 Token = PreviousTokenSource->getNextToken();
48 if (eof())
49 return createEOF();
50 return Token;
51 }
52
53private:
54 bool eof() {
55 return Token.NewlinesBefore > 0 && Token.HasUnescapedNewline;
56 }
57
58 FormatToken createEOF() {
59 FormatToken FormatTok;
60 FormatTok.Tok.startToken();
61 FormatTok.Tok.setKind(tok::eof);
62 return FormatTok;
63 }
64
65 UnwrappedLine &Line;
66 FormatTokenSource *&TokenSource;
67 FormatToken &ResetToken;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000068 unsigned PreviousLineLevel;
Manuel Klimekd4397b92013-01-04 23:34:14 +000069 FormatTokenSource *PreviousTokenSource;
70
71 FormatToken Token;
72};
73
Alexander Kornienko469a21b2012-12-07 16:15:44 +000074UnwrappedLineParser::UnwrappedLineParser(const FormatStyle &Style,
75 FormatTokenSource &Tokens,
Daniel Jasperbac016b2012-12-03 18:12:45 +000076 UnwrappedLineConsumer &Callback)
Manuel Klimek526ed112013-01-09 15:25:02 +000077 : Line(new UnwrappedLine), RootTokenInitialized(false),
78 LastInCurrentLine(NULL), MustBreakBeforeNextToken(false), Style(Style),
79 Tokens(&Tokens), Callback(Callback) {
Daniel Jasperbac016b2012-12-03 18:12:45 +000080}
81
Alexander Kornienkocff563c2012-12-04 17:27:50 +000082bool UnwrappedLineParser::parse() {
Manuel Klimekd4397b92013-01-04 23:34:14 +000083 readToken();
84 return parseFile();
85}
86
87bool UnwrappedLineParser::parseFile() {
Manuel Klimeka5342db2013-01-06 20:07:31 +000088 bool Error = parseLevel(/*HasOpeningBrace=*/false);
Manuel Klimekd4397b92013-01-04 23:34:14 +000089 // Make sure to format the remaining tokens.
90 addUnwrappedLine();
91 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +000092}
93
Manuel Klimeka5342db2013-01-06 20:07:31 +000094bool UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
Alexander Kornienkocff563c2012-12-04 17:27:50 +000095 bool Error = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +000096 do {
97 switch (FormatTok.Tok.getKind()) {
Daniel Jasperbac016b2012-12-03 18:12:45 +000098 case tok::comment:
Daniel Jasper05b1ac82012-12-17 11:29:41 +000099 nextToken();
100 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000101 break;
102 case tok::l_brace:
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000103 Error |= parseBlock();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000104 addUnwrappedLine();
105 break;
106 case tok::r_brace:
Manuel Klimeka5342db2013-01-06 20:07:31 +0000107 if (HasOpeningBrace) {
108 return false;
109 } else {
110 // Stray '}' is an error.
111 Error = true;
112 nextToken();
113 addUnwrappedLine();
114 }
115 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000116 default:
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000117 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000118 break;
119 }
120 } while (!eof());
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000121 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000122}
123
Alexander Kornienko15757312012-12-06 18:03:27 +0000124bool UnwrappedLineParser::parseBlock(unsigned AddLevels) {
Alexander Kornienkoa3a2b3a2012-12-06 17:49:17 +0000125 assert(FormatTok.Tok.is(tok::l_brace) && "'{' expected");
Daniel Jasperbac016b2012-12-03 18:12:45 +0000126 nextToken();
127
Daniel Jasperbac016b2012-12-03 18:12:45 +0000128 addUnwrappedLine();
129
Manuel Klimek526ed112013-01-09 15:25:02 +0000130 Line->Level += AddLevels;
Manuel Klimeka5342db2013-01-06 20:07:31 +0000131 parseLevel(/*HasOpeningBrace=*/true);
Manuel Klimek526ed112013-01-09 15:25:02 +0000132 Line->Level -= AddLevels;
Alexander Kornienko15757312012-12-06 18:03:27 +0000133
Alexander Kornienko393b0082012-12-04 15:40:36 +0000134 if (!FormatTok.Tok.is(tok::r_brace))
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000135 return true;
Alexander Kornienko393b0082012-12-04 15:40:36 +0000136
Manuel Klimekde768542013-01-07 18:10:23 +0000137 nextToken(); // Munch the closing brace.
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000138 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000139}
140
141void UnwrappedLineParser::parsePPDirective() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000142 assert(FormatTok.Tok.is(tok::hash) && "'#' expected");
Manuel Klimek526ed112013-01-09 15:25:02 +0000143 ScopedMacroState MacroState(*Line, Tokens, FormatTok);
Manuel Klimeka080a182013-01-02 16:30:12 +0000144 nextToken();
145
Manuel Klimeka080a182013-01-02 16:30:12 +0000146 if (FormatTok.Tok.getIdentifierInfo() == NULL) {
147 addUnwrappedLine();
Manuel Klimeka080a182013-01-02 16:30:12 +0000148 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000149 }
Manuel Klimeka080a182013-01-02 16:30:12 +0000150
Manuel Klimekd4397b92013-01-04 23:34:14 +0000151 switch (FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
152 case tok::pp_define:
153 parsePPDefine();
154 break;
155 default:
156 parsePPUnknown();
157 break;
158 }
159}
160
161void UnwrappedLineParser::parsePPDefine() {
162 nextToken();
163
164 if (FormatTok.Tok.getKind() != tok::identifier) {
165 parsePPUnknown();
166 return;
167 }
168 nextToken();
169 if (FormatTok.Tok.getKind() == tok::l_paren) {
170 parseParens();
171 }
172 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000173 Line->Level = 1;
Manuel Klimekc3d0c822013-01-07 09:34:28 +0000174
175 // Errors during a preprocessor directive can only affect the layout of the
176 // preprocessor directive, and thus we ignore them. An alternative approach
177 // would be to use the same approach we use on the file level (no
178 // re-indentation if there was a structural error) within the macro
179 // definition.
Manuel Klimekd4397b92013-01-04 23:34:14 +0000180 parseFile();
181}
182
183void UnwrappedLineParser::parsePPUnknown() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000184 do {
Manuel Klimeka080a182013-01-02 16:30:12 +0000185 nextToken();
186 } while (!eof());
187 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000188}
189
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000190void UnwrappedLineParser::parseComments() {
Daniel Jasper33182dd2012-12-05 14:57:28 +0000191 // Consume leading line comments, e.g. for branches without compounds.
192 while (FormatTok.Tok.is(tok::comment)) {
193 nextToken();
194 addUnwrappedLine();
195 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000196}
197
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000198void UnwrappedLineParser::parseStructuralElement() {
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000199 parseComments();
Daniel Jasper33182dd2012-12-05 14:57:28 +0000200
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000201 int TokenNumber = 0;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000202 switch (FormatTok.Tok.getKind()) {
Nico Weber6092d4e2013-01-07 19:05:19 +0000203 case tok::at:
204 nextToken();
205 switch (FormatTok.Tok.getObjCKeywordID()) {
206 case tok::objc_public:
207 case tok::objc_protected:
208 case tok::objc_package:
209 case tok::objc_private:
210 return parseAccessSpecifier();
Nico Weber27d13672013-01-09 20:25:35 +0000211 case tok::objc_interface:
212 return parseObjCInterface();
Nico Weber6092d4e2013-01-07 19:05:19 +0000213 default:
214 break;
215 }
216 break;
Alexander Kornienko15757312012-12-06 18:03:27 +0000217 case tok::kw_namespace:
218 parseNamespace();
219 return;
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000220 case tok::kw_inline:
221 nextToken();
222 TokenNumber++;
223 if (FormatTok.Tok.is(tok::kw_namespace)) {
224 parseNamespace();
225 return;
226 }
227 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000228 case tok::kw_public:
229 case tok::kw_protected:
230 case tok::kw_private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000231 parseAccessSpecifier();
232 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000233 case tok::kw_if:
234 parseIfThenElse();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000235 return;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000236 case tok::kw_for:
237 case tok::kw_while:
238 parseForOrWhileLoop();
239 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000240 case tok::kw_do:
241 parseDoWhile();
242 return;
243 case tok::kw_switch:
244 parseSwitch();
245 return;
246 case tok::kw_default:
247 nextToken();
248 parseLabel();
249 return;
250 case tok::kw_case:
251 parseCaseLabel();
252 return;
253 default:
254 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000255 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000256 do {
257 ++TokenNumber;
258 switch (FormatTok.Tok.getKind()) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000259 case tok::kw_enum:
260 parseEnum();
261 return;
Manuel Klimekde768542013-01-07 18:10:23 +0000262 case tok::kw_struct: // fallthrough
263 case tok::kw_class:
264 parseStructOrClass();
265 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000266 case tok::semi:
267 nextToken();
268 addUnwrappedLine();
269 return;
270 case tok::l_paren:
271 parseParens();
272 break;
273 case tok::l_brace:
274 parseBlock();
275 addUnwrappedLine();
276 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000277 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000278 nextToken();
279 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
280 parseLabel();
281 return;
282 }
283 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000284 case tok::equal:
285 nextToken();
286 // Skip initializers as they will be formatted by a later step.
287 if (FormatTok.Tok.is(tok::l_brace))
288 nextToken();
289 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000290 default:
291 nextToken();
292 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000293 }
294 } while (!eof());
295}
296
297void UnwrappedLineParser::parseParens() {
298 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
299 nextToken();
300 do {
301 switch (FormatTok.Tok.getKind()) {
302 case tok::l_paren:
303 parseParens();
304 break;
305 case tok::r_paren:
306 nextToken();
307 return;
308 default:
309 nextToken();
310 break;
311 }
312 } while (!eof());
313}
314
315void UnwrappedLineParser::parseIfThenElse() {
316 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
317 nextToken();
318 parseParens();
319 bool NeedsUnwrappedLine = false;
320 if (FormatTok.Tok.is(tok::l_brace)) {
321 parseBlock();
322 NeedsUnwrappedLine = true;
323 } else {
324 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000325 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000326 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000327 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000328 }
329 if (FormatTok.Tok.is(tok::kw_else)) {
330 nextToken();
331 if (FormatTok.Tok.is(tok::l_brace)) {
332 parseBlock();
333 addUnwrappedLine();
334 } else if (FormatTok.Tok.is(tok::kw_if)) {
335 parseIfThenElse();
336 } else {
337 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000338 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000339 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000340 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000341 }
342 } else if (NeedsUnwrappedLine) {
343 addUnwrappedLine();
344 }
345}
346
Alexander Kornienko15757312012-12-06 18:03:27 +0000347void UnwrappedLineParser::parseNamespace() {
348 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
349 nextToken();
350 if (FormatTok.Tok.is(tok::identifier))
351 nextToken();
352 if (FormatTok.Tok.is(tok::l_brace)) {
353 parseBlock(0);
354 addUnwrappedLine();
355 }
356 // FIXME: Add error handling.
357}
358
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000359void UnwrappedLineParser::parseForOrWhileLoop() {
360 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
361 "'for' or 'while' expected");
362 nextToken();
363 parseParens();
364 if (FormatTok.Tok.is(tok::l_brace)) {
365 parseBlock();
366 addUnwrappedLine();
367 } else {
368 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000369 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000370 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000371 --Line->Level;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000372 }
373}
374
Daniel Jasperbac016b2012-12-03 18:12:45 +0000375void UnwrappedLineParser::parseDoWhile() {
376 assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
377 nextToken();
378 if (FormatTok.Tok.is(tok::l_brace)) {
379 parseBlock();
380 } else {
381 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000382 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000383 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000384 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000385 }
386
Alexander Kornienko393b0082012-12-04 15:40:36 +0000387 // FIXME: Add error handling.
388 if (!FormatTok.Tok.is(tok::kw_while)) {
389 addUnwrappedLine();
390 return;
391 }
392
Daniel Jasperbac016b2012-12-03 18:12:45 +0000393 nextToken();
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000394 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000395}
396
397void UnwrappedLineParser::parseLabel() {
398 // FIXME: remove all asserts.
399 assert(FormatTok.Tok.is(tok::colon) && "':' expected");
400 nextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000401 unsigned OldLineLevel = Line->Level;
402 if (Line->Level > 0)
403 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000404 if (FormatTok.Tok.is(tok::l_brace)) {
405 parseBlock();
406 }
407 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000408 Line->Level = OldLineLevel;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000409}
410
411void UnwrappedLineParser::parseCaseLabel() {
412 assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected");
413 // FIXME: fix handling of complex expressions here.
414 do {
415 nextToken();
416 } while (!eof() && !FormatTok.Tok.is(tok::colon));
417 parseLabel();
418}
419
420void UnwrappedLineParser::parseSwitch() {
421 assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected");
422 nextToken();
423 parseParens();
424 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000425 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000426 addUnwrappedLine();
427 } else {
428 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000429 Line->Level += (Style.IndentCaseLabels ? 2 : 1);
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000430 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000431 Line->Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000432 }
433}
434
435void UnwrappedLineParser::parseAccessSpecifier() {
436 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000437 // Otherwise, we don't know what it is, and we'd better keep the next token.
438 if (FormatTok.Tok.is(tok::colon))
439 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000440 addUnwrappedLine();
441}
442
443void UnwrappedLineParser::parseEnum() {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000444 bool HasContents = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000445 do {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000446 switch (FormatTok.Tok.getKind()) {
447 case tok::l_brace:
448 nextToken();
449 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000450 ++Line->Level;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000451 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000452 break;
453 case tok::l_paren:
454 parseParens();
455 break;
456 case tok::comma:
457 nextToken();
458 addUnwrappedLine();
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000459 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000460 break;
461 case tok::r_brace:
462 if (HasContents)
463 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000464 --Line->Level;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000465 nextToken();
466 break;
467 case tok::semi:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000468 nextToken();
469 addUnwrappedLine();
470 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000471 default:
472 HasContents = true;
473 nextToken();
474 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000475 }
476 } while (!eof());
477}
478
Manuel Klimekde768542013-01-07 18:10:23 +0000479void UnwrappedLineParser::parseStructOrClass() {
480 nextToken();
481 do {
482 switch (FormatTok.Tok.getKind()) {
483 case tok::l_brace:
484 // FIXME: Think about how to resolve the error handling here.
485 parseBlock();
486 parseStructuralElement();
487 return;
488 case tok::semi:
489 nextToken();
490 addUnwrappedLine();
491 return;
492 default:
493 nextToken();
494 break;
495 }
496 } while (!eof());
497}
498
Nico Weber27d13672013-01-09 20:25:35 +0000499void UnwrappedLineParser::parseObjCInterface() {
500 nextToken();
501 nextToken(); // interface name
502
503 // @interface can be followed by either a base class, or a category.
504 if (FormatTok.Tok.is(tok::colon)) {
505 nextToken();
506 nextToken(); // base class name
507 } else if (FormatTok.Tok.is(tok::l_paren))
508 // Skip category, if present.
509 parseParens();
510
511 // Skip protocol list, if present.
512 if (FormatTok.Tok.is(tok::less)) {
513 do
514 nextToken();
515 while (!eof() && FormatTok.Tok.isNot(tok::greater));
516 nextToken(); // Skip '>'.
517 }
518
519 // If instance variables are present, keep the '{' on the first line too.
520 if (FormatTok.Tok.is(tok::l_brace))
521 parseBlock();
522
523 // With instance variables, this puts '}' on its own line. Without instance
524 // variables, this ends the @interface line.
525 addUnwrappedLine();
526
527 // Read everything up to the @end.
528 do {
529 if (FormatTok.Tok.isObjCAtKeyword(tok::objc_end)) {
530 nextToken();
531 addUnwrappedLine();
532 break;
533 }
534
535 parseStructuralElement();
536 } while (!eof());
537}
538
Daniel Jasperbac016b2012-12-03 18:12:45 +0000539void UnwrappedLineParser::addUnwrappedLine() {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000540 if (!RootTokenInitialized)
541 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000542 // Consume trailing comments.
543 while (!eof() && FormatTok.NewlinesBefore == 0 &&
544 FormatTok.Tok.is(tok::comment)) {
545 nextToken();
546 }
Manuel Klimek526ed112013-01-09 15:25:02 +0000547 Callback.consumeUnwrappedLine(*Line);
Daniel Jasper26f7e782013-01-08 14:56:18 +0000548 RootTokenInitialized = false;
Manuel Klimek526ed112013-01-09 15:25:02 +0000549 LastInCurrentLine = NULL;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000550}
551
552bool UnwrappedLineParser::eof() const {
553 return FormatTok.Tok.is(tok::eof);
554}
555
556void UnwrappedLineParser::nextToken() {
557 if (eof())
558 return;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000559 if (RootTokenInitialized) {
Manuel Klimek526ed112013-01-09 15:25:02 +0000560 assert(LastInCurrentLine->Children.empty());
Daniel Jasper26f7e782013-01-08 14:56:18 +0000561 LastInCurrentLine->Children.push_back(FormatTok);
562 LastInCurrentLine = &LastInCurrentLine->Children.back();
563 } else {
Manuel Klimek526ed112013-01-09 15:25:02 +0000564 Line->RootToken = FormatTok;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000565 RootTokenInitialized = true;
Manuel Klimek526ed112013-01-09 15:25:02 +0000566 LastInCurrentLine = &Line->RootToken;
567 }
568 if (MustBreakBeforeNextToken) {
569 LastInCurrentLine->MustBreakBefore = true;
570 MustBreakBeforeNextToken = false;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000571 }
Manuel Klimekd4397b92013-01-04 23:34:14 +0000572 readToken();
573}
574
575void UnwrappedLineParser::readToken() {
576 FormatTok = Tokens->getNextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000577 while (!Line->InPPDirective && FormatTok.Tok.is(tok::hash) &&
Manuel Klimekf6fd00b2013-01-05 22:56:06 +0000578 ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
579 FormatTok.IsFirst)) {
Manuel Klimek526ed112013-01-09 15:25:02 +0000580 UnwrappedLine* StoredLine = Line.take();
581 Line.reset(new UnwrappedLine(*StoredLine));
582 assert(LastInCurrentLine == NULL || LastInCurrentLine->Children.empty());
583 FormatToken *StoredLastInCurrentLine = LastInCurrentLine;
584 bool PreviousInitialized = RootTokenInitialized;
585 RootTokenInitialized = false;
586 LastInCurrentLine = NULL;
587
Manuel Klimekd4397b92013-01-04 23:34:14 +0000588 parsePPDirective();
Manuel Klimek526ed112013-01-09 15:25:02 +0000589
590 assert(!RootTokenInitialized);
591 Line.reset(StoredLine);
592 RootTokenInitialized = PreviousInitialized;
593 LastInCurrentLine = StoredLastInCurrentLine;
594 assert(LastInCurrentLine == NULL || LastInCurrentLine->Children.empty());
595 MustBreakBeforeNextToken = true;
Manuel Klimekd4397b92013-01-04 23:34:14 +0000596 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000597}
598
Daniel Jaspercd162382013-01-07 13:26:07 +0000599} // end namespace format
600} // end namespace clang