blob: 13c4718882c10be082cb952311f36b916ddf163e [file]
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
// 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:analyzer/dart/element/element.dart';
/// Element categorization used by [MemberSortKey].
enum MemberCategory {
constructor,
propertyAccessor,
topLevelFunctionOrMethod,
interface,
extension,
typeAlias,
}
/// Sort key used to sort elements in the output.
final class MemberSortKey implements Comparable<MemberSortKey> {
final bool isInstanceMember;
final MemberCategory category;
final String name;
final bool isSetter;
MemberSortKey({
required this.isInstanceMember,
required this.category,
required this.name,
required this.isSetter,
});
@override
int compareTo(MemberSortKey other) {
if ((isInstanceMember ? 1 : 0).compareTo(other.isInstanceMember ? 1 : 0)
case final value when value != 0) {
return value;
}
if (category.index.compareTo(other.category.index) case final value
when value != 0) {
return value;
}
if (category == MemberCategory.constructor &&
other.category == MemberCategory.constructor) {
if (name == 'new') {
return other.name == 'new' ? 0 : -1;
} else if (other.name == 'new') {
return 1;
}
}
if (name.compareTo(other.name) case final value when value != 0) {
return value;
}
return (isSetter ? 1 : 0).compareTo(other.isSetter ? 1 : 0);
}
static MemberCategory computeCategory(Element element) => switch (element) {
ConstructorElement() => MemberCategory.constructor,
PropertyAccessorElement() => MemberCategory.propertyAccessor,
TopLevelFunctionElement() => MemberCategory.topLevelFunctionOrMethod,
MethodElement() => MemberCategory.topLevelFunctionOrMethod,
InterfaceElement() => MemberCategory.interface,
ExtensionElement() => MemberCategory.extension,
TypeAliasElement() => MemberCategory.typeAlias,
dynamic(:final runtimeType) => throw UnimplementedError(
'Unexpected element: $runtimeType',
),
};
static bool computeIsInstanceMember(Element element) =>
element.enclosingElement is InstanceElement &&
switch (element) {
ExecutableElement(:final isStatic) => !isStatic,
dynamic(:final runtimeType) => throw UnimplementedError(
'Unexpected element: $runtimeType',
),
};
}