remove darling

This commit is contained in:
Carter Anderson 2020-07-10 02:53:31 -07:00
parent 3b68c7cc4a
commit 2508a59f68
16 changed files with 140 additions and 225 deletions

View file

@ -1,16 +1,15 @@
[package] [package]
name = "bevy_derive"
version = "0.1.0"
authors = ["Carter Anderson <mcanders1@gmail.com>"] authors = ["Carter Anderson <mcanders1@gmail.com>"]
edition = "2018" edition = "2018"
name = "bevy_derive"
version = "0.1.0"
[lib] [lib]
proc-macro = true proc-macro = true
[dependencies] [dependencies]
syn = "1.0" Inflector = {version = "0.11.4", default-features = false}
proc-macro-crate = "0.1.4"
proc-macro2 = "1.0" proc-macro2 = "1.0"
quote = "1.0" quote = "1.0"
Inflector = { version = "0.11.4", default-features = false } syn = "1.0"
darling = "0.10.2"
proc-macro-crate = "0.1.4"

View file

@ -1,20 +1,10 @@
use crate::{ use crate::{
attributes::get_field_attributes,
modules::{get_modules, get_path}, modules::{get_modules, get_path},
}; };
use darling::FromMeta;
use inflector::Inflector; use inflector::Inflector;
use proc_macro::TokenStream; use proc_macro::TokenStream;
use quote::{format_ident, quote}; use quote::{format_ident, quote};
use syn::{parse_macro_input, DeriveInput, Path}; use syn::{parse_macro_input, DeriveInput, Path, Data, DataStruct, Fields, Field, parse::ParseStream};
#[derive(FromMeta, Debug, Default)]
struct VertexAttributeArgs {
#[darling(default)]
pub ignore: Option<bool>,
#[darling(default)]
pub instance: Option<bool>,
}
#[derive(Default)] #[derive(Default)]
struct VertexAttributes { struct VertexAttributes {
@ -22,27 +12,44 @@ struct VertexAttributes {
pub instance: bool, pub instance: bool,
} }
impl From<VertexAttributeArgs> for VertexAttributes {
fn from(args: VertexAttributeArgs) -> Self {
VertexAttributes {
ignore: args.ignore.unwrap_or(false),
instance: args.instance.unwrap_or(false),
}
}
}
static VERTEX_ATTRIBUTE_NAME: &'static str = "vertex"; static VERTEX_ATTRIBUTE_NAME: &'static str = "vertex";
pub fn derive_as_vertex_buffer_descriptor(input: TokenStream) -> TokenStream { pub fn derive_as_vertex_buffer_descriptor(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput); let ast = parse_macro_input!(input as DeriveInput);
let modules = get_modules(&ast); let modules = get_modules();
let bevy_render_path: Path = get_path(&modules.bevy_render); let bevy_render_path: Path = get_path(&modules.bevy_render);
let fields = match &ast.data {
Data::Struct(DataStruct {
fields: Fields::Named(fields),
..
}) => &fields.named,
_ => panic!("expected a struct with named fields"),
};
let field_attributes = fields
.iter()
.map(|field| {
(
field,
field.attrs
.iter()
.find(|a| a.path.get_ident().as_ref().unwrap().to_string() == VERTEX_ATTRIBUTE_NAME)
.map_or_else(|| VertexAttributes::default() ,|a| {
syn::custom_keyword!(ignore);
let mut vertex_attributes = VertexAttributes::default();
a.parse_args_with(|input: ParseStream| {
if let Some(_) = input.parse::<Option<ignore>>()? {
vertex_attributes.ignore = true;
return Ok(());
}
Ok(())
}).expect("invalid 'vertex' attribute format");
let field_attributes = get_field_attributes::<VertexAttributes, VertexAttributeArgs>( vertex_attributes
VERTEX_ATTRIBUTE_NAME, }),
&ast.data, )
); })
.collect::<Vec<(&Field, VertexAttributes)>>();
let struct_name = &ast.ident; let struct_name = &ast.ident;

View file

@ -1,50 +0,0 @@
use darling::FromMeta;
use syn::{Attribute, Data, DataStruct, Field, Fields};
pub fn get_field_attributes<'a, T, TArgs>(
attribute_name: &str,
data: &'a Data,
) -> Vec<(&'a Field, T)>
where
T: Default,
TArgs: FromMeta + Into<T> + Default,
{
let fields = match data {
Data::Struct(DataStruct {
fields: Fields::Named(fields),
..
}) => &fields.named,
_ => panic!("expected a struct with named fields"),
};
fields
.iter()
.map(|f| {
(
f,
f.attrs
.iter()
.find(|a| a.path.get_ident().as_ref().unwrap().to_string() == attribute_name)
.map(|a| {
TArgs::from_meta(&a.parse_meta().unwrap())
.unwrap_or_else(|_err| TArgs::default())
})
.unwrap_or_else(|| TArgs::default())
.into(),
)
})
.collect::<Vec<(&Field, T)>>()
}
pub fn get_attributes<'a, T, TArgs>(attribute_name: &str, attrs: &[Attribute]) -> T
where
T: Default,
TArgs: FromMeta + Into<T> + Default,
{
attrs
.iter()
.find(|a| a.path.get_ident().as_ref().unwrap().to_string() == attribute_name)
.map(|a| TArgs::from_meta(&a.parse_meta().unwrap()).unwrap_or_else(|_err| TArgs::default()))
.unwrap_or_else(|| TArgs::default())
.into()
}

View file

@ -13,7 +13,7 @@ pub fn derive_bytes(input: TokenStream) -> TokenStream {
_ => panic!("expected a struct with named fields"), _ => panic!("expected a struct with named fields"),
}; };
let modules = get_modules(&ast); let modules = get_modules();
let bevy_core_path = get_path(&modules.bevy_core); let bevy_core_path = get_path(&modules.bevy_core);
let fields = fields let fields = fields

View file

@ -13,7 +13,7 @@ pub fn derive_component_set(input: TokenStream) -> TokenStream {
_ => panic!("expected a struct with named fields"), _ => panic!("expected a struct with named fields"),
}; };
let modules = get_modules(&ast); let modules = get_modules();
let bevy_app_path = get_path(&modules.bevy_app); let bevy_app_path = get_path(&modules.bevy_app);
let legion_path = get_path(&modules.legion); let legion_path = get_path(&modules.legion);

