55import 'package:code_builder/code_builder.dart' ;
66import '../interop_gen/namer.dart' ;
77import 'base.dart' ;
8+ import 'builtin.dart' ;
9+ import 'declarations.dart' ;
810
911class ReferredType <T extends Declaration > extends Type {
1012 @override
@@ -24,27 +26,76 @@ class ReferredType<T extends Declaration> extends Type {
2426
2527 @override
2628 Reference emit ([TypeOptions ? options]) {
27- // TODO: implement emit
28- throw UnimplementedError ();
29+ // TODO: Support referred types imported from URL
30+ return TypeReference ((t) => t
31+ ..symbol = declaration.name
32+ ..types.addAll (typeParams.map ((t) => t.emit (options)))
33+ ..isNullable = options? .nullable);
2934 }
3035}
3136
3237// TODO(https://github.com/dart-lang/web/issues/385): Implement Support for UnionType (including implementing `emit`)
3338class UnionType extends Type {
34- List <Type > types;
39+ final List <Type > types;
3540
3641 UnionType ({required this .types});
3742
3843 @override
39- ID get id => ID (type: 'type' , name: types.map ((t) => t.id).join ('|' ));
44+ ID get id => ID (type: 'type' , name: types.map ((t) => t.id.name).join ('|' ));
45+
46+ @override
47+ String ? get name => null ;
4048
4149 @override
4250 Reference emit ([TypeOptions ? options]) {
4351 throw UnimplementedError ('TODO: Implement UnionType.emit' );
4452 }
53+ }
54+
55+ // TODO: Handle naming anonymous declarations
56+ // TODO: Extract having a declaration associated with a type to its own type
57+ // (e.g DeclarationAssociatedType)
58+ class HomogenousEnumType <T extends LiteralType , D extends Declaration >
59+ extends UnionType {
60+ final List <T > _types;
4561
4662 @override
47- String ? get name => null ;
63+ List <T > get types => _types;
64+
65+ final Type baseType;
66+
67+ final bool isNullable;
68+
69+ String declarationName;
70+
71+ HomogenousEnumType (
72+ {required List <T > types, this .isNullable = false , required String name})
73+ : declarationName = name,
74+ _types = types,
75+ baseType = types.first.baseType,
76+ super (types: types);
77+
78+ EnumDeclaration get declaration => EnumDeclaration (
79+ name: declarationName,
80+ dartName: UniqueNamer .makeNonConflicting (declarationName),
81+ baseType: baseType,
82+ members: types.map ((t) {
83+ final name = t.value.toString ();
84+ return EnumMember (
85+ name,
86+ t.value,
87+ dartName: UniqueNamer .makeNonConflicting (name),
88+ parent: UniqueNamer .makeNonConflicting (declarationName),
89+ );
90+ }).toList (),
91+ exported: true );
92+
93+ @override
94+ Reference emit ([TypeOptions ? options]) {
95+ return TypeReference ((t) => t
96+ ..symbol = declarationName
97+ ..isNullable = options? .nullable ?? isNullable);
98+ }
4899}
49100
50101/// The base class for a type generic (like 'T')
@@ -58,13 +109,62 @@ class GenericType extends Type {
58109
59110 GenericType ({required this .name, this .constraint, this .parent});
60111
112+ @override
113+ ID get id =>
114+ ID (type: 'generic-type' , name: '$name @${parent ?.id ?? "(anonymous)" }' );
115+
61116 @override
62117 Reference emit ([TypeOptions ? options]) => TypeReference ((t) => t
63118 ..symbol = name
64119 ..bound = constraint? .emit ()
65120 ..isNullable = options? .nullable);
121+ }
122+
123+ /// A type representing a bare literal, such as `null` , a string or number
124+ class LiteralType extends Type {
125+ final LiteralKind kind;
126+
127+ final Object ? value;
66128
67129 @override
68- ID get id =>
69- ID (type: 'generic-type' , name: '$name @${parent ?.id ?? "(anonymous)" }' );
130+ String get name => switch (kind) {
131+ LiteralKind .$null => 'null' ,
132+ LiteralKind .int || LiteralKind .double => 'number' ,
133+ LiteralKind .string => 'string' ,
134+ LiteralKind .$true => 'true' ,
135+ LiteralKind .$false => 'false'
136+ };
137+
138+ BuiltinType get baseType {
139+ final primitive = kind.primitive;
140+
141+ return BuiltinType .primitiveType (primitive);
142+ }
143+
144+ LiteralType ({required this .kind, required this .value});
145+
146+ @override
147+ Reference emit ([TypeOptions ? options]) {
148+ return baseType.emit (options);
149+ }
150+
151+ @override
152+ ID get id => ID (type: 'type' , name: name);
153+ }
154+
155+ enum LiteralKind {
156+ $null,
157+ string,
158+ double ,
159+ $true,
160+ $false,
161+ int ;
162+
163+ PrimitiveType get primitive => switch (this ) {
164+ LiteralKind .$null => PrimitiveType .undefined,
165+ LiteralKind .string => PrimitiveType .string,
166+ LiteralKind .int => PrimitiveType .num ,
167+ LiteralKind .double => PrimitiveType .double ,
168+ LiteralKind .$true || LiteralKind .$false => PrimitiveType .boolean
169+ };
70170}
0 commit comments