Add ALLOW_MULTILINE_DICTIONARY_KEYS knob

This allows us to split a dictionary key over multiple lines, which is
something pylint doesn't like.
diff --git a/CHANGELOG b/CHANGELOG
index 38e3272..ed619f1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -11,6 +11,8 @@
   dictionary/set generator.
 - The `BLANK_LINE_BEFORE_CLASS_DOCSTRING` knob adds a blank line before a
   class's docstring.
+- The `ALLOW_MULTILINE_DICTIONARY_KEYS` knob allows dictionary keys to span
+  more than one line.
 ### Fixed
 - Split before all entries in a dict/set or list maker when comma-terminated,
   even if there's only one entry.
diff --git a/README.rst b/README.rst
index 6abb80d..c15464d 100644
--- a/README.rst
+++ b/README.rst
@@ -290,6 +290,17 @@
 ``ALLOW_MULTILINE_LAMBDAS``
     Allow lambdas to be formatted on more than one line.
 
+``ALLOW_MULTILINE_DICTIONARY_KEYS``
+    Allow dictionary keys to exist on multiple lines. For example:
+
+    .. code-block:: python
+
+        x = {
+            ('this is the first element of a tuple',
+             'this is the second element of a tuple'):
+                 value,
+        }
+
 ``BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF``
     Insert a blank line before a ``def`` or ``class`` immediately nested within
     another ``def`` or ``class``. For example:
diff --git a/setup.py b/setup.py
index fc8781e..c73016b 100644
--- a/setup.py
+++ b/setup.py
@@ -64,5 +64,9 @@
           'Topic :: Software Development :: Libraries :: Python Modules',
           'Topic :: Software Development :: Quality Assurance',
       ],
-      entry_points={'console_scripts': ['yapf = yapf:run_main'],},
-      cmdclass={'test': RunTests,},)
+      entry_points={
+          'console_scripts': ['yapf = yapf:run_main'],
+      },
+      cmdclass={
+          'test': RunTests,
+      },)
diff --git a/yapf/yapflib/format_decision_state.py b/yapf/yapflib/format_decision_state.py
index 93379e2..65e4c8d 100644
--- a/yapf/yapflib/format_decision_state.py
+++ b/yapf/yapflib/format_decision_state.py
@@ -111,13 +111,27 @@
             (self.column, repr(self.next_token), self.paren_level,
              '\n\t'.join(repr(s) for s in self.stack) + ']'))
 
-  def CanSplit(self):
-    """Returns True if the line can be split before the next token."""
+  def CanSplit(self, must_split):
+    """Determine if we can split before the next token.
+
+    Arguments:
+      must_split: (bool) A newline was required before this token.
+
+    Returns:
+      True if the line can be split before the next token.
+    """
     current = self.next_token
 
     if current.is_pseudo_paren:
       return False
 
+    if (format_token.Subtype.DICTIONARY_KEY_PART in current.subtypes and
+        format_token.Subtype.DICTIONARY_KEY not in current.subtypes and
+        not style.Get('ALLOW_MULTILINE_DICTIONARY_KEYS') and not must_split):
+      # In some situations, a dictionary may be multiline, but pylint doesn't
+      # like it. So don't allow it unless forced to.
+      return False
+
     return current.can_break_before
 
   def MustSplit(self):
@@ -209,8 +223,7 @@
         format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN_ARG_LIST in
         current.subtypes):
       if (previous.value not in {'=', ':', '*', '**'} and
-          current.value not in ':=,)' and
-          not _IsFunctionDefinition(previous)):
+          current.value not in ':=,)' and not _IsFunctionDefinition(previous)):
         # If we're going to split the lines because of named arguments, then we
         # want to split after the opening bracket as well. But not when this is
         # part of a function definition.
@@ -276,8 +289,8 @@
             return True
 
     pprevious = previous.previous_token
-    if (current.is_name and pprevious and
-        pprevious.is_name and previous.value == '('):
+    if (current.is_name and pprevious and pprevious.is_name and
+        previous.value == '('):
       if (not self._FitsOnLine(previous, previous.matching_bracket) and
           _IsFunctionCallWithArguments(current)):
         # There is a function call, with more than 1 argument, where the first
diff --git a/yapf/yapflib/format_token.py b/yapf/yapflib/format_token.py
index 13d78ff..ec9f0e4 100644
--- a/yapf/yapflib/format_token.py
+++ b/yapf/yapflib/format_token.py
@@ -46,12 +46,13 @@
   KWARGS_STAR_STAR = 9
   ASSIGN_OPERATOR = 10
   DICTIONARY_KEY = 11
