Don't force for fully split if initializers or updaters do.

Fix #375. Fix #377.

R=kevmoo@google.com

Review URL: https://chromiumcodereview.appspot.com//1255703002 .
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 64d213a..e8a2ed1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,7 @@
 * New optimized line splitter (#360, #380).
 * Allow splitting after argument name (#368).
 * Parsing a statement fails if there is unconsumed input (#372).
+* Don't force `for` fully split if initializers or updaters do (#375, #377).
 * Split before `deferred` (#381).
 * Allow splitting on `as` and `is` expressions (#384).
 * Support null-aware operators (`?.`, `??`, and `??=`) (#385).
diff --git a/lib/src/source_visitor.dart b/lib/src/source_visitor.dart
index dbeb1fd..42897b8 100644
--- a/lib/src/source_visitor.dart
+++ b/lib/src/source_visitor.dart
@@ -849,6 +849,9 @@
       // as the rest of the loop clauses.
       builder.indent(Indent.loopVariable);
 
+      // Allow the variables to stay unsplit even if the clauses split.
+      builder.startRule();
+
       var declaration = node.variables;
       visitDeclarationMetadata(declaration.metadata);
       modifier(declaration.keyword);
@@ -858,6 +861,7 @@
         split();
       });
 
+      builder.endRule();
       builder.unindent();
     }
 
@@ -871,7 +875,13 @@
     // The update clause.
     if (node.updaters.isNotEmpty) {
       split();
+
+      // Allow the updates to stay unsplit even if the clauses split.
+      builder.startRule();
+
       visitCommaSeparatedNodes(node.updaters, between: split);
+
+      builder.endRule();
     }
 
     token(node.rightParenthesis);
diff --git a/test/regression/0300/0375.stmt b/test/regression/0300/0375.stmt
new file mode 100644
index 0000000..026a9c9
--- /dev/null
+++ b/test/regression/0300/0375.stmt
@@ -0,0 +1,8 @@
+>>> (indent 4)
+    for (int inputIndex = 1, statementIndex = 0;
+         inputIndex < inputs.length;
+         statementIndex++) {}
+<<<
+    for (int inputIndex = 1, statementIndex = 0;
+        inputIndex < inputs.length;
+        statementIndex++) {}
\ No newline at end of file
diff --git a/test/regression/0300/0377.stmt b/test/regression/0300/0377.stmt
new file mode 100644
index 0000000..40099c0
--- /dev/null
+++ b/test/regression/0300/0377.stmt
@@ -0,0 +1,8 @@
+>>> (indent 6)
+      for (int i = 0;
+           i < positionalArgumentCount;
+           arguments = arguments.tail, i++) {}
+<<<
+      for (int i = 0;
+          i < positionalArgumentCount;
+          arguments = arguments.tail, i++) {}
\ No newline at end of file
diff --git a/test/splitting/loops.stmt b/test/splitting/loops.stmt
index f9c520a..800e01d 100644
--- a/test/splitting/loops.stmt
+++ b/test/splitting/loops.stmt
@@ -33,13 +33,14 @@
 <<<
 for (foo; bar; a++, b++) {}
 >>> split between updaters splits everything
-for (foo; bar; first = 1, second = 2, third = 3) {}
+for (foo; bar; first = 1, second = 2, third = 3, fourth = 4) {}
 <<<
 for (foo;
     bar;
     first = 1,
     second = 2,
-    third = 3) {}
+    third = 3,
+    fourth = 4) {}
 >>> nest wrapped initializer
 for (very + long + initialization + expression; a; b) {}
 <<<
@@ -62,4 +63,24 @@
 while (
     aLongConditionExpressionThatWraps) {
   ;
+}
+>>> don't force variables to split if clauses do
+for (var a = 1, b = 2; longCondition(expression); a += b) {
+  ;
+}
+<<<
+for (var a = 1, b = 2;
+    longCondition(expression);
+    a += b) {
+  ;
+}
+>>> don't force updates to split if clauses do
+for (var a = 0; longCondition(expression); a += 1, b += 1) {
+  ;
+}
+<<<
+for (var a = 0;
+    longCondition(expression);
+    a += 1, b += 1) {
+  ;
 }
\ No newline at end of file