mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:09:49 +00:00
[analysis_server] Fix relationships for subtypes that provide type arguments
Change-Id: I655f7bff036a17ee79a1d0f9f163125112766f2b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/264001 Commit-Queue: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
parent
3e7a1703bb
commit
54d7847787
|
@ -94,18 +94,23 @@ class DartLazyTypeHierarchyComputer {
|
|||
InterfaceElement target, SearchEngine searchEngine) async {
|
||||
final targetType = target.thisType;
|
||||
|
||||
/// Helper to check whether [type] refers to the same class as [target]
|
||||
/// irrespective of any concrete type arguments.
|
||||
bool isTargetClass(InterfaceType? type) =>
|
||||
type?.element == targetType.element;
|
||||
|
||||
/// Helper to convert an [InterfaceElement] to a [TypeHierarchyRelatedItem].
|
||||
TypeHierarchyRelatedItem toHierarchyItem(InterfaceElement element) {
|
||||
final type = element.thisType;
|
||||
if (element is MixinElement &&
|
||||
element.superclassConstraints.contains(targetType)) {
|
||||
element.superclassConstraints.any(isTargetClass)) {
|
||||
return TypeHierarchyRelatedItem.constrainedTo(type);
|
||||
} else if (element.supertype == targetType) {
|
||||
} else if (isTargetClass(element.supertype)) {
|
||||
return TypeHierarchyRelatedItem.extends_(type);
|
||||
} else if (element.interfaces.contains(targetType)) {
|
||||
} else if (element.interfaces.any(isTargetClass)) {
|
||||
return TypeHierarchyRelatedItem.implements(type);
|
||||
} else if (element.mixins.contains(targetType)) {
|
||||
return TypeHierarchyRelatedItem.with_(type);
|
||||
} else if (element.mixins.any(isTargetClass)) {
|
||||
return TypeHierarchyRelatedItem.mixesIn(type);
|
||||
} else {
|
||||
assert(false, 'Subtype found with unknown relationship type');
|
||||
return TypeHierarchyRelatedItem.unknown(type);
|
||||
|
@ -136,7 +141,7 @@ class DartLazyTypeHierarchyComputer {
|
|||
if (supertype != null) TypeHierarchyRelatedItem.extends_(supertype),
|
||||
...?superclassConstraints?.map(TypeHierarchyRelatedItem.constrainedTo),
|
||||
...?interfaces?.map(TypeHierarchyRelatedItem.implements),
|
||||
...?mixins?.map(TypeHierarchyRelatedItem.with_),
|
||||
...?mixins?.map(TypeHierarchyRelatedItem.mixesIn),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -213,14 +218,14 @@ class TypeHierarchyRelatedItem extends TypeHierarchyItem {
|
|||
: this._forElement(type.element,
|
||||
relationship: TypeHierarchyItemRelationship.implements);
|
||||
|
||||
TypeHierarchyRelatedItem.mixesIn(InterfaceType type)
|
||||
: this._forElement(type.element,
|
||||
relationship: TypeHierarchyItemRelationship.mixesIn);
|
||||
|
||||
TypeHierarchyRelatedItem.unknown(InterfaceType type)
|
||||
: this._forElement(type.element,
|
||||
relationship: TypeHierarchyItemRelationship.unknown);
|
||||
|
||||
TypeHierarchyRelatedItem.with_(InterfaceType type)
|
||||
: this._forElement(type.element,
|
||||
relationship: TypeHierarchyItemRelationship.mixesIn);
|
||||
|
||||
TypeHierarchyRelatedItem._forElement(super.element,
|
||||
{required this.relationship})
|
||||
: super.forElement();
|
||||
|
|
|
@ -112,6 +112,26 @@ class TypeHierarchyComputerFindSubtypesTest extends AbstractTypeHierarchyTest {
|
|||
]);
|
||||
}
|
||||
|
||||
Future<void> test_class_generic() async {
|
||||
final content = '''
|
||||
class My^Class1<T> {}
|
||||
/*[0*/class /*[1*/MyClass2/*1]*/ implements MyClass1<String> {}/*0]*/
|
||||
''';
|
||||
|
||||
addTestSource(content);
|
||||
final target = await findTarget();
|
||||
final supertypes = await findSubtypes(target!);
|
||||
expect(supertypes, [
|
||||
_isRelatedItem(
|
||||
'MyClass2',
|
||||
testFile,
|
||||
relationship: TypeHierarchyItemRelationship.implements,
|
||||
codeRange: code.ranges[0].sourceRange,
|
||||
nameRange: code.ranges[1].sourceRange,
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
Future<void> test_class_interfaces() async {
|
||||
final content = '''
|
||||
class ^MyClass1 {}
|
||||
|
@ -300,6 +320,27 @@ class ^MyClass2 extends MyClass1 {}
|
|||
]);
|
||||
}
|
||||
|
||||
Future<void> test_class_generic() async {
|
||||
final content = '''
|
||||
/*[0*/class /*[1*/MyClass1/*1]*/<T> {}/*0]*/
|
||||
class ^MyClass2 implements MyClass1<String> {}
|
||||
''';
|
||||
|
||||
addTestSource(content);
|
||||
final target = await findTarget();
|
||||
final supertypes = await findSupertypes(target!);
|
||||
expect(supertypes, [
|
||||
_isObject,
|
||||
_isRelatedItem(
|
||||
'MyClass1',
|
||||
testFile,
|
||||
relationship: TypeHierarchyItemRelationship.implements,
|
||||
codeRange: code.ranges[0].sourceRange,
|
||||
nameRange: code.ranges[1].sourceRange,
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
Future<void> test_class_interfaces() async {
|
||||
final content = '''
|
||||
/*[0*/class /*[1*/MyClass1/*1]*/ {}/*0]*/
|
||||
|
|
Loading…
Reference in a new issue