feat(napi-derive): add ts_type attribute to override typtescript type for fields in structs

This commit is contained in:
Jose L 2022-01-23 02:45:41 -08:00 committed by GitHub
parent 5b9e33cff7
commit 40651714c9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 40 additions and 6 deletions

View file

@ -79,6 +79,7 @@ pub struct NapiStructField {
pub setter: bool,
pub comments: Vec<String>,
pub skip_typescript: bool,
pub ts_type: Option<String>,
}
#[derive(Debug, Clone)]

View file

@ -89,7 +89,10 @@ impl NapiStruct {
if !f.setter {
field_str.push_str("readonly ")
}
let (arg, is_optional) = ty_to_ts_type(&f.ty, false);
let arg = f.ts_type.as_ref().map(|ty| ty.to_string()).unwrap_or(arg);
let sep = if is_optional { "?" } else { "" };
let arg = format!("{}{}: {}", &f.js_name, sep, arg);
if self.kind == NapiStructKind::Constructor {

View file

@ -54,6 +54,7 @@ macro_rules! attrgen {
(namespace, Namespace(Span, String, Span)),
(ts_args_type, TsArgsType(Span, String, Span)),
(ts_return_type, TsReturnType(Span, String, Span)),
(ts_type, TsType(Span, String, Span)),
// impl later
// (inspectable, Inspectable(Span)),

View file

@ -602,6 +602,12 @@ impl ParseNapi for syn::Item {
impl ParseNapi for syn::ItemFn {
fn parse_napi(&mut self, tokens: &mut TokenStream, opts: BindgenAttrs) -> BindgenResult<Napi> {
if opts.ts_type().is_some() {
bail_span!(
self,
"#[napi] can't be applied to a function with #[napi(ts_type)]"
);
}
self.to_tokens(tokens);
self.convert_to_ast(opts)
}
@ -611,10 +617,11 @@ impl ParseNapi for syn::ItemStruct {
if opts.ts_args_type().is_some()
|| opts.ts_return_type().is_some()
|| opts.skip_typescript().is_some()
|| opts.ts_type().is_some()
{
bail_span!(
self,
"#[napi] can't be applied to a struct with #[napi(ts_args_type)] or #[napi(ts_return_type)] or #[napi(skip_typescript)]"
"#[napi] can't be applied to a struct with #[napi(ts_args_type)], #[napi(ts_return_type)], #[napi(skip_typescript)] or #[napi(ts_type)]"
);
}
let napi = self.convert_to_ast(opts);
@ -628,10 +635,11 @@ impl ParseNapi for syn::ItemImpl {
if opts.ts_args_type().is_some()
|| opts.ts_return_type().is_some()
|| opts.skip_typescript().is_some()
|| opts.ts_type().is_some()
{
bail_span!(
self,
"#[napi] can't be applied to impl with #[napi(ts_args_type)] or #[napi(ts_return_type)] or #[napi(skip_typescript)]"
"#[napi] can't be applied to impl with #[napi(ts_args_type)], #[napi(ts_return_type)], #[napi(skip_typescript)] or #[napi(ts_type)]"
);
}
// #[napi] macro will be remove from impl items after converted to ast
@ -643,10 +651,11 @@ impl ParseNapi for syn::ItemImpl {
}
impl ParseNapi for syn::ItemEnum {
fn parse_napi(&mut self, tokens: &mut TokenStream, opts: BindgenAttrs) -> BindgenResult<Napi> {
if opts.ts_args_type().is_some() || opts.ts_return_type().is_some() {
if opts.ts_args_type().is_some() || opts.ts_return_type().is_some() || opts.ts_type().is_some()
{
bail_span!(
self,
"#[napi] can't be applied to a enum with #[napi(ts_args_type)] or #[napi(ts_return_type)]"
"#[napi] can't be applied to a enum with #[napi(ts_args_type)], #[napi(ts_return_type)] or #[napi(ts_type)]"
);
}
let napi = self.convert_to_ast(opts);
@ -657,10 +666,11 @@ impl ParseNapi for syn::ItemEnum {
}
impl ParseNapi for syn::ItemConst {
fn parse_napi(&mut self, tokens: &mut TokenStream, opts: BindgenAttrs) -> BindgenResult<Napi> {
if opts.ts_args_type().is_some() || opts.ts_return_type().is_some() {
if opts.ts_args_type().is_some() || opts.ts_return_type().is_some() || opts.ts_type().is_some()
{
bail_span!(
self,
"#[napi] can't be applied to a const with #[napi(ts_args_type)] or #[napi(ts_return_type)]"
"#[napi] can't be applied to a const with #[napi(ts_args_type)], #[napi(ts_return_type)] or #[napi(ts_type)]"
);
}
let napi = self.convert_to_ast(opts);
@ -760,6 +770,7 @@ impl ConvertToAST for syn::ItemStruct {
let ignored = field_opts.skip().is_some();
let readonly = field_opts.readonly().is_some();
let skip_typescript = field_opts.skip_typescript().is_some();
let ts_type = field_opts.ts_type().map(|e| e.0.to_string());
fields.push(NapiStructField {
name,
@ -769,6 +780,7 @@ impl ConvertToAST for syn::ItemStruct {
setter: !(ignored || readonly),
comments: extract_doc_comments(&field.attrs),
skip_typescript,
ts_type,
})
}

View file

@ -102,6 +102,10 @@ Generated by [AVA](https://avajs.dev).
}␊
export function receiveStrictObject(strictObject: StrictObject): void␊
export function getStrFromObject(): void␊
export interface TsTypeChanged {␊
typeOverride: object␊
typeOverrideOptional?: object␊
}␊
export function asyncPlus100(p: Promise<number>): Promise<number>
/** This is an interface for package.json */␊
export interface PackageJson {␊

View file

@ -92,6 +92,10 @@ export interface StrictObject {
}
export function receiveStrictObject(strictObject: StrictObject): void
export function getStrFromObject(): void
export interface TsTypeChanged {
typeOverride: object
typeOverrideOptional?: object
}
export function asyncPlus100(p: Promise<number>): Promise<number>
/** This is an interface for package.json */
export interface PackageJson {

View file

@ -76,3 +76,12 @@ pub fn get_str_from_object(env: Env) {
obj.set("name", "value").unwrap();
assert_eq!(obj.get("name").unwrap(), Some("value"));
}
#[napi(object)]
pub struct TsTypeChanged {
#[napi(ts_type = "object")]
pub type_override: String,
#[napi(ts_type = "object")]
pub type_override_optional: Option<String>,
}