blob: e1fa72e84bda5504318853b9bc5ce77e87415800 [file] [log] [blame]
Daniel Jasperf7935112012-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
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000011/// This file contains the implementation of the UnwrappedLineParser,
Daniel Jasperf7935112012-12-03 18:12:45 +000012/// which turns a stream of tokens into UnwrappedLines.
13///
Daniel Jasperf7935112012-12-03 18:12:45 +000014//===----------------------------------------------------------------------===//
15
Chandler Carruth4b417452013-01-19 08:09:44 +000016#include "UnwrappedLineParser.h"
Benjamin Kramer33335df2015-03-01 21:36:40 +000017#include "llvm/ADT/STLExtras.h"
Manuel Klimekab3dc002013-01-16 12:31:12 +000018#include "llvm/Support/Debug.h"
Benjamin Kramer53f5e892015-03-23 18:05:43 +000019#include "llvm/Support/raw_ostream.h"
Manuel Klimekab3dc002013-01-16 12:31:12 +000020
Martin Probst7e0f25b2017-11-25 09:19:42 +000021#include <algorithm>
22
Chandler Carruth10346662014-04-22 03:17:02 +000023#define DEBUG_TYPE "format-parser"
24
Daniel Jasperf7935112012-12-03 18:12:45 +000025namespace clang {
26namespace format {
27
Manuel Klimek15dfe7a2013-05-28 11:55:06 +000028class FormatTokenSource {
29public:
Angel Garcia Gomez637d1e62015-10-20 13:23:58 +000030 virtual ~FormatTokenSource() {}
Manuel Klimek15dfe7a2013-05-28 11:55:06 +000031 virtual FormatToken *getNextToken() = 0;
32
33 virtual unsigned getPosition() = 0;
34 virtual FormatToken *setPosition(unsigned Position) = 0;
35};
36
Craig Topper69665e12013-07-01 04:21:54 +000037namespace {
38
Manuel Klimek0a3a3c92013-01-23 09:32:48 +000039class ScopedDeclarationState {
40public:
41 ScopedDeclarationState(UnwrappedLine &Line, std::vector<bool> &Stack,
42 bool MustBeDeclaration)
43 : Line(Line), Stack(Stack) {
Manuel Klimek0a3a3c92013-01-23 09:32:48 +000044 Line.MustBeDeclaration = MustBeDeclaration;
Manuel Klimek39080572013-01-23 11:03:04 +000045 Stack.push_back(MustBeDeclaration);
Manuel Klimek0a3a3c92013-01-23 09:32:48 +000046 }
47 ~ScopedDeclarationState() {
Manuel Klimek0a3a3c92013-01-23 09:32:48 +000048 Stack.pop_back();
Manuel Klimekc1237a82013-01-23 14:08:21 +000049 if (!Stack.empty())
50 Line.MustBeDeclaration = Stack.back();
51 else
52 Line.MustBeDeclaration = true;
Manuel Klimek0a3a3c92013-01-23 09:32:48 +000053 }
Daniel Jasper393564f2013-05-31 14:56:29 +000054
Manuel Klimek0a3a3c92013-01-23 09:32:48 +000055private:
56 UnwrappedLine &Line;
57 std::vector<bool> &Stack;
58};
59
Krasimir Georgieva1c30932017-05-19 10:34:57 +000060static bool isLineComment(const FormatToken &FormatTok) {
Krasimir Georgiev410ed242017-11-10 12:50:09 +000061 return FormatTok.is(tok::comment) && !FormatTok.TokenText.startswith("/*");
Krasimir Georgieva1c30932017-05-19 10:34:57 +000062}
63
Krasimir Georgievea222a72017-05-22 10:07:56 +000064// Checks if \p FormatTok is a line comment that continues the line comment
65// \p Previous. The original column of \p MinColumnToken is used to determine
66// whether \p FormatTok is indented enough to the right to continue \p Previous.
67static bool continuesLineComment(const FormatToken &FormatTok,
68 const FormatToken *Previous,
69 const FormatToken *MinColumnToken) {
70 if (!Previous || !MinColumnToken)
71 return false;
72 unsigned MinContinueColumn =
73 MinColumnToken->OriginalColumn + (isLineComment(*MinColumnToken) ? 0 : 1);
74 return isLineComment(FormatTok) && FormatTok.NewlinesBefore == 1 &&
75 isLineComment(*Previous) &&
76 FormatTok.OriginalColumn >= MinContinueColumn;
77}
78
Manuel Klimek1abf7892013-01-04 23:34:14 +000079class ScopedMacroState : public FormatTokenSource {
80public:
81 ScopedMacroState(UnwrappedLine &Line, FormatTokenSource *&TokenSource,
Manuel Klimek20e0af62015-05-06 11:56:29 +000082 FormatToken *&ResetToken)
Manuel Klimek1abf7892013-01-04 23:34:14 +000083 : Line(Line), TokenSource(TokenSource), ResetToken(ResetToken),
Manuel Klimek1a18c402013-04-12 14:13:36 +000084 PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource),
Krasimir Georgieva1c30932017-05-19 10:34:57 +000085 Token(nullptr), PreviousToken(nullptr) {
David L. Jones5de22722018-06-15 06:08:54 +000086 FakeEOF.Tok.startToken();
87 FakeEOF.Tok.setKind(tok::eof);
Manuel Klimek1abf7892013-01-04 23:34:14 +000088 TokenSource = this;
Manuel Klimekef2cfb12013-01-05 22:14:16 +000089 Line.Level = 0;
Manuel Klimek1abf7892013-01-04 23:34:14 +000090 Line.InPPDirective = true;
91 }
92
Alexander Kornienko34eb2072015-04-11 02:00:23 +000093 ~ScopedMacroState() override {
Manuel Klimek1abf7892013-01-04 23:34:14 +000094 TokenSource = PreviousTokenSource;
95 ResetToken = Token;
96 Line.InPPDirective = false;
Manuel Klimekef2cfb12013-01-05 22:14:16 +000097 Line.Level = PreviousLineLevel;
Manuel Klimek1abf7892013-01-04 23:34:14 +000098 }
99
Craig Topperfb6b25b2014-03-15 04:29:04 +0000100 FormatToken *getNextToken() override {
Manuel Klimek78725712013-01-07 10:03:37 +0000101 // The \c UnwrappedLineParser guards against this by never calling
102 // \c getNextToken() after it has encountered the first eof token.
103 assert(!eof());
Krasimir Georgieva1c30932017-05-19 10:34:57 +0000104 PreviousToken = Token;
Manuel Klimek1abf7892013-01-04 23:34:14 +0000105 Token = PreviousTokenSource->getNextToken();
106 if (eof())
David L. Jones5de22722018-06-15 06:08:54 +0000107 return &FakeEOF;
Manuel Klimek1abf7892013-01-04 23:34:14 +0000108 return Token;
109 }
110
Craig Topperfb6b25b2014-03-15 04:29:04 +0000111 unsigned getPosition() override { return PreviousTokenSource->getPosition(); }
Manuel Klimekab419912013-05-23 09:41:43 +0000112
Craig Topperfb6b25b2014-03-15 04:29:04 +0000113 FormatToken *setPosition(unsigned Position) override {
Krasimir Georgieva1c30932017-05-19 10:34:57 +0000114 PreviousToken = nullptr;
Manuel Klimekab419912013-05-23 09:41:43 +0000115 Token = PreviousTokenSource->setPosition(Position);
116 return Token;
117 }
118
Manuel Klimek1abf7892013-01-04 23:34:14 +0000119private:
Krasimir Georgieva1c30932017-05-19 10:34:57 +0000120 bool eof() {
121 return Token && Token->HasUnescapedNewline &&
Krasimir Georgievea222a72017-05-22 10:07:56 +0000122 !continuesLineComment(*Token, PreviousToken,
123 /*MinColumnToken=*/PreviousToken);
Krasimir Georgieva1c30932017-05-19 10:34:57 +0000124 }
Manuel Klimek1abf7892013-01-04 23:34:14 +0000125
David L. Jones5de22722018-06-15 06:08:54 +0000126 FormatToken FakeEOF;
Manuel Klimek1abf7892013-01-04 23:34:14 +0000127 UnwrappedLine &Line;
128 FormatTokenSource *&TokenSource;
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000129 FormatToken *&ResetToken;
Manuel Klimekef2cfb12013-01-05 22:14:16 +0000130 unsigned PreviousLineLevel;
Manuel Klimek1abf7892013-01-04 23:34:14 +0000131 FormatTokenSource *PreviousTokenSource;
132
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000133 FormatToken *Token;
Krasimir Georgieva1c30932017-05-19 10:34:57 +0000134 FormatToken *PreviousToken;
Manuel Klimek1abf7892013-01-04 23:34:14 +0000135};
136
Craig Topper69665e12013-07-01 04:21:54 +0000137} // end anonymous namespace
138
Manuel Klimek8e07a1b2013-01-10 11:52:21 +0000139class ScopedLineState {
140public:
Manuel Klimekd3b92fa2013-01-18 14:04:34 +0000141 ScopedLineState(UnwrappedLineParser &Parser,
142 bool SwitchToPreprocessorLines = false)
David Blaikieefb6eb22014-08-09 20:02:07 +0000143 : Parser(Parser), OriginalLines(Parser.CurrentLines) {
Manuel Klimekd3b92fa2013-01-18 14:04:34 +0000144 if (SwitchToPreprocessorLines)
145 Parser.CurrentLines = &Parser.PreprocessorDirectives;
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +0000146 else if (!Parser.Line->Tokens.empty())
147 Parser.CurrentLines = &Parser.Line->Tokens.back().Children;
David Blaikieefb6eb22014-08-09 20:02:07 +0000148 PreBlockLine = std::move(Parser.Line);
149 Parser.Line = llvm::make_unique<UnwrappedLine>();
Daniel Jasperdaffc0d2013-01-16 09:10:19 +0000150 Parser.Line->Level = PreBlockLine->Level;
151 Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
Manuel Klimek8e07a1b2013-01-10 11:52:21 +0000152 }
153
154 ~ScopedLineState() {
Daniel Jasperdaffc0d2013-01-16 09:10:19 +0000155 if (!Parser.Line->Tokens.empty()) {
Manuel Klimek8e07a1b2013-01-10 11:52:21 +0000156 Parser.addUnwrappedLine();
157 }
Daniel Jasperdaffc0d2013-01-16 09:10:19 +0000158 assert(Parser.Line->Tokens.empty());
David Blaikieefb6eb22014-08-09 20:02:07 +0000159 Parser.Line = std::move(PreBlockLine);
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +0000160 if (Parser.CurrentLines == &Parser.PreprocessorDirectives)
161 Parser.MustBreakBeforeNextToken = true;
162 Parser.CurrentLines = OriginalLines;
Manuel Klimek8e07a1b2013-01-10 11:52:21 +0000163 }
164
165private:
166 UnwrappedLineParser &Parser;
167
David Blaikieefb6eb22014-08-09 20:02:07 +0000168 std::unique_ptr<UnwrappedLine> PreBlockLine;
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +0000169 SmallVectorImpl<UnwrappedLine> *OriginalLines;
Manuel Klimek8e07a1b2013-01-10 11:52:21 +0000170};
171
Alexander Kornienko3a33f022013-12-12 09:49:52 +0000172class CompoundStatementIndenter {
173public:
174 CompoundStatementIndenter(UnwrappedLineParser *Parser,
175 const FormatStyle &Style, unsigned &LineLevel)
176 : LineLevel(LineLevel), OldLineLevel(LineLevel) {
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000177 if (Style.BraceWrapping.AfterControlStatement)
Alexander Kornienko3a33f022013-12-12 09:49:52 +0000178 Parser->addUnwrappedLine();
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000179 if (Style.BraceWrapping.IndentBraces)
Alexander Kornienko3a33f022013-12-12 09:49:52 +0000180 ++LineLevel;
Alexander Kornienko3a33f022013-12-12 09:49:52 +0000181 }
Daniel Jasperb05a81d2014-05-09 13:11:16 +0000182 ~CompoundStatementIndenter() { LineLevel = OldLineLevel; }
Alexander Kornienko3a33f022013-12-12 09:49:52 +0000183
184private:
185 unsigned &LineLevel;
186 unsigned OldLineLevel;
187};
188
Craig Topper69665e12013-07-01 04:21:54 +0000189namespace {
190
Manuel Klimekab419912013-05-23 09:41:43 +0000191class IndexedTokenSource : public FormatTokenSource {
192public:
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000193 IndexedTokenSource(ArrayRef<FormatToken *> Tokens)
Manuel Klimekab419912013-05-23 09:41:43 +0000194 : Tokens(Tokens), Position(-1) {}
195
Craig Topperfb6b25b2014-03-15 04:29:04 +0000196 FormatToken *getNextToken() override {
Manuel Klimekab419912013-05-23 09:41:43 +0000197 ++Position;
198 return Tokens[Position];
199 }
200
Craig Topperfb6b25b2014-03-15 04:29:04 +0000201 unsigned getPosition() override {
Manuel Klimekab419912013-05-23 09:41:43 +0000202 assert(Position >= 0);
203 return Position;
204 }
205
Craig Topperfb6b25b2014-03-15 04:29:04 +0000206 FormatToken *setPosition(unsigned P) override {
Manuel Klimekab419912013-05-23 09:41:43 +0000207 Position = P;
208 return Tokens[Position];
209 }
210
Manuel Klimek71814b42013-10-11 21:25:45 +0000211 void reset() { Position = -1; }
212
Manuel Klimekab419912013-05-23 09:41:43 +0000213private:
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000214 ArrayRef<FormatToken *> Tokens;
Manuel Klimekab419912013-05-23 09:41:43 +0000215 int Position;
216};
217
Craig Topper69665e12013-07-01 04:21:54 +0000218} // end anonymous namespace
219
Daniel Jasperd2ae41a2013-05-15 08:14:19 +0000220UnwrappedLineParser::UnwrappedLineParser(const FormatStyle &Style,
Daniel Jasperd0ec0d62014-11-04 12:41:02 +0000221 const AdditionalKeywords &Keywords,
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +0000222 unsigned FirstStartColumn,
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000223 ArrayRef<FormatToken *> Tokens,
Daniel Jasperd2ae41a2013-05-15 08:14:19 +0000224 UnwrappedLineConsumer &Callback)
Daniel Jasperb05a81d2014-05-09 13:11:16 +0000225 : Line(new UnwrappedLine), MustBreakBeforeNextToken(false),
Krasimir Georgiev00c5c722017-02-02 15:32:19 +0000226 CurrentLines(&Lines), Style(Style), Keywords(Keywords),
227 CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr),
Krasimir Georgievad47c902017-08-30 14:34:57 +0000228 Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1),
Mark Zeren1c3afaf2018-02-05 15:59:00 +0000229 IncludeGuard(Style.IndentPPDirectives == FormatStyle::PPDIS_None
230 ? IG_Rejected
231 : IG_Inited),
232 IncludeGuardToken(nullptr), FirstStartColumn(FirstStartColumn) {}
Manuel Klimek71814b42013-10-11 21:25:45 +0000233
234void UnwrappedLineParser::reset() {
235 PPBranchLevel = -1;
Mark Zeren1c3afaf2018-02-05 15:59:00 +0000236 IncludeGuard = Style.IndentPPDirectives == FormatStyle::PPDIS_None
237 ? IG_Rejected
238 : IG_Inited;
239 IncludeGuardToken = nullptr;
Manuel Klimek71814b42013-10-11 21:25:45 +0000240 Line.reset(new UnwrappedLine);
241 CommentsBeforeNextToken.clear();
Craig Topper2145bc02014-05-09 08:15:10 +0000242 FormatTok = nullptr;
Manuel Klimek71814b42013-10-11 21:25:45 +0000243 MustBreakBeforeNextToken = false;
244 PreprocessorDirectives.clear();
245 CurrentLines = &Lines;
246 DeclarationScopeStack.clear();
Manuel Klimek71814b42013-10-11 21:25:45 +0000247 PPStack.clear();
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +0000248 Line->FirstStartColumn = FirstStartColumn;
Manuel Klimek71814b42013-10-11 21:25:45 +0000249}
Daniel Jasperf7935112012-12-03 18:12:45 +0000250
Manuel Klimek20e0af62015-05-06 11:56:29 +0000251void UnwrappedLineParser::parse() {
Manuel Klimekab419912013-05-23 09:41:43 +0000252 IndexedTokenSource TokenSource(AllTokens);
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +0000253 Line->FirstStartColumn = FirstStartColumn;
Manuel Klimek71814b42013-10-11 21:25:45 +0000254 do {
Nicola Zaghen3538b392018-05-15 13:30:56 +0000255 LLVM_DEBUG(llvm::dbgs() << "----\n");
Manuel Klimek71814b42013-10-11 21:25:45 +0000256 reset();
257 Tokens = &TokenSource;
258 TokenSource.reset();
Daniel Jaspera79064a2013-03-01 18:11:39 +0000259
Manuel Klimek71814b42013-10-11 21:25:45 +0000260 readToken();
261 parseFile();
Mark Zeren1c3afaf2018-02-05 15:59:00 +0000262
263 // If we found an include guard then all preprocessor directives (other than
264 // the guard) are over-indented by one.
265 if (IncludeGuard == IG_Found)
266 for (auto &Line : Lines)
267 if (Line.InPPDirective && Line.Level > 0)
268 --Line.Level;
269
Manuel Klimek71814b42013-10-11 21:25:45 +0000270 // Create line with eof token.
271 pushToken(FormatTok);
272 addUnwrappedLine();
273
274 for (SmallVectorImpl<UnwrappedLine>::iterator I = Lines.begin(),
275 E = Lines.end();
276 I != E; ++I) {
277 Callback.consumeUnwrappedLine(*I);
278 }
279 Callback.finishRun();
280 Lines.clear();
281 while (!PPLevelBranchIndex.empty() &&
Daniel Jasper53bd1672013-10-12 13:32:56 +0000282 PPLevelBranchIndex.back() + 1 >= PPLevelBranchCount.back()) {
Manuel Klimek71814b42013-10-11 21:25:45 +0000283 PPLevelBranchIndex.resize(PPLevelBranchIndex.size() - 1);
284 PPLevelBranchCount.resize(PPLevelBranchCount.size() - 1);
285 }
286 if (!PPLevelBranchIndex.empty()) {
287 ++PPLevelBranchIndex.back();
288 assert(PPLevelBranchIndex.size() == PPLevelBranchCount.size());
289 assert(PPLevelBranchIndex.back() <= PPLevelBranchCount.back());
290 }
291 } while (!PPLevelBranchIndex.empty());
Manuel Klimek1abf7892013-01-04 23:34:14 +0000292}
293
Manuel Klimek1a18c402013-04-12 14:13:36 +0000294void UnwrappedLineParser::parseFile() {
Daniel Jasper9326f912015-05-05 08:40:32 +0000295 // The top-level context in a file always has declarations, except for pre-
296 // processor directives and JavaScript files.
297 bool MustBeDeclaration =
298 !Line->InPPDirective && Style.Language != FormatStyle::LK_JavaScript;
299 ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
300 MustBeDeclaration);
Krasimir Georgiev26b144c2017-07-03 15:05:14 +0000301 if (Style.Language == FormatStyle::LK_TextProto)
302 parseBracedList();
303 else
304 parseLevel(/*HasOpeningBrace=*/false);
Manuel Klimek1abf7892013-01-04 23:34:14 +0000305 // Make sure to format the remaining tokens.
Manuel Klimekf92f7bc2013-01-22 16:31:55 +0000306 flushComments(true);
Manuel Klimek1abf7892013-01-04 23:34:14 +0000307 addUnwrappedLine();
Daniel Jasperf7935112012-12-03 18:12:45 +0000308}
309
Manuel Klimek1a18c402013-04-12 14:13:36 +0000310void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
Daniel Jasper516d7972013-07-25 11:31:57 +0000311 bool SwitchLabelEncountered = false;
Daniel Jasperf7935112012-12-03 18:12:45 +0000312 do {
Birunthan Mohanathasb001a0b2015-07-03 17:25:16 +0000313 tok::TokenKind kind = FormatTok->Tok.getKind();
314 if (FormatTok->Type == TT_MacroBlockBegin) {
315 kind = tok::l_brace;
316 } else if (FormatTok->Type == TT_MacroBlockEnd) {
317 kind = tok::r_brace;
318 }
319
320 switch (kind) {
Daniel Jasperf7935112012-12-03 18:12:45 +0000321 case tok::comment:
Daniel Jaspere25509f2012-12-17 11:29:41 +0000322 nextToken();
323 addUnwrappedLine();
Daniel Jasperf7935112012-12-03 18:12:45 +0000324 break;
325 case tok::l_brace:
Manuel Klimek0a3a3c92013-01-23 09:32:48 +0000326 // FIXME: Add parameter whether this can happen - if this happens, we must
327 // be in a non-declaration context.
Daniel Jasperb86e2722015-08-24 13:23:37 +0000328 if (!FormatTok->is(TT_MacroBlockBegin) && tryToParseBracedList())
329 continue;
Nico Weber9096fc02013-06-26 00:30:14 +0000330 parseBlock(/*MustBeDeclaration=*/false);
Daniel Jasperf7935112012-12-03 18:12:45 +0000331 addUnwrappedLine();
332 break;
333 case tok::r_brace:
Manuel Klimek1a18c402013-04-12 14:13:36 +0000334 if (HasOpeningBrace)
335 return;
Manuel Klimek1a18c402013-04-12 14:13:36 +0000336 nextToken();
337 addUnwrappedLine();
Manuel Klimek1058d982013-01-06 20:07:31 +0000338 break;
Nico Weberc29f83b2018-01-23 16:30:56 +0000339 case tok::kw_default: {
340 unsigned StoredPosition = Tokens->getPosition();
341 FormatToken *Next = Tokens->getNextToken();
342 FormatTok = Tokens->setPosition(StoredPosition);
343 if (Next && Next->isNot(tok::colon)) {
344 // default not followed by ':' is not a case label; treat it like
345 // an identifier.
346 parseStructuralElement();
347 break;
348 }
349 // Else, if it is 'default:', fall through to the case handling.
Nico Weberf1add5e2018-01-24 01:47:22 +0000350 LLVM_FALLTHROUGH;
Nico Weberc29f83b2018-01-23 16:30:56 +0000351 }
Daniel Jasper516d7972013-07-25 11:31:57 +0000352 case tok::kw_case:
Manuel Klimek89628f62017-09-20 09:51:03 +0000353 if (Style.Language == FormatStyle::LK_JavaScript &&
354 Line->MustBeDeclaration) {
Martin Probstf785fd92017-08-04 17:07:15 +0000355 // A 'case: string' style field declaration.
356 parseStructuralElement();
357 break;
358 }
Daniel Jasper72407622013-09-02 08:26:29 +0000359 if (!SwitchLabelEncountered &&
360 (Style.IndentCaseLabels || (Line->InPPDirective && Line->Level == 1)))
361 ++Line->Level;
Daniel Jasper516d7972013-07-25 11:31:57 +0000362 SwitchLabelEncountered = true;
363 parseStructuralElement();
364 break;
Daniel Jasperf7935112012-12-03 18:12:45 +0000365 default:
Manuel Klimek6b9eeba2013-01-07 14:56:16 +0000366 parseStructuralElement();
Daniel Jasperf7935112012-12-03 18:12:45 +0000367 break;
368 }
369 } while (!eof());
370}
371
Daniel Jasperadba2aa2015-05-18 12:52:00 +0000372void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
Manuel Klimekab419912013-05-23 09:41:43 +0000373 // We'll parse forward through the tokens until we hit
374 // a closing brace or eof - note that getNextToken() will
375 // parse macros, so this will magically work inside macro
376 // definitions, too.
377 unsigned StoredPosition = Tokens->getPosition();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000378 FormatToken *Tok = FormatTok;
Manuel Klimek89628f62017-09-20 09:51:03 +0000379 const FormatToken *PrevTok = Tok->Previous;
Manuel Klimekab419912013-05-23 09:41:43 +0000380 // Keep a stack of positions of lbrace tokens. We will
381 // update information about whether an lbrace starts a
382 // braced init list or a different block during the loop.
Daniel Jasperb1f74a82013-07-09 09:06:29 +0000383 SmallVector<FormatToken *, 8> LBraceStack;
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000384 assert(Tok->Tok.is(tok::l_brace));
Manuel Klimekab419912013-05-23 09:41:43 +0000385 do {
Daniel Jaspereb65e912015-12-21 18:31:15 +0000386 // Get next non-comment token.
Daniel Jasper7f5d53e2013-07-01 09:15:46 +0000387 FormatToken *NextTok;
Daniel Jasperca7bd722013-07-01 16:43:38 +0000388 unsigned ReadTokens = 0;
Daniel Jasper7f5d53e2013-07-01 09:15:46 +0000389 do {
390 NextTok = Tokens->getNextToken();
Daniel Jasperca7bd722013-07-01 16:43:38 +0000391 ++ReadTokens;
Daniel Jasper7f5d53e2013-07-01 09:15:46 +0000392 } while (NextTok->is(tok::comment));
393
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000394 switch (Tok->Tok.getKind()) {
Manuel Klimekab419912013-05-23 09:41:43 +0000395 case tok::l_brace:
Martin Probst95ed8e72017-05-31 09:29:40 +0000396 if (Style.Language == FormatStyle::LK_JavaScript && PrevTok) {
Martin Probste8e27ca2017-11-25 09:33:47 +0000397 if (PrevTok->isOneOf(tok::colon, tok::less))
398 // A ':' indicates this code is in a type, or a braced list
399 // following a label in an object literal ({a: {b: 1}}).
400 // A '<' could be an object used in a comparison, but that is nonsense
401 // code (can never return true), so more likely it is a generic type
402 // argument (`X<{a: string; b: number}>`).
403 // The code below could be confused by semicolons between the
404 // individual members in a type member list, which would normally
405 // trigger BK_Block. In both cases, this must be parsed as an inline
406 // braced init.
Martin Probst95ed8e72017-05-31 09:29:40 +0000407 Tok->BlockKind = BK_BracedInit;
408 else if (PrevTok->is(tok::r_paren))
409 // `) { }` can only occur in function or method declarations in JS.
410 Tok->BlockKind = BK_Block;
411 } else {
Daniel Jasperb9a49902016-01-09 15:56:28 +0000412 Tok->BlockKind = BK_Unknown;
Martin Probst95ed8e72017-05-31 09:29:40 +0000413 }
Daniel Jasperb1f74a82013-07-09 09:06:29 +0000414 LBraceStack.push_back(Tok);
Manuel Klimekab419912013-05-23 09:41:43 +0000415 break;
416 case tok::r_brace:
Daniel Jasperb9a49902016-01-09 15:56:28 +0000417 if (LBraceStack.empty())
418 break;
419 if (LBraceStack.back()->BlockKind == BK_Unknown) {
420 bool ProbablyBracedList = false;
421 if (Style.Language == FormatStyle::LK_Proto) {
422 ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square);
423 } else {
424 // Using OriginalColumn to distinguish between ObjC methods and
425 // binary operators is a bit hacky.
426 bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) &&
427 NextTok->OriginalColumn == 0;
Daniel Jasper91b032a2014-05-22 12:46:38 +0000428
Daniel Jasperb9a49902016-01-09 15:56:28 +0000429 // If there is a comma, semicolon or right paren after the closing
430 // brace, we assume this is a braced initializer list. Note that
431 // regardless how we mark inner braces here, we will overwrite the
432 // BlockKind later if we parse a braced list (where all blocks
433 // inside are by default braced lists), or when we explicitly detect
434 // blocks (for example while parsing lambdas).
Martin Probst95ed8e72017-05-31 09:29:40 +0000435 // FIXME: Some of these do not apply to JS, e.g. "} {" can never be a
436 // braced list in JS.
Daniel Jasperb9a49902016-01-09 15:56:28 +0000437 ProbablyBracedList =
Daniel Jasperacffeb82016-03-05 18:34:26 +0000438 (Style.Language == FormatStyle::LK_JavaScript &&
Martin Probste1e12a72016-08-19 14:35:01 +0000439 NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
440 Keywords.kw_as)) ||
Martin Probstb7fb2672017-05-10 13:53:29 +0000441 (Style.isCpp() && NextTok->is(tok::l_paren)) ||
Daniel Jasperb9a49902016-01-09 15:56:28 +0000442 NextTok->isOneOf(tok::comma, tok::period, tok::colon,
443 tok::r_paren, tok::r_square, tok::l_brace,
Manuel Klimekd0f3fe52018-04-11 14:51:54 +0000444 tok::ellipsis) ||
Daniel Jaspere4ada022016-12-13 10:05:03 +0000445 (NextTok->is(tok::identifier) &&
446 !PrevTok->isOneOf(tok::semi, tok::r_brace, tok::l_brace)) ||
Daniel Jasperb9a49902016-01-09 15:56:28 +0000447 (NextTok->is(tok::semi) &&
448 (!ExpectClassBody || LBraceStack.size() != 1)) ||
449 (NextTok->isBinaryOperator() && !NextIsObjCMethod);
Manuel Klimekd0f3fe52018-04-11 14:51:54 +0000450 if (NextTok->is(tok::l_square)) {
451 // We can have an array subscript after a braced init
452 // list, but C++11 attributes are expected after blocks.
453 NextTok = Tokens->getNextToken();
454 ++ReadTokens;
455 ProbablyBracedList = NextTok->isNot(tok::l_square);
456 }
Manuel Klimekab419912013-05-23 09:41:43 +0000457 }
Daniel Jasperb9a49902016-01-09 15:56:28 +0000458 if (ProbablyBracedList) {
459 Tok->BlockKind = BK_BracedInit;
460 LBraceStack.back()->BlockKind = BK_BracedInit;
461 } else {
462 Tok->BlockKind = BK_Block;
463 LBraceStack.back()->BlockKind = BK_Block;
464 }
Manuel Klimekab419912013-05-23 09:41:43 +0000465 }
Daniel Jasperb9a49902016-01-09 15:56:28 +0000466 LBraceStack.pop_back();
Manuel Klimekab419912013-05-23 09:41:43 +0000467 break;
Daniel Jasperac7e34e2014-03-13 10:11:17 +0000468 case tok::at:
Manuel Klimekab419912013-05-23 09:41:43 +0000469 case tok::semi:
470 case tok::kw_if:
471 case tok::kw_while:
472 case tok::kw_for:
473 case tok::kw_switch:
474 case tok::kw_try:
Nico Weberfac23712015-02-04 15:26:27 +0000475 case tok::kw___try:
Daniel Jasperb9a49902016-01-09 15:56:28 +0000476 if (!LBraceStack.empty() && LBraceStack.back()->BlockKind == BK_Unknown)
Daniel Jasperb1f74a82013-07-09 09:06:29 +0000477 LBraceStack.back()->BlockKind = BK_Block;
Manuel Klimekab419912013-05-23 09:41:43 +0000478 break;
479 default:
480 break;
481 }
Daniel Jasperb9a49902016-01-09 15:56:28 +0000482 PrevTok = Tok;
Manuel Klimekab419912013-05-23 09:41:43 +0000483 Tok = NextTok;
Manuel Klimekbab25fd2013-09-04 08:20:47 +0000484 } while (Tok->Tok.isNot(tok::eof) && !LBraceStack.empty());
Daniel Jasperb9a49902016-01-09 15:56:28 +0000485
Manuel Klimekab419912013-05-23 09:41:43 +0000486 // Assume other blocks for all unclosed opening braces.
487 for (unsigned i = 0, e = LBraceStack.size(); i != e; ++i) {
Daniel Jasperb1f74a82013-07-09 09:06:29 +0000488 if (LBraceStack[i]->BlockKind == BK_Unknown)
489 LBraceStack[i]->BlockKind = BK_Block;
Manuel Klimekab419912013-05-23 09:41:43 +0000490 }
Manuel Klimekbab25fd2013-09-04 08:20:47 +0000491
Manuel Klimekab419912013-05-23 09:41:43 +0000492 FormatTok = Tokens->setPosition(StoredPosition);
493}
494
Francois Ferranda98a95c2017-07-28 07:56:14 +0000495template <class T>
496static inline void hash_combine(std::size_t &seed, const T &v) {
497 std::hash<T> hasher;
498 seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
499}
500
501size_t UnwrappedLineParser::computePPHash() const {
502 size_t h = 0;
503 for (const auto &i : PPStack) {
504 hash_combine(h, size_t(i.Kind));
505 hash_combine(h, i.Line);
506 }
507 return h;
508}
509
Manuel Klimekb212f3b2013-10-12 22:46:56 +0000510void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel,
511 bool MunchSemi) {
Birunthan Mohanathasb001a0b2015-07-03 17:25:16 +0000512 assert(FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) &&
513 "'{' or macro block token expected");
514 const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin);
Daniel Jaspereb65e912015-12-21 18:31:15 +0000515 FormatTok->BlockKind = BK_Block;
Birunthan Mohanathasb001a0b2015-07-03 17:25:16 +0000516
Francois Ferranda98a95c2017-07-28 07:56:14 +0000517 size_t PPStartHash = computePPHash();
518
Daniel Jasper516d7972013-07-25 11:31:57 +0000519 unsigned InitialLevel = Line->Level;
Krasimir Georgiev3e051052017-07-24 14:51:59 +0000520 nextToken(/*LevelDifference=*/AddLevel ? 1 : 0);
Daniel Jasperf7935112012-12-03 18:12:45 +0000521
Birunthan Mohanathasb001a0b2015-07-03 17:25:16 +0000522 if (MacroBlock && FormatTok->is(tok::l_paren))
523 parseParens();
524
Francois Ferranda98a95c2017-07-28 07:56:14 +0000525 size_t NbPreprocessorDirectives =
526 CurrentLines == &Lines ? PreprocessorDirectives.size() : 0;
Manuel Klimeka4fe1c12013-01-21 16:42:44 +0000527 addUnwrappedLine();
Francois Ferranda98a95c2017-07-28 07:56:14 +0000528 size_t OpeningLineIndex =
529 CurrentLines->empty()
530 ? (UnwrappedLine::kInvalidIndex)
531 : (CurrentLines->size() - 1 - NbPreprocessorDirectives);
Daniel Jasperf7935112012-12-03 18:12:45 +0000532
Manuel Klimek0a3a3c92013-01-23 09:32:48 +0000533 ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
534 MustBeDeclaration);
Daniel Jasper65ee3472013-07-31 23:16:02 +0000535 if (AddLevel)
536 ++Line->Level;
Nico Weber9096fc02013-06-26 00:30:14 +0000537 parseLevel(/*HasOpeningBrace=*/true);
Alexander Kornienko578fdd82012-12-06 18:03:27 +0000538
Marianne Mailhot-Sarrasin03137c62016-04-14 14:56:49 +0000539 if (eof())
540 return;
541
Birunthan Mohanathasb001a0b2015-07-03 17:25:16 +0000542 if (MacroBlock ? !FormatTok->is(TT_MacroBlockEnd)
543 : !FormatTok->is(tok::r_brace)) {
Daniel Jasper516d7972013-07-25 11:31:57 +0000544 Line->Level = InitialLevel;
Daniel Jaspereb65e912015-12-21 18:31:15 +0000545 FormatTok->BlockKind = BK_Block;
Manuel Klimek1a18c402013-04-12 14:13:36 +0000546 return;
Manuel Klimekf92f7bc2013-01-22 16:31:55 +0000547 }
Alexander Kornienko0ea8e102012-12-04 15:40:36 +0000548
Francois Ferranda98a95c2017-07-28 07:56:14 +0000549 size_t PPEndHash = computePPHash();
550
Krasimir Georgiev3e051052017-07-24 14:51:59 +0000551 // Munch the closing brace.
552 nextToken(/*LevelDifference=*/AddLevel ? -1 : 0);
Birunthan Mohanathasb001a0b2015-07-03 17:25:16 +0000553
554 if (MacroBlock && FormatTok->is(tok::l_paren))
555 parseParens();
556
Manuel Klimekb212f3b2013-10-12 22:46:56 +0000557 if (MunchSemi && FormatTok->Tok.is(tok::semi))
558 nextToken();
Krasimir Georgiev3e051052017-07-24 14:51:59 +0000559 Line->Level = InitialLevel;
Francois Ferranda98a95c2017-07-28 07:56:14 +0000560
561 if (PPStartHash == PPEndHash) {
562 Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
563 if (OpeningLineIndex != UnwrappedLine::kInvalidIndex) {
564 // Update the opening line to add the forward reference as well
Manuel Klimek0dddcf72018-04-23 09:34:26 +0000565 (*CurrentLines)[OpeningLineIndex].MatchingClosingBlockLineIndex =
Francois Ferranda98a95c2017-07-28 07:56:14 +0000566 CurrentLines->size() - 1;
567 }
Francois Ferrande56a8292017-06-14 12:29:47 +0000568 }
Daniel Jasperf7935112012-12-03 18:12:45 +0000569}
570
Daniel Jasper02c7bca2015-03-30 09:56:50 +0000571static bool isGoogScope(const UnwrappedLine &Line) {
Daniel Jasper616de8642014-11-23 16:46:28 +0000572 // FIXME: Closure-library specific stuff should not be hard-coded but be
573 // configurable.
Daniel Jasper4a39c842014-05-06 13:54:10 +0000574 if (Line.Tokens.size() < 4)
575 return false;
576 auto I = Line.Tokens.begin();
577 if (I->Tok->TokenText != "goog")
578 return false;
579 ++I;
580 if (I->Tok->isNot(tok::period))
581 return false;
582 ++I;
583 if (I->Tok->TokenText != "scope")
584 return false;
585 ++I;
586 return I->Tok->is(tok::l_paren);
587}
588
Martin Probst101ec892017-05-09 20:04:09 +0000589static bool isIIFE(const UnwrappedLine &Line,
590 const AdditionalKeywords &Keywords) {
591 // Look for the start of an immediately invoked anonymous function.
592 // https://en.wikipedia.org/wiki/Immediately-invoked_function_expression
593 // This is commonly done in JavaScript to create a new, anonymous scope.
594 // Example: (function() { ... })()
595 if (Line.Tokens.size() < 3)
596 return false;
597 auto I = Line.Tokens.begin();
598 if (I->Tok->isNot(tok::l_paren))
599 return false;
600 ++I;
601 if (I->Tok->isNot(Keywords.kw_function))
602 return false;
603 ++I;
604 return I->Tok->is(tok::l_paren);
605}
606
Roman Kashitsyna043ced2014-08-11 12:18:01 +0000607static bool ShouldBreakBeforeBrace(const FormatStyle &Style,
608 const FormatToken &InitialToken) {
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000609 if (InitialToken.is(tok::kw_namespace))
610 return Style.BraceWrapping.AfterNamespace;
611 if (InitialToken.is(tok::kw_class))
612 return Style.BraceWrapping.AfterClass;
613 if (InitialToken.is(tok::kw_union))
614 return Style.BraceWrapping.AfterUnion;
615 if (InitialToken.is(tok::kw_struct))
616 return Style.BraceWrapping.AfterStruct;
617 return false;
Roman Kashitsyna043ced2014-08-11 12:18:01 +0000618}
619
Manuel Klimek516e0542013-09-04 13:25:30 +0000620void UnwrappedLineParser::parseChildBlock() {
621 FormatTok->BlockKind = BK_Block;
622 nextToken();
623 {
Manuel Klimek89628f62017-09-20 09:51:03 +0000624 bool SkipIndent = (Style.Language == FormatStyle::LK_JavaScript &&
625 (isGoogScope(*Line) || isIIFE(*Line, Keywords)));
Manuel Klimek516e0542013-09-04 13:25:30 +0000626 ScopedLineState LineState(*this);
627 ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
628 /*MustBeDeclaration=*/false);
Martin Probst101ec892017-05-09 20:04:09 +0000629 Line->Level += SkipIndent ? 0 : 1;
Manuel Klimek516e0542013-09-04 13:25:30 +0000630 parseLevel(/*HasOpeningBrace=*/true);
Daniel Jasper02c7bca2015-03-30 09:56:50 +0000631 flushComments(isOnNewLine(*FormatTok));
Martin Probst101ec892017-05-09 20:04:09 +0000632 Line->Level -= SkipIndent ? 0 : 1;
Manuel Klimek516e0542013-09-04 13:25:30 +0000633 }
634 nextToken();
635}
636
Daniel Jasperf7935112012-12-03 18:12:45 +0000637void UnwrappedLineParser::parsePPDirective() {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000638 assert(FormatTok->Tok.is(tok::hash) && "'#' expected");
Manuel Klimek20e0af62015-05-06 11:56:29 +0000639 ScopedMacroState MacroState(*Line, Tokens, FormatTok);
Manuel Klimeka71e5d82013-01-02 16:30:12 +0000640 nextToken();
641
Craig Topper2145bc02014-05-09 08:15:10 +0000642 if (!FormatTok->Tok.getIdentifierInfo()) {
Manuel Klimek591b5802013-01-31 15:58:48 +0000643 parsePPUnknown();
Manuel Klimeka71e5d82013-01-02 16:30:12 +0000644 return;
Daniel Jasperf7935112012-12-03 18:12:45 +0000645 }
Manuel Klimeka71e5d82013-01-02 16:30:12 +0000646
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000647 switch (FormatTok->Tok.getIdentifierInfo()->getPPKeywordID()) {
Manuel Klimek1abf7892013-01-04 23:34:14 +0000648 case tok::pp_define:
649 parsePPDefine();
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000650 return;
651 case tok::pp_if:
Manuel Klimek71814b42013-10-11 21:25:45 +0000652 parsePPIf(/*IfDef=*/false);
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000653 break;
654 case tok::pp_ifdef:
655 case tok::pp_ifndef:
Manuel Klimek71814b42013-10-11 21:25:45 +0000656 parsePPIf(/*IfDef=*/true);
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000657 break;
658 case tok::pp_else:
659 parsePPElse();
660 break;
661 case tok::pp_elif:
662 parsePPElIf();
663 break;
664 case tok::pp_endif:
665 parsePPEndIf();
Manuel Klimek1abf7892013-01-04 23:34:14 +0000666 break;
667 default:
668 parsePPUnknown();
669 break;
670 }
671}
672
Manuel Klimek68b03042014-04-14 09:14:11 +0000673void UnwrappedLineParser::conditionalCompilationCondition(bool Unreachable) {
Francois Ferranda98a95c2017-07-28 07:56:14 +0000674 size_t Line = CurrentLines->size();
675 if (CurrentLines == &PreprocessorDirectives)
676 Line += Lines.size();
677
678 if (Unreachable ||
679 (!PPStack.empty() && PPStack.back().Kind == PP_Unreachable))
680 PPStack.push_back({PP_Unreachable, Line});
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000681 else
Francois Ferranda98a95c2017-07-28 07:56:14 +0000682 PPStack.push_back({PP_Conditional, Line});
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000683}
684
Manuel Klimek68b03042014-04-14 09:14:11 +0000685void UnwrappedLineParser::conditionalCompilationStart(bool Unreachable) {
Manuel Klimek71814b42013-10-11 21:25:45 +0000686 ++PPBranchLevel;
687 assert(PPBranchLevel >= 0 && PPBranchLevel <= (int)PPLevelBranchIndex.size());
688 if (PPBranchLevel == (int)PPLevelBranchIndex.size()) {
689 PPLevelBranchIndex.push_back(0);
690 PPLevelBranchCount.push_back(0);
691 }
692 PPChainBranchIndex.push(0);
Manuel Klimek68b03042014-04-14 09:14:11 +0000693 bool Skip = PPLevelBranchIndex[PPBranchLevel] > 0;
694 conditionalCompilationCondition(Unreachable || Skip);
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000695}
696
Manuel Klimek68b03042014-04-14 09:14:11 +0000697void UnwrappedLineParser::conditionalCompilationAlternative() {
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000698 if (!PPStack.empty())
699 PPStack.pop_back();
Manuel Klimek71814b42013-10-11 21:25:45 +0000700 assert(PPBranchLevel < (int)PPLevelBranchIndex.size());
701 if (!PPChainBranchIndex.empty())
702 ++PPChainBranchIndex.top();
Manuel Klimek68b03042014-04-14 09:14:11 +0000703 conditionalCompilationCondition(
704 PPBranchLevel >= 0 && !PPChainBranchIndex.empty() &&
705 PPLevelBranchIndex[PPBranchLevel] != PPChainBranchIndex.top());
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000706}
707
Manuel Klimek68b03042014-04-14 09:14:11 +0000708void UnwrappedLineParser::conditionalCompilationEnd() {
Manuel Klimek71814b42013-10-11 21:25:45 +0000709 assert(PPBranchLevel < (int)PPLevelBranchIndex.size());
710 if (PPBranchLevel >= 0 && !PPChainBranchIndex.empty()) {
711 if (PPChainBranchIndex.top() + 1 > PPLevelBranchCount[PPBranchLevel]) {
Manuel Klimek71814b42013-10-11 21:25:45 +0000712 PPLevelBranchCount[PPBranchLevel] = PPChainBranchIndex.top() + 1;
713 }
714 }
Manuel Klimek14bd9172014-01-29 08:49:02 +0000715 // Guard against #endif's without #if.
Krasimir Georgievad47c902017-08-30 14:34:57 +0000716 if (PPBranchLevel > -1)
Manuel Klimek14bd9172014-01-29 08:49:02 +0000717 --PPBranchLevel;
Manuel Klimek71814b42013-10-11 21:25:45 +0000718 if (!PPChainBranchIndex.empty())
719 PPChainBranchIndex.pop();
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000720 if (!PPStack.empty())
721 PPStack.pop_back();
Manuel Klimek68b03042014-04-14 09:14:11 +0000722}
723
724void UnwrappedLineParser::parsePPIf(bool IfDef) {
Daniel Jasper62703eb2017-03-01 11:10:11 +0000725 bool IfNDef = FormatTok->is(tok::pp_ifndef);
Manuel Klimek68b03042014-04-14 09:14:11 +0000726 nextToken();
Daniel Jaspereab6cd42017-03-01 10:47:52 +0000727 bool Unreachable = false;
728 if (!IfDef && (FormatTok->is(tok::kw_false) || FormatTok->TokenText == "0"))
729 Unreachable = true;
Daniel Jasper62703eb2017-03-01 11:10:11 +0000730 if (IfDef && !IfNDef && FormatTok->TokenText == "SWIG")
Daniel Jaspereab6cd42017-03-01 10:47:52 +0000731 Unreachable = true;
732 conditionalCompilationStart(Unreachable);
Krasimir Georgievad47c902017-08-30 14:34:57 +0000733 FormatToken *IfCondition = FormatTok;
734 // If there's a #ifndef on the first line, and the only lines before it are
735 // comments, it could be an include guard.
736 bool MaybeIncludeGuard = IfNDef;
Mark Zeren1c3afaf2018-02-05 15:59:00 +0000737 if (IncludeGuard == IG_Inited && MaybeIncludeGuard)
Krasimir Georgievad47c902017-08-30 14:34:57 +0000738 for (auto &Line : Lines) {
739 if (!Line.Tokens.front().Tok->is(tok::comment)) {
740 MaybeIncludeGuard = false;
Mark Zeren1c3afaf2018-02-05 15:59:00 +0000741 IncludeGuard = IG_Rejected;
Krasimir Georgievad47c902017-08-30 14:34:57 +0000742 break;
743 }
744 }
Krasimir Georgievad47c902017-08-30 14:34:57 +0000745 --PPBranchLevel;
Manuel Klimek68b03042014-04-14 09:14:11 +0000746 parsePPUnknown();
Krasimir Georgievad47c902017-08-30 14:34:57 +0000747 ++PPBranchLevel;
Mark Zeren1c3afaf2018-02-05 15:59:00 +0000748 if (IncludeGuard == IG_Inited && MaybeIncludeGuard) {
749 IncludeGuard = IG_IfNdefed;
750 IncludeGuardToken = IfCondition;
751 }
Manuel Klimek68b03042014-04-14 09:14:11 +0000752}
753
754void UnwrappedLineParser::parsePPElse() {
Krasimir Georgievad47c902017-08-30 14:34:57 +0000755 // If a potential include guard has an #else, it's not an include guard.
Mark Zeren1c3afaf2018-02-05 15:59:00 +0000756 if (IncludeGuard == IG_Defined && PPBranchLevel == 0)
757 IncludeGuard = IG_Rejected;
Manuel Klimek68b03042014-04-14 09:14:11 +0000758 conditionalCompilationAlternative();
Krasimir Georgievad47c902017-08-30 14:34:57 +0000759 if (PPBranchLevel > -1)
760 --PPBranchLevel;
Manuel Klimek68b03042014-04-14 09:14:11 +0000761 parsePPUnknown();
Krasimir Georgievad47c902017-08-30 14:34:57 +0000762 ++PPBranchLevel;
Manuel Klimek68b03042014-04-14 09:14:11 +0000763}
764
765void UnwrappedLineParser::parsePPElIf() { parsePPElse(); }
766
767void UnwrappedLineParser::parsePPEndIf() {
768 conditionalCompilationEnd();
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000769 parsePPUnknown();
Krasimir Georgievad47c902017-08-30 14:34:57 +0000770 // If the #endif of a potential include guard is the last thing in the file,
Mark Zeren1c3afaf2018-02-05 15:59:00 +0000771 // then we found an include guard.
Krasimir Georgievad47c902017-08-30 14:34:57 +0000772 unsigned TokenPosition = Tokens->getPosition();
773 FormatToken *PeekNext = AllTokens[TokenPosition];
Mark Zeren1c3afaf2018-02-05 15:59:00 +0000774 if (IncludeGuard == IG_Defined && PPBranchLevel == -1 &&
775 PeekNext->is(tok::eof) &&
Daniel Jasper4df130f2017-09-04 13:33:52 +0000776 Style.IndentPPDirectives != FormatStyle::PPDIS_None)
Mark Zeren1c3afaf2018-02-05 15:59:00 +0000777 IncludeGuard = IG_Found;
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000778}
779
Manuel Klimek1abf7892013-01-04 23:34:14 +0000780void UnwrappedLineParser::parsePPDefine() {
781 nextToken();
782
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000783 if (FormatTok->Tok.getKind() != tok::identifier) {
Mark Zeren1c3afaf2018-02-05 15:59:00 +0000784 IncludeGuard = IG_Rejected;
785 IncludeGuardToken = nullptr;
Manuel Klimek1abf7892013-01-04 23:34:14 +0000786 parsePPUnknown();
787 return;
788 }
Mark Zeren1c3afaf2018-02-05 15:59:00 +0000789
790 if (IncludeGuard == IG_IfNdefed &&
791 IncludeGuardToken->TokenText == FormatTok->TokenText) {
792 IncludeGuard = IG_Defined;
793 IncludeGuardToken = nullptr;
Krasimir Georgievad47c902017-08-30 14:34:57 +0000794 for (auto &Line : Lines) {
795 if (!Line.Tokens.front().Tok->isOneOf(tok::comment, tok::hash)) {
Mark Zeren1c3afaf2018-02-05 15:59:00 +0000796 IncludeGuard = IG_Rejected;
Krasimir Georgievad47c902017-08-30 14:34:57 +0000797 break;
798 }
799 }
800 }
Mark Zeren1c3afaf2018-02-05 15:59:00 +0000801
Manuel Klimek1abf7892013-01-04 23:34:14 +0000802 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000803 if (FormatTok->Tok.getKind() == tok::l_paren &&
804 FormatTok->WhitespaceRange.getBegin() ==
805 FormatTok->WhitespaceRange.getEnd()) {
Manuel Klimek1abf7892013-01-04 23:34:14 +0000806 parseParens();
807 }
Krasimir Georgievad47c902017-08-30 14:34:57 +0000808 if (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash)
809 Line->Level += PPBranchLevel + 1;
Manuel Klimek1abf7892013-01-04 23:34:14 +0000810 addUnwrappedLine();
Krasimir Georgievad47c902017-08-30 14:34:57 +0000811 ++Line->Level;
Manuel Klimek1b896292013-01-07 09:34:28 +0000812
813 // Errors during a preprocessor directive can only affect the layout of the
814 // preprocessor directive, and thus we ignore them. An alternative approach
815 // would be to use the same approach we use on the file level (no
816 // re-indentation if there was a structural error) within the macro
817 // definition.
Manuel Klimek1abf7892013-01-04 23:34:14 +0000818 parseFile();
819}
820
821void UnwrappedLineParser::parsePPUnknown() {
Manuel Klimeka71e5d82013-01-02 16:30:12 +0000822 do {
Manuel Klimeka71e5d82013-01-02 16:30:12 +0000823 nextToken();
824 } while (!eof());
Krasimir Georgievad47c902017-08-30 14:34:57 +0000825 if (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash)
826 Line->Level += PPBranchLevel + 1;
Manuel Klimeka71e5d82013-01-02 16:30:12 +0000827 addUnwrappedLine();
Daniel Jasperf7935112012-12-03 18:12:45 +0000828}
829
Alexander Kornienkoa04e5e22013-04-09 16:15:19 +0000830// Here we blacklist certain tokens that are not usually the first token in an
831// unwrapped line. This is used in attempt to distinguish macro calls without
832// trailing semicolons from other constructs split to several lines.
Benjamin Kramer8407df72015-03-09 16:47:52 +0000833static bool tokenCanStartNewLine(const clang::Token &Tok) {
Alexander Kornienkoa04e5e22013-04-09 16:15:19 +0000834 // Semicolon can be a null-statement, l_square can be a start of a macro or
835 // a C++11 attribute, but this doesn't seem to be common.
836 return Tok.isNot(tok::semi) && Tok.isNot(tok::l_brace) &&
837 Tok.isNot(tok::l_square) &&
838 // Tokens that can only be used as binary operators and a part of
839 // overloaded operator names.
840 Tok.isNot(tok::period) && Tok.isNot(tok::periodstar) &&
841 Tok.isNot(tok::arrow) && Tok.isNot(tok::arrowstar) &&
842 Tok.isNot(tok::less) && Tok.isNot(tok::greater) &&
843 Tok.isNot(tok::slash) && Tok.isNot(tok::percent) &&
844 Tok.isNot(tok::lessless) && Tok.isNot(tok::greatergreater) &&
845 Tok.isNot(tok::equal) && Tok.isNot(tok::plusequal) &&
846 Tok.isNot(tok::minusequal) && Tok.isNot(tok::starequal) &&
847 Tok.isNot(tok::slashequal) && Tok.isNot(tok::percentequal) &&
848 Tok.isNot(tok::ampequal) && Tok.isNot(tok::pipeequal) &&
849 Tok.isNot(tok::caretequal) && Tok.isNot(tok::greatergreaterequal) &&
850 Tok.isNot(tok::lesslessequal) &&
851 // Colon is used in labels, base class lists, initializer lists,
852 // range-based for loops, ternary operator, but should never be the
853 // first token in an unwrapped line.
Daniel Jasper5ebb2f32014-05-21 13:08:17 +0000854 Tok.isNot(tok::colon) &&
855 // 'noexcept' is a trailing annotation.
856 Tok.isNot(tok::kw_noexcept);
Alexander Kornienkoa04e5e22013-04-09 16:15:19 +0000857}
858
Martin Probst533965c2016-04-19 18:19:06 +0000859static bool mustBeJSIdent(const AdditionalKeywords &Keywords,
860 const FormatToken *FormatTok) {
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +0000861 // FIXME: This returns true for C/C++ keywords like 'struct'.
862 return FormatTok->is(tok::identifier) &&
863 (FormatTok->Tok.getIdentifierInfo() == nullptr ||
Martin Probst3dbbefa2016-11-10 16:21:02 +0000864 !FormatTok->isOneOf(
865 Keywords.kw_in, Keywords.kw_of, Keywords.kw_as, Keywords.kw_async,
866 Keywords.kw_await, Keywords.kw_yield, Keywords.kw_finally,
867 Keywords.kw_function, Keywords.kw_import, Keywords.kw_is,
868 Keywords.kw_let, Keywords.kw_var, tok::kw_const,
869 Keywords.kw_abstract, Keywords.kw_extends, Keywords.kw_implements,
Manuel Klimek89628f62017-09-20 09:51:03 +0000870 Keywords.kw_instanceof, Keywords.kw_interface, Keywords.kw_throws,
871 Keywords.kw_from));
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +0000872}
873
Martin Probst533965c2016-04-19 18:19:06 +0000874static bool mustBeJSIdentOrValue(const AdditionalKeywords &Keywords,
875 const FormatToken *FormatTok) {
Martin Probstb9316ff2016-09-18 17:21:52 +0000876 return FormatTok->Tok.isLiteral() ||
877 FormatTok->isOneOf(tok::kw_true, tok::kw_false) ||
878 mustBeJSIdent(Keywords, FormatTok);
Martin Probst533965c2016-04-19 18:19:06 +0000879}
880
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +0000881// isJSDeclOrStmt returns true if |FormatTok| starts a declaration or statement
882// when encountered after a value (see mustBeJSIdentOrValue).
883static bool isJSDeclOrStmt(const AdditionalKeywords &Keywords,
884 const FormatToken *FormatTok) {
885 return FormatTok->isOneOf(
Martin Probst5f8445b2016-04-24 22:05:09 +0000886 tok::kw_return, Keywords.kw_yield,
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +0000887 // conditionals
888 tok::kw_if, tok::kw_else,
889 // loops
890 tok::kw_for, tok::kw_while, tok::kw_do, tok::kw_continue, tok::kw_break,
891 // switch/case
892 tok::kw_switch, tok::kw_case,
893 // exceptions
894 tok::kw_throw, tok::kw_try, tok::kw_catch, Keywords.kw_finally,
895 // declaration
896 tok::kw_const, tok::kw_class, Keywords.kw_var, Keywords.kw_let,
Martin Probst5f8445b2016-04-24 22:05:09 +0000897 Keywords.kw_async, Keywords.kw_function,
898 // import/export
899 Keywords.kw_import, tok::kw_export);
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +0000900}
901
902// readTokenWithJavaScriptASI reads the next token and terminates the current
903// line if JavaScript Automatic Semicolon Insertion must
904// happen between the current token and the next token.
905//
906// This method is conservative - it cannot cover all edge cases of JavaScript,
907// but only aims to correctly handle certain well known cases. It *must not*
908// return true in speculative cases.
909void UnwrappedLineParser::readTokenWithJavaScriptASI() {
910 FormatToken *Previous = FormatTok;
911 readToken();
912 FormatToken *Next = FormatTok;
913
914 bool IsOnSameLine =
915 CommentsBeforeNextToken.empty()
916 ? Next->NewlinesBefore == 0
917 : CommentsBeforeNextToken.front()->NewlinesBefore == 0;
918 if (IsOnSameLine)
919 return;
920
921 bool PreviousMustBeValue = mustBeJSIdentOrValue(Keywords, Previous);
Martin Probst717f6dc2016-10-21 05:11:38 +0000922 bool PreviousStartsTemplateExpr =
923 Previous->is(TT_TemplateString) && Previous->TokenText.endswith("${");
Martin Probst7e0f25b2017-11-25 09:19:42 +0000924 if (PreviousMustBeValue || Previous->is(tok::r_paren)) {
925 // If the line contains an '@' sign, the previous token might be an
926 // annotation, which can precede another identifier/value.
927 bool HasAt = std::find_if(Line->Tokens.begin(), Line->Tokens.end(),
928 [](UnwrappedLineNode &LineNode) {
929 return LineNode.Tok->is(tok::at);
930 }) != Line->Tokens.end();
931 if (HasAt)
Martin Probstbbffeac2016-04-11 07:35:57 +0000932 return;
933 }
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +0000934 if (Next->is(tok::exclaim) && PreviousMustBeValue)
Martin Probstd40bca42017-01-09 08:56:36 +0000935 return addUnwrappedLine();
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +0000936 bool NextMustBeValue = mustBeJSIdentOrValue(Keywords, Next);
Martin Probst717f6dc2016-10-21 05:11:38 +0000937 bool NextEndsTemplateExpr =
938 Next->is(TT_TemplateString) && Next->TokenText.startswith("}");
939 if (NextMustBeValue && !NextEndsTemplateExpr && !PreviousStartsTemplateExpr &&
940 (PreviousMustBeValue ||
941 Previous->isOneOf(tok::r_square, tok::r_paren, tok::plusplus,
942 tok::minusminus)))
Martin Probstd40bca42017-01-09 08:56:36 +0000943 return addUnwrappedLine();
Martin Probst0a19d432017-08-09 15:19:16 +0000944 if ((PreviousMustBeValue || Previous->is(tok::r_paren)) &&
945 isJSDeclOrStmt(Keywords, Next))
Martin Probstd40bca42017-01-09 08:56:36 +0000946 return addUnwrappedLine();
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +0000947}
948
Manuel Klimek6b9eeba2013-01-07 14:56:16 +0000949void UnwrappedLineParser::parseStructuralElement() {
Daniel Jasper498f5582015-12-25 08:53:31 +0000950 assert(!FormatTok->is(tok::l_brace));
951 if (Style.Language == FormatStyle::LK_TableGen &&
952 FormatTok->is(tok::pp_include)) {
953 nextToken();
954 if (FormatTok->is(tok::string_literal))
955 nextToken();
956 addUnwrappedLine();
957 return;
958 }
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000959 switch (FormatTok->Tok.getKind()) {
Daniel Jasper8f463652014-08-26 23:15:12 +0000960 case tok::kw_asm:
Daniel Jasper8f463652014-08-26 23:15:12 +0000961 nextToken();
962 if (FormatTok->is(tok::l_brace)) {
Daniel Jasperc6366072015-05-10 08:42:04 +0000963 FormatTok->Type = TT_InlineASMBrace;
Daniel Jasper2337f282015-01-12 10:14:56 +0000964 nextToken();
Daniel Jasper4429f142014-08-27 17:16:46 +0000965 while (FormatTok && FormatTok->isNot(tok::eof)) {
Daniel Jasper8f463652014-08-26 23:15:12 +0000966 if (FormatTok->is(tok::r_brace)) {
Daniel Jasperc6366072015-05-10 08:42:04 +0000967 FormatTok->Type = TT_InlineASMBrace;
Daniel Jasper8f463652014-08-26 23:15:12 +0000968 nextToken();
Daniel Jasper790d4f92015-05-11 11:59:46 +0000969 addUnwrappedLine();
Daniel Jasper8f463652014-08-26 23:15:12 +0000970 break;
971 }
Daniel Jasper2337f282015-01-12 10:14:56 +0000972 FormatTok->Finalized = true;
Daniel Jasper8f463652014-08-26 23:15:12 +0000973 nextToken();
974 }
975 }
976 break;
Alexander Kornienko578fdd82012-12-06 18:03:27 +0000977 case tok::kw_namespace:
978 parseNamespace();
979 return;
Dmitri Gribenko58d64e22012-12-30 21:27:25 +0000980 case tok::kw_inline:
981 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000982 if (FormatTok->Tok.is(tok::kw_namespace)) {
Dmitri Gribenko58d64e22012-12-30 21:27:25 +0000983 parseNamespace();
984 return;
985 }
986 break;
Alexander Kornienkob7076a22012-12-04 14:46:19 +0000987 case tok::kw_public:
988 case tok::kw_protected:
989 case tok::kw_private:
Daniel Jasper83709082015-02-18 17:14:05 +0000990 if (Style.Language == FormatStyle::LK_Java ||
991 Style.Language == FormatStyle::LK_JavaScript)
Daniel Jasperc58c70e2014-09-15 11:21:46 +0000992 nextToken();
993 else
994 parseAccessSpecifier();
Daniel Jasperf7935112012-12-03 18:12:45 +0000995 return;
Alexander Kornienkob7076a22012-12-04 14:46:19 +0000996 case tok::kw_if:
997 parseIfThenElse();
Daniel Jasperf7935112012-12-03 18:12:45 +0000998 return;
Alexander Kornienko37d6c942012-12-05 15:06:06 +0000999 case tok::kw_for:
1000 case tok::kw_while:
1001 parseForOrWhileLoop();
1002 return;
Alexander Kornienkob7076a22012-12-04 14:46:19 +00001003 case tok::kw_do:
1004 parseDoWhile();
1005 return;
1006 case tok::kw_switch:
Martin Probstf785fd92017-08-04 17:07:15 +00001007 if (Style.Language == FormatStyle::LK_JavaScript && Line->MustBeDeclaration)
1008 // 'switch: string' field declaration.
1009 break;
Alexander Kornienkob7076a22012-12-04 14:46:19 +00001010 parseSwitch();
1011 return;
1012 case tok::kw_default:
Martin Probstf785fd92017-08-04 17:07:15 +00001013 if (Style.Language == FormatStyle::LK_JavaScript && Line->MustBeDeclaration)
1014 // 'default: string' field declaration.
1015 break;
Alexander Kornienkob7076a22012-12-04 14:46:19 +00001016 nextToken();
Nico Weberc29f83b2018-01-23 16:30:56 +00001017 if (FormatTok->is(tok::colon)) {
1018 parseLabel();
1019 return;
1020 }
1021 // e.g. "default void f() {}" in a Java interface.
1022 break;
Alexander Kornienkob7076a22012-12-04 14:46:19 +00001023 case tok::kw_case:
Martin Probstf785fd92017-08-04 17:07:15 +00001024 if (Style.Language == FormatStyle::LK_JavaScript && Line->MustBeDeclaration)
1025 // 'case: string' field declaration.
1026 break;
Alexander Kornienkob7076a22012-12-04 14:46:19 +00001027 parseCaseLabel();
1028 return;
Daniel Jasper04a71a42014-05-08 11:58:24 +00001029 case tok::kw_try:
Nico Weberfac23712015-02-04 15:26:27 +00001030 case tok::kw___try:
Daniel Jasper04a71a42014-05-08 11:58:24 +00001031 parseTryCatch();
1032 return;
Manuel Klimekae610d12013-01-21 14:32:05 +00001033 case tok::kw_extern:
1034 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001035 if (FormatTok->Tok.is(tok::string_literal)) {
Manuel Klimekae610d12013-01-21 14:32:05 +00001036 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001037 if (FormatTok->Tok.is(tok::l_brace)) {
Krasimir Georgievd6ce9372017-09-15 11:23:50 +00001038 if (Style.BraceWrapping.AfterExternBlock) {
1039 addUnwrappedLine();
1040 parseBlock(/*MustBeDeclaration=*/true);
1041 } else {
1042 parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/false);
1043 }
Manuel Klimekae610d12013-01-21 14:32:05 +00001044 addUnwrappedLine();
1045 return;
1046 }
1047 }
Daniel Jaspere1e43192014-04-01 12:55:11 +00001048 break;
Daniel Jasperfca735c2015-02-19 16:14:18 +00001049 case tok::kw_export:
1050 if (Style.Language == FormatStyle::LK_JavaScript) {
1051 parseJavaScriptEs6ImportExport();
1052 return;
1053 }
1054 break;
Daniel Jaspere1e43192014-04-01 12:55:11 +00001055 case tok::identifier:
Daniel Jasper66cb8c52015-05-04 09:22:29 +00001056 if (FormatTok->is(TT_ForEachMacro)) {
Daniel Jaspere1e43192014-04-01 12:55:11 +00001057 parseForOrWhileLoop();
1058 return;
1059 }
Birunthan Mohanathasb001a0b2015-07-03 17:25:16 +00001060 if (FormatTok->is(TT_MacroBlockBegin)) {
1061 parseBlock(/*MustBeDeclaration=*/false, /*AddLevel=*/true,
1062 /*MunchSemi=*/false);
1063 return;
1064 }
Daniel Jasper3d5a7d62016-06-20 18:20:38 +00001065 if (FormatTok->is(Keywords.kw_import)) {
1066 if (Style.Language == FormatStyle::LK_JavaScript) {
1067 parseJavaScriptEs6ImportExport();
1068 return;
1069 }
1070 if (Style.Language == FormatStyle::LK_Proto) {
1071 nextToken();
Daniel Jasper8b61d142016-06-20 20:39:53 +00001072 if (FormatTok->is(tok::kw_public))
1073 nextToken();
Daniel Jasper3d5a7d62016-06-20 18:20:38 +00001074 if (!FormatTok->is(tok::string_literal))
1075 return;
1076 nextToken();
1077 if (FormatTok->is(tok::semi))
1078 nextToken();
1079 addUnwrappedLine();
1080 return;
1081 }
Daniel Jasper354aa512015-02-19 16:07:32 +00001082 }
Daniel Jasper1dbc2102017-03-31 13:30:24 +00001083 if (Style.isCpp() &&
Daniel Jasper72b33572017-03-31 12:04:37 +00001084 FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
Daniel Jaspera00de632015-12-01 12:05:04 +00001085 Keywords.kw_slots, Keywords.kw_qslots)) {
Daniel Jasperde0d1f32015-04-24 07:50:34 +00001086 nextToken();
1087 if (FormatTok->is(tok::colon)) {
1088 nextToken();
1089 addUnwrappedLine();
Daniel Jasper31343832016-07-27 10:13:24 +00001090 return;
Daniel Jasperde0d1f32015-04-24 07:50:34 +00001091 }
Daniel Jasper53395402015-04-07 15:04:40 +00001092 }
Manuel Klimekae610d12013-01-21 14:32:05 +00001093 // In all other cases, parse the declaration.
1094 break;
Alexander Kornienkob7076a22012-12-04 14:46:19 +00001095 default:
1096 break;
Daniel Jasperf7935112012-12-03 18:12:45 +00001097 }
Daniel Jasperf7935112012-12-03 18:12:45 +00001098 do {
Manuel Klimeke411aa82017-09-20 09:29:37 +00001099 const FormatToken *Previous = FormatTok->Previous;
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001100 switch (FormatTok->Tok.getKind()) {
Nico Weber372d8dc2013-02-10 20:35:35 +00001101 case tok::at:
1102 nextToken();
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001103 if (FormatTok->Tok.is(tok::l_brace)) {
1104 nextToken();
Nico Weber372d8dc2013-02-10 20:35:35 +00001105 parseBracedList();
Nico Weberc068ff72018-01-23 17:10:25 +00001106 break;
1107 }
1108 switch (FormatTok->Tok.getObjCKeywordID()) {
1109 case tok::objc_public:
1110 case tok::objc_protected:
1111 case tok::objc_package:
1112 case tok::objc_private:
1113 return parseAccessSpecifier();
1114 case tok::objc_interface:
1115 case tok::objc_implementation:
1116 return parseObjCInterfaceOrImplementation();
1117 case tok::objc_protocol:
1118 if (parseObjCProtocol())
1119 return;
1120 break;
1121 case tok::objc_end:
1122 return; // Handled by the caller.
1123 case tok::objc_optional:
1124 case tok::objc_required:
1125 nextToken();
1126 addUnwrappedLine();
1127 return;
1128 case tok::objc_autoreleasepool:
1129 nextToken();
1130 if (FormatTok->Tok.is(tok::l_brace)) {
Francois Ferranda2484b22018-02-27 13:48:27 +00001131 if (Style.BraceWrapping.AfterControlStatement)
Nico Weberc068ff72018-01-23 17:10:25 +00001132 addUnwrappedLine();
1133 parseBlock(/*MustBeDeclaration=*/false);
1134 }
1135 addUnwrappedLine();
1136 return;
Francois Ferrandba91c3d2018-02-27 13:48:21 +00001137 case tok::objc_synchronized:
1138 nextToken();
1139 if (FormatTok->Tok.is(tok::l_paren))
1140 // Skip synchronization object
1141 parseParens();
1142 if (FormatTok->Tok.is(tok::l_brace)) {
Francois Ferranda2484b22018-02-27 13:48:27 +00001143 if (Style.BraceWrapping.AfterControlStatement)
Francois Ferrandba91c3d2018-02-27 13:48:21 +00001144 addUnwrappedLine();
1145 parseBlock(/*MustBeDeclaration=*/false);
1146 }
1147 addUnwrappedLine();
1148 return;
Nico Weberc068ff72018-01-23 17:10:25 +00001149 case tok::objc_try:
1150 // This branch isn't strictly necessary (the kw_try case below would
1151 // do this too after the tok::at is parsed above). But be explicit.
1152 parseTryCatch();
1153 return;
1154 default:
1155 break;
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001156 }
Nico Weber372d8dc2013-02-10 20:35:35 +00001157 break;
Alexander Kornienkob7076a22012-12-04 14:46:19 +00001158 case tok::kw_enum:
Daniel Jaspera7900ad2016-05-08 18:12:22 +00001159 // Ignore if this is part of "template <enum ...".
1160 if (Previous && Previous->is(tok::less)) {
1161 nextToken();
1162 break;
1163 }
1164
Daniel Jasper90cf3802015-06-17 09:44:02 +00001165 // parseEnum falls through and does not yet add an unwrapped line as an
1166 // enum definition can start a structural element.
Daniel Jasper6f5a1932015-12-29 08:54:23 +00001167 if (!parseEnum())
1168 break;
Daniel Jasperc6dd2732015-07-16 14:25:43 +00001169 // This only applies for C++.
Daniel Jasper1dbc2102017-03-31 13:30:24 +00001170 if (!Style.isCpp()) {
Daniel Jasper90cf3802015-06-17 09:44:02 +00001171 addUnwrappedLine();
1172 return;
1173 }
Manuel Klimek2cec0192013-01-21 19:17:52 +00001174 break;
Daniel Jaspera88f80a2014-01-30 14:38:37 +00001175 case tok::kw_typedef:
1176 nextToken();
Daniel Jasper31f6c542014-12-05 10:42:21 +00001177 if (FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS,
1178 Keywords.kw_CF_ENUM, Keywords.kw_CF_OPTIONS))
Daniel Jaspera88f80a2014-01-30 14:38:37 +00001179 parseEnum();
1180 break;
Alexander Kornienko1231e062013-01-16 11:43:46 +00001181 case tok::kw_struct:
1182 case tok::kw_union:
Manuel Klimek28cacc72013-01-07 18:10:23 +00001183 case tok::kw_class:
Daniel Jasper910807d2015-06-12 04:52:02 +00001184 // parseRecord falls through and does not yet add an unwrapped line as a
1185 // record declaration or definition can start a structural element.
Manuel Klimeke01bab52013-01-15 13:38:33 +00001186 parseRecord();
Daniel Jasper910807d2015-06-12 04:52:02 +00001187 // This does not apply for Java and JavaScript.
1188 if (Style.Language == FormatStyle::LK_Java ||
1189 Style.Language == FormatStyle::LK_JavaScript) {
Daniel Jasperd5ec65b2016-01-08 07:06:07 +00001190 if (FormatTok->is(tok::semi))
1191 nextToken();
Daniel Jasper910807d2015-06-12 04:52:02 +00001192 addUnwrappedLine();
1193 return;
1194 }
Manuel Klimeke01bab52013-01-15 13:38:33 +00001195 break;
Daniel Jaspere5d74862014-11-26 08:17:08 +00001196 case tok::period:
1197 nextToken();
1198 // In Java, classes have an implicit static member "class".
1199 if (Style.Language == FormatStyle::LK_Java && FormatTok &&
1200 FormatTok->is(tok::kw_class))
1201 nextToken();
Daniel Jasperba52fcb2015-09-28 14:29:45 +00001202 if (Style.Language == FormatStyle::LK_JavaScript && FormatTok &&
1203 FormatTok->Tok.getIdentifierInfo())
1204 // JavaScript only has pseudo keywords, all keywords are allowed to
1205 // appear in "IdentifierName" positions. See http://es5.github.io/#x7.6
1206 nextToken();
Daniel Jaspere5d74862014-11-26 08:17:08 +00001207 break;
Daniel Jasperf7935112012-12-03 18:12:45 +00001208 case tok::semi:
1209 nextToken();
1210 addUnwrappedLine();
1211 return;
Alexander Kornienko1231e062013-01-16 11:43:46 +00001212 case tok::r_brace:
1213 addUnwrappedLine();
1214 return;
Daniel Jasperf7935112012-12-03 18:12:45 +00001215 case tok::l_paren:
1216 parseParens();
1217 break;
Daniel Jasper5af04a42015-10-07 03:43:10 +00001218 case tok::kw_operator:
1219 nextToken();
1220 if (FormatTok->isBinaryOperator())
1221 nextToken();
1222 break;
Manuel Klimek516e0542013-09-04 13:25:30 +00001223 case tok::caret:
1224 nextToken();
Daniel Jasper395193c2014-03-28 07:48:59 +00001225 if (FormatTok->Tok.isAnyIdentifier() ||
1226 FormatTok->isSimpleTypeSpecifier())
1227 nextToken();
1228 if (FormatTok->is(tok::l_paren))
1229 parseParens();
1230 if (FormatTok->is(tok::l_brace))
Manuel Klimek516e0542013-09-04 13:25:30 +00001231 parseChildBlock();
Manuel Klimek516e0542013-09-04 13:25:30 +00001232 break;
Daniel Jasperf7935112012-12-03 18:12:45 +00001233 case tok::l_brace:
Manuel Klimekab419912013-05-23 09:41:43 +00001234 if (!tryToParseBracedList()) {
1235 // A block outside of parentheses must be the last part of a
1236 // structural element.
1237 // FIXME: Figure out cases where this is not true, and add projections
1238 // for them (the one we know is missing are lambdas).
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00001239 if (Style.BraceWrapping.AfterFunction)
Manuel Klimekab419912013-05-23 09:41:43 +00001240 addUnwrappedLine();
Alexander Kornienko3cfa9732013-11-20 16:33:05 +00001241 FormatTok->Type = TT_FunctionLBrace;
Nico Weber9096fc02013-06-26 00:30:14 +00001242 parseBlock(/*MustBeDeclaration=*/false);
Manuel Klimeka8eb9142013-05-13 12:51:40 +00001243 addUnwrappedLine();
Manuel Klimekab419912013-05-23 09:41:43 +00001244 return;
1245 }
1246 // Otherwise this was a braced init list, and the structural
1247 // element continues.
1248 break;
Daniel Jasper04a71a42014-05-08 11:58:24 +00001249 case tok::kw_try:
1250 // We arrive here when parsing function-try blocks.
1251 parseTryCatch();
1252 return;
Daniel Jasper40e19212013-05-29 13:16:10 +00001253 case tok::identifier: {
Birunthan Mohanathasb001a0b2015-07-03 17:25:16 +00001254 if (FormatTok->is(TT_MacroBlockEnd)) {
1255 addUnwrappedLine();
1256 return;
1257 }
1258
Martin Probst973ff792017-04-27 13:07:24 +00001259 // Function declarations (as opposed to function expressions) are parsed
1260 // on their own unwrapped line by continuing this loop. Function
1261 // expressions (functions that are not on their own line) must not create
1262 // a new unwrapped line, so they are special cased below.
1263 size_t TokenCount = Line->Tokens.size();
Daniel Jasper9326f912015-05-05 08:40:32 +00001264 if (Style.Language == FormatStyle::LK_JavaScript &&
Martin Probst973ff792017-04-27 13:07:24 +00001265 FormatTok->is(Keywords.kw_function) &&
1266 (TokenCount > 1 || (TokenCount == 1 && !Line->Tokens.front().Tok->is(
1267 Keywords.kw_async)))) {
Daniel Jasper069e5f42014-05-20 11:14:57 +00001268 tryToParseJSFunction();
1269 break;
1270 }
Daniel Jasper9326f912015-05-05 08:40:32 +00001271 if ((Style.Language == FormatStyle::LK_JavaScript ||
1272 Style.Language == FormatStyle::LK_Java) &&
1273 FormatTok->is(Keywords.kw_interface)) {
Martin Probst1e8261e2016-04-19 18:18:59 +00001274 if (Style.Language == FormatStyle::LK_JavaScript) {
1275 // In JavaScript/TypeScript, "interface" can be used as a standalone
1276 // identifier, e.g. in `var interface = 1;`. If "interface" is
1277 // followed by another identifier, it is very like to be an actual
1278 // interface declaration.
1279 unsigned StoredPosition = Tokens->getPosition();
1280 FormatToken *Next = Tokens->getNextToken();
1281 FormatTok = Tokens->setPosition(StoredPosition);
Martin Probst533965c2016-04-19 18:19:06 +00001282 if (Next && !mustBeJSIdent(Keywords, Next)) {
Martin Probst1e8261e2016-04-19 18:18:59 +00001283 nextToken();
1284 break;
1285 }
1286 }
Daniel Jasper9326f912015-05-05 08:40:32 +00001287 parseRecord();
Daniel Jasper259188b2015-06-12 04:56:34 +00001288 addUnwrappedLine();
Daniel Jasper5c235c02015-07-06 14:26:04 +00001289 return;
Daniel Jasper9326f912015-05-05 08:40:32 +00001290 }
1291
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +00001292 // See if the following token should start a new unwrapped line.
Daniel Jasper9326f912015-05-05 08:40:32 +00001293 StringRef Text = FormatTok->TokenText;
Daniel Jasperf7935112012-12-03 18:12:45 +00001294 nextToken();
Daniel Jasper83709082015-02-18 17:14:05 +00001295 if (Line->Tokens.size() == 1 &&
1296 // JS doesn't have macros, and within classes colons indicate fields,
1297 // not labels.
Daniel Jasper676e5162015-04-07 14:36:33 +00001298 Style.Language != FormatStyle::LK_JavaScript) {
1299 if (FormatTok->Tok.is(tok::colon) && !Line->MustBeDeclaration) {
Daniel Jasper40609472016-04-06 15:02:46 +00001300 Line->Tokens.begin()->Tok->MustBreakBefore = true;
Alexander Kornienkode644272013-04-08 22:16:06 +00001301 parseLabel();
1302 return;
1303 }
Daniel Jasper680b09b2014-11-05 10:48:04 +00001304 // Recognize function-like macro usages without trailing semicolon as
Daniel Jasper83709082015-02-18 17:14:05 +00001305 // well as free-standing macros like Q_OBJECT.
Daniel Jasper680b09b2014-11-05 10:48:04 +00001306 bool FunctionLike = FormatTok->is(tok::l_paren);
1307 if (FunctionLike)
Alexander Kornienkode644272013-04-08 22:16:06 +00001308 parseParens();
Daniel Jaspere60cba12015-05-13 11:35:53 +00001309
1310 bool FollowedByNewline =
1311 CommentsBeforeNextToken.empty()
1312 ? FormatTok->NewlinesBefore > 0
1313 : CommentsBeforeNextToken.front()->NewlinesBefore > 0;
1314
Daniel Jaspere6fcf7d2015-06-17 13:08:06 +00001315 if (FollowedByNewline && (Text.size() >= 5 || FunctionLike) &&
Daniel Jasper680b09b2014-11-05 10:48:04 +00001316 tokenCanStartNewLine(FormatTok->Tok) && Text == Text.upper()) {
Daniel Jasper40e19212013-05-29 13:16:10 +00001317 addUnwrappedLine();
Daniel Jasper41a0f782013-05-29 14:09:17 +00001318 return;
Alexander Kornienkode644272013-04-08 22:16:06 +00001319 }
Daniel Jasperf7935112012-12-03 18:12:45 +00001320 }
1321 break;
Daniel Jasper40e19212013-05-29 13:16:10 +00001322 }
Daniel Jaspere25509f2012-12-17 11:29:41 +00001323 case tok::equal:
Manuel Klimek79e06082015-05-21 12:23:34 +00001324 // Fat arrows (=>) have tok::TokenKind tok::equal but TokenType
1325 // TT_JsFatArrow. The always start an expression or a child block if
1326 // followed by a curly.
1327 if (FormatTok->is(TT_JsFatArrow)) {
1328 nextToken();
Daniel Jasperbe520bd2015-05-31 08:51:54 +00001329 if (FormatTok->is(tok::l_brace))
Manuel Klimek79e06082015-05-21 12:23:34 +00001330 parseChildBlock();
Manuel Klimek79e06082015-05-21 12:23:34 +00001331 break;
1332 }
1333
Daniel Jaspere25509f2012-12-17 11:29:41 +00001334 nextToken();
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001335 if (FormatTok->Tok.is(tok::l_brace)) {
1336 nextToken();
Manuel Klimek8e07a1b2013-01-10 11:52:21 +00001337 parseBracedList();
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001338 } else if (Style.Language == FormatStyle::LK_Proto &&
Manuel Klimek89628f62017-09-20 09:51:03 +00001339 FormatTok->Tok.is(tok::less)) {
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001340 nextToken();
Krasimir Georgiev0b41fcb2017-06-27 13:58:41 +00001341 parseBracedList(/*ContinueOnSemicolons=*/false,
1342 /*ClosingBraceKind=*/tok::greater);
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001343 }
Daniel Jaspere25509f2012-12-17 11:29:41 +00001344 break;
Manuel Klimekffdeb592013-09-03 15:10:01 +00001345 case tok::l_square:
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001346 parseSquare();
Manuel Klimekffdeb592013-09-03 15:10:01 +00001347 break;
Daniel Jasper6acf5132015-03-12 14:44:29 +00001348 case tok::kw_new:
1349 parseNew();
1350 break;
Alexander Kornienkob7076a22012-12-04 14:46:19 +00001351 default:
1352 nextToken();
1353 break;
Daniel Jasperf7935112012-12-03 18:12:45 +00001354 }
1355 } while (!eof());
1356}
1357
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001358bool UnwrappedLineParser::tryToParseLambda() {
Daniel Jasper1dbc2102017-03-31 13:30:24 +00001359 if (!Style.isCpp()) {
Daniel Jasper1feab0f2015-06-02 15:31:37 +00001360 nextToken();
1361 return false;
1362 }
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +00001363 assert(FormatTok->is(tok::l_square));
1364 FormatToken &LSquare = *FormatTok;
Daniel Jasper9a8d48b2013-09-05 10:04:31 +00001365 if (!tryToParseLambdaIntroducer())
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001366 return false;
Manuel Klimekffdeb592013-09-03 15:10:01 +00001367
Alexander Kornienkoc2ee9cf2014-03-13 13:59:48 +00001368 while (FormatTok->isNot(tok::l_brace)) {
Daniel Jaspercb51cf42014-01-16 09:11:55 +00001369 if (FormatTok->isSimpleTypeSpecifier()) {
1370 nextToken();
1371 continue;
1372 }
Manuel Klimekffdeb592013-09-03 15:10:01 +00001373 switch (FormatTok->Tok.getKind()) {
Daniel Jasper9a8d48b2013-09-05 10:04:31 +00001374 case tok::l_brace:
1375 break;
1376 case tok::l_paren:
1377 parseParens();
1378 break;
Daniel Jasperbcb55ee2014-11-21 14:08:38 +00001379 case tok::amp:
1380 case tok::star:
1381 case tok::kw_const:
Daniel Jasper3431b752014-12-08 13:22:37 +00001382 case tok::comma:
Daniel Jaspercb51cf42014-01-16 09:11:55 +00001383 case tok::less:
1384 case tok::greater:
Daniel Jasper9a8d48b2013-09-05 10:04:31 +00001385 case tok::identifier:
Daniel Jasper5eaa0092015-08-13 13:37:08 +00001386 case tok::numeric_constant:
Daniel Jasper1067ab02014-02-11 10:16:55 +00001387 case tok::coloncolon:
Daniel Jasper9a8d48b2013-09-05 10:04:31 +00001388 case tok::kw_mutable:
Daniel Jasper81a20782014-03-10 10:02:02 +00001389 nextToken();
1390 break;
Daniel Jaspercb51cf42014-01-16 09:11:55 +00001391 case tok::arrow:
Daniel Jasper6f2b88a2015-06-05 13:18:09 +00001392 FormatTok->Type = TT_LambdaArrow;
Daniel Jasper9a8d48b2013-09-05 10:04:31 +00001393 nextToken();
1394 break;
1395 default:
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001396 return true;
Manuel Klimekffdeb592013-09-03 15:10:01 +00001397 }
1398 }
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +00001399 LSquare.Type = TT_LambdaLSquare;
Manuel Klimek516e0542013-09-04 13:25:30 +00001400 parseChildBlock();
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001401 return true;
Manuel Klimekffdeb592013-09-03 15:10:01 +00001402}
1403
1404bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
Manuel Klimek89628f62017-09-20 09:51:03 +00001405 const FormatToken *Previous = FormatTok->Previous;
Manuel Klimek9f0a4e52017-09-19 09:59:30 +00001406 if (Previous &&
1407 (Previous->isOneOf(tok::identifier, tok::kw_operator, tok::kw_new,
Manuel Klimekd0f3fe52018-04-11 14:51:54 +00001408 tok::kw_delete, tok::l_square) ||
Manuel Klimek89628f62017-09-20 09:51:03 +00001409 FormatTok->isCppStructuredBinding(Style) || Previous->closesScope() ||
1410 Previous->isSimpleTypeSpecifier())) {
Manuel Klimekffdeb592013-09-03 15:10:01 +00001411 nextToken();
Manuel Klimek9f0a4e52017-09-19 09:59:30 +00001412 return false;
Manuel Klimekffdeb592013-09-03 15:10:01 +00001413 }
Manuel Klimek9f0a4e52017-09-19 09:59:30 +00001414 nextToken();
Manuel Klimekd0f3fe52018-04-11 14:51:54 +00001415 if (FormatTok->is(tok::l_square)) {
1416 return false;
1417 }
Manuel Klimek9f0a4e52017-09-19 09:59:30 +00001418 parseSquare(/*LambdaIntroducer=*/true);
1419 return true;
Manuel Klimekffdeb592013-09-03 15:10:01 +00001420}
1421
Daniel Jasperc03e16a2014-05-08 09:25:39 +00001422void UnwrappedLineParser::tryToParseJSFunction() {
Martin Probst409697e2016-05-29 14:41:07 +00001423 assert(FormatTok->is(Keywords.kw_function) ||
1424 FormatTok->startsSequence(Keywords.kw_async, Keywords.kw_function));
Martin Probst5f8445b2016-04-24 22:05:09 +00001425 if (FormatTok->is(Keywords.kw_async))
1426 nextToken();
1427 // Consume "function".
Daniel Jasperc03e16a2014-05-08 09:25:39 +00001428 nextToken();
Daniel Jasper5217a8b2014-06-13 07:02:04 +00001429
Daniel Jasper71e50af2016-11-01 06:22:59 +00001430 // Consume * (generator function). Treat it like C++'s overloaded operators.
1431 if (FormatTok->is(tok::star)) {
1432 FormatTok->Type = TT_OverloadedOperator;
Martin Probst5f8445b2016-04-24 22:05:09 +00001433 nextToken();
Daniel Jasper71e50af2016-11-01 06:22:59 +00001434 }
Martin Probst5f8445b2016-04-24 22:05:09 +00001435
Daniel Jasper5217a8b2014-06-13 07:02:04 +00001436 // Consume function name.
1437 if (FormatTok->is(tok::identifier))
Daniel Jasperfca735c2015-02-19 16:14:18 +00001438 nextToken();
Daniel Jasper5217a8b2014-06-13 07:02:04 +00001439
Daniel Jasperc03e16a2014-05-08 09:25:39 +00001440 if (FormatTok->isNot(tok::l_paren))
1441 return;
Manuel Klimek79e06082015-05-21 12:23:34 +00001442
1443 // Parse formal parameter list.
Daniel Jasperbe520bd2015-05-31 08:51:54 +00001444 parseParens();
Manuel Klimek79e06082015-05-21 12:23:34 +00001445
1446 if (FormatTok->is(tok::colon)) {
1447 // Parse a type definition.
1448 nextToken();
1449
1450 // Eat the type declaration. For braced inline object types, balance braces,
1451 // otherwise just parse until finding an l_brace for the function body.
Daniel Jasperbe520bd2015-05-31 08:51:54 +00001452 if (FormatTok->is(tok::l_brace))
1453 tryToParseBracedList();
1454 else
Martin Probstaf16c502017-01-04 13:36:43 +00001455 while (!FormatTok->isOneOf(tok::l_brace, tok::semi) && !eof())
Manuel Klimek79e06082015-05-21 12:23:34 +00001456 nextToken();
Manuel Klimek79e06082015-05-21 12:23:34 +00001457 }
1458
Martin Probstaf16c502017-01-04 13:36:43 +00001459 if (FormatTok->is(tok::semi))
1460 return;
1461
Manuel Klimek79e06082015-05-21 12:23:34 +00001462 parseChildBlock();
1463}
1464
Daniel Jasper3c883d12015-05-18 14:49:19 +00001465bool UnwrappedLineParser::tryToParseBracedList() {
Daniel Jasperb1f74a82013-07-09 09:06:29 +00001466 if (FormatTok->BlockKind == BK_Unknown)
Daniel Jasper3c883d12015-05-18 14:49:19 +00001467 calculateBraceTypes();
Daniel Jasperb1f74a82013-07-09 09:06:29 +00001468 assert(FormatTok->BlockKind != BK_Unknown);
1469 if (FormatTok->BlockKind == BK_Block)
Manuel Klimekab419912013-05-23 09:41:43 +00001470 return false;
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001471 nextToken();
Manuel Klimekab419912013-05-23 09:41:43 +00001472 parseBracedList();
1473 return true;
1474}
1475
Krasimir Georgievff747be2017-06-27 13:43:07 +00001476bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons,
1477 tok::TokenKind ClosingBraceKind) {
Daniel Jasper015ed022013-09-13 09:20:45 +00001478 bool HasError = false;
Manuel Klimek8e07a1b2013-01-10 11:52:21 +00001479
Manuel Klimeka3ff45e2013-04-10 09:52:05 +00001480 // FIXME: Once we have an expression parser in the UnwrappedLineParser,
1481 // replace this by using parseAssigmentExpression() inside.
Manuel Klimek8e07a1b2013-01-10 11:52:21 +00001482 do {
Manuel Klimek79e06082015-05-21 12:23:34 +00001483 if (Style.Language == FormatStyle::LK_JavaScript) {
Martin Probst409697e2016-05-29 14:41:07 +00001484 if (FormatTok->is(Keywords.kw_function) ||
1485 FormatTok->startsSequence(Keywords.kw_async, Keywords.kw_function)) {
Manuel Klimek79e06082015-05-21 12:23:34 +00001486 tryToParseJSFunction();
1487 continue;
Daniel Jasperbe520bd2015-05-31 08:51:54 +00001488 }
1489 if (FormatTok->is(TT_JsFatArrow)) {
Manuel Klimek79e06082015-05-21 12:23:34 +00001490 nextToken();
1491 // Fat arrows can be followed by simple expressions or by child blocks
1492 // in curly braces.
Daniel Jaspere6fcf7d2015-06-17 13:08:06 +00001493 if (FormatTok->is(tok::l_brace)) {
Manuel Klimek79e06082015-05-21 12:23:34 +00001494 parseChildBlock();
1495 continue;
1496 }
1497 }
Martin Probst8e3eba02017-02-07 16:33:13 +00001498 if (FormatTok->is(tok::l_brace)) {
1499 // Could be a method inside of a braced list `{a() { return 1; }}`.
1500 if (tryToParseBracedList())
1501 continue;
1502 parseChildBlock();
1503 }
Daniel Jasperc03e16a2014-05-08 09:25:39 +00001504 }
Krasimir Georgievff747be2017-06-27 13:43:07 +00001505 if (FormatTok->Tok.getKind() == ClosingBraceKind) {
1506 nextToken();
1507 return !HasError;
1508 }
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001509 switch (FormatTok->Tok.getKind()) {
Manuel Klimek516e0542013-09-04 13:25:30 +00001510 case tok::caret:
1511 nextToken();
1512 if (FormatTok->is(tok::l_brace)) {
1513 parseChildBlock();
1514 }
1515 break;
1516 case tok::l_square:
1517 tryToParseLambda();
1518 break;
Daniel Jaspera87af7a2015-06-30 11:32:22 +00001519 case tok::l_paren:
1520 parseParens();
Daniel Jasperf46dec82015-03-31 14:34:15 +00001521 // JavaScript can just have free standing methods and getters/setters in
1522 // object literals. Detect them by a "{" following ")".
1523 if (Style.Language == FormatStyle::LK_JavaScript) {
Daniel Jasperf46dec82015-03-31 14:34:15 +00001524 if (FormatTok->is(tok::l_brace))
1525 parseChildBlock();
1526 break;
1527 }
Daniel Jasperf46dec82015-03-31 14:34:15 +00001528 break;
Martin Probst8e3eba02017-02-07 16:33:13 +00001529 case tok::l_brace:
1530 // Assume there are no blocks inside a braced init list apart
1531 // from the ones we explicitly parse out (like lambdas).
1532 FormatTok->BlockKind = BK_BracedInit;
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001533 nextToken();
Martin Probst8e3eba02017-02-07 16:33:13 +00001534 parseBracedList();
1535 break;
Krasimir Georgievfa4dbb62017-08-03 13:43:45 +00001536 case tok::less:
1537 if (Style.Language == FormatStyle::LK_Proto) {
1538 nextToken();
1539 parseBracedList(/*ContinueOnSemicolons=*/false,
1540 /*ClosingBraceKind=*/tok::greater);
1541 } else {
1542 nextToken();
1543 }
1544 break;
Manuel Klimeka3ff45e2013-04-10 09:52:05 +00001545 case tok::semi:
Daniel Jasperb9a49902016-01-09 15:56:28 +00001546 // JavaScript (or more precisely TypeScript) can have semicolons in braced
1547 // lists (in so-called TypeMemberLists). Thus, the semicolon cannot be
1548 // used for error recovery if we have otherwise determined that this is
1549 // a braced list.
1550 if (Style.Language == FormatStyle::LK_JavaScript) {
1551 nextToken();
1552 break;
1553 }
Daniel Jasper015ed022013-09-13 09:20:45 +00001554 HasError = true;
1555 if (!ContinueOnSemicolons)
1556 return !HasError;
1557 nextToken();
1558 break;
Manuel Klimeka3ff45e2013-04-10 09:52:05 +00001559 case tok::comma:
1560 nextToken();
Manuel Klimeka3ff45e2013-04-10 09:52:05 +00001561 break;
Manuel Klimek8e07a1b2013-01-10 11:52:21 +00001562 default:
1563 nextToken();
1564 break;
1565 }
1566 } while (!eof());
Daniel Jasper015ed022013-09-13 09:20:45 +00001567 return false;
Manuel Klimek8e07a1b2013-01-10 11:52:21 +00001568}
1569
Daniel Jasperf7935112012-12-03 18:12:45 +00001570void UnwrappedLineParser::parseParens() {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001571 assert(FormatTok->Tok.is(tok::l_paren) && "'(' expected.");
Daniel Jasperf7935112012-12-03 18:12:45 +00001572 nextToken();
1573 do {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001574 switch (FormatTok->Tok.getKind()) {
Daniel Jasperf7935112012-12-03 18:12:45 +00001575 case tok::l_paren:
1576 parseParens();
Daniel Jasper5f1fa852015-01-04 20:40:51 +00001577 if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::l_brace))
1578 parseChildBlock();
Daniel Jasperf7935112012-12-03 18:12:45 +00001579 break;
1580 case tok::r_paren:
1581 nextToken();
1582 return;
Daniel Jasper393564f2013-05-31 14:56:29 +00001583 case tok::r_brace:
1584 // A "}" inside parenthesis is an error if there wasn't a matching "{".
1585 return;
Daniel Jasper9a8d48b2013-09-05 10:04:31 +00001586 case tok::l_square:
1587 tryToParseLambda();
1588 break;
Daniel Jasper5f1fa852015-01-04 20:40:51 +00001589 case tok::l_brace:
Daniel Jasperadba2aa2015-05-18 12:52:00 +00001590 if (!tryToParseBracedList())
Manuel Klimekf017dc02013-09-04 13:34:14 +00001591 parseChildBlock();
Manuel Klimek8e07a1b2013-01-10 11:52:21 +00001592 break;
Nico Weber372d8dc2013-02-10 20:35:35 +00001593 case tok::at:
1594 nextToken();
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001595 if (FormatTok->Tok.is(tok::l_brace)) {
1596 nextToken();
Nico Weber372d8dc2013-02-10 20:35:35 +00001597 parseBracedList();
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001598 }
Nico Weber372d8dc2013-02-10 20:35:35 +00001599 break;
Martin Probst1027fb82017-02-07 14:05:30 +00001600 case tok::kw_class:
1601 if (Style.Language == FormatStyle::LK_JavaScript)
1602 parseRecord(/*ParseAsExpr=*/true);
1603 else
1604 nextToken();
1605 break;
Daniel Jasper3f69ba12014-09-05 08:42:27 +00001606 case tok::identifier:
1607 if (Style.Language == FormatStyle::LK_JavaScript &&
Martin Probst409697e2016-05-29 14:41:07 +00001608 (FormatTok->is(Keywords.kw_function) ||
1609 FormatTok->startsSequence(Keywords.kw_async, Keywords.kw_function)))
Daniel Jasper3f69ba12014-09-05 08:42:27 +00001610 tryToParseJSFunction();
1611 else
1612 nextToken();
1613 break;
Daniel Jasperf7935112012-12-03 18:12:45 +00001614 default:
1615 nextToken();
1616 break;
1617 }
1618 } while (!eof());
1619}
1620
Manuel Klimek9f0a4e52017-09-19 09:59:30 +00001621void UnwrappedLineParser::parseSquare(bool LambdaIntroducer) {
1622 if (!LambdaIntroducer) {
1623 assert(FormatTok->Tok.is(tok::l_square) && "'[' expected.");
1624 if (tryToParseLambda())
1625 return;
1626 }
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001627 do {
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001628 switch (FormatTok->Tok.getKind()) {
1629 case tok::l_paren:
1630 parseParens();
1631 break;
1632 case tok::r_square:
1633 nextToken();
1634 return;
1635 case tok::r_brace:
1636 // A "}" inside parenthesis is an error if there wasn't a matching "{".
1637 return;
1638 case tok::l_square:
1639 parseSquare();
1640 break;
1641 case tok::l_brace: {
Daniel Jasperadba2aa2015-05-18 12:52:00 +00001642 if (!tryToParseBracedList())
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001643 parseChildBlock();
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001644 break;
1645 }
1646 case tok::at:
1647 nextToken();
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001648 if (FormatTok->Tok.is(tok::l_brace)) {
1649 nextToken();
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001650 parseBracedList();
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001651 }
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001652 break;
1653 default:
1654 nextToken();
1655 break;
1656 }
1657 } while (!eof());
1658}
1659
Daniel Jasperf7935112012-12-03 18:12:45 +00001660void UnwrappedLineParser::parseIfThenElse() {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001661 assert(FormatTok->Tok.is(tok::kw_if) && "'if' expected");
Daniel Jasperf7935112012-12-03 18:12:45 +00001662 nextToken();
Daniel Jasper6a7d5a72017-06-19 07:40:49 +00001663 if (FormatTok->Tok.is(tok::kw_constexpr))
1664 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001665 if (FormatTok->Tok.is(tok::l_paren))
Manuel Klimekadededf2013-01-11 18:28:36 +00001666 parseParens();
Daniel Jasperf7935112012-12-03 18:12:45 +00001667 bool NeedsUnwrappedLine = false;
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001668 if (FormatTok->Tok.is(tok::l_brace)) {
Alexander Kornienko3a33f022013-12-12 09:49:52 +00001669 CompoundStatementIndenter Indenter(this, Style, Line->Level);
Nico Weber9096fc02013-06-26 00:30:14 +00001670 parseBlock(/*MustBeDeclaration=*/false);
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00001671 if (Style.BraceWrapping.BeforeElse)
Manuel Klimekd3ed59a2013-08-02 21:31:59 +00001672 addUnwrappedLine();
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00001673 else
Manuel Klimekd3ed59a2013-08-02 21:31:59 +00001674 NeedsUnwrappedLine = true;
Daniel Jasperf7935112012-12-03 18:12:45 +00001675 } else {
1676 addUnwrappedLine();
Manuel Klimek52b15152013-01-09 15:25:02 +00001677 ++Line->Level;
Manuel Klimek6b9eeba2013-01-07 14:56:16 +00001678 parseStructuralElement();
Manuel Klimek52b15152013-01-09 15:25:02 +00001679 --Line->Level;
Daniel Jasperf7935112012-12-03 18:12:45 +00001680 }
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001681 if (FormatTok->Tok.is(tok::kw_else)) {
Daniel Jasperf7935112012-12-03 18:12:45 +00001682 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001683 if (FormatTok->Tok.is(tok::l_brace)) {
Alexander Kornienko3a33f022013-12-12 09:49:52 +00001684 CompoundStatementIndenter Indenter(this, Style, Line->Level);
Nico Weber9096fc02013-06-26 00:30:14 +00001685 parseBlock(/*MustBeDeclaration=*/false);
Daniel Jasperf7935112012-12-03 18:12:45 +00001686 addUnwrappedLine();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001687 } else if (FormatTok->Tok.is(tok::kw_if)) {
Daniel Jasperf7935112012-12-03 18:12:45 +00001688 parseIfThenElse();
1689 } else {
1690 addUnwrappedLine();
Manuel Klimek52b15152013-01-09 15:25:02 +00001691 ++Line->Level;
Manuel Klimek6b9eeba2013-01-07 14:56:16 +00001692 parseStructuralElement();
Daniel Jasper451544a2016-05-19 06:30:48 +00001693 if (FormatTok->is(tok::eof))
1694 addUnwrappedLine();
Manuel Klimek52b15152013-01-09 15:25:02 +00001695 --Line->Level;
Daniel Jasperf7935112012-12-03 18:12:45 +00001696 }
1697 } else if (NeedsUnwrappedLine) {
1698 addUnwrappedLine();
1699 }
1700}
1701
Daniel Jasper04a71a42014-05-08 11:58:24 +00001702void UnwrappedLineParser::parseTryCatch() {
Nico Weberfac23712015-02-04 15:26:27 +00001703 assert(FormatTok->isOneOf(tok::kw_try, tok::kw___try) && "'try' expected");
Daniel Jasper04a71a42014-05-08 11:58:24 +00001704 nextToken();
1705 bool NeedsUnwrappedLine = false;
1706 if (FormatTok->is(tok::colon)) {
1707 // We are in a function try block, what comes is an initializer list.
1708 nextToken();
1709 while (FormatTok->is(tok::identifier)) {
1710 nextToken();
1711 if (FormatTok->is(tok::l_paren))
1712 parseParens();
Daniel Jasper04a71a42014-05-08 11:58:24 +00001713 if (FormatTok->is(tok::comma))
1714 nextToken();
1715 }
1716 }
Daniel Jaspere189d462015-01-14 10:48:41 +00001717 // Parse try with resource.
1718 if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::l_paren)) {
1719 parseParens();
1720 }
Daniel Jasper04a71a42014-05-08 11:58:24 +00001721 if (FormatTok->is(tok::l_brace)) {
1722 CompoundStatementIndenter Indenter(this, Style, Line->Level);
1723 parseBlock(/*MustBeDeclaration=*/false);
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00001724 if (Style.BraceWrapping.BeforeCatch) {
Daniel Jasper04a71a42014-05-08 11:58:24 +00001725 addUnwrappedLine();
1726 } else {
1727 NeedsUnwrappedLine = true;
1728 }
1729 } else if (!FormatTok->is(tok::kw_catch)) {
1730 // The C++ standard requires a compound-statement after a try.
1731 // If there's none, we try to assume there's a structuralElement
1732 // and try to continue.
Daniel Jasper04a71a42014-05-08 11:58:24 +00001733 addUnwrappedLine();
1734 ++Line->Level;
1735 parseStructuralElement();
1736 --Line->Level;
1737 }
Nico Weber33381f52015-02-07 01:57:32 +00001738 while (1) {
1739 if (FormatTok->is(tok::at))
1740 nextToken();
1741 if (!(FormatTok->isOneOf(tok::kw_catch, Keywords.kw___except,
1742 tok::kw___finally) ||
1743 ((Style.Language == FormatStyle::LK_Java ||
1744 Style.Language == FormatStyle::LK_JavaScript) &&
1745 FormatTok->is(Keywords.kw_finally)) ||
1746 (FormatTok->Tok.isObjCAtKeyword(tok::objc_catch) ||
1747 FormatTok->Tok.isObjCAtKeyword(tok::objc_finally))))
1748 break;
Daniel Jasper04a71a42014-05-08 11:58:24 +00001749 nextToken();
1750 while (FormatTok->isNot(tok::l_brace)) {
1751 if (FormatTok->is(tok::l_paren)) {
1752 parseParens();
1753 continue;
1754 }
Daniel Jasper2bd7a642015-01-19 10:50:51 +00001755 if (FormatTok->isOneOf(tok::semi, tok::r_brace, tok::eof))
Daniel Jasper04a71a42014-05-08 11:58:24 +00001756 return;
1757 nextToken();
1758 }
1759 NeedsUnwrappedLine = false;
1760 CompoundStatementIndenter Indenter(this, Style, Line->Level);
1761 parseBlock(/*MustBeDeclaration=*/false);
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00001762 if (Style.BraceWrapping.BeforeCatch)
Daniel Jasper04a71a42014-05-08 11:58:24 +00001763 addUnwrappedLine();
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00001764 else
Daniel Jasper04a71a42014-05-08 11:58:24 +00001765 NeedsUnwrappedLine = true;
Daniel Jasper04a71a42014-05-08 11:58:24 +00001766 }
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00001767 if (NeedsUnwrappedLine)
Daniel Jasper04a71a42014-05-08 11:58:24 +00001768 addUnwrappedLine();
Daniel Jasper04a71a42014-05-08 11:58:24 +00001769}
1770
Alexander Kornienko578fdd82012-12-06 18:03:27 +00001771void UnwrappedLineParser::parseNamespace() {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001772 assert(FormatTok->Tok.is(tok::kw_namespace) && "'namespace' expected");
Roman Kashitsyna043ced2014-08-11 12:18:01 +00001773
1774 const FormatToken &InitialToken = *FormatTok;
Alexander Kornienko578fdd82012-12-06 18:03:27 +00001775 nextToken();
Saleem Abdulrasool328085f2015-10-30 05:07:56 +00001776 while (FormatTok->isOneOf(tok::identifier, tok::coloncolon))
Alexander Kornienko578fdd82012-12-06 18:03:27 +00001777 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001778 if (FormatTok->Tok.is(tok::l_brace)) {
Roman Kashitsyna043ced2014-08-11 12:18:01 +00001779 if (ShouldBreakBeforeBrace(Style, InitialToken))
Manuel Klimeka8eb9142013-05-13 12:51:40 +00001780 addUnwrappedLine();
1781
Daniel Jasper65ee3472013-07-31 23:16:02 +00001782 bool AddLevel = Style.NamespaceIndentation == FormatStyle::NI_All ||
1783 (Style.NamespaceIndentation == FormatStyle::NI_Inner &&
1784 DeclarationScopeStack.size() > 1);
1785 parseBlock(/*MustBeDeclaration=*/true, AddLevel);
Manuel Klimek046b9302013-02-06 16:08:09 +00001786 // Munch the semicolon after a namespace. This is more common than one would
1787 // think. Puttin the semicolon into its own line is very ugly.
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001788 if (FormatTok->Tok.is(tok::semi))
Manuel Klimek046b9302013-02-06 16:08:09 +00001789 nextToken();
Alexander Kornienko578fdd82012-12-06 18:03:27 +00001790 addUnwrappedLine();
1791 }
1792 // FIXME: Add error handling.
1793}
1794
Daniel Jasper6acf5132015-03-12 14:44:29 +00001795void UnwrappedLineParser::parseNew() {
1796 assert(FormatTok->is(tok::kw_new) && "'new' expected");
1797 nextToken();
1798 if (Style.Language != FormatStyle::LK_Java)
1799 return;
1800
1801 // In Java, we can parse everything up to the parens, which aren't optional.
1802 do {
1803 // There should not be a ;, { or } before the new's open paren.
1804 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::r_brace))
1805 return;
1806
1807 // Consume the parens.
1808 if (FormatTok->is(tok::l_paren)) {
1809 parseParens();
1810
1811 // If there is a class body of an anonymous class, consume that as child.
1812 if (FormatTok->is(tok::l_brace))
1813 parseChildBlock();
1814 return;
1815 }
1816 nextToken();
1817 } while (!eof());
1818}
1819
Alexander Kornienko37d6c942012-12-05 15:06:06 +00001820void UnwrappedLineParser::parseForOrWhileLoop() {
Daniel Jasper66cb8c52015-05-04 09:22:29 +00001821 assert(FormatTok->isOneOf(tok::kw_for, tok::kw_while, TT_ForEachMacro) &&
Daniel Jaspere1e43192014-04-01 12:55:11 +00001822 "'for', 'while' or foreach macro expected");
Alexander Kornienko37d6c942012-12-05 15:06:06 +00001823 nextToken();
Martin Probsta050f412017-05-18 21:19:29 +00001824 // JS' for await ( ...
Martin Probstbd49e322017-05-15 19:33:20 +00001825 if (Style.Language == FormatStyle::LK_JavaScript &&
Martin Probsta050f412017-05-18 21:19:29 +00001826 FormatTok->is(Keywords.kw_await))
Martin Probstbd49e322017-05-15 19:33:20 +00001827 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001828 if (FormatTok->Tok.is(tok::l_paren))
Manuel Klimek9fa8d552013-01-11 19:23:05 +00001829 parseParens();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001830 if (FormatTok->Tok.is(tok::l_brace)) {
Alexander Kornienko3a33f022013-12-12 09:49:52 +00001831 CompoundStatementIndenter Indenter(this, Style, Line->Level);
Nico Weber9096fc02013-06-26 00:30:14 +00001832 parseBlock(/*MustBeDeclaration=*/false);
Alexander Kornienko37d6c942012-12-05 15:06:06 +00001833 addUnwrappedLine();
1834 } else {
1835 addUnwrappedLine();
Manuel Klimek52b15152013-01-09 15:25:02 +00001836 ++Line->Level;
Manuel Klimek6b9eeba2013-01-07 14:56:16 +00001837 parseStructuralElement();
Manuel Klimek52b15152013-01-09 15:25:02 +00001838 --Line->Level;
Alexander Kornienko37d6c942012-12-05 15:06:06 +00001839 }
1840}
1841
Daniel Jasperf7935112012-12-03 18:12:45 +00001842void UnwrappedLineParser::parseDoWhile() {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001843 assert(FormatTok->Tok.is(tok::kw_do) && "'do' expected");
Daniel Jasperf7935112012-12-03 18:12:45 +00001844 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001845 if (FormatTok->Tok.is(tok::l_brace)) {
Alexander Kornienko3a33f022013-12-12 09:49:52 +00001846 CompoundStatementIndenter Indenter(this, Style, Line->Level);
Nico Weber9096fc02013-06-26 00:30:14 +00001847 parseBlock(/*MustBeDeclaration=*/false);
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00001848 if (Style.BraceWrapping.IndentBraces)
Alexander Kornienko3a33f022013-12-12 09:49:52 +00001849 addUnwrappedLine();
Daniel Jasperf7935112012-12-03 18:12:45 +00001850 } else {
1851 addUnwrappedLine();
Manuel Klimek52b15152013-01-09 15:25:02 +00001852 ++Line->Level;
Manuel Klimek6b9eeba2013-01-07 14:56:16 +00001853 parseStructuralElement();
Manuel Klimek52b15152013-01-09 15:25:02 +00001854 --Line->Level;
Daniel Jasperf7935112012-12-03 18:12:45 +00001855 }
1856
Alexander Kornienko0ea8e102012-12-04 15:40:36 +00001857 // FIXME: Add error handling.
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001858 if (!FormatTok->Tok.is(tok::kw_while)) {
Alexander Kornienko0ea8e102012-12-04 15:40:36 +00001859 addUnwrappedLine();
1860 return;
1861 }
1862
Daniel Jasperf7935112012-12-03 18:12:45 +00001863 nextToken();
Manuel Klimek6b9eeba2013-01-07 14:56:16 +00001864 parseStructuralElement();
Daniel Jasperf7935112012-12-03 18:12:45 +00001865}
1866
1867void UnwrappedLineParser::parseLabel() {
Daniel Jasperf7935112012-12-03 18:12:45 +00001868 nextToken();
Manuel Klimek52b15152013-01-09 15:25:02 +00001869 unsigned OldLineLevel = Line->Level;
Daniel Jaspera1275122013-03-20 10:23:53 +00001870 if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0))
Manuel Klimek52b15152013-01-09 15:25:02 +00001871 --Line->Level;
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001872 if (CommentsBeforeNextToken.empty() && FormatTok->Tok.is(tok::l_brace)) {
Alexander Kornienko3a33f022013-12-12 09:49:52 +00001873 CompoundStatementIndenter Indenter(this, Style, Line->Level);
Nico Weber9096fc02013-06-26 00:30:14 +00001874 parseBlock(/*MustBeDeclaration=*/false);
Manuel Klimekd3ed59a2013-08-02 21:31:59 +00001875 if (FormatTok->Tok.is(tok::kw_break)) {
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00001876 if (Style.BraceWrapping.AfterControlStatement)
Manuel Klimekd3ed59a2013-08-02 21:31:59 +00001877 addUnwrappedLine();
1878 parseStructuralElement();
1879 }
Alexander Kornienko3a33f022013-12-12 09:49:52 +00001880 addUnwrappedLine();
1881 } else {
Daniel Jasper1fe0d5c2015-05-06 15:19:47 +00001882 if (FormatTok->is(tok::semi))
1883 nextToken();
Alexander Kornienko3a33f022013-12-12 09:49:52 +00001884 addUnwrappedLine();
Daniel Jasperf7935112012-12-03 18:12:45 +00001885 }
Manuel Klimek52b15152013-01-09 15:25:02 +00001886 Line->Level = OldLineLevel;
Daniel Jasper2cce7b72016-04-06 16:41:39 +00001887 if (FormatTok->isNot(tok::l_brace)) {
Daniel Jasper40609472016-04-06 15:02:46 +00001888 parseStructuralElement();
Daniel Jasper2cce7b72016-04-06 16:41:39 +00001889 addUnwrappedLine();
1890 }
Daniel Jasperf7935112012-12-03 18:12:45 +00001891}
1892
1893void UnwrappedLineParser::parseCaseLabel() {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001894 assert(FormatTok->Tok.is(tok::kw_case) && "'case' expected");
Daniel Jasperf7935112012-12-03 18:12:45 +00001895 // FIXME: fix handling of complex expressions here.
1896 do {
1897 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001898 } while (!eof() && !FormatTok->Tok.is(tok::colon));
Daniel Jasperf7935112012-12-03 18:12:45 +00001899 parseLabel();
1900}
1901
1902void UnwrappedLineParser::parseSwitch() {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001903 assert(FormatTok->Tok.is(tok::kw_switch) && "'switch' expected");
Daniel Jasperf7935112012-12-03 18:12:45 +00001904 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001905 if (FormatTok->Tok.is(tok::l_paren))
Manuel Klimek9fa8d552013-01-11 19:23:05 +00001906 parseParens();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001907 if (FormatTok->Tok.is(tok::l_brace)) {
Alexander Kornienko3a33f022013-12-12 09:49:52 +00001908 CompoundStatementIndenter Indenter(this, Style, Line->Level);
Daniel Jasper65ee3472013-07-31 23:16:02 +00001909 parseBlock(/*MustBeDeclaration=*/false);
Daniel Jasperf7935112012-12-03 18:12:45 +00001910 addUnwrappedLine();
1911 } else {
1912 addUnwrappedLine();
Daniel Jasper516d7972013-07-25 11:31:57 +00001913 ++Line->Level;
Manuel Klimek6b9eeba2013-01-07 14:56:16 +00001914 parseStructuralElement();
Daniel Jasper516d7972013-07-25 11:31:57 +00001915 --Line->Level;
Daniel Jasperf7935112012-12-03 18:12:45 +00001916 }
1917}
1918
1919void UnwrappedLineParser::parseAccessSpecifier() {
1920 nextToken();
Daniel Jasper84c47a12013-11-23 17:53:41 +00001921 // Understand Qt's slots.
Daniel Jasper53395402015-04-07 15:04:40 +00001922 if (FormatTok->isOneOf(Keywords.kw_slots, Keywords.kw_qslots))
Daniel Jasper84c47a12013-11-23 17:53:41 +00001923 nextToken();
Alexander Kornienko2ca766f2012-12-10 16:34:48 +00001924 // Otherwise, we don't know what it is, and we'd better keep the next token.
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001925 if (FormatTok->Tok.is(tok::colon))
Alexander Kornienko2ca766f2012-12-10 16:34:48 +00001926 nextToken();
Daniel Jasperf7935112012-12-03 18:12:45 +00001927 addUnwrappedLine();
1928}
1929
Daniel Jasper6f5a1932015-12-29 08:54:23 +00001930bool UnwrappedLineParser::parseEnum() {
Daniel Jasper6be0f552014-11-13 15:56:28 +00001931 // Won't be 'enum' for NS_ENUMs.
1932 if (FormatTok->Tok.is(tok::kw_enum))
Daniel Jasperccb68b42014-11-19 22:38:18 +00001933 nextToken();
Daniel Jasper6be0f552014-11-13 15:56:28 +00001934
Daniel Jasper6f5a1932015-12-29 08:54:23 +00001935 // In TypeScript, "enum" can also be used as property name, e.g. in interface
1936 // declarations. An "enum" keyword followed by a colon would be a syntax
1937 // error and thus assume it is just an identifier.
Daniel Jasper87379302016-02-03 05:33:44 +00001938 if (Style.Language == FormatStyle::LK_JavaScript &&
1939 FormatTok->isOneOf(tok::colon, tok::question))
Daniel Jasper6f5a1932015-12-29 08:54:23 +00001940 return false;
1941
Daniel Jasper2b41a822013-08-20 12:42:50 +00001942 // Eat up enum class ...
Daniel Jasperb05a81d2014-05-09 13:11:16 +00001943 if (FormatTok->Tok.is(tok::kw_class) || FormatTok->Tok.is(tok::kw_struct))
1944 nextToken();
Daniel Jasperb5a0b852015-06-19 08:17:32 +00001945
Daniel Jasper786a5502013-09-06 21:32:35 +00001946 while (FormatTok->Tok.getIdentifierInfo() ||
Daniel Jasperccb68b42014-11-19 22:38:18 +00001947 FormatTok->isOneOf(tok::colon, tok::coloncolon, tok::less,
1948 tok::greater, tok::comma, tok::question)) {
Manuel Klimek2cec0192013-01-21 19:17:52 +00001949 nextToken();
1950 // We can have macros or attributes in between 'enum' and the enum name.
Daniel Jasperccb68b42014-11-19 22:38:18 +00001951 if (FormatTok->is(tok::l_paren))
Alexander Kornienkob7076a22012-12-04 14:46:19 +00001952 parseParens();
Daniel Jasperb5a0b852015-06-19 08:17:32 +00001953 if (FormatTok->is(tok::identifier)) {
Manuel Klimek2cec0192013-01-21 19:17:52 +00001954 nextToken();
Daniel Jasperb5a0b852015-06-19 08:17:32 +00001955 // If there are two identifiers in a row, this is likely an elaborate
1956 // return type. In Java, this can be "implements", etc.
Daniel Jasper1dbc2102017-03-31 13:30:24 +00001957 if (Style.isCpp() && FormatTok->is(tok::identifier))
Daniel Jasper6f5a1932015-12-29 08:54:23 +00001958 return false;
Daniel Jasperb5a0b852015-06-19 08:17:32 +00001959 }
Manuel Klimek2cec0192013-01-21 19:17:52 +00001960 }
Daniel Jasper6be0f552014-11-13 15:56:28 +00001961
1962 // Just a declaration or something is wrong.
Daniel Jasperccb68b42014-11-19 22:38:18 +00001963 if (FormatTok->isNot(tok::l_brace))
Daniel Jasper6f5a1932015-12-29 08:54:23 +00001964 return true;
Daniel Jasper6be0f552014-11-13 15:56:28 +00001965 FormatTok->BlockKind = BK_Block;
1966
1967 if (Style.Language == FormatStyle::LK_Java) {
1968 // Java enums are different.
1969 parseJavaEnumBody();
Daniel Jasper6f5a1932015-12-29 08:54:23 +00001970 return true;
1971 }
1972 if (Style.Language == FormatStyle::LK_Proto) {
Daniel Jasperc6dd2732015-07-16 14:25:43 +00001973 parseBlock(/*MustBeDeclaration=*/true);
Daniel Jasper6f5a1932015-12-29 08:54:23 +00001974 return true;
Manuel Klimek2cec0192013-01-21 19:17:52 +00001975 }
Daniel Jasper6be0f552014-11-13 15:56:28 +00001976
1977 // Parse enum body.
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001978 nextToken();
Daniel Jasper6be0f552014-11-13 15:56:28 +00001979 bool HasError = !parseBracedList(/*ContinueOnSemicolons=*/true);
1980 if (HasError) {
1981 if (FormatTok->is(tok::semi))
1982 nextToken();
1983 addUnwrappedLine();
1984 }
Daniel Jasper6f5a1932015-12-29 08:54:23 +00001985 return true;
Daniel Jasper6be0f552014-11-13 15:56:28 +00001986
Daniel Jasper90cf3802015-06-17 09:44:02 +00001987 // There is no addUnwrappedLine() here so that we fall through to parsing a
1988 // structural element afterwards. Thus, in "enum A {} n, m;",
Manuel Klimek2cec0192013-01-21 19:17:52 +00001989 // "} n, m;" will end up in one unwrapped line.
Daniel Jasper6be0f552014-11-13 15:56:28 +00001990}
1991
1992void UnwrappedLineParser::parseJavaEnumBody() {
1993 // Determine whether the enum is simple, i.e. does not have a semicolon or
1994 // constants with class bodies. Simple enums can be formatted like braced
1995 // lists, contracted to a single line, etc.
1996 unsigned StoredPosition = Tokens->getPosition();
1997 bool IsSimple = true;
1998 FormatToken *Tok = Tokens->getNextToken();
1999 while (Tok) {
2000 if (Tok->is(tok::r_brace))
2001 break;
2002 if (Tok->isOneOf(tok::l_brace, tok::semi)) {
2003 IsSimple = false;
2004 break;
2005 }
2006 // FIXME: This will also mark enums with braces in the arguments to enum
2007 // constants as "not simple". This is probably fine in practice, though.
2008 Tok = Tokens->getNextToken();
2009 }
2010 FormatTok = Tokens->setPosition(StoredPosition);
2011
2012 if (IsSimple) {
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00002013 nextToken();
Daniel Jasper6be0f552014-11-13 15:56:28 +00002014 parseBracedList();
Daniel Jasperdf2ff002014-11-02 22:31:39 +00002015 addUnwrappedLine();
Daniel Jasper6be0f552014-11-13 15:56:28 +00002016 return;
2017 }
2018
2019 // Parse the body of a more complex enum.
2020 // First add a line for everything up to the "{".
2021 nextToken();
2022 addUnwrappedLine();
2023 ++Line->Level;
2024
2025 // Parse the enum constants.
2026 while (FormatTok) {
2027 if (FormatTok->is(tok::l_brace)) {
2028 // Parse the constant's class body.
2029 parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/true,
2030 /*MunchSemi=*/false);
2031 } else if (FormatTok->is(tok::l_paren)) {
2032 parseParens();
2033 } else if (FormatTok->is(tok::comma)) {
2034 nextToken();
2035 addUnwrappedLine();
2036 } else if (FormatTok->is(tok::semi)) {
2037 nextToken();
2038 addUnwrappedLine();
2039 break;
2040 } else if (FormatTok->is(tok::r_brace)) {
2041 addUnwrappedLine();
2042 break;
2043 } else {
2044 nextToken();
2045 }
2046 }
2047
2048 // Parse the class body after the enum's ";" if any.
2049 parseLevel(/*HasOpeningBrace=*/true);
2050 nextToken();
2051 --Line->Level;
2052 addUnwrappedLine();
Daniel Jasperf7935112012-12-03 18:12:45 +00002053}
2054
Martin Probst1027fb82017-02-07 14:05:30 +00002055void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
Roman Kashitsyna043ced2014-08-11 12:18:01 +00002056 const FormatToken &InitialToken = *FormatTok;
Manuel Klimek28cacc72013-01-07 18:10:23 +00002057 nextToken();
Daniel Jasper04785d02015-05-06 14:03:02 +00002058
Daniel Jasper04785d02015-05-06 14:03:02 +00002059 // The actual identifier can be a nested name specifier, and in macros
2060 // it is often token-pasted.
2061 while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash,
2062 tok::kw___attribute, tok::kw___declspec,
2063 tok::kw_alignas) ||
2064 ((Style.Language == FormatStyle::LK_Java ||
2065 Style.Language == FormatStyle::LK_JavaScript) &&
2066 FormatTok->isOneOf(tok::period, tok::comma))) {
Martin Probstcb870c52017-08-01 15:46:10 +00002067 if (Style.Language == FormatStyle::LK_JavaScript &&
2068 FormatTok->isOneOf(Keywords.kw_extends, Keywords.kw_implements)) {
2069 // JavaScript/TypeScript supports inline object types in
2070 // extends/implements positions:
2071 // class Foo implements {bar: number} { }
2072 nextToken();
2073 if (FormatTok->is(tok::l_brace)) {
2074 tryToParseBracedList();
2075 continue;
2076 }
2077 }
Daniel Jasper04785d02015-05-06 14:03:02 +00002078 bool IsNonMacroIdentifier =
2079 FormatTok->is(tok::identifier) &&
2080 FormatTok->TokenText != FormatTok->TokenText.upper();
Manuel Klimeke01bab52013-01-15 13:38:33 +00002081 nextToken();
2082 // We can have macros or attributes in between 'class' and the class name.
Daniel Jasper04785d02015-05-06 14:03:02 +00002083 if (!IsNonMacroIdentifier && FormatTok->Tok.is(tok::l_paren))
Manuel Klimeke01bab52013-01-15 13:38:33 +00002084 parseParens();
Daniel Jasper04785d02015-05-06 14:03:02 +00002085 }
Manuel Klimeke01bab52013-01-15 13:38:33 +00002086
Daniel Jasper04785d02015-05-06 14:03:02 +00002087 // Note that parsing away template declarations here leads to incorrectly
2088 // accepting function declarations as record declarations.
2089 // In general, we cannot solve this problem. Consider:
2090 // class A<int> B() {}
2091 // which can be a function definition or a class definition when B() is a
2092 // macro. If we find enough real-world cases where this is a problem, we
2093 // can parse for the 'template' keyword in the beginning of the statement,
2094 // and thus rule out the record production in case there is no template
2095 // (this would still leave us with an ambiguity between template function
2096 // and class declarations).
Daniel Jasperadba2aa2015-05-18 12:52:00 +00002097 if (FormatTok->isOneOf(tok::colon, tok::less)) {
2098 while (!eof()) {
Daniel Jasper3c883d12015-05-18 14:49:19 +00002099 if (FormatTok->is(tok::l_brace)) {
2100 calculateBraceTypes(/*ExpectClassBody=*/true);
2101 if (!tryToParseBracedList())
2102 break;
2103 }
Daniel Jasper04785d02015-05-06 14:03:02 +00002104 if (FormatTok->Tok.is(tok::semi))
2105 return;
2106 nextToken();
Manuel Klimeke01bab52013-01-15 13:38:33 +00002107 }
2108 }
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002109 if (FormatTok->Tok.is(tok::l_brace)) {
Martin Probst1027fb82017-02-07 14:05:30 +00002110 if (ParseAsExpr) {
2111 parseChildBlock();
2112 } else {
2113 if (ShouldBreakBeforeBrace(Style, InitialToken))
2114 addUnwrappedLine();
Manuel Klimeka8eb9142013-05-13 12:51:40 +00002115
Martin Probst1027fb82017-02-07 14:05:30 +00002116 parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/true,
2117 /*MunchSemi=*/false);
2118 }
Manuel Klimeka8eb9142013-05-13 12:51:40 +00002119 }
Daniel Jasper90cf3802015-06-17 09:44:02 +00002120 // There is no addUnwrappedLine() here so that we fall through to parsing a
2121 // structural element afterwards. Thus, in "class A {} n, m;",
2122 // "} n, m;" will end up in one unwrapped line.
Manuel Klimek28cacc72013-01-07 18:10:23 +00002123}
2124
Ben Hamilton707e68f2018-05-30 15:21:38 +00002125void UnwrappedLineParser::parseObjCMethod() {
2126 assert(FormatTok->Tok.isOneOf(tok::l_paren, tok::identifier) &&
2127 "'(' or identifier expected.");
2128 do {
2129 if (FormatTok->Tok.is(tok::semi)) {
2130 nextToken();
2131 addUnwrappedLine();
2132 return;
2133 } else if (FormatTok->Tok.is(tok::l_brace)) {
2134 parseBlock(/*MustBeDeclaration=*/false);
2135 addUnwrappedLine();
2136 return;
2137 } else {
2138 nextToken();
2139 }
2140 } while (!eof());
2141}
2142
Nico Weber8696a8d2013-01-09 21:15:03 +00002143void UnwrappedLineParser::parseObjCProtocolList() {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002144 assert(FormatTok->Tok.is(tok::less) && "'<' expected.");
Ben Hamilton1462e842018-04-05 15:26:25 +00002145 do {
Nico Weber8696a8d2013-01-09 21:15:03 +00002146 nextToken();
Ben Hamilton1462e842018-04-05 15:26:25 +00002147 // Early exit in case someone forgot a close angle.
2148 if (FormatTok->isOneOf(tok::semi, tok::l_brace) ||
2149 FormatTok->Tok.isObjCAtKeyword(tok::objc_end))
2150 return;
2151 } while (!eof() && FormatTok->Tok.isNot(tok::greater));
Nico Weber8696a8d2013-01-09 21:15:03 +00002152 nextToken(); // Skip '>'.
2153}
2154
2155void UnwrappedLineParser::parseObjCUntilAtEnd() {
2156 do {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002157 if (FormatTok->Tok.isObjCAtKeyword(tok::objc_end)) {
Nico Weber8696a8d2013-01-09 21:15:03 +00002158 nextToken();
2159 addUnwrappedLine();
2160 break;
2161 }
Daniel Jaspera15da302013-08-28 08:04:23 +00002162 if (FormatTok->is(tok::l_brace)) {
2163 parseBlock(/*MustBeDeclaration=*/false);
2164 // In ObjC interfaces, nothing should be following the "}".
2165 addUnwrappedLine();
Benjamin Kramere21cb742014-01-08 15:59:42 +00002166 } else if (FormatTok->is(tok::r_brace)) {
2167 // Ignore stray "}". parseStructuralElement doesn't consume them.
2168 nextToken();
2169 addUnwrappedLine();
Ben Hamilton707e68f2018-05-30 15:21:38 +00002170 } else if (FormatTok->isOneOf(tok::minus, tok::plus)) {
2171 nextToken();
2172 parseObjCMethod();
Daniel Jaspera15da302013-08-28 08:04:23 +00002173 } else {
2174 parseStructuralElement();
2175 }
Nico Weber8696a8d2013-01-09 21:15:03 +00002176 } while (!eof());
2177}
2178
Nico Weber2ce0ac52013-01-09 23:25:37 +00002179void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
Nico Weberc068ff72018-01-23 17:10:25 +00002180 assert(FormatTok->Tok.getObjCKeywordID() == tok::objc_interface ||
2181 FormatTok->Tok.getObjCKeywordID() == tok::objc_implementation);
Nico Weber7eecf4b2013-01-09 20:25:35 +00002182 nextToken();
Daniel Jasperd1ae3582013-03-20 12:37:50 +00002183 nextToken(); // interface name
Nico Weber7eecf4b2013-01-09 20:25:35 +00002184
Ben Hamilton1462e842018-04-05 15:26:25 +00002185 // @interface can be followed by a lightweight generic
2186 // specialization list, then either a base class or a category.
2187 if (FormatTok->Tok.is(tok::less)) {
2188 // Unlike protocol lists, generic parameterizations support
2189 // nested angles:
2190 //
2191 // @interface Foo<ValueType : id <NSCopying, NSSecureCoding>> :
2192 // NSObject <NSCopying, NSSecureCoding>
2193 //
2194 // so we need to count how many open angles we have left.
2195 unsigned NumOpenAngles = 1;
2196 do {
2197 nextToken();
2198 // Early exit in case someone forgot a close angle.
2199 if (FormatTok->isOneOf(tok::semi, tok::l_brace) ||
2200 FormatTok->Tok.isObjCAtKeyword(tok::objc_end))
2201 break;
2202 if (FormatTok->Tok.is(tok::less))
2203 ++NumOpenAngles;
2204 else if (FormatTok->Tok.is(tok::greater)) {
2205 assert(NumOpenAngles > 0 && "'>' makes NumOpenAngles negative");
2206 --NumOpenAngles;
2207 }
2208 } while (!eof() && NumOpenAngles != 0);
2209 nextToken(); // Skip '>'.
2210 }
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002211 if (FormatTok->Tok.is(tok::colon)) {
Nico Weber7eecf4b2013-01-09 20:25:35 +00002212 nextToken();
Daniel Jasperd1ae3582013-03-20 12:37:50 +00002213 nextToken(); // base class name
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002214 } else if (FormatTok->Tok.is(tok::l_paren))
Nico Weber7eecf4b2013-01-09 20:25:35 +00002215 // Skip category, if present.
2216 parseParens();
2217
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002218 if (FormatTok->Tok.is(tok::less))
Nico Weber8696a8d2013-01-09 21:15:03 +00002219 parseObjCProtocolList();
Nico Weber7eecf4b2013-01-09 20:25:35 +00002220
Dinesh Dwivediea3aca82014-05-02 17:01:46 +00002221 if (FormatTok->Tok.is(tok::l_brace)) {
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00002222 if (Style.BraceWrapping.AfterObjCDeclaration)
Dinesh Dwivediea3aca82014-05-02 17:01:46 +00002223 addUnwrappedLine();
Nico Weber9096fc02013-06-26 00:30:14 +00002224 parseBlock(/*MustBeDeclaration=*/true);
Dinesh Dwivediea3aca82014-05-02 17:01:46 +00002225 }
Nico Weber7eecf4b2013-01-09 20:25:35 +00002226
2227 // With instance variables, this puts '}' on its own line. Without instance
2228 // variables, this ends the @interface line.
2229 addUnwrappedLine();
2230
Nico Weber8696a8d2013-01-09 21:15:03 +00002231 parseObjCUntilAtEnd();
2232}
Nico Weber7eecf4b2013-01-09 20:25:35 +00002233
Nico Weberc068ff72018-01-23 17:10:25 +00002234// Returns true for the declaration/definition form of @protocol,
2235// false for the expression form.
2236bool UnwrappedLineParser::parseObjCProtocol() {
2237 assert(FormatTok->Tok.getObjCKeywordID() == tok::objc_protocol);
Nico Weber8696a8d2013-01-09 21:15:03 +00002238 nextToken();
Nico Weberc068ff72018-01-23 17:10:25 +00002239
2240 if (FormatTok->is(tok::l_paren))
2241 // The expression form of @protocol, e.g. "Protocol* p = @protocol(foo);".
2242 return false;
2243
2244 // The definition/declaration form,
2245 // @protocol Foo
2246 // - (int)someMethod;
2247 // @end
2248
Daniel Jasperd1ae3582013-03-20 12:37:50 +00002249 nextToken(); // protocol name
Nico Weber8696a8d2013-01-09 21:15:03 +00002250
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002251 if (FormatTok->Tok.is(tok::less))
Nico Weber8696a8d2013-01-09 21:15:03 +00002252 parseObjCProtocolList();
2253
2254 // Check for protocol declaration.
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002255 if (FormatTok->Tok.is(tok::semi)) {
Nico Weber8696a8d2013-01-09 21:15:03 +00002256 nextToken();
Nico Weberc068ff72018-01-23 17:10:25 +00002257 addUnwrappedLine();
2258 return true;
Nico Weber8696a8d2013-01-09 21:15:03 +00002259 }
2260
2261 addUnwrappedLine();
2262 parseObjCUntilAtEnd();
Nico Weberc068ff72018-01-23 17:10:25 +00002263 return true;
Nico Weber7eecf4b2013-01-09 20:25:35 +00002264}
2265
Daniel Jasperfca735c2015-02-19 16:14:18 +00002266void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
Martin Probst053f1aa2016-04-19 14:55:37 +00002267 bool IsImport = FormatTok->is(Keywords.kw_import);
2268 assert(IsImport || FormatTok->is(tok::kw_export));
Daniel Jasper354aa512015-02-19 16:07:32 +00002269 nextToken();
Daniel Jasperfca735c2015-02-19 16:14:18 +00002270
Daniel Jasperec05fc72015-05-11 09:14:50 +00002271 // Consume the "default" in "export default class/function".
Daniel Jasper668c7bb2015-05-11 09:03:10 +00002272 if (FormatTok->is(tok::kw_default))
2273 nextToken();
Daniel Jasperec05fc72015-05-11 09:14:50 +00002274
Martin Probst5f8445b2016-04-24 22:05:09 +00002275 // Consume "async function", "function" and "default function", so that these
2276 // get parsed as free-standing JS functions, i.e. do not require a trailing
2277 // semicolon.
2278 if (FormatTok->is(Keywords.kw_async))
2279 nextToken();
Daniel Jasper668c7bb2015-05-11 09:03:10 +00002280 if (FormatTok->is(Keywords.kw_function)) {
2281 nextToken();
2282 return;
2283 }
2284
Martin Probst053f1aa2016-04-19 14:55:37 +00002285 // For imports, `export *`, `export {...}`, consume the rest of the line up
2286 // to the terminating `;`. For everything else, just return and continue
2287 // parsing the structural element, i.e. the declaration or expression for
2288 // `export default`.
2289 if (!IsImport && !FormatTok->isOneOf(tok::l_brace, tok::star) &&
2290 !FormatTok->isStringLiteral())
2291 return;
Daniel Jasperfca735c2015-02-19 16:14:18 +00002292
Martin Probstd40bca42017-01-09 08:56:36 +00002293 while (!eof()) {
2294 if (FormatTok->is(tok::semi))
2295 return;
Krasimir Georgiev112c2e92017-11-09 13:22:03 +00002296 if (Line->Tokens.empty()) {
Martin Probstd40bca42017-01-09 08:56:36 +00002297 // Common issue: Automatic Semicolon Insertion wrapped the line, so the
2298 // import statement should terminate.
2299 return;
2300 }
Daniel Jasperefc1a832016-01-07 08:53:35 +00002301 if (FormatTok->is(tok::l_brace)) {
2302 FormatTok->BlockKind = BK_Block;
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00002303 nextToken();
Daniel Jasperefc1a832016-01-07 08:53:35 +00002304 parseBracedList();
2305 } else {
2306 nextToken();
2307 }
Daniel Jasper354aa512015-02-19 16:07:32 +00002308 }
2309}
2310
Daniel Jasper3b203a62013-09-05 16:05:56 +00002311LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line,
2312 StringRef Prefix = "") {
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00002313 llvm::dbgs() << Prefix << "Line(" << Line.Level
2314 << ", FSC=" << Line.FirstStartColumn << ")"
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +00002315 << (Line.InPPDirective ? " MACRO" : "") << ": ";
2316 for (std::list<UnwrappedLineNode>::const_iterator I = Line.Tokens.begin(),
2317 E = Line.Tokens.end();
2318 I != E; ++I) {
Krasimir Georgiev91834222017-01-25 13:58:58 +00002319 llvm::dbgs() << I->Tok->Tok.getName() << "["
Manuel Klimek89628f62017-09-20 09:51:03 +00002320 << "T=" << I->Tok->Type << ", OC=" << I->Tok->OriginalColumn
2321 << "] ";
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +00002322 }
2323 for (std::list<UnwrappedLineNode>::const_iterator I = Line.Tokens.begin(),
2324 E = Line.Tokens.end();
2325 I != E; ++I) {
2326 const UnwrappedLineNode &Node = *I;
2327 for (SmallVectorImpl<UnwrappedLine>::const_iterator
2328 I = Node.Children.begin(),
2329 E = Node.Children.end();
2330 I != E; ++I) {
2331 printDebugInfo(*I, "\nChild: ");
2332 }
2333 }
2334 llvm::dbgs() << "\n";
2335}
2336
Daniel Jasperf7935112012-12-03 18:12:45 +00002337void UnwrappedLineParser::addUnwrappedLine() {
Daniel Jasperdaffc0d2013-01-16 09:10:19 +00002338 if (Line->Tokens.empty())
Daniel Jasper7c85fde2013-01-08 14:56:18 +00002339 return;
Nicola Zaghen3538b392018-05-15 13:30:56 +00002340 LLVM_DEBUG({
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +00002341 if (CurrentLines == &Lines)
2342 printDebugInfo(*Line);
Manuel Klimekab3dc002013-01-16 12:31:12 +00002343 });
Benjamin Kramerc7551a42015-05-31 11:18:05 +00002344 CurrentLines->push_back(std::move(*Line));
Daniel Jasperdaffc0d2013-01-16 09:10:19 +00002345 Line->Tokens.clear();
Krasimir Georgiev85c37042017-03-01 16:38:08 +00002346 Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex;
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00002347 Line->FirstStartColumn = 0;
Manuel Klimekd3b92fa2013-01-18 14:04:34 +00002348 if (CurrentLines == &Lines && !PreprocessorDirectives.empty()) {
Benjamin Kramerc7551a42015-05-31 11:18:05 +00002349 CurrentLines->append(
2350 std::make_move_iterator(PreprocessorDirectives.begin()),
2351 std::make_move_iterator(PreprocessorDirectives.end()));
Manuel Klimekd3b92fa2013-01-18 14:04:34 +00002352 PreprocessorDirectives.clear();
2353 }
Manuel Klimeke411aa82017-09-20 09:29:37 +00002354 // Disconnect the current token from the last token on the previous line.
2355 FormatTok->Previous = nullptr;
Daniel Jasperf7935112012-12-03 18:12:45 +00002356}
2357
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002358bool UnwrappedLineParser::eof() const { return FormatTok->Tok.is(tok::eof); }
Daniel Jasperf7935112012-12-03 18:12:45 +00002359
Daniel Jasperb05a81d2014-05-09 13:11:16 +00002360bool UnwrappedLineParser::isOnNewLine(const FormatToken &FormatTok) {
Manuel Klimek1fcbe672014-04-11 12:27:47 +00002361 return (Line->InPPDirective || FormatTok.HasUnescapedNewline) &&
2362 FormatTok.NewlinesBefore > 0;
2363}
2364
Krasimir Georgiev91834222017-01-25 13:58:58 +00002365// Checks if \p FormatTok is a line comment that continues the line comment
2366// section on \p Line.
Krasimir Georgievea222a72017-05-22 10:07:56 +00002367static bool continuesLineCommentSection(const FormatToken &FormatTok,
2368 const UnwrappedLine &Line,
2369 llvm::Regex &CommentPragmasRegex) {
Krasimir Georgiev91834222017-01-25 13:58:58 +00002370 if (Line.Tokens.empty())
2371 return false;
Krasimir Georgiev84321612017-01-30 19:18:55 +00002372
Krasimir Georgiev00c5c722017-02-02 15:32:19 +00002373 StringRef IndentContent = FormatTok.TokenText;
2374 if (FormatTok.TokenText.startswith("//") ||
2375 FormatTok.TokenText.startswith("/*"))
2376 IndentContent = FormatTok.TokenText.substr(2);
2377 if (CommentPragmasRegex.match(IndentContent))
2378 return false;
2379
Krasimir Georgiev91834222017-01-25 13:58:58 +00002380 // If Line starts with a line comment, then FormatTok continues the comment
Krasimir Georgiev84321612017-01-30 19:18:55 +00002381 // section if its original column is greater or equal to the original start
Krasimir Georgiev91834222017-01-25 13:58:58 +00002382 // column of the line.
2383 //
Krasimir Georgiev84321612017-01-30 19:18:55 +00002384 // Define the min column token of a line as follows: if a line ends in '{' or
2385 // contains a '{' followed by a line comment, then the min column token is
2386 // that '{'. Otherwise, the min column token of the line is the first token of
2387 // the line.
2388 //
2389 // If Line starts with a token other than a line comment, then FormatTok
2390 // continues the comment section if its original column is greater than the
2391 // original start column of the min column token of the line.
Krasimir Georgiev91834222017-01-25 13:58:58 +00002392 //
2393 // For example, the second line comment continues the first in these cases:
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002394 //
Krasimir Georgiev91834222017-01-25 13:58:58 +00002395 // // first line
2396 // // second line
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002397 //
Krasimir Georgiev91834222017-01-25 13:58:58 +00002398 // and:
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002399 //
Krasimir Georgiev91834222017-01-25 13:58:58 +00002400 // // first line
2401 // // second line
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002402 //
Krasimir Georgiev91834222017-01-25 13:58:58 +00002403 // and:
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002404 //
Krasimir Georgiev91834222017-01-25 13:58:58 +00002405 // int i; // first line
2406 // // second line
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002407 //
Krasimir Georgiev84321612017-01-30 19:18:55 +00002408 // and:
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002409 //
Krasimir Georgiev84321612017-01-30 19:18:55 +00002410 // do { // first line
2411 // // second line
2412 // int i;
2413 // } while (true);
Krasimir Georgiev91834222017-01-25 13:58:58 +00002414 //
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002415 // and:
2416 //
2417 // enum {
2418 // a, // first line
2419 // // second line
2420 // b
2421 // };
2422 //
Krasimir Georgiev91834222017-01-25 13:58:58 +00002423 // The second line comment doesn't continue the first in these cases:
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002424 //
Krasimir Georgiev91834222017-01-25 13:58:58 +00002425 // // first line
2426 // // second line
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002427 //
Krasimir Georgiev91834222017-01-25 13:58:58 +00002428 // and:
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002429 //
Krasimir Georgiev91834222017-01-25 13:58:58 +00002430 // int i; // first line
2431 // // second line
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002432 //
Krasimir Georgiev84321612017-01-30 19:18:55 +00002433 // and:
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002434 //
Krasimir Georgiev84321612017-01-30 19:18:55 +00002435 // do { // first line
2436 // // second line
2437 // int i;
2438 // } while (true);
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002439 //
2440 // and:
2441 //
2442 // enum {
2443 // a, // first line
2444 // // second line
2445 // };
Krasimir Georgiev84321612017-01-30 19:18:55 +00002446 const FormatToken *MinColumnToken = Line.Tokens.front().Tok;
2447
2448 // Scan for '{//'. If found, use the column of '{' as a min column for line
2449 // comment section continuation.
2450 const FormatToken *PreviousToken = nullptr;
Krasimir Georgievd86c25d2017-03-10 13:09:29 +00002451 for (const UnwrappedLineNode &Node : Line.Tokens) {
Krasimir Georgiev84321612017-01-30 19:18:55 +00002452 if (PreviousToken && PreviousToken->is(tok::l_brace) &&
2453 isLineComment(*Node.Tok)) {
2454 MinColumnToken = PreviousToken;
2455 break;
2456 }
2457 PreviousToken = Node.Tok;
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002458
2459 // Grab the last newline preceding a token in this unwrapped line.
2460 if (Node.Tok->NewlinesBefore > 0) {
2461 MinColumnToken = Node.Tok;
2462 }
Krasimir Georgiev84321612017-01-30 19:18:55 +00002463 }
2464 if (PreviousToken && PreviousToken->is(tok::l_brace)) {
2465 MinColumnToken = PreviousToken;
2466 }
2467
Krasimir Georgievea222a72017-05-22 10:07:56 +00002468 return continuesLineComment(FormatTok, /*Previous=*/Line.Tokens.back().Tok,
2469 MinColumnToken);
Krasimir Georgiev91834222017-01-25 13:58:58 +00002470}
2471
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002472void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) {
2473 bool JustComments = Line->Tokens.empty();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002474 for (SmallVectorImpl<FormatToken *>::const_iterator
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002475 I = CommentsBeforeNextToken.begin(),
2476 E = CommentsBeforeNextToken.end();
2477 I != E; ++I) {
Krasimir Georgiev91834222017-01-25 13:58:58 +00002478 // Line comments that belong to the same line comment section are put on the
2479 // same line since later we might want to reflow content between them.
Krasimir Georgiev753625b2017-01-31 13:32:38 +00002480 // Additional fine-grained breaking of line comment sections is controlled
2481 // by the class BreakableLineCommentSection in case it is desirable to keep
2482 // several line comment sections in the same unwrapped line.
2483 //
2484 // FIXME: Consider putting separate line comment sections as children to the
2485 // unwrapped line instead.
Krasimir Georgiev00c5c722017-02-02 15:32:19 +00002486 (*I)->ContinuesLineCommentSection =
Krasimir Georgievea222a72017-05-22 10:07:56 +00002487 continuesLineCommentSection(**I, *Line, CommentPragmasRegex);
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002488 if (isOnNewLine(**I) && JustComments && !(*I)->ContinuesLineCommentSection)
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002489 addUnwrappedLine();
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002490 pushToken(*I);
2491 }
Daniel Jaspere60cba12015-05-13 11:35:53 +00002492 if (NewlineBeforeNext && JustComments)
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002493 addUnwrappedLine();
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002494 CommentsBeforeNextToken.clear();
2495}
2496
Krasimir Georgiev3e051052017-07-24 14:51:59 +00002497void UnwrappedLineParser::nextToken(int LevelDifference) {
Daniel Jasperf7935112012-12-03 18:12:45 +00002498 if (eof())
2499 return;
Manuel Klimek1fcbe672014-04-11 12:27:47 +00002500 flushComments(isOnNewLine(*FormatTok));
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002501 pushToken(FormatTok);
Manuel Klimek89628f62017-09-20 09:51:03 +00002502 FormatToken *Previous = FormatTok;
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +00002503 if (Style.Language != FormatStyle::LK_JavaScript)
Krasimir Georgiev3e051052017-07-24 14:51:59 +00002504 readToken(LevelDifference);
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +00002505 else
2506 readTokenWithJavaScriptASI();
Manuel Klimeke411aa82017-09-20 09:29:37 +00002507 FormatTok->Previous = Previous;
Daniel Jasperb9a49902016-01-09 15:56:28 +00002508}
2509
Krasimir Georgievf62f9582017-02-08 10:30:44 +00002510void UnwrappedLineParser::distributeComments(
2511 const SmallVectorImpl<FormatToken *> &Comments,
2512 const FormatToken *NextTok) {
2513 // Whether or not a line comment token continues a line is controlled by
Krasimir Georgievea222a72017-05-22 10:07:56 +00002514 // the method continuesLineCommentSection, with the following caveat:
Krasimir Georgievf62f9582017-02-08 10:30:44 +00002515 //
2516 // Define a trail of Comments to be a nonempty proper postfix of Comments such
2517 // that each comment line from the trail is aligned with the next token, if
2518 // the next token exists. If a trail exists, the beginning of the maximal
2519 // trail is marked as a start of a new comment section.
2520 //
2521 // For example in this code:
2522 //
2523 // int a; // line about a
2524 // // line 1 about b
2525 // // line 2 about b
2526 // int b;
2527 //
2528 // the two lines about b form a maximal trail, so there are two sections, the
2529 // first one consisting of the single comment "// line about a" and the
2530 // second one consisting of the next two comments.
2531 if (Comments.empty())
2532 return;
2533 bool ShouldPushCommentsInCurrentLine = true;
2534 bool HasTrailAlignedWithNextToken = false;
2535 unsigned StartOfTrailAlignedWithNextToken = 0;
2536 if (NextTok) {
2537 // We are skipping the first element intentionally.
2538 for (unsigned i = Comments.size() - 1; i > 0; --i) {
2539 if (Comments[i]->OriginalColumn == NextTok->OriginalColumn) {
2540 HasTrailAlignedWithNextToken = true;
2541 StartOfTrailAlignedWithNextToken = i;
2542 }
2543 }
2544 }
2545 for (unsigned i = 0, e = Comments.size(); i < e; ++i) {
2546 FormatToken *FormatTok = Comments[i];
Manuel Klimek89628f62017-09-20 09:51:03 +00002547 if (HasTrailAlignedWithNextToken && i == StartOfTrailAlignedWithNextToken) {
Krasimir Georgievf62f9582017-02-08 10:30:44 +00002548 FormatTok->ContinuesLineCommentSection = false;
2549 } else {
2550 FormatTok->ContinuesLineCommentSection =
Krasimir Georgievea222a72017-05-22 10:07:56 +00002551 continuesLineCommentSection(*FormatTok, *Line, CommentPragmasRegex);
Krasimir Georgievf62f9582017-02-08 10:30:44 +00002552 }
2553 if (!FormatTok->ContinuesLineCommentSection &&
2554 (isOnNewLine(*FormatTok) || FormatTok->IsFirst)) {
2555 ShouldPushCommentsInCurrentLine = false;
2556 }
2557 if (ShouldPushCommentsInCurrentLine) {
2558 pushToken(FormatTok);
2559 } else {
2560 CommentsBeforeNextToken.push_back(FormatTok);
2561 }
2562 }
2563}
2564
Krasimir Georgiev3e051052017-07-24 14:51:59 +00002565void UnwrappedLineParser::readToken(int LevelDifference) {
Krasimir Georgievf62f9582017-02-08 10:30:44 +00002566 SmallVector<FormatToken *, 1> Comments;
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002567 do {
2568 FormatTok = Tokens->getNextToken();
Alexander Kornienkoc2ee9cf2014-03-13 13:59:48 +00002569 assert(FormatTok);
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002570 while (!Line->InPPDirective && FormatTok->Tok.is(tok::hash) &&
2571 (FormatTok->HasUnescapedNewline || FormatTok->IsFirst)) {
Krasimir Georgievf62f9582017-02-08 10:30:44 +00002572 distributeComments(Comments, FormatTok);
2573 Comments.clear();
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002574 // If there is an unfinished unwrapped line, we flush the preprocessor
2575 // directives only after that unwrapped line was finished later.
Daniel Jasper29d39d52015-02-08 09:34:49 +00002576 bool SwitchToPreprocessorLines = !Line->Tokens.empty();
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002577 ScopedLineState BlockState(*this, SwitchToPreprocessorLines);
Krasimir Georgiev3e051052017-07-24 14:51:59 +00002578 assert((LevelDifference >= 0 ||
2579 static_cast<unsigned>(-LevelDifference) <= Line->Level) &&
2580 "LevelDifference makes Line->Level negative");
2581 Line->Level += LevelDifference;
Alexander Kornienkob1be9d62013-04-03 12:38:53 +00002582 // Comments stored before the preprocessor directive need to be output
2583 // before the preprocessor directive, at the same level as the
2584 // preprocessor directive, as we consider them to apply to the directive.
Manuel Klimek1fcbe672014-04-11 12:27:47 +00002585 flushComments(isOnNewLine(*FormatTok));
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002586 parsePPDirective();
2587 }
Manuel Klimek68b03042014-04-14 09:14:11 +00002588 while (FormatTok->Type == TT_ConflictStart ||
2589 FormatTok->Type == TT_ConflictEnd ||
2590 FormatTok->Type == TT_ConflictAlternative) {
2591 if (FormatTok->Type == TT_ConflictStart) {
2592 conditionalCompilationStart(/*Unreachable=*/false);
2593 } else if (FormatTok->Type == TT_ConflictAlternative) {
2594 conditionalCompilationAlternative();
Daniel Jasperb05a81d2014-05-09 13:11:16 +00002595 } else if (FormatTok->Type == TT_ConflictEnd) {
Manuel Klimek68b03042014-04-14 09:14:11 +00002596 conditionalCompilationEnd();
2597 }
2598 FormatTok = Tokens->getNextToken();
2599 FormatTok->MustBreakBefore = true;
2600 }
Alexander Kornienkof2e02122013-05-24 18:24:24 +00002601
Francois Ferranda98a95c2017-07-28 07:56:14 +00002602 if (!PPStack.empty() && (PPStack.back().Kind == PP_Unreachable) &&
Alexander Kornienkof2e02122013-05-24 18:24:24 +00002603 !Line->InPPDirective) {
2604 continue;
2605 }
2606
Krasimir Georgievf62f9582017-02-08 10:30:44 +00002607 if (!FormatTok->Tok.is(tok::comment)) {
2608 distributeComments(Comments, FormatTok);
2609 Comments.clear();
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002610 return;
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002611 }
Krasimir Georgievf62f9582017-02-08 10:30:44 +00002612
2613 Comments.push_back(FormatTok);
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002614 } while (!eof());
Krasimir Georgievf62f9582017-02-08 10:30:44 +00002615
2616 distributeComments(Comments, nullptr);
2617 Comments.clear();
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002618}
2619
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002620void UnwrappedLineParser::pushToken(FormatToken *Tok) {
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +00002621 Line->Tokens.push_back(UnwrappedLineNode(Tok));
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002622 if (MustBreakBeforeNextToken) {
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +00002623 Line->Tokens.back().Tok->MustBreakBefore = true;
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002624 MustBreakBeforeNextToken = false;
Manuel Klimek1abf7892013-01-04 23:34:14 +00002625 }
Daniel Jasperf7935112012-12-03 18:12:45 +00002626}
2627
Daniel Jasper8d1832e2013-01-07 13:26:07 +00002628} // end namespace format
2629} // end namespace clang