From e32c105a26d4426c08facb49d2919e64cf7814af Mon Sep 17 00:00:00 2001 From: liuyi Date: Wed, 13 Dec 2023 12:40:01 +0800 Subject: [PATCH] fix(napi-derive): upgrade syn (#1849) --- crates/backend/Cargo.toml | 2 +- crates/macro/Cargo.toml | 6 +- crates/macro/src/expand/napi.rs | 61 ++--- crates/macro/src/expand/noop.rs | 2 +- crates/macro/src/parser/attrs.rs | 210 ++++++++++++--- crates/macro/src/parser/mod.rs | 248 +++++------------- examples/napi-compat-mode/package.json | 1 + examples/napi/package.json | 1 + .../build_error_tests/ts_arg_type_1.stderr | 4 +- .../build_error_tests/ts_arg_type_2.stderr | 2 +- .../build_error_tests/ts_arg_type_3.stderr | 6 +- .../build_error_tests/ts_arg_type_4.stderr | 2 +- 12 files changed, 284 insertions(+), 261 deletions(-) diff --git a/crates/backend/Cargo.toml b/crates/backend/Cargo.toml index 8572ab56..688a420a 100644 --- a/crates/backend/Cargo.toml +++ b/crates/backend/Cargo.toml @@ -21,7 +21,7 @@ type-def = ["regex", "once_cell", "semver"] convert_case = "0.6" proc-macro2 = "1" quote = "1" -syn = { version = "1.0.61", features = ["fold", "full", "extra-traits"] } +syn = { version = "2", features = ["fold", "full", "extra-traits"] } [dependencies.regex] optional = true diff --git a/crates/macro/Cargo.toml b/crates/macro/Cargo.toml index fcc23ac2..806b44f5 100644 --- a/crates/macro/Cargo.toml +++ b/crates/macro/Cargo.toml @@ -24,9 +24,9 @@ type-def = ["napi-derive-backend/type-def"] [dependencies] convert_case = "0.6" napi-derive-backend = { version = "1.0.56", path = "../backend" } -proc-macro2 = "1.0" -quote = "1.0" -syn = { version = "1.0.61", features = ["fold", "full", "extra-traits"] } +proc-macro2 = "1" +quote = "1" +syn = { version = "2", features = ["fold", "full", "extra-traits"] } cfg-if = "1.0" [lib] diff --git a/crates/macro/src/expand/napi.rs b/crates/macro/src/expand/napi.rs index f9a4b8f4..79657d84 100644 --- a/crates/macro/src/expand/napi.rs +++ b/crates/macro/src/expand/napi.rs @@ -8,7 +8,7 @@ use crate::parser::{attrs::BindgenAttrs, ParseNapi}; #[cfg(feature = "type-def")] use napi_derive_backend::ToTypeDef; use napi_derive_backend::{BindgenResult, Napi, TryToTokens}; -use proc_macro2::{TokenStream, TokenTree}; +use proc_macro2::TokenStream; use quote::ToTokens; use syn::{Attribute, Item}; @@ -66,7 +66,7 @@ pub fn expand(attr: TokenStream, input: TokenStream) -> BindgenResult BindgenResult &mut empty_attrs, }, ) { - let napi = item.parse_napi(&mut tokens, item_opts)?; + let napi = item.parse_napi(&mut tokens, &item_opts)?; + item_opts.check_used()?; napi.try_to_tokens(&mut tokens)?; #[cfg(feature = "type-def")] @@ -96,14 +97,15 @@ pub fn expand(attr: TokenStream, input: TokenStream) -> BindgenResult, ) -> Option { - let napi_attr = attrs.clone(); - let napi_attr = napi_attr + let napi_attr = attrs .iter() .enumerate() - .find(|(_, m)| m.path.segments[0].ident == "napi"); - if let Some((index, napi_attr)) = napi_attr { - let attr_token_stream = napi_attr.tokens.clone(); - let raw_attr_stream = attr_token_stream.to_string(); - let raw_attr_stream = if !raw_attr_stream.is_empty() { - raw_attr_stream - .strip_prefix('(') - .unwrap() - .strip_suffix(')') - .unwrap() - .to_string() - } else { - raw_attr_stream - }; - let raw_attr_token_stream = syn::parse_str::(raw_attr_stream.as_str()).unwrap(); + .find(|(_, m)| m.path().is_ident("napi")); - let new_attr: syn::Attribute = if !raw_attr_stream.is_empty() { - syn::parse_quote!( - #[napi(#raw_attr_token_stream, namespace = #js_namespace)] - ) - } else { - syn::parse_quote!( - #[napi(namespace = #js_namespace)] - ) + if let Some((index, napi_attr)) = napi_attr { + // adds `namespace = #js_namespace` into `#[napi]` attribute + let new_attr = match &napi_attr.meta { + syn::Meta::Path(_) => { + syn::parse_quote!(#[napi(namespace = #js_namespace)]) + } + syn::Meta::List(list) => { + let existing = list.tokens.clone(); + syn::parse_quote!(#[napi(#existing, namespace = #js_namespace)]) + } + syn::Meta::NameValue(name_value) => { + let existing = &name_value.value; + syn::parse_quote!(#[napi(#existing, namespace = #js_namespace)]) + } }; - let struct_opts: BindgenAttrs = - if let Some(TokenTree::Group(g)) = new_attr.tokens.into_iter().next() { - syn::parse2(g.stream()).ok()? - } else { - syn::parse2(quote! {}).ok()? - }; + + let struct_opts = BindgenAttrs::try_from(&new_attr).unwrap(); attrs.remove(index); Some(struct_opts) } else { diff --git a/crates/macro/src/expand/noop.rs b/crates/macro/src/expand/noop.rs index f11d3284..597c032d 100644 --- a/crates/macro/src/expand/noop.rs +++ b/crates/macro/src/expand/noop.rs @@ -24,7 +24,7 @@ fn find_and_remove_napi_attr(attrs: &mut Vec) { let napi_attr = attrs .iter() .enumerate() - .find(|&(_, m)| m.path.segments[0].ident == "napi"); + .find(|&(_, m)| m.path().segments[0].ident == "napi"); let pos = match napi_attr { Some((pos, _raw_attr)) => pos, diff --git a/crates/macro/src/parser/attrs.rs b/crates/macro/src/parser/attrs.rs index 19b4a110..f1e3e11d 100644 --- a/crates/macro/src/parser/attrs.rs +++ b/crates/macro/src/parser/attrs.rs @@ -3,7 +3,12 @@ use std::collections::HashMap; use napi_derive_backend::{bail_span, BindgenResult, Diagnostic}; use proc_macro2::{Delimiter, Ident, Span, TokenTree}; +use quote::ToTokens; +use syn::parse::{Parse, ParseStream}; use syn::spanned::Spanned; +use syn::Attribute; + +use crate::parser::AnyIdent; thread_local! { static ATTRS: AttributeParseState = Default::default(); @@ -23,6 +28,7 @@ struct ParsedStruct { #[derive(Default)] struct AttributeParseState { parsed: Cell, + #[allow(unused)] checks: Cell, } @@ -84,7 +90,8 @@ macro_rules! methods { $(methods!(@method $name, $variant($($contents)*));)* #[cfg(feature = "strict")] - fn check_used(self) -> Result<(), Diagnostic> { + #[allow(unused)] + pub fn check_used(&self) -> Result<(), Diagnostic> { // Account for the fact this method was called ATTRS.with(|state| state.checks.set(state.checks.get() + 1)); @@ -102,7 +109,7 @@ macro_rules! methods { } #[cfg(not(feature = "strict"))] - fn check_used(self) -> Result<(), Diagnostic> { + pub fn check_used(&self) -> Result<(), Diagnostic> { // Account for the fact this method was called ATTRS.with(|state| state.checks.set(state.checks.get() + 1)); Ok(()) @@ -191,43 +198,58 @@ macro_rules! methods { impl BindgenAttrs { /// Find and parse the napi attributes. pub fn find(attrs: &mut Vec) -> Result { - let mut ret = BindgenAttrs::default(); - loop { - let napi_attr = attrs - .iter() - .enumerate() - .find(|&(_, m)| m.path.segments[0].ident == "napi"); + for (index, attr) in attrs.iter().enumerate() { + let attr = BindgenAttrs::try_from(attr)?; + if attr.exists { + attrs.remove(index); - let pos = match napi_attr { - Some((pos, raw_attr)) => { - ret.exists = true; - ret.span = raw_attr.tokens.span(); - pos - } - None => return Ok(ret), - }; - let attr = attrs.remove(pos); - let mut tts = attr.tokens.clone().into_iter(); - let group = match tts.next() { - Some(TokenTree::Group(d)) => d, - Some(_) => bail_span!(attr, "malformed #[napi] attribute"), - None => continue, - }; - if tts.next().is_some() { - bail_span!(attr, "malformed #[napi] attribute"); + return Ok(attr); } - if group.delimiter() != Delimiter::Parenthesis { - bail_span!(attr, "malformed #[napi] attribute"); - } - let mut attrs: BindgenAttrs = syn::parse2(group.stream())?; - ret.attrs.append(&mut attrs.attrs); - attrs.check_used()?; } + + Ok(BindgenAttrs::default()) } attrgen!(methods); } +impl TryFrom<&Attribute> for BindgenAttrs { + type Error = Diagnostic; + + fn try_from(attr: &Attribute) -> Result { + let mut ret = BindgenAttrs { + exists: false, + attrs: vec![], + span: Span::call_site(), + }; + + if attr.path().is_ident("napi") { + ret.exists = true; + ret.span = attr.span(); + + let tts = attr.meta.to_token_stream().into_iter(); + let group = match tts.last() { + // #[napi(xxx)] + // ^^^^^^^^^ + Some(TokenTree::Group(d)) => d, + // #[napi] + // ^^^^ + Some(TokenTree::Ident(_)) => parse_quote!(()), + _ => bail_span!(attr, "invalid #[napi] attribute"), + }; + + if group.delimiter() != Delimiter::Parenthesis { + bail_span!(attr, "malformed #[napi] attribute"); + } + + let mut attrs: BindgenAttrs = syn::parse2(group.stream())?; + ret.attrs.append(&mut attrs.attrs); + } + + Ok(ret) + } +} + impl Default for BindgenAttrs { fn default() -> BindgenAttrs { // Add 1 to the list of parsed attribute sets. We'll use this counter to @@ -297,3 +319,129 @@ pub fn check_recorded_struct_for_impl(ident: &Ident, opts: &BindgenAttrs) -> Bin } }) } + +impl Parse for BindgenAttrs { + fn parse(input: ParseStream) -> syn::Result { + let mut attrs = BindgenAttrs::default(); + if input.is_empty() { + return Ok(attrs); + } + + let opts = syn::punctuated::Punctuated::<_, syn::token::Comma>::parse_terminated(input)?; + attrs.attrs = opts.into_iter().map(|c| (Cell::new(false), c)).collect(); + Ok(attrs) + } +} + +impl Parse for BindgenAttr { + fn parse(input: ParseStream) -> syn::Result { + let original = input.fork(); + let attr: AnyIdent = input.parse()?; + let attr = attr.0; + let attr_span = attr.span(); + let attr_string = attr.to_string(); + let raw_attr_string = format!("r#{}", attr_string); + + macro_rules! parsers { + ($(($name:ident, $($contents:tt)*),)*) => { + $( + if attr_string == stringify!($name) || raw_attr_string == stringify!($name) { + parsers!( + @parser + $($contents)* + ); + } + )* + }; + + (@parser $variant:ident(Span)) => ({ + return Ok(BindgenAttr::$variant(attr_span)); + }); + + (@parser $variant:ident(Span, Ident)) => ({ + input.parse::()?; + let ident = input.parse::()?.0; + return Ok(BindgenAttr::$variant(attr_span, ident)) + }); + + (@parser $variant:ident(Span, Option)) => ({ + if input.parse::().is_ok() { + let ident = input.parse::()?.0; + return Ok(BindgenAttr::$variant(attr_span, Some(ident))) + } else { + return Ok(BindgenAttr::$variant(attr_span, None)); + } + }); + + (@parser $variant:ident(Span, syn::Path)) => ({ + input.parse::()?; + return Ok(BindgenAttr::$variant(attr_span, input.parse()?)); + }); + + (@parser $variant:ident(Span, syn::Expr)) => ({ + input.parse::()?; + return Ok(BindgenAttr::$variant(attr_span, input.parse()?)); + }); + + (@parser $variant:ident(Span, String, Span)) => ({ + input.parse::()?; + let (val, span) = match input.parse::() { + Ok(str) => (str.value(), str.span()), + Err(_) => { + let ident = input.parse::()?.0; + (ident.to_string(), ident.span()) + } + }; + return Ok(BindgenAttr::$variant(attr_span, val, span)) + }); + + (@parser $variant:ident(Span, Option)) => ({ + if let Ok(_) = input.parse::() { + let (val, _) = match input.parse::() { + Ok(str) => (str.value(), str.span()), + Err(_) => { + let ident = input.parse::()?.0; + (true, ident.span()) + } + }; + return Ok::(BindgenAttr::$variant(attr_span, Some(val))) + } else { + return Ok(BindgenAttr::$variant(attr_span, Some(true))) + } + }); + + (@parser $variant:ident(Span, Vec, Vec)) => ({ + input.parse::()?; + let (vals, spans) = match input.parse::() { + Ok(exprs) => { + let mut vals = vec![]; + let mut spans = vec![]; + + for expr in exprs.elems.iter() { + if let syn::Expr::Lit(syn::ExprLit { + lit: syn::Lit::Str(ref str), + .. + }) = expr { + vals.push(str.value()); + spans.push(str.span()); + } else { + return Err(syn::Error::new(expr.span(), "expected string literals")); + } + } + + (vals, spans) + }, + Err(_) => { + let ident = input.parse::()?.0; + (vec![ident.to_string()], vec![ident.span()]) + } + }; + return Ok(BindgenAttr::$variant(attr_span, vals, spans)) + }); + } + + attrgen!(parsers); + + Err(original.error("unknown attribute")) + } +} diff --git a/crates/macro/src/parser/mod.rs b/crates/macro/src/parser/mod.rs index 684a66ec..7165ee0c 100644 --- a/crates/macro/src/parser/mod.rs +++ b/crates/macro/src/parser/mod.rs @@ -1,12 +1,12 @@ #[macro_use] pub mod attrs; -use std::cell::{Cell, RefCell}; +use std::cell::RefCell; use std::collections::HashMap; use std::str::Chars; use std::sync::atomic::AtomicUsize; -use attrs::{BindgenAttr, BindgenAttrs}; +use attrs::BindgenAttrs; use convert_case::{Case, Casing}; use napi_derive_backend::{ @@ -14,11 +14,11 @@ use napi_derive_backend::{ NapiEnumVariant, NapiFn, NapiFnArg, NapiFnArgKind, NapiImpl, NapiItem, NapiStruct, NapiStructField, NapiStructKind, }; -use proc_macro2::{Ident, Span, TokenStream, TokenTree}; +use proc_macro2::{Ident, Span, TokenStream}; use quote::ToTokens; use syn::ext::IdentExt; use syn::parse::{Parse, ParseStream, Result as SynResult}; -use syn::{Attribute, Meta, NestedMeta, PatType, PathSegment, Signature, Type, Visibility}; +use syn::{Attribute, ExprLit, PatType, PathSegment, Signature, Type, Visibility}; use crate::parser::attrs::{check_recorded_struct_for_impl, record_struct}; @@ -48,138 +48,12 @@ impl Parse for AnyIdent { } } -impl Parse for BindgenAttrs { - fn parse(input: ParseStream) -> SynResult { - let mut attrs = BindgenAttrs::default(); - if input.is_empty() { - return Ok(attrs); - } - - let opts = syn::punctuated::Punctuated::<_, syn::token::Comma>::parse_terminated(input)?; - attrs.attrs = opts.into_iter().map(|c| (Cell::new(false), c)).collect(); - Ok(attrs) - } -} - -impl Parse for BindgenAttr { - fn parse(input: ParseStream) -> SynResult { - let original = input.fork(); - let attr: AnyIdent = input.parse()?; - let attr = attr.0; - let attr_span = attr.span(); - let attr_string = attr.to_string(); - let raw_attr_string = format!("r#{}", attr_string); - - macro_rules! parsers { - ($(($name:ident, $($contents:tt)*),)*) => { - $( - if attr_string == stringify!($name) || raw_attr_string == stringify!($name) { - parsers!( - @parser - $($contents)* - ); - } - )* - }; - - (@parser $variant:ident(Span)) => ({ - return Ok(BindgenAttr::$variant(attr_span)); - }); - - (@parser $variant:ident(Span, Ident)) => ({ - input.parse::()?; - let ident = input.parse::()?.0; - return Ok(BindgenAttr::$variant(attr_span, ident)) - }); - - (@parser $variant:ident(Span, Option)) => ({ - if input.parse::().is_ok() { - let ident = input.parse::()?.0; - return Ok(BindgenAttr::$variant(attr_span, Some(ident))) - } else { - return Ok(BindgenAttr::$variant(attr_span, None)); - } - }); - - (@parser $variant:ident(Span, syn::Path)) => ({ - input.parse::()?; - return Ok(BindgenAttr::$variant(attr_span, input.parse()?)); - }); - - (@parser $variant:ident(Span, syn::Expr)) => ({ - input.parse::()?; - return Ok(BindgenAttr::$variant(attr_span, input.parse()?)); - }); - - (@parser $variant:ident(Span, String, Span)) => ({ - input.parse::()?; - let (val, span) = match input.parse::() { - Ok(str) => (str.value(), str.span()), - Err(_) => { - let ident = input.parse::()?.0; - (ident.to_string(), ident.span()) - } - }; - return Ok(BindgenAttr::$variant(attr_span, val, span)) - }); - - (@parser $variant:ident(Span, Option)) => ({ - if let Ok(_) = input.parse::() { - let (val, _) = match input.parse::() { - Ok(str) => (str.value(), str.span()), - Err(_) => { - let ident = input.parse::()?.0; - (true, ident.span()) - } - }; - return Ok::(BindgenAttr::$variant(attr_span, Some(val))) - } else { - return Ok(BindgenAttr::$variant(attr_span, Some(true))) - } - }); - - (@parser $variant:ident(Span, Vec, Vec)) => ({ - input.parse::()?; - let (vals, spans) = match input.parse::() { - Ok(exprs) => { - let mut vals = vec![]; - let mut spans = vec![]; - - for expr in exprs.elems.iter() { - if let syn::Expr::Lit(syn::ExprLit { - lit: syn::Lit::Str(ref str), - .. - }) = expr { - vals.push(str.value()); - spans.push(str.span()); - } else { - return Err(syn::Error::new(expr.span(), "expected string literals")); - } - } - - (vals, spans) - }, - Err(_) => { - let ident = input.parse::()?.0; - (vec![ident.to_string()], vec![ident.span()]) - } - }; - return Ok(BindgenAttr::$variant(attr_span, vals, spans)) - }); - } - - attrgen!(parsers); - - Err(original.error("unknown attribute")) - } -} - pub trait ConvertToAST { - fn convert_to_ast(&mut self, opts: BindgenAttrs) -> BindgenResult; + fn convert_to_ast(&mut self, opts: &BindgenAttrs) -> BindgenResult; } pub trait ParseNapi { - fn parse_napi(&mut self, tokens: &mut TokenStream, opts: BindgenAttrs) -> BindgenResult; + fn parse_napi(&mut self, tokens: &mut TokenStream, opts: &BindgenAttrs) -> BindgenResult; } /// This function does a few things: @@ -197,43 +71,48 @@ fn find_ts_arg_type_and_remove_attribute( p: &mut PatType, ts_args_type: Option<&(&str, Span)>, ) -> BindgenResult> { + let mut ts_type_attr: Option<(usize, String)> = None; for (idx, attr) in p.attrs.iter().enumerate() { - if let Ok(Meta::List(meta_list)) = attr.parse_meta() { - if meta_list.path.get_ident() != Some(&format_ident!("napi")) { - // If this attribute is not for `napi` ignore it. - continue; - } - + if attr.path().is_ident("napi") { if let Some((ts_args_type, _)) = ts_args_type { bail_span!( - meta_list, + attr, "Found a 'ts_args_type'=\"{}\" override. Cannot use 'ts_arg_type' at the same time since they are mutually exclusive.", ts_args_type ); } + let inner: syn::Expr = attr.parse_args()?; + match inner { + syn::Expr::Assign(syn::ExprAssign { left, right, .. }) => { + let left = match *left { + syn::Expr::Path(syn::ExprPath { path, .. }) => path, + _ => bail_span!(left, "Expected path"), + }; - let nested = meta_list.nested.first(); + if !left.is_ident("ts_arg_type") { + bail_span!(left, "Expected 'ts_arg_type'"); + } - let nm = if let Some(NestedMeta::Meta(Meta::NameValue(nm))) = nested { - nm - } else { - bail_span!(meta_list.nested, "Expected Name Value"); + let right = match *right { + syn::Expr::Lit(syn::ExprLit { + lit: syn::Lit::Str(lit), + .. + }) => lit, + _ => bail_span!(right, "Expected string literal"), + }; + ts_type_attr = Some((idx, right.value())); + } + _ => bail_span!(inner, "Expected assignment [ts_arg_type = \"MyType\"]"), }; - - if Some(&format_ident!("ts_arg_type")) != nm.path.get_ident() { - bail_span!(nm.path, "Did not find 'ts_arg_type'"); - } - - if let syn::Lit::Str(lit) = &nm.lit { - p.attrs.remove(idx); - return Ok(Some(lit.value())); - } else { - bail_span!(nm.lit, "Expected a string literal"); - } } } - Ok(None) + if let Some((idx, value)) = ts_type_attr { + p.attrs.remove(idx); + Ok(Some(value)) + } else { + Ok(None) + } } fn get_ty(mut ty: &syn::Type) -> &syn::Type { @@ -361,16 +240,19 @@ fn extract_doc_comments(attrs: &[syn::Attribute]) -> Vec { .filter_map(|a| { // if the path segments include an ident of "doc" we know this // this is a doc comment - if a.path.segments.iter().any(|s| s.ident == "doc") { + if a.path().is_ident("doc") { Some( // We want to filter out any Puncts so just grab the Literals - a.tokens.clone().into_iter().filter_map(|t| match t { - TokenTree::Literal(lit) => { - let quoted = lit.to_string(); + match &a.meta.require_name_value().unwrap().value { + syn::Expr::Lit(ExprLit { + lit: syn::Lit::Str(str), + .. + }) => { + let quoted = str.token().to_string(); Some(try_unescape("ed).unwrap_or(quoted)) } _ => None, - }), + }, ) } else { None @@ -496,6 +378,10 @@ fn extract_fn_closure_generics( )); } } + _ => errors.push(err_span! { + bound, + "unsupported bound in napi" + }), } } } @@ -530,6 +416,10 @@ fn extract_fn_closure_generics( )); } } + _ => errors.push(err_span! { + bound, + "unsupported bound in napi" + }), } } } @@ -715,7 +605,7 @@ fn napi_fn_from_decl( } impl ParseNapi for syn::Item { - fn parse_napi(&mut self, tokens: &mut TokenStream, opts: BindgenAttrs) -> BindgenResult { + fn parse_napi(&mut self, tokens: &mut TokenStream, opts: &BindgenAttrs) -> BindgenResult { match self { syn::Item::Fn(f) => f.parse_napi(tokens, opts), syn::Item::Struct(s) => s.parse_napi(tokens, opts), @@ -731,7 +621,7 @@ impl ParseNapi for syn::Item { } impl ParseNapi for syn::ItemFn { - fn parse_napi(&mut self, tokens: &mut TokenStream, opts: BindgenAttrs) -> BindgenResult { + fn parse_napi(&mut self, tokens: &mut TokenStream, opts: &BindgenAttrs) -> BindgenResult { if opts.ts_type().is_some() { bail_span!( self, @@ -751,7 +641,7 @@ impl ParseNapi for syn::ItemFn { } } impl ParseNapi for syn::ItemStruct { - fn parse_napi(&mut self, tokens: &mut TokenStream, opts: BindgenAttrs) -> BindgenResult { + fn parse_napi(&mut self, tokens: &mut TokenStream, opts: &BindgenAttrs) -> BindgenResult { if opts.ts_args_type().is_some() || opts.ts_return_type().is_some() || opts.skip_typescript().is_some() @@ -785,7 +675,7 @@ impl ParseNapi for syn::ItemStruct { } impl ParseNapi for syn::ItemImpl { - fn parse_napi(&mut self, tokens: &mut TokenStream, opts: BindgenAttrs) -> BindgenResult { + fn parse_napi(&mut self, tokens: &mut TokenStream, opts: &BindgenAttrs) -> BindgenResult { if opts.ts_args_type().is_some() || opts.ts_return_type().is_some() || opts.skip_typescript().is_some() @@ -818,7 +708,7 @@ impl ParseNapi for syn::ItemImpl { } impl ParseNapi for syn::ItemEnum { - fn parse_napi(&mut self, tokens: &mut TokenStream, opts: BindgenAttrs) -> BindgenResult { + fn parse_napi(&mut self, tokens: &mut TokenStream, opts: &BindgenAttrs) -> BindgenResult { if opts.ts_args_type().is_some() || opts.ts_return_type().is_some() || opts.ts_type().is_some() @@ -848,7 +738,7 @@ impl ParseNapi for syn::ItemEnum { } } impl ParseNapi for syn::ItemConst { - fn parse_napi(&mut self, tokens: &mut TokenStream, opts: BindgenAttrs) -> BindgenResult { + fn parse_napi(&mut self, tokens: &mut TokenStream, opts: &BindgenAttrs) -> BindgenResult { if opts.ts_args_type().is_some() || opts.ts_return_type().is_some() || opts.ts_type().is_some() @@ -900,10 +790,10 @@ fn fn_kind(opts: &BindgenAttrs) -> FnKind { } impl ConvertToAST for syn::ItemFn { - fn convert_to_ast(&mut self, opts: BindgenAttrs) -> BindgenResult { + fn convert_to_ast(&mut self, opts: &BindgenAttrs) -> BindgenResult { let func = napi_fn_from_decl( &mut self.sig, - &opts, + opts, self.attrs.clone(), self.vis.clone(), None, @@ -916,7 +806,7 @@ impl ConvertToAST for syn::ItemFn { } impl ConvertToAST for syn::ItemStruct { - fn convert_to_ast(&mut self, opts: BindgenAttrs) -> BindgenResult { + fn convert_to_ast(&mut self, opts: &BindgenAttrs) -> BindgenResult { let mut errors = vec![]; let vis = self.vis.clone(); @@ -988,7 +878,7 @@ impl ConvertToAST for syn::ItemStruct { }) } - record_struct(&struct_name, js_name.clone(), &opts); + record_struct(&struct_name, js_name.clone(), opts); let namespace = opts.namespace().map(|(m, _)| m.to_owned()); let implement_iterator = opts.iterator().is_some(); GENERATOR_STRUCT.with(|inner| { @@ -1021,7 +911,7 @@ impl ConvertToAST for syn::ItemStruct { } impl ConvertToAST for syn::ItemImpl { - fn convert_to_ast(&mut self, impl_opts: BindgenAttrs) -> BindgenResult { + fn convert_to_ast(&mut self, impl_opts: &BindgenAttrs) -> BindgenResult { let struct_name = match get_ty(&self.self_ty) { syn::Type::Path(syn::TypePath { ref path, @@ -1042,7 +932,7 @@ impl ConvertToAST for syn::ItemImpl { let mut iterator_return_type = None; for item in self.items.iter_mut() { if let Some(method) = match item { - syn::ImplItem::Method(m) => Some(m), + syn::ImplItem::Fn(m) => Some(m), syn::ImplItem::Type(m) => { if let Some((_, t, _)) = &self.trait_ { if let Some(PathSegment { ident, .. }) = t.segments.last() { @@ -1119,19 +1009,13 @@ impl ConvertToAST for syn::ItemImpl { } impl ConvertToAST for syn::ItemEnum { - fn convert_to_ast(&mut self, opts: BindgenAttrs) -> BindgenResult { + fn convert_to_ast(&mut self, opts: &BindgenAttrs) -> BindgenResult { match self.vis { Visibility::Public(_) => {} _ => bail_span!(self, "only public enum allowed"), } - self.attrs.push(Attribute { - pound_token: Default::default(), - style: syn::AttrStyle::Outer, - bracket_token: Default::default(), - path: syn::parse_quote! { derive }, - tokens: quote! { (Copy, Clone) }, - }); + self.attrs.push(parse_quote!(#[derive(Copy, Clone)])); let js_name = opts .js_name() @@ -1234,7 +1118,7 @@ impl ConvertToAST for syn::ItemEnum { } impl ConvertToAST for syn::ItemConst { - fn convert_to_ast(&mut self, opts: BindgenAttrs) -> BindgenResult { + fn convert_to_ast(&mut self, opts: &BindgenAttrs) -> BindgenResult { match self.vis { Visibility::Public(_) => Ok(Napi { item: NapiItem::Const(NapiConst { diff --git a/examples/napi-compat-mode/package.json b/examples/napi-compat-mode/package.json index de4d7167..a23f7c54 100644 --- a/examples/napi-compat-mode/package.json +++ b/examples/napi-compat-mode/package.json @@ -26,6 +26,7 @@ "TS_NODE_PROJECT": "../tsconfig.json" }, "workerThreads": false, + "cache": false, "timeout": "5m" } } diff --git a/examples/napi/package.json b/examples/napi/package.json index 1366347a..c1652dba 100644 --- a/examples/napi/package.json +++ b/examples/napi/package.json @@ -27,6 +27,7 @@ "files": [ "__tests__/**/*.spec.{ts,cts,js,cjs,mjs}" ], + "cache": false, "timeout": "10m" }, "dependencies": { diff --git a/examples/napi/tests/build_error_tests/ts_arg_type_1.stderr b/examples/napi/tests/build_error_tests/ts_arg_type_1.stderr index f6994ca6..19bc3657 100644 --- a/examples/napi/tests/build_error_tests/ts_arg_type_1.stderr +++ b/examples/napi/tests/build_error_tests/ts_arg_type_1.stderr @@ -1,5 +1,5 @@ error: Found a 'ts_args_type'="u: number, fn: object" override. Cannot use 'ts_arg_type' at the same time since they are mutually exclusive. - --> tests/build_error_tests/ts_arg_type_1.rs:7:22 + --> tests/build_error_tests/ts_arg_type_1.rs:7:20 | 7 | pub fn add(u: u32, #[napi(ts_arg_type = "object")] f: Option) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/examples/napi/tests/build_error_tests/ts_arg_type_2.stderr b/examples/napi/tests/build_error_tests/ts_arg_type_2.stderr index 7b7515eb..644d5475 100644 --- a/examples/napi/tests/build_error_tests/ts_arg_type_2.stderr +++ b/examples/napi/tests/build_error_tests/ts_arg_type_2.stderr @@ -1,4 +1,4 @@ -error: Expected a string literal +error: Expected string literal --> tests/build_error_tests/ts_arg_type_2.rs:7:41 | 7 | pub fn add(u: u32, #[napi(ts_arg_type = 32)] f: Option) { diff --git a/examples/napi/tests/build_error_tests/ts_arg_type_3.stderr b/examples/napi/tests/build_error_tests/ts_arg_type_3.stderr index 7c70a888..deb6cb88 100644 --- a/examples/napi/tests/build_error_tests/ts_arg_type_3.stderr +++ b/examples/napi/tests/build_error_tests/ts_arg_type_3.stderr @@ -1,5 +1,5 @@ -error: Expected Name Value - --> tests/build_error_tests/ts_arg_type_3.rs:7:27 +error: unexpected token + --> tests/build_error_tests/ts_arg_type_3.rs:7:38 | 7 | pub fn add(u: u32, #[napi(ts_arg_type, not_expected)] f: Option) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ diff --git a/examples/napi/tests/build_error_tests/ts_arg_type_4.stderr b/examples/napi/tests/build_error_tests/ts_arg_type_4.stderr index dc0a40e1..e57ac42e 100644 --- a/examples/napi/tests/build_error_tests/ts_arg_type_4.stderr +++ b/examples/napi/tests/build_error_tests/ts_arg_type_4.stderr @@ -1,4 +1,4 @@ -error: Did not find 'ts_arg_type' +error: Expected 'ts_arg_type' --> tests/build_error_tests/ts_arg_type_4.rs:7:27 | 7 | pub fn add(u: u32, #[napi(not_expected = "obj")] f: Option) {