mirror of
https://github.com/bevyengine/bevy
synced 2024-11-24 21:53:07 +00:00
update syn, encase, glam and hexasphere (#8573)
# Objective - Fixes #8282 - Update `syn` to 2.0, `encase` to 0.6, `glam` to 0.24 and `hexasphere` to 9.0 Blocked ~~on https://github.com/teoxoy/encase/pull/42~~ and ~~on https://github.com/OptimisticPeach/hexasphere/pull/17~~ --------- Co-authored-by: Nicola Papale <nicopap@users.noreply.github.com> Co-authored-by: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
This commit is contained in:
parent
6b0986a6e8
commit
0736195a1e
25 changed files with 250 additions and 284 deletions
|
@ -7,7 +7,7 @@ publish = false
|
|||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[dev-dependencies]
|
||||
glam = "0.23"
|
||||
glam = "0.24"
|
||||
rand = "0.8"
|
||||
rand_chacha = "0.3"
|
||||
criterion = { version = "0.3", features = ["html_reports"] }
|
||||
|
|
|
@ -15,4 +15,4 @@ proc-macro = true
|
|||
bevy_macro_utils = { path = "../bevy_macro_utils", version = "0.11.0-dev" }
|
||||
|
||||
quote = "1.0"
|
||||
syn = { version = "1.0", features = ["full"] }
|
||||
syn = { version = "2.0", features = ["full"] }
|
||||
|
|
|
@ -11,6 +11,6 @@ proc-macro = true
|
|||
[dependencies]
|
||||
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.11.0-dev" }
|
||||
|
||||
syn = "1.0"
|
||||
syn = "2.0"
|
||||
quote = "1.0"
|
||||
proc-macro2 = "1.0"
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use bevy_macro_utils::{get_lit_str, Symbol};
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::{Span, TokenStream as TokenStream2};
|
||||
use quote::{quote, ToTokens};
|
||||
use syn::{parse_macro_input, parse_quote, DeriveInput, Error, Ident, Path, Result};
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, parse_quote, DeriveInput, Ident, LitStr, Path, Result};
|
||||
|
||||
pub fn derive_resource(input: TokenStream) -> TokenStream {
|
||||
let mut ast = parse_macro_input!(input as DeriveInput);
|
||||
|
@ -48,8 +47,8 @@ pub fn derive_component(input: TokenStream) -> TokenStream {
|
|||
})
|
||||
}
|
||||
|
||||
pub const COMPONENT: Symbol = Symbol("component");
|
||||
pub const STORAGE: Symbol = Symbol("storage");
|
||||
pub const COMPONENT: &str = "component";
|
||||
pub const STORAGE: &str = "storage";
|
||||
|
||||
struct Attrs {
|
||||
storage: StorageTy,
|
||||
|
@ -66,48 +65,27 @@ const TABLE: &str = "Table";
|
|||
const SPARSE_SET: &str = "SparseSet";
|
||||
|
||||
fn parse_component_attr(ast: &DeriveInput) -> Result<Attrs> {
|
||||
let meta_items = bevy_macro_utils::parse_attrs(ast, COMPONENT)?;
|
||||
|
||||
let mut attrs = Attrs {
|
||||
storage: StorageTy::Table,
|
||||
};
|
||||
|
||||
for meta in meta_items {
|
||||
use syn::{
|
||||
Meta::NameValue,
|
||||
NestedMeta::{Lit, Meta},
|
||||
};
|
||||
match meta {
|
||||
Meta(NameValue(m)) if m.path == STORAGE => {
|
||||
attrs.storage = match get_lit_str(STORAGE, &m.lit)?.value().as_str() {
|
||||
TABLE => StorageTy::Table,
|
||||
SPARSE_SET => StorageTy::SparseSet,
|
||||
for meta in ast.attrs.iter().filter(|a| a.path().is_ident(COMPONENT)) {
|
||||
meta.parse_nested_meta(|nested| {
|
||||
if nested.path.is_ident(STORAGE) {
|
||||
attrs.storage = match nested.value()?.parse::<LitStr>()?.value() {
|
||||
s if s == TABLE => StorageTy::Table,
|
||||
s if s == SPARSE_SET => StorageTy::SparseSet,
|
||||
s => {
|
||||
return Err(Error::new_spanned(
|
||||
m.lit,
|
||||
format!(
|
||||
"Invalid storage type `{s}`, expected '{TABLE}' or '{SPARSE_SET}'.",
|
||||
),
|
||||
))
|
||||
return Err(nested.error(format!(
|
||||
"Invalid storage type `{s}`, expected '{TABLE}' or '{SPARSE_SET}'.",
|
||||
)));
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
} else {
|
||||
Err(nested.error("Unsuported attribute"))
|
||||
}
|
||||
Meta(meta_item) => {
|
||||
return Err(Error::new_spanned(
|
||||
meta_item.path(),
|
||||
format!(
|
||||
"unknown component attribute `{}`",
|
||||
meta_item.path().into_token_stream()
|
||||
),
|
||||
));
|
||||
}
|
||||
Lit(lit) => {
|
||||
return Err(Error::new_spanned(
|
||||
lit,
|
||||
"unexpected literal in component attribute",
|
||||
))
|
||||
}
|
||||
}
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(attrs)
|
||||
|
|
|
@ -6,7 +6,8 @@ use syn::{
|
|||
parse::{Parse, ParseStream},
|
||||
parse_macro_input, parse_quote,
|
||||
punctuated::Punctuated,
|
||||
Attribute, Data, DataStruct, DeriveInput, Field, Index,
|
||||
token::Comma,
|
||||
Attribute, Data, DataStruct, DeriveInput, Field, Index, Meta,
|
||||
};
|
||||
|
||||
use crate::bevy_ecs_path;
|
||||
|
@ -14,7 +15,7 @@ use crate::bevy_ecs_path;
|
|||
#[derive(Default)]
|
||||
struct FetchStructAttributes {
|
||||
pub is_mutable: bool,
|
||||
pub derive_args: Punctuated<syn::NestedMeta, syn::token::Comma>,
|
||||
pub derive_args: Punctuated<syn::Meta, syn::token::Comma>,
|
||||
}
|
||||
|
||||
static MUTABLE_ATTRIBUTE_NAME: &str = "mutable";
|
||||
|
@ -35,7 +36,7 @@ pub fn derive_world_query_impl(input: TokenStream) -> TokenStream {
|
|||
let mut fetch_struct_attributes = FetchStructAttributes::default();
|
||||
for attr in &ast.attrs {
|
||||
if !attr
|
||||
.path
|
||||
.path()
|
||||
.get_ident()
|
||||
.map_or(false, |ident| ident == WORLD_QUERY_ATTRIBUTE_NAME)
|
||||
{
|
||||
|
@ -43,7 +44,7 @@ pub fn derive_world_query_impl(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
|
||||
attr.parse_args_with(|input: ParseStream| {
|
||||
let meta = input.parse_terminated::<syn::Meta, syn::token::Comma>(syn::Meta::parse)?;
|
||||
let meta = input.parse_terminated(syn::Meta::parse, Comma)?;
|
||||
for meta in meta {
|
||||
let ident = meta.path().get_ident().unwrap_or_else(|| {
|
||||
panic!(
|
||||
|
@ -61,9 +62,10 @@ pub fn derive_world_query_impl(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
} else if ident == DERIVE_ATTRIBUTE_NAME {
|
||||
if let syn::Meta::List(meta_list) = meta {
|
||||
fetch_struct_attributes
|
||||
.derive_args
|
||||
.extend(meta_list.nested.iter().cloned());
|
||||
meta_list.parse_nested_meta(|meta| {
|
||||
fetch_struct_attributes.derive_args.push(Meta::Path(meta.path));
|
||||
Ok(())
|
||||
})?;
|
||||
} else {
|
||||
panic!(
|
||||
"Expected a structured list within the `{DERIVE_ATTRIBUTE_NAME}` attribute",
|
||||
|
@ -463,7 +465,7 @@ fn read_world_query_field_info(field: &Field) -> syn::Result<WorldQueryFieldInfo
|
|||
let mut attrs = Vec::new();
|
||||
for attr in &field.attrs {
|
||||
if attr
|
||||
.path
|
||||
.path()
|
||||
.get_ident()
|
||||
.map_or(false, |ident| ident == WORLD_QUERY_ATTRIBUTE_NAME)
|
||||
{
|
||||
|
|
|
@ -13,8 +13,8 @@ use proc_macro::TokenStream;
|
|||
use proc_macro2::Span;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{
|
||||
parse_macro_input, parse_quote, punctuated::Punctuated, spanned::Spanned, ConstParam,
|
||||
DeriveInput, GenericParam, Ident, Index, Meta, MetaList, NestedMeta, Token, TypeParam,
|
||||
parse_macro_input, parse_quote, punctuated::Punctuated, spanned::Spanned, token::Comma,
|
||||
ConstParam, DeriveInput, GenericParam, Ident, Index, TypeParam,
|
||||
};
|
||||
|
||||
enum BundleFieldKind {
|
||||
|
@ -37,28 +37,23 @@ pub fn derive_bundle(input: TokenStream) -> TokenStream {
|
|||
|
||||
let mut field_kind = Vec::with_capacity(named_fields.len());
|
||||
|
||||
'field_loop: for field in named_fields.iter() {
|
||||
for attr in &field.attrs {
|
||||
if attr.path.is_ident(BUNDLE_ATTRIBUTE_NAME) {
|
||||
if let Ok(Meta::List(MetaList { nested, .. })) = attr.parse_meta() {
|
||||
if let Some(&NestedMeta::Meta(Meta::Path(ref path))) = nested.first() {
|
||||
if path.is_ident(BUNDLE_ATTRIBUTE_IGNORE_NAME) {
|
||||
field_kind.push(BundleFieldKind::Ignore);
|
||||
continue 'field_loop;
|
||||
}
|
||||
|
||||
return syn::Error::new(
|
||||
path.span(),
|
||||
format!(
|
||||
"Invalid bundle attribute. Use `{BUNDLE_ATTRIBUTE_IGNORE_NAME}`"
|
||||
),
|
||||
)
|
||||
.into_compile_error()
|
||||
.into();
|
||||
}
|
||||
|
||||
return syn::Error::new(attr.span(), format!("Invalid bundle attribute. Use `#[{BUNDLE_ATTRIBUTE_NAME}({BUNDLE_ATTRIBUTE_IGNORE_NAME})]`")).into_compile_error().into();
|
||||
for field in named_fields.iter() {
|
||||
for attr in field
|
||||
.attrs
|
||||
.iter()
|
||||
.filter(|a| a.path().is_ident(BUNDLE_ATTRIBUTE_NAME))
|
||||
{
|
||||
if let Err(error) = attr.parse_nested_meta(|meta| {
|
||||
if meta.path.is_ident(BUNDLE_ATTRIBUTE_IGNORE_NAME) {
|
||||
field_kind.push(BundleFieldKind::Ignore);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(meta.error(format!(
|
||||
"Invalid bundle attribute. Use `{BUNDLE_ATTRIBUTE_IGNORE_NAME}`"
|
||||
)))
|
||||
}
|
||||
}) {
|
||||
return error.into_compile_error().into();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -308,7 +303,7 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
|
|||
|
||||
let shadowed_lifetimes: Vec<_> = generics.lifetimes().map(|_| quote!('_)).collect();
|
||||
|
||||
let mut punctuated_generics = Punctuated::<_, Token![,]>::new();
|
||||
let mut punctuated_generics = Punctuated::<_, Comma>::new();
|
||||
punctuated_generics.extend(lifetimeless_generics.iter().map(|g| match g {
|
||||
GenericParam::Type(g) => GenericParam::Type(TypeParam {
|
||||
default: None,
|
||||
|
@ -321,14 +316,14 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
|
|||
_ => unreachable!(),
|
||||
}));
|
||||
|
||||
let mut punctuated_generic_idents = Punctuated::<_, Token![,]>::new();
|
||||
let mut punctuated_generic_idents = Punctuated::<_, Comma>::new();
|
||||
punctuated_generic_idents.extend(lifetimeless_generics.iter().map(|g| match g {
|
||||
GenericParam::Type(g) => &g.ident,
|
||||
GenericParam::Const(g) => &g.ident,
|
||||
_ => unreachable!(),
|
||||
}));
|
||||
|
||||
let punctuated_generics_no_bounds: Punctuated<_, Token![,]> = lifetimeless_generics
|
||||
let punctuated_generics_no_bounds: Punctuated<_, Comma> = lifetimeless_generics
|
||||
.iter()
|
||||
.map(|&g| match g.clone() {
|
||||
GenericParam::Type(mut g) => {
|
||||
|
|
|
@ -13,4 +13,4 @@ proc-macro = true
|
|||
|
||||
[dependencies]
|
||||
bevy_macro_utils = { path = "../bevy_macro_utils", version = "0.11.0-dev" }
|
||||
encase_derive_impl = "0.5.0"
|
||||
encase_derive_impl = "0.6.1"
|
||||
|
|
|
@ -10,6 +10,6 @@ keywords = ["bevy"]
|
|||
|
||||
[dependencies]
|
||||
toml_edit = "0.19"
|
||||
syn = "1.0"
|
||||
syn = "2.0"
|
||||
quote = "1.0"
|
||||
rustc-hash = "1.0"
|
||||
|
|
|
@ -1,41 +1,32 @@
|
|||
use syn::DeriveInput;
|
||||
use syn::{Expr, ExprLit, Lit};
|
||||
|
||||
use crate::symbol::Symbol;
|
||||
|
||||
pub fn parse_attrs(ast: &DeriveInput, attr_name: Symbol) -> syn::Result<Vec<syn::NestedMeta>> {
|
||||
let mut list = Vec::new();
|
||||
for attr in ast.attrs.iter().filter(|a| a.path == attr_name) {
|
||||
match attr.parse_meta()? {
|
||||
syn::Meta::List(meta) => list.extend(meta.nested.into_iter()),
|
||||
other => {
|
||||
return Err(syn::Error::new_spanned(
|
||||
other,
|
||||
format!("expected #[{attr_name}(...)]"),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(list)
|
||||
}
|
||||
|
||||
pub fn get_lit_str(attr_name: Symbol, lit: &syn::Lit) -> syn::Result<&syn::LitStr> {
|
||||
if let syn::Lit::Str(lit) = lit {
|
||||
pub fn get_lit_str(attr_name: Symbol, value: &Expr) -> syn::Result<&syn::LitStr> {
|
||||
if let Expr::Lit(ExprLit {
|
||||
lit: Lit::Str(lit), ..
|
||||
}) = &value
|
||||
{
|
||||
Ok(lit)
|
||||
} else {
|
||||
Err(syn::Error::new_spanned(
|
||||
lit,
|
||||
value,
|
||||
format!("expected {attr_name} attribute to be a string: `{attr_name} = \"...\"`"),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_lit_bool(attr_name: Symbol, lit: &syn::Lit) -> syn::Result<bool> {
|
||||
if let syn::Lit::Bool(lit) = lit {
|
||||
pub fn get_lit_bool(attr_name: Symbol, value: &Expr) -> syn::Result<bool> {
|
||||
if let Expr::Lit(ExprLit {
|
||||
lit: Lit::Bool(lit),
|
||||
..
|
||||
}) = &value
|
||||
{
|
||||
Ok(lit.value())
|
||||
} else {
|
||||
Err(syn::Error::new_spanned(
|
||||
lit,
|
||||
value,
|
||||
format!("expected {attr_name} attribute to be a bool value, `true` or `false`: `{attr_name} = ...`"),
|
||||
))
|
||||
))?
|
||||
}
|
||||
}
|
||||
|
|
|
@ -214,7 +214,7 @@ pub fn derive_label(
|
|||
) -> TokenStream {
|
||||
// return true if the variant specified is an `ignore_fields` attribute
|
||||
fn is_ignore(attr: &syn::Attribute, attr_name: &str) -> bool {
|
||||
if attr.path.get_ident().as_ref().unwrap() != &attr_name {
|
||||
if attr.path().get_ident().as_ref().unwrap() != &attr_name {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0"
|
|||
keywords = ["bevy"]
|
||||
|
||||
[dependencies]
|
||||
glam = { version = "0.23", features = ["bytemuck"] }
|
||||
glam = { version = "0.24", features = ["bytemuck"] }
|
||||
serde = { version = "1", features = ["derive"], optional = true }
|
||||
|
||||
[features]
|
||||
|
|
|
@ -11,7 +11,7 @@ license = "Zlib AND (MIT OR Apache-2.0)"
|
|||
keywords = ["bevy", "3D", "graphics", "algorithm", "tangent"]
|
||||
|
||||
[dependencies]
|
||||
glam = "0.23"
|
||||
glam = "0.24"
|
||||
|
||||
[[example]]
|
||||
name = "generate"
|
||||
|
|
|
@ -31,7 +31,7 @@ thiserror = "1.0"
|
|||
once_cell = "1.11"
|
||||
serde = "1"
|
||||
smallvec = { version = "1.6", features = ["serde", "union", "const_generics"], optional = true }
|
||||
glam = { version = "0.23", features = ["serde"], optional = true }
|
||||
glam = { version = "0.24", features = ["serde"], optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
ron = "0.8.0"
|
||||
|
|
|
@ -19,7 +19,7 @@ documentation = []
|
|||
[dependencies]
|
||||
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.11.0-dev" }
|
||||
|
||||
syn = { version = "1.0", features = ["full"] }
|
||||
syn = { version = "2.0", features = ["full"] }
|
||||
proc-macro2 = "1.0"
|
||||
quote = "1.0"
|
||||
uuid = { version = "1.1", features = ["v4"] }
|
||||
|
|
|
@ -13,7 +13,7 @@ use syn::parse::{Parse, ParseStream};
|
|||
use syn::punctuated::Punctuated;
|
||||
use syn::spanned::Spanned;
|
||||
use syn::token::Comma;
|
||||
use syn::{Meta, NestedMeta, Path};
|
||||
use syn::{Meta, Path};
|
||||
|
||||
// The "special" trait idents that are used internally for reflection.
|
||||
// Received via attributes like `#[reflect(PartialEq, Hash, ...)]`
|
||||
|
@ -45,12 +45,16 @@ pub(crate) enum TraitImpl {
|
|||
impl TraitImpl {
|
||||
/// Merges this [`TraitImpl`] with another.
|
||||
///
|
||||
/// Returns whichever value is not [`TraitImpl::NotImplemented`].
|
||||
/// If both values are [`TraitImpl::NotImplemented`], then that is returned.
|
||||
/// Otherwise, an error is returned if neither value is [`TraitImpl::NotImplemented`].
|
||||
pub fn merge(self, other: TraitImpl) -> Result<TraitImpl, syn::Error> {
|
||||
match (self, other) {
|
||||
(TraitImpl::NotImplemented, value) | (value, TraitImpl::NotImplemented) => Ok(value),
|
||||
/// Update `self` with whichever value is not [`TraitImpl::NotImplemented`].
|
||||
/// If `other` is [`TraitImpl::NotImplemented`], then `self` is not modified.
|
||||
/// An error is returned if neither value is [`TraitImpl::NotImplemented`].
|
||||
pub fn merge(&mut self, other: TraitImpl) -> Result<(), syn::Error> {
|
||||
match (&self, other) {
|
||||
(TraitImpl::NotImplemented, value) => {
|
||||
*self = value;
|
||||
Ok(())
|
||||
}
|
||||
(_, TraitImpl::NotImplemented) => Ok(()),
|
||||
(_, TraitImpl::Implemented(span) | TraitImpl::Custom(_, span)) => {
|
||||
Err(syn::Error::new(span, CONFLICTING_TYPE_DATA_MESSAGE))
|
||||
}
|
||||
|
@ -128,15 +132,12 @@ pub(crate) struct ReflectTraits {
|
|||
}
|
||||
|
||||
impl ReflectTraits {
|
||||
/// Create a new [`ReflectTraits`] instance from a set of nested metas.
|
||||
pub fn from_nested_metas(
|
||||
nested_metas: &Punctuated<NestedMeta, Comma>,
|
||||
) -> Result<Self, syn::Error> {
|
||||
pub fn from_metas(metas: Punctuated<Meta, Comma>) -> Result<Self, syn::Error> {
|
||||
let mut traits = ReflectTraits::default();
|
||||
for nested_meta in nested_metas.iter() {
|
||||
match nested_meta {
|
||||
for meta in &metas {
|
||||
match meta {
|
||||
// Handles `#[reflect( Hash, Default, ... )]`
|
||||
NestedMeta::Meta(Meta::Path(path)) => {
|
||||
Meta::Path(path) => {
|
||||
// Get the first ident in the path (hopefully the path only contains one and not `std::hash::Hash`)
|
||||
let Some(segment) = path.segments.iter().next() else {
|
||||
continue;
|
||||
|
@ -149,14 +150,13 @@ impl ReflectTraits {
|
|||
|
||||
match ident_name.as_str() {
|
||||
DEBUG_ATTR => {
|
||||
traits.debug = traits.debug.merge(TraitImpl::Implemented(span))?;
|
||||
traits.debug.merge(TraitImpl::Implemented(span))?;
|
||||
}
|
||||
PARTIAL_EQ_ATTR => {
|
||||
traits.partial_eq =
|
||||
traits.partial_eq.merge(TraitImpl::Implemented(span))?;
|
||||
traits.partial_eq.merge(TraitImpl::Implemented(span))?;
|
||||
}
|
||||
HASH_ATTR => {
|
||||
traits.hash = traits.hash.merge(TraitImpl::Implemented(span))?;
|
||||
traits.hash.merge(TraitImpl::Implemented(span))?;
|
||||
}
|
||||
// We only track reflected idents for traits not considered special
|
||||
_ => {
|
||||
|
@ -170,7 +170,7 @@ impl ReflectTraits {
|
|||
}
|
||||
}
|
||||
// Handles `#[reflect( Hash(custom_hash_fn) )]`
|
||||
NestedMeta::Meta(Meta::List(list)) => {
|
||||
Meta::List(list) => {
|
||||
// Get the first ident in the path (hopefully the path only contains one and not `std::hash::Hash`)
|
||||
let Some(segment) = list.path.segments.iter().next() else {
|
||||
continue;
|
||||
|
@ -181,23 +181,25 @@ impl ReflectTraits {
|
|||
// Track the span where the trait is implemented for future errors
|
||||
let span = ident.span();
|
||||
|
||||
let list_meta = list.nested.iter().next();
|
||||
if let Some(NestedMeta::Meta(Meta::Path(path))) = list_meta {
|
||||
list.parse_nested_meta(|meta| {
|
||||
// This should be the path of the custom function
|
||||
let trait_func_ident = TraitImpl::Custom(path.clone(), span);
|
||||
let trait_func_ident = TraitImpl::Custom(meta.path, span);
|
||||
match ident.as_str() {
|
||||
DEBUG_ATTR => {
|
||||
traits.debug = traits.debug.merge(trait_func_ident)?;
|
||||
traits.debug.merge(trait_func_ident)?;
|
||||
}
|
||||
PARTIAL_EQ_ATTR => {
|
||||
traits.partial_eq = traits.partial_eq.merge(trait_func_ident)?;
|
||||
traits.partial_eq.merge(trait_func_ident)?;
|
||||
}
|
||||
HASH_ATTR => {
|
||||
traits.hash = traits.hash.merge(trait_func_ident)?;
|
||||
traits.hash.merge(trait_func_ident)?;
|
||||
}
|
||||
_ => {
|
||||
return Err(syn::Error::new(span, "Can only use custom functions for special traits (i.e. `Hash`, `PartialEq`, `Debug`)"));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -289,26 +291,20 @@ impl ReflectTraits {
|
|||
/// Merges the trait implementations of this [`ReflectTraits`] with another one.
|
||||
///
|
||||
/// An error is returned if the two [`ReflectTraits`] have conflicting implementations.
|
||||
pub fn merge(self, other: ReflectTraits) -> Result<Self, syn::Error> {
|
||||
Ok(ReflectTraits {
|
||||
debug: self.debug.merge(other.debug)?,
|
||||
hash: self.hash.merge(other.hash)?,
|
||||
partial_eq: self.partial_eq.merge(other.partial_eq)?,
|
||||
idents: {
|
||||
let mut idents = self.idents;
|
||||
for ident in other.idents {
|
||||
add_unique_ident(&mut idents, ident)?;
|
||||
}
|
||||
idents
|
||||
},
|
||||
})
|
||||
pub fn merge(&mut self, other: ReflectTraits) -> Result<(), syn::Error> {
|
||||
self.debug.merge(other.debug)?;
|
||||
self.hash.merge(other.hash)?;
|
||||
self.partial_eq.merge(other.partial_eq)?;
|
||||
for ident in other.idents {
|
||||
add_unique_ident(&mut self.idents, ident)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for ReflectTraits {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
let result = Punctuated::<NestedMeta, Comma>::parse_terminated(input)?;
|
||||
ReflectTraits::from_nested_metas(&result)
|
||||
ReflectTraits::from_metas(Punctuated::<Meta, Comma>::parse_terminated(input)?)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,11 +4,12 @@ use crate::fq_std::{FQAny, FQDefault, FQSend, FQSync};
|
|||
use crate::utility::{members_to_serialization_denylist, WhereClauseOptions};
|
||||
use bit_set::BitSet;
|
||||
use quote::quote;
|
||||
use syn::token::Comma;
|
||||
|
||||
use crate::{utility, REFLECT_ATTRIBUTE_NAME, REFLECT_VALUE_ATTRIBUTE_NAME};
|
||||
use syn::punctuated::Punctuated;
|
||||
use syn::spanned::Spanned;
|
||||
use syn::{Data, DeriveInput, Field, Fields, Generics, Ident, Meta, Path, Token, Variant};
|
||||
use syn::{Data, DeriveInput, Field, Fields, Generics, Ident, Meta, Path, Variant};
|
||||
|
||||
pub(crate) enum ReflectDerive<'a> {
|
||||
Struct(ReflectStruct<'a>),
|
||||
|
@ -136,8 +137,8 @@ impl<'a> ReflectDerive<'a> {
|
|||
#[cfg(feature = "documentation")]
|
||||
let mut doc = crate::documentation::Documentation::default();
|
||||
|
||||
for attribute in input.attrs.iter().filter_map(|attr| attr.parse_meta().ok()) {
|
||||
match attribute {
|
||||
for attribute in &input.attrs {
|
||||
match &attribute.meta {
|
||||
Meta::List(meta_list) if meta_list.path.is_ident(REFLECT_ATTRIBUTE_NAME) => {
|
||||
if !matches!(reflect_mode, None | Some(ReflectMode::Normal)) {
|
||||
return Err(syn::Error::new(
|
||||
|
@ -147,8 +148,10 @@ impl<'a> ReflectDerive<'a> {
|
|||
}
|
||||
|
||||
reflect_mode = Some(ReflectMode::Normal);
|
||||
let new_traits = ReflectTraits::from_nested_metas(&meta_list.nested)?;
|
||||
traits = traits.merge(new_traits)?;
|
||||
let new_traits = ReflectTraits::from_metas(
|
||||
meta_list.parse_args_with(Punctuated::<Meta, Comma>::parse_terminated)?,
|
||||
)?;
|
||||
traits.merge(new_traits)?;
|
||||
}
|
||||
Meta::List(meta_list) if meta_list.path.is_ident(REFLECT_VALUE_ATTRIBUTE_NAME) => {
|
||||
if !matches!(reflect_mode, None | Some(ReflectMode::Value)) {
|
||||
|
@ -159,8 +162,10 @@ impl<'a> ReflectDerive<'a> {
|
|||
}
|
||||
|
||||
reflect_mode = Some(ReflectMode::Value);
|
||||
let new_traits = ReflectTraits::from_nested_metas(&meta_list.nested)?;
|
||||
traits = traits.merge(new_traits)?;
|
||||
let new_traits = ReflectTraits::from_metas(
|
||||
meta_list.parse_args_with(Punctuated::<Meta, Comma>::parse_terminated)?,
|
||||
)?;
|
||||
traits.merge(new_traits)?;
|
||||
}
|
||||
Meta::Path(path) if path.is_ident(REFLECT_VALUE_ATTRIBUTE_NAME) => {
|
||||
if !matches!(reflect_mode, None | Some(ReflectMode::Value)) {
|
||||
|
@ -174,7 +179,11 @@ impl<'a> ReflectDerive<'a> {
|
|||
}
|
||||
#[cfg(feature = "documentation")]
|
||||
Meta::NameValue(pair) if pair.path.is_ident("doc") => {
|
||||
if let syn::Lit::Str(lit) = pair.lit {
|
||||
if let syn::Expr::Lit(syn::ExprLit {
|
||||
lit: syn::Lit::Str(lit),
|
||||
..
|
||||
}) = &pair.value
|
||||
{
|
||||
doc.push(lit.value());
|
||||
}
|
||||
}
|
||||
|
@ -247,7 +256,7 @@ impl<'a> ReflectDerive<'a> {
|
|||
}
|
||||
|
||||
fn collect_enum_variants(
|
||||
variants: &'a Punctuated<Variant, Token![,]>,
|
||||
variants: &'a Punctuated<Variant, Comma>,
|
||||
) -> Result<Vec<EnumVariant<'a>>, syn::Error> {
|
||||
let sifter: utility::ResultSifter<EnumVariant<'a>> = variants
|
||||
.iter()
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use crate::fq_std::FQOption;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{quote, ToTokens};
|
||||
use syn::{Attribute, Lit, Meta};
|
||||
use syn::{Attribute, Expr, ExprLit, Lit, Meta};
|
||||
|
||||
/// A struct used to represent a type's documentation, if any.
|
||||
///
|
||||
|
@ -21,18 +21,18 @@ impl Documentation {
|
|||
pub fn from_attributes<'a>(attributes: impl IntoIterator<Item = &'a Attribute>) -> Self {
|
||||
let docs = attributes
|
||||
.into_iter()
|
||||
.filter_map(|attr| {
|
||||
let meta = attr.parse_meta().ok()?;
|
||||
match meta {
|
||||
Meta::NameValue(pair) if pair.path.is_ident("doc") => {
|
||||
if let Lit::Str(lit) = pair.lit {
|
||||
Some(lit.value())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
.filter_map(|attr| match &attr.meta {
|
||||
Meta::NameValue(pair) if pair.path.is_ident("doc") => {
|
||||
if let Expr::Lit(ExprLit {
|
||||
lit: Lit::Str(lit), ..
|
||||
}) = &pair.value
|
||||
{
|
||||
Some(lit.value())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
use crate::REFLECT_ATTRIBUTE_NAME;
|
||||
use quote::ToTokens;
|
||||
use syn::spanned::Spanned;
|
||||
use syn::{Attribute, Lit, Meta, NestedMeta};
|
||||
use syn::{Attribute, Expr, ExprLit, Lit, Meta};
|
||||
|
||||
pub(crate) static IGNORE_SERIALIZATION_ATTR: &str = "skip_serializing";
|
||||
pub(crate) static IGNORE_ALL_ATTR: &str = "ignore";
|
||||
|
@ -76,10 +76,9 @@ pub(crate) fn parse_field_attrs(attrs: &[Attribute]) -> Result<ReflectFieldAttr,
|
|||
|
||||
let attrs = attrs
|
||||
.iter()
|
||||
.filter(|a| a.path.is_ident(REFLECT_ATTRIBUTE_NAME));
|
||||
.filter(|a| a.path().is_ident(REFLECT_ATTRIBUTE_NAME));
|
||||
for attr in attrs {
|
||||
let meta = attr.parse_meta()?;
|
||||
if let Err(err) = parse_meta(&mut args, &meta) {
|
||||
if let Err(err) = parse_meta(&mut args, &attr.meta) {
|
||||
if let Some(ref mut error) = errors {
|
||||
error.combine(err);
|
||||
} else {
|
||||
|
@ -117,18 +116,15 @@ fn parse_meta(args: &mut ReflectFieldAttr, meta: &Meta) -> Result<(), syn::Error
|
|||
format!("unknown attribute parameter: {}", path.to_token_stream()),
|
||||
)),
|
||||
Meta::NameValue(pair) if pair.path.is_ident(DEFAULT_ATTR) => {
|
||||
let lit = &pair.lit;
|
||||
match lit {
|
||||
Lit::Str(lit_str) => {
|
||||
args.default = DefaultBehavior::Func(lit_str.parse()?);
|
||||
Ok(())
|
||||
}
|
||||
err => {
|
||||
Err(syn::Error::new(
|
||||
err.span(),
|
||||
format!("expected a string literal containing the name of a function, but found: {}", err.to_token_stream()),
|
||||
))
|
||||
}
|
||||
if let Expr::Lit(ExprLit {lit: Lit::Str(lit_str), ..}) = &pair.value {
|
||||
args.default = DefaultBehavior::Func(lit_str.parse()?);
|
||||
Ok(())
|
||||
}
|
||||
else {
|
||||
Err(syn::Error::new(
|
||||
pair.span(),
|
||||
format!("expected a string literal containing the name of a function, but found: {}", pair.to_token_stream()),
|
||||
))?
|
||||
}
|
||||
}
|
||||
Meta::NameValue(pair) => {
|
||||
|
@ -142,10 +138,8 @@ fn parse_meta(args: &mut ReflectFieldAttr, meta: &Meta) -> Result<(), syn::Error
|
|||
Err(syn::Error::new(list.path.span(), "unexpected property"))
|
||||
}
|
||||
Meta::List(list) => {
|
||||
for nested in &list.nested {
|
||||
if let NestedMeta::Meta(meta) = nested {
|
||||
parse_meta(args, meta)?;
|
||||
}
|
||||
if let Ok(meta) = list.parse_args() {
|
||||
parse_meta(args, &meta)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ extern crate proc_macro;
|
|||
use bevy_macro_utils::BevyManifest;
|
||||
use quote::quote;
|
||||
use syn::parse::{Parse, ParseStream};
|
||||
use syn::token::Comma;
|
||||
use syn::*;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
@ -15,22 +16,13 @@ pub(crate) fn type_uuid_derive(input: proc_macro::TokenStream) -> proc_macro::To
|
|||
let type_ident = ast.ident;
|
||||
|
||||
let mut uuid = None;
|
||||
for attribute in ast.attrs.iter().filter_map(|attr| attr.parse_meta().ok()) {
|
||||
let Meta::NameValue(name_value) = attribute else {
|
||||
for attribute in ast.attrs.iter().filter(|attr| attr.path().is_ident("uuid")) {
|
||||
let Meta::NameValue(ref name_value) = attribute.meta else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if name_value
|
||||
.path
|
||||
.get_ident()
|
||||
.map(|i| i != "uuid")
|
||||
.unwrap_or(true)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let uuid_str = match name_value.lit {
|
||||
Lit::Str(lit_str) => lit_str,
|
||||
let uuid_str = match &name_value.value {
|
||||
Expr::Lit(ExprLit{lit: Lit::Str(lit_str), ..}) => lit_str,
|
||||
_ => panic!("`uuid` attribute must take the form `#[uuid = \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"`."),
|
||||
};
|
||||
|
||||
|
@ -101,7 +93,7 @@ impl Parse for TypeUuidDef {
|
|||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let type_ident = input.parse::<Ident>()?;
|
||||
let generics = input.parse::<Generics>()?;
|
||||
input.parse::<Token![,]>()?;
|
||||
input.parse::<Comma>()?;
|
||||
let uuid = input.parse::<LitStr>()?.value();
|
||||
let uuid = Uuid::parse_str(&uuid).map_err(|err| input.error(format!("{err}")))?;
|
||||
|
||||
|
|
|
@ -1636,6 +1636,24 @@ bevy_reflect::tests::should_reflect_debug::Test {
|
|||
assert_eq!("Foo".to_string(), format!("{foo:?}"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_debug_function() {
|
||||
#[derive(Reflect)]
|
||||
#[reflect(Debug(custom_debug))]
|
||||
struct Foo {
|
||||
a: u32,
|
||||
}
|
||||
|
||||
fn custom_debug(_x: &Foo, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "123")
|
||||
}
|
||||
|
||||
let foo = Foo { a: 1 };
|
||||
let foo: &dyn Reflect = &foo;
|
||||
|
||||
assert_eq!("123", format!("{:?}", foo));
|
||||
}
|
||||
|
||||
#[cfg(feature = "glam")]
|
||||
mod glam {
|
||||
use super::*;
|
||||
|
|
|
@ -69,7 +69,7 @@ thread_local = "1.1"
|
|||
thiserror = "1.0"
|
||||
futures-lite = "1.4.0"
|
||||
anyhow = "1.0"
|
||||
hexasphere = "8.1"
|
||||
hexasphere = "9.0"
|
||||
parking_lot = "0.12.1"
|
||||
regex = "1.5"
|
||||
ddsfile = { version = "0.5.0", optional = true }
|
||||
|
@ -79,7 +79,7 @@ flate2 = { version = "1.0.22", optional = true }
|
|||
ruzstd = { version = "0.2.4", optional = true }
|
||||
# For transcoding of UASTC/ETC1S universal formats, and for .basis file support
|
||||
basis-universal = { version = "0.2.0", optional = true }
|
||||
encase = { version = "0.5", features = ["glam"] }
|
||||
encase = { version = "0.6.1", features = ["glam"] }
|
||||
# For wgpu profiling using tracing. Use `RUST_LOG=info` to also capture the wgpu spans.
|
||||
profiling = { version = "1", features = ["profile-with-tracing"], optional = true }
|
||||
async-channel = "1.8"
|
||||
|
|
|
@ -14,6 +14,6 @@ proc-macro = true
|
|||
[dependencies]
|
||||
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.11.0-dev" }
|
||||
|
||||
syn = "1.0"
|
||||
syn = "2.0"
|
||||
proc-macro2 = "1.0"
|
||||
quote = "1.0"
|
||||
|
|
|
@ -5,7 +5,8 @@ use quote::{quote, ToTokens};
|
|||
use syn::{
|
||||
parse::{Parse, ParseStream},
|
||||
punctuated::Punctuated,
|
||||
Data, DataStruct, Error, Fields, LitInt, LitStr, NestedMeta, Result, Token,
|
||||
token::Comma,
|
||||
Data, DataStruct, Error, Fields, LitInt, LitStr, Meta, Result,
|
||||
};
|
||||
|
||||
const UNIFORM_ATTRIBUTE_NAME: Symbol = Symbol("uniform");
|
||||
|
@ -48,7 +49,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result<TokenStream> {
|
|||
|
||||
// Read struct-level attributes
|
||||
for attr in &ast.attrs {
|
||||
if let Some(attr_ident) = attr.path.get_ident() {
|
||||
if let Some(attr_ident) = attr.path().get_ident() {
|
||||
if attr_ident == BIND_GROUP_DATA_ATTRIBUTE_NAME {
|
||||
if let Ok(prepared_data_ident) =
|
||||
attr.parse_args_with(|input: ParseStream| input.parse::<Ident>())
|
||||
|
@ -117,7 +118,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result<TokenStream> {
|
|||
// Read field-level attributes
|
||||
for field in fields.iter() {
|
||||
for attr in &field.attrs {
|
||||
let Some(attr_ident) = attr.path.get_ident() else {
|
||||
let Some(attr_ident) = attr.path().get_ident() else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
@ -462,14 +463,14 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result<TokenStream> {
|
|||
/// like `#[uniform(LitInt, Ident)]`
|
||||
struct UniformBindingMeta {
|
||||
lit_int: LitInt,
|
||||
_comma: Token![,],
|
||||
_comma: Comma,
|
||||
ident: Ident,
|
||||
}
|
||||
|
||||
/// Represents the arguments for any general binding attribute.
|
||||
///
|
||||
/// If parsed, represents an attribute
|
||||
/// like `#[foo(LitInt, ...)]` where the rest is optional [`NestedMeta`].
|
||||
/// like `#[foo(LitInt, ...)]` where the rest is optional [`Meta`].
|
||||
enum BindingMeta {
|
||||
IndexOnly(LitInt),
|
||||
IndexWithOptions(BindingIndexOptions),
|
||||
|
@ -480,13 +481,13 @@ enum BindingMeta {
|
|||
/// This represents, for example, `#[texture(0, dimension = "2d_array")]`.
|
||||
struct BindingIndexOptions {
|
||||
lit_int: LitInt,
|
||||
_comma: Token![,],
|
||||
meta_list: Punctuated<NestedMeta, Token![,]>,
|
||||
_comma: Comma,
|
||||
meta_list: Punctuated<Meta, Comma>,
|
||||
}
|
||||
|
||||
impl Parse for BindingMeta {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
if input.peek2(Token![,]) {
|
||||
if input.peek2(Comma) {
|
||||
input.parse().map(Self::IndexWithOptions)
|
||||
} else {
|
||||
input.parse().map(Self::IndexOnly)
|
||||
|
@ -499,7 +500,7 @@ impl Parse for BindingIndexOptions {
|
|||
Ok(Self {
|
||||
lit_int: input.parse()?,
|
||||
_comma: input.parse()?,
|
||||
meta_list: input.parse_terminated(NestedMeta::parse)?,
|
||||
meta_list: input.parse_terminated(Meta::parse, Comma)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -523,7 +524,7 @@ fn get_uniform_binding_attr(attr: &syn::Attribute) -> Result<(u32, Ident)> {
|
|||
Ok((binding_index, ident))
|
||||
}
|
||||
|
||||
fn get_binding_nested_attr(attr: &syn::Attribute) -> Result<(u32, Vec<NestedMeta>)> {
|
||||
fn get_binding_nested_attr(attr: &syn::Attribute) -> Result<(u32, Vec<Meta>)> {
|
||||
let binding_meta = attr.parse_args_with(BindingMeta::parse)?;
|
||||
|
||||
match binding_meta {
|
||||
|
@ -598,43 +599,39 @@ const VISIBILITY_COMPUTE: Symbol = Symbol("compute");
|
|||
const VISIBILITY_ALL: Symbol = Symbol("all");
|
||||
const VISIBILITY_NONE: Symbol = Symbol("none");
|
||||
|
||||
fn get_visibility_flag_value(
|
||||
nested_metas: &Punctuated<NestedMeta, Token![,]>,
|
||||
) -> Result<ShaderStageVisibility> {
|
||||
fn get_visibility_flag_value(meta: Meta) -> Result<ShaderStageVisibility> {
|
||||
let mut visibility = VisibilityFlags::vertex_fragment();
|
||||
|
||||
for meta in nested_metas {
|
||||
use syn::{Meta::Path, NestedMeta::Meta};
|
||||
match meta {
|
||||
// Parse `visibility(all)]`.
|
||||
Meta(Path(path)) if path == VISIBILITY_ALL => {
|
||||
return Ok(ShaderStageVisibility::All)
|
||||
}
|
||||
// Parse `visibility(none)]`.
|
||||
Meta(Path(path)) if path == VISIBILITY_NONE => {
|
||||
return Ok(ShaderStageVisibility::None)
|
||||
}
|
||||
// Parse `visibility(vertex, ...)]`.
|
||||
Meta(Path(path)) if path == VISIBILITY_VERTEX => {
|
||||
visibility.vertex = true;
|
||||
}
|
||||
// Parse `visibility(fragment, ...)]`.
|
||||
Meta(Path(path)) if path == VISIBILITY_FRAGMENT => {
|
||||
visibility.fragment = true;
|
||||
}
|
||||
// Parse `visibility(compute, ...)]`.
|
||||
Meta(Path(path)) if path == VISIBILITY_COMPUTE => {
|
||||
visibility.compute = true;
|
||||
}
|
||||
Meta(Path(path)) => return Err(Error::new_spanned(
|
||||
path,
|
||||
"Not a valid visibility flag. Must be `all`, `none`, or a list-combination of `vertex`, `fragment` and/or `compute`."
|
||||
)),
|
||||
_ => return Err(Error::new_spanned(
|
||||
meta,
|
||||
"Invalid visibility format: `visibility(...)`.",
|
||||
)),
|
||||
use syn::Meta::Path;
|
||||
match meta {
|
||||
// Parse `#[visibility(all)]`.
|
||||
Path(path) if path == VISIBILITY_ALL => {
|
||||
return Ok(ShaderStageVisibility::All)
|
||||
}
|
||||
// Parse `#[visibility(none)]`.
|
||||
Path(path) if path == VISIBILITY_NONE => {
|
||||
return Ok(ShaderStageVisibility::None)
|
||||
}
|
||||
// Parse `#[visibility(vertex, ...)]`.
|
||||
Path(path) if path == VISIBILITY_VERTEX => {
|
||||
visibility.vertex = true;
|
||||
}
|
||||
// Parse `#[visibility(fragment, ...)]`.
|
||||
Path(path) if path == VISIBILITY_FRAGMENT => {
|
||||
visibility.fragment = true;
|
||||
}
|
||||
// Parse `#[visibility(compute, ...)]`.
|
||||
Path(path) if path == VISIBILITY_COMPUTE => {
|
||||
visibility.compute = true;
|
||||
}
|
||||
Path(path) => return Err(Error::new_spanned(
|
||||
path,
|
||||
"Not a valid visibility flag. Must be `all`, `none`, or a list-combination of `vertex`, `fragment` and/or `compute`."
|
||||
)),
|
||||
_ => return Err(Error::new_spanned(
|
||||
meta,
|
||||
"Invalid visibility format: `visibility(...)`.",
|
||||
)),
|
||||
}
|
||||
|
||||
Ok(ShaderStageVisibility::Flags(visibility))
|
||||
|
@ -727,7 +724,7 @@ const DEPTH: &str = "depth";
|
|||
const S_INT: &str = "s_int";
|
||||
const U_INT: &str = "u_int";
|
||||
|
||||
fn get_texture_attrs(metas: Vec<NestedMeta>) -> Result<TextureAttrs> {
|
||||
fn get_texture_attrs(metas: Vec<Meta>) -> Result<TextureAttrs> {
|
||||
let mut dimension = Default::default();
|
||||
let mut sample_type = Default::default();
|
||||
let mut multisampled = Default::default();
|
||||
|
@ -737,35 +734,32 @@ fn get_texture_attrs(metas: Vec<NestedMeta>) -> Result<TextureAttrs> {
|
|||
let mut visibility = ShaderStageVisibility::vertex_fragment();
|
||||
|
||||
for meta in metas {
|
||||
use syn::{
|
||||
Meta::{List, NameValue},
|
||||
NestedMeta::Meta,
|
||||
};
|
||||
use syn::Meta::{List, NameValue};
|
||||
match meta {
|
||||
// Parse #[texture(0, dimension = "...")].
|
||||
Meta(NameValue(m)) if m.path == DIMENSION => {
|
||||
let value = get_lit_str(DIMENSION, &m.lit)?;
|
||||
NameValue(m) if m.path == DIMENSION => {
|
||||
let value = get_lit_str(DIMENSION, &m.value)?;
|
||||
dimension = get_texture_dimension_value(value)?;
|
||||
}
|
||||
// Parse #[texture(0, sample_type = "...")].
|
||||
Meta(NameValue(m)) if m.path == SAMPLE_TYPE => {
|
||||
let value = get_lit_str(SAMPLE_TYPE, &m.lit)?;
|
||||
NameValue(m) if m.path == SAMPLE_TYPE => {
|
||||
let value = get_lit_str(SAMPLE_TYPE, &m.value)?;
|
||||
sample_type = get_texture_sample_type_value(value)?;
|
||||
}
|
||||
// Parse #[texture(0, multisampled = "...")].
|
||||
Meta(NameValue(m)) if m.path == MULTISAMPLED => {
|
||||
multisampled = get_lit_bool(MULTISAMPLED, &m.lit)?;
|
||||
NameValue(m) if m.path == MULTISAMPLED => {
|
||||
multisampled = get_lit_bool(MULTISAMPLED, &m.value)?;
|
||||
}
|
||||
// Parse #[texture(0, filterable = "...")].
|
||||
Meta(NameValue(m)) if m.path == FILTERABLE => {
|
||||
filterable = get_lit_bool(FILTERABLE, &m.lit)?.into();
|
||||
NameValue(m) if m.path == FILTERABLE => {
|
||||
filterable = get_lit_bool(FILTERABLE, &m.value)?.into();
|
||||
filterable_ident = m.path.into();
|
||||
}
|
||||
// Parse #[texture(0, visibility(...))].
|
||||
Meta(List(m)) if m.path == VISIBILITY => {
|
||||
visibility = get_visibility_flag_value(&m.nested)?;
|
||||
List(m) if m.path == VISIBILITY => {
|
||||
visibility = get_visibility_flag_value(Meta::Path(m.path))?;
|
||||
}
|
||||
Meta(NameValue(m)) => {
|
||||
NameValue(m) => {
|
||||
return Err(Error::new_spanned(
|
||||
m.path,
|
||||
"Not a valid name. Available attributes: `dimension`, `sample_type`, `multisampled`, or `filterable`."
|
||||
|
@ -865,26 +859,23 @@ const FILTERING: &str = "filtering";
|
|||
const NON_FILTERING: &str = "non_filtering";
|
||||
const COMPARISON: &str = "comparison";
|
||||
|
||||
fn get_sampler_attrs(metas: Vec<NestedMeta>) -> Result<SamplerAttrs> {
|
||||
fn get_sampler_attrs(metas: Vec<Meta>) -> Result<SamplerAttrs> {
|
||||
let mut sampler_binding_type = Default::default();
|
||||
let mut visibility = ShaderStageVisibility::vertex_fragment();
|
||||
|
||||
for meta in metas {
|
||||
use syn::{
|
||||
Meta::{List, NameValue},
|
||||
NestedMeta::Meta,
|
||||
};
|
||||
use syn::Meta::{List, NameValue};
|
||||
match meta {
|
||||
// Parse #[sampler(0, sampler_type = "..."))].
|
||||
Meta(NameValue(m)) if m.path == SAMPLER_TYPE => {
|
||||
let value = get_lit_str(DIMENSION, &m.lit)?;
|
||||
NameValue(m) if m.path == SAMPLER_TYPE => {
|
||||
let value = get_lit_str(DIMENSION, &m.value)?;
|
||||
sampler_binding_type = get_sampler_binding_type_value(value)?;
|
||||
}
|
||||
// Parse #[sampler(0, visibility(...))].
|
||||
Meta(List(m)) if m.path == VISIBILITY => {
|
||||
visibility = get_visibility_flag_value(&m.nested)?;
|
||||
List(m) if m.path == VISIBILITY => {
|
||||
visibility = get_visibility_flag_value(Meta::Path(m.path))?;
|
||||
}
|
||||
Meta(NameValue(m)) => {
|
||||
NameValue(m) => {
|
||||
return Err(Error::new_spanned(
|
||||
m.path,
|
||||
"Not a valid name. Available attributes: `sampler_type`.",
|
||||
|
@ -928,22 +919,22 @@ struct StorageAttrs {
|
|||
const READ_ONLY: Symbol = Symbol("read_only");
|
||||
const BUFFER: Symbol = Symbol("buffer");
|
||||
|
||||
fn get_storage_binding_attr(metas: Vec<NestedMeta>) -> Result<StorageAttrs> {
|
||||
fn get_storage_binding_attr(metas: Vec<Meta>) -> Result<StorageAttrs> {
|
||||
let mut visibility = ShaderStageVisibility::vertex_fragment();
|
||||
let mut read_only = false;
|
||||
let mut buffer = false;
|
||||
|
||||
for meta in metas {
|
||||
use syn::{Meta::List, Meta::Path, NestedMeta::Meta};
|
||||
use syn::{Meta::List, Meta::Path};
|
||||
match meta {
|
||||
// Parse #[storage(0, visibility(...))].
|
||||
Meta(List(m)) if m.path == VISIBILITY => {
|
||||
visibility = get_visibility_flag_value(&m.nested)?;
|
||||
List(m) if m.path == VISIBILITY => {
|
||||
visibility = get_visibility_flag_value(Meta::Path(m.path))?;
|
||||
}
|
||||
Meta(Path(path)) if path == READ_ONLY => {
|
||||
Path(path) if path == READ_ONLY => {
|
||||
read_only = true;
|
||||
}
|
||||
Meta(Path(path)) if path == BUFFER => {
|
||||
Path(path) if path == BUFFER => {
|
||||
buffer = true;
|
||||
}
|
||||
_ => {
|
||||
|
|
|
@ -20,7 +20,7 @@ pub fn derive_extract_component(input: TokenStream) -> TokenStream {
|
|||
let filter = if let Some(attr) = ast
|
||||
.attrs
|
||||
.iter()
|
||||
.find(|a| a.path.is_ident("extract_component_filter"))
|
||||
.find(|a| a.path().is_ident("extract_component_filter"))
|
||||
{
|
||||
let filter = match attr.parse_args::<syn::Type>() {
|
||||
Ok(filter) => filter,
|
||||
|
|
|
@ -9,6 +9,6 @@ license = "MIT OR Apache-2.0"
|
|||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
syn = "1.0"
|
||||
syn = "2.0"
|
||||
quote = "1.0"
|
||||
proc-macro2 = "1.0"
|
||||
|
|
Loading…
Reference in a new issue