[interop] Minor Fixes in Generics with Anonymous Closures (#447)
* Minor Fixes in Generics with Anonymous Closures
* added test, and made generic type list a set
diff --git a/web_generator/lib/src/ast/helpers.dart b/web_generator/lib/src/ast/helpers.dart
index 4d071e9..f509c71 100644
--- a/web_generator/lib/src/ast/helpers.dart
+++ b/web_generator/lib/src/ast/helpers.dart
@@ -160,8 +160,8 @@
}
/// Recursively get the generic types specified in a given type [t]
-List<GenericType> getGenericTypes(Type t) {
- final types = <(String, Type?)>[];
+Set<GenericType> getGenericTypes(Type t) {
+ final types = <(String, Type?)>{};
switch (t) {
case GenericType():
types.add((t.name, t.constraint));
@@ -250,7 +250,7 @@
// Types are cloned so that modifications to constraints can happen without
// affecting initial references
- return types.map((t) => GenericType(name: t.$1, constraint: t.$2)).toList();
+ return types.map((t) => GenericType(name: t.$1, constraint: t.$2)).toSet();
}
Type desugarTypeAliases(Type t) {
diff --git a/web_generator/lib/src/ast/types.dart b/web_generator/lib/src/ast/types.dart
index 5e5552a..4bc6bb8 100644
--- a/web_generator/lib/src/ast/types.dart
+++ b/web_generator/lib/src/ast/types.dart
@@ -337,13 +337,24 @@
this.typeParameters = const [],
this.parameters = const [],
this.isNullable = false,
- }) : declarationName = name;
+ }) : declarationName = name {
+ if (typeParameters.isEmpty) {
+ typeParameters.addAll(getGenericTypes(this).map((t) {
+ t.constraint ??= BuiltinType.anyType;
+ return t;
+ }));
+ }
+ }
@override
Reference emit([TypeOptions? options]) {
return TypeReference((t) => t
..symbol = declarationName
- ..isNullable = options?.nullable ?? isNullable);
+ ..isNullable = options?.nullable ?? isNullable
+ ..types.addAll(typeParameters.map((t) {
+ final clonedT = GenericType(name: t.name, isNullable: t.isNullable);
+ return clonedT.emit(options);
+ })));
}
}
@@ -388,8 +399,7 @@
name: 'call',
id: const ID(type: 'fun', name: 'call'),
returnType: returnType,
- parameters: parameters,
- typeParameters: typeParameters)
+ parameters: parameters)
]);
}
@@ -445,8 +455,6 @@
.addAll(typeParameters.map((t) => t.emit(options?.toTypeOptions())))
..methods.add(Method((m) => m
..name = 'call'
- ..types
- .addAll(typeParameters.map((t) => t.emit(options?.toTypeOptions())))
..returns = returnType.emit(options?.toTypeOptions())
..requiredParameters.addAll(requiredParams)
..optionalParameters.addAll(optionalParams)
diff --git a/web_generator/test/integration/interop_gen/ts_typing_expected.dart b/web_generator/test/integration/interop_gen/ts_typing_expected.dart
index 9962ca3..c583c9b 100644
--- a/web_generator/test/integration/interop_gen/ts_typing_expected.dart
+++ b/web_generator/test/integration/interop_gen/ts_typing_expected.dart
@@ -33,6 +33,7 @@
static const MyEnum D = MyEnum._(4);
}
+typedef Transformer<T extends _i1.JSAny?> = _AnonymousFunction_5293571<T>;
@_i1.JS()
external _i1.JSFunction copyOfmyEnclosingFunction;
@_i1.JS()
@@ -112,6 +113,10 @@
external T value;
}
+extension type _AnonymousFunction_5293571<T extends _i1.JSAny?>._(
+ _i1.JSFunction _) implements _i1.JSFunction {
+ external ComposedType<T> call(T object);
+}
extension type ComposedType<T extends _i1.JSAny?>._(_i1.JSObject _)
implements _i1.JSObject {
external T enclosed;
diff --git a/web_generator/test/integration/interop_gen/ts_typing_input.d.ts b/web_generator/test/integration/interop_gen/ts_typing_input.d.ts
index b47a6cc..713db27 100644
--- a/web_generator/test/integration/interop_gen/ts_typing_input.d.ts
+++ b/web_generator/test/integration/interop_gen/ts_typing_input.d.ts
@@ -11,6 +11,7 @@
interface ComposedType<T = any> {
enclosed: T;
}
+export type Transformer<T> = (object: T) => ComposedType<T>;
export declare let copyOfmyEnclosingFunction: typeof myEnclosingFunction;
export declare const myEnumValue: MyEnum;
export declare const myEnumValue2: typeof MyEnum;