From df9dc91562e648b21eaa97bae9f2c9354ed1b976 Mon Sep 17 00:00:00 2001 From: h-a-n-a Date: Sun, 19 Dec 2021 17:47:02 +0800 Subject: [PATCH] feat(napi): add ts typegen skip --- cli/src/build.ts | 5 +++- crates/backend/src/ast.rs | 4 ++++ crates/backend/src/lib.rs | 2 +- crates/backend/src/typegen.rs | 2 +- crates/backend/src/typegen/const.rs | 11 ++++++--- crates/backend/src/typegen/enum.rs | 11 ++++++--- crates/backend/src/typegen/fn.rs | 10 +++++--- crates/backend/src/typegen/struct.rs | 35 ++++++++++++++++++---------- crates/macro/src/lib.rs | 20 +++++++++------- crates/macro/src/parser/attrs.rs | 2 +- crates/macro/src/parser/mod.rs | 19 +++++++++++---- 11 files changed, 84 insertions(+), 37 deletions(-) diff --git a/cli/src/build.ts b/cli/src/build.ts index 4dcc2360..919fd400 100644 --- a/cli/src/build.ts +++ b/cli/src/build.ts @@ -361,7 +361,10 @@ async function processIntermediateTypeFile( return idents } - const dtsHeader = `/* eslint-disable */ + const dtsHeader = `/* tslint:disable */ +/* eslint-disable */ + +/* auto-generated by Napi-rs */ export class ExternalObject { readonly '': { diff --git a/crates/backend/src/ast.rs b/crates/backend/src/ast.rs index 7f3cd6bf..687f5748 100644 --- a/crates/backend/src/ast.rs +++ b/crates/backend/src/ast.rs @@ -18,6 +18,7 @@ pub struct NapiFn { pub js_mod: Option, pub ts_args_type: Option, pub ts_return_type: Option, + pub skip_typescript: bool, pub comments: Vec, } @@ -77,6 +78,7 @@ pub struct NapiStructField { pub getter: bool, pub setter: bool, pub comments: Vec, + pub skip_typescript: bool, } #[derive(Debug, Clone)] @@ -96,6 +98,7 @@ pub struct NapiEnum { pub variants: Vec, pub js_mod: Option, pub comments: Vec, + pub skip_typescript: bool, } #[derive(Debug, Clone)] @@ -113,6 +116,7 @@ pub struct NapiConst { pub value: Expr, pub js_mod: Option, pub comments: Vec, + pub skip_typescript: bool, } #[derive(Debug, Clone)] diff --git a/crates/backend/src/lib.rs b/crates/backend/src/lib.rs index ad779c8d..4e4c0217 100644 --- a/crates/backend/src/lib.rs +++ b/crates/backend/src/lib.rs @@ -38,7 +38,7 @@ macro_rules! napi_ast_impl { #[cfg(feature = "type-def")] impl ToTypeDef for Napi { - fn to_type_def(&self) -> TypeDef { + fn to_type_def(&self) -> Option { match self.item { $( NapiItem::$v(ref ast) => ast.to_type_def() ),* } diff --git a/crates/backend/src/typegen.rs b/crates/backend/src/typegen.rs index 527e46d7..58f9caa5 100644 --- a/crates/backend/src/typegen.rs +++ b/crates/backend/src/typegen.rs @@ -90,7 +90,7 @@ impl ToString for TypeDef { } pub trait ToTypeDef { - fn to_type_def(&self) -> TypeDef; + fn to_type_def(&self) -> Option; } static KNOWN_TYPES: Lazy> = Lazy::new(|| { diff --git a/crates/backend/src/typegen/const.rs b/crates/backend/src/typegen/const.rs index 29343d3a..1ae5b808 100644 --- a/crates/backend/src/typegen/const.rs +++ b/crates/backend/src/typegen/const.rs @@ -3,9 +3,14 @@ use super::{ToTypeDef, TypeDef}; use crate::{js_doc_from_comments, ty_to_ts_type, typegen::add_alias, NapiConst}; impl ToTypeDef for NapiConst { - fn to_type_def(&self) -> TypeDef { + fn to_type_def(&self) -> Option { + if self.skip_typescript { + return None; + } + add_alias(self.name.to_string(), self.js_name.to_string()); - TypeDef { + + Some(TypeDef { kind: "const".to_owned(), name: self.js_name.to_owned(), def: format!( @@ -15,6 +20,6 @@ impl ToTypeDef for NapiConst { ), js_mod: self.js_mod.to_owned(), js_doc: js_doc_from_comments(&self.comments), - } + }) } } diff --git a/crates/backend/src/typegen/enum.rs b/crates/backend/src/typegen/enum.rs index eeabbe53..c22666f8 100644 --- a/crates/backend/src/typegen/enum.rs +++ b/crates/backend/src/typegen/enum.rs @@ -2,15 +2,20 @@ use super::{add_alias, ToTypeDef, TypeDef}; use crate::{js_doc_from_comments, NapiEnum}; impl ToTypeDef for NapiEnum { - fn to_type_def(&self) -> TypeDef { + fn to_type_def(&self) -> Option { + if self.skip_typescript { + return None; + } + add_alias(self.name.to_string(), self.js_name.to_string()); - TypeDef { + + Some(TypeDef { kind: "enum".to_owned(), name: self.js_name.to_owned(), def: self.gen_ts_variants(), js_doc: js_doc_from_comments(&self.comments), js_mod: self.js_mod.to_owned(), - } + }) } } diff --git a/crates/backend/src/typegen/fn.rs b/crates/backend/src/typegen/fn.rs index 0199823d..45297793 100644 --- a/crates/backend/src/typegen/fn.rs +++ b/crates/backend/src/typegen/fn.rs @@ -6,7 +6,11 @@ use super::{ty_to_ts_type, ToTypeDef, TypeDef}; use crate::{js_doc_from_comments, CallbackArg, FnKind, NapiFn}; impl ToTypeDef for NapiFn { - fn to_type_def(&self) -> TypeDef { + fn to_type_def(&self) -> Option { + if self.skip_typescript { + return None; + } + let def = format!( r#"{prefix} {name}({args}){ret}"#, prefix = self.gen_ts_func_prefix(), @@ -22,13 +26,13 @@ impl ToTypeDef for NapiFn { .unwrap_or_else(|| self.gen_ts_func_ret()), ); - TypeDef { + Some(TypeDef { kind: "fn".to_owned(), name: self.js_name.clone(), def, js_mod: self.js_mod.to_owned(), js_doc: js_doc_from_comments(&self.comments), - } + }) } } diff --git a/crates/backend/src/typegen/struct.rs b/crates/backend/src/typegen/struct.rs index c592bf8b..7f039052 100644 --- a/crates/backend/src/typegen/struct.rs +++ b/crates/backend/src/typegen/struct.rs @@ -10,13 +10,14 @@ thread_local! { } impl ToTypeDef for NapiStruct { - fn to_type_def(&self) -> TypeDef { + fn to_type_def(&self) -> Option { CLASS_STRUCTS.with(|c| { c.borrow_mut() .insert(self.name.to_string(), self.js_name.clone()); }); add_alias(self.name.to_string(), self.js_name.to_string()); - TypeDef { + + Some(TypeDef { kind: String::from(if self.kind == NapiStructKind::Object { "interface" } else { @@ -26,36 +27,42 @@ impl ToTypeDef for NapiStruct { def: self.gen_ts_class(), js_mod: self.js_mod.to_owned(), js_doc: js_doc_from_comments(&self.comments), - } + }) } } impl ToTypeDef for NapiImpl { - fn to_type_def(&self) -> TypeDef { + fn to_type_def(&self) -> Option { if let Some(output_type) = &self.task_output_type { TASK_STRUCTS.with(|t| { t.borrow_mut() .insert(self.js_name.clone(), ty_to_ts_type(output_type, false).0); }); } - TypeDef { + + Some(TypeDef { kind: "impl".to_owned(), name: self.js_name.to_owned(), def: self .items .iter() - .map(|f| { - format!( - "{}{}", - js_doc_from_comments(&f.comments), - f.to_type_def().def - ) + .filter_map(|f| { + if f.skip_typescript { + None + } else { + Some(format!( + "{}{}", + js_doc_from_comments(&f.comments), + f.to_type_def() + .map_or(String::default(), |type_def| type_def.def) + )) + } }) .collect::>() .join("\\n"), js_mod: self.js_mod.to_owned(), js_doc: "".to_string(), - } + }) } } @@ -69,6 +76,10 @@ impl NapiStruct { .map(|f| { let mut field_str = String::from(""); + if f.skip_typescript { + return field_str; + } + if !f.comments.is_empty() { field_str.push_str(&js_doc_from_comments(&f.comments)) } diff --git a/crates/macro/src/lib.rs b/crates/macro/src/lib.rs index 19a99aa8..21b8241b 100644 --- a/crates/macro/src/lib.rs +++ b/crates/macro/src/lib.rs @@ -141,15 +141,19 @@ fn expand(attr: TokenStream, input: TokenStream) -> BindgenResult { } #[cfg(all(feature = "type-def", not(feature = "noop")))] -fn output_type_def(type_def_file: String, type_def: TypeDef) -> IOResult<()> { - let file = fs::OpenOptions::new() - .append(true) - .create(true) - .open(type_def_file)?; +fn output_type_def(type_def_file: String, type_def: Option) -> IOResult<()> { + if type_def.is_some() { + let file = fs::OpenOptions::new() + .append(true) + .create(true) + .open(type_def_file)?; - let mut writer = BufWriter::::new(file); - writer.write_all(type_def.to_string().as_bytes())?; - writer.write_all("\n".as_bytes()) + let mut writer = BufWriter::::new(file); + writer.write_all(type_def.unwrap().to_string().as_bytes())?; + writer.write_all("\n".as_bytes()) + } else { + IOResult::Ok(()) + } } #[cfg(feature = "compat-mode")] diff --git a/crates/macro/src/parser/attrs.rs b/crates/macro/src/parser/attrs.rs index 111135d5..afd00aa6 100644 --- a/crates/macro/src/parser/attrs.rs +++ b/crates/macro/src/parser/attrs.rs @@ -58,7 +58,7 @@ macro_rules! attrgen { // impl later // (inspectable, Inspectable(Span)), // (typescript_custom_section, TypescriptCustomSection(Span)), - // (skip_typescript, SkipTypescript(Span)), + (skip_typescript, SkipTypescript(Span)), // (getter_with_clone, GetterWithClone(Span)), // For testing purposes only. diff --git a/crates/macro/src/parser/mod.rs b/crates/macro/src/parser/mod.rs index 737068bf..91cb7ef7 100644 --- a/crates/macro/src/parser/mod.rs +++ b/crates/macro/src/parser/mod.rs @@ -578,6 +578,7 @@ fn napi_fn_from_decl( 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()), + skip_typescript: opts.skip_typescript().is_some(), } }) } @@ -606,10 +607,13 @@ impl ParseNapi for syn::ItemFn { } impl ParseNapi for syn::ItemStruct { fn parse_napi(&mut self, tokens: &mut TokenStream, opts: BindgenAttrs) -> BindgenResult { - 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.skip_typescript().is_some() + { bail_span!( self, - "#[napi] can't be applied to a struct with #[napi(ts_args_type)] or #[napi(ts_return_type)]" + "#[napi] can't be applied to a struct with #[napi(ts_args_type)] or #[napi(ts_return_type)] or #[napi(skip_typescript)]" ); } let napi = self.convert_to_ast(opts); @@ -620,10 +624,13 @@ impl ParseNapi for syn::ItemStruct { } impl ParseNapi for syn::ItemImpl { fn parse_napi(&mut self, tokens: &mut TokenStream, opts: BindgenAttrs) -> BindgenResult { - 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.skip_typescript().is_some() + { bail_span!( self, - "#[napi] can't be applied to impl with #[napi(ts_args_type)] or #[napi(ts_return_type)]" + "#[napi] can't be applied to impl with #[napi(ts_args_type)] or #[napi(ts_return_type)] or #[napi(skip_typescript)]" ); } // #[napi] macro will be remove from impl items after converted to ast @@ -751,6 +758,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(); fields.push(NapiStructField { name, @@ -759,6 +767,7 @@ impl ConvertToAST for syn::ItemStruct { getter: !ignored, setter: !(ignored || readonly), comments: extract_doc_comments(&field.attrs), + skip_typescript, }) } @@ -943,6 +952,7 @@ impl ConvertToAST for syn::ItemEnum { variants, js_mod: opts.namespace().map(|(m, _)| m.to_owned()), comments: extract_doc_comments(&self.attrs), + skip_typescript: opts.skip_typescript().is_some(), }), }) } @@ -961,6 +971,7 @@ impl ConvertToAST for syn::ItemConst { value: *self.expr.clone(), js_mod: opts.namespace().map(|(m, _)| m.to_owned()), comments: extract_doc_comments(&self.attrs), + skip_typescript: opts.skip_typescript().is_some(), }), }), _ => bail_span!(self, "only public const allowed"),