[analyser] Sort TypeHierarchy results

Fixes https://github.com/dart-lang/sdk/issues/26412

Change-Id: I0d00e8be645532695bb52a8b7c9afec455c39319
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/215546
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/lib/src/search/type_hierarchy.dart b/pkg/analysis_server/lib/src/search/type_hierarchy.dart
index 988f96a..4877ec5 100644
--- a/pkg/analysis_server/lib/src/search/type_hierarchy.dart
+++ b/pkg/analysis_server/lib/src/search/type_hierarchy.dart
@@ -52,7 +52,19 @@
     var pivotClass = _pivotClass;
     if (pivotClass != null) {
       _createSuperItem(pivotClass, null);
+      var superLength = _items.length;
       await _createSubclasses(_items[0], 0, pivotClass);
+
+      // sort subclasses only
+      if (_items.length > superLength + 1) {
+        var subList = _items.sublist(superLength);
+        subList
+            .sort((a, b) => a.classElement.name.compareTo(b.classElement.name));
+        for (var i = 0; i < subList.length; i++) {
+          _items[i + superLength] = subList[i];
+        }
+      }
+
       return _items;
     }
     return null;
diff --git a/pkg/analysis_server/test/search/type_hierarchy_test.dart b/pkg/analysis_server/test/search/type_hierarchy_test.dart
index 2cc6f9f..e0fef5d 100644
--- a/pkg/analysis_server/test/search/type_hierarchy_test.dart
+++ b/pkg/analysis_server/test/search/type_hierarchy_test.dart
@@ -431,6 +431,116 @@
     ]);
   }
 
+  Future<void> test_class_order() async {
+    addTestFile('''
+class A {}
+class D extends A {}
+class C extends A {}
+class B extends A {}
+class G extends B {}
+class F extends B {}
+class E extends A {}
+''');
+    var items = await _getTypeHierarchy('A {}');
+    expect(_toJson(items), [
+      {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'A',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 1,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': [2, 3, 4, 5]
+      },
+      {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'Object',
+          'location': anything,
+          'flags': 0
+        },
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      },
+      {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'B',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 0,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': [6, 7]
+      },
+      {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'C',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 0,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      },
+      {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'D',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 0,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      },
+      {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'E',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 0,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      },
+      {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'F',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 4,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      },
+      {
+        'classElement': {
+          'kind': 'CLASS',
+          'name': 'G',
+          'location': anything,
+          'flags': 0
+        },
+        'superclass': 4,
+        'interfaces': [],
+        'mixins': [],
+        'subclasses': []
+      }
+    ]);
+  }
+
   Future<void> test_class_withTypes() async {
     addTestFile('''
 class MA {}