feat(napi-derive): support renmae function args and return type

This commit is contained in:
LongYinan 2021-11-26 17:26:14 +08:00
parent e6f341f632
commit e2e3ef95f8
No known key found for this signature in database
GPG key ID: C3666B7FC82ADAD7
11 changed files with 54 additions and 5 deletions

View file

@ -16,6 +16,8 @@ pub struct NapiFn {
pub parent: Option<Ident>, pub parent: Option<Ident>,
pub strict: bool, pub strict: bool,
pub js_mod: Option<String>, pub js_mod: Option<String>,
pub ts_args_type: Option<String>,
pub ts_return_type: Option<String>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View file

@ -67,6 +67,7 @@ static KNOWN_TYPES: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
("char", "string"), ("char", "string"),
("JsObject", "object"), ("JsObject", "object"),
("Object", "object"), ("Object", "object"),
("Array", "unknown[]"),
("Value", "any"), ("Value", "any"),
("Map", "Record<string, any>"), ("Map", "Record<string, any>"),
("HashMap", "Record<{}, {}>"), ("HashMap", "Record<{}, {}>"),

View file

@ -11,8 +11,15 @@ impl ToTypeDef for NapiFn {
r#"{prefix} {name}({args}){ret}"#, r#"{prefix} {name}({args}){ret}"#,
prefix = self.gen_ts_func_prefix(), prefix = self.gen_ts_func_prefix(),
name = &self.js_name, name = &self.js_name,
args = self.gen_ts_func_args(), args = self
ret = self.gen_ts_func_ret(), .ts_args_type
.clone()
.unwrap_or_else(|| self.gen_ts_func_args()),
ret = self
.ts_return_type
.clone()
.map(|t| format!(": {}", t))
.unwrap_or_else(|| self.gen_ts_func_ret()),
); );
TypeDef { TypeDef {

View file

@ -53,12 +53,13 @@ macro_rules! attrgen {
(strict, Strict(Span)), (strict, Strict(Span)),
(object, Object(Span)), (object, Object(Span)),
(namespace, Namespace(Span, String, Span)), (namespace, Namespace(Span, String, Span)),
(ts_args_type, TsArgsType(Span, String, Span)),
(ts_return_type, TsReturnType(Span, String, Span)),
// impl later // impl later
// (inspectable, Inspectable(Span)), // (inspectable, Inspectable(Span)),
// (typescript_custom_section, TypescriptCustomSection(Span)), // (typescript_custom_section, TypescriptCustomSection(Span)),
// (skip_typescript, SkipTypescript(Span)), // (skip_typescript, SkipTypescript(Span)),
// (typescript_type, TypeScriptType(Span, String, Span)),
// (getter_with_clone, GetterWithClone(Span)), // (getter_with_clone, GetterWithClone(Span)),
// For testing purposes only. // For testing purposes only.

View file

@ -575,6 +575,8 @@ fn napi_fn_from_decl(
attrs, attrs,
strict: opts.strict().is_some(), strict: opts.strict().is_some(),
js_mod: opts.namespace().map(|(m, _)| m.to_owned()), js_mod: opts.namespace().map(|(m, _)| m.to_owned()),
ts_args_type: opts.ts_args_type().map(|(m, _)| m.to_owned()),
ts_return_type: opts.ts_return_type().map(|(m, _)| m.to_owned()),
} }
}) })
} }
@ -603,6 +605,12 @@ impl ParseNapi for syn::ItemFn {
} }
impl ParseNapi for syn::ItemStruct { impl ParseNapi for syn::ItemStruct {
fn parse_napi(&mut self, tokens: &mut TokenStream, opts: BindgenAttrs) -> BindgenResult<Napi> { 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() {
bail_span!(
self,
"#[napi] can't be applied to a struct with #[napi(ts_args_type)] or #[napi(ts_return_type)]"
);
}
let napi = self.convert_to_ast(opts); let napi = self.convert_to_ast(opts);
self.to_tokens(tokens); self.to_tokens(tokens);
@ -611,6 +619,12 @@ impl ParseNapi for syn::ItemStruct {
} }
impl ParseNapi for syn::ItemImpl { impl ParseNapi for syn::ItemImpl {
fn parse_napi(&mut self, tokens: &mut TokenStream, opts: BindgenAttrs) -> BindgenResult<Napi> { 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() {
bail_span!(
self,
"#[napi] can't be applied to impl with #[napi(ts_args_type)] or #[napi(ts_return_type)]"
);
}
// #[napi] macro will be remove from impl items after converted to ast // #[napi] macro will be remove from impl items after converted to ast
let napi = self.convert_to_ast(opts); let napi = self.convert_to_ast(opts);
self.to_tokens(tokens); self.to_tokens(tokens);
@ -618,18 +632,28 @@ impl ParseNapi for syn::ItemImpl {
napi napi
} }
} }
impl ParseNapi for syn::ItemEnum { impl ParseNapi for syn::ItemEnum {
fn parse_napi(&mut self, tokens: &mut TokenStream, opts: BindgenAttrs) -> BindgenResult<Napi> { 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() {
bail_span!(
self,
"#[napi] can't be applied to a enum with #[napi(ts_args_type)] or #[napi(ts_return_type)]"
);
}
let napi = self.convert_to_ast(opts); let napi = self.convert_to_ast(opts);
self.to_tokens(tokens); self.to_tokens(tokens);
napi napi
} }
} }
impl ParseNapi for syn::ItemConst { impl ParseNapi for syn::ItemConst {
fn parse_napi(&mut self, tokens: &mut TokenStream, opts: BindgenAttrs) -> BindgenResult<Napi> { 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() {
bail_span!(
self,
"#[napi] can't be applied to a const with #[napi(ts_args_type)] or #[napi(ts_return_type)]"
);
}
let napi = self.convert_to_ast(opts); let napi = self.convert_to_ast(opts);
self.to_tokens(tokens); self.to_tokens(tokens);
napi napi

View file

@ -42,6 +42,7 @@ Generated by [AVA](https://avajs.dev).
export function createExternalString(content: string): ExternalObject<string> export function createExternalString(content: string): ExternalObject<string>
export function getExternal(external: ExternalObject<number>): number␊ export function getExternal(external: ExternalObject<number>): number␊
export function mutateExternal(external: ExternalObject<number>, newVal: number): void␊ export function mutateExternal(external: ExternalObject<number>, newVal: number): void␊
export function tsRename(a: { foo: number }): string[]␊
export function xxh64Alias(input: Buffer): BigInt␊ export function xxh64Alias(input: Buffer): BigInt␊
export function mapOption(val?: number | undefined | null): number | undefined | null␊ export function mapOption(val?: number | undefined | null): number | undefined | null␊
export function add(a: number, b: number): number␊ export function add(a: number, b: number): number␊

View file

@ -55,6 +55,7 @@ import {
xxh2, xxh2,
xxh3, xxh3,
xxh64Alias, xxh64Alias,
tsRename,
} from '../' } from '../'
test('export const', (t) => { test('export const', (t) => {
@ -194,6 +195,10 @@ test('Result', (t) => {
t.throws(() => throwError(), null, 'Manual Error') t.throws(() => throwError(), null, 'Manual Error')
}) })
test('function ts type override', (t) => {
t.deepEqual(tsRename({ foo: 1, bar: 2, baz: 2 }), ['foo', 'bar', 'baz'])
})
test('serde-json', (t) => { test('serde-json', (t) => {
const packageJson = readPackageJson() const packageJson = readPackageJson()
t.is(packageJson.name, 'napi-rs') t.is(packageJson.name, 'napi-rs')

View file

@ -32,6 +32,7 @@ export function createExternal(size: number): ExternalObject<number>
export function createExternalString(content: string): ExternalObject<string> export function createExternalString(content: string): ExternalObject<string>
export function getExternal(external: ExternalObject<number>): number export function getExternal(external: ExternalObject<number>): number
export function mutateExternal(external: ExternalObject<number>, newVal: number): void export function mutateExternal(external: ExternalObject<number>, newVal: number): void
export function tsRename(a: { foo: number }): string[]
export function xxh64Alias(input: Buffer): BigInt export function xxh64Alias(input: Buffer): BigInt
export function mapOption(val?: number | undefined | null): number | undefined | null export function mapOption(val?: number | undefined | null): number | undefined | null
export function add(a: number, b: number): number export function add(a: number, b: number): number

View file

@ -0,0 +1,6 @@
use napi::bindgen_prelude::{Object, Result};
#[napi(ts_args_type = "a: { foo: number }", ts_return_type = "string[]")]
fn ts_rename(a: Object) -> Result<Object> {
a.get_property_names()
}

View file

@ -16,6 +16,7 @@ mod either;
mod r#enum; mod r#enum;
mod error; mod error;
mod external; mod external;
mod fn_ts_override;
mod js_mod; mod js_mod;
mod nullable; mod nullable;
mod number; mod number;