Index: clang/lib/Format/UnwrappedLineParser.h =================================================================== --- clang/lib/Format/UnwrappedLineParser.h +++ clang/lib/Format/UnwrappedLineParser.h @@ -92,6 +92,7 @@ void reset(); void parseFile(); bool precededByCommentOrPPDirective() const; + bool mightFitOnOneLine() const; bool parseLevel(bool HasOpeningBrace, bool CanContainBracedList, IfStmtKind *IfKind = nullptr, TokenType NextLBracesType = TT_Unknown); Index: clang/lib/Format/UnwrappedLineParser.cpp =================================================================== --- clang/lib/Format/UnwrappedLineParser.cpp +++ clang/lib/Format/UnwrappedLineParser.cpp @@ -14,6 +14,7 @@ #include "UnwrappedLineParser.h" #include "FormatToken.h" +#include "TokenAnnotator.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -460,13 +461,56 @@ return Previous && Previous->is(tok::comment) && (Previous->IsMultiline || Previous->NewlinesBefore > 0); } + +bool UnwrappedLineParser::mightFitOnOneLine() const { + const auto ColumnLimit = Style.ColumnLimit; + if (ColumnLimit == 0) + return true; + + if (Lines.empty()) + return true; + + const auto &PreviousLine = Lines.back(); + const auto &Tokens = PreviousLine.Tokens; + assert(!Tokens.empty()); + const auto *LastToken = Tokens.back().Tok; + assert(LastToken); + if (!LastToken->isOneOf(tok::semi, tok::comment)) + return true; + + SmallVector SavedTokens; + for (const auto &Token : PreviousLine.Tokens) { + FormatToken *Tok = new FormatToken; + Tok->copyFrom(*Token.Tok); + SavedTokens.push_back(Tok); + } + + AnnotatedLine Line(PreviousLine); + assert(Line.Last == LastToken); + + TokenAnnotator Annotator(Style, Keywords); + Annotator.annotate(Line); + Annotator.calculateFormattingInformation(Line); + + const int Length = LastToken->TotalLength; + + int I = 0; + for (const auto &Token : PreviousLine.Tokens) { + const FormatToken *Tok = SavedTokens[I++]; + Token.Tok->copyFrom(*Tok); + delete Tok; + } + + return Line.Level * Style.IndentWidth + Length <= ColumnLimit; +} + /// \brief Parses a level, that is ???. /// \param HasOpeningBrace If that level is started by an opening brace. /// \param CanContainBracedList If the content can contain (at any level) a /// braced list. /// \param NextLBracesType The type for left brace found in this level. /// \returns true if a simple block, or false otherwise. (A simple block has a -/// single statement.) +/// single statement that fits on a single line.) bool UnwrappedLineParser::parseLevel(bool HasOpeningBrace, bool CanContainBracedList, IfStmtKind *IfKind, @@ -533,7 +577,9 @@ precededByCommentOrPPDirective()) return false; const FormatToken *Next = Tokens->peekNextToken(); - return Next->isNot(tok::comment) || Next->NewlinesBefore > 0; + if (Next->is(tok::comment) && Next->NewlinesBefore == 0) + return false; + return mightFitOnOneLine(); } nextToken(); addUnwrappedLine(); Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -25351,8 +25351,6 @@ "}", Style); - // FIXME: See https://github.com/llvm/llvm-project/issues/53543. -#if 0 Style.ColumnLimit = 65; verifyFormat("if (condition) {\n" @@ -25380,9 +25378,6 @@ " b = c >= 0 ? d : e;\n" "}", Style); -#endif - - Style.ColumnLimit = 20; verifyFormat("if (a)\n" " b = c > 0 ? d : e;",