1e5dd7070Spatrick //===--- UnwrappedLineParser.cpp - Format C++ code ------------------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick ///
9e5dd7070Spatrick /// \file
10e5dd7070Spatrick /// This file contains the implementation of the UnwrappedLineParser,
11e5dd7070Spatrick /// which turns a stream of tokens into UnwrappedLines.
12e5dd7070Spatrick ///
13e5dd7070Spatrick //===----------------------------------------------------------------------===//
14e5dd7070Spatrick
15e5dd7070Spatrick #include "UnwrappedLineParser.h"
16ec727ea7Spatrick #include "FormatToken.h"
17*12c85518Srobert #include "TokenAnnotator.h"
18*12c85518Srobert #include "clang/Basic/TokenKinds.h"
19e5dd7070Spatrick #include "llvm/ADT/STLExtras.h"
20e5dd7070Spatrick #include "llvm/Support/Debug.h"
21e5dd7070Spatrick #include "llvm/Support/raw_ostream.h"
22e5dd7070Spatrick
23e5dd7070Spatrick #include <algorithm>
24*12c85518Srobert #include <utility>
25e5dd7070Spatrick
26e5dd7070Spatrick #define DEBUG_TYPE "format-parser"
27e5dd7070Spatrick
28e5dd7070Spatrick namespace clang {
29e5dd7070Spatrick namespace format {
30e5dd7070Spatrick
31e5dd7070Spatrick class FormatTokenSource {
32e5dd7070Spatrick public:
~FormatTokenSource()33e5dd7070Spatrick virtual ~FormatTokenSource() {}
34*12c85518Srobert
35*12c85518Srobert // Returns the next token in the token stream.
36e5dd7070Spatrick virtual FormatToken *getNextToken() = 0;
37e5dd7070Spatrick
38*12c85518Srobert // Returns the token preceding the token returned by the last call to
39*12c85518Srobert // getNextToken() in the token stream, or nullptr if no such token exists.
40*12c85518Srobert virtual FormatToken *getPreviousToken() = 0;
41*12c85518Srobert
42*12c85518Srobert // Returns the token that would be returned by the next call to
43*12c85518Srobert // getNextToken().
44*12c85518Srobert virtual FormatToken *peekNextToken(bool SkipComment = false) = 0;
45*12c85518Srobert
46*12c85518Srobert // Returns whether we are at the end of the file.
47*12c85518Srobert // This can be different from whether getNextToken() returned an eof token
48*12c85518Srobert // when the FormatTokenSource is a view on a part of the token stream.
49*12c85518Srobert virtual bool isEOF() = 0;
50*12c85518Srobert
51*12c85518Srobert // Gets the current position in the token stream, to be used by setPosition().
52e5dd7070Spatrick virtual unsigned getPosition() = 0;
53*12c85518Srobert
54*12c85518Srobert // Resets the token stream to the state it was in when getPosition() returned
55*12c85518Srobert // Position, and return the token at that position in the stream.
56e5dd7070Spatrick virtual FormatToken *setPosition(unsigned Position) = 0;
57e5dd7070Spatrick };
58e5dd7070Spatrick
59e5dd7070Spatrick namespace {
60e5dd7070Spatrick
printLine(llvm::raw_ostream & OS,const UnwrappedLine & Line,StringRef Prefix="",bool PrintText=false)61*12c85518Srobert void printLine(llvm::raw_ostream &OS, const UnwrappedLine &Line,
62*12c85518Srobert StringRef Prefix = "", bool PrintText = false) {
63*12c85518Srobert OS << Prefix << "Line(" << Line.Level << ", FSC=" << Line.FirstStartColumn
64*12c85518Srobert << ")" << (Line.InPPDirective ? " MACRO" : "") << ": ";
65*12c85518Srobert bool NewLine = false;
66*12c85518Srobert for (std::list<UnwrappedLineNode>::const_iterator I = Line.Tokens.begin(),
67*12c85518Srobert E = Line.Tokens.end();
68*12c85518Srobert I != E; ++I) {
69*12c85518Srobert if (NewLine) {
70*12c85518Srobert OS << Prefix;
71*12c85518Srobert NewLine = false;
72*12c85518Srobert }
73*12c85518Srobert OS << I->Tok->Tok.getName() << "["
74*12c85518Srobert << "T=" << (unsigned)I->Tok->getType()
75*12c85518Srobert << ", OC=" << I->Tok->OriginalColumn << ", \"" << I->Tok->TokenText
76*12c85518Srobert << "\"] ";
77*12c85518Srobert for (SmallVectorImpl<UnwrappedLine>::const_iterator
78*12c85518Srobert CI = I->Children.begin(),
79*12c85518Srobert CE = I->Children.end();
80*12c85518Srobert CI != CE; ++CI) {
81*12c85518Srobert OS << "\n";
82*12c85518Srobert printLine(OS, *CI, (Prefix + " ").str());
83*12c85518Srobert NewLine = true;
84*12c85518Srobert }
85*12c85518Srobert }
86*12c85518Srobert if (!NewLine)
87*12c85518Srobert OS << "\n";
88*12c85518Srobert }
89*12c85518Srobert
printDebugInfo(const UnwrappedLine & Line)90*12c85518Srobert LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line) {
91*12c85518Srobert printLine(llvm::dbgs(), Line);
92*12c85518Srobert }
93*12c85518Srobert
94e5dd7070Spatrick class ScopedDeclarationState {
95e5dd7070Spatrick public:
ScopedDeclarationState(UnwrappedLine & Line,llvm::BitVector & Stack,bool MustBeDeclaration)96*12c85518Srobert ScopedDeclarationState(UnwrappedLine &Line, llvm::BitVector &Stack,
97e5dd7070Spatrick bool MustBeDeclaration)
98e5dd7070Spatrick : Line(Line), Stack(Stack) {
99e5dd7070Spatrick Line.MustBeDeclaration = MustBeDeclaration;
100e5dd7070Spatrick Stack.push_back(MustBeDeclaration);
101e5dd7070Spatrick }
~ScopedDeclarationState()102e5dd7070Spatrick ~ScopedDeclarationState() {
103e5dd7070Spatrick Stack.pop_back();
104e5dd7070Spatrick if (!Stack.empty())
105e5dd7070Spatrick Line.MustBeDeclaration = Stack.back();
106e5dd7070Spatrick else
107e5dd7070Spatrick Line.MustBeDeclaration = true;
108e5dd7070Spatrick }
109e5dd7070Spatrick
110e5dd7070Spatrick private:
111e5dd7070Spatrick UnwrappedLine &Line;
112*12c85518Srobert llvm::BitVector &Stack;
113e5dd7070Spatrick };
114e5dd7070Spatrick
isLineComment(const FormatToken & FormatTok)115e5dd7070Spatrick static bool isLineComment(const FormatToken &FormatTok) {
116e5dd7070Spatrick return FormatTok.is(tok::comment) && !FormatTok.TokenText.startswith("/*");
117e5dd7070Spatrick }
118e5dd7070Spatrick
119e5dd7070Spatrick // Checks if \p FormatTok is a line comment that continues the line comment
120e5dd7070Spatrick // \p Previous. The original column of \p MinColumnToken is used to determine
121e5dd7070Spatrick // whether \p FormatTok is indented enough to the right to continue \p Previous.
continuesLineComment(const FormatToken & FormatTok,const FormatToken * Previous,const FormatToken * MinColumnToken)122e5dd7070Spatrick static bool continuesLineComment(const FormatToken &FormatTok,
123e5dd7070Spatrick const FormatToken *Previous,
124e5dd7070Spatrick const FormatToken *MinColumnToken) {
125e5dd7070Spatrick if (!Previous || !MinColumnToken)
126e5dd7070Spatrick return false;
127e5dd7070Spatrick unsigned MinContinueColumn =
128e5dd7070Spatrick MinColumnToken->OriginalColumn + (isLineComment(*MinColumnToken) ? 0 : 1);
129e5dd7070Spatrick return isLineComment(FormatTok) && FormatTok.NewlinesBefore == 1 &&
130e5dd7070Spatrick isLineComment(*Previous) &&
131e5dd7070Spatrick FormatTok.OriginalColumn >= MinContinueColumn;
132e5dd7070Spatrick }
133e5dd7070Spatrick
134e5dd7070Spatrick class ScopedMacroState : public FormatTokenSource {
135e5dd7070Spatrick public:
ScopedMacroState(UnwrappedLine & Line,FormatTokenSource * & TokenSource,FormatToken * & ResetToken)136e5dd7070Spatrick ScopedMacroState(UnwrappedLine &Line, FormatTokenSource *&TokenSource,
137e5dd7070Spatrick FormatToken *&ResetToken)
138e5dd7070Spatrick : Line(Line), TokenSource(TokenSource), ResetToken(ResetToken),
139e5dd7070Spatrick PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource),
140e5dd7070Spatrick Token(nullptr), PreviousToken(nullptr) {
141e5dd7070Spatrick FakeEOF.Tok.startToken();
142e5dd7070Spatrick FakeEOF.Tok.setKind(tok::eof);
143e5dd7070Spatrick TokenSource = this;
144e5dd7070Spatrick Line.Level = 0;
145e5dd7070Spatrick Line.InPPDirective = true;
146*12c85518Srobert // InMacroBody gets set after the `#define x` part.
147e5dd7070Spatrick }
148e5dd7070Spatrick
~ScopedMacroState()149e5dd7070Spatrick ~ScopedMacroState() override {
150e5dd7070Spatrick TokenSource = PreviousTokenSource;
151e5dd7070Spatrick ResetToken = Token;
152e5dd7070Spatrick Line.InPPDirective = false;
153*12c85518Srobert Line.InMacroBody = false;
154e5dd7070Spatrick Line.Level = PreviousLineLevel;
155e5dd7070Spatrick }
156e5dd7070Spatrick
getNextToken()157e5dd7070Spatrick FormatToken *getNextToken() override {
158e5dd7070Spatrick // The \c UnwrappedLineParser guards against this by never calling
159e5dd7070Spatrick // \c getNextToken() after it has encountered the first eof token.
160e5dd7070Spatrick assert(!eof());
161e5dd7070Spatrick PreviousToken = Token;
162e5dd7070Spatrick Token = PreviousTokenSource->getNextToken();
163e5dd7070Spatrick if (eof())
164e5dd7070Spatrick return &FakeEOF;
165e5dd7070Spatrick return Token;
166e5dd7070Spatrick }
167e5dd7070Spatrick
getPreviousToken()168*12c85518Srobert FormatToken *getPreviousToken() override {
169*12c85518Srobert return PreviousTokenSource->getPreviousToken();
170*12c85518Srobert }
171*12c85518Srobert
peekNextToken(bool SkipComment)172*12c85518Srobert FormatToken *peekNextToken(bool SkipComment) override {
173*12c85518Srobert if (eof())
174*12c85518Srobert return &FakeEOF;
175*12c85518Srobert return PreviousTokenSource->peekNextToken(SkipComment);
176*12c85518Srobert }
177*12c85518Srobert
isEOF()178*12c85518Srobert bool isEOF() override { return PreviousTokenSource->isEOF(); }
179*12c85518Srobert
getPosition()180e5dd7070Spatrick unsigned getPosition() override { return PreviousTokenSource->getPosition(); }
181e5dd7070Spatrick
setPosition(unsigned Position)182e5dd7070Spatrick FormatToken *setPosition(unsigned Position) override {
183e5dd7070Spatrick PreviousToken = nullptr;
184e5dd7070Spatrick Token = PreviousTokenSource->setPosition(Position);
185e5dd7070Spatrick return Token;
186e5dd7070Spatrick }
187e5dd7070Spatrick
188e5dd7070Spatrick private:
eof()189e5dd7070Spatrick bool eof() {
190e5dd7070Spatrick return Token && Token->HasUnescapedNewline &&
191e5dd7070Spatrick !continuesLineComment(*Token, PreviousToken,
192e5dd7070Spatrick /*MinColumnToken=*/PreviousToken);
193e5dd7070Spatrick }
194e5dd7070Spatrick
195e5dd7070Spatrick FormatToken FakeEOF;
196e5dd7070Spatrick UnwrappedLine &Line;
197e5dd7070Spatrick FormatTokenSource *&TokenSource;
198e5dd7070Spatrick FormatToken *&ResetToken;
199e5dd7070Spatrick unsigned PreviousLineLevel;
200e5dd7070Spatrick FormatTokenSource *PreviousTokenSource;
201e5dd7070Spatrick
202e5dd7070Spatrick FormatToken *Token;
203e5dd7070Spatrick FormatToken *PreviousToken;
204e5dd7070Spatrick };
205e5dd7070Spatrick
206e5dd7070Spatrick } // end anonymous namespace
207e5dd7070Spatrick
208e5dd7070Spatrick class ScopedLineState {
209e5dd7070Spatrick public:
ScopedLineState(UnwrappedLineParser & Parser,bool SwitchToPreprocessorLines=false)210e5dd7070Spatrick ScopedLineState(UnwrappedLineParser &Parser,
211e5dd7070Spatrick bool SwitchToPreprocessorLines = false)
212e5dd7070Spatrick : Parser(Parser), OriginalLines(Parser.CurrentLines) {
213e5dd7070Spatrick if (SwitchToPreprocessorLines)
214e5dd7070Spatrick Parser.CurrentLines = &Parser.PreprocessorDirectives;
215e5dd7070Spatrick else if (!Parser.Line->Tokens.empty())
216e5dd7070Spatrick Parser.CurrentLines = &Parser.Line->Tokens.back().Children;
217e5dd7070Spatrick PreBlockLine = std::move(Parser.Line);
218e5dd7070Spatrick Parser.Line = std::make_unique<UnwrappedLine>();
219e5dd7070Spatrick Parser.Line->Level = PreBlockLine->Level;
220*12c85518Srobert Parser.Line->PPLevel = PreBlockLine->PPLevel;
221e5dd7070Spatrick Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
222*12c85518Srobert Parser.Line->InMacroBody = PreBlockLine->InMacroBody;
223e5dd7070Spatrick }
224e5dd7070Spatrick
~ScopedLineState()225e5dd7070Spatrick ~ScopedLineState() {
226*12c85518Srobert if (!Parser.Line->Tokens.empty())
227e5dd7070Spatrick Parser.addUnwrappedLine();
228e5dd7070Spatrick assert(Parser.Line->Tokens.empty());
229e5dd7070Spatrick Parser.Line = std::move(PreBlockLine);
230e5dd7070Spatrick if (Parser.CurrentLines == &Parser.PreprocessorDirectives)
231e5dd7070Spatrick Parser.MustBreakBeforeNextToken = true;
232e5dd7070Spatrick Parser.CurrentLines = OriginalLines;
233e5dd7070Spatrick }
234e5dd7070Spatrick
235e5dd7070Spatrick private:
236e5dd7070Spatrick UnwrappedLineParser &Parser;
237e5dd7070Spatrick
238e5dd7070Spatrick std::unique_ptr<UnwrappedLine> PreBlockLine;
239e5dd7070Spatrick SmallVectorImpl<UnwrappedLine> *OriginalLines;
240e5dd7070Spatrick };
241e5dd7070Spatrick
242e5dd7070Spatrick class CompoundStatementIndenter {
243e5dd7070Spatrick public:
CompoundStatementIndenter(UnwrappedLineParser * Parser,const FormatStyle & Style,unsigned & LineLevel)244e5dd7070Spatrick CompoundStatementIndenter(UnwrappedLineParser *Parser,
245e5dd7070Spatrick const FormatStyle &Style, unsigned &LineLevel)
246e5dd7070Spatrick : CompoundStatementIndenter(Parser, LineLevel,
247e5dd7070Spatrick Style.BraceWrapping.AfterControlStatement,
248e5dd7070Spatrick Style.BraceWrapping.IndentBraces) {}
CompoundStatementIndenter(UnwrappedLineParser * Parser,unsigned & LineLevel,bool WrapBrace,bool IndentBrace)249e5dd7070Spatrick CompoundStatementIndenter(UnwrappedLineParser *Parser, unsigned &LineLevel,
250e5dd7070Spatrick bool WrapBrace, bool IndentBrace)
251e5dd7070Spatrick : LineLevel(LineLevel), OldLineLevel(LineLevel) {
252e5dd7070Spatrick if (WrapBrace)
253e5dd7070Spatrick Parser->addUnwrappedLine();
254e5dd7070Spatrick if (IndentBrace)
255e5dd7070Spatrick ++LineLevel;
256e5dd7070Spatrick }
~CompoundStatementIndenter()257e5dd7070Spatrick ~CompoundStatementIndenter() { LineLevel = OldLineLevel; }
258e5dd7070Spatrick
259e5dd7070Spatrick private:
260e5dd7070Spatrick unsigned &LineLevel;
261e5dd7070Spatrick unsigned OldLineLevel;
262e5dd7070Spatrick };
263e5dd7070Spatrick
264e5dd7070Spatrick namespace {
265e5dd7070Spatrick
266e5dd7070Spatrick class IndexedTokenSource : public FormatTokenSource {
267e5dd7070Spatrick public:
IndexedTokenSource(ArrayRef<FormatToken * > Tokens)268e5dd7070Spatrick IndexedTokenSource(ArrayRef<FormatToken *> Tokens)
269e5dd7070Spatrick : Tokens(Tokens), Position(-1) {}
270e5dd7070Spatrick
getNextToken()271e5dd7070Spatrick FormatToken *getNextToken() override {
272*12c85518Srobert if (Position >= 0 && isEOF()) {
273*12c85518Srobert LLVM_DEBUG({
274*12c85518Srobert llvm::dbgs() << "Next ";
275*12c85518Srobert dbgToken(Position);
276*12c85518Srobert });
277*12c85518Srobert return Tokens[Position];
278*12c85518Srobert }
279e5dd7070Spatrick ++Position;
280*12c85518Srobert LLVM_DEBUG({
281*12c85518Srobert llvm::dbgs() << "Next ";
282*12c85518Srobert dbgToken(Position);
283*12c85518Srobert });
284e5dd7070Spatrick return Tokens[Position];
285e5dd7070Spatrick }
286e5dd7070Spatrick
getPreviousToken()287*12c85518Srobert FormatToken *getPreviousToken() override {
288*12c85518Srobert return Position > 0 ? Tokens[Position - 1] : nullptr;
289*12c85518Srobert }
290*12c85518Srobert
peekNextToken(bool SkipComment)291*12c85518Srobert FormatToken *peekNextToken(bool SkipComment) override {
292*12c85518Srobert int Next = Position + 1;
293*12c85518Srobert if (SkipComment)
294*12c85518Srobert while (Tokens[Next]->is(tok::comment))
295*12c85518Srobert ++Next;
296*12c85518Srobert LLVM_DEBUG({
297*12c85518Srobert llvm::dbgs() << "Peeking ";
298*12c85518Srobert dbgToken(Next);
299*12c85518Srobert });
300*12c85518Srobert return Tokens[Next];
301*12c85518Srobert }
302*12c85518Srobert
isEOF()303*12c85518Srobert bool isEOF() override { return Tokens[Position]->is(tok::eof); }
304*12c85518Srobert
getPosition()305e5dd7070Spatrick unsigned getPosition() override {
306*12c85518Srobert LLVM_DEBUG(llvm::dbgs() << "Getting Position: " << Position << "\n");
307e5dd7070Spatrick assert(Position >= 0);
308e5dd7070Spatrick return Position;
309e5dd7070Spatrick }
310e5dd7070Spatrick
setPosition(unsigned P)311e5dd7070Spatrick FormatToken *setPosition(unsigned P) override {
312*12c85518Srobert LLVM_DEBUG(llvm::dbgs() << "Setting Position: " << P << "\n");
313e5dd7070Spatrick Position = P;
314e5dd7070Spatrick return Tokens[Position];
315e5dd7070Spatrick }
316e5dd7070Spatrick
reset()317e5dd7070Spatrick void reset() { Position = -1; }
318e5dd7070Spatrick
319e5dd7070Spatrick private:
dbgToken(int Position,llvm::StringRef Indent="")320*12c85518Srobert void dbgToken(int Position, llvm::StringRef Indent = "") {
321*12c85518Srobert FormatToken *Tok = Tokens[Position];
322*12c85518Srobert llvm::dbgs() << Indent << "[" << Position
323*12c85518Srobert << "] Token: " << Tok->Tok.getName() << " / " << Tok->TokenText
324*12c85518Srobert << ", Macro: " << !!Tok->MacroCtx << "\n";
325*12c85518Srobert }
326*12c85518Srobert
327e5dd7070Spatrick ArrayRef<FormatToken *> Tokens;
328e5dd7070Spatrick int Position;
329e5dd7070Spatrick };
330e5dd7070Spatrick
331e5dd7070Spatrick } // end anonymous namespace
332e5dd7070Spatrick
UnwrappedLineParser(const FormatStyle & Style,const AdditionalKeywords & Keywords,unsigned FirstStartColumn,ArrayRef<FormatToken * > Tokens,UnwrappedLineConsumer & Callback)333e5dd7070Spatrick UnwrappedLineParser::UnwrappedLineParser(const FormatStyle &Style,
334e5dd7070Spatrick const AdditionalKeywords &Keywords,
335e5dd7070Spatrick unsigned FirstStartColumn,
336e5dd7070Spatrick ArrayRef<FormatToken *> Tokens,
337e5dd7070Spatrick UnwrappedLineConsumer &Callback)
338e5dd7070Spatrick : Line(new UnwrappedLine), MustBreakBeforeNextToken(false),
339e5dd7070Spatrick CurrentLines(&Lines), Style(Style), Keywords(Keywords),
340e5dd7070Spatrick CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr),
341e5dd7070Spatrick Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1),
342e5dd7070Spatrick IncludeGuard(Style.IndentPPDirectives == FormatStyle::PPDIS_None
343e5dd7070Spatrick ? IG_Rejected
344e5dd7070Spatrick : IG_Inited),
345e5dd7070Spatrick IncludeGuardToken(nullptr), FirstStartColumn(FirstStartColumn) {}
346e5dd7070Spatrick
reset()347e5dd7070Spatrick void UnwrappedLineParser::reset() {
348e5dd7070Spatrick PPBranchLevel = -1;
349e5dd7070Spatrick IncludeGuard = Style.IndentPPDirectives == FormatStyle::PPDIS_None
350e5dd7070Spatrick ? IG_Rejected
351e5dd7070Spatrick : IG_Inited;
352e5dd7070Spatrick IncludeGuardToken = nullptr;
353e5dd7070Spatrick Line.reset(new UnwrappedLine);
354e5dd7070Spatrick CommentsBeforeNextToken.clear();
355e5dd7070Spatrick FormatTok = nullptr;
356e5dd7070Spatrick MustBreakBeforeNextToken = false;
357e5dd7070Spatrick PreprocessorDirectives.clear();
358e5dd7070Spatrick CurrentLines = &Lines;
359e5dd7070Spatrick DeclarationScopeStack.clear();
360*12c85518Srobert NestedTooDeep.clear();
361e5dd7070Spatrick PPStack.clear();
362e5dd7070Spatrick Line->FirstStartColumn = FirstStartColumn;
363e5dd7070Spatrick }
364e5dd7070Spatrick
parse()365e5dd7070Spatrick void UnwrappedLineParser::parse() {
366e5dd7070Spatrick IndexedTokenSource TokenSource(AllTokens);
367e5dd7070Spatrick Line->FirstStartColumn = FirstStartColumn;
368e5dd7070Spatrick do {
369e5dd7070Spatrick LLVM_DEBUG(llvm::dbgs() << "----\n");
370e5dd7070Spatrick reset();
371e5dd7070Spatrick Tokens = &TokenSource;
372e5dd7070Spatrick TokenSource.reset();
373e5dd7070Spatrick
374e5dd7070Spatrick readToken();
375e5dd7070Spatrick parseFile();
376e5dd7070Spatrick
377e5dd7070Spatrick // If we found an include guard then all preprocessor directives (other than
378e5dd7070Spatrick // the guard) are over-indented by one.
379*12c85518Srobert if (IncludeGuard == IG_Found) {
380e5dd7070Spatrick for (auto &Line : Lines)
381e5dd7070Spatrick if (Line.InPPDirective && Line.Level > 0)
382e5dd7070Spatrick --Line.Level;
383*12c85518Srobert }
384e5dd7070Spatrick
385e5dd7070Spatrick // Create line with eof token.
386e5dd7070Spatrick pushToken(FormatTok);
387e5dd7070Spatrick addUnwrappedLine();
388e5dd7070Spatrick
389*12c85518Srobert for (const UnwrappedLine &Line : Lines)
390*12c85518Srobert Callback.consumeUnwrappedLine(Line);
391*12c85518Srobert
392e5dd7070Spatrick Callback.finishRun();
393e5dd7070Spatrick Lines.clear();
394e5dd7070Spatrick while (!PPLevelBranchIndex.empty() &&
395e5dd7070Spatrick PPLevelBranchIndex.back() + 1 >= PPLevelBranchCount.back()) {
396e5dd7070Spatrick PPLevelBranchIndex.resize(PPLevelBranchIndex.size() - 1);
397e5dd7070Spatrick PPLevelBranchCount.resize(PPLevelBranchCount.size() - 1);
398e5dd7070Spatrick }
399e5dd7070Spatrick if (!PPLevelBranchIndex.empty()) {
400e5dd7070Spatrick ++PPLevelBranchIndex.back();
401e5dd7070Spatrick assert(PPLevelBranchIndex.size() == PPLevelBranchCount.size());
402e5dd7070Spatrick assert(PPLevelBranchIndex.back() <= PPLevelBranchCount.back());
403e5dd7070Spatrick }
404e5dd7070Spatrick } while (!PPLevelBranchIndex.empty());
405e5dd7070Spatrick }
406e5dd7070Spatrick
parseFile()407e5dd7070Spatrick void UnwrappedLineParser::parseFile() {
408e5dd7070Spatrick // The top-level context in a file always has declarations, except for pre-
409e5dd7070Spatrick // processor directives and JavaScript files.
410*12c85518Srobert bool MustBeDeclaration = !Line->InPPDirective && !Style.isJavaScript();
411e5dd7070Spatrick ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
412e5dd7070Spatrick MustBeDeclaration);
413e5dd7070Spatrick if (Style.Language == FormatStyle::LK_TextProto)
414e5dd7070Spatrick parseBracedList();
415e5dd7070Spatrick else
416*12c85518Srobert parseLevel();
417e5dd7070Spatrick // Make sure to format the remaining tokens.
418e5dd7070Spatrick //
419e5dd7070Spatrick // LK_TextProto is special since its top-level is parsed as the body of a
420e5dd7070Spatrick // braced list, which does not necessarily have natural line separators such
421e5dd7070Spatrick // as a semicolon. Comments after the last entry that have been determined to
422e5dd7070Spatrick // not belong to that line, as in:
423e5dd7070Spatrick // key: value
424e5dd7070Spatrick // // endfile comment
425e5dd7070Spatrick // do not have a chance to be put on a line of their own until this point.
426e5dd7070Spatrick // Here we add this newline before end-of-file comments.
427e5dd7070Spatrick if (Style.Language == FormatStyle::LK_TextProto &&
428*12c85518Srobert !CommentsBeforeNextToken.empty()) {
429e5dd7070Spatrick addUnwrappedLine();
430*12c85518Srobert }
431e5dd7070Spatrick flushComments(true);
432e5dd7070Spatrick addUnwrappedLine();
433e5dd7070Spatrick }
434e5dd7070Spatrick
parseCSharpGenericTypeConstraint()435ec727ea7Spatrick void UnwrappedLineParser::parseCSharpGenericTypeConstraint() {
436ec727ea7Spatrick do {
437ec727ea7Spatrick switch (FormatTok->Tok.getKind()) {
438ec727ea7Spatrick case tok::l_brace:
439ec727ea7Spatrick return;
440ec727ea7Spatrick default:
441ec727ea7Spatrick if (FormatTok->is(Keywords.kw_where)) {
442ec727ea7Spatrick addUnwrappedLine();
443ec727ea7Spatrick nextToken();
444ec727ea7Spatrick parseCSharpGenericTypeConstraint();
445ec727ea7Spatrick break;
446ec727ea7Spatrick }
447ec727ea7Spatrick nextToken();
448ec727ea7Spatrick break;
449ec727ea7Spatrick }
450ec727ea7Spatrick } while (!eof());
451ec727ea7Spatrick }
452ec727ea7Spatrick
parseCSharpAttribute()453ec727ea7Spatrick void UnwrappedLineParser::parseCSharpAttribute() {
454ec727ea7Spatrick int UnpairedSquareBrackets = 1;
455ec727ea7Spatrick do {
456ec727ea7Spatrick switch (FormatTok->Tok.getKind()) {
457ec727ea7Spatrick case tok::r_square:
458ec727ea7Spatrick nextToken();
459ec727ea7Spatrick --UnpairedSquareBrackets;
460ec727ea7Spatrick if (UnpairedSquareBrackets == 0) {
461ec727ea7Spatrick addUnwrappedLine();
462ec727ea7Spatrick return;
463ec727ea7Spatrick }
464ec727ea7Spatrick break;
465ec727ea7Spatrick case tok::l_square:
466ec727ea7Spatrick ++UnpairedSquareBrackets;
467ec727ea7Spatrick nextToken();
468ec727ea7Spatrick break;
469ec727ea7Spatrick default:
470ec727ea7Spatrick nextToken();
471ec727ea7Spatrick break;
472ec727ea7Spatrick }
473ec727ea7Spatrick } while (!eof());
474ec727ea7Spatrick }
475ec727ea7Spatrick
precededByCommentOrPPDirective() const476*12c85518Srobert bool UnwrappedLineParser::precededByCommentOrPPDirective() const {
477*12c85518Srobert if (!Lines.empty() && Lines.back().InPPDirective)
478*12c85518Srobert return true;
479*12c85518Srobert
480*12c85518Srobert const FormatToken *Previous = Tokens->getPreviousToken();
481*12c85518Srobert return Previous && Previous->is(tok::comment) &&
482*12c85518Srobert (Previous->IsMultiline || Previous->NewlinesBefore > 0);
483e5dd7070Spatrick }
484e5dd7070Spatrick
485*12c85518Srobert /// \brief Parses a level, that is ???.
486*12c85518Srobert /// \param OpeningBrace Opening brace (\p nullptr if absent) of that level
487*12c85518Srobert /// \param CanContainBracedList If the content can contain (at any level) a
488*12c85518Srobert /// braced list.
489*12c85518Srobert /// \param NextLBracesType The type for left brace found in this level.
490*12c85518Srobert /// \param IfKind The \p if statement kind in the level.
491*12c85518Srobert /// \param IfLeftBrace The left brace of the \p if block in the level.
492*12c85518Srobert /// \returns true if a simple block of if/else/for/while, or false otherwise.
493*12c85518Srobert /// (A simple block has a single statement.)
parseLevel(const FormatToken * OpeningBrace,bool CanContainBracedList,TokenType NextLBracesType,IfStmtKind * IfKind,FormatToken ** IfLeftBrace)494*12c85518Srobert bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace,
495*12c85518Srobert bool CanContainBracedList,
496*12c85518Srobert TokenType NextLBracesType,
497*12c85518Srobert IfStmtKind *IfKind,
498*12c85518Srobert FormatToken **IfLeftBrace) {
499*12c85518Srobert auto NextLevelLBracesType = NextLBracesType == TT_CompoundRequirementLBrace
500*12c85518Srobert ? TT_BracedListLBrace
501*12c85518Srobert : TT_Unknown;
502*12c85518Srobert const bool IsPrecededByCommentOrPPDirective =
503*12c85518Srobert !Style.RemoveBracesLLVM || precededByCommentOrPPDirective();
504*12c85518Srobert FormatToken *IfLBrace = nullptr;
505*12c85518Srobert bool HasDoWhile = false;
506*12c85518Srobert bool HasLabel = false;
507*12c85518Srobert unsigned StatementCount = 0;
508*12c85518Srobert bool SwitchLabelEncountered = false;
509*12c85518Srobert
510*12c85518Srobert do {
511*12c85518Srobert if (FormatTok->getType() == TT_AttributeMacro) {
512*12c85518Srobert nextToken();
513*12c85518Srobert continue;
514*12c85518Srobert }
515*12c85518Srobert tok::TokenKind kind = FormatTok->Tok.getKind();
516*12c85518Srobert if (FormatTok->getType() == TT_MacroBlockBegin)
517*12c85518Srobert kind = tok::l_brace;
518*12c85518Srobert else if (FormatTok->getType() == TT_MacroBlockEnd)
519*12c85518Srobert kind = tok::r_brace;
520*12c85518Srobert
521*12c85518Srobert auto ParseDefault = [this, OpeningBrace, NextLevelLBracesType, IfKind,
522*12c85518Srobert &IfLBrace, &HasDoWhile, &HasLabel, &StatementCount] {
523*12c85518Srobert parseStructuralElement(!OpeningBrace, NextLevelLBracesType, IfKind,
524*12c85518Srobert &IfLBrace, HasDoWhile ? nullptr : &HasDoWhile,
525*12c85518Srobert HasLabel ? nullptr : &HasLabel);
526*12c85518Srobert ++StatementCount;
527*12c85518Srobert assert(StatementCount > 0 && "StatementCount overflow!");
528*12c85518Srobert };
529*12c85518Srobert
530e5dd7070Spatrick switch (kind) {
531e5dd7070Spatrick case tok::comment:
532e5dd7070Spatrick nextToken();
533e5dd7070Spatrick addUnwrappedLine();
534e5dd7070Spatrick break;
535e5dd7070Spatrick case tok::l_brace:
536*12c85518Srobert if (NextLBracesType != TT_Unknown) {
537*12c85518Srobert FormatTok->setFinalizedType(NextLBracesType);
538*12c85518Srobert } else if (FormatTok->Previous &&
539*12c85518Srobert FormatTok->Previous->ClosesRequiresClause) {
540*12c85518Srobert // We need the 'default' case here to correctly parse a function
541*12c85518Srobert // l_brace.
542*12c85518Srobert ParseDefault();
543e5dd7070Spatrick continue;
544*12c85518Srobert }
545*12c85518Srobert if (CanContainBracedList && !FormatTok->is(TT_MacroBlockBegin) &&
546*12c85518Srobert tryToParseBracedList()) {
547*12c85518Srobert continue;
548*12c85518Srobert }
549*12c85518Srobert parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,
550*12c85518Srobert /*MunchSemi=*/true, /*KeepBraces=*/true, /*IfKind=*/nullptr,
551*12c85518Srobert /*UnindentWhitesmithsBraces=*/false, CanContainBracedList,
552*12c85518Srobert NextLBracesType);
553*12c85518Srobert ++StatementCount;
554*12c85518Srobert assert(StatementCount > 0 && "StatementCount overflow!");
555e5dd7070Spatrick addUnwrappedLine();
556e5dd7070Spatrick break;
557e5dd7070Spatrick case tok::r_brace:
558*12c85518Srobert if (OpeningBrace) {
559*12c85518Srobert if (!Style.RemoveBracesLLVM || Line->InPPDirective ||
560*12c85518Srobert !OpeningBrace->isOneOf(TT_ControlStatementLBrace, TT_ElseLBrace)) {
561*12c85518Srobert return false;
562*12c85518Srobert }
563*12c85518Srobert if (FormatTok->isNot(tok::r_brace) || StatementCount != 1 || HasLabel ||
564*12c85518Srobert HasDoWhile || IsPrecededByCommentOrPPDirective ||
565*12c85518Srobert precededByCommentOrPPDirective()) {
566*12c85518Srobert return false;
567*12c85518Srobert }
568*12c85518Srobert const FormatToken *Next = Tokens->peekNextToken();
569*12c85518Srobert if (Next->is(tok::comment) && Next->NewlinesBefore == 0)
570*12c85518Srobert return false;
571*12c85518Srobert if (IfLeftBrace)
572*12c85518Srobert *IfLeftBrace = IfLBrace;
573*12c85518Srobert return true;
574*12c85518Srobert }
575e5dd7070Spatrick nextToken();
576e5dd7070Spatrick addUnwrappedLine();
577e5dd7070Spatrick break;
578e5dd7070Spatrick case tok::kw_default: {
579e5dd7070Spatrick unsigned StoredPosition = Tokens->getPosition();
580e5dd7070Spatrick FormatToken *Next;
581e5dd7070Spatrick do {
582e5dd7070Spatrick Next = Tokens->getNextToken();
583*12c85518Srobert assert(Next);
584*12c85518Srobert } while (Next->is(tok::comment));
585e5dd7070Spatrick FormatTok = Tokens->setPosition(StoredPosition);
586*12c85518Srobert if (Next->isNot(tok::colon)) {
587e5dd7070Spatrick // default not followed by ':' is not a case label; treat it like
588e5dd7070Spatrick // an identifier.
589e5dd7070Spatrick parseStructuralElement();
590e5dd7070Spatrick break;
591e5dd7070Spatrick }
592e5dd7070Spatrick // Else, if it is 'default:', fall through to the case handling.
593*12c85518Srobert [[fallthrough]];
594e5dd7070Spatrick }
595e5dd7070Spatrick case tok::kw_case:
596*12c85518Srobert if (Style.isProto() || Style.isVerilog() ||
597*12c85518Srobert (Style.isJavaScript() && Line->MustBeDeclaration)) {
598*12c85518Srobert // Proto: there are no switch/case statements
599*12c85518Srobert // Verilog: Case labels don't have this word. We handle case
600*12c85518Srobert // labels including default in TokenAnnotator.
601*12c85518Srobert // JavaScript: A 'case: string' style field declaration.
602*12c85518Srobert ParseDefault();
603e5dd7070Spatrick break;
604e5dd7070Spatrick }
605e5dd7070Spatrick if (!SwitchLabelEncountered &&
606*12c85518Srobert (Style.IndentCaseLabels ||
607*12c85518Srobert (Line->InPPDirective && Line->Level == 1))) {
608e5dd7070Spatrick ++Line->Level;
609*12c85518Srobert }
610e5dd7070Spatrick SwitchLabelEncountered = true;
611e5dd7070Spatrick parseStructuralElement();
612e5dd7070Spatrick break;
613ec727ea7Spatrick case tok::l_square:
614ec727ea7Spatrick if (Style.isCSharp()) {
615ec727ea7Spatrick nextToken();
616ec727ea7Spatrick parseCSharpAttribute();
617ec727ea7Spatrick break;
618ec727ea7Spatrick }
619*12c85518Srobert if (handleCppAttributes())
620*12c85518Srobert break;
621*12c85518Srobert [[fallthrough]];
622e5dd7070Spatrick default:
623*12c85518Srobert ParseDefault();
624e5dd7070Spatrick break;
625e5dd7070Spatrick }
626e5dd7070Spatrick } while (!eof());
627*12c85518Srobert
628*12c85518Srobert return false;
629e5dd7070Spatrick }
630e5dd7070Spatrick
calculateBraceTypes(bool ExpectClassBody)631e5dd7070Spatrick void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
632e5dd7070Spatrick // We'll parse forward through the tokens until we hit
633e5dd7070Spatrick // a closing brace or eof - note that getNextToken() will
634e5dd7070Spatrick // parse macros, so this will magically work inside macro
635e5dd7070Spatrick // definitions, too.
636e5dd7070Spatrick unsigned StoredPosition = Tokens->getPosition();
637e5dd7070Spatrick FormatToken *Tok = FormatTok;
638e5dd7070Spatrick const FormatToken *PrevTok = Tok->Previous;
639e5dd7070Spatrick // Keep a stack of positions of lbrace tokens. We will
640e5dd7070Spatrick // update information about whether an lbrace starts a
641e5dd7070Spatrick // braced init list or a different block during the loop.
642e5dd7070Spatrick SmallVector<FormatToken *, 8> LBraceStack;
643*12c85518Srobert assert(Tok->is(tok::l_brace));
644e5dd7070Spatrick do {
645e5dd7070Spatrick // Get next non-comment token.
646e5dd7070Spatrick FormatToken *NextTok;
647e5dd7070Spatrick do {
648e5dd7070Spatrick NextTok = Tokens->getNextToken();
649e5dd7070Spatrick } while (NextTok->is(tok::comment));
650e5dd7070Spatrick
651e5dd7070Spatrick switch (Tok->Tok.getKind()) {
652e5dd7070Spatrick case tok::l_brace:
653*12c85518Srobert if (Style.isJavaScript() && PrevTok) {
654*12c85518Srobert if (PrevTok->isOneOf(tok::colon, tok::less)) {
655e5dd7070Spatrick // A ':' indicates this code is in a type, or a braced list
656e5dd7070Spatrick // following a label in an object literal ({a: {b: 1}}).
657e5dd7070Spatrick // A '<' could be an object used in a comparison, but that is nonsense
658e5dd7070Spatrick // code (can never return true), so more likely it is a generic type
659e5dd7070Spatrick // argument (`X<{a: string; b: number}>`).
660e5dd7070Spatrick // The code below could be confused by semicolons between the
661e5dd7070Spatrick // individual members in a type member list, which would normally
662e5dd7070Spatrick // trigger BK_Block. In both cases, this must be parsed as an inline
663e5dd7070Spatrick // braced init.
664a9ac8606Spatrick Tok->setBlockKind(BK_BracedInit);
665*12c85518Srobert } else if (PrevTok->is(tok::r_paren)) {
666e5dd7070Spatrick // `) { }` can only occur in function or method declarations in JS.
667a9ac8606Spatrick Tok->setBlockKind(BK_Block);
668*12c85518Srobert }
669e5dd7070Spatrick } else {
670a9ac8606Spatrick Tok->setBlockKind(BK_Unknown);
671e5dd7070Spatrick }
672e5dd7070Spatrick LBraceStack.push_back(Tok);
673e5dd7070Spatrick break;
674e5dd7070Spatrick case tok::r_brace:
675e5dd7070Spatrick if (LBraceStack.empty())
676e5dd7070Spatrick break;
677a9ac8606Spatrick if (LBraceStack.back()->is(BK_Unknown)) {
678e5dd7070Spatrick bool ProbablyBracedList = false;
679e5dd7070Spatrick if (Style.Language == FormatStyle::LK_Proto) {
680e5dd7070Spatrick ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square);
681e5dd7070Spatrick } else {
682*12c85518Srobert // Skip NextTok over preprocessor lines, otherwise we may not
683*12c85518Srobert // properly diagnose the block as a braced intializer
684*12c85518Srobert // if the comma separator appears after the pp directive.
685*12c85518Srobert while (NextTok->is(tok::hash)) {
686*12c85518Srobert ScopedMacroState MacroState(*Line, Tokens, NextTok);
687*12c85518Srobert do {
688*12c85518Srobert NextTok = Tokens->getNextToken();
689*12c85518Srobert } while (NextTok->isNot(tok::eof));
690*12c85518Srobert }
691*12c85518Srobert
692e5dd7070Spatrick // Using OriginalColumn to distinguish between ObjC methods and
693e5dd7070Spatrick // binary operators is a bit hacky.
694e5dd7070Spatrick bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) &&
695e5dd7070Spatrick NextTok->OriginalColumn == 0;
696e5dd7070Spatrick
697*12c85518Srobert // Try to detect a braced list. Note that regardless how we mark inner
698*12c85518Srobert // braces here, we will overwrite the BlockKind later if we parse a
699*12c85518Srobert // braced list (where all blocks inside are by default braced lists),
700*12c85518Srobert // or when we explicitly detect blocks (for example while parsing
701*12c85518Srobert // lambdas).
702*12c85518Srobert
703*12c85518Srobert // If we already marked the opening brace as braced list, the closing
704*12c85518Srobert // must also be part of it.
705*12c85518Srobert ProbablyBracedList = LBraceStack.back()->is(TT_BracedListLBrace);
706*12c85518Srobert
707*12c85518Srobert ProbablyBracedList = ProbablyBracedList ||
708*12c85518Srobert (Style.isJavaScript() &&
709*12c85518Srobert NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
710*12c85518Srobert Keywords.kw_as));
711*12c85518Srobert ProbablyBracedList = ProbablyBracedList ||
712*12c85518Srobert (Style.isCpp() && NextTok->is(tok::l_paren));
713*12c85518Srobert
714e5dd7070Spatrick // If there is a comma, semicolon or right paren after the closing
715*12c85518Srobert // brace, we assume this is a braced initializer list.
716e5dd7070Spatrick // FIXME: Some of these do not apply to JS, e.g. "} {" can never be a
717e5dd7070Spatrick // braced list in JS.
718e5dd7070Spatrick ProbablyBracedList =
719*12c85518Srobert ProbablyBracedList ||
720e5dd7070Spatrick NextTok->isOneOf(tok::comma, tok::period, tok::colon,
721e5dd7070Spatrick tok::r_paren, tok::r_square, tok::l_brace,
722*12c85518Srobert tok::ellipsis);
723*12c85518Srobert
724*12c85518Srobert ProbablyBracedList =
725*12c85518Srobert ProbablyBracedList ||
726e5dd7070Spatrick (NextTok->is(tok::identifier) &&
727*12c85518Srobert !PrevTok->isOneOf(tok::semi, tok::r_brace, tok::l_brace));
728*12c85518Srobert
729*12c85518Srobert ProbablyBracedList = ProbablyBracedList ||
730e5dd7070Spatrick (NextTok->is(tok::semi) &&
731*12c85518Srobert (!ExpectClassBody || LBraceStack.size() != 1));
732*12c85518Srobert
733*12c85518Srobert ProbablyBracedList =
734*12c85518Srobert ProbablyBracedList ||
735e5dd7070Spatrick (NextTok->isBinaryOperator() && !NextIsObjCMethod);
736*12c85518Srobert
737e5dd7070Spatrick if (!Style.isCSharp() && NextTok->is(tok::l_square)) {
738e5dd7070Spatrick // We can have an array subscript after a braced init
739e5dd7070Spatrick // list, but C++11 attributes are expected after blocks.
740e5dd7070Spatrick NextTok = Tokens->getNextToken();
741e5dd7070Spatrick ProbablyBracedList = NextTok->isNot(tok::l_square);
742e5dd7070Spatrick }
743e5dd7070Spatrick }
744e5dd7070Spatrick if (ProbablyBracedList) {
745a9ac8606Spatrick Tok->setBlockKind(BK_BracedInit);
746a9ac8606Spatrick LBraceStack.back()->setBlockKind(BK_BracedInit);
747e5dd7070Spatrick } else {
748a9ac8606Spatrick Tok->setBlockKind(BK_Block);
749a9ac8606Spatrick LBraceStack.back()->setBlockKind(BK_Block);
750e5dd7070Spatrick }
751e5dd7070Spatrick }
752e5dd7070Spatrick LBraceStack.pop_back();
753e5dd7070Spatrick break;
754e5dd7070Spatrick case tok::identifier:
755e5dd7070Spatrick if (!Tok->is(TT_StatementMacro))
756e5dd7070Spatrick break;
757*12c85518Srobert [[fallthrough]];
758e5dd7070Spatrick case tok::at:
759e5dd7070Spatrick case tok::semi:
760e5dd7070Spatrick case tok::kw_if:
761e5dd7070Spatrick case tok::kw_while:
762e5dd7070Spatrick case tok::kw_for:
763e5dd7070Spatrick case tok::kw_switch:
764e5dd7070Spatrick case tok::kw_try:
765e5dd7070Spatrick case tok::kw___try:
766a9ac8606Spatrick if (!LBraceStack.empty() && LBraceStack.back()->is(BK_Unknown))
767a9ac8606Spatrick LBraceStack.back()->setBlockKind(BK_Block);
768e5dd7070Spatrick break;
769e5dd7070Spatrick default:
770e5dd7070Spatrick break;
771e5dd7070Spatrick }
772e5dd7070Spatrick PrevTok = Tok;
773e5dd7070Spatrick Tok = NextTok;
774*12c85518Srobert } while (Tok->isNot(tok::eof) && !LBraceStack.empty());
775e5dd7070Spatrick
776e5dd7070Spatrick // Assume other blocks for all unclosed opening braces.
777*12c85518Srobert for (FormatToken *LBrace : LBraceStack)
778*12c85518Srobert if (LBrace->is(BK_Unknown))
779*12c85518Srobert LBrace->setBlockKind(BK_Block);
780e5dd7070Spatrick
781e5dd7070Spatrick FormatTok = Tokens->setPosition(StoredPosition);
782e5dd7070Spatrick }
783e5dd7070Spatrick
784e5dd7070Spatrick template <class T>
hash_combine(std::size_t & seed,const T & v)785e5dd7070Spatrick static inline void hash_combine(std::size_t &seed, const T &v) {
786e5dd7070Spatrick std::hash<T> hasher;
787e5dd7070Spatrick seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
788e5dd7070Spatrick }
789e5dd7070Spatrick
computePPHash() const790e5dd7070Spatrick size_t UnwrappedLineParser::computePPHash() const {
791e5dd7070Spatrick size_t h = 0;
792e5dd7070Spatrick for (const auto &i : PPStack) {
793e5dd7070Spatrick hash_combine(h, size_t(i.Kind));
794e5dd7070Spatrick hash_combine(h, i.Line);
795e5dd7070Spatrick }
796e5dd7070Spatrick return h;
797e5dd7070Spatrick }
798e5dd7070Spatrick
799*12c85518Srobert // Checks whether \p ParsedLine might fit on a single line. If \p OpeningBrace
800*12c85518Srobert // is not null, subtracts its length (plus the preceding space) when computing
801*12c85518Srobert // the length of \p ParsedLine. We must clone the tokens of \p ParsedLine before
802*12c85518Srobert // running the token annotator on it so that we can restore them afterward.
mightFitOnOneLine(UnwrappedLine & ParsedLine,const FormatToken * OpeningBrace) const803*12c85518Srobert bool UnwrappedLineParser::mightFitOnOneLine(
804*12c85518Srobert UnwrappedLine &ParsedLine, const FormatToken *OpeningBrace) const {
805*12c85518Srobert const auto ColumnLimit = Style.ColumnLimit;
806*12c85518Srobert if (ColumnLimit == 0)
807*12c85518Srobert return true;
808*12c85518Srobert
809*12c85518Srobert auto &Tokens = ParsedLine.Tokens;
810*12c85518Srobert assert(!Tokens.empty());
811*12c85518Srobert
812*12c85518Srobert const auto *LastToken = Tokens.back().Tok;
813*12c85518Srobert assert(LastToken);
814*12c85518Srobert
815*12c85518Srobert SmallVector<UnwrappedLineNode> SavedTokens(Tokens.size());
816*12c85518Srobert
817*12c85518Srobert int Index = 0;
818*12c85518Srobert for (const auto &Token : Tokens) {
819*12c85518Srobert assert(Token.Tok);
820*12c85518Srobert auto &SavedToken = SavedTokens[Index++];
821*12c85518Srobert SavedToken.Tok = new FormatToken;
822*12c85518Srobert SavedToken.Tok->copyFrom(*Token.Tok);
823*12c85518Srobert SavedToken.Children = std::move(Token.Children);
824*12c85518Srobert }
825*12c85518Srobert
826*12c85518Srobert AnnotatedLine Line(ParsedLine);
827*12c85518Srobert assert(Line.Last == LastToken);
828*12c85518Srobert
829*12c85518Srobert TokenAnnotator Annotator(Style, Keywords);
830*12c85518Srobert Annotator.annotate(Line);
831*12c85518Srobert Annotator.calculateFormattingInformation(Line);
832*12c85518Srobert
833*12c85518Srobert auto Length = LastToken->TotalLength;
834*12c85518Srobert if (OpeningBrace) {
835*12c85518Srobert assert(OpeningBrace != Tokens.front().Tok);
836*12c85518Srobert if (auto Prev = OpeningBrace->Previous;
837*12c85518Srobert Prev && Prev->TotalLength + ColumnLimit == OpeningBrace->TotalLength) {
838*12c85518Srobert Length -= ColumnLimit;
839*12c85518Srobert }
840*12c85518Srobert Length -= OpeningBrace->TokenText.size() + 1;
841*12c85518Srobert }
842*12c85518Srobert
843*12c85518Srobert if (const auto *FirstToken = Line.First; FirstToken->is(tok::r_brace)) {
844*12c85518Srobert assert(!OpeningBrace || OpeningBrace->is(TT_ControlStatementLBrace));
845*12c85518Srobert Length -= FirstToken->TokenText.size() + 1;
846*12c85518Srobert }
847*12c85518Srobert
848*12c85518Srobert Index = 0;
849*12c85518Srobert for (auto &Token : Tokens) {
850*12c85518Srobert const auto &SavedToken = SavedTokens[Index++];
851*12c85518Srobert Token.Tok->copyFrom(*SavedToken.Tok);
852*12c85518Srobert Token.Children = std::move(SavedToken.Children);
853*12c85518Srobert delete SavedToken.Tok;
854*12c85518Srobert }
855*12c85518Srobert
856*12c85518Srobert // If these change PPLevel needs to be used for get correct indentation.
857*12c85518Srobert assert(!Line.InMacroBody);
858*12c85518Srobert assert(!Line.InPPDirective);
859*12c85518Srobert return Line.Level * Style.IndentWidth + Length <= ColumnLimit;
860*12c85518Srobert }
861*12c85518Srobert
parseBlock(bool MustBeDeclaration,unsigned AddLevels,bool MunchSemi,bool KeepBraces,IfStmtKind * IfKind,bool UnindentWhitesmithsBraces,bool CanContainBracedList,TokenType NextLBracesType)862*12c85518Srobert FormatToken *UnwrappedLineParser::parseBlock(
863*12c85518Srobert bool MustBeDeclaration, unsigned AddLevels, bool MunchSemi, bool KeepBraces,
864*12c85518Srobert IfStmtKind *IfKind, bool UnindentWhitesmithsBraces,
865*12c85518Srobert bool CanContainBracedList, TokenType NextLBracesType) {
866*12c85518Srobert auto HandleVerilogBlockLabel = [this]() {
867*12c85518Srobert // ":" name
868*12c85518Srobert if (Style.isVerilog() && FormatTok->is(tok::colon)) {
869*12c85518Srobert nextToken();
870*12c85518Srobert if (Keywords.isVerilogIdentifier(*FormatTok))
871*12c85518Srobert nextToken();
872*12c85518Srobert }
873*12c85518Srobert };
874*12c85518Srobert
875*12c85518Srobert // Whether this is a Verilog-specific block that has a special header like a
876*12c85518Srobert // module.
877*12c85518Srobert const bool VerilogHierarchy =
878*12c85518Srobert Style.isVerilog() && Keywords.isVerilogHierarchy(*FormatTok);
879*12c85518Srobert assert((FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) ||
880*12c85518Srobert (Style.isVerilog() &&
881*12c85518Srobert (Keywords.isVerilogBegin(*FormatTok) || VerilogHierarchy))) &&
882e5dd7070Spatrick "'{' or macro block token expected");
883*12c85518Srobert FormatToken *Tok = FormatTok;
884*12c85518Srobert const bool FollowedByComment = Tokens->peekNextToken()->is(tok::comment);
885*12c85518Srobert auto Index = CurrentLines->size();
886e5dd7070Spatrick const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin);
887a9ac8606Spatrick FormatTok->setBlockKind(BK_Block);
888a9ac8606Spatrick
889a9ac8606Spatrick // For Whitesmiths mode, jump to the next level prior to skipping over the
890a9ac8606Spatrick // braces.
891*12c85518Srobert if (!VerilogHierarchy && AddLevels > 0 &&
892*12c85518Srobert Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) {
893a9ac8606Spatrick ++Line->Level;
894*12c85518Srobert }
895e5dd7070Spatrick
896e5dd7070Spatrick size_t PPStartHash = computePPHash();
897e5dd7070Spatrick
898*12c85518Srobert const unsigned InitialLevel = Line->Level;
899*12c85518Srobert if (VerilogHierarchy) {
900*12c85518Srobert AddLevels += parseVerilogHierarchyHeader();
901*12c85518Srobert } else {
902a9ac8606Spatrick nextToken(/*LevelDifference=*/AddLevels);
903*12c85518Srobert HandleVerilogBlockLabel();
904*12c85518Srobert }
905*12c85518Srobert
906*12c85518Srobert // Bail out if there are too many levels. Otherwise, the stack might overflow.
907*12c85518Srobert if (Line->Level > 300)
908*12c85518Srobert return nullptr;
909e5dd7070Spatrick
910e5dd7070Spatrick if (MacroBlock && FormatTok->is(tok::l_paren))
911e5dd7070Spatrick parseParens();
912e5dd7070Spatrick
913e5dd7070Spatrick size_t NbPreprocessorDirectives =
914e5dd7070Spatrick CurrentLines == &Lines ? PreprocessorDirectives.size() : 0;
915e5dd7070Spatrick addUnwrappedLine();
916e5dd7070Spatrick size_t OpeningLineIndex =
917e5dd7070Spatrick CurrentLines->empty()
918e5dd7070Spatrick ? (UnwrappedLine::kInvalidIndex)
919e5dd7070Spatrick : (CurrentLines->size() - 1 - NbPreprocessorDirectives);
920e5dd7070Spatrick
921a9ac8606Spatrick // Whitesmiths is weird here. The brace needs to be indented for the namespace
922a9ac8606Spatrick // block, but the block itself may not be indented depending on the style
923a9ac8606Spatrick // settings. This allows the format to back up one level in those cases.
924a9ac8606Spatrick if (UnindentWhitesmithsBraces)
925a9ac8606Spatrick --Line->Level;
926a9ac8606Spatrick
927e5dd7070Spatrick ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
928e5dd7070Spatrick MustBeDeclaration);
929a9ac8606Spatrick if (AddLevels > 0u && Style.BreakBeforeBraces != FormatStyle::BS_Whitesmiths)
930a9ac8606Spatrick Line->Level += AddLevels;
931*12c85518Srobert
932*12c85518Srobert FormatToken *IfLBrace = nullptr;
933*12c85518Srobert const bool SimpleBlock =
934*12c85518Srobert parseLevel(Tok, CanContainBracedList, NextLBracesType, IfKind, &IfLBrace);
935e5dd7070Spatrick
936e5dd7070Spatrick if (eof())
937*12c85518Srobert return IfLBrace;
938e5dd7070Spatrick
939e5dd7070Spatrick if (MacroBlock ? !FormatTok->is(TT_MacroBlockEnd)
940e5dd7070Spatrick : !FormatTok->is(tok::r_brace)) {
941e5dd7070Spatrick Line->Level = InitialLevel;
942a9ac8606Spatrick FormatTok->setBlockKind(BK_Block);
943*12c85518Srobert return IfLBrace;
944*12c85518Srobert }
945*12c85518Srobert
946*12c85518Srobert const bool IsFunctionRBrace =
947*12c85518Srobert FormatTok->is(tok::r_brace) && Tok->is(TT_FunctionLBrace);
948*12c85518Srobert
949*12c85518Srobert auto RemoveBraces = [=]() mutable {
950*12c85518Srobert if (!SimpleBlock)
951*12c85518Srobert return false;
952*12c85518Srobert assert(Tok->isOneOf(TT_ControlStatementLBrace, TT_ElseLBrace));
953*12c85518Srobert assert(FormatTok->is(tok::r_brace));
954*12c85518Srobert const bool WrappedOpeningBrace = !Tok->Previous;
955*12c85518Srobert if (WrappedOpeningBrace && FollowedByComment)
956*12c85518Srobert return false;
957*12c85518Srobert const bool HasRequiredIfBraces = IfLBrace && !IfLBrace->Optional;
958*12c85518Srobert if (KeepBraces && !HasRequiredIfBraces)
959*12c85518Srobert return false;
960*12c85518Srobert if (Tok->isNot(TT_ElseLBrace) || !HasRequiredIfBraces) {
961*12c85518Srobert const FormatToken *Previous = Tokens->getPreviousToken();
962*12c85518Srobert assert(Previous);
963*12c85518Srobert if (Previous->is(tok::r_brace) && !Previous->Optional)
964*12c85518Srobert return false;
965*12c85518Srobert }
966*12c85518Srobert assert(!CurrentLines->empty());
967*12c85518Srobert auto &LastLine = CurrentLines->back();
968*12c85518Srobert if (LastLine.Level == InitialLevel + 1 && !mightFitOnOneLine(LastLine))
969*12c85518Srobert return false;
970*12c85518Srobert if (Tok->is(TT_ElseLBrace))
971*12c85518Srobert return true;
972*12c85518Srobert if (WrappedOpeningBrace) {
973*12c85518Srobert assert(Index > 0);
974*12c85518Srobert --Index; // The line above the wrapped l_brace.
975*12c85518Srobert Tok = nullptr;
976*12c85518Srobert }
977*12c85518Srobert return mightFitOnOneLine((*CurrentLines)[Index], Tok);
978*12c85518Srobert };
979*12c85518Srobert if (RemoveBraces()) {
980*12c85518Srobert Tok->MatchingParen = FormatTok;
981*12c85518Srobert FormatTok->MatchingParen = Tok;
982e5dd7070Spatrick }
983e5dd7070Spatrick
984e5dd7070Spatrick size_t PPEndHash = computePPHash();
985e5dd7070Spatrick
986e5dd7070Spatrick // Munch the closing brace.
987a9ac8606Spatrick nextToken(/*LevelDifference=*/-AddLevels);
988e5dd7070Spatrick
989*12c85518Srobert // When this is a function block and there is an unnecessary semicolon
990*12c85518Srobert // afterwards then mark it as optional (so the RemoveSemi pass can get rid of
991*12c85518Srobert // it later).
992*12c85518Srobert if (Style.RemoveSemicolon && IsFunctionRBrace) {
993*12c85518Srobert while (FormatTok->is(tok::semi)) {
994*12c85518Srobert FormatTok->Optional = true;
995*12c85518Srobert nextToken();
996*12c85518Srobert }
997*12c85518Srobert }
998*12c85518Srobert
999*12c85518Srobert HandleVerilogBlockLabel();
1000*12c85518Srobert
1001e5dd7070Spatrick if (MacroBlock && FormatTok->is(tok::l_paren))
1002e5dd7070Spatrick parseParens();
1003e5dd7070Spatrick
1004*12c85518Srobert Line->Level = InitialLevel;
1005*12c85518Srobert
1006*12c85518Srobert if (FormatTok->is(tok::kw_noexcept)) {
1007*12c85518Srobert // A noexcept in a requires expression.
1008*12c85518Srobert nextToken();
1009*12c85518Srobert }
1010*12c85518Srobert
1011a9ac8606Spatrick if (FormatTok->is(tok::arrow)) {
1012*12c85518Srobert // Following the } or noexcept we can find a trailing return type arrow
1013a9ac8606Spatrick // as part of an implicit conversion constraint.
1014a9ac8606Spatrick nextToken();
1015a9ac8606Spatrick parseStructuralElement();
1016a9ac8606Spatrick }
1017a9ac8606Spatrick
1018*12c85518Srobert if (MunchSemi && FormatTok->is(tok::semi))
1019e5dd7070Spatrick nextToken();
1020a9ac8606Spatrick
1021e5dd7070Spatrick if (PPStartHash == PPEndHash) {
1022e5dd7070Spatrick Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
1023e5dd7070Spatrick if (OpeningLineIndex != UnwrappedLine::kInvalidIndex) {
1024e5dd7070Spatrick // Update the opening line to add the forward reference as well
1025e5dd7070Spatrick (*CurrentLines)[OpeningLineIndex].MatchingClosingBlockLineIndex =
1026e5dd7070Spatrick CurrentLines->size() - 1;
1027e5dd7070Spatrick }
1028e5dd7070Spatrick }
1029*12c85518Srobert
1030*12c85518Srobert return IfLBrace;
1031e5dd7070Spatrick }
1032e5dd7070Spatrick
isGoogScope(const UnwrappedLine & Line)1033e5dd7070Spatrick static bool isGoogScope(const UnwrappedLine &Line) {
1034e5dd7070Spatrick // FIXME: Closure-library specific stuff should not be hard-coded but be
1035e5dd7070Spatrick // configurable.
1036e5dd7070Spatrick if (Line.Tokens.size() < 4)
1037e5dd7070Spatrick return false;
1038e5dd7070Spatrick auto I = Line.Tokens.begin();
1039e5dd7070Spatrick if (I->Tok->TokenText != "goog")
1040e5dd7070Spatrick return false;
1041e5dd7070Spatrick ++I;
1042e5dd7070Spatrick if (I->Tok->isNot(tok::period))
1043e5dd7070Spatrick return false;
1044e5dd7070Spatrick ++I;
1045e5dd7070Spatrick if (I->Tok->TokenText != "scope")
1046e5dd7070Spatrick return false;
1047e5dd7070Spatrick ++I;
1048e5dd7070Spatrick return I->Tok->is(tok::l_paren);
1049e5dd7070Spatrick }
1050e5dd7070Spatrick
isIIFE(const UnwrappedLine & Line,const AdditionalKeywords & Keywords)1051e5dd7070Spatrick static bool isIIFE(const UnwrappedLine &Line,
1052e5dd7070Spatrick const AdditionalKeywords &Keywords) {
1053e5dd7070Spatrick // Look for the start of an immediately invoked anonymous function.
1054e5dd7070Spatrick // https://en.wikipedia.org/wiki/Immediately-invoked_function_expression
1055e5dd7070Spatrick // This is commonly done in JavaScript to create a new, anonymous scope.
1056e5dd7070Spatrick // Example: (function() { ... })()
1057e5dd7070Spatrick if (Line.Tokens.size() < 3)
1058e5dd7070Spatrick return false;
1059e5dd7070Spatrick auto I = Line.Tokens.begin();
1060e5dd7070Spatrick if (I->Tok->isNot(tok::l_paren))
1061e5dd7070Spatrick return false;
1062e5dd7070Spatrick ++I;
1063e5dd7070Spatrick if (I->Tok->isNot(Keywords.kw_function))
1064e5dd7070Spatrick return false;
1065e5dd7070Spatrick ++I;
1066e5dd7070Spatrick return I->Tok->is(tok::l_paren);
1067e5dd7070Spatrick }
1068e5dd7070Spatrick
ShouldBreakBeforeBrace(const FormatStyle & Style,const FormatToken & InitialToken)1069e5dd7070Spatrick static bool ShouldBreakBeforeBrace(const FormatStyle &Style,
1070e5dd7070Spatrick const FormatToken &InitialToken) {
1071*12c85518Srobert tok::TokenKind Kind = InitialToken.Tok.getKind();
1072*12c85518Srobert if (InitialToken.is(TT_NamespaceMacro))
1073*12c85518Srobert Kind = tok::kw_namespace;
1074*12c85518Srobert
1075*12c85518Srobert switch (Kind) {
1076*12c85518Srobert case tok::kw_namespace:
1077e5dd7070Spatrick return Style.BraceWrapping.AfterNamespace;
1078*12c85518Srobert case tok::kw_class:
1079e5dd7070Spatrick return Style.BraceWrapping.AfterClass;
1080*12c85518Srobert case tok::kw_union:
1081e5dd7070Spatrick return Style.BraceWrapping.AfterUnion;
1082*12c85518Srobert case tok::kw_struct:
1083e5dd7070Spatrick return Style.BraceWrapping.AfterStruct;
1084*12c85518Srobert case tok::kw_enum:
1085*12c85518Srobert return Style.BraceWrapping.AfterEnum;
1086*12c85518Srobert default:
1087e5dd7070Spatrick return false;
1088e5dd7070Spatrick }
1089*12c85518Srobert }
1090e5dd7070Spatrick
parseChildBlock(bool CanContainBracedList,clang::format::TokenType NextLBracesType)1091*12c85518Srobert void UnwrappedLineParser::parseChildBlock(
1092*12c85518Srobert bool CanContainBracedList, clang::format::TokenType NextLBracesType) {
1093*12c85518Srobert assert(FormatTok->is(tok::l_brace));
1094a9ac8606Spatrick FormatTok->setBlockKind(BK_Block);
1095*12c85518Srobert const FormatToken *OpeningBrace = FormatTok;
1096e5dd7070Spatrick nextToken();
1097e5dd7070Spatrick {
1098*12c85518Srobert bool SkipIndent = (Style.isJavaScript() &&
1099e5dd7070Spatrick (isGoogScope(*Line) || isIIFE(*Line, Keywords)));
1100e5dd7070Spatrick ScopedLineState LineState(*this);
1101e5dd7070Spatrick ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
1102e5dd7070Spatrick /*MustBeDeclaration=*/false);
1103e5dd7070Spatrick Line->Level += SkipIndent ? 0 : 1;
1104*12c85518Srobert parseLevel(OpeningBrace, CanContainBracedList, NextLBracesType);
1105e5dd7070Spatrick flushComments(isOnNewLine(*FormatTok));
1106e5dd7070Spatrick Line->Level -= SkipIndent ? 0 : 1;
1107e5dd7070Spatrick }
1108e5dd7070Spatrick nextToken();
1109e5dd7070Spatrick }
1110e5dd7070Spatrick
parsePPDirective()1111e5dd7070Spatrick void UnwrappedLineParser::parsePPDirective() {
1112*12c85518Srobert assert(FormatTok->is(tok::hash) && "'#' expected");
1113e5dd7070Spatrick ScopedMacroState MacroState(*Line, Tokens, FormatTok);
1114e5dd7070Spatrick
1115e5dd7070Spatrick nextToken();
1116e5dd7070Spatrick
1117e5dd7070Spatrick if (!FormatTok->Tok.getIdentifierInfo()) {
1118e5dd7070Spatrick parsePPUnknown();
1119e5dd7070Spatrick return;
1120e5dd7070Spatrick }
1121e5dd7070Spatrick
1122e5dd7070Spatrick switch (FormatTok->Tok.getIdentifierInfo()->getPPKeywordID()) {
1123e5dd7070Spatrick case tok::pp_define:
1124e5dd7070Spatrick parsePPDefine();
1125e5dd7070Spatrick return;
1126e5dd7070Spatrick case tok::pp_if:
1127e5dd7070Spatrick parsePPIf(/*IfDef=*/false);
1128e5dd7070Spatrick break;
1129e5dd7070Spatrick case tok::pp_ifdef:
1130e5dd7070Spatrick case tok::pp_ifndef:
1131e5dd7070Spatrick parsePPIf(/*IfDef=*/true);
1132e5dd7070Spatrick break;
1133e5dd7070Spatrick case tok::pp_else:
1134a9ac8606Spatrick case tok::pp_elifdef:
1135a9ac8606Spatrick case tok::pp_elifndef:
1136e5dd7070Spatrick case tok::pp_elif:
1137*12c85518Srobert parsePPElse();
1138e5dd7070Spatrick break;
1139e5dd7070Spatrick case tok::pp_endif:
1140e5dd7070Spatrick parsePPEndIf();
1141e5dd7070Spatrick break;
1142*12c85518Srobert case tok::pp_pragma:
1143*12c85518Srobert parsePPPragma();
1144*12c85518Srobert break;
1145e5dd7070Spatrick default:
1146e5dd7070Spatrick parsePPUnknown();
1147e5dd7070Spatrick break;
1148e5dd7070Spatrick }
1149e5dd7070Spatrick }
1150e5dd7070Spatrick
conditionalCompilationCondition(bool Unreachable)1151e5dd7070Spatrick void UnwrappedLineParser::conditionalCompilationCondition(bool Unreachable) {
1152e5dd7070Spatrick size_t Line = CurrentLines->size();
1153e5dd7070Spatrick if (CurrentLines == &PreprocessorDirectives)
1154e5dd7070Spatrick Line += Lines.size();
1155e5dd7070Spatrick
1156e5dd7070Spatrick if (Unreachable ||
1157*12c85518Srobert (!PPStack.empty() && PPStack.back().Kind == PP_Unreachable)) {
1158e5dd7070Spatrick PPStack.push_back({PP_Unreachable, Line});
1159*12c85518Srobert } else {
1160e5dd7070Spatrick PPStack.push_back({PP_Conditional, Line});
1161e5dd7070Spatrick }
1162*12c85518Srobert }
1163e5dd7070Spatrick
conditionalCompilationStart(bool Unreachable)1164e5dd7070Spatrick void UnwrappedLineParser::conditionalCompilationStart(bool Unreachable) {
1165e5dd7070Spatrick ++PPBranchLevel;
1166e5dd7070Spatrick assert(PPBranchLevel >= 0 && PPBranchLevel <= (int)PPLevelBranchIndex.size());
1167e5dd7070Spatrick if (PPBranchLevel == (int)PPLevelBranchIndex.size()) {
1168e5dd7070Spatrick PPLevelBranchIndex.push_back(0);
1169e5dd7070Spatrick PPLevelBranchCount.push_back(0);
1170e5dd7070Spatrick }
1171*12c85518Srobert PPChainBranchIndex.push(Unreachable ? -1 : 0);
1172e5dd7070Spatrick bool Skip = PPLevelBranchIndex[PPBranchLevel] > 0;
1173e5dd7070Spatrick conditionalCompilationCondition(Unreachable || Skip);
1174e5dd7070Spatrick }
1175e5dd7070Spatrick
conditionalCompilationAlternative()1176e5dd7070Spatrick void UnwrappedLineParser::conditionalCompilationAlternative() {
1177e5dd7070Spatrick if (!PPStack.empty())
1178e5dd7070Spatrick PPStack.pop_back();
1179e5dd7070Spatrick assert(PPBranchLevel < (int)PPLevelBranchIndex.size());
1180e5dd7070Spatrick if (!PPChainBranchIndex.empty())
1181e5dd7070Spatrick ++PPChainBranchIndex.top();
1182e5dd7070Spatrick conditionalCompilationCondition(
1183e5dd7070Spatrick PPBranchLevel >= 0 && !PPChainBranchIndex.empty() &&
1184e5dd7070Spatrick PPLevelBranchIndex[PPBranchLevel] != PPChainBranchIndex.top());
1185e5dd7070Spatrick }
1186e5dd7070Spatrick
conditionalCompilationEnd()1187e5dd7070Spatrick void UnwrappedLineParser::conditionalCompilationEnd() {
1188e5dd7070Spatrick assert(PPBranchLevel < (int)PPLevelBranchIndex.size());
1189e5dd7070Spatrick if (PPBranchLevel >= 0 && !PPChainBranchIndex.empty()) {
1190*12c85518Srobert if (PPChainBranchIndex.top() + 1 > PPLevelBranchCount[PPBranchLevel])
1191e5dd7070Spatrick PPLevelBranchCount[PPBranchLevel] = PPChainBranchIndex.top() + 1;
1192e5dd7070Spatrick }
1193e5dd7070Spatrick // Guard against #endif's without #if.
1194e5dd7070Spatrick if (PPBranchLevel > -1)
1195e5dd7070Spatrick --PPBranchLevel;
1196e5dd7070Spatrick if (!PPChainBranchIndex.empty())
1197e5dd7070Spatrick PPChainBranchIndex.pop();
1198e5dd7070Spatrick if (!PPStack.empty())
1199e5dd7070Spatrick PPStack.pop_back();
1200e5dd7070Spatrick }
1201e5dd7070Spatrick
parsePPIf(bool IfDef)1202e5dd7070Spatrick void UnwrappedLineParser::parsePPIf(bool IfDef) {
1203e5dd7070Spatrick bool IfNDef = FormatTok->is(tok::pp_ifndef);
1204e5dd7070Spatrick nextToken();
1205e5dd7070Spatrick bool Unreachable = false;
1206e5dd7070Spatrick if (!IfDef && (FormatTok->is(tok::kw_false) || FormatTok->TokenText == "0"))
1207e5dd7070Spatrick Unreachable = true;
1208e5dd7070Spatrick if (IfDef && !IfNDef && FormatTok->TokenText == "SWIG")
1209e5dd7070Spatrick Unreachable = true;
1210e5dd7070Spatrick conditionalCompilationStart(Unreachable);
1211e5dd7070Spatrick FormatToken *IfCondition = FormatTok;
1212e5dd7070Spatrick // If there's a #ifndef on the first line, and the only lines before it are
1213e5dd7070Spatrick // comments, it could be an include guard.
1214e5dd7070Spatrick bool MaybeIncludeGuard = IfNDef;
1215*12c85518Srobert if (IncludeGuard == IG_Inited && MaybeIncludeGuard) {
1216e5dd7070Spatrick for (auto &Line : Lines) {
1217e5dd7070Spatrick if (!Line.Tokens.front().Tok->is(tok::comment)) {
1218e5dd7070Spatrick MaybeIncludeGuard = false;
1219e5dd7070Spatrick IncludeGuard = IG_Rejected;
1220e5dd7070Spatrick break;
1221e5dd7070Spatrick }
1222e5dd7070Spatrick }
1223*12c85518Srobert }
1224e5dd7070Spatrick --PPBranchLevel;
1225e5dd7070Spatrick parsePPUnknown();
1226e5dd7070Spatrick ++PPBranchLevel;
1227e5dd7070Spatrick if (IncludeGuard == IG_Inited && MaybeIncludeGuard) {
1228e5dd7070Spatrick IncludeGuard = IG_IfNdefed;
1229e5dd7070Spatrick IncludeGuardToken = IfCondition;
1230e5dd7070Spatrick }
1231e5dd7070Spatrick }
1232e5dd7070Spatrick
parsePPElse()1233e5dd7070Spatrick void UnwrappedLineParser::parsePPElse() {
1234e5dd7070Spatrick // If a potential include guard has an #else, it's not an include guard.
1235e5dd7070Spatrick if (IncludeGuard == IG_Defined && PPBranchLevel == 0)
1236e5dd7070Spatrick IncludeGuard = IG_Rejected;
1237*12c85518Srobert // Don't crash when there is an #else without an #if.
1238*12c85518Srobert assert(PPBranchLevel >= -1);
1239*12c85518Srobert if (PPBranchLevel == -1)
1240*12c85518Srobert conditionalCompilationStart(/*Unreachable=*/true);
1241e5dd7070Spatrick conditionalCompilationAlternative();
1242e5dd7070Spatrick --PPBranchLevel;
1243e5dd7070Spatrick parsePPUnknown();
1244e5dd7070Spatrick ++PPBranchLevel;
1245e5dd7070Spatrick }
1246e5dd7070Spatrick
parsePPEndIf()1247e5dd7070Spatrick void UnwrappedLineParser::parsePPEndIf() {
1248e5dd7070Spatrick conditionalCompilationEnd();
1249e5dd7070Spatrick parsePPUnknown();
1250e5dd7070Spatrick // If the #endif of a potential include guard is the last thing in the file,
1251e5dd7070Spatrick // then we found an include guard.
1252*12c85518Srobert if (IncludeGuard == IG_Defined && PPBranchLevel == -1 && Tokens->isEOF() &&
1253*12c85518Srobert Style.IndentPPDirectives != FormatStyle::PPDIS_None) {
1254e5dd7070Spatrick IncludeGuard = IG_Found;
1255e5dd7070Spatrick }
1256*12c85518Srobert }
1257e5dd7070Spatrick
parsePPDefine()1258e5dd7070Spatrick void UnwrappedLineParser::parsePPDefine() {
1259e5dd7070Spatrick nextToken();
1260e5dd7070Spatrick
1261e5dd7070Spatrick if (!FormatTok->Tok.getIdentifierInfo()) {
1262e5dd7070Spatrick IncludeGuard = IG_Rejected;
1263e5dd7070Spatrick IncludeGuardToken = nullptr;
1264e5dd7070Spatrick parsePPUnknown();
1265e5dd7070Spatrick return;
1266e5dd7070Spatrick }
1267e5dd7070Spatrick
1268e5dd7070Spatrick if (IncludeGuard == IG_IfNdefed &&
1269e5dd7070Spatrick IncludeGuardToken->TokenText == FormatTok->TokenText) {
1270e5dd7070Spatrick IncludeGuard = IG_Defined;
1271e5dd7070Spatrick IncludeGuardToken = nullptr;
1272e5dd7070Spatrick for (auto &Line : Lines) {
1273e5dd7070Spatrick if (!Line.Tokens.front().Tok->isOneOf(tok::comment, tok::hash)) {
1274e5dd7070Spatrick IncludeGuard = IG_Rejected;
1275e5dd7070Spatrick break;
1276e5dd7070Spatrick }
1277e5dd7070Spatrick }
1278e5dd7070Spatrick }
1279e5dd7070Spatrick
1280*12c85518Srobert // In the context of a define, even keywords should be treated as normal
1281*12c85518Srobert // identifiers. Setting the kind to identifier is not enough, because we need
1282*12c85518Srobert // to treat additional keywords like __except as well, which are already
1283*12c85518Srobert // identifiers. Setting the identifier info to null interferes with include
1284*12c85518Srobert // guard processing above, and changes preprocessing nesting.
1285*12c85518Srobert FormatTok->Tok.setKind(tok::identifier);
1286*12c85518Srobert FormatTok->Tok.setIdentifierInfo(Keywords.kw_internal_ident_after_define);
1287e5dd7070Spatrick nextToken();
1288e5dd7070Spatrick if (FormatTok->Tok.getKind() == tok::l_paren &&
1289*12c85518Srobert !FormatTok->hasWhitespaceBefore()) {
1290e5dd7070Spatrick parseParens();
1291e5dd7070Spatrick }
1292e5dd7070Spatrick if (Style.IndentPPDirectives != FormatStyle::PPDIS_None)
1293e5dd7070Spatrick Line->Level += PPBranchLevel + 1;
1294e5dd7070Spatrick addUnwrappedLine();
1295e5dd7070Spatrick ++Line->Level;
1296e5dd7070Spatrick
1297*12c85518Srobert Line->PPLevel = PPBranchLevel + (IncludeGuard == IG_Defined ? 0 : 1);
1298*12c85518Srobert assert((int)Line->PPLevel >= 0);
1299*12c85518Srobert Line->InMacroBody = true;
1300*12c85518Srobert
1301e5dd7070Spatrick // Errors during a preprocessor directive can only affect the layout of the
1302e5dd7070Spatrick // preprocessor directive, and thus we ignore them. An alternative approach
1303e5dd7070Spatrick // would be to use the same approach we use on the file level (no
1304e5dd7070Spatrick // re-indentation if there was a structural error) within the macro
1305e5dd7070Spatrick // definition.
1306e5dd7070Spatrick parseFile();
1307e5dd7070Spatrick }
1308e5dd7070Spatrick
parsePPPragma()1309*12c85518Srobert void UnwrappedLineParser::parsePPPragma() {
1310*12c85518Srobert Line->InPragmaDirective = true;
1311*12c85518Srobert parsePPUnknown();
1312*12c85518Srobert }
1313*12c85518Srobert
parsePPUnknown()1314e5dd7070Spatrick void UnwrappedLineParser::parsePPUnknown() {
1315e5dd7070Spatrick do {
1316e5dd7070Spatrick nextToken();
1317e5dd7070Spatrick } while (!eof());
1318e5dd7070Spatrick if (Style.IndentPPDirectives != FormatStyle::PPDIS_None)
1319e5dd7070Spatrick Line->Level += PPBranchLevel + 1;
1320e5dd7070Spatrick addUnwrappedLine();
1321e5dd7070Spatrick }
1322e5dd7070Spatrick
1323ec727ea7Spatrick // Here we exclude certain tokens that are not usually the first token in an
1324e5dd7070Spatrick // unwrapped line. This is used in attempt to distinguish macro calls without
1325e5dd7070Spatrick // trailing semicolons from other constructs split to several lines.
tokenCanStartNewLine(const FormatToken & Tok)1326ec727ea7Spatrick static bool tokenCanStartNewLine(const FormatToken &Tok) {
1327e5dd7070Spatrick // Semicolon can be a null-statement, l_square can be a start of a macro or
1328e5dd7070Spatrick // a C++11 attribute, but this doesn't seem to be common.
1329e5dd7070Spatrick return Tok.isNot(tok::semi) && Tok.isNot(tok::l_brace) &&
1330ec727ea7Spatrick Tok.isNot(TT_AttributeSquare) &&
1331e5dd7070Spatrick // Tokens that can only be used as binary operators and a part of
1332e5dd7070Spatrick // overloaded operator names.
1333e5dd7070Spatrick Tok.isNot(tok::period) && Tok.isNot(tok::periodstar) &&
1334e5dd7070Spatrick Tok.isNot(tok::arrow) && Tok.isNot(tok::arrowstar) &&
1335e5dd7070Spatrick Tok.isNot(tok::less) && Tok.isNot(tok::greater) &&
1336e5dd7070Spatrick Tok.isNot(tok::slash) && Tok.isNot(tok::percent) &&
1337e5dd7070Spatrick Tok.isNot(tok::lessless) && Tok.isNot(tok::greatergreater) &&
1338e5dd7070Spatrick Tok.isNot(tok::equal) && Tok.isNot(tok::plusequal) &&
1339e5dd7070Spatrick Tok.isNot(tok::minusequal) && Tok.isNot(tok::starequal) &&
1340e5dd7070Spatrick Tok.isNot(tok::slashequal) && Tok.isNot(tok::percentequal) &&
1341e5dd7070Spatrick Tok.isNot(tok::ampequal) && Tok.isNot(tok::pipeequal) &&
1342e5dd7070Spatrick Tok.isNot(tok::caretequal) && Tok.isNot(tok::greatergreaterequal) &&
1343e5dd7070Spatrick Tok.isNot(tok::lesslessequal) &&
1344e5dd7070Spatrick // Colon is used in labels, base class lists, initializer lists,
1345e5dd7070Spatrick // range-based for loops, ternary operator, but should never be the
1346e5dd7070Spatrick // first token in an unwrapped line.
1347e5dd7070Spatrick Tok.isNot(tok::colon) &&
1348e5dd7070Spatrick // 'noexcept' is a trailing annotation.
1349e5dd7070Spatrick Tok.isNot(tok::kw_noexcept);
1350e5dd7070Spatrick }
1351e5dd7070Spatrick
mustBeJSIdent(const AdditionalKeywords & Keywords,const FormatToken * FormatTok)1352e5dd7070Spatrick static bool mustBeJSIdent(const AdditionalKeywords &Keywords,
1353e5dd7070Spatrick const FormatToken *FormatTok) {
1354e5dd7070Spatrick // FIXME: This returns true for C/C++ keywords like 'struct'.
1355e5dd7070Spatrick return FormatTok->is(tok::identifier) &&
1356e5dd7070Spatrick (FormatTok->Tok.getIdentifierInfo() == nullptr ||
1357e5dd7070Spatrick !FormatTok->isOneOf(
1358e5dd7070Spatrick Keywords.kw_in, Keywords.kw_of, Keywords.kw_as, Keywords.kw_async,
1359e5dd7070Spatrick Keywords.kw_await, Keywords.kw_yield, Keywords.kw_finally,
1360e5dd7070Spatrick Keywords.kw_function, Keywords.kw_import, Keywords.kw_is,
1361e5dd7070Spatrick Keywords.kw_let, Keywords.kw_var, tok::kw_const,
1362e5dd7070Spatrick Keywords.kw_abstract, Keywords.kw_extends, Keywords.kw_implements,
1363*12c85518Srobert Keywords.kw_instanceof, Keywords.kw_interface,
1364*12c85518Srobert Keywords.kw_override, Keywords.kw_throws, Keywords.kw_from));
1365e5dd7070Spatrick }
1366e5dd7070Spatrick
mustBeJSIdentOrValue(const AdditionalKeywords & Keywords,const FormatToken * FormatTok)1367e5dd7070Spatrick static bool mustBeJSIdentOrValue(const AdditionalKeywords &Keywords,
1368e5dd7070Spatrick const FormatToken *FormatTok) {
1369e5dd7070Spatrick return FormatTok->Tok.isLiteral() ||
1370e5dd7070Spatrick FormatTok->isOneOf(tok::kw_true, tok::kw_false) ||
1371e5dd7070Spatrick mustBeJSIdent(Keywords, FormatTok);
1372e5dd7070Spatrick }
1373e5dd7070Spatrick
1374e5dd7070Spatrick // isJSDeclOrStmt returns true if |FormatTok| starts a declaration or statement
1375e5dd7070Spatrick // when encountered after a value (see mustBeJSIdentOrValue).
isJSDeclOrStmt(const AdditionalKeywords & Keywords,const FormatToken * FormatTok)1376e5dd7070Spatrick static bool isJSDeclOrStmt(const AdditionalKeywords &Keywords,
1377e5dd7070Spatrick const FormatToken *FormatTok) {
1378e5dd7070Spatrick return FormatTok->isOneOf(
1379e5dd7070Spatrick tok::kw_return, Keywords.kw_yield,
1380e5dd7070Spatrick // conditionals
1381e5dd7070Spatrick tok::kw_if, tok::kw_else,
1382e5dd7070Spatrick // loops
1383e5dd7070Spatrick tok::kw_for, tok::kw_while, tok::kw_do, tok::kw_continue, tok::kw_break,
1384e5dd7070Spatrick // switch/case
1385e5dd7070Spatrick tok::kw_switch, tok::kw_case,
1386e5dd7070Spatrick // exceptions
1387e5dd7070Spatrick tok::kw_throw, tok::kw_try, tok::kw_catch, Keywords.kw_finally,
1388e5dd7070Spatrick // declaration
1389e5dd7070Spatrick tok::kw_const, tok::kw_class, Keywords.kw_var, Keywords.kw_let,
1390e5dd7070Spatrick Keywords.kw_async, Keywords.kw_function,
1391e5dd7070Spatrick // import/export
1392e5dd7070Spatrick Keywords.kw_import, tok::kw_export);
1393e5dd7070Spatrick }
1394e5dd7070Spatrick
1395a9ac8606Spatrick // Checks whether a token is a type in K&R C (aka C78).
isC78Type(const FormatToken & Tok)1396a9ac8606Spatrick static bool isC78Type(const FormatToken &Tok) {
1397a9ac8606Spatrick return Tok.isOneOf(tok::kw_char, tok::kw_short, tok::kw_int, tok::kw_long,
1398a9ac8606Spatrick tok::kw_unsigned, tok::kw_float, tok::kw_double,
1399a9ac8606Spatrick tok::identifier);
1400a9ac8606Spatrick }
1401a9ac8606Spatrick
1402a9ac8606Spatrick // This function checks whether a token starts the first parameter declaration
1403a9ac8606Spatrick // in a K&R C (aka C78) function definition, e.g.:
1404a9ac8606Spatrick // int f(a, b)
1405a9ac8606Spatrick // short a, b;
1406a9ac8606Spatrick // {
1407a9ac8606Spatrick // return a + b;
1408a9ac8606Spatrick // }
isC78ParameterDecl(const FormatToken * Tok,const FormatToken * Next,const FormatToken * FuncName)1409a9ac8606Spatrick static bool isC78ParameterDecl(const FormatToken *Tok, const FormatToken *Next,
1410a9ac8606Spatrick const FormatToken *FuncName) {
1411a9ac8606Spatrick assert(Tok);
1412a9ac8606Spatrick assert(Next);
1413a9ac8606Spatrick assert(FuncName);
1414a9ac8606Spatrick
1415a9ac8606Spatrick if (FuncName->isNot(tok::identifier))
1416a9ac8606Spatrick return false;
1417a9ac8606Spatrick
1418a9ac8606Spatrick const FormatToken *Prev = FuncName->Previous;
1419a9ac8606Spatrick if (!Prev || (Prev->isNot(tok::star) && !isC78Type(*Prev)))
1420a9ac8606Spatrick return false;
1421a9ac8606Spatrick
1422a9ac8606Spatrick if (!isC78Type(*Tok) &&
1423*12c85518Srobert !Tok->isOneOf(tok::kw_register, tok::kw_struct, tok::kw_union)) {
1424a9ac8606Spatrick return false;
1425*12c85518Srobert }
1426a9ac8606Spatrick
1427a9ac8606Spatrick if (Next->isNot(tok::star) && !Next->Tok.getIdentifierInfo())
1428a9ac8606Spatrick return false;
1429a9ac8606Spatrick
1430a9ac8606Spatrick Tok = Tok->Previous;
1431a9ac8606Spatrick if (!Tok || Tok->isNot(tok::r_paren))
1432a9ac8606Spatrick return false;
1433a9ac8606Spatrick
1434a9ac8606Spatrick Tok = Tok->Previous;
1435a9ac8606Spatrick if (!Tok || Tok->isNot(tok::identifier))
1436a9ac8606Spatrick return false;
1437a9ac8606Spatrick
1438a9ac8606Spatrick return Tok->Previous && Tok->Previous->isOneOf(tok::l_paren, tok::comma);
1439a9ac8606Spatrick }
1440a9ac8606Spatrick
parseModuleImport()1441*12c85518Srobert bool UnwrappedLineParser::parseModuleImport() {
1442*12c85518Srobert assert(FormatTok->is(Keywords.kw_import) && "'import' expected");
1443*12c85518Srobert
1444*12c85518Srobert if (auto Token = Tokens->peekNextToken(/*SkipComment=*/true);
1445*12c85518Srobert !Token->Tok.getIdentifierInfo() &&
1446*12c85518Srobert !Token->isOneOf(tok::colon, tok::less, tok::string_literal)) {
1447*12c85518Srobert return false;
1448*12c85518Srobert }
1449*12c85518Srobert
1450*12c85518Srobert nextToken();
1451*12c85518Srobert while (!eof()) {
1452*12c85518Srobert if (FormatTok->is(tok::colon)) {
1453*12c85518Srobert FormatTok->setFinalizedType(TT_ModulePartitionColon);
1454*12c85518Srobert }
1455*12c85518Srobert // Handle import <foo/bar.h> as we would an include statement.
1456*12c85518Srobert else if (FormatTok->is(tok::less)) {
1457*12c85518Srobert nextToken();
1458*12c85518Srobert while (!FormatTok->isOneOf(tok::semi, tok::greater, tok::eof)) {
1459*12c85518Srobert // Mark tokens up to the trailing line comments as implicit string
1460*12c85518Srobert // literals.
1461*12c85518Srobert if (FormatTok->isNot(tok::comment) &&
1462*12c85518Srobert !FormatTok->TokenText.startswith("//")) {
1463*12c85518Srobert FormatTok->setFinalizedType(TT_ImplicitStringLiteral);
1464*12c85518Srobert }
1465*12c85518Srobert nextToken();
1466*12c85518Srobert }
1467*12c85518Srobert }
1468*12c85518Srobert if (FormatTok->is(tok::semi)) {
1469*12c85518Srobert nextToken();
1470*12c85518Srobert break;
1471*12c85518Srobert }
1472*12c85518Srobert nextToken();
1473*12c85518Srobert }
1474*12c85518Srobert
1475*12c85518Srobert addUnwrappedLine();
1476*12c85518Srobert return true;
1477*12c85518Srobert }
1478*12c85518Srobert
1479e5dd7070Spatrick // readTokenWithJavaScriptASI reads the next token and terminates the current
1480e5dd7070Spatrick // line if JavaScript Automatic Semicolon Insertion must
1481e5dd7070Spatrick // happen between the current token and the next token.
1482e5dd7070Spatrick //
1483e5dd7070Spatrick // This method is conservative - it cannot cover all edge cases of JavaScript,
1484e5dd7070Spatrick // but only aims to correctly handle certain well known cases. It *must not*
1485e5dd7070Spatrick // return true in speculative cases.
readTokenWithJavaScriptASI()1486e5dd7070Spatrick void UnwrappedLineParser::readTokenWithJavaScriptASI() {
1487e5dd7070Spatrick FormatToken *Previous = FormatTok;
1488e5dd7070Spatrick readToken();
1489e5dd7070Spatrick FormatToken *Next = FormatTok;
1490e5dd7070Spatrick
1491e5dd7070Spatrick bool IsOnSameLine =
1492e5dd7070Spatrick CommentsBeforeNextToken.empty()
1493e5dd7070Spatrick ? Next->NewlinesBefore == 0
1494e5dd7070Spatrick : CommentsBeforeNextToken.front()->NewlinesBefore == 0;
1495e5dd7070Spatrick if (IsOnSameLine)
1496e5dd7070Spatrick return;
1497e5dd7070Spatrick
1498e5dd7070Spatrick bool PreviousMustBeValue = mustBeJSIdentOrValue(Keywords, Previous);
1499e5dd7070Spatrick bool PreviousStartsTemplateExpr =
1500e5dd7070Spatrick Previous->is(TT_TemplateString) && Previous->TokenText.endswith("${");
1501e5dd7070Spatrick if (PreviousMustBeValue || Previous->is(tok::r_paren)) {
1502e5dd7070Spatrick // If the line contains an '@' sign, the previous token might be an
1503e5dd7070Spatrick // annotation, which can precede another identifier/value.
1504*12c85518Srobert bool HasAt = llvm::any_of(Line->Tokens, [](UnwrappedLineNode &LineNode) {
1505e5dd7070Spatrick return LineNode.Tok->is(tok::at);
1506*12c85518Srobert });
1507e5dd7070Spatrick if (HasAt)
1508e5dd7070Spatrick return;
1509e5dd7070Spatrick }
1510e5dd7070Spatrick if (Next->is(tok::exclaim) && PreviousMustBeValue)
1511e5dd7070Spatrick return addUnwrappedLine();
1512e5dd7070Spatrick bool NextMustBeValue = mustBeJSIdentOrValue(Keywords, Next);
1513e5dd7070Spatrick bool NextEndsTemplateExpr =
1514e5dd7070Spatrick Next->is(TT_TemplateString) && Next->TokenText.startswith("}");
1515e5dd7070Spatrick if (NextMustBeValue && !NextEndsTemplateExpr && !PreviousStartsTemplateExpr &&
1516e5dd7070Spatrick (PreviousMustBeValue ||
1517e5dd7070Spatrick Previous->isOneOf(tok::r_square, tok::r_paren, tok::plusplus,
1518*12c85518Srobert tok::minusminus))) {
1519e5dd7070Spatrick return addUnwrappedLine();
1520e5dd7070Spatrick }
1521*12c85518Srobert if ((PreviousMustBeValue || Previous->is(tok::r_paren)) &&
1522*12c85518Srobert isJSDeclOrStmt(Keywords, Next)) {
1523*12c85518Srobert return addUnwrappedLine();
1524*12c85518Srobert }
1525*12c85518Srobert }
1526e5dd7070Spatrick
parseStructuralElement(bool IsTopLevel,TokenType NextLBracesType,IfStmtKind * IfKind,FormatToken ** IfLeftBrace,bool * HasDoWhile,bool * HasLabel)1527*12c85518Srobert void UnwrappedLineParser::parseStructuralElement(
1528*12c85518Srobert bool IsTopLevel, TokenType NextLBracesType, IfStmtKind *IfKind,
1529*12c85518Srobert FormatToken **IfLeftBrace, bool *HasDoWhile, bool *HasLabel) {
1530e5dd7070Spatrick if (Style.Language == FormatStyle::LK_TableGen &&
1531e5dd7070Spatrick FormatTok->is(tok::pp_include)) {
1532e5dd7070Spatrick nextToken();
1533e5dd7070Spatrick if (FormatTok->is(tok::string_literal))
1534e5dd7070Spatrick nextToken();
1535e5dd7070Spatrick addUnwrappedLine();
1536e5dd7070Spatrick return;
1537e5dd7070Spatrick }
1538*12c85518Srobert
1539*12c85518Srobert if (Style.isVerilog()) {
1540*12c85518Srobert // Skip things that can exist before keywords like 'if' and 'case'.
1541*12c85518Srobert while (true) {
1542*12c85518Srobert if (FormatTok->isOneOf(Keywords.kw_priority, Keywords.kw_unique,
1543*12c85518Srobert Keywords.kw_unique0)) {
1544*12c85518Srobert nextToken();
1545*12c85518Srobert } else if (FormatTok->is(tok::l_paren) &&
1546*12c85518Srobert Tokens->peekNextToken()->is(tok::star)) {
1547*12c85518Srobert parseParens();
1548*12c85518Srobert } else {
1549*12c85518Srobert break;
1550*12c85518Srobert }
1551*12c85518Srobert }
1552*12c85518Srobert }
1553*12c85518Srobert
1554*12c85518Srobert // Tokens that only make sense at the beginning of a line.
1555e5dd7070Spatrick switch (FormatTok->Tok.getKind()) {
1556e5dd7070Spatrick case tok::kw_asm:
1557e5dd7070Spatrick nextToken();
1558e5dd7070Spatrick if (FormatTok->is(tok::l_brace)) {
1559*12c85518Srobert FormatTok->setFinalizedType(TT_InlineASMBrace);
1560e5dd7070Spatrick nextToken();
1561*12c85518Srobert while (FormatTok && !eof()) {
1562e5dd7070Spatrick if (FormatTok->is(tok::r_brace)) {
1563*12c85518Srobert FormatTok->setFinalizedType(TT_InlineASMBrace);
1564e5dd7070Spatrick nextToken();
1565e5dd7070Spatrick addUnwrappedLine();
1566e5dd7070Spatrick break;
1567e5dd7070Spatrick }
1568e5dd7070Spatrick FormatTok->Finalized = true;
1569e5dd7070Spatrick nextToken();
1570e5dd7070Spatrick }
1571e5dd7070Spatrick }
1572e5dd7070Spatrick break;
1573e5dd7070Spatrick case tok::kw_namespace:
1574e5dd7070Spatrick parseNamespace();
1575e5dd7070Spatrick return;
1576e5dd7070Spatrick case tok::kw_public:
1577e5dd7070Spatrick case tok::kw_protected:
1578e5dd7070Spatrick case tok::kw_private:
1579*12c85518Srobert if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript() ||
1580*12c85518Srobert Style.isCSharp()) {
1581e5dd7070Spatrick nextToken();
1582*12c85518Srobert } else {
1583e5dd7070Spatrick parseAccessSpecifier();
1584*12c85518Srobert }
1585e5dd7070Spatrick return;
1586*12c85518Srobert case tok::kw_if: {
1587*12c85518Srobert if (Style.isJavaScript() && Line->MustBeDeclaration) {
1588ec727ea7Spatrick // field/method declaration.
1589ec727ea7Spatrick break;
1590*12c85518Srobert }
1591*12c85518Srobert FormatToken *Tok = parseIfThenElse(IfKind);
1592*12c85518Srobert if (IfLeftBrace)
1593*12c85518Srobert *IfLeftBrace = Tok;
1594e5dd7070Spatrick return;
1595*12c85518Srobert }
1596e5dd7070Spatrick case tok::kw_for:
1597e5dd7070Spatrick case tok::kw_while:
1598*12c85518Srobert if (Style.isJavaScript() && Line->MustBeDeclaration) {
1599ec727ea7Spatrick // field/method declaration.
1600ec727ea7Spatrick break;
1601*12c85518Srobert }
1602e5dd7070Spatrick parseForOrWhileLoop();
1603e5dd7070Spatrick return;
1604e5dd7070Spatrick case tok::kw_do:
1605*12c85518Srobert if (Style.isJavaScript() && Line->MustBeDeclaration) {
1606ec727ea7Spatrick // field/method declaration.
1607ec727ea7Spatrick break;
1608*12c85518Srobert }
1609e5dd7070Spatrick parseDoWhile();
1610*12c85518Srobert if (HasDoWhile)
1611*12c85518Srobert *HasDoWhile = true;
1612e5dd7070Spatrick return;
1613e5dd7070Spatrick case tok::kw_switch:
1614*12c85518Srobert if (Style.isJavaScript() && Line->MustBeDeclaration) {
1615e5dd7070Spatrick // 'switch: string' field declaration.
1616e5dd7070Spatrick break;
1617*12c85518Srobert }
1618e5dd7070Spatrick parseSwitch();
1619e5dd7070Spatrick return;
1620e5dd7070Spatrick case tok::kw_default:
1621*12c85518Srobert // In Verilog default along with other labels are handled in the next loop.
1622*12c85518Srobert if (Style.isVerilog())
1623*12c85518Srobert break;
1624*12c85518Srobert if (Style.isJavaScript() && Line->MustBeDeclaration) {
1625e5dd7070Spatrick // 'default: string' field declaration.
1626e5dd7070Spatrick break;
1627*12c85518Srobert }
1628e5dd7070Spatrick nextToken();
1629e5dd7070Spatrick if (FormatTok->is(tok::colon)) {
1630e5dd7070Spatrick parseLabel();
1631e5dd7070Spatrick return;
1632e5dd7070Spatrick }
1633e5dd7070Spatrick // e.g. "default void f() {}" in a Java interface.
1634e5dd7070Spatrick break;
1635e5dd7070Spatrick case tok::kw_case:
1636*12c85518Srobert // Proto: there are no switch/case statements.
1637*12c85518Srobert if (Style.isProto()) {
1638*12c85518Srobert nextToken();
1639*12c85518Srobert return;
1640*12c85518Srobert }
1641*12c85518Srobert if (Style.isVerilog()) {
1642*12c85518Srobert parseBlock();
1643*12c85518Srobert addUnwrappedLine();
1644*12c85518Srobert return;
1645*12c85518Srobert }
1646*12c85518Srobert if (Style.isJavaScript() && Line->MustBeDeclaration) {
1647e5dd7070Spatrick // 'case: string' field declaration.
1648*12c85518Srobert nextToken();
1649e5dd7070Spatrick break;
1650*12c85518Srobert }
1651e5dd7070Spatrick parseCaseLabel();
1652e5dd7070Spatrick return;
1653e5dd7070Spatrick case tok::kw_try:
1654e5dd7070Spatrick case tok::kw___try:
1655*12c85518Srobert if (Style.isJavaScript() && Line->MustBeDeclaration) {
1656ec727ea7Spatrick // field/method declaration.
1657ec727ea7Spatrick break;
1658*12c85518Srobert }
1659e5dd7070Spatrick parseTryCatch();
1660e5dd7070Spatrick return;
1661e5dd7070Spatrick case tok::kw_extern:
1662e5dd7070Spatrick nextToken();
1663*12c85518Srobert if (Style.isVerilog()) {
1664*12c85518Srobert // In Verilog and extern module declaration looks like a start of module.
1665*12c85518Srobert // But there is no body and endmodule. So we handle it separately.
1666*12c85518Srobert if (Keywords.isVerilogHierarchy(*FormatTok)) {
1667*12c85518Srobert parseVerilogHierarchyHeader();
1668*12c85518Srobert return;
1669*12c85518Srobert }
1670*12c85518Srobert } else if (FormatTok->is(tok::string_literal)) {
1671e5dd7070Spatrick nextToken();
1672*12c85518Srobert if (FormatTok->is(tok::l_brace)) {
1673*12c85518Srobert if (Style.BraceWrapping.AfterExternBlock)
1674e5dd7070Spatrick addUnwrappedLine();
1675*12c85518Srobert // Either we indent or for backwards compatibility we follow the
1676*12c85518Srobert // AfterExternBlock style.
1677a9ac8606Spatrick unsigned AddLevels =
1678*12c85518Srobert (Style.IndentExternBlock == FormatStyle::IEBS_Indent) ||
1679*12c85518Srobert (Style.BraceWrapping.AfterExternBlock &&
1680*12c85518Srobert Style.IndentExternBlock ==
1681*12c85518Srobert FormatStyle::IEBS_AfterExternBlock)
1682*12c85518Srobert ? 1u
1683*12c85518Srobert : 0u;
1684a9ac8606Spatrick parseBlock(/*MustBeDeclaration=*/true, AddLevels);
1685e5dd7070Spatrick addUnwrappedLine();
1686e5dd7070Spatrick return;
1687e5dd7070Spatrick }
1688e5dd7070Spatrick }
1689e5dd7070Spatrick break;
1690e5dd7070Spatrick case tok::kw_export:
1691*12c85518Srobert if (Style.isJavaScript()) {
1692e5dd7070Spatrick parseJavaScriptEs6ImportExport();
1693e5dd7070Spatrick return;
1694e5dd7070Spatrick }
1695*12c85518Srobert if (Style.isCpp()) {
1696*12c85518Srobert nextToken();
1697*12c85518Srobert if (FormatTok->is(tok::kw_namespace)) {
1698*12c85518Srobert parseNamespace();
1699*12c85518Srobert return;
1700*12c85518Srobert }
1701*12c85518Srobert if (FormatTok->is(Keywords.kw_import) && parseModuleImport())
1702*12c85518Srobert return;
1703*12c85518Srobert }
1704e5dd7070Spatrick break;
1705e5dd7070Spatrick case tok::kw_inline:
1706e5dd7070Spatrick nextToken();
1707*12c85518Srobert if (FormatTok->is(tok::kw_namespace)) {
1708e5dd7070Spatrick parseNamespace();
1709e5dd7070Spatrick return;
1710e5dd7070Spatrick }
1711e5dd7070Spatrick break;
1712e5dd7070Spatrick case tok::identifier:
1713e5dd7070Spatrick if (FormatTok->is(TT_ForEachMacro)) {
1714e5dd7070Spatrick parseForOrWhileLoop();
1715e5dd7070Spatrick return;
1716e5dd7070Spatrick }
1717e5dd7070Spatrick if (FormatTok->is(TT_MacroBlockBegin)) {
1718a9ac8606Spatrick parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,
1719e5dd7070Spatrick /*MunchSemi=*/false);
1720e5dd7070Spatrick return;
1721e5dd7070Spatrick }
1722e5dd7070Spatrick if (FormatTok->is(Keywords.kw_import)) {
1723*12c85518Srobert if (Style.isJavaScript()) {
1724e5dd7070Spatrick parseJavaScriptEs6ImportExport();
1725e5dd7070Spatrick return;
1726e5dd7070Spatrick }
1727e5dd7070Spatrick if (Style.Language == FormatStyle::LK_Proto) {
1728e5dd7070Spatrick nextToken();
1729e5dd7070Spatrick if (FormatTok->is(tok::kw_public))
1730e5dd7070Spatrick nextToken();
1731e5dd7070Spatrick if (!FormatTok->is(tok::string_literal))
1732e5dd7070Spatrick return;
1733e5dd7070Spatrick nextToken();
1734e5dd7070Spatrick if (FormatTok->is(tok::semi))
1735e5dd7070Spatrick nextToken();
1736e5dd7070Spatrick addUnwrappedLine();
1737e5dd7070Spatrick return;
1738e5dd7070Spatrick }
1739*12c85518Srobert if (Style.isCpp() && parseModuleImport())
1740*12c85518Srobert return;
1741e5dd7070Spatrick }
1742e5dd7070Spatrick if (Style.isCpp() &&
1743e5dd7070Spatrick FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
1744e5dd7070Spatrick Keywords.kw_slots, Keywords.kw_qslots)) {
1745e5dd7070Spatrick nextToken();
1746e5dd7070Spatrick if (FormatTok->is(tok::colon)) {
1747e5dd7070Spatrick nextToken();
1748e5dd7070Spatrick addUnwrappedLine();
1749e5dd7070Spatrick return;
1750e5dd7070Spatrick }
1751e5dd7070Spatrick }
1752e5dd7070Spatrick if (Style.isCpp() && FormatTok->is(TT_StatementMacro)) {
1753e5dd7070Spatrick parseStatementMacro();
1754e5dd7070Spatrick return;
1755e5dd7070Spatrick }
1756e5dd7070Spatrick if (Style.isCpp() && FormatTok->is(TT_NamespaceMacro)) {
1757e5dd7070Spatrick parseNamespace();
1758e5dd7070Spatrick return;
1759e5dd7070Spatrick }
1760e5dd7070Spatrick // In all other cases, parse the declaration.
1761e5dd7070Spatrick break;
1762e5dd7070Spatrick default:
1763e5dd7070Spatrick break;
1764e5dd7070Spatrick }
1765e5dd7070Spatrick do {
1766e5dd7070Spatrick const FormatToken *Previous = FormatTok->Previous;
1767e5dd7070Spatrick switch (FormatTok->Tok.getKind()) {
1768e5dd7070Spatrick case tok::at:
1769e5dd7070Spatrick nextToken();
1770*12c85518Srobert if (FormatTok->is(tok::l_brace)) {
1771e5dd7070Spatrick nextToken();
1772e5dd7070Spatrick parseBracedList();
1773e5dd7070Spatrick break;
1774e5dd7070Spatrick } else if (Style.Language == FormatStyle::LK_Java &&
1775e5dd7070Spatrick FormatTok->is(Keywords.kw_interface)) {
1776e5dd7070Spatrick nextToken();
1777e5dd7070Spatrick break;
1778e5dd7070Spatrick }
1779e5dd7070Spatrick switch (FormatTok->Tok.getObjCKeywordID()) {
1780e5dd7070Spatrick case tok::objc_public:
1781e5dd7070Spatrick case tok::objc_protected:
1782e5dd7070Spatrick case tok::objc_package:
1783e5dd7070Spatrick case tok::objc_private:
1784e5dd7070Spatrick return parseAccessSpecifier();
1785e5dd7070Spatrick case tok::objc_interface:
1786e5dd7070Spatrick case tok::objc_implementation:
1787e5dd7070Spatrick return parseObjCInterfaceOrImplementation();
1788e5dd7070Spatrick case tok::objc_protocol:
1789e5dd7070Spatrick if (parseObjCProtocol())
1790e5dd7070Spatrick return;
1791e5dd7070Spatrick break;
1792e5dd7070Spatrick case tok::objc_end:
1793e5dd7070Spatrick return; // Handled by the caller.
1794e5dd7070Spatrick case tok::objc_optional:
1795e5dd7070Spatrick case tok::objc_required:
1796e5dd7070Spatrick nextToken();
1797e5dd7070Spatrick addUnwrappedLine();
1798e5dd7070Spatrick return;
1799e5dd7070Spatrick case tok::objc_autoreleasepool:
1800e5dd7070Spatrick nextToken();
1801*12c85518Srobert if (FormatTok->is(tok::l_brace)) {
1802e5dd7070Spatrick if (Style.BraceWrapping.AfterControlStatement ==
1803*12c85518Srobert FormatStyle::BWACS_Always) {
1804e5dd7070Spatrick addUnwrappedLine();
1805*12c85518Srobert }
1806*12c85518Srobert parseBlock();
1807e5dd7070Spatrick }
1808e5dd7070Spatrick addUnwrappedLine();
1809e5dd7070Spatrick return;
1810e5dd7070Spatrick case tok::objc_synchronized:
1811e5dd7070Spatrick nextToken();
1812*12c85518Srobert if (FormatTok->is(tok::l_paren)) {
1813e5dd7070Spatrick // Skip synchronization object
1814e5dd7070Spatrick parseParens();
1815*12c85518Srobert }
1816*12c85518Srobert if (FormatTok->is(tok::l_brace)) {
1817e5dd7070Spatrick if (Style.BraceWrapping.AfterControlStatement ==
1818*12c85518Srobert FormatStyle::BWACS_Always) {
1819e5dd7070Spatrick addUnwrappedLine();
1820*12c85518Srobert }
1821*12c85518Srobert parseBlock();
1822e5dd7070Spatrick }
1823e5dd7070Spatrick addUnwrappedLine();
1824e5dd7070Spatrick return;
1825e5dd7070Spatrick case tok::objc_try:
1826e5dd7070Spatrick // This branch isn't strictly necessary (the kw_try case below would
1827e5dd7070Spatrick // do this too after the tok::at is parsed above). But be explicit.
1828e5dd7070Spatrick parseTryCatch();
1829e5dd7070Spatrick return;
1830e5dd7070Spatrick default:
1831e5dd7070Spatrick break;
1832e5dd7070Spatrick }
1833e5dd7070Spatrick break;
1834*12c85518Srobert case tok::kw_requires: {
1835*12c85518Srobert if (Style.isCpp()) {
1836*12c85518Srobert bool ParsedClause = parseRequires();
1837*12c85518Srobert if (ParsedClause)
1838*12c85518Srobert return;
1839*12c85518Srobert } else {
1840*12c85518Srobert nextToken();
1841*12c85518Srobert }
1842a9ac8606Spatrick break;
1843*12c85518Srobert }
1844e5dd7070Spatrick case tok::kw_enum:
1845e5dd7070Spatrick // Ignore if this is part of "template <enum ...".
1846e5dd7070Spatrick if (Previous && Previous->is(tok::less)) {
1847e5dd7070Spatrick nextToken();
1848e5dd7070Spatrick break;
1849e5dd7070Spatrick }
1850e5dd7070Spatrick
1851e5dd7070Spatrick // parseEnum falls through and does not yet add an unwrapped line as an
1852e5dd7070Spatrick // enum definition can start a structural element.
1853e5dd7070Spatrick if (!parseEnum())
1854e5dd7070Spatrick break;
1855e5dd7070Spatrick // This only applies for C++.
1856e5dd7070Spatrick if (!Style.isCpp()) {
1857e5dd7070Spatrick addUnwrappedLine();
1858e5dd7070Spatrick return;
1859e5dd7070Spatrick }
1860e5dd7070Spatrick break;
1861e5dd7070Spatrick case tok::kw_typedef:
1862e5dd7070Spatrick nextToken();
1863e5dd7070Spatrick if (FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS,
1864e5dd7070Spatrick Keywords.kw_CF_ENUM, Keywords.kw_CF_OPTIONS,
1865e5dd7070Spatrick Keywords.kw_CF_CLOSED_ENUM,
1866*12c85518Srobert Keywords.kw_NS_CLOSED_ENUM)) {
1867e5dd7070Spatrick parseEnum();
1868*12c85518Srobert }
1869e5dd7070Spatrick break;
1870e5dd7070Spatrick case tok::kw_class:
1871*12c85518Srobert if (Style.isVerilog()) {
1872*12c85518Srobert parseBlock();
1873*12c85518Srobert addUnwrappedLine();
1874e5dd7070Spatrick return;
1875e5dd7070Spatrick }
1876*12c85518Srobert [[fallthrough]];
1877*12c85518Srobert case tok::kw_struct:
1878*12c85518Srobert case tok::kw_union:
1879*12c85518Srobert if (parseStructLike())
1880*12c85518Srobert return;
1881e5dd7070Spatrick break;
1882e5dd7070Spatrick case tok::period:
1883e5dd7070Spatrick nextToken();
1884e5dd7070Spatrick // In Java, classes have an implicit static member "class".
1885e5dd7070Spatrick if (Style.Language == FormatStyle::LK_Java && FormatTok &&
1886*12c85518Srobert FormatTok->is(tok::kw_class)) {
1887e5dd7070Spatrick nextToken();
1888*12c85518Srobert }
1889*12c85518Srobert if (Style.isJavaScript() && FormatTok &&
1890*12c85518Srobert FormatTok->Tok.getIdentifierInfo()) {
1891e5dd7070Spatrick // JavaScript only has pseudo keywords, all keywords are allowed to
1892e5dd7070Spatrick // appear in "IdentifierName" positions. See http://es5.github.io/#x7.6
1893e5dd7070Spatrick nextToken();
1894*12c85518Srobert }
1895e5dd7070Spatrick break;
1896e5dd7070Spatrick case tok::semi:
1897e5dd7070Spatrick nextToken();
1898e5dd7070Spatrick addUnwrappedLine();
1899e5dd7070Spatrick return;
1900e5dd7070Spatrick case tok::r_brace:
1901e5dd7070Spatrick addUnwrappedLine();
1902e5dd7070Spatrick return;
1903a9ac8606Spatrick case tok::l_paren: {
1904e5dd7070Spatrick parseParens();
1905a9ac8606Spatrick // Break the unwrapped line if a K&R C function definition has a parameter
1906a9ac8606Spatrick // declaration.
1907*12c85518Srobert if (!IsTopLevel || !Style.isCpp() || !Previous || eof())
1908e5dd7070Spatrick break;
1909*12c85518Srobert if (isC78ParameterDecl(FormatTok,
1910*12c85518Srobert Tokens->peekNextToken(/*SkipComment=*/true),
1911*12c85518Srobert Previous)) {
1912a9ac8606Spatrick addUnwrappedLine();
1913a9ac8606Spatrick return;
1914a9ac8606Spatrick }
1915a9ac8606Spatrick break;
1916a9ac8606Spatrick }
1917e5dd7070Spatrick case tok::kw_operator:
1918e5dd7070Spatrick nextToken();
1919e5dd7070Spatrick if (FormatTok->isBinaryOperator())
1920e5dd7070Spatrick nextToken();
1921e5dd7070Spatrick break;
1922e5dd7070Spatrick case tok::caret:
1923e5dd7070Spatrick nextToken();
1924e5dd7070Spatrick if (FormatTok->Tok.isAnyIdentifier() ||
1925*12c85518Srobert FormatTok->isSimpleTypeSpecifier()) {
1926e5dd7070Spatrick nextToken();
1927*12c85518Srobert }
1928e5dd7070Spatrick if (FormatTok->is(tok::l_paren))
1929e5dd7070Spatrick parseParens();
1930e5dd7070Spatrick if (FormatTok->is(tok::l_brace))
1931e5dd7070Spatrick parseChildBlock();
1932e5dd7070Spatrick break;
1933e5dd7070Spatrick case tok::l_brace:
1934*12c85518Srobert if (NextLBracesType != TT_Unknown)
1935*12c85518Srobert FormatTok->setFinalizedType(NextLBracesType);
1936ec727ea7Spatrick if (!tryToParsePropertyAccessor() && !tryToParseBracedList()) {
1937e5dd7070Spatrick // A block outside of parentheses must be the last part of a
1938e5dd7070Spatrick // structural element.
1939e5dd7070Spatrick // FIXME: Figure out cases where this is not true, and add projections
1940e5dd7070Spatrick // for them (the one we know is missing are lambdas).
1941*12c85518Srobert if (Style.Language == FormatStyle::LK_Java &&
1942*12c85518Srobert Line->Tokens.front().Tok->is(Keywords.kw_synchronized)) {
1943*12c85518Srobert // If necessary, we could set the type to something different than
1944*12c85518Srobert // TT_FunctionLBrace.
1945*12c85518Srobert if (Style.BraceWrapping.AfterControlStatement ==
1946*12c85518Srobert FormatStyle::BWACS_Always) {
1947e5dd7070Spatrick addUnwrappedLine();
1948*12c85518Srobert }
1949*12c85518Srobert } else if (Style.BraceWrapping.AfterFunction) {
1950*12c85518Srobert addUnwrappedLine();
1951*12c85518Srobert }
1952*12c85518Srobert FormatTok->setFinalizedType(TT_FunctionLBrace);
1953*12c85518Srobert parseBlock();
1954e5dd7070Spatrick addUnwrappedLine();
1955e5dd7070Spatrick return;
1956e5dd7070Spatrick }
1957e5dd7070Spatrick // Otherwise this was a braced init list, and the structural
1958e5dd7070Spatrick // element continues.
1959e5dd7070Spatrick break;
1960e5dd7070Spatrick case tok::kw_try:
1961*12c85518Srobert if (Style.isJavaScript() && Line->MustBeDeclaration) {
1962ec727ea7Spatrick // field/method declaration.
1963ec727ea7Spatrick nextToken();
1964ec727ea7Spatrick break;
1965ec727ea7Spatrick }
1966e5dd7070Spatrick // We arrive here when parsing function-try blocks.
1967e5dd7070Spatrick if (Style.BraceWrapping.AfterFunction)
1968e5dd7070Spatrick addUnwrappedLine();
1969e5dd7070Spatrick parseTryCatch();
1970e5dd7070Spatrick return;
1971e5dd7070Spatrick case tok::identifier: {
1972ec727ea7Spatrick if (Style.isCSharp() && FormatTok->is(Keywords.kw_where) &&
1973ec727ea7Spatrick Line->MustBeDeclaration) {
1974ec727ea7Spatrick addUnwrappedLine();
1975ec727ea7Spatrick parseCSharpGenericTypeConstraint();
1976ec727ea7Spatrick break;
1977ec727ea7Spatrick }
1978e5dd7070Spatrick if (FormatTok->is(TT_MacroBlockEnd)) {
1979e5dd7070Spatrick addUnwrappedLine();
1980e5dd7070Spatrick return;
1981e5dd7070Spatrick }
1982e5dd7070Spatrick
1983e5dd7070Spatrick // Function declarations (as opposed to function expressions) are parsed
1984e5dd7070Spatrick // on their own unwrapped line by continuing this loop. Function
1985e5dd7070Spatrick // expressions (functions that are not on their own line) must not create
1986e5dd7070Spatrick // a new unwrapped line, so they are special cased below.
1987e5dd7070Spatrick size_t TokenCount = Line->Tokens.size();
1988*12c85518Srobert if (Style.isJavaScript() && FormatTok->is(Keywords.kw_function) &&
1989e5dd7070Spatrick (TokenCount > 1 || (TokenCount == 1 && !Line->Tokens.front().Tok->is(
1990e5dd7070Spatrick Keywords.kw_async)))) {
1991e5dd7070Spatrick tryToParseJSFunction();
1992e5dd7070Spatrick break;
1993e5dd7070Spatrick }
1994*12c85518Srobert if ((Style.isJavaScript() || Style.Language == FormatStyle::LK_Java) &&
1995e5dd7070Spatrick FormatTok->is(Keywords.kw_interface)) {
1996*12c85518Srobert if (Style.isJavaScript()) {
1997e5dd7070Spatrick // In JavaScript/TypeScript, "interface" can be used as a standalone
1998e5dd7070Spatrick // identifier, e.g. in `var interface = 1;`. If "interface" is
1999e5dd7070Spatrick // followed by another identifier, it is very like to be an actual
2000e5dd7070Spatrick // interface declaration.
2001e5dd7070Spatrick unsigned StoredPosition = Tokens->getPosition();
2002e5dd7070Spatrick FormatToken *Next = Tokens->getNextToken();
2003e5dd7070Spatrick FormatTok = Tokens->setPosition(StoredPosition);
2004*12c85518Srobert if (!mustBeJSIdent(Keywords, Next)) {
2005e5dd7070Spatrick nextToken();
2006e5dd7070Spatrick break;
2007e5dd7070Spatrick }
2008e5dd7070Spatrick }
2009e5dd7070Spatrick parseRecord();
2010e5dd7070Spatrick addUnwrappedLine();
2011e5dd7070Spatrick return;
2012e5dd7070Spatrick }
2013e5dd7070Spatrick
2014*12c85518Srobert if (Style.isVerilog()) {
2015*12c85518Srobert if (FormatTok->is(Keywords.kw_table)) {
2016*12c85518Srobert parseVerilogTable();
2017a9ac8606Spatrick return;
2018a9ac8606Spatrick }
2019*12c85518Srobert if (Keywords.isVerilogBegin(*FormatTok) ||
2020*12c85518Srobert Keywords.isVerilogHierarchy(*FormatTok)) {
2021*12c85518Srobert parseBlock();
2022*12c85518Srobert addUnwrappedLine();
2023*12c85518Srobert return;
2024*12c85518Srobert }
2025*12c85518Srobert }
2026*12c85518Srobert
2027*12c85518Srobert if (FormatTok->is(Keywords.kw_interface)) {
2028*12c85518Srobert if (parseStructLike())
2029*12c85518Srobert return;
2030a9ac8606Spatrick break;
2031a9ac8606Spatrick }
2032a9ac8606Spatrick
2033e5dd7070Spatrick if (Style.isCpp() && FormatTok->is(TT_StatementMacro)) {
2034e5dd7070Spatrick parseStatementMacro();
2035e5dd7070Spatrick return;
2036e5dd7070Spatrick }
2037e5dd7070Spatrick
2038e5dd7070Spatrick // See if the following token should start a new unwrapped line.
2039e5dd7070Spatrick StringRef Text = FormatTok->TokenText;
2040*12c85518Srobert
2041*12c85518Srobert FormatToken *PreviousToken = FormatTok;
2042e5dd7070Spatrick nextToken();
2043e5dd7070Spatrick
2044e5dd7070Spatrick // JS doesn't have macros, and within classes colons indicate fields, not
2045e5dd7070Spatrick // labels.
2046*12c85518Srobert if (Style.isJavaScript())
2047e5dd7070Spatrick break;
2048e5dd7070Spatrick
2049*12c85518Srobert auto OneTokenSoFar = [&]() {
2050*12c85518Srobert auto I = Line->Tokens.begin(), E = Line->Tokens.end();
2051*12c85518Srobert while (I != E && I->Tok->is(tok::comment))
2052*12c85518Srobert ++I;
2053*12c85518Srobert while (I != E && Style.isVerilog() && I->Tok->is(tok::hash))
2054*12c85518Srobert ++I;
2055*12c85518Srobert return I != E && (++I == E);
2056*12c85518Srobert };
2057*12c85518Srobert if (OneTokenSoFar()) {
2058*12c85518Srobert // In Verilog labels can be any expression, so we don't do them here.
2059*12c85518Srobert if (!Style.isVerilog() && FormatTok->is(tok::colon) &&
2060*12c85518Srobert !Line->MustBeDeclaration) {
2061e5dd7070Spatrick Line->Tokens.begin()->Tok->MustBreakBefore = true;
2062e5dd7070Spatrick parseLabel(!Style.IndentGotoLabels);
2063*12c85518Srobert if (HasLabel)
2064*12c85518Srobert *HasLabel = true;
2065e5dd7070Spatrick return;
2066e5dd7070Spatrick }
2067e5dd7070Spatrick // Recognize function-like macro usages without trailing semicolon as
2068e5dd7070Spatrick // well as free-standing macros like Q_OBJECT.
2069e5dd7070Spatrick bool FunctionLike = FormatTok->is(tok::l_paren);
2070e5dd7070Spatrick if (FunctionLike)
2071e5dd7070Spatrick parseParens();
2072e5dd7070Spatrick
2073e5dd7070Spatrick bool FollowedByNewline =
2074e5dd7070Spatrick CommentsBeforeNextToken.empty()
2075e5dd7070Spatrick ? FormatTok->NewlinesBefore > 0
2076e5dd7070Spatrick : CommentsBeforeNextToken.front()->NewlinesBefore > 0;
2077e5dd7070Spatrick
2078e5dd7070Spatrick if (FollowedByNewline && (Text.size() >= 5 || FunctionLike) &&
2079ec727ea7Spatrick tokenCanStartNewLine(*FormatTok) && Text == Text.upper()) {
2080*12c85518Srobert if (PreviousToken->isNot(TT_UntouchableMacroFunc))
2081*12c85518Srobert PreviousToken->setFinalizedType(TT_FunctionLikeOrFreestandingMacro);
2082e5dd7070Spatrick addUnwrappedLine();
2083e5dd7070Spatrick return;
2084e5dd7070Spatrick }
2085e5dd7070Spatrick }
2086e5dd7070Spatrick break;
2087e5dd7070Spatrick }
2088e5dd7070Spatrick case tok::equal:
2089*12c85518Srobert if ((Style.isJavaScript() || Style.isCSharp()) &&
2090*12c85518Srobert FormatTok->is(TT_FatArrow)) {
2091*12c85518Srobert tryToParseChildBlock();
2092e5dd7070Spatrick break;
2093e5dd7070Spatrick }
2094e5dd7070Spatrick
2095e5dd7070Spatrick nextToken();
2096*12c85518Srobert if (FormatTok->is(tok::l_brace)) {
2097ec727ea7Spatrick // Block kind should probably be set to BK_BracedInit for any language.
2098ec727ea7Spatrick // C# needs this change to ensure that array initialisers and object
2099ec727ea7Spatrick // initialisers are indented the same way.
2100ec727ea7Spatrick if (Style.isCSharp())
2101a9ac8606Spatrick FormatTok->setBlockKind(BK_BracedInit);
2102e5dd7070Spatrick nextToken();
2103e5dd7070Spatrick parseBracedList();
2104e5dd7070Spatrick } else if (Style.Language == FormatStyle::LK_Proto &&
2105*12c85518Srobert FormatTok->is(tok::less)) {
2106e5dd7070Spatrick nextToken();
2107ec727ea7Spatrick parseBracedList(/*ContinueOnSemicolons=*/false, /*IsEnum=*/false,
2108e5dd7070Spatrick /*ClosingBraceKind=*/tok::greater);
2109e5dd7070Spatrick }
2110e5dd7070Spatrick break;
2111e5dd7070Spatrick case tok::l_square:
2112e5dd7070Spatrick parseSquare();
2113e5dd7070Spatrick break;
2114e5dd7070Spatrick case tok::kw_new:
2115e5dd7070Spatrick parseNew();
2116e5dd7070Spatrick break;
2117*12c85518Srobert case tok::kw_case:
2118*12c85518Srobert // Proto: there are no switch/case statements.
2119*12c85518Srobert if (Style.isProto()) {
2120*12c85518Srobert nextToken();
2121*12c85518Srobert return;
2122*12c85518Srobert }
2123*12c85518Srobert // In Verilog switch is called case.
2124*12c85518Srobert if (Style.isVerilog()) {
2125*12c85518Srobert parseBlock();
2126*12c85518Srobert addUnwrappedLine();
2127*12c85518Srobert return;
2128*12c85518Srobert }
2129*12c85518Srobert if (Style.isJavaScript() && Line->MustBeDeclaration) {
2130*12c85518Srobert // 'case: string' field declaration.
2131*12c85518Srobert nextToken();
2132*12c85518Srobert break;
2133*12c85518Srobert }
2134*12c85518Srobert parseCaseLabel();
2135*12c85518Srobert break;
2136*12c85518Srobert case tok::kw_default:
2137*12c85518Srobert nextToken();
2138*12c85518Srobert if (Style.isVerilog()) {
2139*12c85518Srobert if (FormatTok->is(tok::colon)) {
2140*12c85518Srobert // The label will be handled in the next iteration.
2141*12c85518Srobert break;
2142*12c85518Srobert }
2143*12c85518Srobert if (FormatTok->is(Keywords.kw_clocking)) {
2144*12c85518Srobert // A default clocking block.
2145*12c85518Srobert parseBlock();
2146*12c85518Srobert addUnwrappedLine();
2147*12c85518Srobert return;
2148*12c85518Srobert }
2149*12c85518Srobert parseVerilogCaseLabel();
2150*12c85518Srobert return;
2151*12c85518Srobert }
2152*12c85518Srobert break;
2153*12c85518Srobert case tok::colon:
2154*12c85518Srobert nextToken();
2155*12c85518Srobert if (Style.isVerilog()) {
2156*12c85518Srobert parseVerilogCaseLabel();
2157*12c85518Srobert return;
2158*12c85518Srobert }
2159*12c85518Srobert break;
2160e5dd7070Spatrick default:
2161e5dd7070Spatrick nextToken();
2162e5dd7070Spatrick break;
2163e5dd7070Spatrick }
2164e5dd7070Spatrick } while (!eof());
2165e5dd7070Spatrick }
2166e5dd7070Spatrick
tryToParsePropertyAccessor()2167ec727ea7Spatrick bool UnwrappedLineParser::tryToParsePropertyAccessor() {
2168ec727ea7Spatrick assert(FormatTok->is(tok::l_brace));
2169ec727ea7Spatrick if (!Style.isCSharp())
2170ec727ea7Spatrick return false;
2171ec727ea7Spatrick // See if it's a property accessor.
2172ec727ea7Spatrick if (FormatTok->Previous->isNot(tok::identifier))
2173ec727ea7Spatrick return false;
2174ec727ea7Spatrick
2175ec727ea7Spatrick // See if we are inside a property accessor.
2176ec727ea7Spatrick //
2177ec727ea7Spatrick // Record the current tokenPosition so that we can advance and
2178ec727ea7Spatrick // reset the current token. `Next` is not set yet so we need
2179ec727ea7Spatrick // another way to advance along the token stream.
2180ec727ea7Spatrick unsigned int StoredPosition = Tokens->getPosition();
2181ec727ea7Spatrick FormatToken *Tok = Tokens->getNextToken();
2182ec727ea7Spatrick
2183ec727ea7Spatrick // A trivial property accessor is of the form:
2184*12c85518Srobert // { [ACCESS_SPECIFIER] [get]; [ACCESS_SPECIFIER] [set|init] }
2185ec727ea7Spatrick // Track these as they do not require line breaks to be introduced.
2186*12c85518Srobert bool HasSpecialAccessor = false;
2187ec727ea7Spatrick bool IsTrivialPropertyAccessor = true;
2188ec727ea7Spatrick while (!eof()) {
2189ec727ea7Spatrick if (Tok->isOneOf(tok::semi, tok::kw_public, tok::kw_private,
2190ec727ea7Spatrick tok::kw_protected, Keywords.kw_internal, Keywords.kw_get,
2191*12c85518Srobert Keywords.kw_init, Keywords.kw_set)) {
2192*12c85518Srobert if (Tok->isOneOf(Keywords.kw_get, Keywords.kw_init, Keywords.kw_set))
2193*12c85518Srobert HasSpecialAccessor = true;
2194ec727ea7Spatrick Tok = Tokens->getNextToken();
2195ec727ea7Spatrick continue;
2196ec727ea7Spatrick }
2197ec727ea7Spatrick if (Tok->isNot(tok::r_brace))
2198ec727ea7Spatrick IsTrivialPropertyAccessor = false;
2199ec727ea7Spatrick break;
2200ec727ea7Spatrick }
2201ec727ea7Spatrick
2202*12c85518Srobert if (!HasSpecialAccessor) {
2203ec727ea7Spatrick Tokens->setPosition(StoredPosition);
2204ec727ea7Spatrick return false;
2205ec727ea7Spatrick }
2206ec727ea7Spatrick
2207ec727ea7Spatrick // Try to parse the property accessor:
2208ec727ea7Spatrick // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties
2209ec727ea7Spatrick Tokens->setPosition(StoredPosition);
2210*12c85518Srobert if (!IsTrivialPropertyAccessor && Style.BraceWrapping.AfterFunction)
2211ec727ea7Spatrick addUnwrappedLine();
2212ec727ea7Spatrick nextToken();
2213ec727ea7Spatrick do {
2214ec727ea7Spatrick switch (FormatTok->Tok.getKind()) {
2215ec727ea7Spatrick case tok::r_brace:
2216ec727ea7Spatrick nextToken();
2217ec727ea7Spatrick if (FormatTok->is(tok::equal)) {
2218ec727ea7Spatrick while (!eof() && FormatTok->isNot(tok::semi))
2219ec727ea7Spatrick nextToken();
2220ec727ea7Spatrick nextToken();
2221ec727ea7Spatrick }
2222ec727ea7Spatrick addUnwrappedLine();
2223ec727ea7Spatrick return true;
2224ec727ea7Spatrick case tok::l_brace:
2225ec727ea7Spatrick ++Line->Level;
2226ec727ea7Spatrick parseBlock(/*MustBeDeclaration=*/true);
2227ec727ea7Spatrick addUnwrappedLine();
2228ec727ea7Spatrick --Line->Level;
2229ec727ea7Spatrick break;
2230ec727ea7Spatrick case tok::equal:
2231a9ac8606Spatrick if (FormatTok->is(TT_FatArrow)) {
2232ec727ea7Spatrick ++Line->Level;
2233ec727ea7Spatrick do {
2234ec727ea7Spatrick nextToken();
2235ec727ea7Spatrick } while (!eof() && FormatTok->isNot(tok::semi));
2236ec727ea7Spatrick nextToken();
2237ec727ea7Spatrick addUnwrappedLine();
2238ec727ea7Spatrick --Line->Level;
2239ec727ea7Spatrick break;
2240ec727ea7Spatrick }
2241ec727ea7Spatrick nextToken();
2242ec727ea7Spatrick break;
2243ec727ea7Spatrick default:
2244*12c85518Srobert if (FormatTok->isOneOf(Keywords.kw_get, Keywords.kw_init,
2245*12c85518Srobert Keywords.kw_set) &&
2246ec727ea7Spatrick !IsTrivialPropertyAccessor) {
2247ec727ea7Spatrick // Non-trivial get/set needs to be on its own line.
2248ec727ea7Spatrick addUnwrappedLine();
2249ec727ea7Spatrick }
2250ec727ea7Spatrick nextToken();
2251ec727ea7Spatrick }
2252ec727ea7Spatrick } while (!eof());
2253ec727ea7Spatrick
2254ec727ea7Spatrick // Unreachable for well-formed code (paired '{' and '}').
2255ec727ea7Spatrick return true;
2256ec727ea7Spatrick }
2257ec727ea7Spatrick
tryToParseLambda()2258e5dd7070Spatrick bool UnwrappedLineParser::tryToParseLambda() {
2259*12c85518Srobert assert(FormatTok->is(tok::l_square));
2260e5dd7070Spatrick if (!Style.isCpp()) {
2261e5dd7070Spatrick nextToken();
2262e5dd7070Spatrick return false;
2263e5dd7070Spatrick }
2264e5dd7070Spatrick FormatToken &LSquare = *FormatTok;
2265e5dd7070Spatrick if (!tryToParseLambdaIntroducer())
2266e5dd7070Spatrick return false;
2267e5dd7070Spatrick
2268e5dd7070Spatrick bool SeenArrow = false;
2269*12c85518Srobert bool InTemplateParameterList = false;
2270e5dd7070Spatrick
2271e5dd7070Spatrick while (FormatTok->isNot(tok::l_brace)) {
2272e5dd7070Spatrick if (FormatTok->isSimpleTypeSpecifier()) {
2273e5dd7070Spatrick nextToken();
2274e5dd7070Spatrick continue;
2275e5dd7070Spatrick }
2276e5dd7070Spatrick switch (FormatTok->Tok.getKind()) {
2277e5dd7070Spatrick case tok::l_brace:
2278e5dd7070Spatrick break;
2279e5dd7070Spatrick case tok::l_paren:
2280e5dd7070Spatrick parseParens();
2281e5dd7070Spatrick break;
2282*12c85518Srobert case tok::l_square:
2283*12c85518Srobert parseSquare();
2284*12c85518Srobert break;
2285*12c85518Srobert case tok::less:
2286*12c85518Srobert assert(FormatTok->Previous);
2287*12c85518Srobert if (FormatTok->Previous->is(tok::r_square))
2288*12c85518Srobert InTemplateParameterList = true;
2289*12c85518Srobert nextToken();
2290*12c85518Srobert break;
2291*12c85518Srobert case tok::kw_auto:
2292*12c85518Srobert case tok::kw_class:
2293*12c85518Srobert case tok::kw_template:
2294*12c85518Srobert case tok::kw_typename:
2295e5dd7070Spatrick case tok::amp:
2296e5dd7070Spatrick case tok::star:
2297e5dd7070Spatrick case tok::kw_const:
2298*12c85518Srobert case tok::kw_constexpr:
2299*12c85518Srobert case tok::kw_consteval:
2300e5dd7070Spatrick case tok::comma:
2301e5dd7070Spatrick case tok::greater:
2302e5dd7070Spatrick case tok::identifier:
2303e5dd7070Spatrick case tok::numeric_constant:
2304e5dd7070Spatrick case tok::coloncolon:
2305e5dd7070Spatrick case tok::kw_mutable:
2306e5dd7070Spatrick case tok::kw_noexcept:
2307*12c85518Srobert case tok::kw_static:
2308e5dd7070Spatrick nextToken();
2309e5dd7070Spatrick break;
2310e5dd7070Spatrick // Specialization of a template with an integer parameter can contain
2311e5dd7070Spatrick // arithmetic, logical, comparison and ternary operators.
2312e5dd7070Spatrick //
2313e5dd7070Spatrick // FIXME: This also accepts sequences of operators that are not in the scope
2314e5dd7070Spatrick // of a template argument list.
2315e5dd7070Spatrick //
2316e5dd7070Spatrick // In a C++ lambda a template type can only occur after an arrow. We use
2317e5dd7070Spatrick // this as an heuristic to distinguish between Objective-C expressions
2318e5dd7070Spatrick // followed by an `a->b` expression, such as:
2319e5dd7070Spatrick // ([obj func:arg] + a->b)
2320e5dd7070Spatrick // Otherwise the code below would parse as a lambda.
2321e5dd7070Spatrick //
2322e5dd7070Spatrick // FIXME: This heuristic is incorrect for C++20 generic lambdas with
2323e5dd7070Spatrick // explicit template lists: []<bool b = true && false>(U &&u){}
2324e5dd7070Spatrick case tok::plus:
2325e5dd7070Spatrick case tok::minus:
2326e5dd7070Spatrick case tok::exclaim:
2327e5dd7070Spatrick case tok::tilde:
2328e5dd7070Spatrick case tok::slash:
2329e5dd7070Spatrick case tok::percent:
2330e5dd7070Spatrick case tok::lessless:
2331e5dd7070Spatrick case tok::pipe:
2332e5dd7070Spatrick case tok::pipepipe:
2333e5dd7070Spatrick case tok::ampamp:
2334e5dd7070Spatrick case tok::caret:
2335e5dd7070Spatrick case tok::equalequal:
2336e5dd7070Spatrick case tok::exclaimequal:
2337e5dd7070Spatrick case tok::greaterequal:
2338e5dd7070Spatrick case tok::lessequal:
2339e5dd7070Spatrick case tok::question:
2340e5dd7070Spatrick case tok::colon:
2341ec727ea7Spatrick case tok::ellipsis:
2342e5dd7070Spatrick case tok::kw_true:
2343e5dd7070Spatrick case tok::kw_false:
2344*12c85518Srobert if (SeenArrow || InTemplateParameterList) {
2345e5dd7070Spatrick nextToken();
2346e5dd7070Spatrick break;
2347e5dd7070Spatrick }
2348e5dd7070Spatrick return true;
2349e5dd7070Spatrick case tok::arrow:
2350e5dd7070Spatrick // This might or might not actually be a lambda arrow (this could be an
2351e5dd7070Spatrick // ObjC method invocation followed by a dereferencing arrow). We might
2352e5dd7070Spatrick // reset this back to TT_Unknown in TokenAnnotator.
2353*12c85518Srobert FormatTok->setFinalizedType(TT_LambdaArrow);
2354e5dd7070Spatrick SeenArrow = true;
2355e5dd7070Spatrick nextToken();
2356e5dd7070Spatrick break;
2357e5dd7070Spatrick default:
2358e5dd7070Spatrick return true;
2359e5dd7070Spatrick }
2360e5dd7070Spatrick }
2361*12c85518Srobert FormatTok->setFinalizedType(TT_LambdaLBrace);
2362*12c85518Srobert LSquare.setFinalizedType(TT_LambdaLSquare);
2363e5dd7070Spatrick parseChildBlock();
2364e5dd7070Spatrick return true;
2365e5dd7070Spatrick }
2366e5dd7070Spatrick
tryToParseLambdaIntroducer()2367e5dd7070Spatrick bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
2368e5dd7070Spatrick const FormatToken *Previous = FormatTok->Previous;
2369*12c85518Srobert const FormatToken *LeftSquare = FormatTok;
2370*12c85518Srobert nextToken();
2371e5dd7070Spatrick if (Previous &&
2372e5dd7070Spatrick (Previous->isOneOf(tok::identifier, tok::kw_operator, tok::kw_new,
2373e5dd7070Spatrick tok::kw_delete, tok::l_square) ||
2374*12c85518Srobert LeftSquare->isCppStructuredBinding(Style) || Previous->closesScope() ||
2375e5dd7070Spatrick Previous->isSimpleTypeSpecifier())) {
2376e5dd7070Spatrick return false;
2377e5dd7070Spatrick }
2378*12c85518Srobert if (FormatTok->is(tok::l_square))
2379*12c85518Srobert return false;
2380*12c85518Srobert if (FormatTok->is(tok::r_square)) {
2381*12c85518Srobert const FormatToken *Next = Tokens->peekNextToken(/*SkipComment=*/true);
2382*12c85518Srobert if (Next->is(tok::greater))
2383e5dd7070Spatrick return false;
2384e5dd7070Spatrick }
2385e5dd7070Spatrick parseSquare(/*LambdaIntroducer=*/true);
2386e5dd7070Spatrick return true;
2387e5dd7070Spatrick }
2388e5dd7070Spatrick
tryToParseJSFunction()2389e5dd7070Spatrick void UnwrappedLineParser::tryToParseJSFunction() {
2390e5dd7070Spatrick assert(FormatTok->is(Keywords.kw_function) ||
2391e5dd7070Spatrick FormatTok->startsSequence(Keywords.kw_async, Keywords.kw_function));
2392e5dd7070Spatrick if (FormatTok->is(Keywords.kw_async))
2393e5dd7070Spatrick nextToken();
2394e5dd7070Spatrick // Consume "function".
2395e5dd7070Spatrick nextToken();
2396e5dd7070Spatrick
2397e5dd7070Spatrick // Consume * (generator function). Treat it like C++'s overloaded operators.
2398e5dd7070Spatrick if (FormatTok->is(tok::star)) {
2399*12c85518Srobert FormatTok->setFinalizedType(TT_OverloadedOperator);
2400e5dd7070Spatrick nextToken();
2401e5dd7070Spatrick }
2402e5dd7070Spatrick
2403e5dd7070Spatrick // Consume function name.
2404e5dd7070Spatrick if (FormatTok->is(tok::identifier))
2405e5dd7070Spatrick nextToken();
2406e5dd7070Spatrick
2407e5dd7070Spatrick if (FormatTok->isNot(tok::l_paren))
2408e5dd7070Spatrick return;
2409e5dd7070Spatrick
2410e5dd7070Spatrick // Parse formal parameter list.
2411e5dd7070Spatrick parseParens();
2412e5dd7070Spatrick
2413e5dd7070Spatrick if (FormatTok->is(tok::colon)) {
2414e5dd7070Spatrick // Parse a type definition.
2415e5dd7070Spatrick nextToken();
2416e5dd7070Spatrick
2417e5dd7070Spatrick // Eat the type declaration. For braced inline object types, balance braces,
2418e5dd7070Spatrick // otherwise just parse until finding an l_brace for the function body.
2419e5dd7070Spatrick if (FormatTok->is(tok::l_brace))
2420e5dd7070Spatrick tryToParseBracedList();
2421e5dd7070Spatrick else
2422e5dd7070Spatrick while (!FormatTok->isOneOf(tok::l_brace, tok::semi) && !eof())
2423e5dd7070Spatrick nextToken();
2424e5dd7070Spatrick }
2425e5dd7070Spatrick
2426e5dd7070Spatrick if (FormatTok->is(tok::semi))
2427e5dd7070Spatrick return;
2428e5dd7070Spatrick
2429e5dd7070Spatrick parseChildBlock();
2430e5dd7070Spatrick }
2431e5dd7070Spatrick
tryToParseBracedList()2432e5dd7070Spatrick bool UnwrappedLineParser::tryToParseBracedList() {
2433a9ac8606Spatrick if (FormatTok->is(BK_Unknown))
2434e5dd7070Spatrick calculateBraceTypes();
2435a9ac8606Spatrick assert(FormatTok->isNot(BK_Unknown));
2436a9ac8606Spatrick if (FormatTok->is(BK_Block))
2437e5dd7070Spatrick return false;
2438e5dd7070Spatrick nextToken();
2439e5dd7070Spatrick parseBracedList();
2440e5dd7070Spatrick return true;
2441e5dd7070Spatrick }
2442e5dd7070Spatrick
tryToParseChildBlock()2443*12c85518Srobert bool UnwrappedLineParser::tryToParseChildBlock() {
2444*12c85518Srobert assert(Style.isJavaScript() || Style.isCSharp());
2445*12c85518Srobert assert(FormatTok->is(TT_FatArrow));
2446*12c85518Srobert // Fat arrows (=>) have tok::TokenKind tok::equal but TokenType TT_FatArrow.
2447*12c85518Srobert // They always start an expression or a child block if followed by a curly
2448*12c85518Srobert // brace.
2449*12c85518Srobert nextToken();
2450*12c85518Srobert if (FormatTok->isNot(tok::l_brace))
2451*12c85518Srobert return false;
2452*12c85518Srobert parseChildBlock();
2453*12c85518Srobert return true;
2454*12c85518Srobert }
2455*12c85518Srobert
parseBracedList(bool ContinueOnSemicolons,bool IsEnum,tok::TokenKind ClosingBraceKind)2456e5dd7070Spatrick bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons,
2457ec727ea7Spatrick bool IsEnum,
2458e5dd7070Spatrick tok::TokenKind ClosingBraceKind) {
2459e5dd7070Spatrick bool HasError = false;
2460e5dd7070Spatrick
2461e5dd7070Spatrick // FIXME: Once we have an expression parser in the UnwrappedLineParser,
2462a9ac8606Spatrick // replace this by using parseAssignmentExpression() inside.
2463e5dd7070Spatrick do {
2464*12c85518Srobert if (Style.isCSharp() && FormatTok->is(TT_FatArrow) &&
2465*12c85518Srobert tryToParseChildBlock()) {
2466ec727ea7Spatrick continue;
2467ec727ea7Spatrick }
2468*12c85518Srobert if (Style.isJavaScript()) {
2469e5dd7070Spatrick if (FormatTok->is(Keywords.kw_function) ||
2470e5dd7070Spatrick FormatTok->startsSequence(Keywords.kw_async, Keywords.kw_function)) {
2471e5dd7070Spatrick tryToParseJSFunction();
2472e5dd7070Spatrick continue;
2473e5dd7070Spatrick }
2474e5dd7070Spatrick if (FormatTok->is(tok::l_brace)) {
2475e5dd7070Spatrick // Could be a method inside of a braced list `{a() { return 1; }}`.
2476e5dd7070Spatrick if (tryToParseBracedList())
2477e5dd7070Spatrick continue;
2478e5dd7070Spatrick parseChildBlock();
2479e5dd7070Spatrick }
2480e5dd7070Spatrick }
2481e5dd7070Spatrick if (FormatTok->Tok.getKind() == ClosingBraceKind) {
2482ec727ea7Spatrick if (IsEnum && !Style.AllowShortEnumsOnASingleLine)
2483ec727ea7Spatrick addUnwrappedLine();
2484e5dd7070Spatrick nextToken();
2485e5dd7070Spatrick return !HasError;
2486e5dd7070Spatrick }
2487e5dd7070Spatrick switch (FormatTok->Tok.getKind()) {
2488e5dd7070Spatrick case tok::l_square:
2489ec727ea7Spatrick if (Style.isCSharp())
2490ec727ea7Spatrick parseSquare();
2491ec727ea7Spatrick else
2492e5dd7070Spatrick tryToParseLambda();
2493e5dd7070Spatrick break;
2494e5dd7070Spatrick case tok::l_paren:
2495e5dd7070Spatrick parseParens();
2496e5dd7070Spatrick // JavaScript can just have free standing methods and getters/setters in
2497e5dd7070Spatrick // object literals. Detect them by a "{" following ")".
2498*12c85518Srobert if (Style.isJavaScript()) {
2499e5dd7070Spatrick if (FormatTok->is(tok::l_brace))
2500e5dd7070Spatrick parseChildBlock();
2501e5dd7070Spatrick break;
2502e5dd7070Spatrick }
2503e5dd7070Spatrick break;
2504e5dd7070Spatrick case tok::l_brace:
2505e5dd7070Spatrick // Assume there are no blocks inside a braced init list apart
2506e5dd7070Spatrick // from the ones we explicitly parse out (like lambdas).
2507a9ac8606Spatrick FormatTok->setBlockKind(BK_BracedInit);
2508e5dd7070Spatrick nextToken();
2509e5dd7070Spatrick parseBracedList();
2510e5dd7070Spatrick break;
2511e5dd7070Spatrick case tok::less:
2512*12c85518Srobert if (Style.Language == FormatStyle::LK_Proto ||
2513*12c85518Srobert ClosingBraceKind == tok::greater) {
2514e5dd7070Spatrick nextToken();
2515ec727ea7Spatrick parseBracedList(/*ContinueOnSemicolons=*/false, /*IsEnum=*/false,
2516e5dd7070Spatrick /*ClosingBraceKind=*/tok::greater);
2517e5dd7070Spatrick } else {
2518e5dd7070Spatrick nextToken();
2519e5dd7070Spatrick }
2520e5dd7070Spatrick break;
2521e5dd7070Spatrick case tok::semi:
2522e5dd7070Spatrick // JavaScript (or more precisely TypeScript) can have semicolons in braced
2523e5dd7070Spatrick // lists (in so-called TypeMemberLists). Thus, the semicolon cannot be
2524e5dd7070Spatrick // used for error recovery if we have otherwise determined that this is
2525e5dd7070Spatrick // a braced list.
2526*12c85518Srobert if (Style.isJavaScript()) {
2527e5dd7070Spatrick nextToken();
2528e5dd7070Spatrick break;
2529e5dd7070Spatrick }
2530e5dd7070Spatrick HasError = true;
2531e5dd7070Spatrick if (!ContinueOnSemicolons)
2532e5dd7070Spatrick return !HasError;
2533e5dd7070Spatrick nextToken();
2534e5dd7070Spatrick break;
2535e5dd7070Spatrick case tok::comma:
2536e5dd7070Spatrick nextToken();
2537ec727ea7Spatrick if (IsEnum && !Style.AllowShortEnumsOnASingleLine)
2538ec727ea7Spatrick addUnwrappedLine();
2539e5dd7070Spatrick break;
2540e5dd7070Spatrick default:
2541e5dd7070Spatrick nextToken();
2542e5dd7070Spatrick break;
2543e5dd7070Spatrick }
2544e5dd7070Spatrick } while (!eof());
2545e5dd7070Spatrick return false;
2546e5dd7070Spatrick }
2547e5dd7070Spatrick
2548*12c85518Srobert /// \brief Parses a pair of parentheses (and everything between them).
2549*12c85518Srobert /// \param AmpAmpTokenType If different than TT_Unknown sets this type for all
2550*12c85518Srobert /// double ampersands. This only counts for the current parens scope.
parseParens(TokenType AmpAmpTokenType)2551*12c85518Srobert void UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) {
2552*12c85518Srobert assert(FormatTok->is(tok::l_paren) && "'(' expected.");
2553e5dd7070Spatrick nextToken();
2554e5dd7070Spatrick do {
2555e5dd7070Spatrick switch (FormatTok->Tok.getKind()) {
2556e5dd7070Spatrick case tok::l_paren:
2557e5dd7070Spatrick parseParens();
2558e5dd7070Spatrick if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::l_brace))
2559e5dd7070Spatrick parseChildBlock();
2560e5dd7070Spatrick break;
2561e5dd7070Spatrick case tok::r_paren:
2562e5dd7070Spatrick nextToken();
2563e5dd7070Spatrick return;
2564e5dd7070Spatrick case tok::r_brace:
2565e5dd7070Spatrick // A "}" inside parenthesis is an error if there wasn't a matching "{".
2566e5dd7070Spatrick return;
2567e5dd7070Spatrick case tok::l_square:
2568e5dd7070Spatrick tryToParseLambda();
2569e5dd7070Spatrick break;
2570e5dd7070Spatrick case tok::l_brace:
2571e5dd7070Spatrick if (!tryToParseBracedList())
2572e5dd7070Spatrick parseChildBlock();
2573e5dd7070Spatrick break;
2574e5dd7070Spatrick case tok::at:
2575e5dd7070Spatrick nextToken();
2576*12c85518Srobert if (FormatTok->is(tok::l_brace)) {
2577e5dd7070Spatrick nextToken();
2578e5dd7070Spatrick parseBracedList();
2579e5dd7070Spatrick }
2580e5dd7070Spatrick break;
2581a9ac8606Spatrick case tok::equal:
2582a9ac8606Spatrick if (Style.isCSharp() && FormatTok->is(TT_FatArrow))
2583*12c85518Srobert tryToParseChildBlock();
2584a9ac8606Spatrick else
2585a9ac8606Spatrick nextToken();
2586a9ac8606Spatrick break;
2587e5dd7070Spatrick case tok::kw_class:
2588*12c85518Srobert if (Style.isJavaScript())
2589e5dd7070Spatrick parseRecord(/*ParseAsExpr=*/true);
2590e5dd7070Spatrick else
2591e5dd7070Spatrick nextToken();
2592e5dd7070Spatrick break;
2593e5dd7070Spatrick case tok::identifier:
2594*12c85518Srobert if (Style.isJavaScript() &&
2595e5dd7070Spatrick (FormatTok->is(Keywords.kw_function) ||
2596*12c85518Srobert FormatTok->startsSequence(Keywords.kw_async,
2597*12c85518Srobert Keywords.kw_function))) {
2598e5dd7070Spatrick tryToParseJSFunction();
2599*12c85518Srobert } else {
2600e5dd7070Spatrick nextToken();
2601*12c85518Srobert }
2602e5dd7070Spatrick break;
2603*12c85518Srobert case tok::kw_requires: {
2604*12c85518Srobert auto RequiresToken = FormatTok;
2605*12c85518Srobert nextToken();
2606*12c85518Srobert parseRequiresExpression(RequiresToken);
2607*12c85518Srobert break;
2608*12c85518Srobert }
2609*12c85518Srobert case tok::ampamp:
2610*12c85518Srobert if (AmpAmpTokenType != TT_Unknown)
2611*12c85518Srobert FormatTok->setFinalizedType(AmpAmpTokenType);
2612*12c85518Srobert [[fallthrough]];
2613e5dd7070Spatrick default:
2614e5dd7070Spatrick nextToken();
2615e5dd7070Spatrick break;
2616e5dd7070Spatrick }
2617e5dd7070Spatrick } while (!eof());
2618e5dd7070Spatrick }
2619e5dd7070Spatrick
parseSquare(bool LambdaIntroducer)2620e5dd7070Spatrick void UnwrappedLineParser::parseSquare(bool LambdaIntroducer) {
2621e5dd7070Spatrick if (!LambdaIntroducer) {
2622*12c85518Srobert assert(FormatTok->is(tok::l_square) && "'[' expected.");
2623e5dd7070Spatrick if (tryToParseLambda())
2624e5dd7070Spatrick return;
2625e5dd7070Spatrick }
2626e5dd7070Spatrick do {
2627e5dd7070Spatrick switch (FormatTok->Tok.getKind()) {
2628e5dd7070Spatrick case tok::l_paren:
2629e5dd7070Spatrick parseParens();
2630e5dd7070Spatrick break;
2631e5dd7070Spatrick case tok::r_square:
2632e5dd7070Spatrick nextToken();
2633e5dd7070Spatrick return;
2634e5dd7070Spatrick case tok::r_brace:
2635e5dd7070Spatrick // A "}" inside parenthesis is an error if there wasn't a matching "{".
2636e5dd7070Spatrick return;
2637e5dd7070Spatrick case tok::l_square:
2638e5dd7070Spatrick parseSquare();
2639e5dd7070Spatrick break;
2640e5dd7070Spatrick case tok::l_brace: {
2641e5dd7070Spatrick if (!tryToParseBracedList())
2642e5dd7070Spatrick parseChildBlock();
2643e5dd7070Spatrick break;
2644e5dd7070Spatrick }
2645e5dd7070Spatrick case tok::at:
2646e5dd7070Spatrick nextToken();
2647*12c85518Srobert if (FormatTok->is(tok::l_brace)) {
2648e5dd7070Spatrick nextToken();
2649e5dd7070Spatrick parseBracedList();
2650e5dd7070Spatrick }
2651e5dd7070Spatrick break;
2652e5dd7070Spatrick default:
2653e5dd7070Spatrick nextToken();
2654e5dd7070Spatrick break;
2655e5dd7070Spatrick }
2656e5dd7070Spatrick } while (!eof());
2657e5dd7070Spatrick }
2658e5dd7070Spatrick
keepAncestorBraces()2659*12c85518Srobert void UnwrappedLineParser::keepAncestorBraces() {
2660*12c85518Srobert if (!Style.RemoveBracesLLVM)
2661*12c85518Srobert return;
2662*12c85518Srobert
2663*12c85518Srobert const int MaxNestingLevels = 2;
2664*12c85518Srobert const int Size = NestedTooDeep.size();
2665*12c85518Srobert if (Size >= MaxNestingLevels)
2666*12c85518Srobert NestedTooDeep[Size - MaxNestingLevels] = true;
2667*12c85518Srobert NestedTooDeep.push_back(false);
2668*12c85518Srobert }
2669*12c85518Srobert
getLastNonComment(const UnwrappedLine & Line)2670*12c85518Srobert static FormatToken *getLastNonComment(const UnwrappedLine &Line) {
2671*12c85518Srobert for (const auto &Token : llvm::reverse(Line.Tokens))
2672*12c85518Srobert if (Token.Tok->isNot(tok::comment))
2673*12c85518Srobert return Token.Tok;
2674*12c85518Srobert
2675*12c85518Srobert return nullptr;
2676*12c85518Srobert }
2677*12c85518Srobert
parseUnbracedBody(bool CheckEOF)2678*12c85518Srobert void UnwrappedLineParser::parseUnbracedBody(bool CheckEOF) {
2679*12c85518Srobert FormatToken *Tok = nullptr;
2680*12c85518Srobert
2681*12c85518Srobert if (Style.InsertBraces && !Line->InPPDirective && !Line->Tokens.empty() &&
2682*12c85518Srobert PreprocessorDirectives.empty() && FormatTok->isNot(tok::semi)) {
2683*12c85518Srobert Tok = Style.BraceWrapping.AfterControlStatement == FormatStyle::BWACS_Never
2684*12c85518Srobert ? getLastNonComment(*Line)
2685*12c85518Srobert : Line->Tokens.back().Tok;
2686*12c85518Srobert assert(Tok);
2687*12c85518Srobert if (Tok->BraceCount < 0) {
2688*12c85518Srobert assert(Tok->BraceCount == -1);
2689*12c85518Srobert Tok = nullptr;
2690*12c85518Srobert } else {
2691*12c85518Srobert Tok->BraceCount = -1;
2692*12c85518Srobert }
2693*12c85518Srobert }
2694*12c85518Srobert
2695*12c85518Srobert addUnwrappedLine();
2696*12c85518Srobert ++Line->Level;
2697*12c85518Srobert parseStructuralElement();
2698*12c85518Srobert
2699*12c85518Srobert if (Tok) {
2700*12c85518Srobert assert(!Line->InPPDirective);
2701*12c85518Srobert Tok = nullptr;
2702*12c85518Srobert for (const auto &L : llvm::reverse(*CurrentLines)) {
2703*12c85518Srobert if (!L.InPPDirective && getLastNonComment(L)) {
2704*12c85518Srobert Tok = L.Tokens.back().Tok;
2705*12c85518Srobert break;
2706*12c85518Srobert }
2707*12c85518Srobert }
2708*12c85518Srobert assert(Tok);
2709*12c85518Srobert ++Tok->BraceCount;
2710*12c85518Srobert }
2711*12c85518Srobert
2712*12c85518Srobert if (CheckEOF && eof())
2713*12c85518Srobert addUnwrappedLine();
2714*12c85518Srobert
2715*12c85518Srobert --Line->Level;
2716*12c85518Srobert }
2717*12c85518Srobert
markOptionalBraces(FormatToken * LeftBrace)2718*12c85518Srobert static void markOptionalBraces(FormatToken *LeftBrace) {
2719*12c85518Srobert if (!LeftBrace)
2720*12c85518Srobert return;
2721*12c85518Srobert
2722*12c85518Srobert assert(LeftBrace->is(tok::l_brace));
2723*12c85518Srobert
2724*12c85518Srobert FormatToken *RightBrace = LeftBrace->MatchingParen;
2725*12c85518Srobert if (!RightBrace) {
2726*12c85518Srobert assert(!LeftBrace->Optional);
2727*12c85518Srobert return;
2728*12c85518Srobert }
2729*12c85518Srobert
2730*12c85518Srobert assert(RightBrace->is(tok::r_brace));
2731*12c85518Srobert assert(RightBrace->MatchingParen == LeftBrace);
2732*12c85518Srobert assert(LeftBrace->Optional == RightBrace->Optional);
2733*12c85518Srobert
2734*12c85518Srobert LeftBrace->Optional = true;
2735*12c85518Srobert RightBrace->Optional = true;
2736*12c85518Srobert }
2737*12c85518Srobert
handleAttributes()2738*12c85518Srobert void UnwrappedLineParser::handleAttributes() {
2739*12c85518Srobert // Handle AttributeMacro, e.g. `if (x) UNLIKELY`.
2740*12c85518Srobert if (FormatTok->is(TT_AttributeMacro))
2741e5dd7070Spatrick nextToken();
2742*12c85518Srobert if (FormatTok->is(tok::l_square))
2743*12c85518Srobert handleCppAttributes();
2744*12c85518Srobert }
2745*12c85518Srobert
handleCppAttributes()2746*12c85518Srobert bool UnwrappedLineParser::handleCppAttributes() {
2747*12c85518Srobert // Handle [[likely]] / [[unlikely]] attributes.
2748*12c85518Srobert assert(FormatTok->is(tok::l_square));
2749*12c85518Srobert if (!tryToParseSimpleAttribute())
2750*12c85518Srobert return false;
2751ec727ea7Spatrick parseSquare();
2752*12c85518Srobert return true;
2753*12c85518Srobert }
2754*12c85518Srobert
2755*12c85518Srobert /// Returns whether \c Tok begins a block.
isBlockBegin(const FormatToken & Tok) const2756*12c85518Srobert bool UnwrappedLineParser::isBlockBegin(const FormatToken &Tok) const {
2757*12c85518Srobert // FIXME: rename the function or make
2758*12c85518Srobert // Tok.isOneOf(tok::l_brace, TT_MacroBlockBegin) work.
2759*12c85518Srobert return Style.isVerilog() ? Keywords.isVerilogBegin(Tok)
2760*12c85518Srobert : Tok.is(tok::l_brace);
2761*12c85518Srobert }
2762*12c85518Srobert
parseIfThenElse(IfStmtKind * IfKind,bool KeepBraces)2763*12c85518Srobert FormatToken *UnwrappedLineParser::parseIfThenElse(IfStmtKind *IfKind,
2764*12c85518Srobert bool KeepBraces) {
2765*12c85518Srobert assert(FormatTok->is(tok::kw_if) && "'if' expected");
2766*12c85518Srobert nextToken();
2767*12c85518Srobert if (FormatTok->is(tok::exclaim))
2768*12c85518Srobert nextToken();
2769*12c85518Srobert
2770*12c85518Srobert bool KeepIfBraces = true;
2771*12c85518Srobert if (FormatTok->is(tok::kw_consteval)) {
2772*12c85518Srobert nextToken();
2773*12c85518Srobert } else {
2774*12c85518Srobert KeepIfBraces = !Style.RemoveBracesLLVM || KeepBraces;
2775*12c85518Srobert if (FormatTok->isOneOf(tok::kw_constexpr, tok::identifier))
2776*12c85518Srobert nextToken();
2777*12c85518Srobert if (FormatTok->is(tok::l_paren))
2778*12c85518Srobert parseParens();
2779*12c85518Srobert }
2780*12c85518Srobert handleAttributes();
2781*12c85518Srobert
2782e5dd7070Spatrick bool NeedsUnwrappedLine = false;
2783*12c85518Srobert keepAncestorBraces();
2784*12c85518Srobert
2785*12c85518Srobert FormatToken *IfLeftBrace = nullptr;
2786*12c85518Srobert IfStmtKind IfBlockKind = IfStmtKind::NotIf;
2787*12c85518Srobert
2788*12c85518Srobert if (isBlockBegin(*FormatTok)) {
2789*12c85518Srobert FormatTok->setFinalizedType(TT_ControlStatementLBrace);
2790*12c85518Srobert IfLeftBrace = FormatTok;
2791e5dd7070Spatrick CompoundStatementIndenter Indenter(this, Style, Line->Level);
2792*12c85518Srobert parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,
2793*12c85518Srobert /*MunchSemi=*/true, KeepIfBraces, &IfBlockKind);
2794e5dd7070Spatrick if (Style.BraceWrapping.BeforeElse)
2795e5dd7070Spatrick addUnwrappedLine();
2796e5dd7070Spatrick else
2797e5dd7070Spatrick NeedsUnwrappedLine = true;
2798e5dd7070Spatrick } else {
2799*12c85518Srobert parseUnbracedBody();
2800e5dd7070Spatrick }
2801*12c85518Srobert
2802*12c85518Srobert if (Style.RemoveBracesLLVM) {
2803*12c85518Srobert assert(!NestedTooDeep.empty());
2804*12c85518Srobert KeepIfBraces = KeepIfBraces ||
2805*12c85518Srobert (IfLeftBrace && !IfLeftBrace->MatchingParen) ||
2806*12c85518Srobert NestedTooDeep.back() || IfBlockKind == IfStmtKind::IfOnly ||
2807*12c85518Srobert IfBlockKind == IfStmtKind::IfElseIf;
2808*12c85518Srobert }
2809*12c85518Srobert
2810*12c85518Srobert bool KeepElseBraces = KeepIfBraces;
2811*12c85518Srobert FormatToken *ElseLeftBrace = nullptr;
2812*12c85518Srobert IfStmtKind Kind = IfStmtKind::IfOnly;
2813*12c85518Srobert
2814*12c85518Srobert if (FormatTok->is(tok::kw_else)) {
2815*12c85518Srobert if (Style.RemoveBracesLLVM) {
2816*12c85518Srobert NestedTooDeep.back() = false;
2817*12c85518Srobert Kind = IfStmtKind::IfElse;
2818*12c85518Srobert }
2819e5dd7070Spatrick nextToken();
2820*12c85518Srobert handleAttributes();
2821*12c85518Srobert if (isBlockBegin(*FormatTok)) {
2822*12c85518Srobert const bool FollowedByIf = Tokens->peekNextToken()->is(tok::kw_if);
2823*12c85518Srobert FormatTok->setFinalizedType(TT_ElseLBrace);
2824*12c85518Srobert ElseLeftBrace = FormatTok;
2825e5dd7070Spatrick CompoundStatementIndenter Indenter(this, Style, Line->Level);
2826*12c85518Srobert IfStmtKind ElseBlockKind = IfStmtKind::NotIf;
2827*12c85518Srobert FormatToken *IfLBrace =
2828*12c85518Srobert parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,
2829*12c85518Srobert /*MunchSemi=*/true, KeepElseBraces, &ElseBlockKind);
2830*12c85518Srobert if (FormatTok->is(tok::kw_else)) {
2831*12c85518Srobert KeepElseBraces = KeepElseBraces ||
2832*12c85518Srobert ElseBlockKind == IfStmtKind::IfOnly ||
2833*12c85518Srobert ElseBlockKind == IfStmtKind::IfElseIf;
2834*12c85518Srobert } else if (FollowedByIf && IfLBrace && !IfLBrace->Optional) {
2835*12c85518Srobert KeepElseBraces = true;
2836*12c85518Srobert assert(ElseLeftBrace->MatchingParen);
2837*12c85518Srobert markOptionalBraces(ElseLeftBrace);
2838*12c85518Srobert }
2839e5dd7070Spatrick addUnwrappedLine();
2840*12c85518Srobert } else if (FormatTok->is(tok::kw_if)) {
2841*12c85518Srobert const FormatToken *Previous = Tokens->getPreviousToken();
2842*12c85518Srobert assert(Previous);
2843*12c85518Srobert const bool IsPrecededByComment = Previous->is(tok::comment);
2844*12c85518Srobert if (IsPrecededByComment) {
2845a9ac8606Spatrick addUnwrappedLine();
2846a9ac8606Spatrick ++Line->Level;
2847a9ac8606Spatrick }
2848*12c85518Srobert bool TooDeep = true;
2849*12c85518Srobert if (Style.RemoveBracesLLVM) {
2850*12c85518Srobert Kind = IfStmtKind::IfElseIf;
2851*12c85518Srobert TooDeep = NestedTooDeep.pop_back_val();
2852*12c85518Srobert }
2853*12c85518Srobert ElseLeftBrace = parseIfThenElse(/*IfKind=*/nullptr, KeepIfBraces);
2854*12c85518Srobert if (Style.RemoveBracesLLVM)
2855*12c85518Srobert NestedTooDeep.push_back(TooDeep);
2856*12c85518Srobert if (IsPrecededByComment)
2857a9ac8606Spatrick --Line->Level;
2858e5dd7070Spatrick } else {
2859*12c85518Srobert parseUnbracedBody(/*CheckEOF=*/true);
2860e5dd7070Spatrick }
2861*12c85518Srobert } else {
2862*12c85518Srobert KeepIfBraces = KeepIfBraces || IfBlockKind == IfStmtKind::IfElse;
2863*12c85518Srobert if (NeedsUnwrappedLine)
2864e5dd7070Spatrick addUnwrappedLine();
2865e5dd7070Spatrick }
2866*12c85518Srobert
2867*12c85518Srobert if (!Style.RemoveBracesLLVM)
2868*12c85518Srobert return nullptr;
2869*12c85518Srobert
2870*12c85518Srobert assert(!NestedTooDeep.empty());
2871*12c85518Srobert KeepElseBraces = KeepElseBraces ||
2872*12c85518Srobert (ElseLeftBrace && !ElseLeftBrace->MatchingParen) ||
2873*12c85518Srobert NestedTooDeep.back();
2874*12c85518Srobert
2875*12c85518Srobert NestedTooDeep.pop_back();
2876*12c85518Srobert
2877*12c85518Srobert if (!KeepIfBraces && !KeepElseBraces) {
2878*12c85518Srobert markOptionalBraces(IfLeftBrace);
2879*12c85518Srobert markOptionalBraces(ElseLeftBrace);
2880*12c85518Srobert } else if (IfLeftBrace) {
2881*12c85518Srobert FormatToken *IfRightBrace = IfLeftBrace->MatchingParen;
2882*12c85518Srobert if (IfRightBrace) {
2883*12c85518Srobert assert(IfRightBrace->MatchingParen == IfLeftBrace);
2884*12c85518Srobert assert(!IfLeftBrace->Optional);
2885*12c85518Srobert assert(!IfRightBrace->Optional);
2886*12c85518Srobert IfLeftBrace->MatchingParen = nullptr;
2887*12c85518Srobert IfRightBrace->MatchingParen = nullptr;
2888*12c85518Srobert }
2889*12c85518Srobert }
2890*12c85518Srobert
2891*12c85518Srobert if (IfKind)
2892*12c85518Srobert *IfKind = Kind;
2893*12c85518Srobert
2894*12c85518Srobert return IfLeftBrace;
2895e5dd7070Spatrick }
2896e5dd7070Spatrick
parseTryCatch()2897e5dd7070Spatrick void UnwrappedLineParser::parseTryCatch() {
2898e5dd7070Spatrick assert(FormatTok->isOneOf(tok::kw_try, tok::kw___try) && "'try' expected");
2899e5dd7070Spatrick nextToken();
2900e5dd7070Spatrick bool NeedsUnwrappedLine = false;
2901e5dd7070Spatrick if (FormatTok->is(tok::colon)) {
2902e5dd7070Spatrick // We are in a function try block, what comes is an initializer list.
2903e5dd7070Spatrick nextToken();
2904ec727ea7Spatrick
2905ec727ea7Spatrick // In case identifiers were removed by clang-tidy, what might follow is
2906ec727ea7Spatrick // multiple commas in sequence - before the first identifier.
2907ec727ea7Spatrick while (FormatTok->is(tok::comma))
2908ec727ea7Spatrick nextToken();
2909ec727ea7Spatrick
2910e5dd7070Spatrick while (FormatTok->is(tok::identifier)) {
2911e5dd7070Spatrick nextToken();
2912e5dd7070Spatrick if (FormatTok->is(tok::l_paren))
2913e5dd7070Spatrick parseParens();
2914a9ac8606Spatrick if (FormatTok->Previous && FormatTok->Previous->is(tok::identifier) &&
2915a9ac8606Spatrick FormatTok->is(tok::l_brace)) {
2916a9ac8606Spatrick do {
2917a9ac8606Spatrick nextToken();
2918a9ac8606Spatrick } while (!FormatTok->is(tok::r_brace));
2919a9ac8606Spatrick nextToken();
2920a9ac8606Spatrick }
2921ec727ea7Spatrick
2922ec727ea7Spatrick // In case identifiers were removed by clang-tidy, what might follow is
2923ec727ea7Spatrick // multiple commas in sequence - after the first identifier.
2924ec727ea7Spatrick while (FormatTok->is(tok::comma))
2925e5dd7070Spatrick nextToken();
2926e5dd7070Spatrick }
2927e5dd7070Spatrick }
2928e5dd7070Spatrick // Parse try with resource.
2929*12c85518Srobert if (Style.Language == FormatStyle::LK_Java && FormatTok->is(tok::l_paren))
2930e5dd7070Spatrick parseParens();
2931*12c85518Srobert
2932*12c85518Srobert keepAncestorBraces();
2933*12c85518Srobert
2934e5dd7070Spatrick if (FormatTok->is(tok::l_brace)) {
2935e5dd7070Spatrick CompoundStatementIndenter Indenter(this, Style, Line->Level);
2936*12c85518Srobert parseBlock();
2937*12c85518Srobert if (Style.BraceWrapping.BeforeCatch)
2938e5dd7070Spatrick addUnwrappedLine();
2939*12c85518Srobert else
2940e5dd7070Spatrick NeedsUnwrappedLine = true;
2941e5dd7070Spatrick } else if (!FormatTok->is(tok::kw_catch)) {
2942e5dd7070Spatrick // The C++ standard requires a compound-statement after a try.
2943e5dd7070Spatrick // If there's none, we try to assume there's a structuralElement
2944e5dd7070Spatrick // and try to continue.
2945e5dd7070Spatrick addUnwrappedLine();
2946e5dd7070Spatrick ++Line->Level;
2947e5dd7070Spatrick parseStructuralElement();
2948e5dd7070Spatrick --Line->Level;
2949e5dd7070Spatrick }
2950*12c85518Srobert while (true) {
2951e5dd7070Spatrick if (FormatTok->is(tok::at))
2952e5dd7070Spatrick nextToken();
2953e5dd7070Spatrick if (!(FormatTok->isOneOf(tok::kw_catch, Keywords.kw___except,
2954e5dd7070Spatrick tok::kw___finally) ||
2955*12c85518Srobert ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&
2956e5dd7070Spatrick FormatTok->is(Keywords.kw_finally)) ||
2957*12c85518Srobert (FormatTok->isObjCAtKeyword(tok::objc_catch) ||
2958*12c85518Srobert FormatTok->isObjCAtKeyword(tok::objc_finally)))) {
2959e5dd7070Spatrick break;
2960*12c85518Srobert }
2961e5dd7070Spatrick nextToken();
2962e5dd7070Spatrick while (FormatTok->isNot(tok::l_brace)) {
2963e5dd7070Spatrick if (FormatTok->is(tok::l_paren)) {
2964e5dd7070Spatrick parseParens();
2965e5dd7070Spatrick continue;
2966e5dd7070Spatrick }
2967*12c85518Srobert if (FormatTok->isOneOf(tok::semi, tok::r_brace, tok::eof)) {
2968*12c85518Srobert if (Style.RemoveBracesLLVM)
2969*12c85518Srobert NestedTooDeep.pop_back();
2970e5dd7070Spatrick return;
2971*12c85518Srobert }
2972e5dd7070Spatrick nextToken();
2973e5dd7070Spatrick }
2974e5dd7070Spatrick NeedsUnwrappedLine = false;
2975*12c85518Srobert Line->MustBeDeclaration = false;
2976e5dd7070Spatrick CompoundStatementIndenter Indenter(this, Style, Line->Level);
2977*12c85518Srobert parseBlock();
2978e5dd7070Spatrick if (Style.BraceWrapping.BeforeCatch)
2979e5dd7070Spatrick addUnwrappedLine();
2980e5dd7070Spatrick else
2981e5dd7070Spatrick NeedsUnwrappedLine = true;
2982e5dd7070Spatrick }
2983*12c85518Srobert
2984*12c85518Srobert if (Style.RemoveBracesLLVM)
2985*12c85518Srobert NestedTooDeep.pop_back();
2986*12c85518Srobert
2987e5dd7070Spatrick if (NeedsUnwrappedLine)
2988e5dd7070Spatrick addUnwrappedLine();
2989e5dd7070Spatrick }
2990e5dd7070Spatrick
parseNamespace()2991e5dd7070Spatrick void UnwrappedLineParser::parseNamespace() {
2992e5dd7070Spatrick assert(FormatTok->isOneOf(tok::kw_namespace, TT_NamespaceMacro) &&
2993e5dd7070Spatrick "'namespace' expected");
2994e5dd7070Spatrick
2995e5dd7070Spatrick const FormatToken &InitialToken = *FormatTok;
2996e5dd7070Spatrick nextToken();
2997e5dd7070Spatrick if (InitialToken.is(TT_NamespaceMacro)) {
2998e5dd7070Spatrick parseParens();
2999e5dd7070Spatrick } else {
3000e5dd7070Spatrick while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::kw_inline,
3001*12c85518Srobert tok::l_square, tok::period, tok::l_paren) ||
3002*12c85518Srobert (Style.isCSharp() && FormatTok->is(tok::kw_union))) {
3003e5dd7070Spatrick if (FormatTok->is(tok::l_square))
3004e5dd7070Spatrick parseSquare();
3005*12c85518Srobert else if (FormatTok->is(tok::l_paren))
3006*12c85518Srobert parseParens();
3007e5dd7070Spatrick else
3008e5dd7070Spatrick nextToken();
3009e5dd7070Spatrick }
3010e5dd7070Spatrick }
3011*12c85518Srobert if (FormatTok->is(tok::l_brace)) {
3012e5dd7070Spatrick if (ShouldBreakBeforeBrace(Style, InitialToken))
3013e5dd7070Spatrick addUnwrappedLine();
3014e5dd7070Spatrick
3015a9ac8606Spatrick unsigned AddLevels =
3016a9ac8606Spatrick Style.NamespaceIndentation == FormatStyle::NI_All ||
3017e5dd7070Spatrick (Style.NamespaceIndentation == FormatStyle::NI_Inner &&
3018a9ac8606Spatrick DeclarationScopeStack.size() > 1)
3019a9ac8606Spatrick ? 1u
3020a9ac8606Spatrick : 0u;
3021a9ac8606Spatrick bool ManageWhitesmithsBraces =
3022a9ac8606Spatrick AddLevels == 0u &&
3023a9ac8606Spatrick Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths;
3024a9ac8606Spatrick
3025a9ac8606Spatrick // If we're in Whitesmiths mode, indent the brace if we're not indenting
3026a9ac8606Spatrick // the whole block.
3027a9ac8606Spatrick if (ManageWhitesmithsBraces)
3028a9ac8606Spatrick ++Line->Level;
3029a9ac8606Spatrick
3030*12c85518Srobert parseBlock(/*MustBeDeclaration=*/true, AddLevels, /*MunchSemi=*/true,
3031*12c85518Srobert /*KeepBraces=*/true, /*IfKind=*/nullptr,
3032*12c85518Srobert ManageWhitesmithsBraces);
3033a9ac8606Spatrick
3034e5dd7070Spatrick // Munch the semicolon after a namespace. This is more common than one would
3035ec727ea7Spatrick // think. Putting the semicolon into its own line is very ugly.
3036*12c85518Srobert if (FormatTok->is(tok::semi))
3037e5dd7070Spatrick nextToken();
3038a9ac8606Spatrick
3039a9ac8606Spatrick addUnwrappedLine(AddLevels > 0 ? LineLevel::Remove : LineLevel::Keep);
3040a9ac8606Spatrick
3041a9ac8606Spatrick if (ManageWhitesmithsBraces)
3042a9ac8606Spatrick --Line->Level;
3043e5dd7070Spatrick }
3044e5dd7070Spatrick // FIXME: Add error handling.
3045e5dd7070Spatrick }
3046e5dd7070Spatrick
parseNew()3047e5dd7070Spatrick void UnwrappedLineParser::parseNew() {
3048e5dd7070Spatrick assert(FormatTok->is(tok::kw_new) && "'new' expected");
3049e5dd7070Spatrick nextToken();
3050ec727ea7Spatrick
3051ec727ea7Spatrick if (Style.isCSharp()) {
3052ec727ea7Spatrick do {
3053*12c85518Srobert // Handle constructor invocation, e.g. `new(field: value)`.
3054*12c85518Srobert if (FormatTok->is(tok::l_paren))
3055*12c85518Srobert parseParens();
3056*12c85518Srobert
3057*12c85518Srobert // Handle array initialization syntax, e.g. `new[] {10, 20, 30}`.
3058ec727ea7Spatrick if (FormatTok->is(tok::l_brace))
3059ec727ea7Spatrick parseBracedList();
3060ec727ea7Spatrick
3061ec727ea7Spatrick if (FormatTok->isOneOf(tok::semi, tok::comma))
3062ec727ea7Spatrick return;
3063ec727ea7Spatrick
3064ec727ea7Spatrick nextToken();
3065ec727ea7Spatrick } while (!eof());
3066ec727ea7Spatrick }
3067ec727ea7Spatrick
3068e5dd7070Spatrick if (Style.Language != FormatStyle::LK_Java)
3069e5dd7070Spatrick return;
3070e5dd7070Spatrick
3071e5dd7070Spatrick // In Java, we can parse everything up to the parens, which aren't optional.
3072e5dd7070Spatrick do {
3073e5dd7070Spatrick // There should not be a ;, { or } before the new's open paren.
3074e5dd7070Spatrick if (FormatTok->isOneOf(tok::semi, tok::l_brace, tok::r_brace))
3075e5dd7070Spatrick return;
3076e5dd7070Spatrick
3077e5dd7070Spatrick // Consume the parens.
3078e5dd7070Spatrick if (FormatTok->is(tok::l_paren)) {
3079e5dd7070Spatrick parseParens();
3080e5dd7070Spatrick
3081e5dd7070Spatrick // If there is a class body of an anonymous class, consume that as child.
3082e5dd7070Spatrick if (FormatTok->is(tok::l_brace))
3083e5dd7070Spatrick parseChildBlock();
3084e5dd7070Spatrick return;
3085e5dd7070Spatrick }
3086e5dd7070Spatrick nextToken();
3087e5dd7070Spatrick } while (!eof());
3088e5dd7070Spatrick }
3089e5dd7070Spatrick
parseLoopBody(bool KeepBraces,bool WrapRightBrace)3090*12c85518Srobert void UnwrappedLineParser::parseLoopBody(bool KeepBraces, bool WrapRightBrace) {
3091*12c85518Srobert keepAncestorBraces();
3092*12c85518Srobert
3093*12c85518Srobert if (isBlockBegin(*FormatTok)) {
3094*12c85518Srobert if (!KeepBraces)
3095*12c85518Srobert FormatTok->setFinalizedType(TT_ControlStatementLBrace);
3096*12c85518Srobert FormatToken *LeftBrace = FormatTok;
3097*12c85518Srobert CompoundStatementIndenter Indenter(this, Style, Line->Level);
3098*12c85518Srobert parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,
3099*12c85518Srobert /*MunchSemi=*/true, KeepBraces);
3100*12c85518Srobert if (!KeepBraces) {
3101*12c85518Srobert assert(!NestedTooDeep.empty());
3102*12c85518Srobert if (!NestedTooDeep.back())
3103*12c85518Srobert markOptionalBraces(LeftBrace);
3104*12c85518Srobert }
3105*12c85518Srobert if (WrapRightBrace)
3106*12c85518Srobert addUnwrappedLine();
3107*12c85518Srobert } else {
3108*12c85518Srobert parseUnbracedBody();
3109*12c85518Srobert }
3110*12c85518Srobert
3111*12c85518Srobert if (!KeepBraces)
3112*12c85518Srobert NestedTooDeep.pop_back();
3113*12c85518Srobert }
3114*12c85518Srobert
parseForOrWhileLoop()3115e5dd7070Spatrick void UnwrappedLineParser::parseForOrWhileLoop() {
3116e5dd7070Spatrick assert(FormatTok->isOneOf(tok::kw_for, tok::kw_while, TT_ForEachMacro) &&
3117e5dd7070Spatrick "'for', 'while' or foreach macro expected");
3118*12c85518Srobert const bool KeepBraces = !Style.RemoveBracesLLVM ||
3119*12c85518Srobert !FormatTok->isOneOf(tok::kw_for, tok::kw_while);
3120*12c85518Srobert
3121e5dd7070Spatrick nextToken();
3122e5dd7070Spatrick // JS' for await ( ...
3123*12c85518Srobert if (Style.isJavaScript() && FormatTok->is(Keywords.kw_await))
3124e5dd7070Spatrick nextToken();
3125*12c85518Srobert if (Style.isCpp() && FormatTok->is(tok::kw_co_await))
3126*12c85518Srobert nextToken();
3127*12c85518Srobert if (FormatTok->is(tok::l_paren))
3128e5dd7070Spatrick parseParens();
3129*12c85518Srobert
3130*12c85518Srobert handleAttributes();
3131*12c85518Srobert parseLoopBody(KeepBraces, /*WrapRightBrace=*/true);
3132e5dd7070Spatrick }
3133e5dd7070Spatrick
parseDoWhile()3134e5dd7070Spatrick void UnwrappedLineParser::parseDoWhile() {
3135*12c85518Srobert assert(FormatTok->is(tok::kw_do) && "'do' expected");
3136e5dd7070Spatrick nextToken();
3137*12c85518Srobert
3138*12c85518Srobert parseLoopBody(/*KeepBraces=*/true, Style.BraceWrapping.BeforeWhile);
3139e5dd7070Spatrick
3140e5dd7070Spatrick // FIXME: Add error handling.
3141*12c85518Srobert if (!FormatTok->is(tok::kw_while)) {
3142e5dd7070Spatrick addUnwrappedLine();
3143e5dd7070Spatrick return;
3144e5dd7070Spatrick }
3145e5dd7070Spatrick
3146a9ac8606Spatrick // If in Whitesmiths mode, the line with the while() needs to be indented
3147a9ac8606Spatrick // to the same level as the block.
3148a9ac8606Spatrick if (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths)
3149a9ac8606Spatrick ++Line->Level;
3150a9ac8606Spatrick
3151e5dd7070Spatrick nextToken();
3152e5dd7070Spatrick parseStructuralElement();
3153e5dd7070Spatrick }
3154e5dd7070Spatrick
parseLabel(bool LeftAlignLabel)3155e5dd7070Spatrick void UnwrappedLineParser::parseLabel(bool LeftAlignLabel) {
3156e5dd7070Spatrick nextToken();
3157e5dd7070Spatrick unsigned OldLineLevel = Line->Level;
3158e5dd7070Spatrick if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0))
3159e5dd7070Spatrick --Line->Level;
3160e5dd7070Spatrick if (LeftAlignLabel)
3161e5dd7070Spatrick Line->Level = 0;
3162a9ac8606Spatrick
3163ec727ea7Spatrick if (!Style.IndentCaseBlocks && CommentsBeforeNextToken.empty() &&
3164*12c85518Srobert FormatTok->is(tok::l_brace)) {
3165a9ac8606Spatrick
3166e5dd7070Spatrick CompoundStatementIndenter Indenter(this, Line->Level,
3167e5dd7070Spatrick Style.BraceWrapping.AfterCaseLabel,
3168e5dd7070Spatrick Style.BraceWrapping.IndentBraces);
3169*12c85518Srobert parseBlock();
3170*12c85518Srobert if (FormatTok->is(tok::kw_break)) {
3171e5dd7070Spatrick if (Style.BraceWrapping.AfterControlStatement ==
3172ec727ea7Spatrick FormatStyle::BWACS_Always) {
3173e5dd7070Spatrick addUnwrappedLine();
3174ec727ea7Spatrick if (!Style.IndentCaseBlocks &&
3175ec727ea7Spatrick Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths) {
3176*12c85518Srobert ++Line->Level;
3177ec727ea7Spatrick }
3178ec727ea7Spatrick }
3179e5dd7070Spatrick parseStructuralElement();
3180e5dd7070Spatrick }
3181e5dd7070Spatrick addUnwrappedLine();
3182e5dd7070Spatrick } else {
3183e5dd7070Spatrick if (FormatTok->is(tok::semi))
3184e5dd7070Spatrick nextToken();
3185e5dd7070Spatrick addUnwrappedLine();
3186e5dd7070Spatrick }
3187e5dd7070Spatrick Line->Level = OldLineLevel;
3188e5dd7070Spatrick if (FormatTok->isNot(tok::l_brace)) {
3189e5dd7070Spatrick parseStructuralElement();
3190e5dd7070Spatrick addUnwrappedLine();
3191e5dd7070Spatrick }
3192e5dd7070Spatrick }
3193e5dd7070Spatrick
parseCaseLabel()3194e5dd7070Spatrick void UnwrappedLineParser::parseCaseLabel() {
3195*12c85518Srobert assert(FormatTok->is(tok::kw_case) && "'case' expected");
3196a9ac8606Spatrick
3197e5dd7070Spatrick // FIXME: fix handling of complex expressions here.
3198e5dd7070Spatrick do {
3199e5dd7070Spatrick nextToken();
3200*12c85518Srobert } while (!eof() && !FormatTok->is(tok::colon));
3201e5dd7070Spatrick parseLabel();
3202e5dd7070Spatrick }
3203e5dd7070Spatrick
parseSwitch()3204e5dd7070Spatrick void UnwrappedLineParser::parseSwitch() {
3205*12c85518Srobert assert(FormatTok->is(tok::kw_switch) && "'switch' expected");
3206e5dd7070Spatrick nextToken();
3207*12c85518Srobert if (FormatTok->is(tok::l_paren))
3208e5dd7070Spatrick parseParens();
3209*12c85518Srobert
3210*12c85518Srobert keepAncestorBraces();
3211*12c85518Srobert
3212*12c85518Srobert if (FormatTok->is(tok::l_brace)) {
3213e5dd7070Spatrick CompoundStatementIndenter Indenter(this, Style, Line->Level);
3214*12c85518Srobert parseBlock();
3215e5dd7070Spatrick addUnwrappedLine();
3216e5dd7070Spatrick } else {
3217e5dd7070Spatrick addUnwrappedLine();
3218e5dd7070Spatrick ++Line->Level;
3219e5dd7070Spatrick parseStructuralElement();
3220e5dd7070Spatrick --Line->Level;
3221e5dd7070Spatrick }
3222*12c85518Srobert
3223*12c85518Srobert if (Style.RemoveBracesLLVM)
3224*12c85518Srobert NestedTooDeep.pop_back();
3225*12c85518Srobert }
3226*12c85518Srobert
3227*12c85518Srobert // Operators that can follow a C variable.
isCOperatorFollowingVar(tok::TokenKind kind)3228*12c85518Srobert static bool isCOperatorFollowingVar(tok::TokenKind kind) {
3229*12c85518Srobert switch (kind) {
3230*12c85518Srobert case tok::ampamp:
3231*12c85518Srobert case tok::ampequal:
3232*12c85518Srobert case tok::arrow:
3233*12c85518Srobert case tok::caret:
3234*12c85518Srobert case tok::caretequal:
3235*12c85518Srobert case tok::comma:
3236*12c85518Srobert case tok::ellipsis:
3237*12c85518Srobert case tok::equal:
3238*12c85518Srobert case tok::equalequal:
3239*12c85518Srobert case tok::exclaim:
3240*12c85518Srobert case tok::exclaimequal:
3241*12c85518Srobert case tok::greater:
3242*12c85518Srobert case tok::greaterequal:
3243*12c85518Srobert case tok::greatergreater:
3244*12c85518Srobert case tok::greatergreaterequal:
3245*12c85518Srobert case tok::l_paren:
3246*12c85518Srobert case tok::l_square:
3247*12c85518Srobert case tok::less:
3248*12c85518Srobert case tok::lessequal:
3249*12c85518Srobert case tok::lessless:
3250*12c85518Srobert case tok::lesslessequal:
3251*12c85518Srobert case tok::minus:
3252*12c85518Srobert case tok::minusequal:
3253*12c85518Srobert case tok::minusminus:
3254*12c85518Srobert case tok::percent:
3255*12c85518Srobert case tok::percentequal:
3256*12c85518Srobert case tok::period:
3257*12c85518Srobert case tok::pipe:
3258*12c85518Srobert case tok::pipeequal:
3259*12c85518Srobert case tok::pipepipe:
3260*12c85518Srobert case tok::plus:
3261*12c85518Srobert case tok::plusequal:
3262*12c85518Srobert case tok::plusplus:
3263*12c85518Srobert case tok::question:
3264*12c85518Srobert case tok::r_brace:
3265*12c85518Srobert case tok::r_paren:
3266*12c85518Srobert case tok::r_square:
3267*12c85518Srobert case tok::semi:
3268*12c85518Srobert case tok::slash:
3269*12c85518Srobert case tok::slashequal:
3270*12c85518Srobert case tok::star:
3271*12c85518Srobert case tok::starequal:
3272*12c85518Srobert return true;
3273*12c85518Srobert default:
3274*12c85518Srobert return false;
3275*12c85518Srobert }
3276e5dd7070Spatrick }
3277e5dd7070Spatrick
parseAccessSpecifier()3278e5dd7070Spatrick void UnwrappedLineParser::parseAccessSpecifier() {
3279*12c85518Srobert FormatToken *AccessSpecifierCandidate = FormatTok;
3280e5dd7070Spatrick nextToken();
3281e5dd7070Spatrick // Understand Qt's slots.
3282e5dd7070Spatrick if (FormatTok->isOneOf(Keywords.kw_slots, Keywords.kw_qslots))
3283e5dd7070Spatrick nextToken();
3284e5dd7070Spatrick // Otherwise, we don't know what it is, and we'd better keep the next token.
3285*12c85518Srobert if (FormatTok->is(tok::colon)) {
3286e5dd7070Spatrick nextToken();
3287e5dd7070Spatrick addUnwrappedLine();
3288*12c85518Srobert } else if (!FormatTok->is(tok::coloncolon) &&
3289*12c85518Srobert !isCOperatorFollowingVar(FormatTok->Tok.getKind())) {
3290*12c85518Srobert // Not a variable name nor namespace name.
3291*12c85518Srobert addUnwrappedLine();
3292*12c85518Srobert } else if (AccessSpecifierCandidate) {
3293*12c85518Srobert // Consider the access specifier to be a C identifier.
3294*12c85518Srobert AccessSpecifierCandidate->Tok.setKind(tok::identifier);
3295a9ac8606Spatrick }
3296a9ac8606Spatrick }
3297a9ac8606Spatrick
3298*12c85518Srobert /// \brief Parses a requires, decides if it is a clause or an expression.
3299*12c85518Srobert /// \pre The current token has to be the requires keyword.
3300*12c85518Srobert /// \returns true if it parsed a clause.
parseRequires()3301*12c85518Srobert bool clang::format::UnwrappedLineParser::parseRequires() {
3302*12c85518Srobert assert(FormatTok->is(tok::kw_requires) && "'requires' expected");
3303*12c85518Srobert auto RequiresToken = FormatTok;
3304*12c85518Srobert
3305*12c85518Srobert // We try to guess if it is a requires clause, or a requires expression. For
3306*12c85518Srobert // that we first consume the keyword and check the next token.
3307*12c85518Srobert nextToken();
3308*12c85518Srobert
3309*12c85518Srobert switch (FormatTok->Tok.getKind()) {
3310*12c85518Srobert case tok::l_brace:
3311*12c85518Srobert // This can only be an expression, never a clause.
3312*12c85518Srobert parseRequiresExpression(RequiresToken);
3313*12c85518Srobert return false;
3314*12c85518Srobert case tok::l_paren:
3315*12c85518Srobert // Clauses and expression can start with a paren, it's unclear what we have.
3316*12c85518Srobert break;
3317*12c85518Srobert default:
3318*12c85518Srobert // All other tokens can only be a clause.
3319*12c85518Srobert parseRequiresClause(RequiresToken);
3320*12c85518Srobert return true;
3321a9ac8606Spatrick }
3322a9ac8606Spatrick
3323*12c85518Srobert // Looking forward we would have to decide if there are function declaration
3324*12c85518Srobert // like arguments to the requires expression:
3325*12c85518Srobert // requires (T t) {
3326*12c85518Srobert // Or there is a constraint expression for the requires clause:
3327*12c85518Srobert // requires (C<T> && ...
3328*12c85518Srobert
3329*12c85518Srobert // But first let's look behind.
3330*12c85518Srobert auto *PreviousNonComment = RequiresToken->getPreviousNonComment();
3331*12c85518Srobert
3332*12c85518Srobert if (!PreviousNonComment ||
3333*12c85518Srobert PreviousNonComment->is(TT_RequiresExpressionLBrace)) {
3334*12c85518Srobert // If there is no token, or an expression left brace, we are a requires
3335*12c85518Srobert // clause within a requires expression.
3336*12c85518Srobert parseRequiresClause(RequiresToken);
3337*12c85518Srobert return true;
3338a9ac8606Spatrick }
3339a9ac8606Spatrick
3340*12c85518Srobert switch (PreviousNonComment->Tok.getKind()) {
3341*12c85518Srobert case tok::greater:
3342*12c85518Srobert case tok::r_paren:
3343*12c85518Srobert case tok::kw_noexcept:
3344*12c85518Srobert case tok::kw_const:
3345*12c85518Srobert // This is a requires clause.
3346*12c85518Srobert parseRequiresClause(RequiresToken);
3347*12c85518Srobert return true;
3348*12c85518Srobert case tok::amp:
3349*12c85518Srobert case tok::ampamp: {
3350*12c85518Srobert // This can be either:
3351*12c85518Srobert // if (... && requires (T t) ...)
3352*12c85518Srobert // Or
3353*12c85518Srobert // void member(...) && requires (C<T> ...
3354*12c85518Srobert // We check the one token before that for a const:
3355*12c85518Srobert // void member(...) const && requires (C<T> ...
3356*12c85518Srobert auto PrevPrev = PreviousNonComment->getPreviousNonComment();
3357*12c85518Srobert if (PrevPrev && PrevPrev->is(tok::kw_const)) {
3358*12c85518Srobert parseRequiresClause(RequiresToken);
3359*12c85518Srobert return true;
3360a9ac8606Spatrick }
3361a9ac8606Spatrick break;
3362a9ac8606Spatrick }
3363*12c85518Srobert default:
3364*12c85518Srobert if (PreviousNonComment->isTypeOrIdentifier()) {
3365*12c85518Srobert // This is a requires clause.
3366*12c85518Srobert parseRequiresClause(RequiresToken);
3367*12c85518Srobert return true;
3368*12c85518Srobert }
3369*12c85518Srobert // It's an expression.
3370*12c85518Srobert parseRequiresExpression(RequiresToken);
3371*12c85518Srobert return false;
3372*12c85518Srobert }
3373*12c85518Srobert
3374*12c85518Srobert // Now we look forward and try to check if the paren content is a parameter
3375*12c85518Srobert // list. The parameters can be cv-qualified and contain references or
3376*12c85518Srobert // pointers.
3377*12c85518Srobert // So we want basically to check for TYPE NAME, but TYPE can contain all kinds
3378*12c85518Srobert // of stuff: typename, const, *, &, &&, ::, identifiers.
3379*12c85518Srobert
3380*12c85518Srobert unsigned StoredPosition = Tokens->getPosition();
3381*12c85518Srobert FormatToken *NextToken = Tokens->getNextToken();
3382*12c85518Srobert int Lookahead = 0;
3383*12c85518Srobert auto PeekNext = [&Lookahead, &NextToken, this] {
3384*12c85518Srobert ++Lookahead;
3385*12c85518Srobert NextToken = Tokens->getNextToken();
3386*12c85518Srobert };
3387*12c85518Srobert
3388*12c85518Srobert bool FoundType = false;
3389*12c85518Srobert bool LastWasColonColon = false;
3390*12c85518Srobert int OpenAngles = 0;
3391*12c85518Srobert
3392*12c85518Srobert for (; Lookahead < 50; PeekNext()) {
3393*12c85518Srobert switch (NextToken->Tok.getKind()) {
3394*12c85518Srobert case tok::kw_volatile:
3395*12c85518Srobert case tok::kw_const:
3396*12c85518Srobert case tok::comma:
3397*12c85518Srobert FormatTok = Tokens->setPosition(StoredPosition);
3398*12c85518Srobert parseRequiresExpression(RequiresToken);
3399*12c85518Srobert return false;
3400*12c85518Srobert case tok::r_paren:
3401*12c85518Srobert case tok::pipepipe:
3402*12c85518Srobert FormatTok = Tokens->setPosition(StoredPosition);
3403*12c85518Srobert parseRequiresClause(RequiresToken);
3404*12c85518Srobert return true;
3405*12c85518Srobert case tok::eof:
3406*12c85518Srobert // Break out of the loop.
3407*12c85518Srobert Lookahead = 50;
3408*12c85518Srobert break;
3409*12c85518Srobert case tok::coloncolon:
3410*12c85518Srobert LastWasColonColon = true;
3411*12c85518Srobert break;
3412*12c85518Srobert case tok::identifier:
3413*12c85518Srobert if (FoundType && !LastWasColonColon && OpenAngles == 0) {
3414*12c85518Srobert FormatTok = Tokens->setPosition(StoredPosition);
3415*12c85518Srobert parseRequiresExpression(RequiresToken);
3416*12c85518Srobert return false;
3417*12c85518Srobert }
3418*12c85518Srobert FoundType = true;
3419*12c85518Srobert LastWasColonColon = false;
3420*12c85518Srobert break;
3421*12c85518Srobert case tok::less:
3422*12c85518Srobert ++OpenAngles;
3423*12c85518Srobert break;
3424*12c85518Srobert case tok::greater:
3425*12c85518Srobert --OpenAngles;
3426*12c85518Srobert break;
3427*12c85518Srobert default:
3428*12c85518Srobert if (NextToken->isSimpleTypeSpecifier()) {
3429*12c85518Srobert FormatTok = Tokens->setPosition(StoredPosition);
3430*12c85518Srobert parseRequiresExpression(RequiresToken);
3431*12c85518Srobert return false;
3432*12c85518Srobert }
3433*12c85518Srobert break;
3434*12c85518Srobert }
3435*12c85518Srobert }
3436*12c85518Srobert // This seems to be a complicated expression, just assume it's a clause.
3437*12c85518Srobert FormatTok = Tokens->setPosition(StoredPosition);
3438*12c85518Srobert parseRequiresClause(RequiresToken);
3439*12c85518Srobert return true;
3440*12c85518Srobert }
3441*12c85518Srobert
3442*12c85518Srobert /// \brief Parses a requires clause.
3443*12c85518Srobert /// \param RequiresToken The requires keyword token, which starts this clause.
3444*12c85518Srobert /// \pre We need to be on the next token after the requires keyword.
3445*12c85518Srobert /// \sa parseRequiresExpression
3446*12c85518Srobert ///
3447*12c85518Srobert /// Returns if it either has finished parsing the clause, or it detects, that
3448*12c85518Srobert /// the clause is incorrect.
parseRequiresClause(FormatToken * RequiresToken)3449*12c85518Srobert void UnwrappedLineParser::parseRequiresClause(FormatToken *RequiresToken) {
3450*12c85518Srobert assert(FormatTok->getPreviousNonComment() == RequiresToken);
3451*12c85518Srobert assert(RequiresToken->is(tok::kw_requires) && "'requires' expected");
3452*12c85518Srobert
3453*12c85518Srobert // If there is no previous token, we are within a requires expression,
3454*12c85518Srobert // otherwise we will always have the template or function declaration in front
3455*12c85518Srobert // of it.
3456*12c85518Srobert bool InRequiresExpression =
3457*12c85518Srobert !RequiresToken->Previous ||
3458*12c85518Srobert RequiresToken->Previous->is(TT_RequiresExpressionLBrace);
3459*12c85518Srobert
3460*12c85518Srobert RequiresToken->setFinalizedType(InRequiresExpression
3461*12c85518Srobert ? TT_RequiresClauseInARequiresExpression
3462*12c85518Srobert : TT_RequiresClause);
3463*12c85518Srobert
3464*12c85518Srobert // NOTE: parseConstraintExpression is only ever called from this function.
3465*12c85518Srobert // It could be inlined into here.
3466*12c85518Srobert parseConstraintExpression();
3467*12c85518Srobert
3468*12c85518Srobert if (!InRequiresExpression)
3469*12c85518Srobert FormatTok->Previous->ClosesRequiresClause = true;
3470*12c85518Srobert }
3471*12c85518Srobert
3472*12c85518Srobert /// \brief Parses a requires expression.
3473*12c85518Srobert /// \param RequiresToken The requires keyword token, which starts this clause.
3474*12c85518Srobert /// \pre We need to be on the next token after the requires keyword.
3475*12c85518Srobert /// \sa parseRequiresClause
3476*12c85518Srobert ///
3477*12c85518Srobert /// Returns if it either has finished parsing the expression, or it detects,
3478*12c85518Srobert /// that the expression is incorrect.
parseRequiresExpression(FormatToken * RequiresToken)3479*12c85518Srobert void UnwrappedLineParser::parseRequiresExpression(FormatToken *RequiresToken) {
3480*12c85518Srobert assert(FormatTok->getPreviousNonComment() == RequiresToken);
3481*12c85518Srobert assert(RequiresToken->is(tok::kw_requires) && "'requires' expected");
3482*12c85518Srobert
3483*12c85518Srobert RequiresToken->setFinalizedType(TT_RequiresExpression);
3484*12c85518Srobert
3485*12c85518Srobert if (FormatTok->is(tok::l_paren)) {
3486*12c85518Srobert FormatTok->setFinalizedType(TT_RequiresExpressionLParen);
3487*12c85518Srobert parseParens();
3488*12c85518Srobert }
3489*12c85518Srobert
3490*12c85518Srobert if (FormatTok->is(tok::l_brace)) {
3491*12c85518Srobert FormatTok->setFinalizedType(TT_RequiresExpressionLBrace);
3492*12c85518Srobert parseChildBlock(/*CanContainBracedList=*/false,
3493*12c85518Srobert /*NextLBracesType=*/TT_CompoundRequirementLBrace);
3494*12c85518Srobert }
3495*12c85518Srobert }
3496*12c85518Srobert
3497*12c85518Srobert /// \brief Parses a constraint expression.
3498*12c85518Srobert ///
3499*12c85518Srobert /// This is the body of a requires clause. It returns, when the parsing is
3500*12c85518Srobert /// complete, or the expression is incorrect.
parseConstraintExpression()3501*12c85518Srobert void UnwrappedLineParser::parseConstraintExpression() {
3502*12c85518Srobert // The special handling for lambdas is needed since tryToParseLambda() eats a
3503*12c85518Srobert // token and if a requires expression is the last part of a requires clause
3504*12c85518Srobert // and followed by an attribute like [[nodiscard]] the ClosesRequiresClause is
3505*12c85518Srobert // not set on the correct token. Thus we need to be aware if we even expect a
3506*12c85518Srobert // lambda to be possible.
3507*12c85518Srobert // template <typename T> requires requires { ... } [[nodiscard]] ...;
3508*12c85518Srobert bool LambdaNextTimeAllowed = true;
3509*12c85518Srobert do {
3510*12c85518Srobert bool LambdaThisTimeAllowed = std::exchange(LambdaNextTimeAllowed, false);
3511*12c85518Srobert
3512*12c85518Srobert switch (FormatTok->Tok.getKind()) {
3513*12c85518Srobert case tok::kw_requires: {
3514*12c85518Srobert auto RequiresToken = FormatTok;
3515*12c85518Srobert nextToken();
3516*12c85518Srobert parseRequiresExpression(RequiresToken);
3517*12c85518Srobert break;
3518*12c85518Srobert }
3519*12c85518Srobert
3520*12c85518Srobert case tok::l_paren:
3521*12c85518Srobert parseParens(/*AmpAmpTokenType=*/TT_BinaryOperator);
3522*12c85518Srobert break;
3523*12c85518Srobert
3524*12c85518Srobert case tok::l_square:
3525*12c85518Srobert if (!LambdaThisTimeAllowed || !tryToParseLambda())
3526*12c85518Srobert return;
3527*12c85518Srobert break;
3528*12c85518Srobert
3529*12c85518Srobert case tok::kw_const:
3530*12c85518Srobert case tok::semi:
3531*12c85518Srobert case tok::kw_class:
3532*12c85518Srobert case tok::kw_struct:
3533*12c85518Srobert case tok::kw_union:
3534*12c85518Srobert return;
3535*12c85518Srobert
3536*12c85518Srobert case tok::l_brace:
3537*12c85518Srobert // Potential function body.
3538*12c85518Srobert return;
3539*12c85518Srobert
3540*12c85518Srobert case tok::ampamp:
3541*12c85518Srobert case tok::pipepipe:
3542*12c85518Srobert FormatTok->setFinalizedType(TT_BinaryOperator);
3543*12c85518Srobert nextToken();
3544*12c85518Srobert LambdaNextTimeAllowed = true;
3545*12c85518Srobert break;
3546*12c85518Srobert
3547*12c85518Srobert case tok::comma:
3548*12c85518Srobert case tok::comment:
3549*12c85518Srobert LambdaNextTimeAllowed = LambdaThisTimeAllowed;
3550*12c85518Srobert nextToken();
3551*12c85518Srobert break;
3552*12c85518Srobert
3553*12c85518Srobert case tok::kw_sizeof:
3554*12c85518Srobert case tok::greater:
3555*12c85518Srobert case tok::greaterequal:
3556*12c85518Srobert case tok::greatergreater:
3557*12c85518Srobert case tok::less:
3558*12c85518Srobert case tok::lessequal:
3559*12c85518Srobert case tok::lessless:
3560*12c85518Srobert case tok::equalequal:
3561*12c85518Srobert case tok::exclaim:
3562*12c85518Srobert case tok::exclaimequal:
3563*12c85518Srobert case tok::plus:
3564*12c85518Srobert case tok::minus:
3565*12c85518Srobert case tok::star:
3566*12c85518Srobert case tok::slash:
3567*12c85518Srobert LambdaNextTimeAllowed = true;
3568*12c85518Srobert // Just eat them.
3569*12c85518Srobert nextToken();
3570*12c85518Srobert break;
3571*12c85518Srobert
3572*12c85518Srobert case tok::numeric_constant:
3573*12c85518Srobert case tok::coloncolon:
3574*12c85518Srobert case tok::kw_true:
3575*12c85518Srobert case tok::kw_false:
3576*12c85518Srobert // Just eat them.
3577*12c85518Srobert nextToken();
3578*12c85518Srobert break;
3579*12c85518Srobert
3580*12c85518Srobert case tok::kw_static_cast:
3581*12c85518Srobert case tok::kw_const_cast:
3582*12c85518Srobert case tok::kw_reinterpret_cast:
3583*12c85518Srobert case tok::kw_dynamic_cast:
3584*12c85518Srobert nextToken();
3585*12c85518Srobert if (!FormatTok->is(tok::less))
3586*12c85518Srobert return;
3587a9ac8606Spatrick
3588a9ac8606Spatrick nextToken();
3589*12c85518Srobert parseBracedList(/*ContinueOnSemicolons=*/false, /*IsEnum=*/false,
3590*12c85518Srobert /*ClosingBraceKind=*/tok::greater);
3591*12c85518Srobert break;
3592a9ac8606Spatrick
3593*12c85518Srobert case tok::kw_bool:
3594*12c85518Srobert // bool is only allowed if it is directly followed by a paren for a cast:
3595*12c85518Srobert // concept C = bool(...);
3596*12c85518Srobert // and bool is the only type, all other types as cast must be inside a
3597*12c85518Srobert // cast to bool an thus are handled by the other cases.
3598*12c85518Srobert if (Tokens->peekNextToken()->isNot(tok::l_paren))
3599*12c85518Srobert return;
3600a9ac8606Spatrick nextToken();
3601*12c85518Srobert parseParens();
3602*12c85518Srobert break;
3603a9ac8606Spatrick
3604*12c85518Srobert default:
3605*12c85518Srobert if (!FormatTok->Tok.getIdentifierInfo()) {
3606*12c85518Srobert // Identifiers are part of the default case, we check for more then
3607*12c85518Srobert // tok::identifier to handle builtin type traits.
3608*12c85518Srobert return;
3609*12c85518Srobert }
3610*12c85518Srobert
3611*12c85518Srobert // We need to differentiate identifiers for a template deduction guide,
3612*12c85518Srobert // variables, or function return types (the constraint expression has
3613*12c85518Srobert // ended before that), and basically all other cases. But it's easier to
3614*12c85518Srobert // check the other way around.
3615*12c85518Srobert assert(FormatTok->Previous);
3616*12c85518Srobert switch (FormatTok->Previous->Tok.getKind()) {
3617*12c85518Srobert case tok::coloncolon: // Nested identifier.
3618*12c85518Srobert case tok::ampamp: // Start of a function or variable for the
3619*12c85518Srobert case tok::pipepipe: // constraint expression. (binary)
3620*12c85518Srobert case tok::exclaim: // The same as above, but unary.
3621*12c85518Srobert case tok::kw_requires: // Initial identifier of a requires clause.
3622*12c85518Srobert case tok::equal: // Initial identifier of a concept declaration.
3623*12c85518Srobert break;
3624*12c85518Srobert default:
3625*12c85518Srobert return;
3626*12c85518Srobert }
3627*12c85518Srobert
3628*12c85518Srobert // Read identifier with optional template declaration.
3629*12c85518Srobert nextToken();
3630*12c85518Srobert if (FormatTok->is(tok::less)) {
3631*12c85518Srobert nextToken();
3632*12c85518Srobert parseBracedList(/*ContinueOnSemicolons=*/false, /*IsEnum=*/false,
3633*12c85518Srobert /*ClosingBraceKind=*/tok::greater);
3634*12c85518Srobert }
3635*12c85518Srobert break;
3636*12c85518Srobert }
3637*12c85518Srobert } while (!eof());
3638a9ac8606Spatrick }
3639a9ac8606Spatrick
parseEnum()3640e5dd7070Spatrick bool UnwrappedLineParser::parseEnum() {
3641*12c85518Srobert const FormatToken &InitialToken = *FormatTok;
3642*12c85518Srobert
3643e5dd7070Spatrick // Won't be 'enum' for NS_ENUMs.
3644*12c85518Srobert if (FormatTok->is(tok::kw_enum))
3645e5dd7070Spatrick nextToken();
3646e5dd7070Spatrick
3647e5dd7070Spatrick // In TypeScript, "enum" can also be used as property name, e.g. in interface
3648e5dd7070Spatrick // declarations. An "enum" keyword followed by a colon would be a syntax
3649e5dd7070Spatrick // error and thus assume it is just an identifier.
3650*12c85518Srobert if (Style.isJavaScript() && FormatTok->isOneOf(tok::colon, tok::question))
3651e5dd7070Spatrick return false;
3652e5dd7070Spatrick
3653e5dd7070Spatrick // In protobuf, "enum" can be used as a field name.
3654e5dd7070Spatrick if (Style.Language == FormatStyle::LK_Proto && FormatTok->is(tok::equal))
3655e5dd7070Spatrick return false;
3656e5dd7070Spatrick
3657e5dd7070Spatrick // Eat up enum class ...
3658*12c85518Srobert if (FormatTok->isOneOf(tok::kw_class, tok::kw_struct))
3659e5dd7070Spatrick nextToken();
3660e5dd7070Spatrick
3661e5dd7070Spatrick while (FormatTok->Tok.getIdentifierInfo() ||
3662e5dd7070Spatrick FormatTok->isOneOf(tok::colon, tok::coloncolon, tok::less,
3663*12c85518Srobert tok::greater, tok::comma, tok::question,
3664*12c85518Srobert tok::l_square, tok::r_square)) {
3665e5dd7070Spatrick nextToken();
3666e5dd7070Spatrick // We can have macros or attributes in between 'enum' and the enum name.
3667e5dd7070Spatrick if (FormatTok->is(tok::l_paren))
3668e5dd7070Spatrick parseParens();
3669*12c85518Srobert if (FormatTok->is(TT_AttributeSquare)) {
3670*12c85518Srobert parseSquare();
3671*12c85518Srobert // Consume the closing TT_AttributeSquare.
3672*12c85518Srobert if (FormatTok->Next && FormatTok->is(TT_AttributeSquare))
3673*12c85518Srobert nextToken();
3674*12c85518Srobert }
3675e5dd7070Spatrick if (FormatTok->is(tok::identifier)) {
3676e5dd7070Spatrick nextToken();
3677e5dd7070Spatrick // If there are two identifiers in a row, this is likely an elaborate
3678e5dd7070Spatrick // return type. In Java, this can be "implements", etc.
3679e5dd7070Spatrick if (Style.isCpp() && FormatTok->is(tok::identifier))
3680e5dd7070Spatrick return false;
3681e5dd7070Spatrick }
3682e5dd7070Spatrick }
3683e5dd7070Spatrick
3684e5dd7070Spatrick // Just a declaration or something is wrong.
3685e5dd7070Spatrick if (FormatTok->isNot(tok::l_brace))
3686e5dd7070Spatrick return true;
3687*12c85518Srobert FormatTok->setFinalizedType(TT_EnumLBrace);
3688a9ac8606Spatrick FormatTok->setBlockKind(BK_Block);
3689e5dd7070Spatrick
3690e5dd7070Spatrick if (Style.Language == FormatStyle::LK_Java) {
3691e5dd7070Spatrick // Java enums are different.
3692e5dd7070Spatrick parseJavaEnumBody();
3693e5dd7070Spatrick return true;
3694e5dd7070Spatrick }
3695e5dd7070Spatrick if (Style.Language == FormatStyle::LK_Proto) {
3696e5dd7070Spatrick parseBlock(/*MustBeDeclaration=*/true);
3697e5dd7070Spatrick return true;
3698e5dd7070Spatrick }
3699e5dd7070Spatrick
3700*12c85518Srobert if (!Style.AllowShortEnumsOnASingleLine &&
3701*12c85518Srobert ShouldBreakBeforeBrace(Style, InitialToken)) {
3702ec727ea7Spatrick addUnwrappedLine();
3703*12c85518Srobert }
3704e5dd7070Spatrick // Parse enum body.
3705e5dd7070Spatrick nextToken();
3706ec727ea7Spatrick if (!Style.AllowShortEnumsOnASingleLine) {
3707ec727ea7Spatrick addUnwrappedLine();
3708ec727ea7Spatrick Line->Level += 1;
3709ec727ea7Spatrick }
3710ec727ea7Spatrick bool HasError = !parseBracedList(/*ContinueOnSemicolons=*/true,
3711ec727ea7Spatrick /*IsEnum=*/true);
3712ec727ea7Spatrick if (!Style.AllowShortEnumsOnASingleLine)
3713ec727ea7Spatrick Line->Level -= 1;
3714e5dd7070Spatrick if (HasError) {
3715e5dd7070Spatrick if (FormatTok->is(tok::semi))
3716e5dd7070Spatrick nextToken();
3717e5dd7070Spatrick addUnwrappedLine();
3718e5dd7070Spatrick }
3719e5dd7070Spatrick return true;
3720e5dd7070Spatrick
3721e5dd7070Spatrick // There is no addUnwrappedLine() here so that we fall through to parsing a
3722e5dd7070Spatrick // structural element afterwards. Thus, in "enum A {} n, m;",
3723e5dd7070Spatrick // "} n, m;" will end up in one unwrapped line.
3724e5dd7070Spatrick }
3725e5dd7070Spatrick
parseStructLike()3726a9ac8606Spatrick bool UnwrappedLineParser::parseStructLike() {
3727a9ac8606Spatrick // parseRecord falls through and does not yet add an unwrapped line as a
3728a9ac8606Spatrick // record declaration or definition can start a structural element.
3729a9ac8606Spatrick parseRecord();
3730a9ac8606Spatrick // This does not apply to Java, JavaScript and C#.
3731*12c85518Srobert if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript() ||
3732*12c85518Srobert Style.isCSharp()) {
3733a9ac8606Spatrick if (FormatTok->is(tok::semi))
3734a9ac8606Spatrick nextToken();
3735a9ac8606Spatrick addUnwrappedLine();
3736a9ac8606Spatrick return true;
3737a9ac8606Spatrick }
3738a9ac8606Spatrick return false;
3739a9ac8606Spatrick }
3740a9ac8606Spatrick
3741ec727ea7Spatrick namespace {
3742ec727ea7Spatrick // A class used to set and restore the Token position when peeking
3743ec727ea7Spatrick // ahead in the token source.
3744ec727ea7Spatrick class ScopedTokenPosition {
3745ec727ea7Spatrick unsigned StoredPosition;
3746ec727ea7Spatrick FormatTokenSource *Tokens;
3747ec727ea7Spatrick
3748ec727ea7Spatrick public:
ScopedTokenPosition(FormatTokenSource * Tokens)3749ec727ea7Spatrick ScopedTokenPosition(FormatTokenSource *Tokens) : Tokens(Tokens) {
3750ec727ea7Spatrick assert(Tokens && "Tokens expected to not be null");
3751ec727ea7Spatrick StoredPosition = Tokens->getPosition();
3752ec727ea7Spatrick }
3753ec727ea7Spatrick
~ScopedTokenPosition()3754ec727ea7Spatrick ~ScopedTokenPosition() { Tokens->setPosition(StoredPosition); }
3755ec727ea7Spatrick };
3756ec727ea7Spatrick } // namespace
3757ec727ea7Spatrick
3758ec727ea7Spatrick // Look to see if we have [[ by looking ahead, if
3759ec727ea7Spatrick // its not then rewind to the original position.
tryToParseSimpleAttribute()3760ec727ea7Spatrick bool UnwrappedLineParser::tryToParseSimpleAttribute() {
3761ec727ea7Spatrick ScopedTokenPosition AutoPosition(Tokens);
3762ec727ea7Spatrick FormatToken *Tok = Tokens->getNextToken();
3763ec727ea7Spatrick // We already read the first [ check for the second.
3764*12c85518Srobert if (!Tok->is(tok::l_square))
3765ec727ea7Spatrick return false;
3766ec727ea7Spatrick // Double check that the attribute is just something
3767ec727ea7Spatrick // fairly simple.
3768*12c85518Srobert while (Tok->isNot(tok::eof)) {
3769*12c85518Srobert if (Tok->is(tok::r_square))
3770ec727ea7Spatrick break;
3771ec727ea7Spatrick Tok = Tokens->getNextToken();
3772ec727ea7Spatrick }
3773*12c85518Srobert if (Tok->is(tok::eof))
3774ec727ea7Spatrick return false;
3775ec727ea7Spatrick Tok = Tokens->getNextToken();
3776*12c85518Srobert if (!Tok->is(tok::r_square))
3777ec727ea7Spatrick return false;
3778*12c85518Srobert Tok = Tokens->getNextToken();
3779*12c85518Srobert if (Tok->is(tok::semi))
3780*12c85518Srobert return false;
3781ec727ea7Spatrick return true;
3782ec727ea7Spatrick }
3783ec727ea7Spatrick
parseJavaEnumBody()3784e5dd7070Spatrick void UnwrappedLineParser::parseJavaEnumBody() {
3785*12c85518Srobert assert(FormatTok->is(tok::l_brace));
3786*12c85518Srobert const FormatToken *OpeningBrace = FormatTok;
3787*12c85518Srobert
3788e5dd7070Spatrick // Determine whether the enum is simple, i.e. does not have a semicolon or
3789e5dd7070Spatrick // constants with class bodies. Simple enums can be formatted like braced
3790e5dd7070Spatrick // lists, contracted to a single line, etc.
3791e5dd7070Spatrick unsigned StoredPosition = Tokens->getPosition();
3792e5dd7070Spatrick bool IsSimple = true;
3793e5dd7070Spatrick FormatToken *Tok = Tokens->getNextToken();
3794*12c85518Srobert while (!Tok->is(tok::eof)) {
3795e5dd7070Spatrick if (Tok->is(tok::r_brace))
3796e5dd7070Spatrick break;
3797e5dd7070Spatrick if (Tok->isOneOf(tok::l_brace, tok::semi)) {
3798e5dd7070Spatrick IsSimple = false;
3799e5dd7070Spatrick break;
3800e5dd7070Spatrick }
3801e5dd7070Spatrick // FIXME: This will also mark enums with braces in the arguments to enum
3802e5dd7070Spatrick // constants as "not simple". This is probably fine in practice, though.
3803e5dd7070Spatrick Tok = Tokens->getNextToken();
3804e5dd7070Spatrick }
3805e5dd7070Spatrick FormatTok = Tokens->setPosition(StoredPosition);
3806e5dd7070Spatrick
3807e5dd7070Spatrick if (IsSimple) {
3808e5dd7070Spatrick nextToken();
3809e5dd7070Spatrick parseBracedList();
3810e5dd7070Spatrick addUnwrappedLine();
3811e5dd7070Spatrick return;
3812e5dd7070Spatrick }
3813e5dd7070Spatrick
3814e5dd7070Spatrick // Parse the body of a more complex enum.
3815e5dd7070Spatrick // First add a line for everything up to the "{".
3816e5dd7070Spatrick nextToken();
3817e5dd7070Spatrick addUnwrappedLine();
3818e5dd7070Spatrick ++Line->Level;
3819e5dd7070Spatrick
3820e5dd7070Spatrick // Parse the enum constants.
3821*12c85518Srobert while (!eof()) {
3822e5dd7070Spatrick if (FormatTok->is(tok::l_brace)) {
3823e5dd7070Spatrick // Parse the constant's class body.
3824a9ac8606Spatrick parseBlock(/*MustBeDeclaration=*/true, /*AddLevels=*/1u,
3825e5dd7070Spatrick /*MunchSemi=*/false);
3826e5dd7070Spatrick } else if (FormatTok->is(tok::l_paren)) {
3827e5dd7070Spatrick parseParens();
3828e5dd7070Spatrick } else if (FormatTok->is(tok::comma)) {
3829e5dd7070Spatrick nextToken();
3830e5dd7070Spatrick addUnwrappedLine();
3831e5dd7070Spatrick } else if (FormatTok->is(tok::semi)) {
3832e5dd7070Spatrick nextToken();
3833e5dd7070Spatrick addUnwrappedLine();
3834e5dd7070Spatrick break;
3835e5dd7070Spatrick } else if (FormatTok->is(tok::r_brace)) {
3836e5dd7070Spatrick addUnwrappedLine();
3837e5dd7070Spatrick break;
3838e5dd7070Spatrick } else {
3839e5dd7070Spatrick nextToken();
3840e5dd7070Spatrick }
3841e5dd7070Spatrick }
3842e5dd7070Spatrick
3843e5dd7070Spatrick // Parse the class body after the enum's ";" if any.
3844*12c85518Srobert parseLevel(OpeningBrace);
3845e5dd7070Spatrick nextToken();
3846e5dd7070Spatrick --Line->Level;
3847e5dd7070Spatrick addUnwrappedLine();
3848e5dd7070Spatrick }
3849e5dd7070Spatrick
parseRecord(bool ParseAsExpr)3850e5dd7070Spatrick void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
3851e5dd7070Spatrick const FormatToken &InitialToken = *FormatTok;
3852e5dd7070Spatrick nextToken();
3853e5dd7070Spatrick
3854e5dd7070Spatrick // The actual identifier can be a nested name specifier, and in macros
3855e5dd7070Spatrick // it is often token-pasted.
3856ec727ea7Spatrick // An [[attribute]] can be before the identifier.
3857e5dd7070Spatrick while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash,
3858e5dd7070Spatrick tok::kw___attribute, tok::kw___declspec,
3859*12c85518Srobert tok::kw_alignas, tok::l_square) ||
3860*12c85518Srobert ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&
3861e5dd7070Spatrick FormatTok->isOneOf(tok::period, tok::comma))) {
3862*12c85518Srobert if (Style.isJavaScript() &&
3863e5dd7070Spatrick FormatTok->isOneOf(Keywords.kw_extends, Keywords.kw_implements)) {
3864e5dd7070Spatrick // JavaScript/TypeScript supports inline object types in
3865e5dd7070Spatrick // extends/implements positions:
3866e5dd7070Spatrick // class Foo implements {bar: number} { }
3867e5dd7070Spatrick nextToken();
3868e5dd7070Spatrick if (FormatTok->is(tok::l_brace)) {
3869e5dd7070Spatrick tryToParseBracedList();
3870e5dd7070Spatrick continue;
3871e5dd7070Spatrick }
3872e5dd7070Spatrick }
3873*12c85518Srobert if (FormatTok->is(tok::l_square) && handleCppAttributes())
3874*12c85518Srobert continue;
3875e5dd7070Spatrick bool IsNonMacroIdentifier =
3876e5dd7070Spatrick FormatTok->is(tok::identifier) &&
3877e5dd7070Spatrick FormatTok->TokenText != FormatTok->TokenText.upper();
3878e5dd7070Spatrick nextToken();
3879*12c85518Srobert // We can have macros in between 'class' and the class name.
3880*12c85518Srobert if (!IsNonMacroIdentifier && FormatTok->is(tok::l_paren))
3881e5dd7070Spatrick parseParens();
3882e5dd7070Spatrick }
3883e5dd7070Spatrick
3884e5dd7070Spatrick // Note that parsing away template declarations here leads to incorrectly
3885e5dd7070Spatrick // accepting function declarations as record declarations.
3886e5dd7070Spatrick // In general, we cannot solve this problem. Consider:
3887e5dd7070Spatrick // class A<int> B() {}
3888e5dd7070Spatrick // which can be a function definition or a class definition when B() is a
3889e5dd7070Spatrick // macro. If we find enough real-world cases where this is a problem, we
3890e5dd7070Spatrick // can parse for the 'template' keyword in the beginning of the statement,
3891e5dd7070Spatrick // and thus rule out the record production in case there is no template
3892e5dd7070Spatrick // (this would still leave us with an ambiguity between template function
3893e5dd7070Spatrick // and class declarations).
3894e5dd7070Spatrick if (FormatTok->isOneOf(tok::colon, tok::less)) {
3895*12c85518Srobert do {
3896e5dd7070Spatrick if (FormatTok->is(tok::l_brace)) {
3897e5dd7070Spatrick calculateBraceTypes(/*ExpectClassBody=*/true);
3898e5dd7070Spatrick if (!tryToParseBracedList())
3899e5dd7070Spatrick break;
3900e5dd7070Spatrick }
3901*12c85518Srobert if (FormatTok->is(tok::l_square)) {
3902*12c85518Srobert FormatToken *Previous = FormatTok->Previous;
3903*12c85518Srobert if (!Previous ||
3904*12c85518Srobert !(Previous->is(tok::r_paren) || Previous->isTypeOrIdentifier())) {
3905*12c85518Srobert // Don't try parsing a lambda if we had a closing parenthesis before,
3906*12c85518Srobert // it was probably a pointer to an array: int (*)[].
3907*12c85518Srobert if (!tryToParseLambda())
3908*12c85518Srobert break;
3909*12c85518Srobert } else {
3910*12c85518Srobert parseSquare();
3911*12c85518Srobert continue;
3912*12c85518Srobert }
3913*12c85518Srobert }
3914*12c85518Srobert if (FormatTok->is(tok::semi))
3915e5dd7070Spatrick return;
3916ec727ea7Spatrick if (Style.isCSharp() && FormatTok->is(Keywords.kw_where)) {
3917ec727ea7Spatrick addUnwrappedLine();
3918ec727ea7Spatrick nextToken();
3919ec727ea7Spatrick parseCSharpGenericTypeConstraint();
3920ec727ea7Spatrick break;
3921ec727ea7Spatrick }
3922e5dd7070Spatrick nextToken();
3923*12c85518Srobert } while (!eof());
3924e5dd7070Spatrick }
3925*12c85518Srobert
3926*12c85518Srobert auto GetBraceType = [](const FormatToken &RecordTok) {
3927*12c85518Srobert switch (RecordTok.Tok.getKind()) {
3928*12c85518Srobert case tok::kw_class:
3929*12c85518Srobert return TT_ClassLBrace;
3930*12c85518Srobert case tok::kw_struct:
3931*12c85518Srobert return TT_StructLBrace;
3932*12c85518Srobert case tok::kw_union:
3933*12c85518Srobert return TT_UnionLBrace;
3934*12c85518Srobert default:
3935*12c85518Srobert // Useful for e.g. interface.
3936*12c85518Srobert return TT_RecordLBrace;
3937e5dd7070Spatrick }
3938*12c85518Srobert };
3939*12c85518Srobert if (FormatTok->is(tok::l_brace)) {
3940*12c85518Srobert FormatTok->setFinalizedType(GetBraceType(InitialToken));
3941e5dd7070Spatrick if (ParseAsExpr) {
3942e5dd7070Spatrick parseChildBlock();
3943e5dd7070Spatrick } else {
3944e5dd7070Spatrick if (ShouldBreakBeforeBrace(Style, InitialToken))
3945e5dd7070Spatrick addUnwrappedLine();
3946e5dd7070Spatrick
3947a9ac8606Spatrick unsigned AddLevels = Style.IndentAccessModifiers ? 2u : 1u;
3948a9ac8606Spatrick parseBlock(/*MustBeDeclaration=*/true, AddLevels, /*MunchSemi=*/false);
3949e5dd7070Spatrick }
3950e5dd7070Spatrick }
3951e5dd7070Spatrick // There is no addUnwrappedLine() here so that we fall through to parsing a
3952e5dd7070Spatrick // structural element afterwards. Thus, in "class A {} n, m;",
3953e5dd7070Spatrick // "} n, m;" will end up in one unwrapped line.
3954e5dd7070Spatrick }
3955e5dd7070Spatrick
parseObjCMethod()3956e5dd7070Spatrick void UnwrappedLineParser::parseObjCMethod() {
3957*12c85518Srobert assert(FormatTok->isOneOf(tok::l_paren, tok::identifier) &&
3958e5dd7070Spatrick "'(' or identifier expected.");
3959e5dd7070Spatrick do {
3960*12c85518Srobert if (FormatTok->is(tok::semi)) {
3961e5dd7070Spatrick nextToken();
3962e5dd7070Spatrick addUnwrappedLine();
3963e5dd7070Spatrick return;
3964*12c85518Srobert } else if (FormatTok->is(tok::l_brace)) {
3965e5dd7070Spatrick if (Style.BraceWrapping.AfterFunction)
3966e5dd7070Spatrick addUnwrappedLine();
3967*12c85518Srobert parseBlock();
3968e5dd7070Spatrick addUnwrappedLine();
3969e5dd7070Spatrick return;
3970e5dd7070Spatrick } else {
3971e5dd7070Spatrick nextToken();
3972e5dd7070Spatrick }
3973e5dd7070Spatrick } while (!eof());
3974e5dd7070Spatrick }
3975e5dd7070Spatrick
parseObjCProtocolList()3976e5dd7070Spatrick void UnwrappedLineParser::parseObjCProtocolList() {
3977*12c85518Srobert assert(FormatTok->is(tok::less) && "'<' expected.");
3978e5dd7070Spatrick do {
3979e5dd7070Spatrick nextToken();
3980e5dd7070Spatrick // Early exit in case someone forgot a close angle.
3981e5dd7070Spatrick if (FormatTok->isOneOf(tok::semi, tok::l_brace) ||
3982*12c85518Srobert FormatTok->isObjCAtKeyword(tok::objc_end)) {
3983e5dd7070Spatrick return;
3984*12c85518Srobert }
3985*12c85518Srobert } while (!eof() && FormatTok->isNot(tok::greater));
3986e5dd7070Spatrick nextToken(); // Skip '>'.
3987e5dd7070Spatrick }
3988e5dd7070Spatrick
parseObjCUntilAtEnd()3989e5dd7070Spatrick void UnwrappedLineParser::parseObjCUntilAtEnd() {
3990e5dd7070Spatrick do {
3991*12c85518Srobert if (FormatTok->isObjCAtKeyword(tok::objc_end)) {
3992e5dd7070Spatrick nextToken();
3993e5dd7070Spatrick addUnwrappedLine();
3994e5dd7070Spatrick break;
3995e5dd7070Spatrick }
3996e5dd7070Spatrick if (FormatTok->is(tok::l_brace)) {
3997*12c85518Srobert parseBlock();
3998e5dd7070Spatrick // In ObjC interfaces, nothing should be following the "}".
3999e5dd7070Spatrick addUnwrappedLine();
4000e5dd7070Spatrick } else if (FormatTok->is(tok::r_brace)) {
4001e5dd7070Spatrick // Ignore stray "}". parseStructuralElement doesn't consume them.
4002e5dd7070Spatrick nextToken();
4003e5dd7070Spatrick addUnwrappedLine();
4004e5dd7070Spatrick } else if (FormatTok->isOneOf(tok::minus, tok::plus)) {
4005e5dd7070Spatrick nextToken();
4006e5dd7070Spatrick parseObjCMethod();
4007e5dd7070Spatrick } else {
4008e5dd7070Spatrick parseStructuralElement();
4009e5dd7070Spatrick }
4010e5dd7070Spatrick } while (!eof());
4011e5dd7070Spatrick }
4012e5dd7070Spatrick
parseObjCInterfaceOrImplementation()4013e5dd7070Spatrick void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
4014e5dd7070Spatrick assert(FormatTok->Tok.getObjCKeywordID() == tok::objc_interface ||
4015e5dd7070Spatrick FormatTok->Tok.getObjCKeywordID() == tok::objc_implementation);
4016e5dd7070Spatrick nextToken();
4017e5dd7070Spatrick nextToken(); // interface name
4018e5dd7070Spatrick
4019e5dd7070Spatrick // @interface can be followed by a lightweight generic
4020e5dd7070Spatrick // specialization list, then either a base class or a category.
4021*12c85518Srobert if (FormatTok->is(tok::less))
4022a9ac8606Spatrick parseObjCLightweightGenerics();
4023*12c85518Srobert if (FormatTok->is(tok::colon)) {
4024a9ac8606Spatrick nextToken();
4025a9ac8606Spatrick nextToken(); // base class name
4026a9ac8606Spatrick // The base class can also have lightweight generics applied to it.
4027*12c85518Srobert if (FormatTok->is(tok::less))
4028a9ac8606Spatrick parseObjCLightweightGenerics();
4029*12c85518Srobert } else if (FormatTok->is(tok::l_paren)) {
4030a9ac8606Spatrick // Skip category, if present.
4031a9ac8606Spatrick parseParens();
4032*12c85518Srobert }
4033a9ac8606Spatrick
4034*12c85518Srobert if (FormatTok->is(tok::less))
4035a9ac8606Spatrick parseObjCProtocolList();
4036a9ac8606Spatrick
4037*12c85518Srobert if (FormatTok->is(tok::l_brace)) {
4038a9ac8606Spatrick if (Style.BraceWrapping.AfterObjCDeclaration)
4039a9ac8606Spatrick addUnwrappedLine();
4040a9ac8606Spatrick parseBlock(/*MustBeDeclaration=*/true);
4041a9ac8606Spatrick }
4042a9ac8606Spatrick
4043a9ac8606Spatrick // With instance variables, this puts '}' on its own line. Without instance
4044a9ac8606Spatrick // variables, this ends the @interface line.
4045a9ac8606Spatrick addUnwrappedLine();
4046a9ac8606Spatrick
4047a9ac8606Spatrick parseObjCUntilAtEnd();
4048a9ac8606Spatrick }
4049a9ac8606Spatrick
parseObjCLightweightGenerics()4050a9ac8606Spatrick void UnwrappedLineParser::parseObjCLightweightGenerics() {
4051*12c85518Srobert assert(FormatTok->is(tok::less));
4052e5dd7070Spatrick // Unlike protocol lists, generic parameterizations support
4053e5dd7070Spatrick // nested angles:
4054e5dd7070Spatrick //
4055e5dd7070Spatrick // @interface Foo<ValueType : id <NSCopying, NSSecureCoding>> :
4056e5dd7070Spatrick // NSObject <NSCopying, NSSecureCoding>
4057e5dd7070Spatrick //
4058e5dd7070Spatrick // so we need to count how many open angles we have left.
4059e5dd7070Spatrick unsigned NumOpenAngles = 1;
4060e5dd7070Spatrick do {
4061e5dd7070Spatrick nextToken();
4062e5dd7070Spatrick // Early exit in case someone forgot a close angle.
4063e5dd7070Spatrick if (FormatTok->isOneOf(tok::semi, tok::l_brace) ||
4064*12c85518Srobert FormatTok->isObjCAtKeyword(tok::objc_end)) {
4065e5dd7070Spatrick break;
4066*12c85518Srobert }
4067*12c85518Srobert if (FormatTok->is(tok::less)) {
4068e5dd7070Spatrick ++NumOpenAngles;
4069*12c85518Srobert } else if (FormatTok->is(tok::greater)) {
4070e5dd7070Spatrick assert(NumOpenAngles > 0 && "'>' makes NumOpenAngles negative");
4071e5dd7070Spatrick --NumOpenAngles;
4072e5dd7070Spatrick }
4073e5dd7070Spatrick } while (!eof() && NumOpenAngles != 0);
4074e5dd7070Spatrick nextToken(); // Skip '>'.
4075e5dd7070Spatrick }
4076e5dd7070Spatrick
4077e5dd7070Spatrick // Returns true for the declaration/definition form of @protocol,
4078e5dd7070Spatrick // false for the expression form.
parseObjCProtocol()4079e5dd7070Spatrick bool UnwrappedLineParser::parseObjCProtocol() {
4080e5dd7070Spatrick assert(FormatTok->Tok.getObjCKeywordID() == tok::objc_protocol);
4081e5dd7070Spatrick nextToken();
4082e5dd7070Spatrick
4083*12c85518Srobert if (FormatTok->is(tok::l_paren)) {
4084e5dd7070Spatrick // The expression form of @protocol, e.g. "Protocol* p = @protocol(foo);".
4085e5dd7070Spatrick return false;
4086*12c85518Srobert }
4087e5dd7070Spatrick
4088e5dd7070Spatrick // The definition/declaration form,
4089e5dd7070Spatrick // @protocol Foo
4090e5dd7070Spatrick // - (int)someMethod;
4091e5dd7070Spatrick // @end
4092e5dd7070Spatrick
4093e5dd7070Spatrick nextToken(); // protocol name
4094e5dd7070Spatrick
4095*12c85518Srobert if (FormatTok->is(tok::less))
4096e5dd7070Spatrick parseObjCProtocolList();
4097e5dd7070Spatrick
4098e5dd7070Spatrick // Check for protocol declaration.
4099*12c85518Srobert if (FormatTok->is(tok::semi)) {
4100e5dd7070Spatrick nextToken();
4101e5dd7070Spatrick addUnwrappedLine();
4102e5dd7070Spatrick return true;
4103e5dd7070Spatrick }
4104e5dd7070Spatrick
4105e5dd7070Spatrick addUnwrappedLine();
4106e5dd7070Spatrick parseObjCUntilAtEnd();
4107e5dd7070Spatrick return true;
4108e5dd7070Spatrick }
4109e5dd7070Spatrick
parseJavaScriptEs6ImportExport()4110e5dd7070Spatrick void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
4111e5dd7070Spatrick bool IsImport = FormatTok->is(Keywords.kw_import);
4112e5dd7070Spatrick assert(IsImport || FormatTok->is(tok::kw_export));
4113e5dd7070Spatrick nextToken();
4114e5dd7070Spatrick
4115e5dd7070Spatrick // Consume the "default" in "export default class/function".
4116e5dd7070Spatrick if (FormatTok->is(tok::kw_default))
4117e5dd7070Spatrick nextToken();
4118e5dd7070Spatrick
4119e5dd7070Spatrick // Consume "async function", "function" and "default function", so that these
4120e5dd7070Spatrick // get parsed as free-standing JS functions, i.e. do not require a trailing
4121e5dd7070Spatrick // semicolon.
4122e5dd7070Spatrick if (FormatTok->is(Keywords.kw_async))
4123e5dd7070Spatrick nextToken();
4124e5dd7070Spatrick if (FormatTok->is(Keywords.kw_function)) {
4125e5dd7070Spatrick nextToken();
4126e5dd7070Spatrick return;
4127e5dd7070Spatrick }
4128e5dd7070Spatrick
4129e5dd7070Spatrick // For imports, `export *`, `export {...}`, consume the rest of the line up
4130e5dd7070Spatrick // to the terminating `;`. For everything else, just return and continue
4131e5dd7070Spatrick // parsing the structural element, i.e. the declaration or expression for
4132e5dd7070Spatrick // `export default`.
4133e5dd7070Spatrick if (!IsImport && !FormatTok->isOneOf(tok::l_brace, tok::star) &&
4134*12c85518Srobert !FormatTok->isStringLiteral()) {
4135e5dd7070Spatrick return;
4136*12c85518Srobert }
4137e5dd7070Spatrick
4138e5dd7070Spatrick while (!eof()) {
4139e5dd7070Spatrick if (FormatTok->is(tok::semi))
4140e5dd7070Spatrick return;
4141e5dd7070Spatrick if (Line->Tokens.empty()) {
4142e5dd7070Spatrick // Common issue: Automatic Semicolon Insertion wrapped the line, so the
4143e5dd7070Spatrick // import statement should terminate.
4144e5dd7070Spatrick return;
4145e5dd7070Spatrick }
4146e5dd7070Spatrick if (FormatTok->is(tok::l_brace)) {
4147a9ac8606Spatrick FormatTok->setBlockKind(BK_Block);
4148e5dd7070Spatrick nextToken();
4149e5dd7070Spatrick parseBracedList();
4150e5dd7070Spatrick } else {
4151e5dd7070Spatrick nextToken();
4152e5dd7070Spatrick }
4153e5dd7070Spatrick }
4154e5dd7070Spatrick }
4155e5dd7070Spatrick
parseStatementMacro()4156e5dd7070Spatrick void UnwrappedLineParser::parseStatementMacro() {
4157e5dd7070Spatrick nextToken();
4158e5dd7070Spatrick if (FormatTok->is(tok::l_paren))
4159e5dd7070Spatrick parseParens();
4160e5dd7070Spatrick if (FormatTok->is(tok::semi))
4161e5dd7070Spatrick nextToken();
4162e5dd7070Spatrick addUnwrappedLine();
4163e5dd7070Spatrick }
4164e5dd7070Spatrick
parseVerilogHierarchyIdentifier()4165*12c85518Srobert void UnwrappedLineParser::parseVerilogHierarchyIdentifier() {
4166*12c85518Srobert // consume things like a::`b.c[d:e] or a::*
4167*12c85518Srobert while (true) {
4168*12c85518Srobert if (FormatTok->isOneOf(tok::star, tok::period, tok::periodstar,
4169*12c85518Srobert tok::coloncolon, tok::hash) ||
4170*12c85518Srobert Keywords.isVerilogIdentifier(*FormatTok)) {
4171*12c85518Srobert nextToken();
4172*12c85518Srobert } else if (FormatTok->is(tok::l_square)) {
4173*12c85518Srobert parseSquare();
4174*12c85518Srobert } else {
4175*12c85518Srobert break;
4176e5dd7070Spatrick }
4177e5dd7070Spatrick }
4178*12c85518Srobert }
4179*12c85518Srobert
parseVerilogSensitivityList()4180*12c85518Srobert void UnwrappedLineParser::parseVerilogSensitivityList() {
4181*12c85518Srobert if (!FormatTok->is(tok::at))
4182*12c85518Srobert return;
4183*12c85518Srobert nextToken();
4184*12c85518Srobert // A block event expression has 2 at signs.
4185*12c85518Srobert if (FormatTok->is(tok::at))
4186*12c85518Srobert nextToken();
4187*12c85518Srobert switch (FormatTok->Tok.getKind()) {
4188*12c85518Srobert case tok::star:
4189*12c85518Srobert nextToken();
4190*12c85518Srobert break;
4191*12c85518Srobert case tok::l_paren:
4192*12c85518Srobert parseParens();
4193*12c85518Srobert break;
4194*12c85518Srobert default:
4195*12c85518Srobert parseVerilogHierarchyIdentifier();
4196*12c85518Srobert break;
4197*12c85518Srobert }
4198*12c85518Srobert }
4199*12c85518Srobert
parseVerilogHierarchyHeader()4200*12c85518Srobert unsigned UnwrappedLineParser::parseVerilogHierarchyHeader() {
4201*12c85518Srobert unsigned AddLevels = 0;
4202*12c85518Srobert
4203*12c85518Srobert if (FormatTok->is(Keywords.kw_clocking)) {
4204*12c85518Srobert nextToken();
4205*12c85518Srobert if (Keywords.isVerilogIdentifier(*FormatTok))
4206*12c85518Srobert nextToken();
4207*12c85518Srobert parseVerilogSensitivityList();
4208*12c85518Srobert if (FormatTok->is(tok::semi))
4209*12c85518Srobert nextToken();
4210*12c85518Srobert } else if (FormatTok->isOneOf(tok::kw_case, Keywords.kw_casex,
4211*12c85518Srobert Keywords.kw_casez, Keywords.kw_randcase,
4212*12c85518Srobert Keywords.kw_randsequence)) {
4213*12c85518Srobert if (Style.IndentCaseLabels)
4214*12c85518Srobert AddLevels++;
4215*12c85518Srobert nextToken();
4216*12c85518Srobert if (FormatTok->is(tok::l_paren)) {
4217*12c85518Srobert FormatTok->setFinalizedType(TT_ConditionLParen);
4218*12c85518Srobert parseParens();
4219*12c85518Srobert }
4220*12c85518Srobert if (FormatTok->isOneOf(Keywords.kw_inside, Keywords.kw_matches))
4221*12c85518Srobert nextToken();
4222*12c85518Srobert // The case header has no semicolon.
4223*12c85518Srobert } else {
4224*12c85518Srobert // "module" etc.
4225*12c85518Srobert nextToken();
4226*12c85518Srobert // all the words like the name of the module and specifiers like
4227*12c85518Srobert // "automatic" and the width of function return type
4228*12c85518Srobert while (true) {
4229*12c85518Srobert if (FormatTok->is(tok::l_square)) {
4230*12c85518Srobert auto Prev = FormatTok->getPreviousNonComment();
4231*12c85518Srobert if (Prev && Keywords.isVerilogIdentifier(*Prev))
4232*12c85518Srobert Prev->setFinalizedType(TT_VerilogDimensionedTypeName);
4233*12c85518Srobert parseSquare();
4234*12c85518Srobert } else if (Keywords.isVerilogIdentifier(*FormatTok) ||
4235*12c85518Srobert FormatTok->isOneOf(Keywords.kw_automatic, tok::kw_static)) {
4236*12c85518Srobert nextToken();
4237*12c85518Srobert } else {
4238*12c85518Srobert break;
4239*12c85518Srobert }
4240*12c85518Srobert }
4241*12c85518Srobert
4242*12c85518Srobert auto NewLine = [this]() {
4243*12c85518Srobert addUnwrappedLine();
4244*12c85518Srobert Line->IsContinuation = true;
4245*12c85518Srobert };
4246*12c85518Srobert
4247*12c85518Srobert // package imports
4248*12c85518Srobert while (FormatTok->is(Keywords.kw_import)) {
4249*12c85518Srobert NewLine();
4250*12c85518Srobert nextToken();
4251*12c85518Srobert parseVerilogHierarchyIdentifier();
4252*12c85518Srobert if (FormatTok->is(tok::semi))
4253*12c85518Srobert nextToken();
4254*12c85518Srobert }
4255*12c85518Srobert
4256*12c85518Srobert // parameters and ports
4257*12c85518Srobert if (FormatTok->is(Keywords.kw_verilogHash)) {
4258*12c85518Srobert NewLine();
4259*12c85518Srobert nextToken();
4260*12c85518Srobert if (FormatTok->is(tok::l_paren))
4261*12c85518Srobert parseParens();
4262*12c85518Srobert }
4263*12c85518Srobert if (FormatTok->is(tok::l_paren)) {
4264*12c85518Srobert NewLine();
4265*12c85518Srobert parseParens();
4266*12c85518Srobert }
4267*12c85518Srobert
4268*12c85518Srobert // extends and implements
4269*12c85518Srobert if (FormatTok->is(Keywords.kw_extends)) {
4270*12c85518Srobert NewLine();
4271*12c85518Srobert nextToken();
4272*12c85518Srobert parseVerilogHierarchyIdentifier();
4273*12c85518Srobert if (FormatTok->is(tok::l_paren))
4274*12c85518Srobert parseParens();
4275*12c85518Srobert }
4276*12c85518Srobert if (FormatTok->is(Keywords.kw_implements)) {
4277*12c85518Srobert NewLine();
4278*12c85518Srobert do {
4279*12c85518Srobert nextToken();
4280*12c85518Srobert parseVerilogHierarchyIdentifier();
4281*12c85518Srobert } while (FormatTok->is(tok::comma));
4282*12c85518Srobert }
4283*12c85518Srobert
4284*12c85518Srobert // Coverage event for cover groups.
4285*12c85518Srobert if (FormatTok->is(tok::at)) {
4286*12c85518Srobert NewLine();
4287*12c85518Srobert parseVerilogSensitivityList();
4288*12c85518Srobert }
4289*12c85518Srobert
4290*12c85518Srobert if (FormatTok->is(tok::semi))
4291*12c85518Srobert nextToken(/*LevelDifference=*/1);
4292*12c85518Srobert addUnwrappedLine();
4293*12c85518Srobert }
4294*12c85518Srobert
4295*12c85518Srobert return AddLevels;
4296*12c85518Srobert }
4297*12c85518Srobert
parseVerilogTable()4298*12c85518Srobert void UnwrappedLineParser::parseVerilogTable() {
4299*12c85518Srobert assert(FormatTok->is(Keywords.kw_table));
4300*12c85518Srobert nextToken(/*LevelDifference=*/1);
4301*12c85518Srobert addUnwrappedLine();
4302*12c85518Srobert
4303*12c85518Srobert auto InitialLevel = Line->Level++;
4304*12c85518Srobert while (!eof() && !Keywords.isVerilogEnd(*FormatTok)) {
4305*12c85518Srobert FormatToken *Tok = FormatTok;
4306*12c85518Srobert nextToken();
4307*12c85518Srobert if (Tok->is(tok::semi))
4308*12c85518Srobert addUnwrappedLine();
4309*12c85518Srobert else if (Tok->isOneOf(tok::star, tok::colon, tok::question, tok::minus))
4310*12c85518Srobert Tok->setFinalizedType(TT_VerilogTableItem);
4311*12c85518Srobert }
4312*12c85518Srobert Line->Level = InitialLevel;
4313*12c85518Srobert nextToken(/*LevelDifference=*/-1);
4314*12c85518Srobert addUnwrappedLine();
4315*12c85518Srobert }
4316*12c85518Srobert
parseVerilogCaseLabel()4317*12c85518Srobert void UnwrappedLineParser::parseVerilogCaseLabel() {
4318*12c85518Srobert // The label will get unindented in AnnotatingParser. If there are no leading
4319*12c85518Srobert // spaces, indent the rest here so that things inside the block will be
4320*12c85518Srobert // indented relative to things outside. We don't use parseLabel because we
4321*12c85518Srobert // don't know whether this colon is a label or a ternary expression at this
4322*12c85518Srobert // point.
4323*12c85518Srobert auto OrigLevel = Line->Level;
4324*12c85518Srobert auto FirstLine = CurrentLines->size();
4325*12c85518Srobert if (Line->Level == 0 || (Line->InPPDirective && Line->Level <= 1))
4326*12c85518Srobert ++Line->Level;
4327*12c85518Srobert else if (!Style.IndentCaseBlocks && Keywords.isVerilogBegin(*FormatTok))
4328*12c85518Srobert --Line->Level;
4329*12c85518Srobert parseStructuralElement();
4330*12c85518Srobert // Restore the indentation in both the new line and the line that has the
4331*12c85518Srobert // label.
4332*12c85518Srobert if (CurrentLines->size() > FirstLine)
4333*12c85518Srobert (*CurrentLines)[FirstLine].Level = OrigLevel;
4334*12c85518Srobert Line->Level = OrigLevel;
4335e5dd7070Spatrick }
4336e5dd7070Spatrick
addUnwrappedLine(LineLevel AdjustLevel)4337a9ac8606Spatrick void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) {
4338e5dd7070Spatrick if (Line->Tokens.empty())
4339e5dd7070Spatrick return;
4340e5dd7070Spatrick LLVM_DEBUG({
4341e5dd7070Spatrick if (CurrentLines == &Lines)
4342e5dd7070Spatrick printDebugInfo(*Line);
4343e5dd7070Spatrick });
4344a9ac8606Spatrick
4345a9ac8606Spatrick // If this line closes a block when in Whitesmiths mode, remember that
4346a9ac8606Spatrick // information so that the level can be decreased after the line is added.
4347a9ac8606Spatrick // This has to happen after the addition of the line since the line itself
4348a9ac8606Spatrick // needs to be indented.
4349a9ac8606Spatrick bool ClosesWhitesmithsBlock =
4350a9ac8606Spatrick Line->MatchingOpeningBlockLineIndex != UnwrappedLine::kInvalidIndex &&
4351a9ac8606Spatrick Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths;
4352a9ac8606Spatrick
4353e5dd7070Spatrick CurrentLines->push_back(std::move(*Line));
4354e5dd7070Spatrick Line->Tokens.clear();
4355e5dd7070Spatrick Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex;
4356e5dd7070Spatrick Line->FirstStartColumn = 0;
4357*12c85518Srobert Line->IsContinuation = false;
4358a9ac8606Spatrick
4359a9ac8606Spatrick if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove)
4360a9ac8606Spatrick --Line->Level;
4361e5dd7070Spatrick if (CurrentLines == &Lines && !PreprocessorDirectives.empty()) {
4362e5dd7070Spatrick CurrentLines->append(
4363e5dd7070Spatrick std::make_move_iterator(PreprocessorDirectives.begin()),
4364e5dd7070Spatrick std::make_move_iterator(PreprocessorDirectives.end()));
4365e5dd7070Spatrick PreprocessorDirectives.clear();
4366e5dd7070Spatrick }
4367e5dd7070Spatrick // Disconnect the current token from the last token on the previous line.
4368e5dd7070Spatrick FormatTok->Previous = nullptr;
4369e5dd7070Spatrick }
4370e5dd7070Spatrick
eof() const4371*12c85518Srobert bool UnwrappedLineParser::eof() const { return FormatTok->is(tok::eof); }
4372e5dd7070Spatrick
isOnNewLine(const FormatToken & FormatTok)4373e5dd7070Spatrick bool UnwrappedLineParser::isOnNewLine(const FormatToken &FormatTok) {
4374e5dd7070Spatrick return (Line->InPPDirective || FormatTok.HasUnescapedNewline) &&
4375e5dd7070Spatrick FormatTok.NewlinesBefore > 0;
4376e5dd7070Spatrick }
4377e5dd7070Spatrick
4378e5dd7070Spatrick // Checks if \p FormatTok is a line comment that continues the line comment
4379e5dd7070Spatrick // section on \p Line.
4380e5dd7070Spatrick static bool
continuesLineCommentSection(const FormatToken & FormatTok,const UnwrappedLine & Line,const llvm::Regex & CommentPragmasRegex)4381e5dd7070Spatrick continuesLineCommentSection(const FormatToken &FormatTok,
4382e5dd7070Spatrick const UnwrappedLine &Line,
4383e5dd7070Spatrick const llvm::Regex &CommentPragmasRegex) {
4384e5dd7070Spatrick if (Line.Tokens.empty())
4385e5dd7070Spatrick return false;
4386e5dd7070Spatrick
4387e5dd7070Spatrick StringRef IndentContent = FormatTok.TokenText;
4388e5dd7070Spatrick if (FormatTok.TokenText.startswith("//") ||
4389*12c85518Srobert FormatTok.TokenText.startswith("/*")) {
4390e5dd7070Spatrick IndentContent = FormatTok.TokenText.substr(2);
4391*12c85518Srobert }
4392e5dd7070Spatrick if (CommentPragmasRegex.match(IndentContent))
4393e5dd7070Spatrick return false;
4394e5dd7070Spatrick
4395e5dd7070Spatrick // If Line starts with a line comment, then FormatTok continues the comment
4396e5dd7070Spatrick // section if its original column is greater or equal to the original start
4397e5dd7070Spatrick // column of the line.
4398e5dd7070Spatrick //
4399e5dd7070Spatrick // Define the min column token of a line as follows: if a line ends in '{' or
4400e5dd7070Spatrick // contains a '{' followed by a line comment, then the min column token is
4401e5dd7070Spatrick // that '{'. Otherwise, the min column token of the line is the first token of
4402e5dd7070Spatrick // the line.
4403e5dd7070Spatrick //
4404e5dd7070Spatrick // If Line starts with a token other than a line comment, then FormatTok
4405e5dd7070Spatrick // continues the comment section if its original column is greater than the
4406e5dd7070Spatrick // original start column of the min column token of the line.
4407e5dd7070Spatrick //
4408e5dd7070Spatrick // For example, the second line comment continues the first in these cases:
4409e5dd7070Spatrick //
4410e5dd7070Spatrick // // first line
4411e5dd7070Spatrick // // second line
4412e5dd7070Spatrick //
4413e5dd7070Spatrick // and:
4414e5dd7070Spatrick //
4415e5dd7070Spatrick // // first line
4416e5dd7070Spatrick // // second line
4417e5dd7070Spatrick //
4418e5dd7070Spatrick // and:
4419e5dd7070Spatrick //
4420e5dd7070Spatrick // int i; // first line
4421e5dd7070Spatrick // // second line
4422e5dd7070Spatrick //
4423e5dd7070Spatrick // and:
4424e5dd7070Spatrick //
4425e5dd7070Spatrick // do { // first line
4426e5dd7070Spatrick // // second line
4427e5dd7070Spatrick // int i;
4428e5dd7070Spatrick // } while (true);
4429e5dd7070Spatrick //
4430e5dd7070Spatrick // and:
4431e5dd7070Spatrick //
4432e5dd7070Spatrick // enum {
4433e5dd7070Spatrick // a, // first line
4434e5dd7070Spatrick // // second line
4435e5dd7070Spatrick // b
4436e5dd7070Spatrick // };
4437e5dd7070Spatrick //
4438e5dd7070Spatrick // The second line comment doesn't continue the first in these cases:
4439e5dd7070Spatrick //
4440e5dd7070Spatrick // // first line
4441e5dd7070Spatrick // // second line
4442e5dd7070Spatrick //
4443e5dd7070Spatrick // and:
4444e5dd7070Spatrick //
4445e5dd7070Spatrick // int i; // first line
4446e5dd7070Spatrick // // second line
4447e5dd7070Spatrick //
4448e5dd7070Spatrick // and:
4449e5dd7070Spatrick //
4450e5dd7070Spatrick // do { // first line
4451e5dd7070Spatrick // // second line
4452e5dd7070Spatrick // int i;
4453e5dd7070Spatrick // } while (true);
4454e5dd7070Spatrick //
4455e5dd7070Spatrick // and:
4456e5dd7070Spatrick //
4457e5dd7070Spatrick // enum {
4458e5dd7070Spatrick // a, // first line
4459e5dd7070Spatrick // // second line
4460e5dd7070Spatrick // };
4461e5dd7070Spatrick const FormatToken *MinColumnToken = Line.Tokens.front().Tok;
4462e5dd7070Spatrick
4463e5dd7070Spatrick // Scan for '{//'. If found, use the column of '{' as a min column for line
4464e5dd7070Spatrick // comment section continuation.
4465e5dd7070Spatrick const FormatToken *PreviousToken = nullptr;
4466e5dd7070Spatrick for (const UnwrappedLineNode &Node : Line.Tokens) {
4467e5dd7070Spatrick if (PreviousToken && PreviousToken->is(tok::l_brace) &&
4468e5dd7070Spatrick isLineComment(*Node.Tok)) {
4469e5dd7070Spatrick MinColumnToken = PreviousToken;
4470e5dd7070Spatrick break;
4471e5dd7070Spatrick }
4472e5dd7070Spatrick PreviousToken = Node.Tok;
4473e5dd7070Spatrick
4474e5dd7070Spatrick // Grab the last newline preceding a token in this unwrapped line.
4475*12c85518Srobert if (Node.Tok->NewlinesBefore > 0)
4476e5dd7070Spatrick MinColumnToken = Node.Tok;
4477e5dd7070Spatrick }
4478*12c85518Srobert if (PreviousToken && PreviousToken->is(tok::l_brace))
4479e5dd7070Spatrick MinColumnToken = PreviousToken;
4480e5dd7070Spatrick
4481e5dd7070Spatrick return continuesLineComment(FormatTok, /*Previous=*/Line.Tokens.back().Tok,
4482e5dd7070Spatrick MinColumnToken);
4483e5dd7070Spatrick }
4484e5dd7070Spatrick
flushComments(bool NewlineBeforeNext)4485e5dd7070Spatrick void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) {
4486e5dd7070Spatrick bool JustComments = Line->Tokens.empty();
4487*12c85518Srobert for (FormatToken *Tok : CommentsBeforeNextToken) {
4488e5dd7070Spatrick // Line comments that belong to the same line comment section are put on the
4489e5dd7070Spatrick // same line since later we might want to reflow content between them.
4490e5dd7070Spatrick // Additional fine-grained breaking of line comment sections is controlled
4491e5dd7070Spatrick // by the class BreakableLineCommentSection in case it is desirable to keep
4492e5dd7070Spatrick // several line comment sections in the same unwrapped line.
4493e5dd7070Spatrick //
4494e5dd7070Spatrick // FIXME: Consider putting separate line comment sections as children to the
4495e5dd7070Spatrick // unwrapped line instead.
4496*12c85518Srobert Tok->ContinuesLineCommentSection =
4497*12c85518Srobert continuesLineCommentSection(*Tok, *Line, CommentPragmasRegex);
4498*12c85518Srobert if (isOnNewLine(*Tok) && JustComments && !Tok->ContinuesLineCommentSection)
4499e5dd7070Spatrick addUnwrappedLine();
4500*12c85518Srobert pushToken(Tok);
4501e5dd7070Spatrick }
4502e5dd7070Spatrick if (NewlineBeforeNext && JustComments)
4503e5dd7070Spatrick addUnwrappedLine();
4504e5dd7070Spatrick CommentsBeforeNextToken.clear();
4505e5dd7070Spatrick }
4506e5dd7070Spatrick
nextToken(int LevelDifference)4507e5dd7070Spatrick void UnwrappedLineParser::nextToken(int LevelDifference) {
4508e5dd7070Spatrick if (eof())
4509e5dd7070Spatrick return;
4510e5dd7070Spatrick flushComments(isOnNewLine(*FormatTok));
4511e5dd7070Spatrick pushToken(FormatTok);
4512e5dd7070Spatrick FormatToken *Previous = FormatTok;
4513*12c85518Srobert if (!Style.isJavaScript())
4514e5dd7070Spatrick readToken(LevelDifference);
4515e5dd7070Spatrick else
4516e5dd7070Spatrick readTokenWithJavaScriptASI();
4517e5dd7070Spatrick FormatTok->Previous = Previous;
4518*12c85518Srobert if (Style.isVerilog()) {
4519*12c85518Srobert // Blocks in Verilog can have `begin` and `end` instead of braces. For
4520*12c85518Srobert // keywords like `begin`, we can't treat them the same as left braces
4521*12c85518Srobert // because some contexts require one of them. For example structs use
4522*12c85518Srobert // braces and if blocks use keywords, and a left brace can occur in an if
4523*12c85518Srobert // statement, but it is not a block. For keywords like `end`, we simply
4524*12c85518Srobert // treat them the same as right braces.
4525*12c85518Srobert if (Keywords.isVerilogEnd(*FormatTok))
4526*12c85518Srobert FormatTok->Tok.setKind(tok::r_brace);
4527*12c85518Srobert }
4528e5dd7070Spatrick }
4529e5dd7070Spatrick
distributeComments(const SmallVectorImpl<FormatToken * > & Comments,const FormatToken * NextTok)4530e5dd7070Spatrick void UnwrappedLineParser::distributeComments(
4531e5dd7070Spatrick const SmallVectorImpl<FormatToken *> &Comments,
4532e5dd7070Spatrick const FormatToken *NextTok) {
4533e5dd7070Spatrick // Whether or not a line comment token continues a line is controlled by
4534e5dd7070Spatrick // the method continuesLineCommentSection, with the following caveat:
4535e5dd7070Spatrick //
4536e5dd7070Spatrick // Define a trail of Comments to be a nonempty proper postfix of Comments such
4537e5dd7070Spatrick // that each comment line from the trail is aligned with the next token, if
4538e5dd7070Spatrick // the next token exists. If a trail exists, the beginning of the maximal
4539e5dd7070Spatrick // trail is marked as a start of a new comment section.
4540e5dd7070Spatrick //
4541e5dd7070Spatrick // For example in this code:
4542e5dd7070Spatrick //
4543e5dd7070Spatrick // int a; // line about a
4544e5dd7070Spatrick // // line 1 about b
4545e5dd7070Spatrick // // line 2 about b
4546e5dd7070Spatrick // int b;
4547e5dd7070Spatrick //
4548e5dd7070Spatrick // the two lines about b form a maximal trail, so there are two sections, the
4549e5dd7070Spatrick // first one consisting of the single comment "// line about a" and the
4550e5dd7070Spatrick // second one consisting of the next two comments.
4551e5dd7070Spatrick if (Comments.empty())
4552e5dd7070Spatrick return;
4553e5dd7070Spatrick bool ShouldPushCommentsInCurrentLine = true;
4554e5dd7070Spatrick bool HasTrailAlignedWithNextToken = false;
4555e5dd7070Spatrick unsigned StartOfTrailAlignedWithNextToken = 0;
4556e5dd7070Spatrick if (NextTok) {
4557e5dd7070Spatrick // We are skipping the first element intentionally.
4558e5dd7070Spatrick for (unsigned i = Comments.size() - 1; i > 0; --i) {
4559e5dd7070Spatrick if (Comments[i]->OriginalColumn == NextTok->OriginalColumn) {
4560e5dd7070Spatrick HasTrailAlignedWithNextToken = true;
4561e5dd7070Spatrick StartOfTrailAlignedWithNextToken = i;
4562e5dd7070Spatrick }
4563e5dd7070Spatrick }
4564e5dd7070Spatrick }
4565e5dd7070Spatrick for (unsigned i = 0, e = Comments.size(); i < e; ++i) {
4566e5dd7070Spatrick FormatToken *FormatTok = Comments[i];
4567e5dd7070Spatrick if (HasTrailAlignedWithNextToken && i == StartOfTrailAlignedWithNextToken) {
4568e5dd7070Spatrick FormatTok->ContinuesLineCommentSection = false;
4569e5dd7070Spatrick } else {
4570e5dd7070Spatrick FormatTok->ContinuesLineCommentSection =
4571e5dd7070Spatrick continuesLineCommentSection(*FormatTok, *Line, CommentPragmasRegex);
4572e5dd7070Spatrick }
4573e5dd7070Spatrick if (!FormatTok->ContinuesLineCommentSection &&
4574e5dd7070Spatrick (isOnNewLine(*FormatTok) || FormatTok->IsFirst)) {
4575e5dd7070Spatrick ShouldPushCommentsInCurrentLine = false;
4576e5dd7070Spatrick }
4577*12c85518Srobert if (ShouldPushCommentsInCurrentLine)
4578e5dd7070Spatrick pushToken(FormatTok);
4579*12c85518Srobert else
4580e5dd7070Spatrick CommentsBeforeNextToken.push_back(FormatTok);
4581e5dd7070Spatrick }
4582e5dd7070Spatrick }
4583e5dd7070Spatrick
readToken(int LevelDifference)4584e5dd7070Spatrick void UnwrappedLineParser::readToken(int LevelDifference) {
4585e5dd7070Spatrick SmallVector<FormatToken *, 1> Comments;
4586*12c85518Srobert bool PreviousWasComment = false;
4587*12c85518Srobert bool FirstNonCommentOnLine = false;
4588e5dd7070Spatrick do {
4589e5dd7070Spatrick FormatTok = Tokens->getNextToken();
4590e5dd7070Spatrick assert(FormatTok);
4591*12c85518Srobert while (FormatTok->getType() == TT_ConflictStart ||
4592*12c85518Srobert FormatTok->getType() == TT_ConflictEnd ||
4593*12c85518Srobert FormatTok->getType() == TT_ConflictAlternative) {
4594*12c85518Srobert if (FormatTok->getType() == TT_ConflictStart)
4595*12c85518Srobert conditionalCompilationStart(/*Unreachable=*/false);
4596*12c85518Srobert else if (FormatTok->getType() == TT_ConflictAlternative)
4597*12c85518Srobert conditionalCompilationAlternative();
4598*12c85518Srobert else if (FormatTok->getType() == TT_ConflictEnd)
4599*12c85518Srobert conditionalCompilationEnd();
4600*12c85518Srobert FormatTok = Tokens->getNextToken();
4601*12c85518Srobert FormatTok->MustBreakBefore = true;
4602*12c85518Srobert }
4603*12c85518Srobert
4604*12c85518Srobert auto IsFirstNonCommentOnLine = [](bool FirstNonCommentOnLine,
4605*12c85518Srobert const FormatToken &Tok,
4606*12c85518Srobert bool PreviousWasComment) {
4607*12c85518Srobert auto IsFirstOnLine = [](const FormatToken &Tok) {
4608*12c85518Srobert return Tok.HasUnescapedNewline || Tok.IsFirst;
4609*12c85518Srobert };
4610*12c85518Srobert
4611*12c85518Srobert // Consider preprocessor directives preceded by block comments as first
4612*12c85518Srobert // on line.
4613*12c85518Srobert if (PreviousWasComment)
4614*12c85518Srobert return FirstNonCommentOnLine || IsFirstOnLine(Tok);
4615*12c85518Srobert return IsFirstOnLine(Tok);
4616*12c85518Srobert };
4617*12c85518Srobert
4618*12c85518Srobert FirstNonCommentOnLine = IsFirstNonCommentOnLine(
4619*12c85518Srobert FirstNonCommentOnLine, *FormatTok, PreviousWasComment);
4620*12c85518Srobert PreviousWasComment = FormatTok->is(tok::comment);
4621*12c85518Srobert
4622*12c85518Srobert while (!Line->InPPDirective && FormatTok->is(tok::hash) &&
4623*12c85518Srobert (!Style.isVerilog() ||
4624*12c85518Srobert Keywords.isVerilogPPDirective(*Tokens->peekNextToken())) &&
4625*12c85518Srobert FirstNonCommentOnLine) {
4626e5dd7070Spatrick distributeComments(Comments, FormatTok);
4627e5dd7070Spatrick Comments.clear();
4628e5dd7070Spatrick // If there is an unfinished unwrapped line, we flush the preprocessor
4629e5dd7070Spatrick // directives only after that unwrapped line was finished later.
4630e5dd7070Spatrick bool SwitchToPreprocessorLines = !Line->Tokens.empty();
4631e5dd7070Spatrick ScopedLineState BlockState(*this, SwitchToPreprocessorLines);
4632e5dd7070Spatrick assert((LevelDifference >= 0 ||
4633e5dd7070Spatrick static_cast<unsigned>(-LevelDifference) <= Line->Level) &&
4634e5dd7070Spatrick "LevelDifference makes Line->Level negative");
4635e5dd7070Spatrick Line->Level += LevelDifference;
4636e5dd7070Spatrick // Comments stored before the preprocessor directive need to be output
4637e5dd7070Spatrick // before the preprocessor directive, at the same level as the
4638e5dd7070Spatrick // preprocessor directive, as we consider them to apply to the directive.
4639e5dd7070Spatrick if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
4640*12c85518Srobert PPBranchLevel > 0) {
4641e5dd7070Spatrick Line->Level += PPBranchLevel;
4642*12c85518Srobert }
4643e5dd7070Spatrick flushComments(isOnNewLine(*FormatTok));
4644e5dd7070Spatrick parsePPDirective();
4645*12c85518Srobert PreviousWasComment = FormatTok->is(tok::comment);
4646*12c85518Srobert FirstNonCommentOnLine = IsFirstNonCommentOnLine(
4647*12c85518Srobert FirstNonCommentOnLine, *FormatTok, PreviousWasComment);
4648e5dd7070Spatrick }
4649e5dd7070Spatrick
4650e5dd7070Spatrick if (!PPStack.empty() && (PPStack.back().Kind == PP_Unreachable) &&
4651e5dd7070Spatrick !Line->InPPDirective) {
4652e5dd7070Spatrick continue;
4653e5dd7070Spatrick }
4654e5dd7070Spatrick
4655*12c85518Srobert if (!FormatTok->is(tok::comment)) {
4656e5dd7070Spatrick distributeComments(Comments, FormatTok);
4657e5dd7070Spatrick Comments.clear();
4658e5dd7070Spatrick return;
4659e5dd7070Spatrick }
4660e5dd7070Spatrick
4661e5dd7070Spatrick Comments.push_back(FormatTok);
4662e5dd7070Spatrick } while (!eof());
4663e5dd7070Spatrick
4664e5dd7070Spatrick distributeComments(Comments, nullptr);
4665e5dd7070Spatrick Comments.clear();
4666e5dd7070Spatrick }
4667e5dd7070Spatrick
pushToken(FormatToken * Tok)4668e5dd7070Spatrick void UnwrappedLineParser::pushToken(FormatToken *Tok) {
4669e5dd7070Spatrick Line->Tokens.push_back(UnwrappedLineNode(Tok));
4670e5dd7070Spatrick if (MustBreakBeforeNextToken) {
4671e5dd7070Spatrick Line->Tokens.back().Tok->MustBreakBefore = true;
4672e5dd7070Spatrick MustBreakBeforeNextToken = false;
4673e5dd7070Spatrick }
4674e5dd7070Spatrick }
4675e5dd7070Spatrick
4676e5dd7070Spatrick } // end namespace format
4677e5dd7070Spatrick } // end namespace clang
4678