View file

@ -2,7 +2,6 @@ extern crate proc_macro;
mod app_plugin; mod app_plugin;
mod as_vertex_buffer_descriptor; mod as_vertex_buffer_descriptor;
mod attributes;
mod bytes; mod bytes;
mod component_set; mod component_set;
mod modules; mod modules;

View file

@ -1,26 +1,6 @@
use darling::FromMeta;
use proc_macro::TokenStream; use proc_macro::TokenStream;
use proc_macro_crate::crate_name; use proc_macro_crate::crate_name;
use syn::{DeriveInput, Path}; use syn::Path;
#[derive(FromMeta, Debug, Default)]
pub struct ModuleAttributeArgs {
#[darling(default)]
pub bevy_render: Option<String>,
#[darling(default)]
pub bevy_asset: Option<String>,
#[darling(default)]
pub bevy_core: Option<String>,
#[darling(default)]
pub bevy_app: Option<String>,
#[darling(default)]
pub legion: Option<String>,
/// If true, it will use the meta "bevy" crate for dependencies by default (ex: bevy:app). If this is set to false, the individual bevy crates
/// will be used (ex: "bevy_app"). Defaults to "true" if the "bevy" crate is in your cargo.toml
#[darling(default)]
pub meta: Option<bool>,
}
#[derive(Debug)] #[derive(Debug)]
pub struct Modules { pub struct Modules {
@ -57,44 +37,12 @@ fn use_meta() -> bool {
crate_name("bevy").is_ok() crate_name("bevy").is_ok()
} }
pub static MODULE_ATTRIBUTE_NAME: &'static str = "module"; pub fn get_modules() -> Modules {
if use_meta() {
pub fn get_modules(ast: &DeriveInput) -> Modules {
let module_attribute_args = ast
.attrs
.iter()
.find(|a| a.path.get_ident().as_ref().unwrap().to_string() == MODULE_ATTRIBUTE_NAME)
.map_or_else(
|| ModuleAttributeArgs::default(),
|a| {
ModuleAttributeArgs::from_meta(&a.parse_meta().unwrap())
.unwrap_or_else(|_err| ModuleAttributeArgs::default())
},
);
let mut modules = if module_attribute_args.meta.unwrap_or_else(|| use_meta()) {
Modules::meta() Modules::meta()
} else { } else {
Modules::external() Modules::external()
};
if let Some(path) = module_attribute_args.bevy_asset {
modules.bevy_asset = path;
} }
if let Some(path) = module_attribute_args.bevy_render {
modules.bevy_render = path;
}
if let Some(path) = module_attribute_args.bevy_core {
modules.bevy_core = path;
}
if let Some(path) = module_attribute_args.bevy_app {
modules.bevy_app = path;
}
modules
} }
pub fn get_path(path_str: &str) -> Path { pub fn get_path(path_str: &str) -> Path {

View file

@ -5,7 +5,7 @@ use syn::{parse_macro_input, DeriveInput, Path};
pub fn derive_render_resource(input: TokenStream) -> TokenStream { pub fn derive_render_resource(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput); let ast = parse_macro_input!(input as DeriveInput);
let modules = get_modules(&ast); let modules = get_modules();
let bevy_render_path: Path = get_path(&modules.bevy_render); let bevy_render_path: Path = get_path(&modules.bevy_render);
let bevy_asset_path: Path = get_path(&modules.bevy_asset); let bevy_asset_path: Path = get_path(&modules.bevy_asset);

View file

@ -1,50 +1,50 @@
use crate::{ use crate::modules::{get_modules, get_path};
attributes::{get_attributes, get_field_attributes},
modules::{get_modules, get_path},
};
use darling::FromMeta;
use proc_macro::TokenStream; use proc_macro::TokenStream;
use quote::{format_ident, quote}; use quote::{format_ident, quote};
use syn::{parse_macro_input, DeriveInput, Path}; use syn::{
parse::ParseStream, parse_macro_input, Data, DataStruct, DeriveInput, Field, Fields, Path,
};
#[derive(FromMeta, Debug, Default)] #[derive(Default)]
struct RenderResourceAttributeArgs { struct RenderResourceFieldAttributes {
#[darling(default)] pub ignore: bool,
pub ignore: Option<bool>, pub buffer: bool,
#[darling(default)]
pub buffer: Option<bool>,
#[darling(default)]
pub from_self: Option<bool>,
} }
#[derive(Default)] #[derive(Default)]
struct RenderResourceAttributes { struct RenderResourceAttributes {
pub ignore: bool,
pub buffer: bool,
pub from_self: bool, pub from_self: bool,
} }
impl From<RenderResourceAttributeArgs> for RenderResourceAttributes {
fn from(args: RenderResourceAttributeArgs) -> Self {
Self {
ignore: args.ignore.unwrap_or(false),
buffer: args.buffer.unwrap_or(false),
from_self: args.from_self.unwrap_or(false),
}
}
}
static RENDER_RESOURCE_ATTRIBUTE_NAME: &'static str = "render_resources"; static RENDER_RESOURCE_ATTRIBUTE_NAME: &'static str = "render_resources";
pub fn derive_render_resources(input: TokenStream) -> TokenStream { pub fn derive_render_resources(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput); let ast = parse_macro_input!(input as DeriveInput);
let modules = get_modules(&ast); let modules = get_modules();
let bevy_render_path: Path = get_path(&modules.bevy_render); let bevy_render_path: Path = get_path(&modules.bevy_render);
let attributes = get_attributes::<RenderResourceAttributes, RenderResourceAttributeArgs>( let attributes = ast
RENDER_RESOURCE_ATTRIBUTE_NAME, .attrs
&ast.attrs, .iter()
); .find(|a| {
a.path.get_ident().as_ref().unwrap().to_string() == RENDER_RESOURCE_ATTRIBUTE_NAME
})
.map_or_else(
|| RenderResourceAttributes::default(),
|a| {
syn::custom_keyword!(from_self);
let mut attributes = RenderResourceAttributes::default();
a.parse_args_with(|input: ParseStream| {
if let Some(_) = input.parse::<Option<from_self>>()? {
attributes.from_self = true;
}
Ok(())
})
.expect("invalid 'render_resources' attribute format");
attributes
},
);
let struct_name = &ast.ident; let struct_name = &ast.ident;
let struct_name_string = struct_name.to_string(); let struct_name_string = struct_name.to_string();
@ -77,11 +77,47 @@ pub fn derive_render_resources(input: TokenStream) -> TokenStream {
} }
}) })
} else { } else {
let field_attributes = get_field_attributes::< let fields = match &ast.data {
RenderResourceAttributes, Data::Struct(DataStruct {
RenderResourceAttributeArgs, fields: Fields::Named(fields),
>(RENDER_RESOURCE_ATTRIBUTE_NAME, &ast.data); ..
}) => &fields.named,
_ => panic!("expected a struct with named fields"),
};
let field_attributes = fields
.iter()
.map(|field| {
(
field,
field
.attrs
.iter()
.find(|a| {
a.path.get_ident().as_ref().unwrap().to_string()
== RENDER_RESOURCE_ATTRIBUTE_NAME
})
.map_or_else(
|| RenderResourceFieldAttributes::default(),
|a| {
syn::custom_keyword!(ignore);
syn::custom_keyword!(buffer);
let mut attributes = RenderResourceFieldAttributes::default();
a.parse_args_with(|input: ParseStream| {
if let Some(_) = input.parse::<Option<ignore>>()? {
attributes.ignore = true;
} else if let Some(_) = input.parse::<Option<buffer>>()? {
attributes.buffer = true;
}
Ok(())
})
.expect("invalid 'render_resources' attribute format");
attributes
},
),
)
})
.collect::<Vec<(&Field, RenderResourceFieldAttributes)>>();
let mut render_resource_names = Vec::new(); let mut render_resource_names = Vec::new();
let mut render_resource_fields = Vec::new(); let mut render_resource_fields = Vec::new();
let mut render_resource_hints = Vec::new(); let mut render_resource_hints = Vec::new();

View file

@ -13,7 +13,7 @@ pub fn derive_from_resources(input: TokenStream) -> TokenStream {
_ => panic!("expected a struct with named fields"), _ => panic!("expected a struct with named fields"),
}; };
let modules = get_modules(&ast); let modules = get_modules();
let bevy_app_path = get_path(&modules.bevy_app); let bevy_app_path = get_path(&modules.bevy_app);
let field_types = fields.iter().map(|field| &field.ty); let field_types = fields.iter().map(|field| &field.ty);

