mirror of
https://codeberg.org/icewind/tf-log-parser.git
synced 2026-06-03 10:14:10 +02:00
syn2 + structmeta
This commit is contained in:
parent
8b94c0d515
commit
a6b5e67ce8
4 changed files with 64 additions and 23 deletions
|
|
@ -8,10 +8,10 @@ name = "tf_log_parser_derive"
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
syn = "1.0"
|
syn = "2.0.12"
|
||||||
quote = "1.0"
|
quote = "1.0.26"
|
||||||
proc-macro2 = "1.0"
|
proc-macro2 = "1.0.54"
|
||||||
syn_util = "0.4"
|
structmeta = "0.2.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tf-log-parser = { version = "0.1", path = ".." }
|
tf-log-parser = { version = "0.1", path = ".." }
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
use crate::{err, Derivable, DeriveParams};
|
use crate::{err, Derivable, DeriveParams};
|
||||||
use proc_macro2::{Ident, Span, TokenStream};
|
use proc_macro2::{Ident, Span, TokenStream};
|
||||||
use quote::{quote, quote_spanned};
|
use quote::{quote, quote_spanned};
|
||||||
|
use structmeta::StructMeta;
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
use syn::{Data, DeriveInput, Field, Fields, Generics, Lifetime, Result, Type, TypePath};
|
use syn::{
|
||||||
use syn_util::{contains_attribute, get_attribute_value};
|
Attribute, Data, DeriveInput, Field, Fields, Generics, Lifetime, LitBool, LitInt, LitStr,
|
||||||
|
Result, Type, TypePath,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct Event;
|
pub struct Event;
|
||||||
|
|
||||||
|
|
@ -107,7 +110,6 @@ impl Derivable for Event {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct EventParams {
|
pub struct EventParams {
|
||||||
name: Ident,
|
name: Ident,
|
||||||
lifetime: Lifetime,
|
lifetime: Lifetime,
|
||||||
|
|
@ -117,6 +119,7 @@ pub struct EventParams {
|
||||||
|
|
||||||
impl DeriveParams for EventParams {
|
impl DeriveParams for EventParams {
|
||||||
fn parse(input: &DeriveInput) -> Result<EventParams> {
|
fn parse(input: &DeriveInput) -> Result<EventParams> {
|
||||||
|
let attrs: EventAttr = parse_attrs(&input.attrs);
|
||||||
let Data::Struct(data) = &input.data else {
|
let Data::Struct(data) = &input.data else {
|
||||||
return err("only supported on structs", input);
|
return err("only supported on structs", input);
|
||||||
};
|
};
|
||||||
|
|
@ -142,10 +145,8 @@ impl DeriveParams for EventParams {
|
||||||
last_optional = param.optional;
|
last_optional = param.optional;
|
||||||
}
|
}
|
||||||
|
|
||||||
let lifetime = if let Some(lifetime) =
|
let lifetime = if let Some(lifetime) = attrs.lifetime {
|
||||||
get_attribute_value::<String>(&input.attrs, &["event", "lifetime"])
|
lifetime
|
||||||
{
|
|
||||||
Lifetime::new(&lifetime, name.span())
|
|
||||||
} else {
|
} else {
|
||||||
let mut lifetimes = input.generics.lifetimes().cloned();
|
let mut lifetimes = input.generics.lifetimes().cloned();
|
||||||
let lifetime = lifetimes
|
let lifetime = lifetimes
|
||||||
|
|
@ -167,7 +168,6 @@ impl DeriveParams for EventParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct EventParam {
|
pub struct EventParam {
|
||||||
span: Span,
|
span: Span,
|
||||||
field_name: Ident,
|
field_name: Ident,
|
||||||
|
|
@ -180,12 +180,15 @@ pub struct EventParam {
|
||||||
|
|
||||||
impl EventParam {
|
impl EventParam {
|
||||||
pub fn parse(input: &Field) -> Result<EventParam> {
|
pub fn parse(input: &Field) -> Result<EventParam> {
|
||||||
|
let attrs: EventAttr = parse_attrs(&input.attrs);
|
||||||
let field_name = input.ident.clone().expect("no name on named fields");
|
let field_name = input.ident.clone().expect("no name on named fields");
|
||||||
let param_name = if contains_attribute(&input.attrs, &["event", "unnamed"]) {
|
let param_name = if attrs.unnamed {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(
|
Some(
|
||||||
get_attribute_value(&input.attrs, &["event", "name"])
|
attrs
|
||||||
|
.name
|
||||||
|
.map(|lit| lit.value())
|
||||||
.unwrap_or_else(|| field_name.to_string()),
|
.unwrap_or_else(|| field_name.to_string()),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
@ -199,16 +202,20 @@ impl EventParam {
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
let optional = is_option || contains_attribute(&input.attrs, &["event", "default"]);
|
let optional = is_option || attrs.default;
|
||||||
let skip_after =
|
let skip_after = attrs
|
||||||
get_attribute_value(&input.attrs, &["event", "skip_after"]).unwrap_or_default();
|
.skip_after
|
||||||
|
.and_then(|lit| lit.base10_parse().ok())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
if optional && skip_after > 0 {
|
if optional && skip_after > 0 {
|
||||||
return err("skip_after can't be used with optional fields", input);
|
return err("skip_after can't be used with optional fields", input);
|
||||||
}
|
}
|
||||||
let quoted =
|
let quoted = attrs
|
||||||
get_attribute_value(&input.attrs, &["event", "quoted"]).unwrap_or(param_name.is_none());
|
.quoted
|
||||||
let subject = contains_attribute(&input.attrs, &["event", "subject"]);
|
.map(|lit| lit.value)
|
||||||
|
.unwrap_or(param_name.is_none());
|
||||||
|
let subject = attrs.subject;
|
||||||
|
|
||||||
Ok(EventParam {
|
Ok(EventParam {
|
||||||
span: input.span(),
|
span: input.span(),
|
||||||
|
|
@ -253,3 +260,38 @@ impl EventParam {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_attrs(attrs: &[Attribute]) -> EventAttr {
|
||||||
|
let mut result = EventAttr::default();
|
||||||
|
for attr in attrs {
|
||||||
|
if let Ok(parsed) = attr.parse_args() {
|
||||||
|
result = result.merge(parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, StructMeta)]
|
||||||
|
struct EventAttr {
|
||||||
|
quoted: Option<LitBool>,
|
||||||
|
subject: bool,
|
||||||
|
default: bool,
|
||||||
|
unnamed: bool,
|
||||||
|
skip_after: Option<LitInt>,
|
||||||
|
name: Option<LitStr>,
|
||||||
|
lifetime: Option<Lifetime>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventAttr {
|
||||||
|
fn merge(self, other: Self) -> Self {
|
||||||
|
Self {
|
||||||
|
quoted: self.quoted.or(other.quoted),
|
||||||
|
subject: self.subject || other.subject,
|
||||||
|
default: self.default || other.default,
|
||||||
|
unnamed: self.unnamed || other.unnamed,
|
||||||
|
skip_after: self.skip_after.or(other.skip_after),
|
||||||
|
name: self.name.or(other.name),
|
||||||
|
lifetime: self.lifetime.or(other.lifetime),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@ impl Derivable for Events {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct EventsParam {
|
pub struct EventsParam {
|
||||||
name: Ident,
|
name: Ident,
|
||||||
generics: Generics,
|
generics: Generics,
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use crate::event::Event;
|
||||||
use crate::events::Events;
|
use crate::events::Events;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
use std::fmt::{Debug, Display};
|
use std::fmt::Display;
|
||||||
use syn::{parse_macro_input, DeriveInput, Error, Result};
|
use syn::{parse_macro_input, DeriveInput, Error, Result};
|
||||||
|
|
||||||
/// Derive the `Event` trait for a struct
|
/// Derive the `Event` trait for a struct
|
||||||
|
|
@ -44,7 +44,7 @@ trait Derivable {
|
||||||
fn derive(params: Self::Params) -> Result<TokenStream>;
|
fn derive(params: Self::Params) -> Result<TokenStream>;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait DeriveParams: Sized + Debug {
|
trait DeriveParams: Sized {
|
||||||
fn parse(input: &DeriveInput) -> Result<Self>;
|
fn parse(input: &DeriveInput) -> Result<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue