From 19ccb1227f5dc338d4b2d9dbbaeaa973c293f8d0 Mon Sep 17 00:00:00 2001 From: Daniel Jasper Date: Tue, 8 Oct 2013 05:11:18 +0000 Subject: [PATCH] clang-format: Improve constructor initializer linewrapping. Specifically make ConstructorInitializerAllOnOneLineOrOnePerLine work nicely with BreakConstructorInitializersBeforeComma. This fixes llvm.org/PR17395. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192168 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/ContinuationIndenter.cpp | 27 ++++++++++++++++----------- lib/Format/TokenAnnotator.cpp | 6 +++++- unittests/Format/FormatTest.cpp | 14 ++++++++++++++ 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index 6a5f8763d9..ff1f1aa853 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -44,6 +44,18 @@ static bool startsSegmentOfBuilderTypeCall(const FormatToken &Tok) { return Tok.isMemberAccess() && Tok.Previous && Tok.Previous->closesScope(); } +// Returns \c true if \c Current starts a new parameter. +static bool startsNextParameter(const FormatToken &Current, + const FormatStyle &Style) { + const FormatToken &Previous = *Current.Previous; + if (Current.Type == TT_CtorInitializerComma && + Style.BreakConstructorInitializersBeforeComma) + return true; + return Previous.is(tok::comma) && !Current.isTrailingComment() && + (Previous.Type != TT_CtorInitializerComma || + !Style.BreakConstructorInitializersBeforeComma); +} + ContinuationIndenter::ContinuationIndenter(const FormatStyle &Style, SourceManager &SourceMgr, WhitespaceManager &Whitespaces, @@ -113,15 +125,9 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { return true; if (Previous.is(tok::semi) && State.LineContainsContinuedForLoopSection) return true; - if (Style.BreakConstructorInitializersBeforeComma) { - if (Previous.Type == TT_CtorInitializerComma) - return false; - if (Current.Type == TT_CtorInitializerComma) - return true; - } - if ((Previous.isOneOf(tok::comma, tok::semi) || Current.is(tok::question) || - (Current.Type == TT_ConditionalExpr && - !(Current.is(tok::colon) && Previous.is(tok::question)))) && + if ((startsNextParameter(Current, Style) || Previous.is(tok::semi) || + Current.is(tok::question) || + (Current.Type == TT_ConditionalExpr && Previous.isNot(tok::question))) && State.Stack.back().BreakBeforeParameter && !Current.isTrailingComment() && !Current.isOneOf(tok::r_paren, tok::r_brace)) return true; @@ -250,8 +256,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, if (Previous.opensScope() && Previous.Type != TT_ObjCMethodExpr && Current.Type != TT_LineComment) State.Stack.back().Indent = State.Column + Spaces; - if (Previous.is(tok::comma) && !Current.isTrailingComment() && - State.Stack.back().AvoidBinPacking) + if (State.Stack.back().AvoidBinPacking && startsNextParameter(Current, Style)) State.Stack.back().NoLineBreak = true; if (startsSegmentOfBuilderTypeCall(Current)) State.Stack.back().ContainsUnwrappedBuilder = true; diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index 220da707b1..0e06d3b651 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -1366,7 +1366,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, // FIXME: Fix horrible hack of using BindingStrength to find top-level <>. return true; } else if (Right.Type == TT_CtorInitializerComma && - Style.BreakConstructorInitializersBeforeComma) { + Style.BreakConstructorInitializersBeforeComma && + !Style.ConstructorInitializerAllOnOneLineOrOnePerLine) { return true; } else if (Right.Previous->BlockKind == BK_Block && Right.Previous->isNot(tok::r_brace) && @@ -1450,6 +1451,9 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, if (Left.Type == TT_CtorInitializerComma && Style.BreakConstructorInitializersBeforeComma) return false; + if (Right.Type == TT_CtorInitializerComma && + Style.BreakConstructorInitializersBeforeComma) + return true; if (Right.isBinaryOperator() && Style.BreakBeforeBinaryOperators) return true; if (Left.is(tok::greater) && Right.is(tok::greater) && diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 6bb38e92f8..1916076ca0 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -6587,6 +6587,20 @@ TEST_F(FormatTest, ConstructorInitializerIndentWidth) { ", b(b)\n" ", c(c) {}", Style); + + Style.ConstructorInitializerAllOnOneLineOrOnePerLine = true; + Style.ConstructorInitializerIndentWidth = 4; + verifyFormat( + "SomeClass::Constructor()\n" + " : aaaaaaaa(aaaaaaaa), aaaaaaaa(aaaaaaaa), aaaaaaaa(aaaaaaaa) {}", + Style); + Style.ConstructorInitializerIndentWidth = 4; + Style.ColumnLimit = 60; + verifyFormat("SomeClass::Constructor()\n" + " : aaaaaaaa(aaaaaaaa)\n" + " , aaaaaaaa(aaaaaaaa)\n" + " , aaaaaaaa(aaaaaaaa) {}", + Style); } TEST_F(FormatTest, FormatsWithWebKitStyle) { -- 2.40.0