View file

@ -9,7 +9,7 @@ static SHADER_DEF_ATTRIBUTE_NAME: &'static str = "shader_def";
pub fn derive_shader_defs(input: TokenStream) -> TokenStream { pub fn derive_shader_defs(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput); let ast = parse_macro_input!(input as DeriveInput);
let modules = get_modules(&ast); let modules = get_modules();
let bevy_render_path: Path = get_path(&modules.bevy_render); let bevy_render_path: Path = get_path(&modules.bevy_render);
let fields = match &ast.data { let fields = match &ast.data {

View file

@ -28,7 +28,6 @@ hecs-macros = { path = "macros", version = "0.3.0", optional = true }
hashbrown = { version = "0.8.0", default-features = false, features = ["ahash", "inline-more"] } hashbrown = { version = "0.8.0", default-features = false, features = ["ahash", "inline-more"] }
lazy_static = { version = "1.4.0", optional = true, features = ["spin_no_std"] } lazy_static = { version = "1.4.0", optional = true, features = ["spin_no_std"] }
serde = { version = "1", features = ["derive"], optional = true} serde = { version = "1", features = ["derive"], optional = true}
getrandom = "0.1"
rand = "0.7.3" rand = "0.7.3"
[dev-dependencies] [dev-dependencies]

View file

@ -11,5 +11,4 @@ proc-macro = true
syn = "1.0" syn = "1.0"
proc-macro2 = "1.0" proc-macro2 = "1.0"
quote = "1.0" quote = "1.0"
darling = "0.10.2"
proc-macro-crate = "0.1.4" proc-macro-crate = "0.1.4"

View file

@ -2,22 +2,20 @@ extern crate proc_macro;
mod modules; mod modules;
use darling::FromMeta;
use modules::{get_modules, get_path}; use modules::{get_modules, get_path};
use proc_macro::TokenStream; use proc_macro::{TokenStream};
use proc_macro_crate::crate_name; use proc_macro_crate::crate_name;
use quote::quote; use quote::quote;
use syn::{ use syn::{
parse::Parse, parse::{ParseStream, Parse},
parse_macro_input, parse_macro_input,
punctuated::Punctuated, punctuated::Punctuated,
token::{Comma, Where}, token::{Comma, Where},
Data, DataStruct, DeriveInput, Field, Fields, Generics, Ident, Index, Member, Data, DataStruct, DeriveInput, Field, Fields, Generics, Ident, Index, Member,
}; };
#[derive(FromMeta, Debug, Default)] #[derive(Default)]
struct PropAttributeArgs { struct PropAttributeArgs {
#[darling(default)]
pub ignore: Option<bool>, pub ignore: Option<bool>,
} }
@ -50,12 +48,21 @@ pub fn derive_properties(input: TokenStream) -> TokenStream {
f, f,
f.attrs f.attrs
.iter() .iter()
.find(|a| { .find(|a| a.path.get_ident().as_ref().unwrap().to_string() == PROP_ATTRIBUTE_NAME)
a.path.get_ident().as_ref().unwrap().to_string() == PROP_ATTRIBUTE_NAME
})
.map(|a| { .map(|a| {
PropAttributeArgs::from_meta(&a.parse_meta().unwrap()) syn::custom_keyword!(ignore);
.unwrap_or_else(|_err| PropAttributeArgs::default()) let mut attribute_args = PropAttributeArgs {
ignore: None,
};
a.parse_args_with(|input: ParseStream| {
if let Some(_) = input.parse::<Option<ignore>>()? {
attribute_args.ignore = Some(true);
return Ok(());
}
Ok(())
}).expect("invalid 'property' attribute format");
attribute_args
}), }),
i, i,
) )
@ -73,7 +80,7 @@ pub fn derive_properties(input: TokenStream) -> TokenStream {
.map(|(f, _attr, i)| (*f, *i)) .map(|(f, _attr, i)| (*f, *i))
.collect::<Vec<(&Field, usize)>>(); .collect::<Vec<(&Field, usize)>>();
let modules = get_modules(&ast); let modules = get_modules();
let bevy_property_path = get_path(&modules.bevy_property); let bevy_property_path = get_path(&modules.bevy_property);
let field_names = active_fields let field_names = active_fields
@ -224,7 +231,7 @@ pub fn derive_properties(input: TokenStream) -> TokenStream {
#[proc_macro_derive(Property)] #[proc_macro_derive(Property)]
pub fn derive_property(input: TokenStream) -> TokenStream { pub fn derive_property(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput); let ast = parse_macro_input!(input as DeriveInput);
let modules = get_modules(&ast); let modules = get_modules();
let bevy_property_path = get_path(&modules.bevy_property); let bevy_property_path = get_path(&modules.bevy_property);
let generics = ast.generics; let generics = ast.generics;

View file

@ -1,16 +1,6 @@
use darling::FromMeta;
use proc_macro::TokenStream; use proc_macro::TokenStream;
use proc_macro_crate::crate_name; use proc_macro_crate::crate_name;
use syn::{DeriveInput, Path}; use syn::Path;
#[derive(FromMeta, Debug, Default)]
pub struct ModuleAttributeArgs {
pub bevy_property: Option<String>,
/// If true, it will use the meta "bevy" crate for dependencies by default (ex: bevy:app). If this is set to false, the individual bevy crates
/// will be used (ex: "bevy_app"). Defaults to "true" if the "bevy" crate is in your cargo.toml
#[darling(default)]
pub meta: Option<bool>,
}
#[derive(Debug)] #[derive(Debug)]
pub struct Modules { pub struct Modules {
@ -35,32 +25,12 @@ fn use_meta() -> bool {
crate_name("bevy").is_ok() crate_name("bevy").is_ok()
} }
pub static MODULE_ATTRIBUTE_NAME: &'static str = "module"; pub fn get_modules() -> Modules {
if use_meta() {
pub fn get_modules(ast: &DeriveInput) -> Modules {
let module_attribute_args = ast
.attrs
.iter()
.find(|a| a.path.get_ident().as_ref().unwrap().to_string() == MODULE_ATTRIBUTE_NAME)
.map_or_else(
|| ModuleAttributeArgs::default(),
|a| {
ModuleAttributeArgs::from_meta(&a.parse_meta().unwrap())
.unwrap_or_else(|_err| ModuleAttributeArgs::default())
},
);
let mut modules = if module_attribute_args.meta.unwrap_or_else(|| use_meta()) {
Modules::meta() Modules::meta()
} else { } else {
Modules::external() Modules::external()
};
if let Some(path) = module_attribute_args.bevy_property {
modules.bevy_property = path;
} }
modules
} }
pub fn get_path(path_str: &str) -> Path { pub fn get_path(path_str: &str) -> Path {

View file

@ -1,9 +1,10 @@
use crate::pipeline::AsVertexBufferDescriptor; use crate::pipeline::AsVertexBufferDescriptor;
use bevy_core::bytes::Byteable; use bevy_core::bytes::Byteable;
use crate as bevy_render;
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy, AsVertexBufferDescriptor)] #[derive(Clone, Copy, AsVertexBufferDescriptor)]
#[module(bevy_render = "crate")]
pub struct Vertex { pub struct Vertex {
pub position: [f32; 3], pub position: [f32; 3],
pub normal: [f32; 3], pub normal: [f32; 3],