fix(napi-derive): fix union type generation for ts function notation (#1439)
* fix(backend): fix union type generation for ts function notation * chore: update snapshot * fix: naming
This commit is contained in:
parent
c61b20234e
commit
78b6e1574a
6 changed files with 139 additions and 103 deletions
|
@ -56,40 +56,40 @@ napi_ast_impl! {
|
||||||
(Const, NapiConst),
|
(Const, NapiConst),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) static PRIMITIVE_TYPES: &[(&str, &str)] = &[
|
pub(crate) static PRIMITIVE_TYPES: &[(&str, (&str, bool, bool))] = &[
|
||||||
("JsUndefined", "undefined"),
|
("JsUndefined", ("undefined", false, false)),
|
||||||
("()", "undefined"),
|
("()", ("undefined", false, false)),
|
||||||
("Undefined", "undefined"),
|
("Undefined", ("undefined", false, false)),
|
||||||
("JsNumber", "number"),
|
("JsNumber", ("number", false, false)),
|
||||||
("i8", "number"),
|
("i8", ("number", false, false)),
|
||||||
("i16", "number"),
|
("i16", ("number", false, false)),
|
||||||
("i32", "number"),
|
("i32", ("number", false, false)),
|
||||||
("i64", "number"),
|
("i64", ("number", false, false)),
|
||||||
("f32", "number"),
|
("f32", ("number", false, false)),
|
||||||
("f64", "number"),
|
("f64", ("number", false, false)),
|
||||||
("u8", "number"),
|
("u8", ("number", false, false)),
|
||||||
("u16", "number"),
|
("u16", ("number", false, false)),
|
||||||
("u32", "number"),
|
("u32", ("number", false, false)),
|
||||||
("u64", "bigint"),
|
("u64", ("bigint", false, false)),
|
||||||
("i64n", "bigint"),
|
("i64n", ("bigint", false, false)),
|
||||||
("u128", "bigint"),
|
("u128", ("bigint", false, false)),
|
||||||
("i128", "bigint"),
|
("i128", ("bigint", false, false)),
|
||||||
("usize", "bigint"),
|
("usize", ("bigint", false, false)),
|
||||||
("isize", "bigint"),
|
("isize", ("bigint", false, false)),
|
||||||
("JsBigInt", "bigint"),
|
("JsBigInt", ("bigint", false, false)),
|
||||||
("BigInt", "bigint"),
|
("BigInt", ("bigint", false, false)),
|
||||||
("JsBoolean", "boolean"),
|
("JsBoolean", ("boolean", false, false)),
|
||||||
("bool", "boolean"),
|
("bool", ("boolean", false, false)),
|
||||||
("JsString", "string"),
|
("JsString", ("string", false, false)),
|
||||||
("String", "string"),
|
("String", ("string", false, false)),
|
||||||
("str", "string"),
|
("str", ("string", false, false)),
|
||||||
("Latin1String", "string"),
|
("Latin1String", ("string", false, false)),
|
||||||
("Utf16String", "string"),
|
("Utf16String", ("string", false, false)),
|
||||||
("char", "string"),
|
("char", ("string", false, false)),
|
||||||
("Null", "null"),
|
("Null", ("null", false, false)),
|
||||||
("JsNull", "null"),
|
("JsNull", ("null", false, false)),
|
||||||
("null", "null"),
|
("null", ("null", false, false)),
|
||||||
("Symbol", "symbol"),
|
("Symbol", ("symbol", false, false)),
|
||||||
("JsSymbol", "symbol"),
|
("JsSymbol", ("symbol", false, false)),
|
||||||
("JsFunction", "(...args: any[]) => any"),
|
("JsFunction", ("(...args: any[]) => any", true, false)),
|
||||||
];
|
];
|
||||||
|
|
|
@ -118,74 +118,75 @@ pub trait ToTypeDef {
|
||||||
fn to_type_def(&self) -> Option<TypeDef>;
|
fn to_type_def(&self) -> Option<TypeDef>;
|
||||||
}
|
}
|
||||||
|
|
||||||
static KNOWN_TYPES: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
|
/// Mapping from `rust_type` to (`ts_type`, `is_ts_function_type_notation`, `is_ts_union_type`)
|
||||||
|
static KNOWN_TYPES: Lazy<HashMap<&'static str, (&'static str, bool, bool)>> = Lazy::new(|| {
|
||||||
let mut map = HashMap::default();
|
let mut map = HashMap::default();
|
||||||
map.extend(crate::PRIMITIVE_TYPES.iter().cloned());
|
map.extend(crate::PRIMITIVE_TYPES.iter().cloned());
|
||||||
map.extend([
|
map.extend([
|
||||||
("JsObject", "object"),
|
("JsObject", ("object", false, false)),
|
||||||
("Object", "object"),
|
("Object", ("object", false, false)),
|
||||||
("Array", "unknown[]"),
|
("Array", ("unknown[]", false, false)),
|
||||||
("Value", "any"),
|
("Value", ("any", false, false)),
|
||||||
("Map", "Record<string, any>"),
|
("Map", ("Record<string, any>", false, false)),
|
||||||
("HashMap", "Record<{}, {}>"),
|
("HashMap", ("Record<{}, {}>", false, false)),
|
||||||
("ArrayBuffer", "ArrayBuffer"),
|
("ArrayBuffer", ("ArrayBuffer", false, false)),
|
||||||
("Int8Array", "Int8Array"),
|
("Int8Array", ("Int8Array", false, false)),
|
||||||
("Uint8Array", "Uint8Array"),
|
("Uint8Array", ("Uint8Array", false, false)),
|
||||||
("Uint8ClampedArray", "Uint8ClampedArray"),
|
("Uint8ClampedArray", ("Uint8ClampedArray", false, false)),
|
||||||
("Int16Array", "Int16Array"),
|
("Int16Array", ("Int16Array", false, false)),
|
||||||
("Uint16Array", "Uint16Array"),
|
("Uint16Array", ("Uint16Array", false, false)),
|
||||||
("Int32Array", "Int32Array"),
|
("Int32Array", ("Int32Array", false, false)),
|
||||||
("Uint32Array", "Uint32Array"),
|
("Uint32Array", ("Uint32Array", false, false)),
|
||||||
("Float32Array", "Float32Array"),
|
("Float32Array", ("Float32Array", false, false)),
|
||||||
("Float64Array", "Float64Array"),
|
("Float64Array", ("Float64Array", false, false)),
|
||||||
("BigInt64Array", "BigInt64Array"),
|
("BigInt64Array", ("BigInt64Array", false, false)),
|
||||||
("BigUint64Array", "BigUint64Array"),
|
("BigUint64Array", ("BigUint64Array", false, false)),
|
||||||
("DataView", "DataView"),
|
("DataView", ("DataView", false, false)),
|
||||||
("DateTime", "Date"),
|
("DateTime", ("Date", false, false)),
|
||||||
("Date", "Date"),
|
("Date", ("Date", false, false)),
|
||||||
("JsDate", "Date"),
|
("JsDate", ("Date", false, false)),
|
||||||
("JsBuffer", "Buffer"),
|
("JsBuffer", ("Buffer", false, false)),
|
||||||
("Buffer", "Buffer"),
|
("Buffer", ("Buffer", false, false)),
|
||||||
("Vec", "Array<{}>"),
|
("Vec", ("Array<{}>", false, false)),
|
||||||
("Result", "Error | {}"),
|
("Result", ("Error | {}", false, true)),
|
||||||
("Error", "Error"),
|
("Error", ("Error", false, false)),
|
||||||
("JsError", "Error"),
|
("JsError", ("Error", false, false)),
|
||||||
("JsTypeError", "TypeError"),
|
("JsTypeError", ("TypeError", false, false)),
|
||||||
("JsRangeError", "RangeError"),
|
("JsRangeError", ("RangeError", false, false)),
|
||||||
("ClassInstance", "{}"),
|
("ClassInstance", ("{}", false, false)),
|
||||||
("Either", "{} | {}"),
|
("Either", ("{} | {}", false, true)),
|
||||||
("Either3", "{} | {} | {}"),
|
("Either3", ("{} | {} | {}", false, true)),
|
||||||
("Either4", "{} | {} | {} | {}"),
|
("Either4", ("{} | {} | {} | {}", false, true)),
|
||||||
("Either5", "{} | {} | {} | {} | {}"),
|
("Either5", ("{} | {} | {} | {} | {}", false, true)),
|
||||||
("Either6", "{} | {} | {} | {} | {} | {}"),
|
("Either6", ("{} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("Either7", "{} | {} | {} | {} | {} | {} | {}"),
|
("Either7", ("{} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("Either8", "{} | {} | {} | {} | {} | {} | {} | {}"),
|
("Either8", ("{} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("Either9", "{} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
("Either9", ("{} | {} | {} | {} | {} | {} | {} | {} | {}",false, true)),
|
||||||
("Either10", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
("Either10", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("Either11", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
("Either11", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("Either12", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
("Either12", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("Either13", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
("Either13", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("Either14", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
("Either14", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("Either15", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
("Either15", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("Either16", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
("Either16", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("Either17", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
("Either17", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("Either18", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
("Either18", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("Either19", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
("Either19", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("Either20", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
("Either20", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("Either21", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
("Either21", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("Either22", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
("Either22", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("Either23", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
("Either23", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("Either24", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
("Either24", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("Either25", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
("Either25", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("Either26", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
("Either26", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||||
("external", "object"),
|
("external", ("object", false, false)),
|
||||||
("AbortSignal", "AbortSignal"),
|
("AbortSignal", ("AbortSignal", false, false)),
|
||||||
("JsGlobal", "typeof global"),
|
("JsGlobal", ("typeof global", false, false)),
|
||||||
("External", "ExternalObject<{}>"),
|
("External", ("ExternalObject<{}>", false, false)),
|
||||||
("unknown", "unknown"),
|
("unknown", ("unknown", false, false)),
|
||||||
("Unknown", "unknown"),
|
("Unknown", ("unknown", false, false)),
|
||||||
("JsUnknown", "unknown"),
|
("JsUnknown", ("unknown", false, false)),
|
||||||
("This", "this")
|
("This", ("this", false, false))
|
||||||
]);
|
]);
|
||||||
|
|
||||||
map
|
map
|
||||||
|
@ -209,6 +210,30 @@ fn fill_ty(template: &str, args: Vec<String>) -> String {
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_ts_union_type(rust_ty: &str) -> bool {
|
||||||
|
KNOWN_TYPES
|
||||||
|
.get(rust_ty)
|
||||||
|
.map(|&(_, _, is_union_type)| is_union_type)
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_ts_function_type_notation(ty: &Type) -> bool {
|
||||||
|
match ty {
|
||||||
|
Type::Path(syn::TypePath { qself: None, path }) => {
|
||||||
|
if let Some(syn::PathSegment { ident, .. }) = path.segments.last() {
|
||||||
|
let rust_ty = ident.to_string();
|
||||||
|
return KNOWN_TYPES
|
||||||
|
.get(&*rust_ty)
|
||||||
|
.map(|&(_, is_ts_fn, _)| is_ts_fn)
|
||||||
|
.unwrap_or(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ty_to_ts_type(ty: &Type, is_return_ty: bool, is_struct_field: bool) -> (String, bool) {
|
pub fn ty_to_ts_type(ty: &Type, is_return_ty: bool, is_struct_field: bool) -> (String, bool) {
|
||||||
match ty {
|
match ty {
|
||||||
Type::Reference(r) => ty_to_ts_type(&r.elem, is_return_ty, is_struct_field),
|
Type::Reference(r) => ty_to_ts_type(&r.elem, is_return_ty, is_struct_field),
|
||||||
|
@ -235,13 +260,19 @@ pub fn ty_to_ts_type(ty: &Type, is_return_ty: bool, is_struct_field: bool) -> (S
|
||||||
|
|
||||||
if let Some(syn::PathSegment { ident, arguments }) = path.segments.last() {
|
if let Some(syn::PathSegment { ident, arguments }) = path.segments.last() {
|
||||||
let rust_ty = ident.to_string();
|
let rust_ty = ident.to_string();
|
||||||
|
let is_ts_union_type = is_ts_union_type(&rust_ty);
|
||||||
let args = if let syn::PathArguments::AngleBracketed(arguments) = arguments {
|
let args = if let syn::PathArguments::AngleBracketed(arguments) = arguments {
|
||||||
arguments
|
arguments
|
||||||
.args
|
.args
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|arg| match arg {
|
.filter_map(|arg| match arg {
|
||||||
syn::GenericArgument::Type(generic_ty) => {
|
syn::GenericArgument::Type(generic_ty) => {
|
||||||
Some(ty_to_ts_type(generic_ty, false, false))
|
Some(ty_to_ts_type(generic_ty, false, false)).map(|(mut ty, is_struct_field)| {
|
||||||
|
if is_ts_union_type && is_ts_function_type_notation(generic_ty) {
|
||||||
|
ty = format!("({})", ty);
|
||||||
|
}
|
||||||
|
(ty, is_struct_field)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
|
@ -289,7 +320,7 @@ pub fn ty_to_ts_type(ty: &Type, is_return_ty: bool, is_struct_field: bool) -> (S
|
||||||
Some((rust_ty, false))
|
Some((rust_ty, false))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if let Some(&known_ty) = KNOWN_TYPES.get(rust_ty.as_str()) {
|
} else if let Some(&(known_ty, _, _)) = KNOWN_TYPES.get(rust_ty.as_str()) {
|
||||||
if known_ty.contains("{}") {
|
if known_ty.contains("{}") {
|
||||||
ts_ty = Some((
|
ts_ty = Some((
|
||||||
fill_ty(known_ty, args.into_iter().map(|(arg, _)| arg).collect()),
|
fill_ty(known_ty, args.into_iter().map(|(arg, _)| arg).collect()),
|
||||||
|
|
|
@ -79,6 +79,7 @@ Generated by [AVA](https://avajs.dev).
|
||||||
baz: number␊
|
baz: number␊
|
||||||
}␊
|
}␊
|
||||||
export function eitherFromObjects(input: A | B | C): string␊
|
export function eitherFromObjects(input: A | B | C): string␊
|
||||||
|
export function eitherBoolOrFunction(input: boolean | ((...args: any[]) => any)): void␊
|
||||||
/** default enum values are continuos i32s start from 0 */␊
|
/** default enum values are continuos i32s start from 0 */␊
|
||||||
export const enum Kind {␊
|
export const enum Kind {␊
|
||||||
/** Barks */␊
|
/** Barks */␊
|
||||||
|
|
Binary file not shown.
1
examples/napi/index.d.ts
vendored
1
examples/napi/index.d.ts
vendored
|
@ -69,6 +69,7 @@ export interface C {
|
||||||
baz: number
|
baz: number
|
||||||
}
|
}
|
||||||
export function eitherFromObjects(input: A | B | C): string
|
export function eitherFromObjects(input: A | B | C): string
|
||||||
|
export function eitherBoolOrFunction(input: boolean | ((...args: any[]) => any)): void
|
||||||
/** default enum values are continuos i32s start from 0 */
|
/** default enum values are continuos i32s start from 0 */
|
||||||
export const enum Kind {
|
export const enum Kind {
|
||||||
/** Barks */
|
/** Barks */
|
||||||
|
|
|
@ -127,3 +127,6 @@ pub fn either_from_objects(input: Either3<A, B, C>) -> String {
|
||||||
Either3::C(_) => "C".to_owned(),
|
Either3::C(_) => "C".to_owned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[napi]
|
||||||
|
pub fn either_bool_or_function(_input: Either<bool, JsFunction>) {}
|
||||||
|
|
Loading…
Reference in a new issue