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
2 changes: 2 additions & 0 deletions web_generator/lib/src/ast/helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ Type desugarTypeAliases(Type t) {
if (t case final ReferredType ref
when ref.declaration is TypeAliasDeclaration) {
return desugarTypeAliases((ref.declaration as TypeAliasDeclaration).type);
} else if (t case ReferredDeclarationType(type: final actualType)) {
return desugarTypeAliases(actualType);
}
return t;
}
Expand Down
76 changes: 38 additions & 38 deletions web_generator/lib/src/ast/types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -673,48 +673,48 @@ sealed class _UnionOrIntersectionDeclaration extends NamedDeclaration
dartTypeName ?? typeName,
_ => t.dartName ?? t.id.name
};
final Expression body;
if (desugarTypeAliases(t) == repType) {
body = refer('_');
} else if (jsTypeAlt.id == t.id) {
body = refer('_').asA(type);
} else {
body = switch (t) {
BuiltinType(name: final n) when n == 'int' => refer('_')
.asA(jsTypeAlt.emit(options?.toTypeOptions()))
.property('toDartInt'),
BuiltinType(name: final n) when n == 'double' || n == 'num' =>
refer('_')
.asA(jsTypeAlt.emit(options?.toTypeOptions()))
.property('toDartDouble'),
BuiltinType() => refer('_')
.asA(jsTypeAlt.emit(options?.toTypeOptions()))
.property('toDart'),
ReferredType(
declaration: final decl,
name: final n,
url: final url
)
when decl is EnumDeclaration =>
refer(n, url).property('_').call([
refer('_')
.asA(jsTypeAlt.emit(options?.toTypeOptions()))
.property(decl.baseType is NamedType
? switch ((decl.baseType as NamedType).name) {
'int' => 'toDartInt',
'num' || 'double' => 'toDartDouble',
_ => 'toDart'
}
: 'toDart')
]),
_ => refer('_').asA(jsTypeAlt.emit(options?.toTypeOptions()))
};
}
m
..type = MethodType.getter
..name = 'as${uppercaseFirstLetter(word)}'
..returns = type
..body = jsTypeAlt.id == t.id
? refer('_').asA(type).code
: switch (t) {
BuiltinType(name: final n) when n == 'int' => refer('_')
.asA(jsTypeAlt.emit(options?.toTypeOptions()))
.property('toDartInt')
.code,
BuiltinType(name: final n)
when n == 'double' || n == 'num' =>
refer('_')
.asA(jsTypeAlt.emit(options?.toTypeOptions()))
.property('toDartDouble')
.code,
BuiltinType() => refer('_')
.asA(jsTypeAlt.emit(options?.toTypeOptions()))
.property('toDart')
.code,
ReferredType(
declaration: final decl,
name: final n,
url: final url
)
when decl is EnumDeclaration =>
refer(n, url).property('_').call([
refer('_')
.asA(jsTypeAlt.emit(options?.toTypeOptions()))
.property(decl.baseType is NamedType
? switch ((decl.baseType as NamedType).name) {
'int' => 'toDartInt',
'num' || 'double' => 'toDartDouble',
_ => 'toDart'
}
: 'toDart')
]).code,
_ => refer('_')
.asA(jsTypeAlt.emit(options?.toTypeOptions()))
.code
};
..body = body.code;
});
})));
}
Expand Down
36 changes: 36 additions & 0 deletions web_generator/lib/src/interop_gen/transform/transformer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1113,6 +1113,42 @@ class Transformer {

return _getTypeFromTypeNode(refType,
typeArg: typeArg, isNullable: isNullable ?? false);
case TSSyntaxKind.TypePredicate:
// in the future, we can be smarter about this
// but for now, we just have this as a boolean
return BuiltinType.primitiveType(PrimitiveType.boolean,
isNullable: isNullable);
case TSSyntaxKind.ConditionalType:
final conditionalType = type as TSConditionalTypeNode;
final trueType = _transformType(conditionalType.trueType);
final falseType = _transformType(conditionalType.falseType);

final types = [trueType, falseType]
.sorted((a, b) => a.id.toString().compareTo(b.id.toString()));

final expectedID = ID(type: 'type', name: types.join('|'));

if (typeMap.containsKey(expectedID.toString())) {
return (typeMap[expectedID.toString()] as UnionType)
..isNullable = (isNullable ?? false);
}

final trueTypeName = trueType is NamedType
? trueType.name
: trueType.dartName ?? trueType.id.name;

final falseTypeName = falseType is NamedType
? falseType.name
: falseType.dartName ?? falseType.id.name;
final conditionalName = '${trueTypeName}Or$falseTypeName';

final un = UnionType(types: types, name: conditionalName);
final unType = typeMap.putIfAbsent(expectedID.toString(), () {
namer.markUsed(conditionalName);
return un;
});

return unType..isNullable = (isNullable ?? false);
case TSSyntaxKind.TypeLiteral:
// type literal
final typeLiteralNode = type as TSTypeLiteralNode;
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 @@ -100,6 +100,8 @@ extension type const TSSyntaxKind._(num _) {
static const TSSyntaxKind FunctionType = TSSyntaxKind._(184);
static const TSSyntaxKind ConstructorType = TSSyntaxKind._(185);
static const TSSyntaxKind TypeOperator = TSSyntaxKind._(198);
static const TSSyntaxKind TypePredicate = TSSyntaxKind._(182);
static const TSSyntaxKind ConditionalType = TSSyntaxKind._(194);

// Other
static const TSSyntaxKind Identifier = TSSyntaxKind._(80);
Expand Down Expand Up @@ -202,6 +204,24 @@ extension type TSParenthesizedTypeNode._(JSObject _) implements TSTypeNode {
external TSTypeNode get type;
}

@JS('TypePredicateNode')
extension type TSTypePredicateNode._(JSObject _) implements TSTypeNode {
@redeclare
TSSyntaxKind get kind => TSSyntaxKind.TypePredicate;
external TSIdentifier get parameterName;
external TSTypeNode? get type;
}

@JS('ConditionalTypeNode')
extension type TSConditionalTypeNode._(JSObject _) implements TSTypeNode {
@redeclare
TSSyntaxKind get kind => TSSyntaxKind.ConditionalType;
external TSTypeNode get checkType;
external TSTypeNode get extendsType;
external TSTypeNode get trueType;
external TSTypeNode get falseType;
}

@JS('TupleTypeNode')
extension type TSTupleTypeNode._(JSObject _) implements TSTypeNode {
external TSNodeArray<TSTypeNode> get elements;
Expand Down
45 changes: 29 additions & 16 deletions web_generator/test/integration/interop_gen/ts_typing_expected.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ external String myFunction(String param);
@_i1.JS()
external String myEnclosingFunction(_i1.JSFunction func);
@_i1.JS()
external bool objectIsProduct(_i1.JSObject obj);
@_i1.JS()
external AnonymousType_2194029 get randomNonTypedProduct;
@_i1.JS()
external ProductOrrandomNonTypedProduct objectAsProduct(
_i1.JSObject obj,
bool structured,
);
@_i1.JS()
external _i1.JSArray<AnonymousType_9143117<T>>
indexedArray<T extends _i1.JSAny?>(_i1.JSArray<T> arr);
@_i1.JS()
Expand Down Expand Up @@ -84,8 +93,6 @@ external _i2.JSTuple4<_i1.JSString, _i1.JSNumber, _i1.JSBoolean, _i1.JSSymbol>
@_i1.JS()
external AnonymousUnion_7503220 get eightOrSixteen;
@_i1.JS()
external AnonymousType_2194029 get randomNonTypedProduct;
@_i1.JS()
external AnonymousType_1358595 get config;
extension type MyProduct._(_i1.JSObject _) implements Product {
external MyProduct(
Expand Down Expand Up @@ -125,6 +132,26 @@ external _i1.JSAny? get someIntersection;
external AnonymousIntersection_4895242 get myThirdIntersection;
@_i1.JS()
external AnonymousIntersection_1711585 get myTypeGymnastic;
extension type AnonymousType_2194029._(_i1.JSObject _) implements _i1.JSObject {
external AnonymousType_2194029({
double id,
String name,
double price,
});

external double id;

external String name;

external double price;
}
typedef Product = AnonymousType_2194029;
extension type ProductOrrandomNonTypedProduct._(AnonymousType_2194029 _)
implements AnonymousType_2194029 {
Product get asProduct => _;

AnonymousType_2194029 get asRandomNonTypedProduct => _;
}
extension type AnonymousType_9143117<T extends _i1.JSAny?>._(_i1.JSObject _)
implements _i1.JSObject {
external AnonymousType_9143117({
Expand Down Expand Up @@ -210,19 +237,6 @@ extension type AnonymousUnion_7503220._(_i1.JSTypedArray _)

_i1.JSUint16Array get asJSUint16Array => (_ as _i1.JSUint16Array);
}
extension type AnonymousType_2194029._(_i1.JSObject _) implements _i1.JSObject {
external AnonymousType_2194029({
double id,
String name,
double price,
});

external double id;

external String name;

external double price;
}
extension type AnonymousType_1358595._(_i1.JSObject _) implements _i1.JSObject {
external AnonymousType_1358595({
double discountRate,
Expand All @@ -233,7 +247,6 @@ extension type AnonymousType_1358595._(_i1.JSObject _) implements _i1.JSObject {

external double taxRate;
}
typedef Product = AnonymousType_2194029;
extension type AnonymousType_2773310._(_i1.JSObject _) implements _i1.JSObject {
external AnonymousType_2773310({
String id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export declare const myEnumValue2: typeof MyEnum;
export declare function myFunction(param: string): string;
export declare let myFunctionAlias: typeof myFunction;
export declare let myFunctionAlias2: typeof myFunctionAlias;
// export declare let myPreClone: typeof myComposedType;
export declare function myEnclosingFunction(func: typeof myFunction): string;
export declare const myEnclosingFunctionAlias: typeof myEnclosingFunction;
export declare const myComposedType: ComposedType;
Expand Down Expand Up @@ -65,7 +64,9 @@ export declare class MyProduct implements Product {
price: number;
constructor(id: number, name: string, price: number);
}
export function indexedArray<T>(arr: T[]): { id: number, value: T }[];
export declare function objectIsProduct(obj: object): obj is Product;
export declare function objectAsProduct(obj: object, structured: boolean): (typeof structured) extends true ? Product : typeof randomNonTypedProduct;
export declare function indexedArray<T>(arr: T[]): { id: number, value: T }[];
export const responseObject: {
id: string;
value: any;
Expand Down