diff options
Diffstat (limited to 'clang/lib/Format')
-rw-r--r-- | clang/lib/Format/TokenAnnotator.cpp | 42 | ||||
-rw-r--r-- | clang/lib/Format/UnwrappedLineParser.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Format/WhitespaceManager.cpp | 16 |
3 files changed, 55 insertions, 8 deletions
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 11dc661abc24..86c9ac4aa364 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -3604,6 +3604,16 @@ static bool isAllmanLambdaBrace(const FormatToken &Tok) { !Tok.isOneOf(TT_ObjCBlockLBrace, TT_DictLiteral)); } +// Returns the first token on the line that is not a comment. +static const FormatToken *getFirstNonComment(const AnnotatedLine &Line) { + const FormatToken *Next = Line.First; + if (!Next) + return Next; + if (Next->is(tok::comment)) + Next = Next->getNextNonComment(); + return Next; +} + bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, const FormatToken &Right) { const FormatToken &Left = *Right.Previous; @@ -3785,12 +3795,34 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, if (Right.is(TT_InlineASMBrace)) return Right.HasUnescapedNewline; - if (isAllmanBrace(Left) || isAllmanBrace(Right)) - return (Line.startsWith(tok::kw_enum) && Style.BraceWrapping.AfterEnum) || - (Line.startsWith(tok::kw_typedef, tok::kw_enum) && - Style.BraceWrapping.AfterEnum) || - (Line.startsWith(tok::kw_class) && Style.BraceWrapping.AfterClass) || + if (isAllmanBrace(Left) || isAllmanBrace(Right)) { + auto FirstNonComment = getFirstNonComment(Line); + bool AccessSpecifier = + FirstNonComment && + FirstNonComment->isOneOf(Keywords.kw_internal, tok::kw_public, + tok::kw_private, tok::kw_protected); + + if (Style.BraceWrapping.AfterEnum) { + if (Line.startsWith(tok::kw_enum) || + Line.startsWith(tok::kw_typedef, tok::kw_enum)) + return true; + // Ensure BraceWrapping for `public enum A {`. + if (AccessSpecifier && FirstNonComment->Next && + FirstNonComment->Next->is(tok::kw_enum)) + return true; + } + + // Ensure BraceWrapping for `public interface A {`. + if (Style.BraceWrapping.AfterClass && + ((AccessSpecifier && FirstNonComment->Next && + FirstNonComment->Next->is(Keywords.kw_interface)) || + Line.startsWith(Keywords.kw_interface))) + return true; + + return (Line.startsWith(tok::kw_class) && Style.BraceWrapping.AfterClass) || (Line.startsWith(tok::kw_struct) && Style.BraceWrapping.AfterStruct); + } + if (Left.is(TT_ObjCBlockLBrace) && Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) return true; diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 673986d16af2..8487875064aa 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -2532,6 +2532,8 @@ bool UnwrappedLineParser::parseEnum() { if (FormatTok->Tok.is(tok::kw_enum)) nextToken(); + const FormatToken &InitialToken = *FormatTok; + // In TypeScript, "enum" can also be used as property name, e.g. in interface // declarations. An "enum" keyword followed by a colon would be a syntax // error and thus assume it is just an identifier. @@ -2578,7 +2580,8 @@ bool UnwrappedLineParser::parseEnum() { return true; } - if (!Style.AllowShortEnumsOnASingleLine) + if (!Style.AllowShortEnumsOnASingleLine && + ShouldBreakBeforeBrace(Style, InitialToken)) addUnwrappedLine(); // Parse enum body. nextToken(); diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index a822e0aaf1f9..74136d2f5caa 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -1146,14 +1146,15 @@ WhitespaceManager::CellDescriptions WhitespaceManager::getCells(unsigned Start, } else if (C.Tok->is(tok::comma)) { if (!Cells.empty()) Cells.back().EndIndex = i; - Cell++; + if (C.Tok->getNextNonComment()->isNot(tok::r_brace)) // dangling comma + ++Cell; } } else if (Depth == 1) { if (C.Tok == MatchingParen) { if (!Cells.empty()) Cells.back().EndIndex = i; Cells.push_back(CellDescription{i, ++Cell, i + 1, false, nullptr}); - CellCount = Cell + 1; + CellCount = C.Tok->Previous->isNot(tok::comma) ? Cell + 1 : Cell; // Go to the next non-comment and ensure there is a break in front const auto *NextNonComment = C.Tok->getNextNonComment(); while (NextNonComment->is(tok::comma)) @@ -1190,6 +1191,17 @@ WhitespaceManager::CellDescriptions WhitespaceManager::getCells(unsigned Start, // So if we split a line previously and the tail line + this token is // less then the column limit we remove the split here and just put // the column start at a space past the comma + // + // FIXME This if branch covers the cases where the column is not + // the first column. This leads to weird pathologies like the formatting + // auto foo = Items{ + // Section{ + // 0, bar(), + // } + // }; + // Well if it doesn't lead to that it's indicative that the line + // breaking should be revisited. Unfortunately alot of other options + // interact with this auto j = i - 1; if ((j - 1) > Start && Changes[j].Tok->is(tok::comma) && Changes[j - 1].NewlinesBefore > 0) { |