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),
|
||||
}
|
||||
|
||||
pub(crate) static PRIMITIVE_TYPES: &[(&str, &str)] = &[
|
||||
("JsUndefined", "undefined"),
|
||||
("()", "undefined"),
|
||||
("Undefined", "undefined"),
|
||||
("JsNumber", "number"),
|
||||
("i8", "number"),
|
||||
("i16", "number"),
|
||||
("i32", "number"),
|
||||
("i64", "number"),
|
||||
("f32", "number"),
|
||||
("f64", "number"),
|
||||
("u8", "number"),
|
||||
("u16", "number"),
|
||||
("u32", "number"),
|
||||
("u64", "bigint"),
|
||||
("i64n", "bigint"),
|
||||
("u128", "bigint"),
|
||||
("i128", "bigint"),
|
||||
("usize", "bigint"),
|
||||
("isize", "bigint"),
|
||||
("JsBigInt", "bigint"),
|
||||
("BigInt", "bigint"),
|
||||
("JsBoolean", "boolean"),
|
||||
("bool", "boolean"),
|
||||
("JsString", "string"),
|
||||
("String", "string"),
|
||||
("str", "string"),
|
||||
("Latin1String", "string"),
|
||||
("Utf16String", "string"),
|
||||
("char", "string"),
|
||||
("Null", "null"),
|
||||
("JsNull", "null"),
|
||||
("null", "null"),
|
||||
("Symbol", "symbol"),
|
||||
("JsSymbol", "symbol"),
|
||||
("JsFunction", "(...args: any[]) => any"),
|
||||
pub(crate) static PRIMITIVE_TYPES: &[(&str, (&str, bool, bool))] = &[
|
||||
("JsUndefined", ("undefined", false, false)),
|
||||
("()", ("undefined", false, false)),
|
||||
("Undefined", ("undefined", false, false)),
|
||||
("JsNumber", ("number", false, false)),
|
||||
("i8", ("number", false, false)),
|
||||
("i16", ("number", false, false)),
|
||||
("i32", ("number", false, false)),
|
||||
("i64", ("number", false, false)),
|
||||
("f32", ("number", false, false)),
|
||||
("f64", ("number", false, false)),
|
||||
("u8", ("number", false, false)),
|
||||
("u16", ("number", false, false)),
|
||||
("u32", ("number", false, false)),
|
||||
("u64", ("bigint", false, false)),
|
||||
("i64n", ("bigint", false, false)),
|
||||
("u128", ("bigint", false, false)),
|
||||
("i128", ("bigint", false, false)),
|
||||
("usize", ("bigint", false, false)),
|
||||
("isize", ("bigint", false, false)),
|
||||
("JsBigInt", ("bigint", false, false)),
|
||||
("BigInt", ("bigint", false, false)),
|
||||
("JsBoolean", ("boolean", false, false)),
|
||||
("bool", ("boolean", false, false)),
|
||||
("JsString", ("string", false, false)),
|
||||
("String", ("string", false, false)),
|
||||
("str", ("string", false, false)),
|
||||
("Latin1String", ("string", false, false)),
|
||||
("Utf16String", ("string", false, false)),
|
||||
("char", ("string", false, false)),
|
||||
("Null", ("null", false, false)),
|
||||
("JsNull", ("null", false, false)),
|
||||
("null", ("null", false, false)),
|
||||
("Symbol", ("symbol", false, false)),
|
||||
("JsSymbol", ("symbol", false, false)),
|
||||
("JsFunction", ("(...args: any[]) => any", true, false)),
|
||||
];
|
||||
|
|
|
@ -118,74 +118,75 @@ pub trait ToTypeDef {
|
|||
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();
|
||||
map.extend(crate::PRIMITIVE_TYPES.iter().cloned());
|
||||
map.extend([
|
||||
("JsObject", "object"),
|
||||
("Object", "object"),
|
||||
("Array", "unknown[]"),
|
||||
("Value", "any"),
|
||||
("Map", "Record<string, any>"),
|
||||
("HashMap", "Record<{}, {}>"),
|
||||
("ArrayBuffer", "ArrayBuffer"),
|
||||
("Int8Array", "Int8Array"),
|
||||
("Uint8Array", "Uint8Array"),
|
||||
("Uint8ClampedArray", "Uint8ClampedArray"),
|
||||
("Int16Array", "Int16Array"),
|
||||
("Uint16Array", "Uint16Array"),
|
||||
("Int32Array", "Int32Array"),
|
||||
("Uint32Array", "Uint32Array"),
|
||||
("Float32Array", "Float32Array"),
|
||||
("Float64Array", "Float64Array"),
|
||||
("BigInt64Array", "BigInt64Array"),
|
||||
("BigUint64Array", "BigUint64Array"),
|
||||
("DataView", "DataView"),
|
||||
("DateTime", "Date"),
|
||||
("Date", "Date"),
|
||||
("JsDate", "Date"),
|
||||
("JsBuffer", "Buffer"),
|
||||
("Buffer", "Buffer"),
|
||||
("Vec", "Array<{}>"),
|
||||
("Result", "Error | {}"),
|
||||
("Error", "Error"),
|
||||
("JsError", "Error"),
|
||||
("JsTypeError", "TypeError"),
|
||||
("JsRangeError", "RangeError"),
|
||||
("ClassInstance", "{}"),
|
||||
("Either", "{} | {}"),
|
||||
("Either3", "{} | {} | {}"),
|
||||
("Either4", "{} | {} | {} | {}"),
|
||||
("Either5", "{} | {} | {} | {} | {}"),
|
||||
("Either6", "{} | {} | {} | {} | {} | {}"),
|
||||
("Either7", "{} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either8", "{} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either9", "{} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either10", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either11", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either12", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either13", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either14", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either15", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either16", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either17", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either18", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either19", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either20", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either21", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either22", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either23", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either24", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either25", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either26", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("external", "object"),
|
||||
("AbortSignal", "AbortSignal"),
|
||||
("JsGlobal", "typeof global"),
|
||||
("External", "ExternalObject<{}>"),
|
||||
("unknown", "unknown"),
|
||||
("Unknown", "unknown"),
|
||||
("JsUnknown", "unknown"),
|
||||
("This", "this")
|
||||
("JsObject", ("object", false, false)),
|
||||
("Object", ("object", false, false)),
|
||||
("Array", ("unknown[]", false, false)),
|
||||
("Value", ("any", false, false)),
|
||||
("Map", ("Record<string, any>", false, false)),
|
||||
("HashMap", ("Record<{}, {}>", false, false)),
|
||||
("ArrayBuffer", ("ArrayBuffer", false, false)),
|
||||
("Int8Array", ("Int8Array", false, false)),
|
||||
("Uint8Array", ("Uint8Array", false, false)),
|
||||
("Uint8ClampedArray", ("Uint8ClampedArray", false, false)),
|
||||
("Int16Array", ("Int16Array", false, false)),
|
||||
("Uint16Array", ("Uint16Array", false, false)),
|
||||
("Int32Array", ("Int32Array", false, false)),
|
||||
("Uint32Array", ("Uint32Array", false, false)),
|
||||
("Float32Array", ("Float32Array", false, false)),
|
||||
("Float64Array", ("Float64Array", false, false)),
|
||||
("BigInt64Array", ("BigInt64Array", false, false)),
|
||||
("BigUint64Array", ("BigUint64Array", false, false)),
|
||||
("DataView", ("DataView", false, false)),
|
||||
("DateTime", ("Date", false, false)),
|
||||
("Date", ("Date", false, false)),
|
||||
("JsDate", ("Date", false, false)),
|
||||
("JsBuffer", ("Buffer", false, false)),
|
||||
("Buffer", ("Buffer", false, false)),
|
||||
("Vec", ("Array<{}>", false, false)),
|
||||
("Result", ("Error | {}", false, true)),
|
||||
("Error", ("Error", false, false)),
|
||||
("JsError", ("Error", false, false)),
|
||||
("JsTypeError", ("TypeError", false, false)),
|
||||
("JsRangeError", ("RangeError", false, false)),
|
||||
("ClassInstance", ("{}", false, false)),
|
||||
("Either", ("{} | {}", false, true)),
|
||||
("Either3", ("{} | {} | {}", false, true)),
|
||||
("Either4", ("{} | {} | {} | {}", false, true)),
|
||||
("Either5", ("{} | {} | {} | {} | {}", false, true)),
|
||||
("Either6", ("{} | {} | {} | {} | {} | {}", false, true)),
|
||||
("Either7", ("{} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||
("Either8", ("{} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||
("Either9", ("{} | {} | {} | {} | {} | {} | {} | {} | {}",false, true)),
|
||||
("Either10", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||
("Either11", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||
("Either12", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||
("Either13", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||
("Either14", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||
("Either15", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||
("Either16", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||
("Either17", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||
("Either18", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||
("Either19", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||
("Either20", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||
("Either21", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||
("Either22", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||
("Either23", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||
("Either24", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||
("Either25", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||
("Either26", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
|
||||
("external", ("object", false, false)),
|
||||
("AbortSignal", ("AbortSignal", false, false)),
|
||||
("JsGlobal", ("typeof global", false, false)),
|
||||
("External", ("ExternalObject<{}>", false, false)),
|
||||
("unknown", ("unknown", false, false)),
|
||||
("Unknown", ("unknown", false, false)),
|
||||
("JsUnknown", ("unknown", false, false)),
|
||||
("This", ("this", false, false))
|
||||
]);
|
||||
|
||||
map
|
||||
|
@ -209,6 +210,30 @@ fn fill_ty(template: &str, args: Vec<String>) -> String {
|
|||
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) {
|
||||
match ty {
|
||||
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() {
|
||||
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 {
|
||||
arguments
|
||||
.args
|
||||
.iter()
|
||||
.filter_map(|arg| match arg {
|
||||
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,
|
||||
})
|
||||
|
@ -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))
|
||||
}
|
||||
});
|
||||
} 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("{}") {
|
||||
ts_ty = Some((
|
||||
fill_ty(known_ty, args.into_iter().map(|(arg, _)| arg).collect()),
|
||||
|
|
|
@ -79,6 +79,7 @@ Generated by [AVA](https://avajs.dev).
|
|||
baz: number␊
|
||||
}␊
|
||||
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 */␊
|
||||
export const enum Kind {␊
|
||||
/** 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
|
||||
}
|
||||
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 */
|
||||
export const enum Kind {
|
||||
/** Barks */
|
||||
|
|
|
@ -127,3 +127,6 @@ pub fn either_from_objects(input: Either3<A, B, C>) -> String {
|
|||
Either3::C(_) => "C".to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn either_bool_or_function(_input: Either<bool, JsFunction>) {}
|
||||
|
|
Loading…
Reference in a new issue