-  DICTIONARY_VALUE = 12
-  DICT_SET_GENERATOR = 13
-  COMP_FOR = 14
-  COMP_IF = 15
-  FUNC_DEF = 16
-  DECORATOR = 17
+  DICTIONARY_KEY_PART = 12
+  DICTIONARY_VALUE = 13
+  DICT_SET_GENERATOR = 14
+  COMP_FOR = 15
+  COMP_IF = 16
+  FUNC_DEF = 17
+  DECORATOR = 18
 
 
 class FormatToken(object):
diff --git a/yapf/yapflib/reformatter.py b/yapf/yapflib/reformatter.py
index 1d69783..5fd9ca1 100644
--- a/yapf/yapflib/reformatter.py
+++ b/yapf/yapflib/reformatter.py
@@ -357,10 +357,10 @@
   Returns:
     The updated number of elements in the queue.
   """
-  if newline and not previous_node.state.CanSplit():
+  must_split = previous_node.state.MustSplit()
+  if newline and not previous_node.state.CanSplit(must_split):
     # Don't add a newline if the token cannot be split.
     return count
-  must_split = previous_node.state.MustSplit()
   if not newline and must_split:
     # Don't add a token we must split but where we aren't splitting.
     return count
diff --git a/yapf/yapflib/style.py b/yapf/yapflib/style.py
index 0b4a1f4..63d110a 100644
--- a/yapf/yapflib/style.py
+++ b/yapf/yapflib/style.py
@@ -51,6 +51,14 @@
       Align closing bracket with visual indentation."""),
     ALLOW_MULTILINE_LAMBDAS=textwrap.dedent("""\
       Allow lambdas to be formatted on more than one line."""),
