From a53bbae476f8f20d18250effb4cc3f110c9b8030 Mon Sep 17 00:00:00 2001
From: Daniel Jasper <djasper@google.com>
Date: Sun, 20 Oct 2013 16:45:46 +0000
Subject: [PATCH] clang-format: Improve formatting of ObjC dict literals.

Before:
  NSDictionary *d = @{ @"nam" : NSUserNam(), @"dte" : [NSDate date],
                       @"processInfo" : [NSProcessInfo processInfo]
  };

After:
  NSDictionary *d = @{
    @"nam" : NSUserNam(),
    @"dte" : [NSDate date],
    @"processInfo" : [NSProcessInfo processInfo]
  };

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@193049 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Format/ContinuationIndenter.cpp | 11 +++++++++--
 unittests/Format/FormatTest.cpp     | 15 +++++++++------
 2 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp
index 0cf9e32ea8..63a03e0d44 100644
--- a/lib/Format/ContinuationIndenter.cpp
+++ b/lib/Format/ContinuationIndenter.cpp
@@ -136,6 +136,9 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
       !Previous.isOneOf(tok::kw_return, tok::lessless) &&
       Previous.Type != TT_InlineASMColon && NextIsMultilineString(State))
     return true;
+  if (Previous.Type == TT_ObjCDictLiteral && Previous.is(tok::l_brace) &&
+      getLengthToMatchingParen(Previous) + State.Column > getColumnLimit(State))
+    return true;
 
   if (!Style.BreakBeforeBinaryOperators) {
     // If we need to break somewhere inside the LHS of a binary expression, we
@@ -593,11 +596,15 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
 
   // If this '[' opens an ObjC call, determine whether all parameters fit into
   // one line and put one per line if they don't.
-  if (Current.is(tok::l_square) && Current.Type == TT_ObjCMethodExpr &&
+  if (Current.isOneOf(tok::l_brace, tok::l_square) &&
+      (Current.Type == TT_ObjCDictLiteral ||
+       Current.Type == TT_ObjCMethodExpr) &&
       Current.MatchingParen != NULL) {
     if (getLengthToMatchingParen(Current) + State.Column >
-        getColumnLimit(State))
+        getColumnLimit(State)) {
       State.Stack.back().BreakBeforeParameter = true;
+      State.Stack.back().AvoidBinPacking = true;
+    }
   }
 
   // If we encounter a closing ), ], } or >, we can remove a level from our
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index 23a2203b01..dcb708e0d7 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -5363,14 +5363,17 @@ TEST_F(FormatTest, ObjCLiterals) {
   verifyFormat(
       "NSDictionary *settings = @{ AVEncoderKey : @(AVAudioQualityMax) };");
 
-  // FIXME: Nested and multi-line array and dictionary literals need more work.
   verifyFormat(
-      "NSDictionary *d = @{ @\"nam\" : NSUserNam(), @\"dte\" : [NSDate date],\n"
-      "                     @\"processInfo\" : [NSProcessInfo processInfo] };");
+      "NSDictionary *d = @{\n"
+      "  @\"nam\" : NSUserNam(),\n"
+      "  @\"dte\" : [NSDate date],\n"
+      "  @\"processInfo\" : [NSProcessInfo processInfo]\n"
+      "};");
   verifyFormat(
-      "@{ NSFontAttributeNameeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee :\n"
-      "   regularFont, };");
-
+      "@{\n"
+      "  NSFontAttributeNameeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee : "
+      "regularFont,\n"
+      "};");
 }
 
 TEST_F(FormatTest, ReformatRegionAdjustsIndent) {
-- 
2.40.0