Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Use bevy_reflect as path in case of no direct references #1875

Closed
wants to merge 11 commits into from
3 changes: 2 additions & 1 deletion crates/bevy_derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ keywords = ["bevy"]
proc-macro = true

[dependencies]
bevy_macro_utils = { path = "../bevy_macro_utils", version = "0.5.0" }

Inflector = { version = "0.11.4", default-features = false }
find-crate = "0.6"
proc-macro2 = "1.0"
quote = "1.0"
syn = "1.0"
5 changes: 2 additions & 3 deletions crates/bevy_derive/src/bytes.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::modules::{get_modules, get_path};
use bevy_macro_utils::BevyManifest;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Fields};
Expand All @@ -13,8 +13,7 @@ pub fn derive_bytes(input: TokenStream) -> TokenStream {
_ => panic!("Expected a struct with named fields."),
};

let modules = get_modules(&ast.attrs);
let bevy_core_path = get_path(&modules.bevy_core);
let bevy_core_path = BevyManifest::default().get_path(crate::modules::BEVY_CORE);

let fields = fields
.iter()
Expand Down
5 changes: 2 additions & 3 deletions crates/bevy_derive/src/enum_variant_meta.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::modules::{get_modules, get_path};
use bevy_macro_utils::BevyManifest;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data, DeriveInput};
Expand All @@ -10,8 +10,7 @@ pub fn derive_enum_variant_meta(input: TokenStream) -> TokenStream {
_ => panic!("Expected an enum."),
};

let modules = get_modules(&ast.attrs);
let bevy_util_path = get_path(&modules.bevy_utils);
let bevy_util_path = BevyManifest::default().get_path(crate::modules::BEVY_UTILS);

let generics = ast.generics;
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
Expand Down
12 changes: 6 additions & 6 deletions crates/bevy_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,33 @@ use proc_macro::TokenStream;

/// Derives the FromResources trait. Each field must also implement the FromResources trait or this
/// will fail. FromResources is automatically implemented for types that implement Default.
#[proc_macro_derive(FromResources, attributes(as_crate))]
#[proc_macro_derive(FromResources)]
pub fn derive_from_resources(input: TokenStream) -> TokenStream {
resource::derive_from_resources(input)
}

/// Derives the Bytes trait. Each field must also implements Bytes or this will fail.
#[proc_macro_derive(Bytes, attributes(as_crate))]
#[proc_macro_derive(Bytes)]
pub fn derive_bytes(input: TokenStream) -> TokenStream {
bytes::derive_bytes(input)
}

/// Derives the RenderResources trait. Each field must implement RenderResource or this will fail.
/// You can ignore fields using `#[render_resources(ignore)]`.
#[proc_macro_derive(RenderResources, attributes(render_resources, as_crate))]
#[proc_macro_derive(RenderResources, attributes(render_resources))]
pub fn derive_render_resources(input: TokenStream) -> TokenStream {
render_resources::derive_render_resources(input)
}

/// Derives the RenderResource trait. The type must also implement `Bytes` or this will fail.
#[proc_macro_derive(RenderResource, attributes(as_crate))]
#[proc_macro_derive(RenderResource)]
pub fn derive_render_resource(input: TokenStream) -> TokenStream {
render_resource::derive_render_resource(input)
}

/// Derives the ShaderDefs trait. Each field must implement ShaderDef or this will fail.
/// You can ignore fields using `#[shader_defs(ignore)]`.
#[proc_macro_derive(ShaderDefs, attributes(shader_def, as_crate))]
#[proc_macro_derive(ShaderDefs, attributes(shader_def))]
pub fn derive_shader_defs(input: TokenStream) -> TokenStream {
shader_defs::derive_shader_defs(input)
}
Expand All @@ -56,7 +56,7 @@ pub fn bevy_main(attr: TokenStream, item: TokenStream) -> TokenStream {
bevy_main::bevy_main(attr, item)
}

#[proc_macro_derive(EnumVariantMeta, attributes(as_crate))]
#[proc_macro_derive(EnumVariantMeta)]
pub fn derive_enum_variant_meta(input: TokenStream) -> TokenStream {
enum_variant_meta::derive_enum_variant_meta(input)
}
76 changes: 5 additions & 71 deletions crates/bevy_derive/src/modules.rs
Original file line number Diff line number Diff line change
@@ -1,71 +1,5 @@
use find_crate::Manifest;
use proc_macro::TokenStream;
use syn::{Attribute, Path};

#[derive(Debug)]
pub struct Modules {
pub bevy_render: String,
pub bevy_asset: String,
pub bevy_core: String,
pub bevy_utils: String,
pub bevy_app: String,
}

impl Modules {
pub fn meta(name: &str) -> Modules {
Modules {
bevy_asset: format!("{}::asset", name),
bevy_render: format!("{}::render", name),
bevy_core: format!("{}::core", name),
bevy_utils: format!("{}::utils", name),
bevy_app: format!("{}::app", name),
}
}

pub fn external() -> Modules {
Modules {
bevy_asset: "bevy_asset".to_string(),
bevy_render: "bevy_render".to_string(),
bevy_core: "bevy_core".to_string(),
bevy_utils: "bevy_utils".to_string(),
bevy_app: "bevy_app".to_string(),
}
}
}

