blob: 1057fabb77c4936c5c25fe98df0ea8690548766a [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
11/// \brief This file contains the implementation of the UnwrappedLineParser,
12/// 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) {
Manuel Klimek1abf7892013-01-04 23:34:14 +000086 TokenSource = this;
Manuel Klimekef2cfb12013-01-05 22:14:16 +000087 Line.Level = 0;
Manuel Klimek1abf7892013-01-04 23:34:14 +000088 Line.InPPDirective = true;
89 }
90
Alexander Kornienko34eb2072015-04-11 02:00:23 +000091 ~ScopedMacroState() override {
Manuel Klimek1abf7892013-01-04 23:34:14 +000092 TokenSource = PreviousTokenSource;
93 ResetToken = Token;
94 Line.InPPDirective = false;
Manuel Klimekef2cfb12013-01-05 22:14:16 +000095 Line.Level = PreviousLineLevel;
Manuel Klimek1abf7892013-01-04 23:34:14 +000096 }
97
Craig Topperfb6b25b2014-03-15 04:29:04 +000098 FormatToken *getNextToken() override {
Manuel Klimek78725712013-01-07 10:03:37 +000099 // The \c UnwrappedLineParser guards against this by never calling
100 // \c getNextToken() after it has encountered the first eof token.
101 assert(!eof());
Krasimir Georgieva1c30932017-05-19 10:34:57 +0000102 PreviousToken = Token;
Manuel Klimek1abf7892013-01-04 23:34:14 +0000103 Token = PreviousTokenSource->getNextToken();
104 if (eof())
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000105 return getFakeEOF();
Manuel Klimek1abf7892013-01-04 23:34:14 +0000106 return Token;
107 }
108
Craig Topperfb6b25b2014-03-15 04:29:04 +0000109 unsigned getPosition() override { return PreviousTokenSource->getPosition(); }
Manuel Klimekab419912013-05-23 09:41:43 +0000110
Craig Topperfb6b25b2014-03-15 04:29:04 +0000111 FormatToken *setPosition(unsigned Position) override {
Krasimir Georgieva1c30932017-05-19 10:34:57 +0000112 PreviousToken = nullptr;
Manuel Klimekab419912013-05-23 09:41:43 +0000113 Token = PreviousTokenSource->setPosition(Position);
114 return Token;
115 }
116
Manuel Klimek1abf7892013-01-04 23:34:14 +0000117private:
Krasimir Georgieva1c30932017-05-19 10:34:57 +0000118 bool eof() {
119 return Token && Token->HasUnescapedNewline &&
Krasimir Georgievea222a72017-05-22 10:07:56 +0000120 !continuesLineComment(*Token, PreviousToken,
121 /*MinColumnToken=*/PreviousToken);
Krasimir Georgieva1c30932017-05-19 10:34:57 +0000122 }
Manuel Klimek1abf7892013-01-04 23:34:14 +0000123
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000124 FormatToken *getFakeEOF() {
125 static bool EOFInitialized = false;
126 static FormatToken FormatTok;
127 if (!EOFInitialized) {
128 FormatTok.Tok.startToken();
129 FormatTok.Tok.setKind(tok::eof);
130 EOFInitialized = true;
131 }
132 return &FormatTok;
Manuel Klimek1abf7892013-01-04 23:34:14 +0000133 }
134
135 UnwrappedLine &Line;
136 FormatTokenSource *&TokenSource;
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000137 FormatToken *&ResetToken;
Manuel Klimekef2cfb12013-01-05 22:14:16 +0000138 unsigned PreviousLineLevel;
Manuel Klimek1abf7892013-01-04 23:34:14 +0000139 FormatTokenSource *PreviousTokenSource;
140
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000141 FormatToken *Token;
Krasimir Georgieva1c30932017-05-19 10:34:57 +0000142 FormatToken *PreviousToken;
Manuel Klimek1abf7892013-01-04 23:34:14 +0000143};
144
Craig Topper69665e12013-07-01 04:21:54 +0000145} // end anonymous namespace
146
Manuel Klimek8e07a1b2013-01-10 11:52:21 +0000147class ScopedLineState {
148public:
Manuel Klimekd3b92fa2013-01-18 14:04:34 +0000149 ScopedLineState(UnwrappedLineParser &Parser,
150 bool SwitchToPreprocessorLines = false)
David Blaikieefb6eb22014-08-09 20:02:07 +0000151 : Parser(Parser), OriginalLines(Parser.CurrentLines) {
Manuel Klimekd3b92fa2013-01-18 14:04:34 +0000152 if (SwitchToPreprocessorLines)
153 Parser.CurrentLines = &Parser.PreprocessorDirectives;
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +0000154 else if (!Parser.Line->Tokens.empty())
155 Parser.CurrentLines = &Parser.Line->Tokens.back().Children;
David Blaikieefb6eb22014-08-09 20:02:07 +0000156 PreBlockLine = std::move(Parser.Line);
157 Parser.Line = llvm::make_unique<UnwrappedLine>();
Daniel Jasperdaffc0d2013-01-16 09:10:19 +0000158 Parser.Line->Level = PreBlockLine->Level;
159 Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
Manuel Klimek8e07a1b2013-01-10 11:52:21 +0000160 }
161
162 ~ScopedLineState() {
Daniel Jasperdaffc0d2013-01-16 09:10:19 +0000163 if (!Parser.Line->Tokens.empty()) {
Manuel Klimek8e07a1b2013-01-10 11:52:21 +0000164 Parser.addUnwrappedLine();
165 }
Daniel Jasperdaffc0d2013-01-16 09:10:19 +0000166 assert(Parser.Line->Tokens.empty());
David Blaikieefb6eb22014-08-09 20:02:07 +0000167 Parser.Line = std::move(PreBlockLine);
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +0000168 if (Parser.CurrentLines == &Parser.PreprocessorDirectives)
169 Parser.MustBreakBeforeNextToken = true;
170 Parser.CurrentLines = OriginalLines;
Manuel Klimek8e07a1b2013-01-10 11:52:21 +0000171 }
172
173private:
174 UnwrappedLineParser &Parser;
175
David Blaikieefb6eb22014-08-09 20:02:07 +0000176 std::unique_ptr<UnwrappedLine> PreBlockLine;
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +0000177 SmallVectorImpl<UnwrappedLine> *OriginalLines;
Manuel Klimek8e07a1b2013-01-10 11:52:21 +0000178};
179
Alexander Kornienko3a33f022013-12-12 09:49:52 +0000180class CompoundStatementIndenter {
181public:
182 CompoundStatementIndenter(UnwrappedLineParser *Parser,
183 const FormatStyle &Style, unsigned &LineLevel)
184 : LineLevel(LineLevel), OldLineLevel(LineLevel) {
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000185 if (Style.BraceWrapping.AfterControlStatement)
Alexander Kornienko3a33f022013-12-12 09:49:52 +0000186 Parser->addUnwrappedLine();
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000187 if (Style.BraceWrapping.IndentBraces)
Alexander Kornienko3a33f022013-12-12 09:49:52 +0000188 ++LineLevel;
Alexander Kornienko3a33f022013-12-12 09:49:52 +0000189 }
Daniel Jasperb05a81d2014-05-09 13:11:16 +0000190 ~CompoundStatementIndenter() { LineLevel = OldLineLevel; }
Alexander Kornienko3a33f022013-12-12 09:49:52 +0000191
192private:
193 unsigned &LineLevel;
194 unsigned OldLineLevel;
195};
196
Craig Topper69665e12013-07-01 04:21:54 +0000197namespace {
198
Manuel Klimekab419912013-05-23 09:41:43 +0000199class IndexedTokenSource : public FormatTokenSource {
200public:
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000201 IndexedTokenSource(ArrayRef<FormatToken *> Tokens)
Manuel Klimekab419912013-05-23 09:41:43 +0000202 : Tokens(Tokens), Position(-1) {}
203
Craig Topperfb6b25b2014-03-15 04:29:04 +0000204 FormatToken *getNextToken() override {
Manuel Klimekab419912013-05-23 09:41:43 +0000205 ++Position;
206 return Tokens[Position];
207 }
208
Craig Topperfb6b25b2014-03-15 04:29:04 +0000209 unsigned getPosition() override {
Manuel Klimekab419912013-05-23 09:41:43 +0000210 assert(Position >= 0);
211 return Position;
212 }
213
Craig Topperfb6b25b2014-03-15 04:29:04 +0000214 FormatToken *setPosition(unsigned P) override {
Manuel Klimekab419912013-05-23 09:41:43 +0000215 Position = P;
216 return Tokens[Position];
217 }
218
Manuel Klimek71814b42013-10-11 21:25:45 +0000219 void reset() { Position = -1; }
220
Manuel Klimekab419912013-05-23 09:41:43 +0000221private:
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000222 ArrayRef<FormatToken *> Tokens;
Manuel Klimekab419912013-05-23 09:41:43 +0000223 int Position;
224};
225
Craig Topper69665e12013-07-01 04:21:54 +0000226} // end anonymous namespace
227
Daniel Jasperd2ae41a2013-05-15 08:14:19 +0000228UnwrappedLineParser::UnwrappedLineParser(const FormatStyle &Style,
Daniel Jasperd0ec0d62014-11-04 12:41:02 +0000229 const AdditionalKeywords &Keywords,
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +0000230 unsigned FirstStartColumn,
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000231 ArrayRef<FormatToken *> Tokens,
Daniel Jasperd2ae41a2013-05-15 08:14:19 +0000232 UnwrappedLineConsumer &Callback)
Daniel Jasperb05a81d2014-05-09 13:11:16 +0000233 : Line(new UnwrappedLine), MustBreakBeforeNextToken(false),
Krasimir Georgiev00c5c722017-02-02 15:32:19 +0000234 CurrentLines(&Lines), Style(Style), Keywords(Keywords),
235 CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr),
Krasimir Georgievad47c902017-08-30 14:34:57 +0000236 Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1),
237 IfNdefCondition(nullptr), FoundIncludeGuardStart(false),
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +0000238 IncludeGuardRejected(false), FirstStartColumn(FirstStartColumn) {}
Manuel Klimek71814b42013-10-11 21:25:45 +0000239
240void UnwrappedLineParser::reset() {
241 PPBranchLevel = -1;
Krasimir Georgievad47c902017-08-30 14:34:57 +0000242 IfNdefCondition = nullptr;
243 FoundIncludeGuardStart = false;
244 IncludeGuardRejected = false;
Manuel Klimek71814b42013-10-11 21:25:45 +0000245 Line.reset(new UnwrappedLine);
246 CommentsBeforeNextToken.clear();
Craig Topper2145bc02014-05-09 08:15:10 +0000247 FormatTok = nullptr;
Manuel Klimek71814b42013-10-11 21:25:45 +0000248 MustBreakBeforeNextToken = false;
249 PreprocessorDirectives.clear();
250 CurrentLines = &Lines;
251 DeclarationScopeStack.clear();
Manuel Klimek71814b42013-10-11 21:25:45 +0000252 PPStack.clear();
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +0000253 Line->FirstStartColumn = FirstStartColumn;
Manuel Klimek71814b42013-10-11 21:25:45 +0000254}
Daniel Jasperf7935112012-12-03 18:12:45 +0000255
Manuel Klimek20e0af62015-05-06 11:56:29 +0000256void UnwrappedLineParser::parse() {
Manuel Klimekab419912013-05-23 09:41:43 +0000257 IndexedTokenSource TokenSource(AllTokens);
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +0000258 Line->FirstStartColumn = FirstStartColumn;
Manuel Klimek71814b42013-10-11 21:25:45 +0000259 do {
260 DEBUG(llvm::dbgs() << "----\n");
261 reset();
262 Tokens = &TokenSource;
263 TokenSource.reset();
Daniel Jaspera79064a2013-03-01 18:11:39 +0000264
Manuel Klimek71814b42013-10-11 21:25:45 +0000265 readToken();
266 parseFile();
267 // Create line with eof token.
268 pushToken(FormatTok);
269 addUnwrappedLine();
270
271 for (SmallVectorImpl<UnwrappedLine>::iterator I = Lines.begin(),
272 E = Lines.end();
273 I != E; ++I) {
274 Callback.consumeUnwrappedLine(*I);
275 }
276 Callback.finishRun();
277 Lines.clear();
278 while (!PPLevelBranchIndex.empty() &&
Daniel Jasper53bd1672013-10-12 13:32:56 +0000279 PPLevelBranchIndex.back() + 1 >= PPLevelBranchCount.back()) {
Manuel Klimek71814b42013-10-11 21:25:45 +0000280 PPLevelBranchIndex.resize(PPLevelBranchIndex.size() - 1);
281 PPLevelBranchCount.resize(PPLevelBranchCount.size() - 1);
282 }
283 if (!PPLevelBranchIndex.empty()) {
284 ++PPLevelBranchIndex.back();
285 assert(PPLevelBranchIndex.size() == PPLevelBranchCount.size());
286 assert(PPLevelBranchIndex.back() <= PPLevelBranchCount.back());
287 }
288 } while (!PPLevelBranchIndex.empty());
Manuel Klimek1abf7892013-01-04 23:34:14 +0000289}
290
Manuel Klimek1a18c402013-04-12 14:13:36 +0000291void UnwrappedLineParser::parseFile() {
Daniel Jasper9326f912015-05-05 08:40:32 +0000292 // The top-level context in a file always has declarations, except for pre-
293 // processor directives and JavaScript files.
294 bool MustBeDeclaration =
295 !Line->InPPDirective && Style.Language != FormatStyle::LK_JavaScript;
296 ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
297 MustBeDeclaration);
Krasimir Georgiev26b144c2017-07-03 15:05:14 +0000298 if (Style.Language == FormatStyle::LK_TextProto)
299 parseBracedList();
300 else
301 parseLevel(/*HasOpeningBrace=*/false);
Manuel Klimek1abf7892013-01-04 23:34:14 +0000302 // Make sure to format the remaining tokens.
Manuel Klimekf92f7bc2013-01-22 16:31:55 +0000303 flushComments(true);
Manuel Klimek1abf7892013-01-04 23:34:14 +0000304 addUnwrappedLine();
Daniel Jasperf7935112012-12-03 18:12:45 +0000305}
306
Manuel Klimek1a18c402013-04-12 14:13:36 +0000307void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
Daniel Jasper516d7972013-07-25 11:31:57 +0000308 bool SwitchLabelEncountered = false;
Daniel Jasperf7935112012-12-03 18:12:45 +0000309 do {
Birunthan Mohanathasb001a0b2015-07-03 17:25:16 +0000310 tok::TokenKind kind = FormatTok->Tok.getKind();
311 if (FormatTok->Type == TT_MacroBlockBegin) {
312 kind = tok::l_brace;
313 } else if (FormatTok->Type == TT_MacroBlockEnd) {
314 kind = tok::r_brace;
315 }
316
317 switch (kind) {
Daniel Jasperf7935112012-12-03 18:12:45 +0000318 case tok::comment:
Daniel Jaspere25509f2012-12-17 11:29:41 +0000319 nextToken();
320 addUnwrappedLine();
Daniel Jasperf7935112012-12-03 18:12:45 +0000321 break;
322 case tok::l_brace:
Manuel Klimek0a3a3c92013-01-23 09:32:48 +0000323 // FIXME: Add parameter whether this can happen - if this happens, we must
324 // be in a non-declaration context.
Daniel Jasperb86e2722015-08-24 13:23:37 +0000325 if (!FormatTok->is(TT_MacroBlockBegin) && tryToParseBracedList())
326 continue;
Nico Weber9096fc02013-06-26 00:30:14 +0000327 parseBlock(/*MustBeDeclaration=*/false);
Daniel Jasperf7935112012-12-03 18:12:45 +0000328 addUnwrappedLine();
329 break;
330 case tok::r_brace:
Manuel Klimek1a18c402013-04-12 14:13:36 +0000331 if (HasOpeningBrace)
332 return;
Manuel Klimek1a18c402013-04-12 14:13:36 +0000333 nextToken();
334 addUnwrappedLine();
Manuel Klimek1058d982013-01-06 20:07:31 +0000335 break;
Nico Weberc29f83b2018-01-23 16:30:56 +0000336 case tok::kw_default: {
337 unsigned StoredPosition = Tokens->getPosition();
338 FormatToken *Next = Tokens->getNextToken();
339 FormatTok = Tokens->setPosition(StoredPosition);
340 if (Next && Next->isNot(tok::colon)) {
341 // default not followed by ':' is not a case label; treat it like
342 // an identifier.
343 parseStructuralElement();
344 break;
345 }
346 // Else, if it is 'default:', fall through to the case handling.
Nico Weberf1add5e2018-01-24 01:47:22 +0000347 LLVM_FALLTHROUGH;
Nico Weberc29f83b2018-01-23 16:30:56 +0000348 }
Daniel Jasper516d7972013-07-25 11:31:57 +0000349 case tok::kw_case:
Manuel Klimek89628f62017-09-20 09:51:03 +0000350 if (Style.Language == FormatStyle::LK_JavaScript &&
351 Line->MustBeDeclaration) {
Martin Probstf785fd92017-08-04 17:07:15 +0000352 // A 'case: string' style field declaration.
353 parseStructuralElement();
354 break;
355 }
Daniel Jasper72407622013-09-02 08:26:29 +0000356 if (!SwitchLabelEncountered &&
357 (Style.IndentCaseLabels || (Line->InPPDirective && Line->Level == 1)))
358 ++Line->Level;
Daniel Jasper516d7972013-07-25 11:31:57 +0000359 SwitchLabelEncountered = true;
360 parseStructuralElement();
361 break;
Daniel Jasperf7935112012-12-03 18:12:45 +0000362 default:
Manuel Klimek6b9eeba2013-01-07 14:56:16 +0000363 parseStructuralElement();
Daniel Jasperf7935112012-12-03 18:12:45 +0000364 break;
365 }
366 } while (!eof());
367}
368
Daniel Jasperadba2aa2015-05-18 12:52:00 +0000369void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
Manuel Klimekab419912013-05-23 09:41:43 +0000370 // We'll parse forward through the tokens until we hit
371 // a closing brace or eof - note that getNextToken() will
372 // parse macros, so this will magically work inside macro
373 // definitions, too.
374 unsigned StoredPosition = Tokens->getPosition();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000375 FormatToken *Tok = FormatTok;
Manuel Klimek89628f62017-09-20 09:51:03 +0000376 const FormatToken *PrevTok = Tok->Previous;
Manuel Klimekab419912013-05-23 09:41:43 +0000377 // Keep a stack of positions of lbrace tokens. We will
378 // update information about whether an lbrace starts a
379 // braced init list or a different block during the loop.
Daniel Jasperb1f74a82013-07-09 09:06:29 +0000380 SmallVector<FormatToken *, 8> LBraceStack;
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000381 assert(Tok->Tok.is(tok::l_brace));
Manuel Klimekab419912013-05-23 09:41:43 +0000382 do {
Daniel Jaspereb65e912015-12-21 18:31:15 +0000383 // Get next non-comment token.
Daniel Jasper7f5d53e2013-07-01 09:15:46 +0000384 FormatToken *NextTok;
Daniel Jasperca7bd722013-07-01 16:43:38 +0000385 unsigned ReadTokens = 0;
Daniel Jasper7f5d53e2013-07-01 09:15:46 +0000386 do {
387 NextTok = Tokens->getNextToken();
Daniel Jasperca7bd722013-07-01 16:43:38 +0000388 ++ReadTokens;
Daniel Jasper7f5d53e2013-07-01 09:15:46 +0000389 } while (NextTok->is(tok::comment));
390
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000391 switch (Tok->Tok.getKind()) {
Manuel Klimekab419912013-05-23 09:41:43 +0000392 case tok::l_brace:
Martin Probst95ed8e72017-05-31 09:29:40 +0000393 if (Style.Language == FormatStyle::LK_JavaScript && PrevTok) {
Martin Probste8e27ca2017-11-25 09:33:47 +0000394 if (PrevTok->isOneOf(tok::colon, tok::less))
395 // A ':' indicates this code is in a type, or a braced list
396 // following a label in an object literal ({a: {b: 1}}).
397 // A '<' could be an object used in a comparison, but that is nonsense
398 // code (can never return true), so more likely it is a generic type
399 // argument (`X<{a: string; b: number}>`).
400 // The code below could be confused by semicolons between the
401 // individual members in a type member list, which would normally
402 // trigger BK_Block. In both cases, this must be parsed as an inline
403 // braced init.
Martin Probst95ed8e72017-05-31 09:29:40 +0000404 Tok->BlockKind = BK_BracedInit;
405 else if (PrevTok->is(tok::r_paren))
406 // `) { }` can only occur in function or method declarations in JS.
407 Tok->BlockKind = BK_Block;
408 } else {
Daniel Jasperb9a49902016-01-09 15:56:28 +0000409 Tok->BlockKind = BK_Unknown;
Martin Probst95ed8e72017-05-31 09:29:40 +0000410 }
Daniel Jasperb1f74a82013-07-09 09:06:29 +0000411 LBraceStack.push_back(Tok);
Manuel Klimekab419912013-05-23 09:41:43 +0000412 break;
413 case tok::r_brace:
Daniel Jasperb9a49902016-01-09 15:56:28 +0000414 if (LBraceStack.empty())
415 break;
416 if (LBraceStack.back()->BlockKind == BK_Unknown) {
417 bool ProbablyBracedList = false;
418 if (Style.Language == FormatStyle::LK_Proto) {
419 ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square);
420 } else {
421 // Using OriginalColumn to distinguish between ObjC methods and
422 // binary operators is a bit hacky.
423 bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) &&
424 NextTok->OriginalColumn == 0;
Daniel Jasper91b032a2014-05-22 12:46:38 +0000425
Daniel Jasperb9a49902016-01-09 15:56:28 +0000426 // If there is a comma, semicolon or right paren after the closing
427 // brace, we assume this is a braced initializer list. Note that
428 // regardless how we mark inner braces here, we will overwrite the
429 // BlockKind later if we parse a braced list (where all blocks
430 // inside are by default braced lists), or when we explicitly detect
431 // blocks (for example while parsing lambdas).
Martin Probst95ed8e72017-05-31 09:29:40 +0000432 // FIXME: Some of these do not apply to JS, e.g. "} {" can never be a
433 // braced list in JS.
Daniel Jasperb9a49902016-01-09 15:56:28 +0000434 ProbablyBracedList =
Daniel Jasperacffeb82016-03-05 18:34:26 +0000435 (Style.Language == FormatStyle::LK_JavaScript &&
Martin Probste1e12a72016-08-19 14:35:01 +0000436 NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
437 Keywords.kw_as)) ||
Martin Probstb7fb2672017-05-10 13:53:29 +0000438 (Style.isCpp() && NextTok->is(tok::l_paren)) ||
Daniel Jasperb9a49902016-01-09 15:56:28 +0000439 NextTok->isOneOf(tok::comma, tok::period, tok::colon,
440 tok::r_paren, tok::r_square, tok::l_brace,
Martin Probstb7fb2672017-05-10 13:53:29 +0000441 tok::l_square, tok::ellipsis) ||
Daniel Jaspere4ada022016-12-13 10:05:03 +0000442 (NextTok->is(tok::identifier) &&
443 !PrevTok->isOneOf(tok::semi, tok::r_brace, tok::l_brace)) ||
Daniel Jasperb9a49902016-01-09 15:56:28 +0000444 (NextTok->is(tok::semi) &&
445 (!ExpectClassBody || LBraceStack.size() != 1)) ||
446 (NextTok->isBinaryOperator() && !NextIsObjCMethod);
Manuel Klimekab419912013-05-23 09:41:43 +0000447 }
Daniel Jasperb9a49902016-01-09 15:56:28 +0000448 if (ProbablyBracedList) {
449 Tok->BlockKind = BK_BracedInit;
450 LBraceStack.back()->BlockKind = BK_BracedInit;
451 } else {
452 Tok->BlockKind = BK_Block;
453 LBraceStack.back()->BlockKind = BK_Block;
454 }
Manuel Klimekab419912013-05-23 09:41:43 +0000455 }
Daniel Jasperb9a49902016-01-09 15:56:28 +0000456 LBraceStack.pop_back();
Manuel Klimekab419912013-05-23 09:41:43 +0000457 break;
Daniel Jasperac7e34e2014-03-13 10:11:17 +0000458 case tok::at:
Manuel Klimekab419912013-05-23 09:41:43 +0000459 case tok::semi:
460 case tok::kw_if:
461 case tok::kw_while:
462 case tok::kw_for:
463 case tok::kw_switch:
464 case tok::kw_try:
Nico Weberfac23712015-02-04 15:26:27 +0000465 case tok::kw___try:
Daniel Jasperb9a49902016-01-09 15:56:28 +0000466 if (!LBraceStack.empty() && LBraceStack.back()->BlockKind == BK_Unknown)
Daniel Jasperb1f74a82013-07-09 09:06:29 +0000467 LBraceStack.back()->BlockKind = BK_Block;
Manuel Klimekab419912013-05-23 09:41:43 +0000468 break;
469 default:
470 break;
471 }
Daniel Jasperb9a49902016-01-09 15:56:28 +0000472 PrevTok = Tok;
Manuel Klimekab419912013-05-23 09:41:43 +0000473 Tok = NextTok;
Manuel Klimekbab25fd2013-09-04 08:20:47 +0000474 } while (Tok->Tok.isNot(tok::eof) && !LBraceStack.empty());
Daniel Jasperb9a49902016-01-09 15:56:28 +0000475
Manuel Klimekab419912013-05-23 09:41:43 +0000476 // Assume other blocks for all unclosed opening braces.
477 for (unsigned i = 0, e = LBraceStack.size(); i != e; ++i) {
Daniel Jasperb1f74a82013-07-09 09:06:29 +0000478 if (LBraceStack[i]->BlockKind == BK_Unknown)
479 LBraceStack[i]->BlockKind = BK_Block;
Manuel Klimekab419912013-05-23 09:41:43 +0000480 }
Manuel Klimekbab25fd2013-09-04 08:20:47 +0000481
Manuel Klimekab419912013-05-23 09:41:43 +0000482 FormatTok = Tokens->setPosition(StoredPosition);
483}
484
Francois Ferranda98a95c2017-07-28 07:56:14 +0000485template <class T>
486static inline void hash_combine(std::size_t &seed, const T &v) {
487 std::hash<T> hasher;
488 seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
489}
490
491size_t UnwrappedLineParser::computePPHash() const {
492 size_t h = 0;
493 for (const auto &i : PPStack) {
494 hash_combine(h, size_t(i.Kind));
495 hash_combine(h, i.Line);
496 }
497 return h;
498}
499
Manuel Klimekb212f3b2013-10-12 22:46:56 +0000500void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel,
501 bool MunchSemi) {
Birunthan Mohanathasb001a0b2015-07-03 17:25:16 +0000502 assert(FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) &&
503 "'{' or macro block token expected");
504 const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin);
Daniel Jaspereb65e912015-12-21 18:31:15 +0000505 FormatTok->BlockKind = BK_Block;
Birunthan Mohanathasb001a0b2015-07-03 17:25:16 +0000506
Francois Ferranda98a95c2017-07-28 07:56:14 +0000507 size_t PPStartHash = computePPHash();
508
Daniel Jasper516d7972013-07-25 11:31:57 +0000509 unsigned InitialLevel = Line->Level;
Krasimir Georgiev3e051052017-07-24 14:51:59 +0000510 nextToken(/*LevelDifference=*/AddLevel ? 1 : 0);
Daniel Jasperf7935112012-12-03 18:12:45 +0000511
Birunthan Mohanathasb001a0b2015-07-03 17:25:16 +0000512 if (MacroBlock && FormatTok->is(tok::l_paren))
513 parseParens();
514
Francois Ferranda98a95c2017-07-28 07:56:14 +0000515 size_t NbPreprocessorDirectives =
516 CurrentLines == &Lines ? PreprocessorDirectives.size() : 0;
Manuel Klimeka4fe1c12013-01-21 16:42:44 +0000517 addUnwrappedLine();
Francois Ferranda98a95c2017-07-28 07:56:14 +0000518 size_t OpeningLineIndex =
519 CurrentLines->empty()
520 ? (UnwrappedLine::kInvalidIndex)
521 : (CurrentLines->size() - 1 - NbPreprocessorDirectives);
Daniel Jasperf7935112012-12-03 18:12:45 +0000522
Manuel Klimek0a3a3c92013-01-23 09:32:48 +0000523 ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
524 MustBeDeclaration);
Daniel Jasper65ee3472013-07-31 23:16:02 +0000525 if (AddLevel)
526 ++Line->Level;
Nico Weber9096fc02013-06-26 00:30:14 +0000527 parseLevel(/*HasOpeningBrace=*/true);
Alexander Kornienko578fdd82012-12-06 18:03:27 +0000528
Marianne Mailhot-Sarrasin03137c62016-04-14 14:56:49 +0000529 if (eof())
530 return;
531
Birunthan Mohanathasb001a0b2015-07-03 17:25:16 +0000532 if (MacroBlock ? !FormatTok->is(TT_MacroBlockEnd)
533 : !FormatTok->is(tok::r_brace)) {
Daniel Jasper516d7972013-07-25 11:31:57 +0000534 Line->Level = InitialLevel;
Daniel Jaspereb65e912015-12-21 18:31:15 +0000535 FormatTok->BlockKind = BK_Block;
Manuel Klimek1a18c402013-04-12 14:13:36 +0000536 return;
Manuel Klimekf92f7bc2013-01-22 16:31:55 +0000537 }
Alexander Kornienko0ea8e102012-12-04 15:40:36 +0000538
Francois Ferranda98a95c2017-07-28 07:56:14 +0000539 size_t PPEndHash = computePPHash();
540
Krasimir Georgiev3e051052017-07-24 14:51:59 +0000541 // Munch the closing brace.
542 nextToken(/*LevelDifference=*/AddLevel ? -1 : 0);
Birunthan Mohanathasb001a0b2015-07-03 17:25:16 +0000543
544 if (MacroBlock && FormatTok->is(tok::l_paren))
545 parseParens();
546
Manuel Klimekb212f3b2013-10-12 22:46:56 +0000547 if (MunchSemi && FormatTok->Tok.is(tok::semi))
548 nextToken();
Krasimir Georgiev3e051052017-07-24 14:51:59 +0000549 Line->Level = InitialLevel;
Francois Ferranda98a95c2017-07-28 07:56:14 +0000550
551 if (PPStartHash == PPEndHash) {
552 Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
553 if (OpeningLineIndex != UnwrappedLine::kInvalidIndex) {
554 // Update the opening line to add the forward reference as well
555 (*CurrentLines)[OpeningLineIndex].MatchingOpeningBlockLineIndex =
556 CurrentLines->size() - 1;
557 }
Francois Ferrande56a8292017-06-14 12:29:47 +0000558 }
Daniel Jasperf7935112012-12-03 18:12:45 +0000559}
560
Daniel Jasper02c7bca2015-03-30 09:56:50 +0000561static bool isGoogScope(const UnwrappedLine &Line) {
Daniel Jasper616de8642014-11-23 16:46:28 +0000562 // FIXME: Closure-library specific stuff should not be hard-coded but be
563 // configurable.
Daniel Jasper4a39c842014-05-06 13:54:10 +0000564 if (Line.Tokens.size() < 4)
565 return false;
566 auto I = Line.Tokens.begin();
567 if (I->Tok->TokenText != "goog")
568 return false;
569 ++I;
570 if (I->Tok->isNot(tok::period))
571 return false;
572 ++I;
573 if (I->Tok->TokenText != "scope")
574 return false;
575 ++I;
576 return I->Tok->is(tok::l_paren);
577}
578
Martin Probst101ec892017-05-09 20:04:09 +0000579static bool isIIFE(const UnwrappedLine &Line,
580 const AdditionalKeywords &Keywords) {
581 // Look for the start of an immediately invoked anonymous function.
582 // https://en.wikipedia.org/wiki/Immediately-invoked_function_expression
583 // This is commonly done in JavaScript to create a new, anonymous scope.
584 // Example: (function() { ... })()
585 if (Line.Tokens.size() < 3)
586 return false;
587 auto I = Line.Tokens.begin();
588 if (I->Tok->isNot(tok::l_paren))
589 return false;
590 ++I;
591 if (I->Tok->isNot(Keywords.kw_function))
592 return false;
593 ++I;
594 return I->Tok->is(tok::l_paren);
595}
596
Roman Kashitsyna043ced2014-08-11 12:18:01 +0000597static bool ShouldBreakBeforeBrace(const FormatStyle &Style,
598 const FormatToken &InitialToken) {
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000599 if (InitialToken.is(tok::kw_namespace))
600 return Style.BraceWrapping.AfterNamespace;
601 if (InitialToken.is(tok::kw_class))
602 return Style.BraceWrapping.AfterClass;
603 if (InitialToken.is(tok::kw_union))
604 return Style.BraceWrapping.AfterUnion;
605 if (InitialToken.is(tok::kw_struct))
606 return Style.BraceWrapping.AfterStruct;
607 return false;
Roman Kashitsyna043ced2014-08-11 12:18:01 +0000608}
609
Manuel Klimek516e0542013-09-04 13:25:30 +0000610void UnwrappedLineParser::parseChildBlock() {
611 FormatTok->BlockKind = BK_Block;
612 nextToken();
613 {
Manuel Klimek89628f62017-09-20 09:51:03 +0000614 bool SkipIndent = (Style.Language == FormatStyle::LK_JavaScript &&
615 (isGoogScope(*Line) || isIIFE(*Line, Keywords)));
Manuel Klimek516e0542013-09-04 13:25:30 +0000616 ScopedLineState LineState(*this);
617 ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
618 /*MustBeDeclaration=*/false);
Martin Probst101ec892017-05-09 20:04:09 +0000619 Line->Level += SkipIndent ? 0 : 1;
Manuel Klimek516e0542013-09-04 13:25:30 +0000620 parseLevel(/*HasOpeningBrace=*/true);
Daniel Jasper02c7bca2015-03-30 09:56:50 +0000621 flushComments(isOnNewLine(*FormatTok));
Martin Probst101ec892017-05-09 20:04:09 +0000622 Line->Level -= SkipIndent ? 0 : 1;
Manuel Klimek516e0542013-09-04 13:25:30 +0000623 }
624 nextToken();
625}
626
Daniel Jasperf7935112012-12-03 18:12:45 +0000627void UnwrappedLineParser::parsePPDirective() {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000628 assert(FormatTok->Tok.is(tok::hash) && "'#' expected");
Manuel Klimek20e0af62015-05-06 11:56:29 +0000629 ScopedMacroState MacroState(*Line, Tokens, FormatTok);
Manuel Klimeka71e5d82013-01-02 16:30:12 +0000630 nextToken();
631
Craig Topper2145bc02014-05-09 08:15:10 +0000632 if (!FormatTok->Tok.getIdentifierInfo()) {
Manuel Klimek591b5802013-01-31 15:58:48 +0000633 parsePPUnknown();
Manuel Klimeka71e5d82013-01-02 16:30:12 +0000634 return;
Daniel Jasperf7935112012-12-03 18:12:45 +0000635 }
Manuel Klimeka71e5d82013-01-02 16:30:12 +0000636
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000637 switch (FormatTok->Tok.getIdentifierInfo()->getPPKeywordID()) {
Manuel Klimek1abf7892013-01-04 23:34:14 +0000638 case tok::pp_define:
639 parsePPDefine();
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000640 return;
641 case tok::pp_if:
Manuel Klimek71814b42013-10-11 21:25:45 +0000642 parsePPIf(/*IfDef=*/false);
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000643 break;
644 case tok::pp_ifdef:
645 case tok::pp_ifndef:
Manuel Klimek71814b42013-10-11 21:25:45 +0000646 parsePPIf(/*IfDef=*/true);
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000647 break;
648 case tok::pp_else:
649 parsePPElse();
650 break;
651 case tok::pp_elif:
652 parsePPElIf();
653 break;
654 case tok::pp_endif:
655 parsePPEndIf();
Manuel Klimek1abf7892013-01-04 23:34:14 +0000656 break;
657 default:
658 parsePPUnknown();
659 break;
660 }
661}
662
Manuel Klimek68b03042014-04-14 09:14:11 +0000663void UnwrappedLineParser::conditionalCompilationCondition(bool Unreachable) {
Francois Ferranda98a95c2017-07-28 07:56:14 +0000664 size_t Line = CurrentLines->size();
665 if (CurrentLines == &PreprocessorDirectives)
666 Line += Lines.size();
667
668 if (Unreachable ||
669 (!PPStack.empty() && PPStack.back().Kind == PP_Unreachable))
670 PPStack.push_back({PP_Unreachable, Line});
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000671 else
Francois Ferranda98a95c2017-07-28 07:56:14 +0000672 PPStack.push_back({PP_Conditional, Line});
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000673}
674
Manuel Klimek68b03042014-04-14 09:14:11 +0000675void UnwrappedLineParser::conditionalCompilationStart(bool Unreachable) {
Manuel Klimek71814b42013-10-11 21:25:45 +0000676 ++PPBranchLevel;
677 assert(PPBranchLevel >= 0 && PPBranchLevel <= (int)PPLevelBranchIndex.size());
678 if (PPBranchLevel == (int)PPLevelBranchIndex.size()) {
679 PPLevelBranchIndex.push_back(0);
680 PPLevelBranchCount.push_back(0);
681 }
682 PPChainBranchIndex.push(0);
Manuel Klimek68b03042014-04-14 09:14:11 +0000683 bool Skip = PPLevelBranchIndex[PPBranchLevel] > 0;
684 conditionalCompilationCondition(Unreachable || Skip);
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000685}
686
Manuel Klimek68b03042014-04-14 09:14:11 +0000687void UnwrappedLineParser::conditionalCompilationAlternative() {
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000688 if (!PPStack.empty())
689 PPStack.pop_back();
Manuel Klimek71814b42013-10-11 21:25:45 +0000690 assert(PPBranchLevel < (int)PPLevelBranchIndex.size());
691 if (!PPChainBranchIndex.empty())
692 ++PPChainBranchIndex.top();
Manuel Klimek68b03042014-04-14 09:14:11 +0000693 conditionalCompilationCondition(
694 PPBranchLevel >= 0 && !PPChainBranchIndex.empty() &&
695 PPLevelBranchIndex[PPBranchLevel] != PPChainBranchIndex.top());
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000696}
697
Manuel Klimek68b03042014-04-14 09:14:11 +0000698void UnwrappedLineParser::conditionalCompilationEnd() {
Manuel Klimek71814b42013-10-11 21:25:45 +0000699 assert(PPBranchLevel < (int)PPLevelBranchIndex.size());
700 if (PPBranchLevel >= 0 && !PPChainBranchIndex.empty()) {
701 if (PPChainBranchIndex.top() + 1 > PPLevelBranchCount[PPBranchLevel]) {
Manuel Klimek71814b42013-10-11 21:25:45 +0000702 PPLevelBranchCount[PPBranchLevel] = PPChainBranchIndex.top() + 1;
703 }
704 }
Manuel Klimek14bd9172014-01-29 08:49:02 +0000705 // Guard against #endif's without #if.
Krasimir Georgievad47c902017-08-30 14:34:57 +0000706 if (PPBranchLevel > -1)
Manuel Klimek14bd9172014-01-29 08:49:02 +0000707 --PPBranchLevel;
Manuel Klimek71814b42013-10-11 21:25:45 +0000708 if (!PPChainBranchIndex.empty())
709 PPChainBranchIndex.pop();
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000710 if (!PPStack.empty())
711 PPStack.pop_back();
Manuel Klimek68b03042014-04-14 09:14:11 +0000712}
713
714void UnwrappedLineParser::parsePPIf(bool IfDef) {
Daniel Jasper62703eb2017-03-01 11:10:11 +0000715 bool IfNDef = FormatTok->is(tok::pp_ifndef);
Manuel Klimek68b03042014-04-14 09:14:11 +0000716 nextToken();
Daniel Jaspereab6cd42017-03-01 10:47:52 +0000717 bool Unreachable = false;
718 if (!IfDef && (FormatTok->is(tok::kw_false) || FormatTok->TokenText == "0"))
719 Unreachable = true;
Daniel Jasper62703eb2017-03-01 11:10:11 +0000720 if (IfDef && !IfNDef && FormatTok->TokenText == "SWIG")
Daniel Jaspereab6cd42017-03-01 10:47:52 +0000721 Unreachable = true;
722 conditionalCompilationStart(Unreachable);
Krasimir Georgievad47c902017-08-30 14:34:57 +0000723 FormatToken *IfCondition = FormatTok;
724 // If there's a #ifndef on the first line, and the only lines before it are
725 // comments, it could be an include guard.
726 bool MaybeIncludeGuard = IfNDef;
727 if (!IncludeGuardRejected && !FoundIncludeGuardStart && MaybeIncludeGuard) {
728 for (auto &Line : Lines) {
729 if (!Line.Tokens.front().Tok->is(tok::comment)) {
730 MaybeIncludeGuard = false;
731 IncludeGuardRejected = true;
732 break;
733 }
734 }
735 }
736 --PPBranchLevel;
Manuel Klimek68b03042014-04-14 09:14:11 +0000737 parsePPUnknown();
Krasimir Georgievad47c902017-08-30 14:34:57 +0000738 ++PPBranchLevel;
739 if (!IncludeGuardRejected && !FoundIncludeGuardStart && MaybeIncludeGuard)
740 IfNdefCondition = IfCondition;
Manuel Klimek68b03042014-04-14 09:14:11 +0000741}
742
743void UnwrappedLineParser::parsePPElse() {
Krasimir Georgievad47c902017-08-30 14:34:57 +0000744 // If a potential include guard has an #else, it's not an include guard.
745 if (FoundIncludeGuardStart && PPBranchLevel == 0)
746 FoundIncludeGuardStart = false;
Manuel Klimek68b03042014-04-14 09:14:11 +0000747 conditionalCompilationAlternative();
Krasimir Georgievad47c902017-08-30 14:34:57 +0000748 if (PPBranchLevel > -1)
749 --PPBranchLevel;
Manuel Klimek68b03042014-04-14 09:14:11 +0000750 parsePPUnknown();
Krasimir Georgievad47c902017-08-30 14:34:57 +0000751 ++PPBranchLevel;
Manuel Klimek68b03042014-04-14 09:14:11 +0000752}
753
754void UnwrappedLineParser::parsePPElIf() { parsePPElse(); }
755
756void UnwrappedLineParser::parsePPEndIf() {
757 conditionalCompilationEnd();
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000758 parsePPUnknown();
Krasimir Georgievad47c902017-08-30 14:34:57 +0000759 // If the #endif of a potential include guard is the last thing in the file,
760 // then we count it as a real include guard and subtract one from every
761 // preprocessor indent.
762 unsigned TokenPosition = Tokens->getPosition();
763 FormatToken *PeekNext = AllTokens[TokenPosition];
Daniel Jasper4df130f2017-09-04 13:33:52 +0000764 if (FoundIncludeGuardStart && PPBranchLevel == -1 && PeekNext->is(tok::eof) &&
765 Style.IndentPPDirectives != FormatStyle::PPDIS_None)
766 for (auto &Line : Lines)
Krasimir Georgievad47c902017-08-30 14:34:57 +0000767 if (Line.InPPDirective && Line.Level > 0)
768 --Line.Level;
Alexander Kornienkof2e02122013-05-24 18:24:24 +0000769}
770
Manuel Klimek1abf7892013-01-04 23:34:14 +0000771void UnwrappedLineParser::parsePPDefine() {
772 nextToken();
773
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000774 if (FormatTok->Tok.getKind() != tok::identifier) {
Manuel Klimek1abf7892013-01-04 23:34:14 +0000775 parsePPUnknown();
776 return;
777 }
Krasimir Georgievad47c902017-08-30 14:34:57 +0000778 if (IfNdefCondition && IfNdefCondition->TokenText == FormatTok->TokenText) {
779 FoundIncludeGuardStart = true;
780 for (auto &Line : Lines) {
781 if (!Line.Tokens.front().Tok->isOneOf(tok::comment, tok::hash)) {
782 FoundIncludeGuardStart = false;
783 break;
784 }
785 }
786 }
787 IfNdefCondition = nullptr;
Manuel Klimek1abf7892013-01-04 23:34:14 +0000788 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000789 if (FormatTok->Tok.getKind() == tok::l_paren &&
790 FormatTok->WhitespaceRange.getBegin() ==
791 FormatTok->WhitespaceRange.getEnd()) {
Manuel Klimek1abf7892013-01-04 23:34:14 +0000792 parseParens();
793 }
Krasimir Georgievad47c902017-08-30 14:34:57 +0000794 if (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash)
795 Line->Level += PPBranchLevel + 1;
Manuel Klimek1abf7892013-01-04 23:34:14 +0000796 addUnwrappedLine();
Krasimir Georgievad47c902017-08-30 14:34:57 +0000797 ++Line->Level;
Manuel Klimek1b896292013-01-07 09:34:28 +0000798
799 // Errors during a preprocessor directive can only affect the layout of the
800 // preprocessor directive, and thus we ignore them. An alternative approach
801 // would be to use the same approach we use on the file level (no
802 // re-indentation if there was a structural error) within the macro
803 // definition.
Manuel Klimek1abf7892013-01-04 23:34:14 +0000804 parseFile();
805}
806
807void UnwrappedLineParser::parsePPUnknown() {
Manuel Klimeka71e5d82013-01-02 16:30:12 +0000808 do {
Manuel Klimeka71e5d82013-01-02 16:30:12 +0000809 nextToken();
810 } while (!eof());
Krasimir Georgievad47c902017-08-30 14:34:57 +0000811 if (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash)
812 Line->Level += PPBranchLevel + 1;
Manuel Klimeka71e5d82013-01-02 16:30:12 +0000813 addUnwrappedLine();
Krasimir Georgievad47c902017-08-30 14:34:57 +0000814 IfNdefCondition = nullptr;
Daniel Jasperf7935112012-12-03 18:12:45 +0000815}
816
Alexander Kornienkoa04e5e22013-04-09 16:15:19 +0000817// Here we blacklist certain tokens that are not usually the first token in an
818// unwrapped line. This is used in attempt to distinguish macro calls without
819// trailing semicolons from other constructs split to several lines.
Benjamin Kramer8407df72015-03-09 16:47:52 +0000820static bool tokenCanStartNewLine(const clang::Token &Tok) {
Alexander Kornienkoa04e5e22013-04-09 16:15:19 +0000821 // Semicolon can be a null-statement, l_square can be a start of a macro or
822 // a C++11 attribute, but this doesn't seem to be common.
823 return Tok.isNot(tok::semi) && Tok.isNot(tok::l_brace) &&
824 Tok.isNot(tok::l_square) &&
825 // Tokens that can only be used as binary operators and a part of
826 // overloaded operator names.
827 Tok.isNot(tok::period) && Tok.isNot(tok::periodstar) &&
828 Tok.isNot(tok::arrow) && Tok.isNot(tok::arrowstar) &&
829 Tok.isNot(tok::less) && Tok.isNot(tok::greater) &&
830 Tok.isNot(tok::slash) && Tok.isNot(tok::percent) &&
831 Tok.isNot(tok::lessless) && Tok.isNot(tok::greatergreater) &&
832 Tok.isNot(tok::equal) && Tok.isNot(tok::plusequal) &&
833 Tok.isNot(tok::minusequal) && Tok.isNot(tok::starequal) &&
834 Tok.isNot(tok::slashequal) && Tok.isNot(tok::percentequal) &&
835 Tok.isNot(tok::ampequal) && Tok.isNot(tok::pipeequal) &&
836 Tok.isNot(tok::caretequal) && Tok.isNot(tok::greatergreaterequal) &&
837 Tok.isNot(tok::lesslessequal) &&
838 // Colon is used in labels, base class lists, initializer lists,
839 // range-based for loops, ternary operator, but should never be the
840 // first token in an unwrapped line.
Daniel Jasper5ebb2f32014-05-21 13:08:17 +0000841 Tok.isNot(tok::colon) &&
842 // 'noexcept' is a trailing annotation.
843 Tok.isNot(tok::kw_noexcept);
Alexander Kornienkoa04e5e22013-04-09 16:15:19 +0000844}
845
Martin Probst533965c2016-04-19 18:19:06 +0000846static bool mustBeJSIdent(const AdditionalKeywords &Keywords,
847 const FormatToken *FormatTok) {
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +0000848 // FIXME: This returns true for C/C++ keywords like 'struct'.
849 return FormatTok->is(tok::identifier) &&
850 (FormatTok->Tok.getIdentifierInfo() == nullptr ||
Martin Probst3dbbefa2016-11-10 16:21:02 +0000851 !FormatTok->isOneOf(
852 Keywords.kw_in, Keywords.kw_of, Keywords.kw_as, Keywords.kw_async,
853 Keywords.kw_await, Keywords.kw_yield, Keywords.kw_finally,
854 Keywords.kw_function, Keywords.kw_import, Keywords.kw_is,
855 Keywords.kw_let, Keywords.kw_var, tok::kw_const,
856 Keywords.kw_abstract, Keywords.kw_extends, Keywords.kw_implements,
Manuel Klimek89628f62017-09-20 09:51:03 +0000857 Keywords.kw_instanceof, Keywords.kw_interface, Keywords.kw_throws,
858 Keywords.kw_from));
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +0000859}
860
Martin Probst533965c2016-04-19 18:19:06 +0000861static bool mustBeJSIdentOrValue(const AdditionalKeywords &Keywords,
862 const FormatToken *FormatTok) {
Martin Probstb9316ff2016-09-18 17:21:52 +0000863 return FormatTok->Tok.isLiteral() ||
864 FormatTok->isOneOf(tok::kw_true, tok::kw_false) ||
865 mustBeJSIdent(Keywords, FormatTok);
Martin Probst533965c2016-04-19 18:19:06 +0000866}
867
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +0000868// isJSDeclOrStmt returns true if |FormatTok| starts a declaration or statement
869// when encountered after a value (see mustBeJSIdentOrValue).
870static bool isJSDeclOrStmt(const AdditionalKeywords &Keywords,
871 const FormatToken *FormatTok) {
872 return FormatTok->isOneOf(
Martin Probst5f8445b2016-04-24 22:05:09 +0000873 tok::kw_return, Keywords.kw_yield,
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +0000874 // conditionals
875 tok::kw_if, tok::kw_else,
876 // loops
877 tok::kw_for, tok::kw_while, tok::kw_do, tok::kw_continue, tok::kw_break,
878 // switch/case
879 tok::kw_switch, tok::kw_case,
880 // exceptions
881 tok::kw_throw, tok::kw_try, tok::kw_catch, Keywords.kw_finally,
882 // declaration
883 tok::kw_const, tok::kw_class, Keywords.kw_var, Keywords.kw_let,
Martin Probst5f8445b2016-04-24 22:05:09 +0000884 Keywords.kw_async, Keywords.kw_function,
885 // import/export
886 Keywords.kw_import, tok::kw_export);
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +0000887}
888
889// readTokenWithJavaScriptASI reads the next token and terminates the current
890// line if JavaScript Automatic Semicolon Insertion must
891// happen between the current token and the next token.
892//
893// This method is conservative - it cannot cover all edge cases of JavaScript,
894// but only aims to correctly handle certain well known cases. It *must not*
895// return true in speculative cases.
896void UnwrappedLineParser::readTokenWithJavaScriptASI() {
897 FormatToken *Previous = FormatTok;
898 readToken();
899 FormatToken *Next = FormatTok;
900
901 bool IsOnSameLine =
902 CommentsBeforeNextToken.empty()
903 ? Next->NewlinesBefore == 0
904 : CommentsBeforeNextToken.front()->NewlinesBefore == 0;
905 if (IsOnSameLine)
906 return;
907
908 bool PreviousMustBeValue = mustBeJSIdentOrValue(Keywords, Previous);
Martin Probst717f6dc2016-10-21 05:11:38 +0000909 bool PreviousStartsTemplateExpr =
910 Previous->is(TT_TemplateString) && Previous->TokenText.endswith("${");
Martin Probst7e0f25b2017-11-25 09:19:42 +0000911 if (PreviousMustBeValue || Previous->is(tok::r_paren)) {
912 // If the line contains an '@' sign, the previous token might be an
913 // annotation, which can precede another identifier/value.
914 bool HasAt = std::find_if(Line->Tokens.begin(), Line->Tokens.end(),
915 [](UnwrappedLineNode &LineNode) {
916 return LineNode.Tok->is(tok::at);
917 }) != Line->Tokens.end();
918 if (HasAt)
Martin Probstbbffeac2016-04-11 07:35:57 +0000919 return;
920 }
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +0000921 if (Next->is(tok::exclaim) && PreviousMustBeValue)
Martin Probstd40bca42017-01-09 08:56:36 +0000922 return addUnwrappedLine();
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +0000923 bool NextMustBeValue = mustBeJSIdentOrValue(Keywords, Next);
Martin Probst717f6dc2016-10-21 05:11:38 +0000924 bool NextEndsTemplateExpr =
925 Next->is(TT_TemplateString) && Next->TokenText.startswith("}");
926 if (NextMustBeValue && !NextEndsTemplateExpr && !PreviousStartsTemplateExpr &&
927 (PreviousMustBeValue ||
928 Previous->isOneOf(tok::r_square, tok::r_paren, tok::plusplus,
929 tok::minusminus)))
Martin Probstd40bca42017-01-09 08:56:36 +0000930 return addUnwrappedLine();
Martin Probst0a19d432017-08-09 15:19:16 +0000931 if ((PreviousMustBeValue || Previous->is(tok::r_paren)) &&
932 isJSDeclOrStmt(Keywords, Next))
Martin Probstd40bca42017-01-09 08:56:36 +0000933 return addUnwrappedLine();
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +0000934}
935
Manuel Klimek6b9eeba2013-01-07 14:56:16 +0000936void UnwrappedLineParser::parseStructuralElement() {
Daniel Jasper498f5582015-12-25 08:53:31 +0000937 assert(!FormatTok->is(tok::l_brace));
938 if (Style.Language == FormatStyle::LK_TableGen &&
939 FormatTok->is(tok::pp_include)) {
940 nextToken();
941 if (FormatTok->is(tok::string_literal))
942 nextToken();
943 addUnwrappedLine();
944 return;
945 }
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000946 switch (FormatTok->Tok.getKind()) {
Daniel Jasper8f463652014-08-26 23:15:12 +0000947 case tok::kw_asm:
Daniel Jasper8f463652014-08-26 23:15:12 +0000948 nextToken();
949 if (FormatTok->is(tok::l_brace)) {
Daniel Jasperc6366072015-05-10 08:42:04 +0000950 FormatTok->Type = TT_InlineASMBrace;
Daniel Jasper2337f282015-01-12 10:14:56 +0000951 nextToken();
Daniel Jasper4429f142014-08-27 17:16:46 +0000952 while (FormatTok && FormatTok->isNot(tok::eof)) {
Daniel Jasper8f463652014-08-26 23:15:12 +0000953 if (FormatTok->is(tok::r_brace)) {
Daniel Jasperc6366072015-05-10 08:42:04 +0000954 FormatTok->Type = TT_InlineASMBrace;
Daniel Jasper8f463652014-08-26 23:15:12 +0000955 nextToken();
Daniel Jasper790d4f92015-05-11 11:59:46 +0000956 addUnwrappedLine();
Daniel Jasper8f463652014-08-26 23:15:12 +0000957 break;
958 }
Daniel Jasper2337f282015-01-12 10:14:56 +0000959 FormatTok->Finalized = true;
Daniel Jasper8f463652014-08-26 23:15:12 +0000960 nextToken();
961 }
962 }
963 break;
Alexander Kornienko578fdd82012-12-06 18:03:27 +0000964 case tok::kw_namespace:
965 parseNamespace();
966 return;
Dmitri Gribenko58d64e22012-12-30 21:27:25 +0000967 case tok::kw_inline:
968 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +0000969 if (FormatTok->Tok.is(tok::kw_namespace)) {
Dmitri Gribenko58d64e22012-12-30 21:27:25 +0000970 parseNamespace();
971 return;
972 }
973 break;
Alexander Kornienkob7076a22012-12-04 14:46:19 +0000974 case tok::kw_public:
975 case tok::kw_protected:
976 case tok::kw_private:
Daniel Jasper83709082015-02-18 17:14:05 +0000977 if (Style.Language == FormatStyle::LK_Java ||
978 Style.Language == FormatStyle::LK_JavaScript)
Daniel Jasperc58c70e2014-09-15 11:21:46 +0000979 nextToken();
980 else
981 parseAccessSpecifier();
Daniel Jasperf7935112012-12-03 18:12:45 +0000982 return;
Alexander Kornienkob7076a22012-12-04 14:46:19 +0000983 case tok::kw_if:
984 parseIfThenElse();
Daniel Jasperf7935112012-12-03 18:12:45 +0000985 return;
Alexander Kornienko37d6c942012-12-05 15:06:06 +0000986 case tok::kw_for:
987 case tok::kw_while:
988 parseForOrWhileLoop();
989 return;
Alexander Kornienkob7076a22012-12-04 14:46:19 +0000990 case tok::kw_do:
991 parseDoWhile();
992 return;
993 case tok::kw_switch:
Martin Probstf785fd92017-08-04 17:07:15 +0000994 if (Style.Language == FormatStyle::LK_JavaScript && Line->MustBeDeclaration)
995 // 'switch: string' field declaration.
996 break;
Alexander Kornienkob7076a22012-12-04 14:46:19 +0000997 parseSwitch();
998 return;
999 case tok::kw_default:
Martin Probstf785fd92017-08-04 17:07:15 +00001000 if (Style.Language == FormatStyle::LK_JavaScript && Line->MustBeDeclaration)
1001 // 'default: string' field declaration.
1002 break;
Alexander Kornienkob7076a22012-12-04 14:46:19 +00001003 nextToken();
Nico Weberc29f83b2018-01-23 16:30:56 +00001004 if (FormatTok->is(tok::colon)) {
1005 parseLabel();
1006 return;
1007 }
1008 // e.g. "default void f() {}" in a Java interface.
1009 break;
Alexander Kornienkob7076a22012-12-04 14:46:19 +00001010 case tok::kw_case:
Martin Probstf785fd92017-08-04 17:07:15 +00001011 if (Style.Language == FormatStyle::LK_JavaScript && Line->MustBeDeclaration)
1012 // 'case: string' field declaration.
1013 break;
Alexander Kornienkob7076a22012-12-04 14:46:19 +00001014 parseCaseLabel();
1015 return;
Daniel Jasper04a71a42014-05-08 11:58:24 +00001016 case tok::kw_try:
Nico Weberfac23712015-02-04 15:26:27 +00001017 case tok::kw___try:
Daniel Jasper04a71a42014-05-08 11:58:24 +00001018 parseTryCatch();
1019 return;
Manuel Klimekae610d12013-01-21 14:32:05 +00001020 case tok::kw_extern:
1021 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001022 if (FormatTok->Tok.is(tok::string_literal)) {
Manuel Klimekae610d12013-01-21 14:32:05 +00001023 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001024 if (FormatTok->Tok.is(tok::l_brace)) {
Krasimir Georgievd6ce9372017-09-15 11:23:50 +00001025 if (Style.BraceWrapping.AfterExternBlock) {
1026 addUnwrappedLine();
1027 parseBlock(/*MustBeDeclaration=*/true);
1028 } else {
1029 parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/false);
1030 }
Manuel Klimekae610d12013-01-21 14:32:05 +00001031 addUnwrappedLine();
1032 return;
1033 }
1034 }
Daniel Jaspere1e43192014-04-01 12:55:11 +00001035 break;
Daniel Jasperfca735c2015-02-19 16:14:18 +00001036 case tok::kw_export:
1037 if (Style.Language == FormatStyle::LK_JavaScript) {
1038 parseJavaScriptEs6ImportExport();
1039 return;
1040 }
1041 break;
Daniel Jaspere1e43192014-04-01 12:55:11 +00001042 case tok::identifier:
Daniel Jasper66cb8c52015-05-04 09:22:29 +00001043 if (FormatTok->is(TT_ForEachMacro)) {
Daniel Jaspere1e43192014-04-01 12:55:11 +00001044 parseForOrWhileLoop();
1045 return;
1046 }
Birunthan Mohanathasb001a0b2015-07-03 17:25:16 +00001047 if (FormatTok->is(TT_MacroBlockBegin)) {
1048 parseBlock(/*MustBeDeclaration=*/false, /*AddLevel=*/true,
1049 /*MunchSemi=*/false);
1050 return;
1051 }
Daniel Jasper3d5a7d62016-06-20 18:20:38 +00001052 if (FormatTok->is(Keywords.kw_import)) {
1053 if (Style.Language == FormatStyle::LK_JavaScript) {
1054 parseJavaScriptEs6ImportExport();
1055 return;
1056 }
1057 if (Style.Language == FormatStyle::LK_Proto) {
1058 nextToken();
Daniel Jasper8b61d142016-06-20 20:39:53 +00001059 if (FormatTok->is(tok::kw_public))
1060 nextToken();
Daniel Jasper3d5a7d62016-06-20 18:20:38 +00001061 if (!FormatTok->is(tok::string_literal))
1062 return;
1063 nextToken();
1064 if (FormatTok->is(tok::semi))
1065 nextToken();
1066 addUnwrappedLine();
1067 return;
1068 }
Daniel Jasper354aa512015-02-19 16:07:32 +00001069 }
Daniel Jasper1dbc2102017-03-31 13:30:24 +00001070 if (Style.isCpp() &&
Daniel Jasper72b33572017-03-31 12:04:37 +00001071 FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
Daniel Jaspera00de632015-12-01 12:05:04 +00001072 Keywords.kw_slots, Keywords.kw_qslots)) {
Daniel Jasperde0d1f32015-04-24 07:50:34 +00001073 nextToken();
1074 if (FormatTok->is(tok::colon)) {
1075 nextToken();
1076 addUnwrappedLine();
Daniel Jasper31343832016-07-27 10:13:24 +00001077 return;
Daniel Jasperde0d1f32015-04-24 07:50:34 +00001078 }
Daniel Jasper53395402015-04-07 15:04:40 +00001079 }
Manuel Klimekae610d12013-01-21 14:32:05 +00001080 // In all other cases, parse the declaration.
1081 break;
Alexander Kornienkob7076a22012-12-04 14:46:19 +00001082 default:
1083 break;
Daniel Jasperf7935112012-12-03 18:12:45 +00001084 }
Daniel Jasperf7935112012-12-03 18:12:45 +00001085 do {
Manuel Klimeke411aa82017-09-20 09:29:37 +00001086 const FormatToken *Previous = FormatTok->Previous;
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001087 switch (FormatTok->Tok.getKind()) {
Nico Weber372d8dc2013-02-10 20:35:35 +00001088 case tok::at:
1089 nextToken();
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001090 if (FormatTok->Tok.is(tok::l_brace)) {
1091 nextToken();
Nico Weber372d8dc2013-02-10 20:35:35 +00001092 parseBracedList();
Nico Weberc068ff72018-01-23 17:10:25 +00001093 break;
1094 }
1095 switch (FormatTok->Tok.getObjCKeywordID()) {
1096 case tok::objc_public:
1097 case tok::objc_protected:
1098 case tok::objc_package:
1099 case tok::objc_private:
1100 return parseAccessSpecifier();
1101 case tok::objc_interface:
1102 case tok::objc_implementation:
1103 return parseObjCInterfaceOrImplementation();
1104 case tok::objc_protocol:
1105 if (parseObjCProtocol())
1106 return;
1107 break;
1108 case tok::objc_end:
1109 return; // Handled by the caller.
1110 case tok::objc_optional:
1111 case tok::objc_required:
1112 nextToken();
1113 addUnwrappedLine();
1114 return;
1115 case tok::objc_autoreleasepool:
1116 nextToken();
1117 if (FormatTok->Tok.is(tok::l_brace)) {
1118 if (Style.BraceWrapping.AfterObjCDeclaration)
1119 addUnwrappedLine();
1120 parseBlock(/*MustBeDeclaration=*/false);
1121 }
1122 addUnwrappedLine();
1123 return;
1124 case tok::objc_try:
1125 // This branch isn't strictly necessary (the kw_try case below would
1126 // do this too after the tok::at is parsed above). But be explicit.
1127 parseTryCatch();
1128 return;
1129 default:
1130 break;
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001131 }
Nico Weber372d8dc2013-02-10 20:35:35 +00001132 break;
Alexander Kornienkob7076a22012-12-04 14:46:19 +00001133 case tok::kw_enum:
Daniel Jaspera7900ad2016-05-08 18:12:22 +00001134 // Ignore if this is part of "template <enum ...".
1135 if (Previous && Previous->is(tok::less)) {
1136 nextToken();
1137 break;
1138 }
1139
Daniel Jasper90cf3802015-06-17 09:44:02 +00001140 // parseEnum falls through and does not yet add an unwrapped line as an
1141 // enum definition can start a structural element.
Daniel Jasper6f5a1932015-12-29 08:54:23 +00001142 if (!parseEnum())
1143 break;
Daniel Jasperc6dd2732015-07-16 14:25:43 +00001144 // This only applies for C++.
Daniel Jasper1dbc2102017-03-31 13:30:24 +00001145 if (!Style.isCpp()) {
Daniel Jasper90cf3802015-06-17 09:44:02 +00001146 addUnwrappedLine();
1147 return;
1148 }
Manuel Klimek2cec0192013-01-21 19:17:52 +00001149 break;
Daniel Jaspera88f80a2014-01-30 14:38:37 +00001150 case tok::kw_typedef:
1151 nextToken();
Daniel Jasper31f6c542014-12-05 10:42:21 +00001152 if (FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS,
1153 Keywords.kw_CF_ENUM, Keywords.kw_CF_OPTIONS))
Daniel Jaspera88f80a2014-01-30 14:38:37 +00001154 parseEnum();
1155 break;
Alexander Kornienko1231e062013-01-16 11:43:46 +00001156 case tok::kw_struct:
1157 case tok::kw_union:
Manuel Klimek28cacc72013-01-07 18:10:23 +00001158 case tok::kw_class:
Daniel Jasper910807d2015-06-12 04:52:02 +00001159 // parseRecord falls through and does not yet add an unwrapped line as a
1160 // record declaration or definition can start a structural element.
Manuel Klimeke01bab52013-01-15 13:38:33 +00001161 parseRecord();
Daniel Jasper910807d2015-06-12 04:52:02 +00001162 // This does not apply for Java and JavaScript.
1163 if (Style.Language == FormatStyle::LK_Java ||
1164 Style.Language == FormatStyle::LK_JavaScript) {
Daniel Jasperd5ec65b2016-01-08 07:06:07 +00001165 if (FormatTok->is(tok::semi))
1166 nextToken();
Daniel Jasper910807d2015-06-12 04:52:02 +00001167 addUnwrappedLine();
1168 return;
1169 }
Manuel Klimeke01bab52013-01-15 13:38:33 +00001170 break;
Daniel Jaspere5d74862014-11-26 08:17:08 +00001171 case tok::period:
1172 nextToken();
1173 // In Java, classes have an implicit static member "class".
1174 if (Style.Language == FormatStyle::LK_Java && FormatTok &&
1175 FormatTok->is(tok::kw_class))
1176 nextToken();
Daniel Jasperba52fcb2015-09-28 14:29:45 +00001177 if (Style.Language == FormatStyle::LK_JavaScript && FormatTok &&
1178 FormatTok->Tok.getIdentifierInfo())
1179 // JavaScript only has pseudo keywords, all keywords are allowed to
1180 // appear in "IdentifierName" positions. See http://es5.github.io/#x7.6
1181 nextToken();
Daniel Jaspere5d74862014-11-26 08:17:08 +00001182 break;
Daniel Jasperf7935112012-12-03 18:12:45 +00001183 case tok::semi:
1184 nextToken();
1185 addUnwrappedLine();
1186 return;
Alexander Kornienko1231e062013-01-16 11:43:46 +00001187 case tok::r_brace:
1188 addUnwrappedLine();
1189 return;
Daniel Jasperf7935112012-12-03 18:12:45 +00001190 case tok::l_paren:
1191 parseParens();
1192 break;
Daniel Jasper5af04a42015-10-07 03:43:10 +00001193 case tok::kw_operator:
1194 nextToken();
1195 if (FormatTok->isBinaryOperator())
1196 nextToken();
1197 break;
Manuel Klimek516e0542013-09-04 13:25:30 +00001198 case tok::caret:
1199 nextToken();
Daniel Jasper395193c2014-03-28 07:48:59 +00001200 if (FormatTok->Tok.isAnyIdentifier() ||
1201 FormatTok->isSimpleTypeSpecifier())
1202 nextToken();
1203 if (FormatTok->is(tok::l_paren))
1204 parseParens();
1205 if (FormatTok->is(tok::l_brace))
Manuel Klimek516e0542013-09-04 13:25:30 +00001206 parseChildBlock();
Manuel Klimek516e0542013-09-04 13:25:30 +00001207 break;
Daniel Jasperf7935112012-12-03 18:12:45 +00001208 case tok::l_brace:
Manuel Klimekab419912013-05-23 09:41:43 +00001209 if (!tryToParseBracedList()) {
1210 // A block outside of parentheses must be the last part of a
1211 // structural element.
1212 // FIXME: Figure out cases where this is not true, and add projections
1213 // for them (the one we know is missing are lambdas).
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00001214 if (Style.BraceWrapping.AfterFunction)
Manuel Klimekab419912013-05-23 09:41:43 +00001215 addUnwrappedLine();
Alexander Kornienko3cfa9732013-11-20 16:33:05 +00001216 FormatTok->Type = TT_FunctionLBrace;
Nico Weber9096fc02013-06-26 00:30:14 +00001217 parseBlock(/*MustBeDeclaration=*/false);
Manuel Klimeka8eb9142013-05-13 12:51:40 +00001218 addUnwrappedLine();
Manuel Klimekab419912013-05-23 09:41:43 +00001219 return;
1220 }
1221 // Otherwise this was a braced init list, and the structural
1222 // element continues.
1223 break;
Daniel Jasper04a71a42014-05-08 11:58:24 +00001224 case tok::kw_try:
1225 // We arrive here when parsing function-try blocks.
1226 parseTryCatch();
1227 return;
Daniel Jasper40e19212013-05-29 13:16:10 +00001228 case tok::identifier: {
Birunthan Mohanathasb001a0b2015-07-03 17:25:16 +00001229 if (FormatTok->is(TT_MacroBlockEnd)) {
1230 addUnwrappedLine();
1231 return;
1232 }
1233
Martin Probst973ff792017-04-27 13:07:24 +00001234 // Function declarations (as opposed to function expressions) are parsed
1235 // on their own unwrapped line by continuing this loop. Function
1236 // expressions (functions that are not on their own line) must not create
1237 // a new unwrapped line, so they are special cased below.
1238 size_t TokenCount = Line->Tokens.size();
Daniel Jasper9326f912015-05-05 08:40:32 +00001239 if (Style.Language == FormatStyle::LK_JavaScript &&
Martin Probst973ff792017-04-27 13:07:24 +00001240 FormatTok->is(Keywords.kw_function) &&
1241 (TokenCount > 1 || (TokenCount == 1 && !Line->Tokens.front().Tok->is(
1242 Keywords.kw_async)))) {
Daniel Jasper069e5f42014-05-20 11:14:57 +00001243 tryToParseJSFunction();
1244 break;
1245 }
Daniel Jasper9326f912015-05-05 08:40:32 +00001246 if ((Style.Language == FormatStyle::LK_JavaScript ||
1247 Style.Language == FormatStyle::LK_Java) &&
1248 FormatTok->is(Keywords.kw_interface)) {
Martin Probst1e8261e2016-04-19 18:18:59 +00001249 if (Style.Language == FormatStyle::LK_JavaScript) {
1250 // In JavaScript/TypeScript, "interface" can be used as a standalone
1251 // identifier, e.g. in `var interface = 1;`. If "interface" is
1252 // followed by another identifier, it is very like to be an actual
1253 // interface declaration.
1254 unsigned StoredPosition = Tokens->getPosition();
1255 FormatToken *Next = Tokens->getNextToken();
1256 FormatTok = Tokens->setPosition(StoredPosition);
Martin Probst533965c2016-04-19 18:19:06 +00001257 if (Next && !mustBeJSIdent(Keywords, Next)) {
Martin Probst1e8261e2016-04-19 18:18:59 +00001258 nextToken();
1259 break;
1260 }
1261 }
Daniel Jasper9326f912015-05-05 08:40:32 +00001262 parseRecord();
Daniel Jasper259188b2015-06-12 04:56:34 +00001263 addUnwrappedLine();
Daniel Jasper5c235c02015-07-06 14:26:04 +00001264 return;
Daniel Jasper9326f912015-05-05 08:40:32 +00001265 }
1266
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +00001267 // See if the following token should start a new unwrapped line.
Daniel Jasper9326f912015-05-05 08:40:32 +00001268 StringRef Text = FormatTok->TokenText;
Daniel Jasperf7935112012-12-03 18:12:45 +00001269 nextToken();
Daniel Jasper83709082015-02-18 17:14:05 +00001270 if (Line->Tokens.size() == 1 &&
1271 // JS doesn't have macros, and within classes colons indicate fields,
1272 // not labels.
Daniel Jasper676e5162015-04-07 14:36:33 +00001273 Style.Language != FormatStyle::LK_JavaScript) {
1274 if (FormatTok->Tok.is(tok::colon) && !Line->MustBeDeclaration) {
Daniel Jasper40609472016-04-06 15:02:46 +00001275 Line->Tokens.begin()->Tok->MustBreakBefore = true;
Alexander Kornienkode644272013-04-08 22:16:06 +00001276 parseLabel();
1277 return;
1278 }
Daniel Jasper680b09b2014-11-05 10:48:04 +00001279 // Recognize function-like macro usages without trailing semicolon as
Daniel Jasper83709082015-02-18 17:14:05 +00001280 // well as free-standing macros like Q_OBJECT.
Daniel Jasper680b09b2014-11-05 10:48:04 +00001281 bool FunctionLike = FormatTok->is(tok::l_paren);
1282 if (FunctionLike)
Alexander Kornienkode644272013-04-08 22:16:06 +00001283 parseParens();
Daniel Jaspere60cba12015-05-13 11:35:53 +00001284
1285 bool FollowedByNewline =
1286 CommentsBeforeNextToken.empty()
1287 ? FormatTok->NewlinesBefore > 0
1288 : CommentsBeforeNextToken.front()->NewlinesBefore > 0;
1289
Daniel Jaspere6fcf7d2015-06-17 13:08:06 +00001290 if (FollowedByNewline && (Text.size() >= 5 || FunctionLike) &&
Daniel Jasper680b09b2014-11-05 10:48:04 +00001291 tokenCanStartNewLine(FormatTok->Tok) && Text == Text.upper()) {
Daniel Jasper40e19212013-05-29 13:16:10 +00001292 addUnwrappedLine();
Daniel Jasper41a0f782013-05-29 14:09:17 +00001293 return;
Alexander Kornienkode644272013-04-08 22:16:06 +00001294 }
Daniel Jasperf7935112012-12-03 18:12:45 +00001295 }
1296 break;
Daniel Jasper40e19212013-05-29 13:16:10 +00001297 }
Daniel Jaspere25509f2012-12-17 11:29:41 +00001298 case tok::equal:
Manuel Klimek79e06082015-05-21 12:23:34 +00001299 // Fat arrows (=>) have tok::TokenKind tok::equal but TokenType
1300 // TT_JsFatArrow. The always start an expression or a child block if
1301 // followed by a curly.
1302 if (FormatTok->is(TT_JsFatArrow)) {
1303 nextToken();
Daniel Jasperbe520bd2015-05-31 08:51:54 +00001304 if (FormatTok->is(tok::l_brace))
Manuel Klimek79e06082015-05-21 12:23:34 +00001305 parseChildBlock();
Manuel Klimek79e06082015-05-21 12:23:34 +00001306 break;
1307 }
1308
Daniel Jaspere25509f2012-12-17 11:29:41 +00001309 nextToken();
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001310 if (FormatTok->Tok.is(tok::l_brace)) {
1311 nextToken();
Manuel Klimek8e07a1b2013-01-10 11:52:21 +00001312 parseBracedList();
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001313 } else if (Style.Language == FormatStyle::LK_Proto &&
Manuel Klimek89628f62017-09-20 09:51:03 +00001314 FormatTok->Tok.is(tok::less)) {
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001315 nextToken();
Krasimir Georgiev0b41fcb2017-06-27 13:58:41 +00001316 parseBracedList(/*ContinueOnSemicolons=*/false,
1317 /*ClosingBraceKind=*/tok::greater);
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001318 }
Daniel Jaspere25509f2012-12-17 11:29:41 +00001319 break;
Manuel Klimekffdeb592013-09-03 15:10:01 +00001320 case tok::l_square:
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001321 parseSquare();
Manuel Klimekffdeb592013-09-03 15:10:01 +00001322 break;
Daniel Jasper6acf5132015-03-12 14:44:29 +00001323 case tok::kw_new:
1324 parseNew();
1325 break;
Alexander Kornienkob7076a22012-12-04 14:46:19 +00001326 default:
1327 nextToken();
1328 break;
Daniel Jasperf7935112012-12-03 18:12:45 +00001329 }
1330 } while (!eof());
1331}
1332
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001333bool UnwrappedLineParser::tryToParseLambda() {
Daniel Jasper1dbc2102017-03-31 13:30:24 +00001334 if (!Style.isCpp()) {
Daniel Jasper1feab0f2015-06-02 15:31:37 +00001335 nextToken();
1336 return false;
1337 }
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +00001338 assert(FormatTok->is(tok::l_square));
1339 FormatToken &LSquare = *FormatTok;
Daniel Jasper9a8d48b2013-09-05 10:04:31 +00001340 if (!tryToParseLambdaIntroducer())
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001341 return false;
Manuel Klimekffdeb592013-09-03 15:10:01 +00001342
Alexander Kornienkoc2ee9cf2014-03-13 13:59:48 +00001343 while (FormatTok->isNot(tok::l_brace)) {
Daniel Jaspercb51cf42014-01-16 09:11:55 +00001344 if (FormatTok->isSimpleTypeSpecifier()) {
1345 nextToken();
1346 continue;
1347 }
Manuel Klimekffdeb592013-09-03 15:10:01 +00001348 switch (FormatTok->Tok.getKind()) {
Daniel Jasper9a8d48b2013-09-05 10:04:31 +00001349 case tok::l_brace:
1350 break;
1351 case tok::l_paren:
1352 parseParens();
1353 break;
Daniel Jasperbcb55ee2014-11-21 14:08:38 +00001354 case tok::amp:
1355 case tok::star:
1356 case tok::kw_const:
Daniel Jasper3431b752014-12-08 13:22:37 +00001357 case tok::comma:
Daniel Jaspercb51cf42014-01-16 09:11:55 +00001358 case tok::less:
1359 case tok::greater:
Daniel Jasper9a8d48b2013-09-05 10:04:31 +00001360 case tok::identifier:
Daniel Jasper5eaa0092015-08-13 13:37:08 +00001361 case tok::numeric_constant:
Daniel Jasper1067ab02014-02-11 10:16:55 +00001362 case tok::coloncolon:
Daniel Jasper9a8d48b2013-09-05 10:04:31 +00001363 case tok::kw_mutable:
Daniel Jasper81a20782014-03-10 10:02:02 +00001364 nextToken();
1365 break;
Daniel Jaspercb51cf42014-01-16 09:11:55 +00001366 case tok::arrow:
Daniel Jasper6f2b88a2015-06-05 13:18:09 +00001367 FormatTok->Type = TT_LambdaArrow;
Daniel Jasper9a8d48b2013-09-05 10:04:31 +00001368 nextToken();
1369 break;
1370 default:
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001371 return true;
Manuel Klimekffdeb592013-09-03 15:10:01 +00001372 }
1373 }
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +00001374 LSquare.Type = TT_LambdaLSquare;
Manuel Klimek516e0542013-09-04 13:25:30 +00001375 parseChildBlock();
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001376 return true;
Manuel Klimekffdeb592013-09-03 15:10:01 +00001377}
1378
1379bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
Manuel Klimek89628f62017-09-20 09:51:03 +00001380 const FormatToken *Previous = FormatTok->Previous;
Manuel Klimek9f0a4e52017-09-19 09:59:30 +00001381 if (Previous &&
1382 (Previous->isOneOf(tok::identifier, tok::kw_operator, tok::kw_new,
1383 tok::kw_delete) ||
Manuel Klimek89628f62017-09-20 09:51:03 +00001384 FormatTok->isCppStructuredBinding(Style) || Previous->closesScope() ||
1385 Previous->isSimpleTypeSpecifier())) {
Manuel Klimekffdeb592013-09-03 15:10:01 +00001386 nextToken();
Manuel Klimek9f0a4e52017-09-19 09:59:30 +00001387 return false;
Manuel Klimekffdeb592013-09-03 15:10:01 +00001388 }
Manuel Klimek9f0a4e52017-09-19 09:59:30 +00001389 nextToken();
1390 parseSquare(/*LambdaIntroducer=*/true);
1391 return true;
Manuel Klimekffdeb592013-09-03 15:10:01 +00001392}
1393
Daniel Jasperc03e16a2014-05-08 09:25:39 +00001394void UnwrappedLineParser::tryToParseJSFunction() {
Martin Probst409697e2016-05-29 14:41:07 +00001395 assert(FormatTok->is(Keywords.kw_function) ||
1396 FormatTok->startsSequence(Keywords.kw_async, Keywords.kw_function));
Martin Probst5f8445b2016-04-24 22:05:09 +00001397 if (FormatTok->is(Keywords.kw_async))
1398 nextToken();
1399 // Consume "function".
Daniel Jasperc03e16a2014-05-08 09:25:39 +00001400 nextToken();
Daniel Jasper5217a8b2014-06-13 07:02:04 +00001401
Daniel Jasper71e50af2016-11-01 06:22:59 +00001402 // Consume * (generator function). Treat it like C++'s overloaded operators.
1403 if (FormatTok->is(tok::star)) {
1404 FormatTok->Type = TT_OverloadedOperator;
Martin Probst5f8445b2016-04-24 22:05:09 +00001405 nextToken();
Daniel Jasper71e50af2016-11-01 06:22:59 +00001406 }
Martin Probst5f8445b2016-04-24 22:05:09 +00001407
Daniel Jasper5217a8b2014-06-13 07:02:04 +00001408 // Consume function name.
1409 if (FormatTok->is(tok::identifier))
Daniel Jasperfca735c2015-02-19 16:14:18 +00001410 nextToken();
Daniel Jasper5217a8b2014-06-13 07:02:04 +00001411
Daniel Jasperc03e16a2014-05-08 09:25:39 +00001412 if (FormatTok->isNot(tok::l_paren))
1413 return;
Manuel Klimek79e06082015-05-21 12:23:34 +00001414
1415 // Parse formal parameter list.
Daniel Jasperbe520bd2015-05-31 08:51:54 +00001416 parseParens();
Manuel Klimek79e06082015-05-21 12:23:34 +00001417
1418 if (FormatTok->is(tok::colon)) {
1419 // Parse a type definition.
1420 nextToken();
1421
1422 // Eat the type declaration. For braced inline object types, balance braces,
1423 // otherwise just parse until finding an l_brace for the function body.
Daniel Jasperbe520bd2015-05-31 08:51:54 +00001424 if (FormatTok->is(tok::l_brace))
1425 tryToParseBracedList();
1426 else
Martin Probstaf16c502017-01-04 13:36:43 +00001427 while (!FormatTok->isOneOf(tok::l_brace, tok::semi) && !eof())
Manuel Klimek79e06082015-05-21 12:23:34 +00001428 nextToken();
Manuel Klimek79e06082015-05-21 12:23:34 +00001429 }
1430
Martin Probstaf16c502017-01-04 13:36:43 +00001431 if (FormatTok->is(tok::semi))
1432 return;
1433
Manuel Klimek79e06082015-05-21 12:23:34 +00001434 parseChildBlock();
1435}
1436
Daniel Jasper3c883d12015-05-18 14:49:19 +00001437bool UnwrappedLineParser::tryToParseBracedList() {
Daniel Jasperb1f74a82013-07-09 09:06:29 +00001438 if (FormatTok->BlockKind == BK_Unknown)
Daniel Jasper3c883d12015-05-18 14:49:19 +00001439 calculateBraceTypes();
Daniel Jasperb1f74a82013-07-09 09:06:29 +00001440 assert(FormatTok->BlockKind != BK_Unknown);
1441 if (FormatTok->BlockKind == BK_Block)
Manuel Klimekab419912013-05-23 09:41:43 +00001442 return false;
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001443 nextToken();
Manuel Klimekab419912013-05-23 09:41:43 +00001444 parseBracedList();
1445 return true;
1446}
1447
Krasimir Georgievff747be2017-06-27 13:43:07 +00001448bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons,
1449 tok::TokenKind ClosingBraceKind) {
Daniel Jasper015ed022013-09-13 09:20:45 +00001450 bool HasError = false;
Manuel Klimek8e07a1b2013-01-10 11:52:21 +00001451
Manuel Klimeka3ff45e2013-04-10 09:52:05 +00001452 // FIXME: Once we have an expression parser in the UnwrappedLineParser,
1453 // replace this by using parseAssigmentExpression() inside.
Manuel Klimek8e07a1b2013-01-10 11:52:21 +00001454 do {
Manuel Klimek79e06082015-05-21 12:23:34 +00001455 if (Style.Language == FormatStyle::LK_JavaScript) {
Martin Probst409697e2016-05-29 14:41:07 +00001456 if (FormatTok->is(Keywords.kw_function) ||
1457 FormatTok->startsSequence(Keywords.kw_async, Keywords.kw_function)) {
Manuel Klimek79e06082015-05-21 12:23:34 +00001458 tryToParseJSFunction();
1459 continue;
Daniel Jasperbe520bd2015-05-31 08:51:54 +00001460 }
1461 if (FormatTok->is(TT_JsFatArrow)) {
Manuel Klimek79e06082015-05-21 12:23:34 +00001462 nextToken();
1463 // Fat arrows can be followed by simple expressions or by child blocks
1464 // in curly braces.
Daniel Jaspere6fcf7d2015-06-17 13:08:06 +00001465 if (FormatTok->is(tok::l_brace)) {
Manuel Klimek79e06082015-05-21 12:23:34 +00001466 parseChildBlock();
1467 continue;
1468 }
1469 }
Martin Probst8e3eba02017-02-07 16:33:13 +00001470 if (FormatTok->is(tok::l_brace)) {
1471 // Could be a method inside of a braced list `{a() { return 1; }}`.
1472 if (tryToParseBracedList())
1473 continue;
1474 parseChildBlock();
1475 }
Daniel Jasperc03e16a2014-05-08 09:25:39 +00001476 }
Krasimir Georgievff747be2017-06-27 13:43:07 +00001477 if (FormatTok->Tok.getKind() == ClosingBraceKind) {
1478 nextToken();
1479 return !HasError;
1480 }
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001481 switch (FormatTok->Tok.getKind()) {
Manuel Klimek516e0542013-09-04 13:25:30 +00001482 case tok::caret:
1483 nextToken();
1484 if (FormatTok->is(tok::l_brace)) {
1485 parseChildBlock();
1486 }
1487 break;
1488 case tok::l_square:
1489 tryToParseLambda();
1490 break;
Daniel Jaspera87af7a2015-06-30 11:32:22 +00001491 case tok::l_paren:
1492 parseParens();
Daniel Jasperf46dec82015-03-31 14:34:15 +00001493 // JavaScript can just have free standing methods and getters/setters in
1494 // object literals. Detect them by a "{" following ")".
1495 if (Style.Language == FormatStyle::LK_JavaScript) {
Daniel Jasperf46dec82015-03-31 14:34:15 +00001496 if (FormatTok->is(tok::l_brace))
1497 parseChildBlock();
1498 break;
1499 }
Daniel Jasperf46dec82015-03-31 14:34:15 +00001500 break;
Martin Probst8e3eba02017-02-07 16:33:13 +00001501 case tok::l_brace:
1502 // Assume there are no blocks inside a braced init list apart
1503 // from the ones we explicitly parse out (like lambdas).
1504 FormatTok->BlockKind = BK_BracedInit;
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001505 nextToken();
Martin Probst8e3eba02017-02-07 16:33:13 +00001506 parseBracedList();
1507 break;
Krasimir Georgievfa4dbb62017-08-03 13:43:45 +00001508 case tok::less:
1509 if (Style.Language == FormatStyle::LK_Proto) {
1510 nextToken();
1511 parseBracedList(/*ContinueOnSemicolons=*/false,
1512 /*ClosingBraceKind=*/tok::greater);
1513 } else {
1514 nextToken();
1515 }
1516 break;
Manuel Klimeka3ff45e2013-04-10 09:52:05 +00001517 case tok::semi:
Daniel Jasperb9a49902016-01-09 15:56:28 +00001518 // JavaScript (or more precisely TypeScript) can have semicolons in braced
1519 // lists (in so-called TypeMemberLists). Thus, the semicolon cannot be
1520 // used for error recovery if we have otherwise determined that this is
1521 // a braced list.
1522 if (Style.Language == FormatStyle::LK_JavaScript) {
1523 nextToken();
1524 break;
1525 }
Daniel Jasper015ed022013-09-13 09:20:45 +00001526 HasError = true;
1527 if (!ContinueOnSemicolons)
1528 return !HasError;
1529 nextToken();
1530 break;
Manuel Klimeka3ff45e2013-04-10 09:52:05 +00001531 case tok::comma:
1532 nextToken();
Manuel Klimeka3ff45e2013-04-10 09:52:05 +00001533 break;
Manuel Klimek8e07a1b2013-01-10 11:52:21 +00001534 default:
1535 nextToken();
1536 break;
1537 }
1538 } while (!eof());
Daniel Jasper015ed022013-09-13 09:20:45 +00001539 return false;
Manuel Klimek8e07a1b2013-01-10 11:52:21 +00001540}
1541
Daniel Jasperf7935112012-12-03 18:12:45 +00001542void UnwrappedLineParser::parseParens() {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001543 assert(FormatTok->Tok.is(tok::l_paren) && "'(' expected.");
Daniel Jasperf7935112012-12-03 18:12:45 +00001544 nextToken();
1545 do {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001546 switch (FormatTok->Tok.getKind()) {
Daniel Jasperf7935112012-12-03 18:12:45 +00001547 case tok::l_paren:
1548 parseParens();
Daniel Jasper5f1fa852015-01-04 20:40:51 +00001549 if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::l_brace))
1550 parseChildBlock();
Daniel Jasperf7935112012-12-03 18:12:45 +00001551 break;
1552 case tok::r_paren:
1553 nextToken();
1554 return;
Daniel Jasper393564f2013-05-31 14:56:29 +00001555 case tok::r_brace:
1556 // A "}" inside parenthesis is an error if there wasn't a matching "{".
1557 return;
Daniel Jasper9a8d48b2013-09-05 10:04:31 +00001558 case tok::l_square:
1559 tryToParseLambda();
1560 break;
Daniel Jasper5f1fa852015-01-04 20:40:51 +00001561 case tok::l_brace:
Daniel Jasperadba2aa2015-05-18 12:52:00 +00001562 if (!tryToParseBracedList())
Manuel Klimekf017dc02013-09-04 13:34:14 +00001563 parseChildBlock();
Manuel Klimek8e07a1b2013-01-10 11:52:21 +00001564 break;
Nico Weber372d8dc2013-02-10 20:35:35 +00001565 case tok::at:
1566 nextToken();
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001567 if (FormatTok->Tok.is(tok::l_brace)) {
1568 nextToken();
Nico Weber372d8dc2013-02-10 20:35:35 +00001569 parseBracedList();
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001570 }
Nico Weber372d8dc2013-02-10 20:35:35 +00001571 break;
Martin Probst1027fb82017-02-07 14:05:30 +00001572 case tok::kw_class:
1573 if (Style.Language == FormatStyle::LK_JavaScript)
1574 parseRecord(/*ParseAsExpr=*/true);
1575 else
1576 nextToken();
1577 break;
Daniel Jasper3f69ba12014-09-05 08:42:27 +00001578 case tok::identifier:
1579 if (Style.Language == FormatStyle::LK_JavaScript &&
Martin Probst409697e2016-05-29 14:41:07 +00001580 (FormatTok->is(Keywords.kw_function) ||
1581 FormatTok->startsSequence(Keywords.kw_async, Keywords.kw_function)))
Daniel Jasper3f69ba12014-09-05 08:42:27 +00001582 tryToParseJSFunction();
1583 else
1584 nextToken();
1585 break;
Daniel Jasperf7935112012-12-03 18:12:45 +00001586 default:
1587 nextToken();
1588 break;
1589 }
1590 } while (!eof());
1591}
1592
Manuel Klimek9f0a4e52017-09-19 09:59:30 +00001593void UnwrappedLineParser::parseSquare(bool LambdaIntroducer) {
1594 if (!LambdaIntroducer) {
1595 assert(FormatTok->Tok.is(tok::l_square) && "'[' expected.");
1596 if (tryToParseLambda())
1597 return;
1598 }
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001599 do {
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001600 switch (FormatTok->Tok.getKind()) {
1601 case tok::l_paren:
1602 parseParens();
1603 break;
1604 case tok::r_square:
1605 nextToken();
1606 return;
1607 case tok::r_brace:
1608 // A "}" inside parenthesis is an error if there wasn't a matching "{".
1609 return;
1610 case tok::l_square:
1611 parseSquare();
1612 break;
1613 case tok::l_brace: {
Daniel Jasperadba2aa2015-05-18 12:52:00 +00001614 if (!tryToParseBracedList())
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001615 parseChildBlock();
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001616 break;
1617 }
1618 case tok::at:
1619 nextToken();
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001620 if (FormatTok->Tok.is(tok::l_brace)) {
1621 nextToken();
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001622 parseBracedList();
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001623 }
Daniel Jasperb88b25f2013-12-23 07:29:06 +00001624 break;
1625 default:
1626 nextToken();
1627 break;
1628 }
1629 } while (!eof());
1630}
1631
Daniel Jasperf7935112012-12-03 18:12:45 +00001632void UnwrappedLineParser::parseIfThenElse() {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001633 assert(FormatTok->Tok.is(tok::kw_if) && "'if' expected");
Daniel Jasperf7935112012-12-03 18:12:45 +00001634 nextToken();
Daniel Jasper6a7d5a72017-06-19 07:40:49 +00001635 if (FormatTok->Tok.is(tok::kw_constexpr))
1636 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001637 if (FormatTok->Tok.is(tok::l_paren))
Manuel Klimekadededf2013-01-11 18:28:36 +00001638 parseParens();
Daniel Jasperf7935112012-12-03 18:12:45 +00001639 bool NeedsUnwrappedLine = false;
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001640 if (FormatTok->Tok.is(tok::l_brace)) {
Alexander Kornienko3a33f022013-12-12 09:49:52 +00001641 CompoundStatementIndenter Indenter(this, Style, Line->Level);
Nico Weber9096fc02013-06-26 00:30:14 +00001642 parseBlock(/*MustBeDeclaration=*/false);
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00001643 if (Style.BraceWrapping.BeforeElse)
Manuel Klimekd3ed59a2013-08-02 21:31:59 +00001644 addUnwrappedLine();
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00001645 else
Manuel Klimekd3ed59a2013-08-02 21:31:59 +00001646 NeedsUnwrappedLine = true;
Daniel Jasperf7935112012-12-03 18:12:45 +00001647 } else {
1648 addUnwrappedLine();
Manuel Klimek52b15152013-01-09 15:25:02 +00001649 ++Line->Level;
Manuel Klimek6b9eeba2013-01-07 14:56:16 +00001650 parseStructuralElement();
Manuel Klimek52b15152013-01-09 15:25:02 +00001651 --Line->Level;
Daniel Jasperf7935112012-12-03 18:12:45 +00001652 }
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001653 if (FormatTok->Tok.is(tok::kw_else)) {
Daniel Jasperf7935112012-12-03 18:12:45 +00001654 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001655 if (FormatTok->Tok.is(tok::l_brace)) {
Alexander Kornienko3a33f022013-12-12 09:49:52 +00001656 CompoundStatementIndenter Indenter(this, Style, Line->Level);
Nico Weber9096fc02013-06-26 00:30:14 +00001657 parseBlock(/*MustBeDeclaration=*/false);
Daniel Jasperf7935112012-12-03 18:12:45 +00001658 addUnwrappedLine();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001659 } else if (FormatTok->Tok.is(tok::kw_if)) {
Daniel Jasperf7935112012-12-03 18:12:45 +00001660 parseIfThenElse();
1661 } else {
1662 addUnwrappedLine();
Manuel Klimek52b15152013-01-09 15:25:02 +00001663 ++Line->Level;
Manuel Klimek6b9eeba2013-01-07 14:56:16 +00001664 parseStructuralElement();
Daniel Jasper451544a2016-05-19 06:30:48 +00001665 if (FormatTok->is(tok::eof))
1666 addUnwrappedLine();
Manuel Klimek52b15152013-01-09 15:25:02 +00001667 --Line->Level;
Daniel Jasperf7935112012-12-03 18:12:45 +00001668 }
1669 } else if (NeedsUnwrappedLine) {
1670 addUnwrappedLine();
1671 }
1672}
1673
Daniel Jasper04a71a42014-05-08 11:58:24 +00001674void UnwrappedLineParser::parseTryCatch() {
Nico Weberfac23712015-02-04 15:26:27 +00001675 assert(FormatTok->isOneOf(tok::kw_try, tok::kw___try) && "'try' expected");
Daniel Jasper04a71a42014-05-08 11:58:24 +00001676 nextToken();
1677 bool NeedsUnwrappedLine = false;
1678 if (FormatTok->is(tok::colon)) {
1679 // We are in a function try block, what comes is an initializer list.
1680 nextToken();
1681 while (FormatTok->is(tok::identifier)) {
1682 nextToken();
1683 if (FormatTok->is(tok::l_paren))
1684 parseParens();
Daniel Jasper04a71a42014-05-08 11:58:24 +00001685 if (FormatTok->is(tok::comma))
1686 nextToken();
1687 }
1688 }
Daniel Jaspere189d462015-01-14 10:48:41 +00001689 // Parse try with resource.
1690 if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::l_paren)) {
1691 parseParens();
1692 }
Daniel Jasper04a71a42014-05-08 11:58:24 +00001693 if (FormatTok->is(tok::l_brace)) {
1694 CompoundStatementIndenter Indenter(this, Style, Line->Level);
1695 parseBlock(/*MustBeDeclaration=*/false);
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00001696 if (Style.BraceWrapping.BeforeCatch) {
Daniel Jasper04a71a42014-05-08 11:58:24 +00001697 addUnwrappedLine();
1698 } else {
1699 NeedsUnwrappedLine = true;
1700 }
1701 } else if (!FormatTok->is(tok::kw_catch)) {
1702 // The C++ standard requires a compound-statement after a try.
1703 // If there's none, we try to assume there's a structuralElement
1704 // and try to continue.
Daniel Jasper04a71a42014-05-08 11:58:24 +00001705 addUnwrappedLine();
1706 ++Line->Level;
1707 parseStructuralElement();
1708 --Line->Level;
1709 }
Nico Weber33381f52015-02-07 01:57:32 +00001710 while (1) {
1711 if (FormatTok->is(tok::at))
1712 nextToken();
1713 if (!(FormatTok->isOneOf(tok::kw_catch, Keywords.kw___except,
1714 tok::kw___finally) ||
1715 ((Style.Language == FormatStyle::LK_Java ||
1716 Style.Language == FormatStyle::LK_JavaScript) &&
1717 FormatTok->is(Keywords.kw_finally)) ||
1718 (FormatTok->Tok.isObjCAtKeyword(tok::objc_catch) ||
1719 FormatTok->Tok.isObjCAtKeyword(tok::objc_finally))))
1720 break;
Daniel Jasper04a71a42014-05-08 11:58:24 +00001721 nextToken();
1722 while (FormatTok->isNot(tok::l_brace)) {
1723 if (FormatTok->is(tok::l_paren)) {
1724 parseParens();
1725 continue;
1726 }
Daniel Jasper2bd7a642015-01-19 10:50:51 +00001727 if (FormatTok->isOneOf(tok::semi, tok::r_brace, tok::eof))
Daniel Jasper04a71a42014-05-08 11:58:24 +00001728 return;
1729 nextToken();
1730 }
1731 NeedsUnwrappedLine = false;
1732 CompoundStatementIndenter Indenter(this, Style, Line->Level);
1733 parseBlock(/*MustBeDeclaration=*/false);
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00001734 if (Style.BraceWrapping.BeforeCatch)
Daniel Jasper04a71a42014-05-08 11:58:24 +00001735 addUnwrappedLine();
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00001736 else
Daniel Jasper04a71a42014-05-08 11:58:24 +00001737 NeedsUnwrappedLine = true;
Daniel Jasper04a71a42014-05-08 11:58:24 +00001738 }
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00001739 if (NeedsUnwrappedLine)
Daniel Jasper04a71a42014-05-08 11:58:24 +00001740 addUnwrappedLine();
Daniel Jasper04a71a42014-05-08 11:58:24 +00001741}
1742
Alexander Kornienko578fdd82012-12-06 18:03:27 +00001743void UnwrappedLineParser::parseNamespace() {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001744 assert(FormatTok->Tok.is(tok::kw_namespace) && "'namespace' expected");
Roman Kashitsyna043ced2014-08-11 12:18:01 +00001745
1746 const FormatToken &InitialToken = *FormatTok;
Alexander Kornienko578fdd82012-12-06 18:03:27 +00001747 nextToken();
Saleem Abdulrasool328085f2015-10-30 05:07:56 +00001748 while (FormatTok->isOneOf(tok::identifier, tok::coloncolon))
Alexander Kornienko578fdd82012-12-06 18:03:27 +00001749 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001750 if (FormatTok->Tok.is(tok::l_brace)) {
Roman Kashitsyna043ced2014-08-11 12:18:01 +00001751 if (ShouldBreakBeforeBrace(Style, InitialToken))
Manuel Klimeka8eb9142013-05-13 12:51:40 +00001752 addUnwrappedLine();
1753
Daniel Jasper65ee3472013-07-31 23:16:02 +00001754 bool AddLevel = Style.NamespaceIndentation == FormatStyle::NI_All ||
1755 (Style.NamespaceIndentation == FormatStyle::NI_Inner &&
1756 DeclarationScopeStack.size() > 1);
1757 parseBlock(/*MustBeDeclaration=*/true, AddLevel);
Manuel Klimek046b9302013-02-06 16:08:09 +00001758 // Munch the semicolon after a namespace. This is more common than one would
1759 // think. Puttin the semicolon into its own line is very ugly.
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001760 if (FormatTok->Tok.is(tok::semi))
Manuel Klimek046b9302013-02-06 16:08:09 +00001761 nextToken();
Alexander Kornienko578fdd82012-12-06 18:03:27 +00001762 addUnwrappedLine();
1763 }
1764 // FIXME: Add error handling.
1765}
1766
Daniel Jasper6acf5132015-03-12 14:44:29 +00001767void UnwrappedLineParser::parseNew() {
1768 assert(FormatTok->is(tok::kw_new) && "'new' expected");
1769 nextToken();
1770 if (Style.Language != FormatStyle::LK_Java)
1771 return;
1772
1773 // In Java, we can parse everything up to the parens, which aren't optional.
1774 do {
1775 // There should not be a ;, { or } before the new's open paren.
1776 if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::r_brace))
1777 return;
1778
1779 // Consume the parens.
1780 if (FormatTok->is(tok::l_paren)) {
1781 parseParens();
1782
1783 // If there is a class body of an anonymous class, consume that as child.
1784 if (FormatTok->is(tok::l_brace))
1785 parseChildBlock();
1786 return;
1787 }
1788 nextToken();
1789 } while (!eof());
1790}
1791
Alexander Kornienko37d6c942012-12-05 15:06:06 +00001792void UnwrappedLineParser::parseForOrWhileLoop() {
Daniel Jasper66cb8c52015-05-04 09:22:29 +00001793 assert(FormatTok->isOneOf(tok::kw_for, tok::kw_while, TT_ForEachMacro) &&
Daniel Jaspere1e43192014-04-01 12:55:11 +00001794 "'for', 'while' or foreach macro expected");
Alexander Kornienko37d6c942012-12-05 15:06:06 +00001795 nextToken();
Martin Probsta050f412017-05-18 21:19:29 +00001796 // JS' for await ( ...
Martin Probstbd49e322017-05-15 19:33:20 +00001797 if (Style.Language == FormatStyle::LK_JavaScript &&
Martin Probsta050f412017-05-18 21:19:29 +00001798 FormatTok->is(Keywords.kw_await))
Martin Probstbd49e322017-05-15 19:33:20 +00001799 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001800 if (FormatTok->Tok.is(tok::l_paren))
Manuel Klimek9fa8d552013-01-11 19:23:05 +00001801 parseParens();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001802 if (FormatTok->Tok.is(tok::l_brace)) {
Alexander Kornienko3a33f022013-12-12 09:49:52 +00001803 CompoundStatementIndenter Indenter(this, Style, Line->Level);
Nico Weber9096fc02013-06-26 00:30:14 +00001804 parseBlock(/*MustBeDeclaration=*/false);
Alexander Kornienko37d6c942012-12-05 15:06:06 +00001805 addUnwrappedLine();
1806 } else {
1807 addUnwrappedLine();
Manuel Klimek52b15152013-01-09 15:25:02 +00001808 ++Line->Level;
Manuel Klimek6b9eeba2013-01-07 14:56:16 +00001809 parseStructuralElement();
Manuel Klimek52b15152013-01-09 15:25:02 +00001810 --Line->Level;
Alexander Kornienko37d6c942012-12-05 15:06:06 +00001811 }
1812}
1813
Daniel Jasperf7935112012-12-03 18:12:45 +00001814void UnwrappedLineParser::parseDoWhile() {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001815 assert(FormatTok->Tok.is(tok::kw_do) && "'do' expected");
Daniel Jasperf7935112012-12-03 18:12:45 +00001816 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001817 if (FormatTok->Tok.is(tok::l_brace)) {
Alexander Kornienko3a33f022013-12-12 09:49:52 +00001818 CompoundStatementIndenter Indenter(this, Style, Line->Level);
Nico Weber9096fc02013-06-26 00:30:14 +00001819 parseBlock(/*MustBeDeclaration=*/false);
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00001820 if (Style.BraceWrapping.IndentBraces)
Alexander Kornienko3a33f022013-12-12 09:49:52 +00001821 addUnwrappedLine();
Daniel Jasperf7935112012-12-03 18:12:45 +00001822 } else {
1823 addUnwrappedLine();
Manuel Klimek52b15152013-01-09 15:25:02 +00001824 ++Line->Level;
Manuel Klimek6b9eeba2013-01-07 14:56:16 +00001825 parseStructuralElement();
Manuel Klimek52b15152013-01-09 15:25:02 +00001826 --Line->Level;
Daniel Jasperf7935112012-12-03 18:12:45 +00001827 }
1828
Alexander Kornienko0ea8e102012-12-04 15:40:36 +00001829 // FIXME: Add error handling.
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001830 if (!FormatTok->Tok.is(tok::kw_while)) {
Alexander Kornienko0ea8e102012-12-04 15:40:36 +00001831 addUnwrappedLine();
1832 return;
1833 }
1834
Daniel Jasperf7935112012-12-03 18:12:45 +00001835 nextToken();
Manuel Klimek6b9eeba2013-01-07 14:56:16 +00001836 parseStructuralElement();
Daniel Jasperf7935112012-12-03 18:12:45 +00001837}
1838
1839void UnwrappedLineParser::parseLabel() {
Daniel Jasperf7935112012-12-03 18:12:45 +00001840 nextToken();
Manuel Klimek52b15152013-01-09 15:25:02 +00001841 unsigned OldLineLevel = Line->Level;
Daniel Jaspera1275122013-03-20 10:23:53 +00001842 if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0))
Manuel Klimek52b15152013-01-09 15:25:02 +00001843 --Line->Level;
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001844 if (CommentsBeforeNextToken.empty() && FormatTok->Tok.is(tok::l_brace)) {
Alexander Kornienko3a33f022013-12-12 09:49:52 +00001845 CompoundStatementIndenter Indenter(this, Style, Line->Level);
Nico Weber9096fc02013-06-26 00:30:14 +00001846 parseBlock(/*MustBeDeclaration=*/false);
Manuel Klimekd3ed59a2013-08-02 21:31:59 +00001847 if (FormatTok->Tok.is(tok::kw_break)) {
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00001848 if (Style.BraceWrapping.AfterControlStatement)
Manuel Klimekd3ed59a2013-08-02 21:31:59 +00001849 addUnwrappedLine();
1850 parseStructuralElement();
1851 }
Alexander Kornienko3a33f022013-12-12 09:49:52 +00001852 addUnwrappedLine();
1853 } else {
Daniel Jasper1fe0d5c2015-05-06 15:19:47 +00001854 if (FormatTok->is(tok::semi))
1855 nextToken();
Alexander Kornienko3a33f022013-12-12 09:49:52 +00001856 addUnwrappedLine();
Daniel Jasperf7935112012-12-03 18:12:45 +00001857 }
Manuel Klimek52b15152013-01-09 15:25:02 +00001858 Line->Level = OldLineLevel;
Daniel Jasper2cce7b72016-04-06 16:41:39 +00001859 if (FormatTok->isNot(tok::l_brace)) {
Daniel Jasper40609472016-04-06 15:02:46 +00001860 parseStructuralElement();
Daniel Jasper2cce7b72016-04-06 16:41:39 +00001861 addUnwrappedLine();
1862 }
Daniel Jasperf7935112012-12-03 18:12:45 +00001863}
1864
1865void UnwrappedLineParser::parseCaseLabel() {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001866 assert(FormatTok->Tok.is(tok::kw_case) && "'case' expected");
Daniel Jasperf7935112012-12-03 18:12:45 +00001867 // FIXME: fix handling of complex expressions here.
1868 do {
1869 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001870 } while (!eof() && !FormatTok->Tok.is(tok::colon));
Daniel Jasperf7935112012-12-03 18:12:45 +00001871 parseLabel();
1872}
1873
1874void UnwrappedLineParser::parseSwitch() {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001875 assert(FormatTok->Tok.is(tok::kw_switch) && "'switch' expected");
Daniel Jasperf7935112012-12-03 18:12:45 +00001876 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001877 if (FormatTok->Tok.is(tok::l_paren))
Manuel Klimek9fa8d552013-01-11 19:23:05 +00001878 parseParens();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001879 if (FormatTok->Tok.is(tok::l_brace)) {
Alexander Kornienko3a33f022013-12-12 09:49:52 +00001880 CompoundStatementIndenter Indenter(this, Style, Line->Level);
Daniel Jasper65ee3472013-07-31 23:16:02 +00001881 parseBlock(/*MustBeDeclaration=*/false);
Daniel Jasperf7935112012-12-03 18:12:45 +00001882 addUnwrappedLine();
1883 } else {
1884 addUnwrappedLine();
Daniel Jasper516d7972013-07-25 11:31:57 +00001885 ++Line->Level;
Manuel Klimek6b9eeba2013-01-07 14:56:16 +00001886 parseStructuralElement();
Daniel Jasper516d7972013-07-25 11:31:57 +00001887 --Line->Level;
Daniel Jasperf7935112012-12-03 18:12:45 +00001888 }
1889}
1890
1891void UnwrappedLineParser::parseAccessSpecifier() {
1892 nextToken();
Daniel Jasper84c47a12013-11-23 17:53:41 +00001893 // Understand Qt's slots.
Daniel Jasper53395402015-04-07 15:04:40 +00001894 if (FormatTok->isOneOf(Keywords.kw_slots, Keywords.kw_qslots))
Daniel Jasper84c47a12013-11-23 17:53:41 +00001895 nextToken();
Alexander Kornienko2ca766f2012-12-10 16:34:48 +00001896 // Otherwise, we don't know what it is, and we'd better keep the next token.
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00001897 if (FormatTok->Tok.is(tok::colon))
Alexander Kornienko2ca766f2012-12-10 16:34:48 +00001898 nextToken();
Daniel Jasperf7935112012-12-03 18:12:45 +00001899 addUnwrappedLine();
1900}
1901
Daniel Jasper6f5a1932015-12-29 08:54:23 +00001902bool UnwrappedLineParser::parseEnum() {
Daniel Jasper6be0f552014-11-13 15:56:28 +00001903 // Won't be 'enum' for NS_ENUMs.
1904 if (FormatTok->Tok.is(tok::kw_enum))
Daniel Jasperccb68b42014-11-19 22:38:18 +00001905 nextToken();
Daniel Jasper6be0f552014-11-13 15:56:28 +00001906
Daniel Jasper6f5a1932015-12-29 08:54:23 +00001907 // In TypeScript, "enum" can also be used as property name, e.g. in interface
1908 // declarations. An "enum" keyword followed by a colon would be a syntax
1909 // error and thus assume it is just an identifier.
Daniel Jasper87379302016-02-03 05:33:44 +00001910 if (Style.Language == FormatStyle::LK_JavaScript &&
1911 FormatTok->isOneOf(tok::colon, tok::question))
Daniel Jasper6f5a1932015-12-29 08:54:23 +00001912 return false;
1913
Daniel Jasper2b41a822013-08-20 12:42:50 +00001914 // Eat up enum class ...
Daniel Jasperb05a81d2014-05-09 13:11:16 +00001915 if (FormatTok->Tok.is(tok::kw_class) || FormatTok->Tok.is(tok::kw_struct))
1916 nextToken();
Daniel Jasperb5a0b852015-06-19 08:17:32 +00001917
Daniel Jasper786a5502013-09-06 21:32:35 +00001918 while (FormatTok->Tok.getIdentifierInfo() ||
Daniel Jasperccb68b42014-11-19 22:38:18 +00001919 FormatTok->isOneOf(tok::colon, tok::coloncolon, tok::less,
1920 tok::greater, tok::comma, tok::question)) {
Manuel Klimek2cec0192013-01-21 19:17:52 +00001921 nextToken();
1922 // We can have macros or attributes in between 'enum' and the enum name.
Daniel Jasperccb68b42014-11-19 22:38:18 +00001923 if (FormatTok->is(tok::l_paren))
Alexander Kornienkob7076a22012-12-04 14:46:19 +00001924 parseParens();
Daniel Jasperb5a0b852015-06-19 08:17:32 +00001925 if (FormatTok->is(tok::identifier)) {
Manuel Klimek2cec0192013-01-21 19:17:52 +00001926 nextToken();
Daniel Jasperb5a0b852015-06-19 08:17:32 +00001927 // If there are two identifiers in a row, this is likely an elaborate
1928 // return type. In Java, this can be "implements", etc.
Daniel Jasper1dbc2102017-03-31 13:30:24 +00001929 if (Style.isCpp() && FormatTok->is(tok::identifier))
Daniel Jasper6f5a1932015-12-29 08:54:23 +00001930 return false;
Daniel Jasperb5a0b852015-06-19 08:17:32 +00001931 }
Manuel Klimek2cec0192013-01-21 19:17:52 +00001932 }
Daniel Jasper6be0f552014-11-13 15:56:28 +00001933
1934 // Just a declaration or something is wrong.
Daniel Jasperccb68b42014-11-19 22:38:18 +00001935 if (FormatTok->isNot(tok::l_brace))
Daniel Jasper6f5a1932015-12-29 08:54:23 +00001936 return true;
Daniel Jasper6be0f552014-11-13 15:56:28 +00001937 FormatTok->BlockKind = BK_Block;
1938
1939 if (Style.Language == FormatStyle::LK_Java) {
1940 // Java enums are different.
1941 parseJavaEnumBody();
Daniel Jasper6f5a1932015-12-29 08:54:23 +00001942 return true;
1943 }
1944 if (Style.Language == FormatStyle::LK_Proto) {
Daniel Jasperc6dd2732015-07-16 14:25:43 +00001945 parseBlock(/*MustBeDeclaration=*/true);
Daniel Jasper6f5a1932015-12-29 08:54:23 +00001946 return true;
Manuel Klimek2cec0192013-01-21 19:17:52 +00001947 }
Daniel Jasper6be0f552014-11-13 15:56:28 +00001948
1949 // Parse enum body.
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001950 nextToken();
Daniel Jasper6be0f552014-11-13 15:56:28 +00001951 bool HasError = !parseBracedList(/*ContinueOnSemicolons=*/true);
1952 if (HasError) {
1953 if (FormatTok->is(tok::semi))
1954 nextToken();
1955 addUnwrappedLine();
1956 }
Daniel Jasper6f5a1932015-12-29 08:54:23 +00001957 return true;
Daniel Jasper6be0f552014-11-13 15:56:28 +00001958
Daniel Jasper90cf3802015-06-17 09:44:02 +00001959 // There is no addUnwrappedLine() here so that we fall through to parsing a
1960 // structural element afterwards. Thus, in "enum A {} n, m;",
Manuel Klimek2cec0192013-01-21 19:17:52 +00001961 // "} n, m;" will end up in one unwrapped line.
Daniel Jasper6be0f552014-11-13 15:56:28 +00001962}
1963
1964void UnwrappedLineParser::parseJavaEnumBody() {
1965 // Determine whether the enum is simple, i.e. does not have a semicolon or
1966 // constants with class bodies. Simple enums can be formatted like braced
1967 // lists, contracted to a single line, etc.
1968 unsigned StoredPosition = Tokens->getPosition();
1969 bool IsSimple = true;
1970 FormatToken *Tok = Tokens->getNextToken();
1971 while (Tok) {
1972 if (Tok->is(tok::r_brace))
1973 break;
1974 if (Tok->isOneOf(tok::l_brace, tok::semi)) {
1975 IsSimple = false;
1976 break;
1977 }
1978 // FIXME: This will also mark enums with braces in the arguments to enum
1979 // constants as "not simple". This is probably fine in practice, though.
1980 Tok = Tokens->getNextToken();
1981 }
1982 FormatTok = Tokens->setPosition(StoredPosition);
1983
1984 if (IsSimple) {
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00001985 nextToken();
Daniel Jasper6be0f552014-11-13 15:56:28 +00001986 parseBracedList();
Daniel Jasperdf2ff002014-11-02 22:31:39 +00001987 addUnwrappedLine();
Daniel Jasper6be0f552014-11-13 15:56:28 +00001988 return;
1989 }
1990
1991 // Parse the body of a more complex enum.
1992 // First add a line for everything up to the "{".
1993 nextToken();
1994 addUnwrappedLine();
1995 ++Line->Level;
1996
1997 // Parse the enum constants.
1998 while (FormatTok) {
1999 if (FormatTok->is(tok::l_brace)) {
2000 // Parse the constant's class body.
2001 parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/true,
2002 /*MunchSemi=*/false);
2003 } else if (FormatTok->is(tok::l_paren)) {
2004 parseParens();
2005 } else if (FormatTok->is(tok::comma)) {
2006 nextToken();
2007 addUnwrappedLine();
2008 } else if (FormatTok->is(tok::semi)) {
2009 nextToken();
2010 addUnwrappedLine();
2011 break;
2012 } else if (FormatTok->is(tok::r_brace)) {
2013 addUnwrappedLine();
2014 break;
2015 } else {
2016 nextToken();
2017 }
2018 }
2019
2020 // Parse the class body after the enum's ";" if any.
2021 parseLevel(/*HasOpeningBrace=*/true);
2022 nextToken();
2023 --Line->Level;
2024 addUnwrappedLine();
Daniel Jasperf7935112012-12-03 18:12:45 +00002025}
2026
Martin Probst1027fb82017-02-07 14:05:30 +00002027void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
Roman Kashitsyna043ced2014-08-11 12:18:01 +00002028 const FormatToken &InitialToken = *FormatTok;
Manuel Klimek28cacc72013-01-07 18:10:23 +00002029 nextToken();
Daniel Jasper04785d02015-05-06 14:03:02 +00002030
Daniel Jasper04785d02015-05-06 14:03:02 +00002031 // The actual identifier can be a nested name specifier, and in macros
2032 // it is often token-pasted.
2033 while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash,
2034 tok::kw___attribute, tok::kw___declspec,
2035 tok::kw_alignas) ||
2036 ((Style.Language == FormatStyle::LK_Java ||
2037 Style.Language == FormatStyle::LK_JavaScript) &&
2038 FormatTok->isOneOf(tok::period, tok::comma))) {
Martin Probstcb870c52017-08-01 15:46:10 +00002039 if (Style.Language == FormatStyle::LK_JavaScript &&
2040 FormatTok->isOneOf(Keywords.kw_extends, Keywords.kw_implements)) {
2041 // JavaScript/TypeScript supports inline object types in
2042 // extends/implements positions:
2043 // class Foo implements {bar: number} { }
2044 nextToken();
2045 if (FormatTok->is(tok::l_brace)) {
2046 tryToParseBracedList();
2047 continue;
2048 }
2049 }
Daniel Jasper04785d02015-05-06 14:03:02 +00002050 bool IsNonMacroIdentifier =
2051 FormatTok->is(tok::identifier) &&
2052 FormatTok->TokenText != FormatTok->TokenText.upper();
Manuel Klimeke01bab52013-01-15 13:38:33 +00002053 nextToken();
2054 // We can have macros or attributes in between 'class' and the class name.
Daniel Jasper04785d02015-05-06 14:03:02 +00002055 if (!IsNonMacroIdentifier && FormatTok->Tok.is(tok::l_paren))
Manuel Klimeke01bab52013-01-15 13:38:33 +00002056 parseParens();
Daniel Jasper04785d02015-05-06 14:03:02 +00002057 }
Manuel Klimeke01bab52013-01-15 13:38:33 +00002058
Daniel Jasper04785d02015-05-06 14:03:02 +00002059 // Note that parsing away template declarations here leads to incorrectly
2060 // accepting function declarations as record declarations.
2061 // In general, we cannot solve this problem. Consider:
2062 // class A<int> B() {}
2063 // which can be a function definition or a class definition when B() is a
2064 // macro. If we find enough real-world cases where this is a problem, we
2065 // can parse for the 'template' keyword in the beginning of the statement,
2066 // and thus rule out the record production in case there is no template
2067 // (this would still leave us with an ambiguity between template function
2068 // and class declarations).
Daniel Jasperadba2aa2015-05-18 12:52:00 +00002069 if (FormatTok->isOneOf(tok::colon, tok::less)) {
2070 while (!eof()) {
Daniel Jasper3c883d12015-05-18 14:49:19 +00002071 if (FormatTok->is(tok::l_brace)) {
2072 calculateBraceTypes(/*ExpectClassBody=*/true);
2073 if (!tryToParseBracedList())
2074 break;
2075 }
Daniel Jasper04785d02015-05-06 14:03:02 +00002076 if (FormatTok->Tok.is(tok::semi))
2077 return;
2078 nextToken();
Manuel Klimeke01bab52013-01-15 13:38:33 +00002079 }
2080 }
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002081 if (FormatTok->Tok.is(tok::l_brace)) {
Martin Probst1027fb82017-02-07 14:05:30 +00002082 if (ParseAsExpr) {
2083 parseChildBlock();
2084 } else {
2085 if (ShouldBreakBeforeBrace(Style, InitialToken))
2086 addUnwrappedLine();
Manuel Klimeka8eb9142013-05-13 12:51:40 +00002087
Martin Probst1027fb82017-02-07 14:05:30 +00002088 parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/true,
2089 /*MunchSemi=*/false);
2090 }
Manuel Klimeka8eb9142013-05-13 12:51:40 +00002091 }
Daniel Jasper90cf3802015-06-17 09:44:02 +00002092 // There is no addUnwrappedLine() here so that we fall through to parsing a
2093 // structural element afterwards. Thus, in "class A {} n, m;",
2094 // "} n, m;" will end up in one unwrapped line.
Manuel Klimek28cacc72013-01-07 18:10:23 +00002095}
2096
Nico Weber8696a8d2013-01-09 21:15:03 +00002097void UnwrappedLineParser::parseObjCProtocolList() {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002098 assert(FormatTok->Tok.is(tok::less) && "'<' expected.");
Nico Weber8696a8d2013-01-09 21:15:03 +00002099 do
2100 nextToken();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002101 while (!eof() && FormatTok->Tok.isNot(tok::greater));
Nico Weber8696a8d2013-01-09 21:15:03 +00002102 nextToken(); // Skip '>'.
2103}
2104
2105void UnwrappedLineParser::parseObjCUntilAtEnd() {
2106 do {
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002107 if (FormatTok->Tok.isObjCAtKeyword(tok::objc_end)) {
Nico Weber8696a8d2013-01-09 21:15:03 +00002108 nextToken();
2109 addUnwrappedLine();
2110 break;
2111 }
Daniel Jaspera15da302013-08-28 08:04:23 +00002112 if (FormatTok->is(tok::l_brace)) {
2113 parseBlock(/*MustBeDeclaration=*/false);
2114 // In ObjC interfaces, nothing should be following the "}".
2115 addUnwrappedLine();
Benjamin Kramere21cb742014-01-08 15:59:42 +00002116 } else if (FormatTok->is(tok::r_brace)) {
2117 // Ignore stray "}". parseStructuralElement doesn't consume them.
2118 nextToken();
2119 addUnwrappedLine();
Daniel Jaspera15da302013-08-28 08:04:23 +00002120 } else {
2121 parseStructuralElement();
2122 }
Nico Weber8696a8d2013-01-09 21:15:03 +00002123 } while (!eof());
2124}
2125
Nico Weber2ce0ac52013-01-09 23:25:37 +00002126void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
Nico Weberc068ff72018-01-23 17:10:25 +00002127 assert(FormatTok->Tok.getObjCKeywordID() == tok::objc_interface ||
2128 FormatTok->Tok.getObjCKeywordID() == tok::objc_implementation);
Nico Weber7eecf4b2013-01-09 20:25:35 +00002129 nextToken();
Daniel Jasperd1ae3582013-03-20 12:37:50 +00002130 nextToken(); // interface name
Nico Weber7eecf4b2013-01-09 20:25:35 +00002131
2132 // @interface can be followed by either a base class, or a category.
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002133 if (FormatTok->Tok.is(tok::colon)) {
Nico Weber7eecf4b2013-01-09 20:25:35 +00002134 nextToken();
Daniel Jasperd1ae3582013-03-20 12:37:50 +00002135 nextToken(); // base class name
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002136 } else if (FormatTok->Tok.is(tok::l_paren))
Nico Weber7eecf4b2013-01-09 20:25:35 +00002137 // Skip category, if present.
2138 parseParens();
2139
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002140 if (FormatTok->Tok.is(tok::less))
Nico Weber8696a8d2013-01-09 21:15:03 +00002141 parseObjCProtocolList();
Nico Weber7eecf4b2013-01-09 20:25:35 +00002142
Dinesh Dwivediea3aca82014-05-02 17:01:46 +00002143 if (FormatTok->Tok.is(tok::l_brace)) {
Daniel Jasperc1bc38e2015-09-29 14:57:55 +00002144 if (Style.BraceWrapping.AfterObjCDeclaration)
Dinesh Dwivediea3aca82014-05-02 17:01:46 +00002145 addUnwrappedLine();
Nico Weber9096fc02013-06-26 00:30:14 +00002146 parseBlock(/*MustBeDeclaration=*/true);
Dinesh Dwivediea3aca82014-05-02 17:01:46 +00002147 }
Nico Weber7eecf4b2013-01-09 20:25:35 +00002148
2149 // With instance variables, this puts '}' on its own line. Without instance
2150 // variables, this ends the @interface line.
2151 addUnwrappedLine();
2152
Nico Weber8696a8d2013-01-09 21:15:03 +00002153 parseObjCUntilAtEnd();
2154}
Nico Weber7eecf4b2013-01-09 20:25:35 +00002155
Nico Weberc068ff72018-01-23 17:10:25 +00002156// Returns true for the declaration/definition form of @protocol,
2157// false for the expression form.
2158bool UnwrappedLineParser::parseObjCProtocol() {
2159 assert(FormatTok->Tok.getObjCKeywordID() == tok::objc_protocol);
Nico Weber8696a8d2013-01-09 21:15:03 +00002160 nextToken();
Nico Weberc068ff72018-01-23 17:10:25 +00002161
2162 if (FormatTok->is(tok::l_paren))
2163 // The expression form of @protocol, e.g. "Protocol* p = @protocol(foo);".
2164 return false;
2165
2166 // The definition/declaration form,
2167 // @protocol Foo
2168 // - (int)someMethod;
2169 // @end
2170
Daniel Jasperd1ae3582013-03-20 12:37:50 +00002171 nextToken(); // protocol name
Nico Weber8696a8d2013-01-09 21:15:03 +00002172
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002173 if (FormatTok->Tok.is(tok::less))
Nico Weber8696a8d2013-01-09 21:15:03 +00002174 parseObjCProtocolList();
2175
2176 // Check for protocol declaration.
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002177 if (FormatTok->Tok.is(tok::semi)) {
Nico Weber8696a8d2013-01-09 21:15:03 +00002178 nextToken();
Nico Weberc068ff72018-01-23 17:10:25 +00002179 addUnwrappedLine();
2180 return true;
Nico Weber8696a8d2013-01-09 21:15:03 +00002181 }
2182
2183 addUnwrappedLine();
2184 parseObjCUntilAtEnd();
Nico Weberc068ff72018-01-23 17:10:25 +00002185 return true;
Nico Weber7eecf4b2013-01-09 20:25:35 +00002186}
2187
Daniel Jasperfca735c2015-02-19 16:14:18 +00002188void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
Martin Probst053f1aa2016-04-19 14:55:37 +00002189 bool IsImport = FormatTok->is(Keywords.kw_import);
2190 assert(IsImport || FormatTok->is(tok::kw_export));
Daniel Jasper354aa512015-02-19 16:07:32 +00002191 nextToken();
Daniel Jasperfca735c2015-02-19 16:14:18 +00002192
Daniel Jasperec05fc72015-05-11 09:14:50 +00002193 // Consume the "default" in "export default class/function".
Daniel Jasper668c7bb2015-05-11 09:03:10 +00002194 if (FormatTok->is(tok::kw_default))
2195 nextToken();
Daniel Jasperec05fc72015-05-11 09:14:50 +00002196
Martin Probst5f8445b2016-04-24 22:05:09 +00002197 // Consume "async function", "function" and "default function", so that these
2198 // get parsed as free-standing JS functions, i.e. do not require a trailing
2199 // semicolon.
2200 if (FormatTok->is(Keywords.kw_async))
2201 nextToken();
Daniel Jasper668c7bb2015-05-11 09:03:10 +00002202 if (FormatTok->is(Keywords.kw_function)) {
2203 nextToken();
2204 return;
2205 }
2206
Martin Probst053f1aa2016-04-19 14:55:37 +00002207 // For imports, `export *`, `export {...}`, consume the rest of the line up
2208 // to the terminating `;`. For everything else, just return and continue
2209 // parsing the structural element, i.e. the declaration or expression for
2210 // `export default`.
2211 if (!IsImport && !FormatTok->isOneOf(tok::l_brace, tok::star) &&
2212 !FormatTok->isStringLiteral())
2213 return;
Daniel Jasperfca735c2015-02-19 16:14:18 +00002214
Martin Probstd40bca42017-01-09 08:56:36 +00002215 while (!eof()) {
2216 if (FormatTok->is(tok::semi))
2217 return;
Krasimir Georgiev112c2e92017-11-09 13:22:03 +00002218 if (Line->Tokens.empty()) {
Martin Probstd40bca42017-01-09 08:56:36 +00002219 // Common issue: Automatic Semicolon Insertion wrapped the line, so the
2220 // import statement should terminate.
2221 return;
2222 }
Daniel Jasperefc1a832016-01-07 08:53:35 +00002223 if (FormatTok->is(tok::l_brace)) {
2224 FormatTok->BlockKind = BK_Block;
Krasimir Georgiev26b144c2017-07-03 15:05:14 +00002225 nextToken();
Daniel Jasperefc1a832016-01-07 08:53:35 +00002226 parseBracedList();
2227 } else {
2228 nextToken();
2229 }
Daniel Jasper354aa512015-02-19 16:07:32 +00002230 }
2231}
2232
Daniel Jasper3b203a62013-09-05 16:05:56 +00002233LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line,
2234 StringRef Prefix = "") {
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00002235 llvm::dbgs() << Prefix << "Line(" << Line.Level
2236 << ", FSC=" << Line.FirstStartColumn << ")"
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +00002237 << (Line.InPPDirective ? " MACRO" : "") << ": ";
2238 for (std::list<UnwrappedLineNode>::const_iterator I = Line.Tokens.begin(),
2239 E = Line.Tokens.end();
2240 I != E; ++I) {
Krasimir Georgiev91834222017-01-25 13:58:58 +00002241 llvm::dbgs() << I->Tok->Tok.getName() << "["
Manuel Klimek89628f62017-09-20 09:51:03 +00002242 << "T=" << I->Tok->Type << ", OC=" << I->Tok->OriginalColumn
2243 << "] ";
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +00002244 }
2245 for (std::list<UnwrappedLineNode>::const_iterator I = Line.Tokens.begin(),
2246 E = Line.Tokens.end();
2247 I != E; ++I) {
2248 const UnwrappedLineNode &Node = *I;
2249 for (SmallVectorImpl<UnwrappedLine>::const_iterator
2250 I = Node.Children.begin(),
2251 E = Node.Children.end();
2252 I != E; ++I) {
2253 printDebugInfo(*I, "\nChild: ");
2254 }
2255 }
2256 llvm::dbgs() << "\n";
2257}
2258
Daniel Jasperf7935112012-12-03 18:12:45 +00002259void UnwrappedLineParser::addUnwrappedLine() {
Daniel Jasperdaffc0d2013-01-16 09:10:19 +00002260 if (Line->Tokens.empty())
Daniel Jasper7c85fde2013-01-08 14:56:18 +00002261 return;
Manuel Klimekab3dc002013-01-16 12:31:12 +00002262 DEBUG({
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +00002263 if (CurrentLines == &Lines)
2264 printDebugInfo(*Line);
Manuel Klimekab3dc002013-01-16 12:31:12 +00002265 });
Benjamin Kramerc7551a42015-05-31 11:18:05 +00002266 CurrentLines->push_back(std::move(*Line));
Daniel Jasperdaffc0d2013-01-16 09:10:19 +00002267 Line->Tokens.clear();
Krasimir Georgiev85c37042017-03-01 16:38:08 +00002268 Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex;
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00002269 Line->FirstStartColumn = 0;
Manuel Klimekd3b92fa2013-01-18 14:04:34 +00002270 if (CurrentLines == &Lines && !PreprocessorDirectives.empty()) {
Benjamin Kramerc7551a42015-05-31 11:18:05 +00002271 CurrentLines->append(
2272 std::make_move_iterator(PreprocessorDirectives.begin()),
2273 std::make_move_iterator(PreprocessorDirectives.end()));
Manuel Klimekd3b92fa2013-01-18 14:04:34 +00002274 PreprocessorDirectives.clear();
2275 }
Manuel Klimeke411aa82017-09-20 09:29:37 +00002276 // Disconnect the current token from the last token on the previous line.
2277 FormatTok->Previous = nullptr;
Daniel Jasperf7935112012-12-03 18:12:45 +00002278}
2279
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002280bool UnwrappedLineParser::eof() const { return FormatTok->Tok.is(tok::eof); }
Daniel Jasperf7935112012-12-03 18:12:45 +00002281
Daniel Jasperb05a81d2014-05-09 13:11:16 +00002282bool UnwrappedLineParser::isOnNewLine(const FormatToken &FormatTok) {
Manuel Klimek1fcbe672014-04-11 12:27:47 +00002283 return (Line->InPPDirective || FormatTok.HasUnescapedNewline) &&
2284 FormatTok.NewlinesBefore > 0;
2285}
2286
Krasimir Georgiev91834222017-01-25 13:58:58 +00002287// Checks if \p FormatTok is a line comment that continues the line comment
2288// section on \p Line.
Krasimir Georgievea222a72017-05-22 10:07:56 +00002289static bool continuesLineCommentSection(const FormatToken &FormatTok,
2290 const UnwrappedLine &Line,
2291 llvm::Regex &CommentPragmasRegex) {
Krasimir Georgiev91834222017-01-25 13:58:58 +00002292 if (Line.Tokens.empty())
2293 return false;
Krasimir Georgiev84321612017-01-30 19:18:55 +00002294
Krasimir Georgiev00c5c722017-02-02 15:32:19 +00002295 StringRef IndentContent = FormatTok.TokenText;
2296 if (FormatTok.TokenText.startswith("//") ||
2297 FormatTok.TokenText.startswith("/*"))
2298 IndentContent = FormatTok.TokenText.substr(2);
2299 if (CommentPragmasRegex.match(IndentContent))
2300 return false;
2301
Krasimir Georgiev91834222017-01-25 13:58:58 +00002302 // If Line starts with a line comment, then FormatTok continues the comment
Krasimir Georgiev84321612017-01-30 19:18:55 +00002303 // section if its original column is greater or equal to the original start
Krasimir Georgiev91834222017-01-25 13:58:58 +00002304 // column of the line.
2305 //
Krasimir Georgiev84321612017-01-30 19:18:55 +00002306 // Define the min column token of a line as follows: if a line ends in '{' or
2307 // contains a '{' followed by a line comment, then the min column token is
2308 // that '{'. Otherwise, the min column token of the line is the first token of
2309 // the line.
2310 //
2311 // If Line starts with a token other than a line comment, then FormatTok
2312 // continues the comment section if its original column is greater than the
2313 // original start column of the min column token of the line.
Krasimir Georgiev91834222017-01-25 13:58:58 +00002314 //
2315 // For example, the second line comment continues the first in these cases:
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002316 //
Krasimir Georgiev91834222017-01-25 13:58:58 +00002317 // // first line
2318 // // second line
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002319 //
Krasimir Georgiev91834222017-01-25 13:58:58 +00002320 // and:
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002321 //
Krasimir Georgiev91834222017-01-25 13:58:58 +00002322 // // first line
2323 // // second line
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002324 //
Krasimir Georgiev91834222017-01-25 13:58:58 +00002325 // and:
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002326 //
Krasimir Georgiev91834222017-01-25 13:58:58 +00002327 // int i; // first line
2328 // // second line
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002329 //
Krasimir Georgiev84321612017-01-30 19:18:55 +00002330 // and:
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002331 //
Krasimir Georgiev84321612017-01-30 19:18:55 +00002332 // do { // first line
2333 // // second line
2334 // int i;
2335 // } while (true);
Krasimir Georgiev91834222017-01-25 13:58:58 +00002336 //
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002337 // and:
2338 //
2339 // enum {
2340 // a, // first line
2341 // // second line
2342 // b
2343 // };
2344 //
Krasimir Georgiev91834222017-01-25 13:58:58 +00002345 // The second line comment doesn't continue the first in these cases:
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002346 //
Krasimir Georgiev91834222017-01-25 13:58:58 +00002347 // // first line
2348 // // second line
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002349 //
Krasimir Georgiev91834222017-01-25 13:58:58 +00002350 // and:
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002351 //
Krasimir Georgiev91834222017-01-25 13:58:58 +00002352 // int i; // first line
2353 // // second line
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002354 //
Krasimir Georgiev84321612017-01-30 19:18:55 +00002355 // and:
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002356 //
Krasimir Georgiev84321612017-01-30 19:18:55 +00002357 // do { // first line
2358 // // second line
2359 // int i;
2360 // } while (true);
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002361 //
2362 // and:
2363 //
2364 // enum {
2365 // a, // first line
2366 // // second line
2367 // };
Krasimir Georgiev84321612017-01-30 19:18:55 +00002368 const FormatToken *MinColumnToken = Line.Tokens.front().Tok;
2369
2370 // Scan for '{//'. If found, use the column of '{' as a min column for line
2371 // comment section continuation.
2372 const FormatToken *PreviousToken = nullptr;
Krasimir Georgievd86c25d2017-03-10 13:09:29 +00002373 for (const UnwrappedLineNode &Node : Line.Tokens) {
Krasimir Georgiev84321612017-01-30 19:18:55 +00002374 if (PreviousToken && PreviousToken->is(tok::l_brace) &&
2375 isLineComment(*Node.Tok)) {
2376 MinColumnToken = PreviousToken;
2377 break;
2378 }
2379 PreviousToken = Node.Tok;
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002380
2381 // Grab the last newline preceding a token in this unwrapped line.
2382 if (Node.Tok->NewlinesBefore > 0) {
2383 MinColumnToken = Node.Tok;
2384 }
Krasimir Georgiev84321612017-01-30 19:18:55 +00002385 }
2386 if (PreviousToken && PreviousToken->is(tok::l_brace)) {
2387 MinColumnToken = PreviousToken;
2388 }
2389
Krasimir Georgievea222a72017-05-22 10:07:56 +00002390 return continuesLineComment(FormatTok, /*Previous=*/Line.Tokens.back().Tok,
2391 MinColumnToken);
Krasimir Georgiev91834222017-01-25 13:58:58 +00002392}
2393
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002394void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) {
2395 bool JustComments = Line->Tokens.empty();
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002396 for (SmallVectorImpl<FormatToken *>::const_iterator
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002397 I = CommentsBeforeNextToken.begin(),
2398 E = CommentsBeforeNextToken.end();
2399 I != E; ++I) {
Krasimir Georgiev91834222017-01-25 13:58:58 +00002400 // Line comments that belong to the same line comment section are put on the
2401 // same line since later we might want to reflow content between them.
Krasimir Georgiev753625b2017-01-31 13:32:38 +00002402 // Additional fine-grained breaking of line comment sections is controlled
2403 // by the class BreakableLineCommentSection in case it is desirable to keep
2404 // several line comment sections in the same unwrapped line.
2405 //
2406 // FIXME: Consider putting separate line comment sections as children to the
2407 // unwrapped line instead.
Krasimir Georgiev00c5c722017-02-02 15:32:19 +00002408 (*I)->ContinuesLineCommentSection =
Krasimir Georgievea222a72017-05-22 10:07:56 +00002409 continuesLineCommentSection(**I, *Line, CommentPragmasRegex);
Krasimir Georgievb6ccd382017-02-02 14:36:50 +00002410 if (isOnNewLine(**I) && JustComments && !(*I)->ContinuesLineCommentSection)
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002411 addUnwrappedLine();
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002412 pushToken(*I);
2413 }
Daniel Jaspere60cba12015-05-13 11:35:53 +00002414 if (NewlineBeforeNext && JustComments)
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002415 addUnwrappedLine();
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002416 CommentsBeforeNextToken.clear();
2417}
2418
Krasimir Georgiev3e051052017-07-24 14:51:59 +00002419void UnwrappedLineParser::nextToken(int LevelDifference) {
Daniel Jasperf7935112012-12-03 18:12:45 +00002420 if (eof())
2421 return;
Manuel Klimek1fcbe672014-04-11 12:27:47 +00002422 flushComments(isOnNewLine(*FormatTok));
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002423 pushToken(FormatTok);
Manuel Klimek89628f62017-09-20 09:51:03 +00002424 FormatToken *Previous = FormatTok;
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +00002425 if (Style.Language != FormatStyle::LK_JavaScript)
Krasimir Georgiev3e051052017-07-24 14:51:59 +00002426 readToken(LevelDifference);
Daniel Jasper1dcbbcfc2016-03-14 19:21:36 +00002427 else
2428 readTokenWithJavaScriptASI();
Manuel Klimeke411aa82017-09-20 09:29:37 +00002429 FormatTok->Previous = Previous;
Daniel Jasperb9a49902016-01-09 15:56:28 +00002430}
2431
Krasimir Georgievf62f9582017-02-08 10:30:44 +00002432void UnwrappedLineParser::distributeComments(
2433 const SmallVectorImpl<FormatToken *> &Comments,
2434 const FormatToken *NextTok) {
2435 // Whether or not a line comment token continues a line is controlled by
Krasimir Georgievea222a72017-05-22 10:07:56 +00002436 // the method continuesLineCommentSection, with the following caveat:
Krasimir Georgievf62f9582017-02-08 10:30:44 +00002437 //
2438 // Define a trail of Comments to be a nonempty proper postfix of Comments such
2439 // that each comment line from the trail is aligned with the next token, if
2440 // the next token exists. If a trail exists, the beginning of the maximal
2441 // trail is marked as a start of a new comment section.
2442 //
2443 // For example in this code:
2444 //
2445 // int a; // line about a
2446 // // line 1 about b
2447 // // line 2 about b
2448 // int b;
2449 //
2450 // the two lines about b form a maximal trail, so there are two sections, the
2451 // first one consisting of the single comment "// line about a" and the
2452 // second one consisting of the next two comments.
2453 if (Comments.empty())
2454 return;
2455 bool ShouldPushCommentsInCurrentLine = true;
2456 bool HasTrailAlignedWithNextToken = false;
2457 unsigned StartOfTrailAlignedWithNextToken = 0;
2458 if (NextTok) {
2459 // We are skipping the first element intentionally.
2460 for (unsigned i = Comments.size() - 1; i > 0; --i) {
2461 if (Comments[i]->OriginalColumn == NextTok->OriginalColumn) {
2462 HasTrailAlignedWithNextToken = true;
2463 StartOfTrailAlignedWithNextToken = i;
2464 }
2465 }
2466 }
2467 for (unsigned i = 0, e = Comments.size(); i < e; ++i) {
2468 FormatToken *FormatTok = Comments[i];
Manuel Klimek89628f62017-09-20 09:51:03 +00002469 if (HasTrailAlignedWithNextToken && i == StartOfTrailAlignedWithNextToken) {
Krasimir Georgievf62f9582017-02-08 10:30:44 +00002470 FormatTok->ContinuesLineCommentSection = false;
2471 } else {
2472 FormatTok->ContinuesLineCommentSection =
Krasimir Georgievea222a72017-05-22 10:07:56 +00002473 continuesLineCommentSection(*FormatTok, *Line, CommentPragmasRegex);
Krasimir Georgievf62f9582017-02-08 10:30:44 +00002474 }
2475 if (!FormatTok->ContinuesLineCommentSection &&
2476 (isOnNewLine(*FormatTok) || FormatTok->IsFirst)) {
2477 ShouldPushCommentsInCurrentLine = false;
2478 }
2479 if (ShouldPushCommentsInCurrentLine) {
2480 pushToken(FormatTok);
2481 } else {
2482 CommentsBeforeNextToken.push_back(FormatTok);
2483 }
2484 }
2485}
2486
Krasimir Georgiev3e051052017-07-24 14:51:59 +00002487void UnwrappedLineParser::readToken(int LevelDifference) {
Krasimir Georgievf62f9582017-02-08 10:30:44 +00002488 SmallVector<FormatToken *, 1> Comments;
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002489 do {
2490 FormatTok = Tokens->getNextToken();
Alexander Kornienkoc2ee9cf2014-03-13 13:59:48 +00002491 assert(FormatTok);
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002492 while (!Line->InPPDirective && FormatTok->Tok.is(tok::hash) &&
2493 (FormatTok->HasUnescapedNewline || FormatTok->IsFirst)) {
Krasimir Georgievf62f9582017-02-08 10:30:44 +00002494 distributeComments(Comments, FormatTok);
2495 Comments.clear();
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002496 // If there is an unfinished unwrapped line, we flush the preprocessor
2497 // directives only after that unwrapped line was finished later.
Daniel Jasper29d39d52015-02-08 09:34:49 +00002498 bool SwitchToPreprocessorLines = !Line->Tokens.empty();
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002499 ScopedLineState BlockState(*this, SwitchToPreprocessorLines);
Krasimir Georgiev3e051052017-07-24 14:51:59 +00002500 assert((LevelDifference >= 0 ||
2501 static_cast<unsigned>(-LevelDifference) <= Line->Level) &&
2502 "LevelDifference makes Line->Level negative");
2503 Line->Level += LevelDifference;
Alexander Kornienkob1be9d62013-04-03 12:38:53 +00002504 // Comments stored before the preprocessor directive need to be output
2505 // before the preprocessor directive, at the same level as the
2506 // preprocessor directive, as we consider them to apply to the directive.
Manuel Klimek1fcbe672014-04-11 12:27:47 +00002507 flushComments(isOnNewLine(*FormatTok));
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002508 parsePPDirective();
2509 }
Manuel Klimek68b03042014-04-14 09:14:11 +00002510 while (FormatTok->Type == TT_ConflictStart ||
2511 FormatTok->Type == TT_ConflictEnd ||
2512 FormatTok->Type == TT_ConflictAlternative) {
2513 if (FormatTok->Type == TT_ConflictStart) {
2514 conditionalCompilationStart(/*Unreachable=*/false);
2515 } else if (FormatTok->Type == TT_ConflictAlternative) {
2516 conditionalCompilationAlternative();
Daniel Jasperb05a81d2014-05-09 13:11:16 +00002517 } else if (FormatTok->Type == TT_ConflictEnd) {
Manuel Klimek68b03042014-04-14 09:14:11 +00002518 conditionalCompilationEnd();
2519 }
2520 FormatTok = Tokens->getNextToken();
2521 FormatTok->MustBreakBefore = true;
2522 }
Alexander Kornienkof2e02122013-05-24 18:24:24 +00002523
Francois Ferranda98a95c2017-07-28 07:56:14 +00002524 if (!PPStack.empty() && (PPStack.back().Kind == PP_Unreachable) &&
Alexander Kornienkof2e02122013-05-24 18:24:24 +00002525 !Line->InPPDirective) {
2526 continue;
2527 }
2528
Krasimir Georgievf62f9582017-02-08 10:30:44 +00002529 if (!FormatTok->Tok.is(tok::comment)) {
2530 distributeComments(Comments, FormatTok);
2531 Comments.clear();
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002532 return;
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002533 }
Krasimir Georgievf62f9582017-02-08 10:30:44 +00002534
2535 Comments.push_back(FormatTok);
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002536 } while (!eof());
Krasimir Georgievf62f9582017-02-08 10:30:44 +00002537
2538 distributeComments(Comments, nullptr);
2539 Comments.clear();
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002540}
2541
Manuel Klimek15dfe7a2013-05-28 11:55:06 +00002542void UnwrappedLineParser::pushToken(FormatToken *Tok) {
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +00002543 Line->Tokens.push_back(UnwrappedLineNode(Tok));
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002544 if (MustBreakBeforeNextToken) {
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +00002545 Line->Tokens.back().Tok->MustBreakBefore = true;
Manuel Klimekf92f7bc2013-01-22 16:31:55 +00002546 MustBreakBeforeNextToken = false;
Manuel Klimek1abf7892013-01-04 23:34:14 +00002547 }
Daniel Jasperf7935112012-12-03 18:12:45 +00002548}
2549
Daniel Jasper8d1832e2013-01-07 13:26:07 +00002550} // end namespace format
2551} // end namespace clang