Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
1c76d12
wip: union types
nikeokoronkwo Aug 1, 2025
d79c2cf
wip: completed anonymous unions
nikeokoronkwo Aug 2, 2025
38b3aab
implemented JS Tuple
nikeokoronkwo Aug 2, 2025
cb90943
completed nullability support for `undefined` and `null`
nikeokoronkwo Aug 2, 2025
37e0d1a
Merge branch 'main' into interop/anonymous
nikeokoronkwo Aug 6, 2025
0b943e7
wip: object decl
nikeokoronkwo Aug 6, 2025
e7535a4
implemented anonymous objects
nikeokoronkwo Aug 6, 2025
c49ce6c
added support for closures and constructors
nikeokoronkwo Aug 7, 2025
f1a9e1c
wip: type hierarchy
nikeokoronkwo Aug 7, 2025
7f0a2e0
implemented sub type deduction
nikeokoronkwo Aug 7, 2025
f57165c
added type generics to union types
nikeokoronkwo Aug 7, 2025
49aa015
changed `.reduce` to `.fold`
nikeokoronkwo Aug 7, 2025
574250f
resolved newline and license headers
nikeokoronkwo Aug 8, 2025
283ab5d
isNullable updates and renamed `DeclarationAssociatedType`
nikeokoronkwo Aug 8, 2025
4a9bca6
updated algorithm to use LCA via Topological Ordering
nikeokoronkwo Aug 11, 2025
78a535f
resolved some more comments
nikeokoronkwo Aug 12, 2025
5421359
rm hasher_test
nikeokoronkwo Aug 12, 2025
f92ffc9
resolved some more comments
nikeokoronkwo Aug 12, 2025
9944b7f
refactored tuple generation (common types) and more
nikeokoronkwo Aug 12, 2025
c665449
added LCA test
nikeokoronkwo Aug 14, 2025
3dae04e
removed stray prints
nikeokoronkwo Aug 14, 2025
6632bc0
Merge branch 'main' into interop/anonymous
nikeokoronkwo Aug 14, 2025
5326ae0
added doc support and resolved merge
nikeokoronkwo Aug 14, 2025
552a461
updated documentation formatting using formatting.dart
nikeokoronkwo Aug 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions web_generator/analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ analyzer:
strict-casts: true
strict-inference: true
strict-raw-types: true
errors:
comment_references: ignore

linter:
rules:
Expand Down
5 changes: 5 additions & 0 deletions web_generator/lib/src/ast/base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ abstract class NamedDeclaration extends Declaration {
isNullable: isNullable);
}

abstract interface class DocumentedDeclaration {
/// The documentation associated with the given declaration
abstract Documentation? documentation;
}

abstract interface class ExportableDeclaration extends Declaration {
/// Whether this declaration is exported.
bool get exported;
Expand Down
19 changes: 12 additions & 7 deletions web_generator/lib/src/ast/declarations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import 'documentation.dart';
import 'helpers.dart';
import 'types.dart';

abstract class NestableDeclaration extends NamedDeclaration {
abstract class NestableDeclaration extends NamedDeclaration
implements DocumentedDeclaration {
NestableDeclaration? get parent;

String get qualifiedName =>
Expand Down Expand Up @@ -153,7 +154,7 @@ sealed class TypeDeclaration extends NestableDeclaration
}
}

abstract class MemberDeclaration {
abstract class MemberDeclaration implements DocumentedDeclaration {
late final TypeDeclaration parent;

abstract final DeclScope scope;
Expand All @@ -162,7 +163,7 @@ abstract class MemberDeclaration {
}

class VariableDeclaration extends FieldDeclaration
implements ExportableDeclaration {
implements ExportableDeclaration, DocumentedDeclaration {
/// The variable modifier, as represented in TypeScript
VariableModifier modifier;

Expand Down Expand Up @@ -228,7 +229,7 @@ class VariableDeclaration extends FieldDeclaration
enum VariableModifier { let, $const, $var }

class FunctionDeclaration extends CallableDeclaration
implements ExportableDeclaration {
implements ExportableDeclaration, DocumentedDeclaration {
@override
String name;

Expand Down Expand Up @@ -297,7 +298,7 @@ class FunctionDeclaration extends CallableDeclaration
}

class EnumDeclaration extends NestableDeclaration
implements ExportableDeclaration {
implements ExportableDeclaration, DocumentedDeclaration {
@override
String name;

Expand Down Expand Up @@ -410,7 +411,7 @@ class EnumMember {
}

class TypeAliasDeclaration extends NamedDeclaration
implements ExportableDeclaration {
implements ExportableDeclaration, DocumentedDeclaration {
@override
String name;

Expand Down Expand Up @@ -500,6 +501,8 @@ class NamespaceDeclaration extends NestableDeclaration
@override
ExtensionType emit([covariant DeclarationOptions? options]) {
options?.static = true;

final (doc, annotations) = generateFromDocumentation(documentation);
// static props and vars
final methods = <Method>[];
final fields = <Field>[];
Expand Down Expand Up @@ -683,7 +686,8 @@ class InterfaceDeclaration extends TypeDeclaration {
super.operators,
super.constructors,
this.assertRepType = false,
this.objectLiteralConstructor = false})
this.objectLiteralConstructor = false,
super.documentation})
: _id = id;

@override
Expand Down Expand Up @@ -905,6 +909,7 @@ class ConstructorDeclaration implements MemberDeclaration {

final String? dartName;

@override
Documentation? documentation;

ConstructorDeclaration(
Expand Down
4 changes: 0 additions & 4 deletions web_generator/lib/src/interop_gen/sub_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,6 @@ TypeHierarchy getTypeHierarchy(Type type) {
hierarchy.nodes.add(getTypeHierarchy(
BuiltinType.primitiveType(PrimitiveType.object)));
} else {
print((decl.name, decl.extendedTypes));
for (final t in decl.extendedTypes) {
hierarchy.nodes.add(getTypeHierarchy(t));
}
Expand Down Expand Up @@ -354,12 +353,9 @@ Type getLowestCommonAncestorOfTypes(List<Type> types,
// Calculate the intersection of all type hierarchies
final typeMaps = types.map(getTypeHierarchy);
final parentHierarchy = typeMaps.map((map) => map.expand());
print(parentHierarchy);
final commonTypes =
parentHierarchy.reduce((val, element) => val.intersection(element));

print(commonTypes);

final topoList = topologicalList(typeMaps.toList());
for (final level in topoList) {
final typesAtLevel = commonTypes.intersection(level);
Expand Down
29 changes: 22 additions & 7 deletions web_generator/lib/src/interop_gen/transform.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,36 @@ class TransformResult {
return l;
}));
}
var parentCaseIgnore = false;
var anonymousIgnore = false;
var tupleDecl = false;
var longDocs = false;

for (final value in declMap.values) {
if (value is TupleDeclaration) tupleDecl = true;
if (value.id.name.contains('Anonymous')) anonymousIgnore = true;
if (value case NestableDeclaration(parent: final _?)) {
parentCaseIgnore = true;
}
if (value case DocumentedDeclaration(documentation: final docs?)
when const LineSplitter()
.convert(docs.docs)
.any((d) => d.length >= 50)) {
longDocs = true;
}
}
l
..ignoreForFile.addAll({
'constant_identifier_names',
'non_constant_identifier_names',
if (declMap.values
.any((d) => d is NestableDeclaration && d.parent != null))
'camel_case_types',
if (declMap.values.any((v) => v.id.name.contains('Anonymous'))) ...[
if (parentCaseIgnore) 'camel_case_types',
if (anonymousIgnore) ...[
'camel_case_types',
'library_private_types_in_public_api',
'unnecessary_parenthesis'
],
if (declMap.values.whereType<TupleDeclaration>().isNotEmpty) ...[
'unnecessary_parenthesis'
]
if (tupleDecl) 'unnecessary_parenthesis',
if (longDocs) 'lines_longer_than_80_chars',
})
..body.addAll(specs);
});
Expand Down
22 changes: 16 additions & 6 deletions web_generator/lib/src/interop_gen/transform/transformer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,9 @@ class Transformer {
: _transformType(property.type!)),
static: isStatic,
readonly: isReadonly,
isNullable: property.questionToken != null);
isNullable: property.questionToken != null,
documentation: _parseAndTransformDocumentation(property));

if (parent != null) propertyDeclaration.parent = parent;
return propertyDeclaration;
}
Expand Down Expand Up @@ -596,7 +598,9 @@ class Transformer {
? _transformType(method.type!)
: BuiltinType.anyType),
isNullable: (method.kind == TSSyntaxKind.MethodSignature) &&
(method as TSMethodSignature).questionToken != null);
(method as TSMethodSignature).questionToken != null,
documentation: _parseAndTransformDocumentation(method));

if (parent != null) methodDeclaration.parent = parent;
return methodDeclaration;
}
Expand Down Expand Up @@ -662,7 +666,9 @@ class Transformer {
returnType: methodType ??
(callSignature.type != null
? _transformType(callSignature.type!)
: BuiltinType.anyType));
: BuiltinType.anyType),
documentation: _parseAndTransformDocumentation(callSignature));

if (parent != null) methodDeclaration.parent = parent;
return methodDeclaration;
}
Expand Down Expand Up @@ -761,7 +767,9 @@ class Transformer {
returnType: methodType ??
(getter.type != null
? _transformType(getter.type!)
: BuiltinType.anyType));
: BuiltinType.anyType),
documentation: _parseAndTransformDocumentation(getter));