fn get_meta() -> Option<Modules> {
let manifest = Manifest::new().unwrap();
if let Some(package) = manifest.find(|name| name == "bevy") {
Some(Modules::meta(&package.name))
} else if let Some(package) = manifest.find(|name| name == "bevy_internal") {
Some(Modules::meta(&package.name))
} else {
None
}
}

const AS_CRATE_ATTRIBUTE_NAME: &str = "as_crate";

fn validate_as_crate_attribute(tokens: &str) -> bool {
tokens.len() > 2 && tokens.starts_with('(') && tokens.ends_with(')')
}

pub fn get_modules(attributes: &[Attribute]) -> Modules {
let mut modules = get_meta().unwrap_or_else(Modules::external);
for attribute in attributes.iter() {
if *attribute.path.get_ident().as_ref().unwrap() == AS_CRATE_ATTRIBUTE_NAME {
let value = attribute.tokens.to_string();
if !validate_as_crate_attribute(&value) {
panic!("The attribute `#[as_crate{}]` is invalid. It must follow the format `#[as_crate(<crate name>)]`", value);
} else if value[1..value.len() - 1] == modules.bevy_render {
modules.bevy_render = "crate".to_string();
}
}
}

modules
}

pub fn get_path(path_str: &str) -> Path {
syn::parse(path_str.parse::<TokenStream>().unwrap()).unwrap()
}
pub const BEVY_APP: &str = "bevy_app";
pub const BEVY_ASSET: &str = "bevy_asset";
pub const BEVY_CORE: &str = "bevy_core";
pub const BEVY_RENDER: &str = "bevy_render";
pub const BEVY_UTILS: &str = "bevy_utils";
10 changes: 5 additions & 5 deletions crates/bevy_derive/src/render_resource.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use crate::modules::{get_modules, get_path};
use bevy_macro_utils::BevyManifest;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput, Path};

