From 510c2107eed3b6be53e6a61f16781a30d50a16d1 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Wed, 12 Jun 2024 14:53:28 -0700 Subject: [PATCH] Fix referencing an aliased type parameter. (#3784) What is an aliased type parameter? Good question! `typedef TD = T;` is such an alias. The fix is pretty simple, we just weren't previously handling this case, or being safe. --- lib/src/element_type.dart | 32 ++++++++++++++++++++------------ test/typedef_test.dart | 15 +++++++++++++++ 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/lib/src/element_type.dart b/lib/src/element_type.dart index 983579b218..aa7e1d0f2a 100644 --- a/lib/src/element_type.dart +++ b/lib/src/element_type.dart @@ -272,20 +272,28 @@ abstract class DefinedElementType extends ElementType { factory DefinedElementType._from(DartType type, ModelElement modelElement, Library library, PackageGraph packageGraph) { - // `TypeAliasElement.alias.element` has different implications. - // In that case it is an actual type alias of some kind (generic or - // otherwise). Here however `alias.element` signals that this is a type - // referring to an alias. if (type is! TypeAliasElement && type.alias != null) { - return AliasedElementType._( - type as ParameterizedType, library, packageGraph, modelElement); + // Here, `alias.element` signals that this is a type referring to an + // alias. (`TypeAliasElement.alias.element` has different implications. + // In that case it is an actual type alias of some kind (generic or + // otherwise).) + return switch (type) { + TypeParameterType() => + TypeParameterElementType._(type, library, packageGraph, modelElement), + ParameterizedType() => + AliasedElementType._(type, library, packageGraph, modelElement), + _ => throw UnimplementedError( + 'No ElementType implemented for aliased ${type.runtimeType}'), + }; } - if (type is TypeParameterType) { - return TypeParameterElementType._( - type, library, packageGraph, modelElement); - } - return ParameterizedElementType._( - type as ParameterizedType, library, packageGraph, modelElement); + return switch (type) { + TypeParameterType() => + TypeParameterElementType._(type, library, packageGraph, modelElement), + ParameterizedType() => + ParameterizedElementType._(type, library, packageGraph, modelElement), + _ => throw UnimplementedError( + 'No ElementType implemented for ${type.runtimeType}'), + }; } @override diff --git a/test/typedef_test.dart b/test/typedef_test.dart index ae035d6c1d..2e26170a50 100644 --- a/test/typedef_test.dart +++ b/test/typedef_test.dart @@ -40,6 +40,21 @@ typedef T = C; expect(tTypedef.aliasedType, isA()); } + void test_extensionType_generic_referenceToTypeParameter() async { + var library = await bootPackageWithLibrary(''' +typedef TD = T; + +/// Text [T]. +extension type ET(TD _) {} +'''); + + expect( + library.extensionTypes.named('ET').documentationAsHtml, + // There is no way to link to a type parameter. + contains('

Text T.

'), + ); + } + void test_extensionType_basic() async { var library = await bootPackageWithLibrary(''' extension type E(int i) {}