Split before first argument if dict appears in arg list
diff --git a/CHANGELOG b/CHANGELOG
index 293b6f8..fb7a63e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -6,6 +6,8 @@
 ### Changed
 - Take into account a named function argument when determining if we should
   split before the first argument in a function call.
+- Split before the first argument in a function call if the arguments contain a
+  dictionary that doesn't fit on a single line.
 
 ## [0.19.0] 2017-10-14
 ### Added
diff --git a/yapf/yapflib/format_decision_state.py b/yapf/yapflib/format_decision_state.py
index c5d84fe..31f967a 100644
--- a/yapf/yapflib/format_decision_state.py
+++ b/yapf/yapflib/format_decision_state.py
@@ -352,6 +352,10 @@
               self.stack[-1].indent)
           return arglist_length > self.column_limit
 
+    if (current.value not in '{)' and previous.value == '(' and
+        self._ArgumentListHasDictionaryEntry(current)):
+      return True
+
     if style.Get('SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED'):
       # Split before arguments in a function call or definition if the
       # arguments are terminated by a comma.
@@ -751,6 +755,19 @@
     length += len(entry_start.value)
     return length + self.stack[-2].indent <= self.column_limit
 
+  def _ArgumentListHasDictionaryEntry(self, token):
+    if _IsArgumentToFunction(token):
+      while token:
+        if token.value == '{':
+          length = token.matching_bracket.total_length - token.total_length
+          return length + self.stack[-2].indent > self.column_limit
+        if token.ClosesScope():
+          break
+        if token.OpensScope():
+          token = token.matching_bracket
+        token = token.next_token
+    return False
+
 
 _COMPOUND_STMTS = frozenset(
     {'for', 'while', 'if', 'elif', 'with', 'except', 'def', 'class'})
@@ -779,6 +796,14 @@
   return False
 
 
+def _IsArgumentToFunction(token):
+  bracket = unwrapped_line.IsSurroundedByBrackets(token)
+  if not bracket or bracket.value != '(':
+    return False
+  previous = bracket.previous_token
+  return previous and previous.is_name
+
+
 def _GetLengthOfSubtype(token, subtype, exclude=None):
   current = token
   while (current.next_token and subtype in current.subtypes and
diff --git a/yapftests/reformatter_buganizer_test.py b/yapftests/reformatter_buganizer_test.py
index 9501850..3d040f8 100644
--- a/yapftests/reformatter_buganizer_test.py
+++ b/yapftests/reformatter_buganizer_test.py
@@ -28,6 +28,36 @@
   def setUpClass(cls):
     style.SetGlobalStyle(style.CreateChromiumStyle())
 
+  def testB35210351(self):
+    unformatted_code = """\
+def _():
+  config.AnotherRuleThing(
+      'the_title_to_the_thing_here',
+      {'monitorname': 'firefly',
+       'service': ACCOUNTING_THING,
+       'severity': 'the_bug',
+       'monarch_module_name': alerts.TheLabel(qa_module_regexp, invert=True)},
+      fanout,
+      alerts.AlertUsToSomething(
+          GetTheAlertToIt('the_title_to_the_thing_here'),
+          GetNotificationTemplate('your_email_here')))
+"""
+    expected_formatted_code = """\
+def _():
+  config.AnotherRuleThing(
+      'the_title_to_the_thing_here', {
+          'monitorname': 'firefly',
+          'service': ACCOUNTING_THING,
+          'severity': 'the_bug',
+          'monarch_module_name': alerts.TheLabel(qa_module_regexp, invert=True)
+      }, fanout,
+      alerts.AlertUsToSomething(
+          GetTheAlertToIt('the_title_to_the_thing_here'),
+          GetNotificationTemplate('your_email_here')))
+"""
+    uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code)
+    self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(uwlines))
+
   def testB34774905(self):
     unformatted_code = """\
 x=[VarExprType(ir_name=IrName( value='x',
@@ -894,20 +924,21 @@
         class F():
 
           def f():
-            self.assertDictEqual(accounts, {
-                'foo': {
-                    'account': 'foo',
-                    'lines': 'l1\\nl2\\nl3\\n1 line(s) were elided.'
-                },
-                'bar': {
-                    'account': 'bar',
-                    'lines': 'l5\\nl6\\nl7'
-                },
-                'wiz': {
-                    'account': 'wiz',
-                    'lines': 'l8'
-                }
-            })
+            self.assertDictEqual(
+                accounts, {
+                    'foo': {
+                        'account': 'foo',
+                        'lines': 'l1\\nl2\\nl3\\n1 line(s) were elided.'
+                    },
+                    'bar': {
+                        'account': 'bar',
+                        'lines': 'l5\\nl6\\nl7'
+                    },
+                    'wiz': {
+                        'account': 'wiz',
+                        'lines': 'l8'
+                    }
+                })
         """)
     uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code)
     self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(uwlines))
@@ -972,9 +1003,11 @@
                    | m.ggggggg(bbbbbbbbbbbbbbb)
                    | m.ppppp(
                        (1 - m.ffffffffffffffff(llllllllllllllllllllll * 1000000, m.vvv))
-                       * m.ddddddddddddddddd(m.vvv)), m.fffff(
-                           m.rrr('mmmmmmmmmmmmmmmm', 'sssssssssssssssssssssss'),
-                           dict(ffffffffffffffff, **{
+                       * m.ddddddddddddddddd(m.vvv)),
+                   m.fffff(
+                       m.rrr('mmmmmmmmmmmmmmmm', 'sssssssssssssssssssssss'),
+                       dict(
+                           ffffffffffffffff, **{
                                'mmmmmm:ssssss':
                                    m.rrrrrrrrrrr('|'.join(iiiiiiiiiiiiii), iiiiii=True)
                            }))