Typz updated this revision to Diff 115051. Typz added a comment. Reorder the functions to minimize diff.
https://reviews.llvm.org/D33589 Files: lib/Format/ContinuationIndenter.cpp lib/Format/ContinuationIndenter.h lib/Format/UnwrappedLineFormatter.cpp unittests/Format/FormatTest.cpp
Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -9809,6 +9809,60 @@ EXPECT_EQ("#pragma option -C -A", format("#pragma option -C -A")); } +TEST_F(FormatTest, OptimizeBreakPenaltyVsExcess) { + FormatStyle Style = getLLVMStyle(); + Style.ColumnLimit = 20; + + verifyFormat("int a; // the\n" + " // comment", Style); + EXPECT_EQ("int a; /* first line\n" + " * second\n" + " * line third\n" + " * line\n" + " */", + format("int a; /* first line\n" + " * second\n" + " * line third\n" + " * line\n" + " */", Style)); + EXPECT_EQ("int a; // first line\n" + " // second\n" + " // line third\n" + " // line", + format("int a; // first line\n" + " // second line\n" + " // third line", + Style)); + + Style.PenaltyExcessCharacter = 90; + verifyFormat("int a; // the comment", Style); + EXPECT_EQ("int a; // the\n" + " // comment aa", + format("int a; // the comment aa", Style)); + EXPECT_EQ("int a; /* first line\n" + " * second line\n" + " * third line\n" + " */", + format("int a; /* first line\n" + " * second line\n" + " * third line\n" + " */", Style)); + EXPECT_EQ("int a; // first line\n" + " // second line\n" + " // third line", + format("int a; // first line\n" + " // second line\n" + " // third line", + Style)); + EXPECT_EQ("int a; /* first line\n" + " * second\n" + " * line third\n" + " * line\n" + " */", + format("int a; /* first line second line third line" + "\n*/", Style)); +} + #define EXPECT_ALL_STYLES_EQUAL(Styles) \ for (size_t i = 1; i < Styles.size(); ++i) \ EXPECT_EQ(Styles[0], Styles[i]) << "Style #" << i << " of " << Styles.size() \ Index: lib/Format/UnwrappedLineFormatter.cpp =================================================================== --- lib/Format/UnwrappedLineFormatter.cpp +++ lib/Format/UnwrappedLineFormatter.cpp @@ -951,6 +951,7 @@ for (std::deque<StateNode *>::iterator I = Path.begin(), E = Path.end(); I != E; ++I) { unsigned Penalty = 0; + State.Reflow = (*I)->State.Reflow; formatChildren(State, (*I)->NewLine, /*DryRun=*/false, Penalty); Penalty += Indenter->addTokenToState(State, (*I)->NewLine, false); Index: lib/Format/ContinuationIndenter.h =================================================================== --- lib/Format/ContinuationIndenter.h +++ lib/Format/ContinuationIndenter.h @@ -27,6 +27,7 @@ namespace format { class AnnotatedLine; +class BreakableToken; struct FormatToken; struct LineState; struct ParenState; @@ -100,6 +101,16 @@ unsigned breakProtrudingToken(const FormatToken &Current, LineState &State, bool DryRun); + /// \brief Perform the reflowing of a BreakableToken. + /// If State.Reflow=true, then the function will reflow the token as needed. + /// Otherwise, it simply computes the penalty caused by this tokens characters. + /// + /// \returns The penalty of reflowing the token if State.Reflow=true; otherwise + /// the penalty of characters going beyond the column limit. + unsigned reflowProtrudingToken(const FormatToken & Current, LineState & State, + std::unique_ptr<clang::format::BreakableToken> & Token, + unsigned ColumnLimit, bool DryRun); + /// \brief Appends the next token to \p State and updates information /// necessary for indentation. /// @@ -350,6 +361,11 @@ /// \brief The indent of the first token. unsigned FirstIndent; + /// \brief Indicates if comments are reflown. + /// This value is set when breakProtrudingToken() is called with DryRun=true, + /// and simply used otherwise. + bool Reflow = true; + /// \brief The line that is being formatted. /// /// Does not need to be considered for memoization because it doesn't change. Index: lib/Format/ContinuationIndenter.cpp =================================================================== --- lib/Format/ContinuationIndenter.cpp +++ lib/Format/ContinuationIndenter.cpp @@ -1313,6 +1313,39 @@ if (Current.UnbreakableTailLength >= ColumnLimit) return 0; + unsigned Penalty = 0; + if (!DryRun) { + Penalty = reflowProtrudingToken(Current, State, Token, ColumnLimit, DryRun); + } else { + LineState NoreflowState = State; + NoreflowState.Reflow = false; + unsigned NoreflowPenalty = reflowProtrudingToken(Current, NoreflowState, Token, ColumnLimit, DryRun); + + if (NoreflowPenalty > 0) { + State.Reflow = true; + Penalty = reflowProtrudingToken(Current, State, Token, ColumnLimit, DryRun); + } + + if (NoreflowPenalty <= Penalty) { + State = NoreflowState; + Penalty = NoreflowPenalty; + } + } + + // Do not count the penalty twice, it will be added afterwards + if (State.Column > getColumnLimit(State)) { + unsigned ExcessCharacters = State.Column - getColumnLimit(State); + Penalty -= Style.PenaltyExcessCharacter * ExcessCharacters; + } + + return Penalty; +} + +unsigned ContinuationIndenter::reflowProtrudingToken(const FormatToken &Current, LineState &State, + std::unique_ptr<BreakableToken> &Token, + unsigned ColumnLimit, bool DryRun) { + unsigned StartColumn = State.Column - Current.ColumnWidth; + unsigned RemainingSpace = ColumnLimit - Current.UnbreakableTailLength; bool BreakInserted = false; // We use a conservative reflowing strategy. Reflow starts after a line is @@ -1337,14 +1370,18 @@ RemainingSpace, SplitBefore, Whitespaces); RemainingTokenColumns = Token->getLineLengthAfterSplitBefore( LineIndex, TailOffset, RemainingTokenColumns, ColumnLimit, SplitBefore); + if (!State.Reflow) { + if (RemainingTokenColumns > RemainingSpace) + Penalty += Style.PenaltyExcessCharacter * + (RemainingTokenColumns - RemainingSpace); + continue; + } while (RemainingTokenColumns > RemainingSpace) { BreakableToken::Split Split = Token->getSplit( LineIndex, TailOffset, ColumnLimit, CommentPragmasRegex); if (Split.first == StringRef::npos) { - // The last line's penalty is handled in addNextStateToQueue(). - if (LineIndex < EndIndex - 1) - Penalty += Style.PenaltyExcessCharacter * - (RemainingTokenColumns - RemainingSpace); + Penalty += Style.PenaltyExcessCharacter * + (RemainingTokenColumns - RemainingSpace); break; } assert(Split.first != 0); @@ -1400,6 +1437,8 @@ State.Column = RemainingTokenColumns; if (BreakInserted) { + assert(State.Reflow); + // If we break the token inside a parameter list, we need to break before // the next parameter on all levels, so that the next parameter is clearly // visible. Line comments already introduce a break.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits