Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 10 additions & 2 deletions web_generator/lib/src/ast/base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:code_builder/code_builder.dart';

import '../interop_gen/namer.dart';
import 'documentation.dart';
import 'helpers.dart';
import 'types.dart';

class GlobalOptions {
Expand Down Expand Up @@ -130,7 +131,7 @@ abstract class DeclarationType<T extends Declaration> extends Type {
String get declarationName;
}

class ParameterDeclaration {
class ParameterDeclaration implements DocumentedDeclaration {
final String name;

final bool optional;
Expand All @@ -139,15 +140,22 @@ class ParameterDeclaration {

final bool variadic;

@override
Documentation? documentation;

ParameterDeclaration(
{required this.name,
this.optional = false,
required this.type,
this.variadic = false});
this.variadic = false,
this.documentation});

Parameter emit([DeclarationOptions? options]) {
final (doc, annotations) = generateFromDocumentation(documentation);
return Parameter((p) => p
..name = name
..annotations.addAll(annotations)
..docs.addAll(doc)
..type = type.emit(TypeOptions(nullable: optional)));
}
}
Expand Down
114 changes: 98 additions & 16 deletions web_generator/lib/src/interop_gen/transform/transformer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ class Transformer {
id: id,
scope: scope,
static: isStatic,
parameters: params.map((t) {
parameters: params.mapIndexed((index, t) {
ReferredType? paramType;
final paramRawType = t.type;
if (paramRawType case final ty? when ts.isTypeReferenceNode(ty)) {
Expand All @@ -612,7 +612,7 @@ class Transformer {
paramType = parent?.asReferredType(
parent.typeParameters.map((t) => GenericType(name: t.name)));
}
return _transformParameter(t, paramType);
return _transformParameter(t, type: paramType, index: index);
}).toList(),
typeParameters:
typeParams?.map(_transformTypeParamDeclaration).toList() ?? [],
Expand Down Expand Up @@ -654,7 +654,9 @@ class Transformer {
id: id,
dartName: dartName.trim().isEmpty ? null : dartName.trim(),
name: name,
parameters: params.map(_transformParameter).toList(),
parameters: params
.mapIndexed((index, p) => _transformParameter(p, index: index))
.toList(),
scope: scope,
documentation: _parseAndTransformDocumentation(constructor));
}
Expand Down Expand Up @@ -689,7 +691,9 @@ class Transformer {
name: 'call',
dartName: dartName,
id: id,
parameters: params.map(_transformParameter).toList(),
parameters: params
.mapIndexed((index, p) => _transformParameter(p, index: index))
.toList(),
typeParameters:
typeParams?.map(_transformTypeParamDeclaration).toList() ?? [],
returnType: methodType ??
Expand Down Expand Up @@ -730,7 +734,9 @@ class Transformer {
}

final doc = _parseAndTransformDocumentation(indexSignature);
final transformedParameters = params.map(_transformParameter).toList();
final transformedParameters = params
.mapIndexed((index, p) => _transformParameter(p, index: index))
.toList();
final type = indexerType ?? _transformType(indexSignature.type);
final transformedTypeParams =
typeParams?.map(_transformTypeParamDeclaration).toList() ?? [];
Expand Down Expand Up @@ -800,7 +806,9 @@ class Transformer {
id: id,
kind: MethodKind.getter,
scope: scope,
parameters: params.map(_transformParameter).toList(),
parameters: params
.mapIndexed((index, p) => _transformParameter(p, index: index))
.toList(),
typeParameters:
typeParams?.map(_transformTypeParamDeclaration).toList() ?? [],
returnType: methodType ??
Expand Down Expand Up @@ -830,7 +838,7 @@ class Transformer {
dartName: dartName,
kind: MethodKind.setter,
id: id,
parameters: params.map((t) {
parameters: params.mapIndexed((index, t) {
ReferredType? paramType;
final paramRawType = t.type;
if (paramRawType case final ty? when ts.isTypeReferenceNode(ty)) {
Expand All @@ -845,7 +853,7 @@ class Transformer {
paramType = parent?.asReferredType(
parent.typeParameters.map((t) => GenericType(name: t.name)));
}
return _transformParameter(t, paramType);
return _transformParameter(t, type: paramType, index: index);
}).toList(),
scope: scope,
typeParameters:
Expand Down Expand Up @@ -880,7 +888,9 @@ class Transformer {
id: id,
dartName: uniqueName,
exported: isExported,
parameters: params.map(_transformParameter).toList(),
parameters: params
.mapIndexed((index, p) => _transformParameter(p, index: index))
.toList(),
typeParameters:
typeParams?.map(_transformTypeParamDeclaration).toList() ?? [],
returnType: function.type != null
Expand Down Expand Up @@ -1053,7 +1063,7 @@ class Transformer {
}

ParameterDeclaration _transformParameter(TSParameterDeclaration parameter,
[Type? type]) {
{Type? type, int? index}) {
type ??= parameter.type != null
? _transformType(parameter.type!, parameter: true)
: BuiltinType.anyType;
Expand All @@ -1068,11 +1078,82 @@ class Transformer {
type: type,
variadic: isVariadic,
optional: isOptional);
case TSSyntaxKind.ObjectBindingPattern ||
TSSyntaxKind.ArrayBindingPattern:
Iterable<TSDeclaration> expandBindingPatterns(
@UnionOf(
[TSIdentifier, TSObjectBindingPattern, TSArrayBindingPattern])
TSNode name) {
switch (name.kind) {
case TSSyntaxKind.Identifier:
return [name as TSIdentifier];
case TSSyntaxKind.ObjectBindingPattern ||
TSSyntaxKind.ArrayBindingPattern:
return (name as TSBindingPattern)
.elements
.toDart
.map((e) => e.name == null
? <TSDeclaration>[]
: expandBindingPatterns(e.name!))
.flattenedToList;
default:
return [];
}
}
final name = parameter.name as TSBindingPattern;
// just return the object
final elements = expandBindingPatterns(name);
final elementText = name.getText();
final documentation = isVariadic
? null
: Documentation(docs: 'Parameter is of the form: $elementText');

final rearWord =
parameter.name.kind == TSSyntaxKind.ObjectBindingPattern
? 'obj'
: 'arr';

if (elements.isEmpty) {
return ParameterDeclaration(
name: 'unknown$rearWord',
type: type,
variadic: isVariadic,
optional: isOptional,
documentation: documentation);
} else if (elements.singleOrNull case final singleEl?) {
final singleElName = singleEl.kind == TSSyntaxKind.Identifier
? (singleEl as TSIdentifier).text
: (singleEl as TSNamedDeclaration).name?.text ?? 'unknown';
return ParameterDeclaration(
name: '$singleElName$rearWord',
type: type,
variadic: isVariadic,
optional: isOptional,
documentation: documentation);
} else {
final hash = AnonymousHasher.hashTuple(elements
.map((e) => e.kind == TSSyntaxKind.Identifier
? (e as TSIdentifier).text
: (e as TSNamedDeclaration).name?.text ?? '')
.toList());
return ParameterDeclaration(
name: '$rearWord${hash.substring(0, 3)}',
type: type,
variadic: isVariadic,
optional: isOptional,
documentation: documentation);
}
default:
// TODO: Support Destructured Object Parameters
// and Destructured Array Parameters
throw Exception(
'Unsupported Parameter Name kind ${parameter.name.kind}');
final elementText = parameter.name.getText();
final documentation = isVariadic
? null
: Documentation(docs: 'Parameter is of the form: $elementText');
return ParameterDeclaration(
name: 'unknown${index ?? ""}',
type: type,
variadic: isVariadic,
optional: isOptional,
documentation: documentation);
}
}

Expand Down Expand Up @@ -1247,8 +1328,9 @@ class Transformer {
case TSSyntaxKind.ConstructorType || TSSyntaxKind.FunctionType:
final funType = type as TSFunctionOrConstructorTypeNodeBase;

final parameters =
funType.parameters.toDart.map(_transformParameter).toList();
final parameters = funType.parameters.toDart
.mapIndexed((index, p) => _transformParameter(p, index: index))
.toList();

final typeParameters = funType.typeParameters?.toDart
.map(_transformTypeParamDeclaration)
Expand Down
20 changes: 20 additions & 0 deletions web_generator/lib/src/js/typescript.types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,26 @@ extension type TSParameterDeclaration._(JSObject _) implements TSDeclaration {
external TSNode? get dotDotDotToken;
}

@JS('BindingPattern')
extension type TSBindingPattern<E extends TSNamedDeclaration>._(JSObject _)
implements TSNode {
external TSNodeArray<E> get elements;
}

@JS('ObjectBindingPattern')
extension type TSObjectBindingPattern._(JSObject _)
implements TSBindingPattern<TSBindingElement> {}

@JS('ArrayBindingPattern')
extension type TSArrayBindingPattern._(JSObject _)
implements TSBindingPattern<TSBindingElement> {}

/** We do not need much from this other than its name */
@JS('BindingElement')
extension type TSBindingElement._(JSObject _) implements TSNamedDeclaration {
external TSNode get name;
}

@JS('TypeParameterDeclaration')
extension type TSTypeParameterDeclaration._(JSObject _)
implements TSDeclaration {
Expand Down
43 changes: 38 additions & 5 deletions web_generator/test/integration/interop_gen/ts_typing_expected.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,29 @@ external ProductOrrandomNonTypedProduct objectAsProduct(
external _i1.JSArray<AnonymousType_9143117<T>>
indexedArray<T extends _i1.JSAny?>(_i1.JSArray<T> arr);
@_i1.JS()
external double firstTwoNumbers(

/// Parameter is of the form: [a, b]
_i1.JSArray<_i1.JSNumber> arr117);
@_i1.JS()
external double pointlessArrayFunction(

/// Parameter is of the form: [{}]
_i1.JSArray<AnonymousType_4207514> unknownarr);
@_i1.JS()
external String productInfo(
/// Parameter is of the form: { name, id }
Product obj157, [
AnonymousType_9686701? options,
]);
@_i1.JS()
external String shortendedProductCartInfo(
_i1.JSArray<Product> arr903, [
_i1.JSArray<Product> arr9032,
_i1.JSArray<Product> arr9033,
_i1.JSArray<Product> arr9034,
]);
@_i1.JS()
external String get myString;
@_i1.JS()
external _i1.JSArray<_i1.JSNumber> get myNumberArray;
Expand Down Expand Up @@ -163,6 +186,21 @@ extension type AnonymousType_9143117<T extends _i1.JSAny?>._(_i1.JSObject _)

external T value;
}
extension type AnonymousType_4207514._(_i1.JSObject _) implements _i1.JSObject {
external AnonymousType_4207514({double a});

external double a;
}
extension type AnonymousType_9686701._(_i1.JSObject _) implements _i1.JSObject {
external AnonymousType_9686701({
bool search,
bool showId,
});

external bool? search;

external bool? showId;
}
extension type MyEnum_EnumType._(_i1.JSObject _) implements _i1.JSObject {
static const MyEnum A = MyEnum._(0);

Expand Down Expand Up @@ -376,11 +414,6 @@ extension type AnonymousIntersection_1711585._(_i1.JSAny _)
AnonymousUnion_5737239 get asAnonymousUnion_5737239 =>
(_ as AnonymousUnion_5737239);
}
extension type AnonymousType_4207514._(_i1.JSObject _) implements _i1.JSObject {
external AnonymousType_4207514({double a});

external double a;
}
extension type AnonymousType_1806035._(_i1.JSObject _) implements _i1.JSObject {
external AnonymousType_1806035({String b});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,7 @@ export declare const myThirdIntersection: string & {
export declare const myTypeGymnastic:
({ a: number } | { b: string }) &
({ c: boolean } | ({ d: bigint } & { e: symbol }));
export declare function firstTwoNumbers([a, b]: number[]): number;
export declare function pointlessArrayFunction([{}]: {a: number}[]): number;
export declare function productInfo({ name, id }: Product, options?: { search?: boolean, showId?: boolean }): string;
export declare function shortendedProductCartInfo(...[{ name: prod1, id: prod1ID }, { name: prod2, id: prod2ID }]: Product[]): string;