if (parent != null) methodDeclaration.parent = parent;
return methodDeclaration;
}
Expand Down Expand Up @@ -804,7 +812,9 @@ class Transformer {
typeParams?.map(_transformTypeParamDeclaration).toList() ?? [],
returnType: setter.type != null
? _transformType(setter.type!)
: BuiltinType.anyType);
: BuiltinType.anyType,
documentation: _parseAndTransformDocumentation(setter));

if (parent != null) methodDeclaration.parent = parent;
return methodDeclaration;
}
Expand Down Expand Up @@ -1951,7 +1961,7 @@ class Transformer {
final decls = nodeMap.findByName(part.text);
if (decls.isNotEmpty) {
final firstNode = decls.first;
return firstNode.dartName ?? firstNode.name ?? firstNode.id.name;
return firstNode.dartName ?? (firstNode as Declaration).name;
} else {
return part.text;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// ignore_for_file: constant_identifier_names, non_constant_identifier_names
// ignore_for_file: constant_identifier_names, lines_longer_than_80_chars
// ignore_for_file: non_constant_identifier_names

// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:js_interop' as _i1;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// ignore_for_file: camel_case_types, constant_identifier_names
// ignore_for_file: library_private_types_in_public_api
// ignore_for_file: non_constant_identifier_names, unnecessary_parenthesis
// ignore_for_file: lines_longer_than_80_chars, non_constant_identifier_names
// ignore_for_file: unnecessary_parenthesis

// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:js_interop' as _i1;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// ignore_for_file: constant_identifier_names, non_constant_identifier_names
// ignore_for_file: constant_identifier_names, lines_longer_than_80_chars
// ignore_for_file: non_constant_identifier_names

// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:js_interop' as _i1;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// ignore_for_file: camel_case_types, constant_identifier_names
// ignore_for_file: library_private_types_in_public_api
// ignore_for_file: non_constant_identifier_names, unnecessary_parenthesis
// ignore_for_file: lines_longer_than_80_chars, non_constant_identifier_names
// ignore_for_file: unnecessary_parenthesis

// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:js_interop' as _i1;
Expand All @@ -21,6 +22,7 @@ extension type Comparator<T extends _i1.JSAny?>._(_i1.JSObject _)

/// Represents a basic logger interface with optional flush capability.
extension type ILogger._(_i1.JSObject _) implements _i1.JSObject {
/// Logging level. Defaults to "info" if unspecified.
external AnonymousUnion_1584724? level;

/// Name of the logger (e.g., subsystem or module).
Expand Down
14 changes: 3 additions & 11 deletions web_generator/test/integration/interop_gen/typealias_expected.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:js_interop' as _i1;

import '_tuples.dart' as _i2;

typedef Shape2D = String;
typedef PrismFromShape2D<S extends _i1.JSString> = _i1.JSArray<S>;
@_i1.JS()
Expand All @@ -18,17 +20,7 @@ external PromisedArray<_i1.JSString, _i1.JSArray<_i1.JSString>> fetchNames();
typedef IsActive = bool;
@_i1.JS()
external String isUserActive(IsActive status);
extension type JSTuple2<A extends _i1.JSAny?, B extends _i1.JSAny?>._(
_i1.JSArray<_i1.JSAny?> _) implements _i1.JSArray<_i1.JSAny?> {
A get $1 => (_[0] as A);

B get $2 => (_[1] as B);

set $1(A newValue) => _[0] = newValue;

set $2(B newValue) => _[1] = newValue;
}
typedef NameAndAge = JSTuple2<_i1.JSString, _i1.JSNumber>;
typedef NameAndAge = _i2.JSTuple2<_i1.JSString, _i1.JSNumber>;
typedef Username = String;
typedef Age = double;
typedef Tags = _i1.JSArray<_i1.JSString>;
Expand Down
Loading