fix(napi-derive): upgrade syn (#1849)
This commit is contained in:
parent
e3902e001f
commit
e32c105a26
12 changed files with 284 additions and 261 deletions
|
@ -21,7 +21,7 @@ type-def = ["regex", "once_cell", "semver"]
|
||||||
convert_case = "0.6"
|
convert_case = "0.6"
|
||||||
proc-macro2 = "1"
|
proc-macro2 = "1"
|
||||||
quote = "1"
|
quote = "1"
|
||||||
syn = { version = "1.0.61", features = ["fold", "full", "extra-traits"] }
|
syn = { version = "2", features = ["fold", "full", "extra-traits"] }
|
||||||
|
|
||||||
[dependencies.regex]
|
[dependencies.regex]
|
||||||
optional = true
|
optional = true
|
||||||
|
|
|
@ -24,9 +24,9 @@ type-def = ["napi-derive-backend/type-def"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
convert_case = "0.6"
|
convert_case = "0.6"
|
||||||
napi-derive-backend = { version = "1.0.56", path = "../backend" }
|
napi-derive-backend = { version = "1.0.56", path = "../backend" }
|
||||||
proc-macro2 = "1.0"
|
proc-macro2 = "1"
|
||||||
quote = "1.0"
|
quote = "1"
|
||||||
syn = { version = "1.0.61", features = ["fold", "full", "extra-traits"] }
|
syn = { version = "2", features = ["fold", "full", "extra-traits"] }
|
||||||
cfg-if = "1.0"
|
cfg-if = "1.0"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::parser::{attrs::BindgenAttrs, ParseNapi};
|
||||||
#[cfg(feature = "type-def")]
|
#[cfg(feature = "type-def")]
|
||||||
use napi_derive_backend::ToTypeDef;
|
use napi_derive_backend::ToTypeDef;
|
||||||
use napi_derive_backend::{BindgenResult, Napi, TryToTokens};
|
use napi_derive_backend::{BindgenResult, Napi, TryToTokens};
|
||||||
use proc_macro2::{TokenStream, TokenTree};
|
use proc_macro2::TokenStream;
|
||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
use syn::{Attribute, Item};
|
use syn::{Attribute, Item};
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ pub fn expand(attr: TokenStream, input: TokenStream) -> BindgenResult<TokenStrea
|
||||||
.attrs
|
.attrs
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find(|(_, m)| m.path.segments[0].ident == "napi");
|
.find(|(_, m)| m.path().is_ident("napi"));
|
||||||
if mod_in_mod.is_some() {
|
if mod_in_mod.is_some() {
|
||||||
bail_span!(
|
bail_span!(
|
||||||
mod_,
|
mod_,
|
||||||
|
@ -79,7 +79,8 @@ pub fn expand(attr: TokenStream, input: TokenStream) -> BindgenResult<TokenStrea
|
||||||
_ => &mut empty_attrs,
|
_ => &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)?;
|
napi.try_to_tokens(&mut tokens)?;
|
||||||
|
|
||||||
#[cfg(feature = "type-def")]
|
#[cfg(feature = "type-def")]
|
||||||
|
@ -96,14 +97,15 @@ pub fn expand(attr: TokenStream, input: TokenStream) -> BindgenResult<TokenStrea
|
||||||
.attrs
|
.attrs
|
||||||
.clone()
|
.clone()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|attr| attr.path.segments[0].ident != "napi")
|
.filter(|attr| attr.path().is_ident("napi"))
|
||||||
.collect();
|
.collect();
|
||||||
let mod_name = js_mod.ident;
|
let mod_name = js_mod.ident;
|
||||||
let visible = js_mod.vis;
|
let visible = js_mod.vis;
|
||||||
let mod_tokens = quote! { #(#js_mod_attrs)* #visible mod #mod_name { #tokens } };
|
let mod_tokens = quote! { #(#js_mod_attrs)* #visible mod #mod_name { #tokens } };
|
||||||
Ok(mod_tokens)
|
Ok(mod_tokens)
|
||||||
} else {
|
} 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)?;
|
napi.try_to_tokens(&mut tokens)?;
|
||||||
|
|
||||||
#[cfg(feature = "type-def")]
|
#[cfg(feature = "type-def")]
|
||||||
|
@ -155,41 +157,28 @@ fn replace_napi_attr_in_mod(
|
||||||
js_namespace: String,
|
js_namespace: String,
|
||||||
attrs: &mut Vec<syn::Attribute>,
|
attrs: &mut Vec<syn::Attribute>,
|
||||||
) -> Option<BindgenAttrs> {
|
) -> Option<BindgenAttrs> {
|
||||||
let napi_attr = attrs.clone();
|
let napi_attr = attrs
|
||||||
let napi_attr = napi_attr
|
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find(|(_, m)| m.path.segments[0].ident == "napi");
|
.find(|(_, m)| m.path().is_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();
|
|
||||||
|
|
||||||
let new_attr: syn::Attribute = if !raw_attr_stream.is_empty() {
|
if let Some((index, napi_attr)) = napi_attr {
|
||||||
syn::parse_quote!(
|
// adds `namespace = #js_namespace` into `#[napi]` attribute
|
||||||
#[napi(#raw_attr_token_stream, namespace = #js_namespace)]
|
let new_attr = match &napi_attr.meta {
|
||||||
)
|
syn::Meta::Path(_) => {
|
||||||
} else {
|
syn::parse_quote!(#[napi(namespace = #js_namespace)])
|
||||||
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() {
|
let struct_opts = BindgenAttrs::try_from(&new_attr).unwrap();
|
||||||
syn::parse2(g.stream()).ok()?
|
|
||||||
} else {
|
|
||||||
syn::parse2(quote! {}).ok()?
|
|
||||||
};
|
|
||||||
attrs.remove(index);
|
attrs.remove(index);
|
||||||
Some(struct_opts)
|
Some(struct_opts)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -24,7 +24,7 @@ fn find_and_remove_napi_attr(attrs: &mut Vec<Attribute>) {
|
||||||
let napi_attr = attrs
|
let napi_attr = attrs
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find(|&(_, m)| m.path.segments[0].ident == "napi");
|
.find(|&(_, m)| m.path().segments[0].ident == "napi");
|
||||||
|
|
||||||
let pos = match napi_attr {
|
let pos = match napi_attr {
|
||||||
Some((pos, _raw_attr)) => pos,
|
Some((pos, _raw_attr)) => pos,
|
||||||
|
|
|
@ -3,7 +3,12 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use napi_derive_backend::{bail_span, BindgenResult, Diagnostic};
|
use napi_derive_backend::{bail_span, BindgenResult, Diagnostic};
|
||||||
use proc_macro2::{Delimiter, Ident, Span, TokenTree};
|
use proc_macro2::{Delimiter, Ident, Span, TokenTree};
|
||||||
|
use quote::ToTokens;
|
||||||
|
use syn::parse::{Parse, ParseStream};
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
|
use syn::Attribute;
|
||||||
|
|
||||||
|
use crate::parser::AnyIdent;
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
static ATTRS: AttributeParseState = Default::default();
|
static ATTRS: AttributeParseState = Default::default();
|
||||||
|
@ -23,6 +28,7 @@ struct ParsedStruct {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct AttributeParseState {
|
struct AttributeParseState {
|
||||||
parsed: Cell<usize>,
|
parsed: Cell<usize>,
|
||||||
|
#[allow(unused)]
|
||||||
checks: Cell<usize>,
|
checks: Cell<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +90,8 @@ macro_rules! methods {
|
||||||
$(methods!(@method $name, $variant($($contents)*));)*
|
$(methods!(@method $name, $variant($($contents)*));)*
|
||||||
|
|
||||||
#[cfg(feature = "strict")]
|
#[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
|
// Account for the fact this method was called
|
||||||
ATTRS.with(|state| state.checks.set(state.checks.get() + 1));
|
ATTRS.with(|state| state.checks.set(state.checks.get() + 1));
|
||||||
|
|
||||||
|
@ -102,7 +109,7 @@ macro_rules! methods {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "strict"))]
|
#[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
|
// Account for the fact this method was called
|
||||||
ATTRS.with(|state| state.checks.set(state.checks.get() + 1));
|
ATTRS.with(|state| state.checks.set(state.checks.get() + 1));
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -191,43 +198,58 @@ macro_rules! methods {
|
||||||
impl BindgenAttrs {
|
impl BindgenAttrs {
|
||||||
/// Find and parse the napi attributes.
|
/// Find and parse the napi attributes.
|
||||||
pub fn find(attrs: &mut Vec<syn::Attribute>) -> Result<BindgenAttrs, Diagnostic> {
|
pub fn find(attrs: &mut Vec<syn::Attribute>) -> Result<BindgenAttrs, Diagnostic> {
|
||||||
let mut ret = BindgenAttrs::default();
|
for (index, attr) in attrs.iter().enumerate() {
|
||||||
loop {
|
let attr = BindgenAttrs::try_from(attr)?;
|
||||||
let napi_attr = attrs
|
if attr.exists {
|
||||||
.iter()
|
attrs.remove(index);
|
||||||
.enumerate()
|
|
||||||
.find(|&(_, m)| m.path.segments[0].ident == "napi");
|
|
||||||
|
|
||||||
let pos = match napi_attr {
|
return Ok(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");
|
|
||||||
}
|
}
|
||||||
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);
|
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 {
|
impl Default for BindgenAttrs {
|
||||||
fn default() -> BindgenAttrs {
|
fn default() -> BindgenAttrs {
|
||||||
// Add 1 to the list of parsed attribute sets. We'll use this counter to
|
// 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"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod attrs;
|
pub mod attrs;
|
||||||
|
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::str::Chars;
|
use std::str::Chars;
|
||||||
use std::sync::atomic::AtomicUsize;
|
use std::sync::atomic::AtomicUsize;
|
||||||
|
|
||||||
use attrs::{BindgenAttr, BindgenAttrs};
|
use attrs::BindgenAttrs;
|
||||||
|
|
||||||
use convert_case::{Case, Casing};
|
use convert_case::{Case, Casing};
|
||||||
use napi_derive_backend::{
|
use napi_derive_backend::{
|
||||||
|
@ -14,11 +14,11 @@ use napi_derive_backend::{
|
||||||
NapiEnumVariant, NapiFn, NapiFnArg, NapiFnArgKind, NapiImpl, NapiItem, NapiStruct,
|
NapiEnumVariant, NapiFn, NapiFnArg, NapiFnArgKind, NapiImpl, NapiItem, NapiStruct,
|
||||||
NapiStructField, NapiStructKind,
|
NapiStructField, NapiStructKind,
|
||||||
};
|
};
|
||||||
use proc_macro2::{Ident, Span, TokenStream, TokenTree};
|
use proc_macro2::{Ident, Span, TokenStream};
|
||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
use syn::ext::IdentExt;
|
use syn::ext::IdentExt;
|
||||||
use syn::parse::{Parse, ParseStream, Result as SynResult};
|
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};
|
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 {
|
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 {
|
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:
|
/// This function does a few things:
|
||||||
|
@ -197,43 +71,48 @@ fn find_ts_arg_type_and_remove_attribute(
|
||||||
p: &mut PatType,
|
p: &mut PatType,
|
||||||
ts_args_type: Option<&(&str, Span)>,
|
ts_args_type: Option<&(&str, Span)>,
|
||||||
) -> BindgenResult<Option<String>> {
|
) -> BindgenResult<Option<String>> {
|
||||||
|
let mut ts_type_attr: Option<(usize, String)> = None;
|
||||||
for (idx, attr) in p.attrs.iter().enumerate() {
|
for (idx, attr) in p.attrs.iter().enumerate() {
|
||||||
if let Ok(Meta::List(meta_list)) = attr.parse_meta() {
|
if attr.path().is_ident("napi") {
|
||||||
if meta_list.path.get_ident() != Some(&format_ident!("napi")) {
|
|
||||||
// If this attribute is not for `napi` ignore it.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some((ts_args_type, _)) = ts_args_type {
|
if let Some((ts_args_type, _)) = ts_args_type {
|
||||||
bail_span!(
|
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.",
|
"Found a 'ts_args_type'=\"{}\" override. Cannot use 'ts_arg_type' at the same time since they are mutually exclusive.",
|
||||||
ts_args_type
|
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 {
|
let right = match *right {
|
||||||
nm
|
syn::Expr::Lit(syn::ExprLit {
|
||||||
} else {
|
lit: syn::Lit::Str(lit),
|
||||||
bail_span!(meta_list.nested, "Expected Name Value");
|
..
|
||||||
|
}) => 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 {
|
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| {
|
.filter_map(|a| {
|
||||||
// if the path segments include an ident of "doc" we know this
|
// if the path segments include an ident of "doc" we know this
|
||||||
// this is a doc comment
|
// this is a doc comment
|
||||||
if a.path.segments.iter().any(|s| s.ident == "doc") {
|
if a.path().is_ident("doc") {
|
||||||
Some(
|
Some(
|
||||||
// We want to filter out any Puncts so just grab the Literals
|
// We want to filter out any Puncts so just grab the Literals
|
||||||
a.tokens.clone().into_iter().filter_map(|t| match t {
|
match &a.meta.require_name_value().unwrap().value {
|
||||||
TokenTree::Literal(lit) => {
|
syn::Expr::Lit(ExprLit {
|
||||||
let quoted = lit.to_string();
|
lit: syn::Lit::Str(str),
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
let quoted = str.token().to_string();
|
||||||
Some(try_unescape("ed).unwrap_or(quoted))
|
Some(try_unescape("ed).unwrap_or(quoted))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}),
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
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 {
|
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 {
|
match self {
|
||||||
syn::Item::Fn(f) => f.parse_napi(tokens, opts),
|
syn::Item::Fn(f) => f.parse_napi(tokens, opts),
|
||||||
syn::Item::Struct(s) => s.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 {
|
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() {
|
if opts.ts_type().is_some() {
|
||||||
bail_span!(
|
bail_span!(
|
||||||
self,
|
self,
|
||||||
|
@ -751,7 +641,7 @@ 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()
|
if opts.ts_args_type().is_some()
|
||||||
|| opts.ts_return_type().is_some()
|
|| opts.ts_return_type().is_some()
|
||||||
|| opts.skip_typescript().is_some()
|
|| opts.skip_typescript().is_some()
|
||||||
|
@ -785,7 +675,7 @@ 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()
|
if opts.ts_args_type().is_some()
|
||||||
|| opts.ts_return_type().is_some()
|
|| opts.ts_return_type().is_some()
|
||||||
|| opts.skip_typescript().is_some()
|
|| opts.skip_typescript().is_some()
|
||||||
|
@ -818,7 +708,7 @@ impl ParseNapi for syn::ItemImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
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()
|
if opts.ts_args_type().is_some()
|
||||||
|| opts.ts_return_type().is_some()
|
|| opts.ts_return_type().is_some()
|
||||||
|| opts.ts_type().is_some()
|
|| opts.ts_type().is_some()
|
||||||
|
@ -848,7 +738,7 @@ impl ParseNapi for syn::ItemEnum {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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()
|
if opts.ts_args_type().is_some()
|
||||||
|| opts.ts_return_type().is_some()
|
|| opts.ts_return_type().is_some()
|
||||||
|| opts.ts_type().is_some()
|
|| opts.ts_type().is_some()
|
||||||
|
@ -900,10 +790,10 @@ fn fn_kind(opts: &BindgenAttrs) -> FnKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConvertToAST for syn::ItemFn {
|
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(
|
let func = napi_fn_from_decl(
|
||||||
&mut self.sig,
|
&mut self.sig,
|
||||||
&opts,
|
opts,
|
||||||
self.attrs.clone(),
|
self.attrs.clone(),
|
||||||
self.vis.clone(),
|
self.vis.clone(),
|
||||||
None,
|
None,
|
||||||
|
@ -916,7 +806,7 @@ impl ConvertToAST for syn::ItemFn {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConvertToAST for syn::ItemStruct {
|
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 mut errors = vec![];
|
||||||
|
|
||||||
let vis = self.vis.clone();
|
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 namespace = opts.namespace().map(|(m, _)| m.to_owned());
|
||||||
let implement_iterator = opts.iterator().is_some();
|
let implement_iterator = opts.iterator().is_some();
|
||||||
GENERATOR_STRUCT.with(|inner| {
|
GENERATOR_STRUCT.with(|inner| {
|
||||||
|
@ -1021,7 +911,7 @@ impl ConvertToAST for syn::ItemStruct {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConvertToAST for syn::ItemImpl {
|
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) {
|
let struct_name = match get_ty(&self.self_ty) {
|
||||||
syn::Type::Path(syn::TypePath {
|
syn::Type::Path(syn::TypePath {
|
||||||
ref path,
|
ref path,
|
||||||
|
@ -1042,7 +932,7 @@ impl ConvertToAST for syn::ItemImpl {
|
||||||
let mut iterator_return_type = None;
|
let mut iterator_return_type = None;
|
||||||
for item in self.items.iter_mut() {
|
for item in self.items.iter_mut() {
|
||||||
if let Some(method) = match item {
|
if let Some(method) = match item {
|
||||||
syn::ImplItem::Method(m) => Some(m),
|
syn::ImplItem::Fn(m) => Some(m),
|
||||||
syn::ImplItem::Type(m) => {
|
syn::ImplItem::Type(m) => {
|
||||||
if let Some((_, t, _)) = &self.trait_ {
|
if let Some((_, t, _)) = &self.trait_ {
|
||||||
if let Some(PathSegment { ident, .. }) = t.segments.last() {
|
if let Some(PathSegment { ident, .. }) = t.segments.last() {
|
||||||
|
@ -1119,19 +1009,13 @@ impl ConvertToAST for syn::ItemImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConvertToAST for syn::ItemEnum {
|
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 {
|
match self.vis {
|
||||||
Visibility::Public(_) => {}
|
Visibility::Public(_) => {}
|
||||||
_ => bail_span!(self, "only public enum allowed"),
|
_ => bail_span!(self, "only public enum allowed"),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.attrs.push(Attribute {
|
self.attrs.push(parse_quote!(#[derive(Copy, Clone)]));
|
||||||
pound_token: Default::default(),
|
|
||||||
style: syn::AttrStyle::Outer,
|
|
||||||
bracket_token: Default::default(),
|
|
||||||
path: syn::parse_quote! { derive },
|
|
||||||
tokens: quote! { (Copy, Clone) },
|
|
||||||
});
|
|
||||||
|
|
||||||
let js_name = opts
|
let js_name = opts
|
||||||
.js_name()
|
.js_name()
|
||||||
|
@ -1234,7 +1118,7 @@ impl ConvertToAST for syn::ItemEnum {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConvertToAST for syn::ItemConst {
|
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 {
|
match self.vis {
|
||||||
Visibility::Public(_) => Ok(Napi {
|
Visibility::Public(_) => Ok(Napi {
|
||||||
item: NapiItem::Const(NapiConst {
|
item: NapiItem::Const(NapiConst {
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
"TS_NODE_PROJECT": "../tsconfig.json"
|
"TS_NODE_PROJECT": "../tsconfig.json"
|
||||||
},
|
},
|
||||||
"workerThreads": false,
|
"workerThreads": false,
|
||||||
|
"cache": false,
|
||||||
"timeout": "5m"
|
"timeout": "5m"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
"files": [
|
"files": [
|
||||||
"__tests__/**/*.spec.{ts,cts,js,cjs,mjs}"
|
"__tests__/**/*.spec.{ts,cts,js,cjs,mjs}"
|
||||||
],
|
],
|
||||||
|
"cache": false,
|
||||||
"timeout": "10m"
|
"timeout": "10m"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
@ -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.
|
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>) {
|
7 | pub fn add(u: u32, #[napi(ts_arg_type = "object")] f: Option<String>) {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Expected a string literal
|
error: Expected string literal
|
||||||
--> tests/build_error_tests/ts_arg_type_2.rs:7:41
|
--> 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>) {
|
7 | pub fn add(u: u32, #[napi(ts_arg_type = 32)] f: Option<String>) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: Expected Name Value
|
error: unexpected token
|
||||||
--> tests/build_error_tests/ts_arg_type_3.rs:7:27
|
--> 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>) {
|
7 | pub fn add(u: u32, #[napi(ts_arg_type, not_expected)] f: Option<String>) {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^
|
||||||
|
|
|
@ -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
|
--> tests/build_error_tests/ts_arg_type_4.rs:7:27
|
||||||
|
|
|
|
||||||
7 | pub fn add(u: u32, #[napi(not_expected = "obj")] f: Option<String>) {
|
7 | pub fn add(u: u32, #[napi(not_expected = "obj")] f: Option<String>) {
|
||||||
|
|
Loading…
Reference in a new issue