fix(napi-derive): upgrade syn (#1849)

This commit is contained in:
liuyi 2023-12-13 12:40:01 +08:00 committed by GitHub
parent e3902e001f
commit e32c105a26
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 284 additions and 261 deletions

View file

@ -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

View file

@ -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]

View file

@ -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<TokenStrea
.attrs
.iter()
.enumerate()
.find(|(_, m)| m.path.segments[0].ident == "napi");
.find(|(_, m)| m.path().is_ident("napi"));
if mod_in_mod.is_some() {
bail_span!(
mod_,
@ -79,7 +79,8 @@ pub fn expand(attr: TokenStream, input: TokenStream) -> BindgenResult<TokenStrea
_ => &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<TokenStrea
.attrs
.clone()
.into_iter()
.filter(|attr| attr.path.segments[0].ident != "napi")
.filter(|attr| attr.path().is_ident("napi"))
.collect();
let mod_name = js_mod.ident;
let visible = js_mod.vis;
let mod_tokens = quote! { #(#js_mod_attrs)* #visible mod #mod_name { #tokens } };
Ok(mod_tokens)
} else {
let napi = item.parse_napi(&mut tokens, opts)?;
let napi = item.parse_napi(&mut tokens, &opts)?;
opts.check_used()?;
napi.try_to_tokens(&mut tokens)?;
#[cfg(feature = "type-def")]
@ -155,41 +157,28 @@ fn replace_napi_attr_in_mod(
js_namespace: String,
attrs: &mut Vec<syn::Attribute>,
) -> Option<BindgenAttrs> {
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::<TokenStream>(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 {

View file

@ -24,7 +24,7 @@ fn find_and_remove_napi_attr(attrs: &mut Vec<Attribute>) {
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,

View file

@ -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<usize>,
#[allow(unused)]
checks: Cell<usize>,
}
@ -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<syn::Attribute>) -> Result<BindgenAttrs, Diagnostic> {
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<Self, Self::Error> {
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<Self> {
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<Self> {
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::<Token![=]>()?;
let ident = input.parse::<AnyIdent>()?.0;
return Ok(BindgenAttr::$variant(attr_span, ident))
});
(@parser $variant:ident(Span, Option<Ident>)) => ({
if input.parse::<Token![=]>().is_ok() {
let ident = input.parse::<AnyIdent>()?.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::<Token![=]>()?;
return Ok(BindgenAttr::$variant(attr_span, input.parse()?));
});
(@parser $variant:ident(Span, syn::Expr)) => ({
input.parse::<Token![=]>()?;
return Ok(BindgenAttr::$variant(attr_span, input.parse()?));
});
(@parser $variant:ident(Span, String, Span)) => ({
input.parse::<Token![=]>()?;
let (val, span) = match input.parse::<syn::LitStr>() {
Ok(str) => (str.value(), str.span()),
Err(_) => {
let ident = input.parse::<AnyIdent>()?.0;
(ident.to_string(), ident.span())
}
};
return Ok(BindgenAttr::$variant(attr_span, val, span))
});
(@parser $variant:ident(Span, Option<bool>)) => ({
if let Ok(_) = input.parse::<Token![=]>() {
let (val, _) = match input.parse::<syn::LitBool>() {
Ok(str) => (str.value(), str.span()),
Err(_) => {
let ident = input.parse::<AnyIdent>()?.0;
(true, ident.span())
}
};
return Ok::<BindgenAttr, syn::Error>(BindgenAttr::$variant(attr_span, Some(val)))
} else {
return Ok(BindgenAttr::$variant(attr_span, Some(true)))
}
});
(@parser $variant:ident(Span, Vec<String>, Vec<Span>)) => ({
input.parse::<Token![=]>()?;
let (vals, spans) = match input.parse::<syn::ExprArray>() {
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::<AnyIdent>()?.0;
(vec![ident.to_string()], vec![ident.span()])
}
};
return Ok(BindgenAttr::$variant(attr_span, vals, spans))
});
}
attrgen!(parsers);
Err(original.error("unknown attribute"))
}
}

View file

@ -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<Self> {
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<Self> {
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::<Token![=]>()?;
let ident = input.parse::<AnyIdent>()?.0;
return Ok(BindgenAttr::$variant(attr_span, ident))
});
(@parser $variant:ident(Span, Option<Ident>)) => ({
if input.parse::<Token![=]>().is_ok() {
let ident = input.parse::<AnyIdent>()?.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::<Token![=]>()?;
return Ok(BindgenAttr::$variant(attr_span, input.parse()?));
});
(@parser $variant:ident(Span, syn::Expr)) => ({
input.parse::<Token![=]>()?;
return Ok(BindgenAttr::$variant(attr_span, input.parse()?));
});
(@parser $variant:ident(Span, String, Span)) => ({
input.parse::<Token![=]>()?;
let (val, span) = match input.parse::<syn::LitStr>() {
Ok(str) => (str.value(), str.span()),
Err(_) => {
let ident = input.parse::<AnyIdent>()?.0;
(ident.to_string(), ident.span())
}
};
return Ok(BindgenAttr::$variant(attr_span, val, span))
});
(@parser $variant:ident(Span, Option<bool>)) => ({
if let Ok(_) = input.parse::<Token![=]>() {
let (val, _) = match input.parse::<syn::LitBool>() {
Ok(str) => (str.value(), str.span()),
Err(_) => {
let ident = input.parse::<AnyIdent>()?.0;
(true, ident.span())
}
};
return Ok::<BindgenAttr, syn::Error>(BindgenAttr::$variant(attr_span, Some(val)))
} else {
return Ok(BindgenAttr::$variant(attr_span, Some(true)))
}
});
(@parser $variant:ident(Span, Vec<String>, Vec<Span>)) => ({
input.parse::<Token![=]>()?;
let (vals, spans) = match input.parse::<syn::ExprArray>() {
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::<AnyIdent>()?.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<Napi>;
fn convert_to_ast(&mut self, opts: &BindgenAttrs) -> BindgenResult<Napi>;
}
pub trait ParseNapi {
fn parse_napi(&mut self, tokens: &mut TokenStream, opts: BindgenAttrs) -> BindgenResult<Napi>;
fn parse_napi(&mut self, tokens: &mut TokenStream, opts: &BindgenAttrs) -> BindgenResult<Napi>;
}
/// 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<Option<String>> {
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<String> {
.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(&quoted).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<Napi> {
fn parse_napi(&mut self, tokens: &mut TokenStream, opts: &BindgenAttrs) -> BindgenResult<Napi> {
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<Napi> {
fn parse_napi(&mut self, tokens: &mut TokenStream, opts: &BindgenAttrs) -> BindgenResult<Napi> {
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<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()
|| 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<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()
|| 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<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()
|| 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<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()
|| 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<Napi> {
fn convert_to_ast(&mut self, opts: &BindgenAttrs) -> BindgenResult<Napi> {
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<Napi> {
fn convert_to_ast(&mut self, opts: &BindgenAttrs) -> BindgenResult<Napi> {
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<Napi> {
fn convert_to_ast(&mut self, impl_opts: &BindgenAttrs) -> BindgenResult<Napi> {
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<Napi> {
fn convert_to_ast(&mut self, opts: &BindgenAttrs) -> BindgenResult<Napi> {
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<Napi> {
fn convert_to_ast(&mut self, opts: &BindgenAttrs) -> BindgenResult<Napi> {
match self.vis {
Visibility::Public(_) => Ok(Napi {
item: NapiItem::Const(NapiConst {

View file

@ -26,6 +26,7 @@
"TS_NODE_PROJECT": "../tsconfig.json"
},
"workerThreads": false,
"cache": false,
"timeout": "5m"
}
}

View file

@ -27,6 +27,7 @@
"files": [
"__tests__/**/*.spec.{ts,cts,js,cjs,mjs}"
],
"cache": false,
"timeout": "10m"
},
"dependencies": {

View file

@ -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<String>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -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<String>) {

View file

@ -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<String>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| ^

View file

@ -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<String>) {