pub fn derive_render_resource(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let modules = get_modules(&ast.attrs);
let manifest = BevyManifest::default();

let bevy_render_path: Path = get_path(&modules.bevy_render);
let bevy_asset_path: Path = get_path(&modules.bevy_asset);
let bevy_core_path: Path = get_path(&modules.bevy_core);
let bevy_render_path: Path = manifest.get_path(crate::modules::BEVY_RENDER);
let bevy_asset_path: Path = manifest.get_path(crate::modules::BEVY_ASSET);
let bevy_core_path: Path = manifest.get_path(crate::modules::BEVY_CORE);
let struct_name = &ast.ident;
let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();

Expand Down
5 changes: 2 additions & 3 deletions crates/bevy_derive/src/render_resources.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::modules::{get_modules, get_path};
use bevy_macro_utils::BevyManifest;
use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::{
Expand All @@ -21,9 +21,8 @@ static RENDER_RESOURCE_ATTRIBUTE_NAME: &str = "render_resources";

pub fn derive_render_resources(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let modules = get_modules(&ast.attrs);

let bevy_render_path: Path = get_path(&modules.bevy_render);
let bevy_render_path: Path = BevyManifest::default().get_path(crate::modules::BEVY_RENDER);
let attributes = ast
.attrs
.iter()
Expand Down
9 changes: 2 additions & 7 deletions crates/bevy_derive/src/resource.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::modules::{get_modules, get_path};
use bevy_macro_utils::BevyManifest;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Fields};
Expand All @@ -13,16 +13,11 @@ pub fn derive_from_resources(input: TokenStream) -> TokenStream {
_ => panic!("Expected a struct with named fields."),
};

let modules = get_modules(&ast.attrs);
let bevy_app_path = get_path(&modules.bevy_app);

let bevy_app_path = BevyManifest::default().get_path(crate::modules::BEVY_APP);
let field_types = fields.iter().map(|field| &field.ty);

let fields = fields.iter().map(|field| field.ident.as_ref().unwrap());

let generics = ast.generics;
let (impl_generics, ty_generics, _where_clause) = generics.split_for_impl();

let struct_name = &ast.ident;

TokenStream::from(quote! {
Expand Down
5 changes: 2 additions & 3 deletions crates/bevy_derive/src/shader_defs.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::modules::{get_modules, get_path};
use bevy_macro_utils::BevyManifest;
use inflector::Inflector;
use proc_macro::TokenStream;
use proc_macro2::Ident;
Expand All @@ -9,8 +9,7 @@ static SHADER_DEF_ATTRIBUTE_NAME: &str = "shader_def";

pub fn derive_shader_defs(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let modules = get_modules(&ast.attrs);
let bevy_render_path: Path = get_path(&modules.bevy_render);
let bevy_render_path: Path = BevyManifest::default().get_path(crate::modules::BEVY_RENDER);

let fields = match &ast.data {
Data::Struct(DataStruct {
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_ecs/macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ license = "MIT"
proc-macro = true

[dependencies]
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.5.0" }

syn = "1.0"
quote = "1.0"
proc-macro2 = "1.0"
find-crate = "0.6"
23 changes: 2 additions & 21 deletions crates/bevy_ecs/macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
extern crate proc_macro;

use find_crate::{Dependencies, Manifest};
use bevy_macro_utils::BevyManifest;
use proc_macro::TokenStream;
use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::{format_ident, quote};
Expand Down Expand Up @@ -471,24 +471,5 @@ fn derive_label(input: DeriveInput, label_type: Ident) -> TokenStream2 {
}

fn bevy_ecs_path() -> syn::Path {
fn find_in_manifest(manifest: &mut Manifest, dependencies: Dependencies) -> Option<String> {
manifest.dependencies = dependencies;
if let Some(package) = manifest.find(|name| name == "bevy") {
Some(format!("{}::ecs", package.name))
} else if let Some(package) = manifest.find(|name| name == "bevy_internal") {
Some(format!("{}::ecs", package.name))
} else if let Some(package) = manifest.find(|name| name == "bevy_ecs") {
Some(package.name)
} else {
None
}
}

let mut manifest = Manifest::new().unwrap();
let path_str = find_in_manifest(&mut manifest, Dependencies::Release)
.or_else(|| find_in_manifest(&mut manifest, Dependencies::Dev))
.unwrap_or_else(|| "bevy_ecs".to_string());

let path: Path = syn::parse(path_str.parse::<TokenStream>().unwrap()).unwrap();
path
BevyManifest::default().get_path("bevy_ecs")
}
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub mod prelude {

#[cfg(test)]
mod tests {
use crate as bevy_ecs;
use crate::{
bundle::Bundle,
component::{Component, ComponentDescriptor, ComponentId, StorageType, TypeInfo},
Expand Down Expand Up @@ -78,7 +79,6 @@ mod tests {

#[test]
fn bundle_derive() {
use crate as bevy_ecs;
#[derive(Bundle, PartialEq, Debug)]
struct Foo {
x: &'static str,
Expand Down
18 changes: 18 additions & 0 deletions crates/bevy_macro_utils/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "bevy_macro_utils"
version = "0.5.0"
edition = "2018"
authors = [
"Bevy Contributors <bevyengine@gmail.com>",
"Carter Anderson <mcanders1@gmail.com>",
]
description = "A collection of utils for Bevy Engine"
YohDeadfall marked this conversation as resolved.
Show resolved Hide resolved
homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy"
license = "MIT"
keywords = ["bevy"]

[dependencies]
cargo-manifest = "0.2.3"
proc-macro2 = "1.0"
syn = "1.0"
61 changes: 61 additions & 0 deletions crates/bevy_macro_utils/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
extern crate proc_macro;

use cargo_manifest::{DepsSet, Manifest};
use proc_macro::TokenStream;
use std::{env, path::PathBuf};

pub struct BevyManifest {
manifest: Manifest,
}

impl Default for BevyManifest {
fn default() -> Self {
Self {
manifest: env::var_os("CARGO_MANIFEST_DIR")
.map(PathBuf::from)
.map(|mut path| {
path.push("Cargo.toml");
Manifest::from_path(path).unwrap()
})
.unwrap(),
}
}
}

impl BevyManifest {
pub fn get_path(&self, name: &str) -> syn::Path {
const BEVY: &str = "bevy";
const BEVY_INTERNAL: &str = "bevy_internal";

let find_in_deps = |deps: &DepsSet| -> Option<syn::Path> {
let package = if let Some(dep) = deps.get(BEVY) {
dep.package().unwrap_or(BEVY)
} else if let Some(dep) = deps.get(BEVY_INTERNAL) {
dep.package().unwrap_or(BEVY_INTERNAL)
} else {
return None;
};

let mut path = get_path(package);
if let Some(module) = name.strip_prefix("bevy_") {
path.segments.push(parse_str(module));
}
Some(path)
};

let deps = self.manifest.dependencies.as_ref();
let deps_dev = self.manifest.dev_dependencies.as_ref();

deps.and_then(find_in_deps)
.or_else(|| deps_dev.and_then(find_in_deps))
.unwrap_or_else(|| get_path(name))
}
}

fn get_path(path: &str) -> syn::Path {
parse_str(path)
}

fn parse_str<T: syn::parse::Parse>(path: &str) -> T {
syn::parse(path.parse::<TokenStream>().unwrap()).unwrap()
}
3 changes: 2 additions & 1 deletion crates/bevy_reflect/bevy_reflect_derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ keywords = ["bevy"]
proc-macro = true

[dependencies]
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.5.0" }

syn = "1.0"
proc-macro2 = "1.0"
quote = "1.0"
find-crate = "0.6"
uuid = { version = "0.8", features = ["v4", "serde"] }
Loading