+    ALLOW_MULTILINE_DICTIONARY_KEYS=textwrap.dedent("""\
+      Allow dictionary keys to exist on multiple lines. For example:
+
+        x = {
+            ('this is the first element of a tuple',
+             'this is the second element of a tuple'):
+                 value,
+        }"""),
     BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF=textwrap.dedent("""\
       Insert a blank line before a 'def' or 'class' immediately nested
       within another 'def' or 'class'. For example:
@@ -193,6 +201,7 @@
   return dict(
       ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT=True,
       ALLOW_MULTILINE_LAMBDAS=False,
+      ALLOW_MULTILINE_DICTIONARY_KEYS=False,
       BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF=False,
       BLANK_LINE_BEFORE_CLASS_DOCSTRING=False,
       COALESCE_BRACKETS=False,
@@ -301,6 +310,7 @@
 _STYLE_OPTION_VALUE_CONVERTER = dict(
     ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT=_BoolConverter,
     ALLOW_MULTILINE_LAMBDAS=_BoolConverter,
+    ALLOW_MULTILINE_DICTIONARY_KEYS=_BoolConverter,
     BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF=_BoolConverter,
     BLANK_LINE_BEFORE_CLASS_DOCSTRING=_BoolConverter,
     COALESCE_BRACKETS=_BoolConverter,
diff --git a/yapf/yapflib/subtype_assigner.py b/yapf/yapflib/subtype_assigner.py
index 098eb54..3e27fbf 100644
--- a/yapf/yapflib/subtype_assigner.py
+++ b/yapf/yapflib/subtype_assigner.py
@@ -98,6 +98,7 @@
             # on a single line.
             _AppendFirstLeafTokenSubtype(child,
                                          format_token.Subtype.DICTIONARY_KEY)
+            _AppendSubtypeRec(child, format_token.Subtype.DICTIONARY_KEY_PART)
         last_was_colon = pytree_utils.NodeName(child) == 'COLON'
 
   def Visit_expr_stmt(self, node):  # pylint: disable=invalid-name
diff --git a/yapftests/format_decision_state_test.py b/yapftests/format_decision_state_test.py
index 5f09795..1afa325 100644
--- a/yapftests/format_decision_state_test.py
+++ b/yapftests/format_decision_state_test.py
@@ -42,42 +42,42 @@
     # Add: 'f'
     state = format_decision_state.FormatDecisionState(uwline, 0)
     self.assertEqual('f', state.next_token.value)
-    self.assertFalse(state.CanSplit())
+    self.assertFalse(state.CanSplit(False))
 
     # Add: '('
     state.AddTokenToState(False, True)
     self.assertEqual('(', state.next_token.value)
-    self.assertFalse(state.CanSplit())
+    self.assertFalse(state.CanSplit(False))
     self.assertFalse(state.MustSplit())
 
     # Add: 'a'
     state.AddTokenToState(False, True)
     self.assertEqual('a', state.next_token.value)
-    self.assertTrue(state.CanSplit())
+    self.assertTrue(state.CanSplit(False))
     self.assertFalse(state.MustSplit())
 
     # Add: ','
     state.AddTokenToState(False, True)
     self.assertEqual(',', state.next_token.value)
-    self.assertFalse(state.CanSplit())
+    self.assertFalse(state.CanSplit(False))
     self.assertFalse(state.MustSplit())
 
     # Add: 'b'
     state.AddTokenToState(False, True)
     self.assertEqual('b', state.next_token.value)
-    self.assertTrue(state.CanSplit())
+    self.assertTrue(state.CanSplit(False))
     self.assertFalse(state.MustSplit())
 
     # Add: ')'
     state.AddTokenToState(False, True)
     self.assertEqual(')', state.next_token.value)
-    self.assertTrue(state.CanSplit())
+    self.assertTrue(state.CanSplit(False))
     self.assertFalse(state.MustSplit())
 
     # Add: ':'
     state.AddTokenToState(False, True)
     self.assertEqual(':', state.next_token.value)
-    self.assertFalse(state.CanSplit())
+    self.assertFalse(state.CanSplit(False))
     self.assertFalse(state.MustSplit())
 
     clone = state.Clone()
@@ -95,37 +95,37 @@
     # Add: 'f'
     state = format_decision_state.FormatDecisionState(uwline, 0)
     self.assertEqual('f', state.next_token.value)
-    self.assertFalse(state.CanSplit())
+    self.assertFalse(state.CanSplit(False))
 
     # Add: '('
     state.AddTokenToState(True, True)
     self.assertEqual('(', state.next_token.value)
-    self.assertFalse(state.CanSplit())
+    self.assertFalse(state.CanSplit(False))
 
     # Add: 'a'
     state.AddTokenToState(True, True)
     self.assertEqual('a', state.next_token.value)
-    self.assertTrue(state.CanSplit())
+    self.assertTrue(state.CanSplit(False))
 
     # Add: ','
     state.AddTokenToState(True, True)
     self.assertEqual(',', state.next_token.value)
-    self.assertFalse(state.CanSplit())
+    self.assertFalse(state.CanSplit(False))
 
     # Add: 'b'
     state.AddTokenToState(True, True)
     self.assertEqual('b', state.next_token.value)
-    self.assertTrue(state.CanSplit())
+    self.assertTrue(state.CanSplit(False))
 
     # Add: ')'
     state.AddTokenToState(True, True)
     self.assertEqual(')', state.next_token.value)
-    self.assertTrue(state.CanSplit())
+    self.assertTrue(state.CanSplit(False))
 
     # Add: ':'
     state.AddTokenToState(True, True)
     self.assertEqual(':', state.next_token.value)
-    self.assertFalse(state.CanSplit())
+    self.assertFalse(state.CanSplit(False))
 
     clone = state.Clone()
     self.assertEqual(repr(state), repr(clone))
diff --git a/yapftests/reformatter_basic_test.py b/yapftests/reformatter_basic_test.py
index b612099..5724122 100644
--- a/yapftests/reformatter_basic_test.py
+++ b/yapftests/reformatter_basic_test.py
@@ -1510,6 +1510,38 @@
     finally:
       style.SetGlobalStyle(style.CreateChromiumStyle())
 
+  def testMultilineDictionaryKeys(self):
+    try:
+      style.SetGlobalStyle(
+          style.CreateStyleFromConfig('{based_on_style: chromium, '
+                                      'allow_multiline_dictionary_keys: true}'))
+      unformatted_code = textwrap.dedent("""\
+          MAP_WITH_LONG_KEYS = {
+              ('lorem ipsum', 'dolor sit amet'):
+                  1,
+              ('consectetur adipiscing elit.', 'Vestibulum mauris justo, ornare eget dolor eget'):
+                  2,
+              ('vehicula convallis nulla. Vestibulum dictum nisl in malesuada finibus.',):
+                  3
+          }
+          """)
+      expected_formatted_code = textwrap.dedent("""\
+          MAP_WITH_LONG_KEYS = {
+              ('lorem ipsum', 'dolor sit amet'):
+                  1,
+              ('consectetur adipiscing elit.',
+               'Vestibulum mauris justo, ornare eget dolor eget'):
+                   2,
+              ('vehicula convallis nulla. Vestibulum dictum nisl in malesuada finibus.',):
+                  3
+          }
+          """)
+      uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code)
+      self.assertCodeEqual(expected_formatted_code,
+                           reformatter.Reformat(uwlines))
+    finally:
+      style.SetGlobalStyle(style.CreateChromiumStyle())
+
   def testStableDictionaryFormatting(self):
     try:
       style.SetGlobalStyle(
@@ -1992,8 +2024,7 @@
 
     try:
       style.SetGlobalStyle(
-          style.CreateStyleFromConfig(
-              '{based_on_style: chromium, \
+          style.CreateStyleFromConfig('{based_on_style: chromium, \
 blank_line_before_class_docstring: True}'))
       unformatted_code = textwrap.dedent('''\
           class A: