mirror of
https://git.proxmox.com/git/perlmod
synced 2025-10-04 22:07:05 +00:00
update to syn-2
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
b32c4fd40a
commit
cb86559d13
@ -21,7 +21,7 @@ proc-macro = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
proc-macro2 = "1.0"
|
proc-macro2 = "1.0"
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
syn = { version = "1.0", features = [ "full" ] }
|
syn = { version = "2", features = [ "full" ] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
perlmod = { path = "../perlmod" }
|
perlmod = { path = "../perlmod" }
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use proc_macro2::{Ident, Span};
|
use proc_macro2::{Ident, Span};
|
||||||
|
|
||||||
use syn::AttributeArgs;
|
use syn::punctuated::Punctuated;
|
||||||
use syn::Error;
|
use syn::{Error, Meta, Token};
|
||||||
|
|
||||||
pub struct ModuleAttrs {
|
pub struct ModuleAttrs {
|
||||||
pub package_name: String,
|
pub package_name: String,
|
||||||
@ -22,10 +22,10 @@ fn is_ident_check_dup<T>(path: &syn::Path, var: &Option<T>, what: &'static str)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<AttributeArgs> for ModuleAttrs {
|
impl TryFrom<Punctuated<Meta, Token![,]>> for ModuleAttrs {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn try_from(args: AttributeArgs) -> Result<Self, Self::Error> {
|
fn try_from(args: Punctuated<Meta, Token![,]>) -> Result<Self, Self::Error> {
|
||||||
let mut package_name = None;
|
let mut package_name = None;
|
||||||
let mut file_name = None;
|
let mut file_name = None;
|
||||||
let mut lib_name = None;
|
let mut lib_name = None;
|
||||||
@ -33,36 +33,31 @@ impl TryFrom<AttributeArgs> for ModuleAttrs {
|
|||||||
let mut boot = None;
|
let mut boot = None;
|
||||||
|
|
||||||
for arg in args {
|
for arg in args {
|
||||||
match arg {
|
let (path, value) = match arg {
|
||||||
syn::NestedMeta::Meta(syn::Meta::NameValue(syn::MetaNameValue {
|
syn::Meta::NameValue(syn::MetaNameValue { path, value, .. }) => (path, value),
|
||||||
path,
|
_ => {
|
||||||
lit: syn::Lit::Str(litstr),
|
error!(Span::call_site(), "unexpected attribute argument");
|
||||||
..
|
continue;
|
||||||
})) => {
|
|
||||||
if is_ident_check_dup(&path, &package_name, "name") {
|
|
||||||
package_name = Some(expand_env_vars(&litstr)?);
|
|
||||||
} else if is_ident_check_dup(&path, &file_name, "file") {
|
|
||||||
file_name = Some(expand_env_vars(&litstr)?);
|
|
||||||
} else if is_ident_check_dup(&path, &lib_name, "lib") {
|
|
||||||
lib_name = Some(expand_env_vars(&litstr)?);
|
|
||||||
} else if is_ident_check_dup(&path, &boot, "boot") {
|
|
||||||
boot = Some(litstr.parse::<syn::Path>()?);
|
|
||||||
} else {
|
|
||||||
error!(path => "unknown argument");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
syn::NestedMeta::Meta(syn::Meta::NameValue(syn::MetaNameValue {
|
};
|
||||||
path,
|
|
||||||
lit: syn::Lit::Bool(litbool),
|
if is_ident_check_dup(&path, &package_name, "name") {
|
||||||
..
|
let Some(litstr) = expect_lit_str(value) else { continue };
|
||||||
})) => {
|
package_name = Some(expand_env_vars(&litstr)?);
|
||||||
if is_ident_check_dup(&path, &write, "write") {
|
} else if is_ident_check_dup(&path, &file_name, "file") {
|
||||||
write = Some(litbool.value());
|
let Some(litstr) = expect_lit_str(value) else { continue };
|
||||||
} else {
|
file_name = Some(expand_env_vars(&litstr)?);
|
||||||
error!(path => "unknown argument");
|
} else if is_ident_check_dup(&path, &lib_name, "lib") {
|
||||||
}
|
let Some(litstr) = expect_lit_str(value) else { continue };
|
||||||
}
|
lib_name = Some(expand_env_vars(&litstr)?);
|
||||||
_ => error!(Span::call_site(), "unexpected attribute argument"),
|
} else if is_ident_check_dup(&path, &boot, "boot") {
|
||||||
|
let Some(litstr) = expect_lit_str(value) else { continue };
|
||||||
|
boot = Some(litstr.parse::<syn::Path>()?);
|
||||||
|
} else if is_ident_check_dup(&path, &write, "write") {
|
||||||
|
let Some(litbool) = expect_lit_bool(value) else { continue };
|
||||||
|
write = Some(litbool.value());
|
||||||
|
} else {
|
||||||
|
error!(path => "unknown argument");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,19 +132,16 @@ pub struct FunctionAttrs {
|
|||||||
pub errno: bool,
|
pub errno: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<AttributeArgs> for FunctionAttrs {
|
impl TryFrom<Punctuated<Meta, Token![,]>> for FunctionAttrs {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn try_from(args: AttributeArgs) -> Result<Self, Self::Error> {
|
fn try_from(args: Punctuated<Meta, Token![,]>) -> Result<Self, Self::Error> {
|
||||||
let mut attrs = FunctionAttrs::default();
|
let mut attrs = FunctionAttrs::default();
|
||||||
|
|
||||||
for arg in args {
|
for arg in args {
|
||||||
match arg {
|
match arg {
|
||||||
syn::NestedMeta::Meta(syn::Meta::NameValue(syn::MetaNameValue {
|
syn::Meta::NameValue(syn::MetaNameValue { path, value, .. }) => {
|
||||||
path,
|
let Some(litstr) = expect_lit_str(value) else { continue };
|
||||||
lit: syn::Lit::Str(litstr),
|
|
||||||
..
|
|
||||||
})) => {
|
|
||||||
if is_ident_check_dup(&path, &attrs.xs_name, "xs_name") {
|
if is_ident_check_dup(&path, &attrs.xs_name, "xs_name") {
|
||||||
attrs.xs_name = Some(Ident::new(&litstr.value(), litstr.span()));
|
attrs.xs_name = Some(Ident::new(&litstr.value(), litstr.span()));
|
||||||
} else if is_ident_check_dup(&path, &attrs.perl_name, "name") {
|
} else if is_ident_check_dup(&path, &attrs.perl_name, "name") {
|
||||||
@ -161,7 +153,7 @@ impl TryFrom<AttributeArgs> for FunctionAttrs {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
syn::NestedMeta::Meta(syn::Meta::Path(path)) => {
|
syn::Meta::Path(path) => {
|
||||||
if path.is_ident("raw_return") {
|
if path.is_ident("raw_return") {
|
||||||
attrs.raw_return = true;
|
attrs.raw_return = true;
|
||||||
} else if path.is_ident("serialize_error") {
|
} else if path.is_ident("serialize_error") {
|
||||||
@ -179,3 +171,29 @@ impl TryFrom<AttributeArgs> for FunctionAttrs {
|
|||||||
Ok(attrs)
|
Ok(attrs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expect_lit_str(value: syn::Expr) -> Option<syn::LitStr> {
|
||||||
|
match value {
|
||||||
|
syn::Expr::Lit(syn::ExprLit {
|
||||||
|
lit: syn::Lit::Str(lit),
|
||||||
|
..
|
||||||
|
}) => Some(lit),
|
||||||
|
_ => {
|
||||||
|
error!(value => "value must be a literal string");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expect_lit_bool(value: syn::Expr) -> Option<syn::LitBool> {
|
||||||
|
match value {
|
||||||
|
syn::Expr::Lit(syn::ExprLit {
|
||||||
|
lit: syn::Lit::Bool(lit),
|
||||||
|
..
|
||||||
|
}) => Some(lit),
|
||||||
|
_ => {
|
||||||
|
error!(value => "value must be a literal boolean");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,7 +2,7 @@ use proc_macro2::{Ident, Span, TokenStream};
|
|||||||
|
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
use syn::Error;
|
use syn::{Error, Meta};
|
||||||
|
|
||||||
use crate::attribs::FunctionAttrs;
|
use crate::attribs::FunctionAttrs;
|
||||||
|
|
||||||
@ -41,6 +41,17 @@ impl ArgumentAttrs {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_attr(&mut self, attr: &syn::Attribute) -> bool {
|
||||||
|
if self.handle_path(attr.path()) {
|
||||||
|
if !matches!(attr.meta, Meta::Path(_)) {
|
||||||
|
error!(&attr.meta => "attribute does not take any value or parameter");
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn validate(&self, span: Span) -> Result<(), Error> {
|
fn validate(&self, span: Span) -> Result<(), Error> {
|
||||||
if self.raw as usize + self.try_from_ref as usize + self.cv.is_some() as usize > 1 {
|
if self.raw as usize + self.try_from_ref as usize + self.cv.is_some() as usize > 1 {
|
||||||
bail!(
|
bail!(
|
||||||
@ -104,8 +115,7 @@ pub fn handle_function(
|
|||||||
let pat_ty = match arg {
|
let pat_ty = match arg {
|
||||||
syn::FnArg::Receiver(_) => bail!(arg => "cannot export self-taking methods as xsubs"),
|
syn::FnArg::Receiver(_) => bail!(arg => "cannot export self-taking methods as xsubs"),
|
||||||
syn::FnArg::Typed(ref mut pt) => {
|
syn::FnArg::Typed(ref mut pt) => {
|
||||||
pt.attrs
|
pt.attrs.retain(|attr| !argument_attrs.handle_attr(&attr));
|
||||||
.retain(|attr| !argument_attrs.handle_path(&attr.path));
|
|
||||||
argument_attrs.validate(pt.span())?;
|
argument_attrs.validate(pt.span())?;
|
||||||
&*pt
|
&*pt
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,9 @@ use std::cell::RefCell;
|
|||||||
use proc_macro::TokenStream as TokenStream_1;
|
use proc_macro::TokenStream as TokenStream_1;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
|
|
||||||
use syn::parse_macro_input;
|
use syn::parse::Parser;
|
||||||
use syn::AttributeArgs;
|
use syn::punctuated::Punctuated;
|
||||||
use syn::Error;
|
use syn::{Error, Meta, Token};
|
||||||
|
|
||||||
macro_rules! format_err {
|
macro_rules! format_err {
|
||||||
($span:expr => $($msg:tt)*) => { Error::new_spanned($span, format!($($msg)*)) };
|
($span:expr => $($msg:tt)*) => { Error::new_spanned($span, format!($($msg)*)) };
|
||||||
@ -86,7 +86,6 @@ pub(crate) fn pthx_param() -> TokenStream {
|
|||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn package(attr: TokenStream_1, item: TokenStream_1) -> TokenStream_1 {
|
pub fn package(attr: TokenStream_1, item: TokenStream_1) -> TokenStream_1 {
|
||||||
let _error_guard = init_local_error();
|
let _error_guard = init_local_error();
|
||||||
let attr = parse_macro_input!(attr as AttributeArgs);
|
|
||||||
let item: TokenStream = item.into();
|
let item: TokenStream = item.into();
|
||||||
handle_error(perlmod_impl(attr, item)).into()
|
handle_error(perlmod_impl(attr, item)).into()
|
||||||
}
|
}
|
||||||
@ -96,12 +95,12 @@ pub fn package(attr: TokenStream_1, item: TokenStream_1) -> TokenStream_1 {
|
|||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn export(attr: TokenStream_1, item: TokenStream_1) -> TokenStream_1 {
|
pub fn export(attr: TokenStream_1, item: TokenStream_1) -> TokenStream_1 {
|
||||||
let _error_guard = init_local_error();
|
let _error_guard = init_local_error();
|
||||||
let attr = parse_macro_input!(attr as AttributeArgs);
|
|
||||||
let item: TokenStream = item.into();
|
let item: TokenStream = item.into();
|
||||||
handle_error(export_impl(attr, item)).into()
|
handle_error(export_impl(attr, item)).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn perlmod_impl(attr: AttributeArgs, item: TokenStream) -> Result<TokenStream, Error> {
|
fn perlmod_impl(attr: TokenStream_1, item: TokenStream) -> Result<TokenStream, Error> {
|
||||||
|
let attr = Punctuated::<Meta, Token![,]>::parse_terminated.parse(attr)?;
|
||||||
let item: syn::Item = syn::parse2(item)?;
|
let item: syn::Item = syn::parse2(item)?;
|
||||||
|
|
||||||
match item {
|
match item {
|
||||||
@ -111,7 +110,8 @@ fn perlmod_impl(attr: AttributeArgs, item: TokenStream) -> Result<TokenStream, E
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn export_impl(attr: AttributeArgs, item: TokenStream) -> Result<TokenStream, Error> {
|
fn export_impl(attr: TokenStream_1, item: TokenStream) -> Result<TokenStream, Error> {
|
||||||
|
let attr = Punctuated::<Meta, Token![,]>::parse_terminated.parse(attr)?;
|
||||||
let func: syn::ItemFn = syn::parse2(item)?;
|
let func: syn::ItemFn = syn::parse2(item)?;
|
||||||
|
|
||||||
let attr = attribs::FunctionAttrs::try_from(attr)?;
|
let attr = attribs::FunctionAttrs::try_from(attr)?;
|
||||||
|
@ -2,13 +2,15 @@ use proc_macro2::TokenStream;
|
|||||||
|
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::punctuated::Punctuated;
|
use syn::punctuated::Punctuated;
|
||||||
use syn::Error;
|
use syn::{Error, Meta, Token};
|
||||||
use syn::{AttributeArgs, Token};
|
|
||||||
|
|
||||||
use crate::attribs::FunctionAttrs;
|
use crate::attribs::FunctionAttrs;
|
||||||
use crate::package::Package;
|
use crate::package::Package;
|
||||||
|
|
||||||
pub fn handle_module(attr: AttributeArgs, mut module: syn::ItemMod) -> Result<TokenStream, Error> {
|
pub fn handle_module(
|
||||||
|
attr: Punctuated<Meta, Token![,]>,
|
||||||
|
mut module: syn::ItemMod,
|
||||||
|
) -> Result<TokenStream, Error> {
|
||||||
let mut package = Package::with_attrs(attr)?;
|
let mut package = Package::with_attrs(attr)?;
|
||||||
let mangled_package_name = package.mangle_package_name();
|
let mangled_package_name = package.mangle_package_name();
|
||||||
|
|
||||||
@ -18,27 +20,28 @@ pub fn handle_module(attr: AttributeArgs, mut module: syn::ItemMod) -> Result<To
|
|||||||
syn::Item::Fn(mut func) => {
|
syn::Item::Fn(mut func) => {
|
||||||
let mut attribs = None;
|
let mut attribs = None;
|
||||||
for attr in std::mem::take(&mut func.attrs) {
|
for attr in std::mem::take(&mut func.attrs) {
|
||||||
if attr.path.is_ident("export") {
|
if !attr.path().is_ident("export") {
|
||||||
if attribs.is_some() {
|
|
||||||
error!(attr => "multiple 'export' attributes not allowed");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let args: AttributeArgs = if attr.tokens.is_empty() {
|
|
||||||
Default::default()
|
|
||||||
} else {
|
|
||||||
attr.parse_args_with(
|
|
||||||
Punctuated::<syn::NestedMeta, Token![,]>::parse_terminated,
|
|
||||||
)?
|
|
||||||
.into_iter()
|
|
||||||
.collect()
|
|
||||||
};
|
|
||||||
|
|
||||||
attribs = Some(FunctionAttrs::try_from(args)?);
|
|
||||||
} else {
|
|
||||||
// retain the attribute
|
// retain the attribute
|
||||||
func.attrs.push(attr);
|
func.attrs.push(attr);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
if attribs.is_some() {
|
||||||
|
error!(attr => "multiple 'export' attributes not allowed");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let args = match attr.meta {
|
||||||
|
Meta::Path(_) => Default::default(),
|
||||||
|
Meta::List(list) => list.parse_args_with(
|
||||||
|
Punctuated::<syn::Meta, Token![,]>::parse_terminated,
|
||||||
|
)?,
|
||||||
|
_ => {
|
||||||
|
error!(attr => "invalid 'export' attribute syntax");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
attribs = Some(FunctionAttrs::try_from(args)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we removed an #[export] macro this is an exported function:
|
// if we removed an #[export] macro this is an exported function:
|
||||||
|
@ -3,8 +3,8 @@ use std::env;
|
|||||||
use proc_macro2::{Ident, Span, TokenStream};
|
use proc_macro2::{Ident, Span, TokenStream};
|
||||||
|
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::AttributeArgs;
|
use syn::punctuated::Punctuated;
|
||||||
use syn::Error;
|
use syn::{Error, Meta, Token};
|
||||||
|
|
||||||
use crate::attribs::ModuleAttrs;
|
use crate::attribs::ModuleAttrs;
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ pub struct Package {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Package {
|
impl Package {
|
||||||
pub fn with_attrs(attr: AttributeArgs) -> Result<Self, Error> {
|
pub fn with_attrs(attr: Punctuated<Meta, Token![,]>) -> Result<Self, Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
attrs: ModuleAttrs::try_from(attr)?,
|
attrs: ModuleAttrs::try_from(attr)?,
|
||||||
exported: Vec::new(),
|
exported: Vec::new(),
|
||||||
|
Loading…
Reference in New Issue
Block a user