Skip to content

Commit 779d005

Browse files
[interop] Add Support for Anonymous Declarations (#434)
This adds support for generating declarations for anonymous declarations, such as anonymous objects, unions, closures and constructor types. This also adds support for nullable types (types unioned with undefined and/or null). A hashing function is used for consistently hashing string objects, which is used for hashing identifiers for anonymous unions, objects and more, as well as comparing such names to allow reusing of such types. * wip: union types * wip: completed anonymous unions * implemented JS Tuple * completed nullability support for `undefined` and `null` * wip: object decl * implemented anonymous objects * added support for closures and constructors * wip: type hierarchy * implemented sub type deduction * added type generics to union types * changed `.reduce` to `.fold` * resolved newline and license headers * isNullable updates and renamed `DeclarationAssociatedType` * updated algorithm to use LCA via Topological Ordering * resolved some more comments * rm hasher_test * resolved some more comments * refactored tuple generation (common types) and more * added LCA test * removed stray prints * added doc support and resolved merge * updated documentation formatting using formatting.dart
1 parent cc3aa64 commit 779d005

30 files changed

+2791
-322
lines changed

web_generator/analysis_options.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ analyzer:
66
strict-casts: true
77
strict-inference: true
88
strict-raw-types: true
9+
errors:
10+
comment_references: ignore
911

1012
linter:
1113
rules:

web_generator/lib/src/ast/base.dart

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ class ASTOptions {
4545
}
4646

4747
sealed class Node {
48-
String? get name;
4948
abstract final ID id;
5049
String? get dartName;
5150

@@ -55,7 +54,6 @@ sealed class Node {
5554
}
5655

5756
abstract class Declaration extends Node {
58-
@override
5957
String get name;
6058

6159
@override
@@ -66,11 +64,19 @@ abstract class NamedDeclaration extends Declaration {
6664
@override
6765
abstract String name;
6866

69-
abstract Documentation? documentation;
70-
71-
ReferredType asReferredType([List<Type>? typeArgs, String? url]) =>
67+
ReferredType asReferredType(
68+
[List<Type>? typeArgs, bool isNullable = false, String? url]) =>
7269
ReferredType(
73-
name: name, declaration: this, typeParams: typeArgs ?? [], url: url);
70+
name: name,
71+
declaration: this,
72+
typeParams: typeArgs ?? [],
73+
url: url,
74+
isNullable: isNullable);
75+
}
76+
77+
abstract interface class DocumentedDeclaration {
78+
/// The documentation associated with the given declaration
79+
abstract Documentation? documentation;
7480
}
7581

7682
abstract interface class ExportableDeclaration extends Declaration {
@@ -88,8 +94,20 @@ abstract class Type extends Node {
8894
@override
8995
String? dartName;
9096

97+
/// Whether the given type is nullable or not
98+
/// (unioned with `undefined` or `null`)
99+
abstract bool isNullable;
100+
91101
@override
92102
Reference emit([covariant TypeOptions? options]);
103+
104+
@override
105+
bool operator ==(Object other) {
106+
return other is Type && id == other.id;
107+
}
108+
109+
@override
110+
int get hashCode => Object.hashAll([id]);
93111
}
94112

95113
abstract class FieldDeclaration extends NamedDeclaration {
@@ -106,6 +124,12 @@ abstract class CallableDeclaration extends NamedDeclaration {
106124

107125
enum DeclScope { private, protected, public }
108126

127+
abstract class DeclarationType<T extends Declaration> extends Type {
128+
T get declaration;
129+
130+
String get declarationName;
131+
}
132+
109133
class ParameterDeclaration {
110134
final String name;
111135

@@ -127,3 +151,7 @@ class ParameterDeclaration {
127151
..type = type.emit(TypeOptions(nullable: optional)));
128152
}
129153
}
154+
155+
abstract class NamedType extends Type {
156+
String get name;
157+
}

web_generator/lib/src/ast/builtin.dart

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import 'base.dart';
1212

1313
/// A built in type supported by `dart:js_interop` or by this library
1414
/// (with generated declarations)
15-
class BuiltinType extends Type {
15+
class BuiltinType extends NamedType {
1616
@override
1717
final String name;
1818

@@ -21,15 +21,15 @@ class BuiltinType extends Type {
2121
/// Whether the given type is present in "dart:js_interop"
2222
final bool fromDartJSInterop;
2323

24-
// TODO(nikeokoronkwo): Types in general should have an `isNullable`
25-
// property on them to indicate nullability for Dart generated code.
26-
final bool? isNullable;
24+
@override
25+
bool isNullable;
2726

2827
BuiltinType(
2928
{required this.name,
3029
this.typeParams = const [],
3130
this.fromDartJSInterop = false,
32-
this.isNullable});
31+
bool? isNullable})
32+
: isNullable = isNullable ?? false;
3333

3434
@override
3535
ID get id => ID(type: 'type', name: name);
@@ -39,16 +39,14 @@ class BuiltinType extends Type {
3939

4040
@override
4141
Reference emit([TypeOptions? options]) {
42-
options ??= TypeOptions();
43-
4442
return TypeReference((t) => t
4543
..symbol = name
4644
..types.addAll(typeParams
4745
// if there is only one type param, and it is void, ignore
4846
.where((p) => typeParams.length != 1 || p != $voidType)
49-
.map((p) => p.emit(TypeOptions())))
47+
.map((p) => p.emit(options)))
5048
..url = fromDartJSInterop ? 'dart:js_interop' : null
51-
..isNullable = isNullable ?? options!.nullable);
49+
..isNullable = isNullable || (options?.nullable ?? false));
5250
}
5351

5452
static final BuiltinType $voidType = BuiltinType(name: 'void');
@@ -81,7 +79,10 @@ class BuiltinType extends Type {
8179
name: 'JSString', fromDartJSInterop: true, isNullable: isNullable)
8280
: BuiltinType(name: 'String', isNullable: isNullable),
8381
PrimitiveType.$void || PrimitiveType.undefined => $voidType,
84-
PrimitiveType.any || PrimitiveType.unknown => anyType,
82+
PrimitiveType.any => (isNullable ?? false)
83+
? anyType
84+
: BuiltinType(name: 'JSAny', fromDartJSInterop: true),
85+
PrimitiveType.unknown => anyType,
8586
PrimitiveType.object => BuiltinType(
8687
name: 'JSObject', fromDartJSInterop: true, isNullable: isNullable),
8788
PrimitiveType.symbol => BuiltinType(
@@ -128,13 +129,14 @@ class BuiltinType extends Type {
128129
}
129130
}
130131

131-
class PackageWebType extends Type {
132+
class PackageWebType extends NamedType {
132133
@override
133134
final String name;
134135

135136
final List<Type> typeParams;
136137

137-
final bool? isNullable;
138+
@override
139+
bool isNullable;
138140

139141
@override
140142
ID get id => ID(type: 'type', name: name);
@@ -143,29 +145,29 @@ class PackageWebType extends Type {
143145
String? get dartName => null;
144146

145147
PackageWebType._(
146-
{required this.name, this.typeParams = const [], this.isNullable});
148+
{required this.name,
149+
this.typeParams = const [],
150+
this.isNullable = false});
147151

148152
@override
149153
Reference emit([TypeOptions? options]) {
150-
options ??= TypeOptions();
151-
152154
// TODO: We can make this a shared function as it is called a lot
153155
// between types
154156
return TypeReference((t) => t
155157
..symbol = name
156158
..types.addAll(typeParams
157159
// if there is only one type param, and it is void, ignore
158160
.where((p) => typeParams.length != 1 || p != BuiltinType.$voidType)
159-
.map((p) => p.emit(TypeOptions())))
161+
.map((p) => p.emit(options)))
160162
..url = 'package:web/web.dart'
161-
..isNullable = isNullable ?? options!.nullable);
163+
..isNullable = isNullable || (options?.nullable ?? false));
162164
}
163165

164166
static PackageWebType parse(String name,
165167
{bool? isNullable, List<Type> typeParams = const []}) {
166168
return PackageWebType._(
167169
name: renameMap.containsKey(name) ? renameMap[name]! : name,
168-
isNullable: isNullable,
170+
isNullable: isNullable ?? false,
169171
typeParams: typeParams);
170172
}
171173
}

0 commit comments

Comments
 (0)