From e8ccc81a9f66361450148338b8457dd2c6ad11de Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Sat, 12 Jan 2013 22:48:47 +0000 Subject: [PATCH] Formatter: Prefer breaking before ObjC selector names over breaking at their ':' Before: if ((self = [super initWithContentRect:contentRect styleMask: styleMask backing:NSBackingStoreBuffered defer:YES])) { Now: if ((self = [super initWithContentRect:contentRect styleMask:styleMask backing:NSBackingStoreBuffered defer:YES])) { git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172333 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/Format.cpp | 21 ++++++++++++++++++++- unittests/Format/FormatTest.cpp | 15 +++++++++++---- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 8ca0a823fe..de870900b4 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -170,7 +170,7 @@ static void replacePPWhitespace( /// \brief Checks whether the (remaining) \c UnwrappedLine starting with /// \p RootToken fits into \p Limit columns. -bool fitsIntoLimit(const AnnotatedToken &RootToken, unsigned Limit) { +static bool fitsIntoLimit(const AnnotatedToken &RootToken, unsigned Limit) { unsigned Columns = RootToken.FormatTok.TokenLength; bool FitsOnALine = true; const AnnotatedToken *Tok = &RootToken; @@ -188,6 +188,15 @@ bool fitsIntoLimit(const AnnotatedToken &RootToken, unsigned Limit) { return FitsOnALine; } +/// \brief Returns if a token is an Objective-C selector name. +/// +/// For example, "bar" is a selector name in [foo bar:(4 + 5)] +static bool isObjCSelectorName(const AnnotatedToken &Tok) { + return Tok.is(tok::identifier) && !Tok.Children.empty() && + Tok.Children[0].is(tok::colon) && + Tok.Children[0].Type == TT_ObjCMethodExpr; +} + class UnwrappedLineFormatter { public: UnwrappedLineFormatter(const FormatStyle &Style, SourceManager &SourceMgr, @@ -479,6 +488,14 @@ private: if (Left.is(tok::semi) || Left.is(tok::comma) || Left.ClosesTemplateDeclaration) return 0; + + // In Objective-C method expressions, prefer breaking before "param:" over + // breaking after it. + if (isObjCSelectorName(Right)) + return 0; + if (Right.is(tok::colon) && Right.Type == TT_ObjCMethodExpr) + return 20; + if (Left.is(tok::l_paren)) return 20; @@ -1188,6 +1205,8 @@ private: return false; if (Left.is(tok::colon) && Left.Type == TT_ObjCMethodExpr) return true; + if (isObjCSelectorName(Right)) + return true; if (Left.ClosesTemplateDeclaration) return true; if (Left.Type == TT_PointerOrReference || Left.Type == TT_TemplateCloser || diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 668e8af76b..cba25fcf8f 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -1537,12 +1537,18 @@ TEST_F(FormatTest, FormatObjCMethodExpr) { verifyFormat("throw [self errorFor:a];"); verifyFormat("@throw [self errorFor:a];"); - // The formatting of this isn't ideal yet. It tests that the formatter doesn't - // break after "backing" but before ":", which would be at 80 columns. + // This tests that the formatter doesn't break after "backing" but before ":", + // which would be at 80 columns. verifyFormat( "void f() {\n" - " if ((self = [super initWithContentRect:contentRect styleMask:\n" - " styleMask backing:NSBackingStoreBuffered defer:YES]))"); + " if ((self = [super initWithContentRect:contentRect styleMask:styleMask\n" + " backing:NSBackingStoreBuffered defer:YES]))"); + + verifyFormat("[foo setasdfasdffffffffffffadfasdfasdf:\n" + " [bar dowith:asdfdsfasdfasdfasfasfasfsafasdfsfad]];"); + + verifyFormat("[foo checkThatBreakingAfterColonWorksOk:\n" + " [bar ifItDoes:reduceOverallLineLengthLikeInThisCase]];"); } @@ -1582,6 +1588,7 @@ TEST_F(FormatTest, ObjCAt) { verifyFormat("@'c'"); verifyFormat("@true"); verifyFormat("NSNumber *smallestInt = @(-INT_MAX - 1);"); + // FIXME: Array and dictionary literals need more work. verifyFormat("@["); verifyFormat("@{"); -- 2.40.0