Add List.stablePartition(), use in CreateConstructorForFinalFields.

See https://en.cppreference.com/w/cpp/algorithm/stable_partition

Change-Id: I1cf77ed7c057e4e42009ec4dd1d15ee2af7dd128
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/308812
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/create_constructor_for_final_fields.dart b/pkg/analysis_server/lib/src/services/correction/dart/create_constructor_for_final_fields.dart
index 7cf19d9..cb5de29 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/create_constructor_for_final_fields.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/create_constructor_for_final_fields.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/utilities/extensions/collection.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
@@ -355,10 +356,9 @@
       return;
     }
 
-    final childrenLast = [
-      ...fields.whereNot((field) => field.isChild),
-      ...fields.where((field) => field.isChild),
-    ];
+    final childrenLast = fields.stablePartition(
+      (field) => !field.isChild,
+    );
 
     for (final field in childrenLast) {
       builder.write(', ');
diff --git a/pkg/analyzer/lib/src/utilities/extensions/collection.dart b/pkg/analyzer/lib/src/utilities/extensions/collection.dart
index 12478ee..2208634 100644
--- a/pkg/analyzer/lib/src/utilities/extensions/collection.dart
+++ b/pkg/analyzer/lib/src/utilities/extensions/collection.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:collection/collection.dart';
+
 extension IterableExtension<E> on Iterable<E> {
   /// Returns the fixed-length [List] with elements of `this`.
   List<E> toFixedList() {
@@ -28,6 +30,17 @@
       return null;
     }
   }
+
+  /// Returns a new list with all elements of the target, arranged such that
+  /// all elements for which the [predicate] specified returns `true` come
+  /// before those for which the [predicate] returns `false`. The partitioning
+  /// is stable, i.e. the relative ordering of the elements is preserved.
+  List<E> stablePartition(bool Function(E element) predicate) {
+    return [
+      ...where(predicate),
+      ...whereNot(predicate),
+    ];
+  }
 }
 
 extension SetExtension<E> on Set<E> {
diff --git a/pkg/analyzer/test/src/utilities/extensions/collection_test.dart b/pkg/analyzer/test/src/utilities/extensions/collection_test.dart
index e92ab71..e6c85cf 100644
--- a/pkg/analyzer/test/src/utilities/extensions/collection_test.dart
+++ b/pkg/analyzer/test/src/utilities/extensions/collection_test.dart
@@ -33,6 +33,17 @@
     expect(elements.nextOrNull(2), null);
     expect(elements.nextOrNull(3), null);
   }
+
+  test_stablePartition() {
+    expect(
+      [0, 1, 2, 3, 4, 5].stablePartition((e) => e.isEven),
+      [0, 2, 4, 1, 3, 5],
+    );
+    expect(
+      [5, 4, 3, 2, 1, 0].stablePartition((e) => e.isEven),
+      [4, 2, 0, 5, 3, 1],
+    );
+  }
 }
 
 @reflectiveTest