Skip to content

Commit 653c103

Browse files
YohDeadfallcart
andcommitted
Use bevy_reflect as path in case of no direct references (#1875)
Fixes #1844 Co-authored-by: Carter Anderson <[email protected]>
1 parent a42343d commit 653c103

File tree

25 files changed

+128
-213
lines changed

25 files changed

+128
-213
lines changed

crates/bevy_derive/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ keywords = ["bevy"]
1616
proc-macro = true
1717

1818
[dependencies]
19+
bevy_macro_utils = { path = "../bevy_macro_utils", version = "0.5.0" }
20+
1921
Inflector = { version = "0.11.4", default-features = false }
20-
find-crate = "0.6"
2122
proc-macro2 = "1.0"
2223
quote = "1.0"
2324
syn = "1.0"

crates/bevy_derive/src/bytes.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::modules::{get_modules, get_path};
1+
use bevy_macro_utils::BevyManifest;
22
use proc_macro::TokenStream;
33
use quote::quote;
44
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Fields};
@@ -13,8 +13,7 @@ pub fn derive_bytes(input: TokenStream) -> TokenStream {
1313
_ => panic!("Expected a struct with named fields."),
1414
};
1515

16-
let modules = get_modules(&ast.attrs);
17-
let bevy_core_path = get_path(&modules.bevy_core);
16+
let bevy_core_path = BevyManifest::default().get_path(crate::modules::BEVY_CORE);
1817

1918
let fields = fields
2019
.iter()

crates/bevy_derive/src/enum_variant_meta.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::modules::{get_modules, get_path};
1+
use bevy_macro_utils::BevyManifest;
22
use proc_macro::TokenStream;
33
use quote::quote;
44
use syn::{parse_macro_input, Data, DeriveInput};
@@ -10,8 +10,7 @@ pub fn derive_enum_variant_meta(input: TokenStream) -> TokenStream {
1010
_ => panic!("Expected an enum."),
1111
};
1212

13-
let modules = get_modules(&ast.attrs);
14-
let bevy_util_path = get_path(&modules.bevy_utils);
13+
let bevy_util_path = BevyManifest::default().get_path(crate::modules::BEVY_UTILS);
1514

1615
let generics = ast.generics;
1716
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

crates/bevy_derive/src/lib.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,33 @@ use proc_macro::TokenStream;
1414

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

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

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

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

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

59-
#[proc_macro_derive(EnumVariantMeta, attributes(as_crate))]
59+
#[proc_macro_derive(EnumVariantMeta)]
6060
pub fn derive_enum_variant_meta(input: TokenStream) -> TokenStream {
6161
enum_variant_meta::derive_enum_variant_meta(input)
6262
}

crates/bevy_derive/src/modules.rs

Lines changed: 5 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,5 @@
1-
use find_crate::Manifest;
2-
use proc_macro::TokenStream;
3-
use syn::{Attribute, Path};
4-
5-
#[derive(Debug)]
6-
pub struct Modules {
7-
pub bevy_render: String,
8-
pub bevy_asset: String,
9-
pub bevy_core: String,
10-
pub bevy_utils: String,
11-
pub bevy_app: String,
12-
}
13-
14-
impl Modules {
15-
pub fn meta(name: &str) -> Modules {
16-
Modules {
17-
bevy_asset: format!("{}::asset", name),
18-
bevy_render: format!("{}::render", name),
19-
bevy_core: format!("{}::core", name),
20-
bevy_utils: format!("{}::utils", name),
21-
bevy_app: format!("{}::app", name),
22-
}
23-
}
24-
25-
pub fn external() -> Modules {
26-
Modules {
27-
bevy_asset: "bevy_asset".to_string(),
28-
bevy_render: "bevy_render".to_string(),
29-
bevy_core: "bevy_core".to_string(),
30-
bevy_utils: "bevy_utils".to_string(),
31-
bevy_app: "bevy_app".to_string(),
32-
}
33-
}
34-
}
35-
36-
fn get_meta() -> Option<Modules> {
37-
let manifest = Manifest::new().unwrap();
38-
if let Some(package) = manifest.find(|name| name == "bevy") {
39-
Some(Modules::meta(&package.name))
40-
} else if let Some(package) = manifest.find(|name| name == "bevy_internal") {
41-
Some(Modules::meta(&package.name))
42-
} else {
43-
None
44-
}
45-
}
46-
47-
const AS_CRATE_ATTRIBUTE_NAME: &str = "as_crate";
48-
49-
fn validate_as_crate_attribute(tokens: &str) -> bool {
50-
tokens.len() > 2 && tokens.starts_with('(') && tokens.ends_with(')')
51-
}
52-
53-
pub fn get_modules(attributes: &[Attribute]) -> Modules {
54-
let mut modules = get_meta().unwrap_or_else(Modules::external);
55-
for attribute in attributes.iter() {
56-
if *attribute.path.get_ident().as_ref().unwrap() == AS_CRATE_ATTRIBUTE_NAME {
57-
let value = attribute.tokens.to_string();
58-
if !validate_as_crate_attribute(&value) {
59-
panic!("The attribute `#[as_crate{}]` is invalid. It must follow the format `#[as_crate(<crate name>)]`", value);
60-
} else if value[1..value.len() - 1] == modules.bevy_render {
61-
modules.bevy_render = "crate".to_string();
62-
}
63-
}
64-
}
65-
66-
modules
67-
}
68-
69-
pub fn get_path(path_str: &str) -> Path {
70-
syn::parse(path_str.parse::<TokenStream>().unwrap()).unwrap()
71-
}
1+
pub const BEVY_APP: &str = "bevy_app";
2+
pub const BEVY_ASSET: &str = "bevy_asset";
3+
pub const BEVY_CORE: &str = "bevy_core";
4+
pub const BEVY_RENDER: &str = "bevy_render";
5+
pub const BEVY_UTILS: &str = "bevy_utils";

crates/bevy_derive/src/render_resource.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
use crate::modules::{get_modules, get_path};
1+
use bevy_macro_utils::BevyManifest;
22
use proc_macro::TokenStream;
33
use quote::quote;
44
use syn::{parse_macro_input, DeriveInput, Path};
55

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

10-
let bevy_render_path: Path = get_path(&modules.bevy_render);
11-
let bevy_asset_path: Path = get_path(&modules.bevy_asset);
12-
let bevy_core_path: Path = get_path(&modules.bevy_core);
10+
let bevy_render_path: Path = manifest.get_path(crate::modules::BEVY_RENDER);
11+
let bevy_asset_path: Path = manifest.get_path(crate::modules::BEVY_ASSET);
12+
let bevy_core_path: Path = manifest.get_path(crate::modules::BEVY_CORE);
1313
let struct_name = &ast.ident;
1414
let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();
1515

crates/bevy_derive/src/render_resources.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::modules::{get_modules, get_path};
1+
use bevy_macro_utils::BevyManifest;
22
use proc_macro::TokenStream;
33
use quote::{format_ident, quote};
44
use syn::{
@@ -21,9 +21,8 @@ static RENDER_RESOURCE_ATTRIBUTE_NAME: &str = "render_resources";
2121

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

26-
let bevy_render_path: Path = get_path(&modules.bevy_render);
25+
let bevy_render_path: Path = BevyManifest::default().get_path(crate::modules::BEVY_RENDER);
2726
let attributes = ast
2827
.attrs
2928
.iter()

crates/bevy_derive/src/resource.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::modules::{get_modules, get_path};
1+
use bevy_macro_utils::BevyManifest;
22
use proc_macro::TokenStream;
33
use quote::quote;
44
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Fields};
@@ -13,16 +13,11 @@ pub fn derive_from_resources(input: TokenStream) -> TokenStream {
1313
_ => panic!("Expected a struct with named fields."),
1414
};
1515

16-
let modules = get_modules(&ast.attrs);
17-
let bevy_app_path = get_path(&modules.bevy_app);
18-
16+
let bevy_app_path = BevyManifest::default().get_path(crate::modules::BEVY_APP);
1917
let field_types = fields.iter().map(|field| &field.ty);
20-
2118
let fields = fields.iter().map(|field| field.ident.as_ref().unwrap());
22-
2319
let generics = ast.generics;
2420
let (impl_generics, ty_generics, _where_clause) = generics.split_for_impl();
25-
2621
let struct_name = &ast.ident;
2722

2823
TokenStream::from(quote! {

crates/bevy_derive/src/shader_defs.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::modules::{get_modules, get_path};
1+
use bevy_macro_utils::BevyManifest;
22
use inflector::Inflector;
33
use proc_macro::TokenStream;
44
use proc_macro2::Ident;
@@ -9,8 +9,7 @@ static SHADER_DEF_ATTRIBUTE_NAME: &str = "shader_def";
99

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

1514
let fields = match &ast.data {
1615
Data::Struct(DataStruct {

crates/bevy_ecs/macros/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ license = "MIT"
1313
proc-macro = true
1414

1515
[dependencies]
16+
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.5.0" }
17+
1618
syn = "1.0"
1719
quote = "1.0"
1820
proc-macro2 = "1.0"
19-
find-crate = "0.6"

crates/bevy_ecs/macros/src/lib.rs

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
extern crate proc_macro;
22

3-
use find_crate::{Dependencies, Manifest};
3+
use bevy_macro_utils::BevyManifest;
44
use proc_macro::TokenStream;
55
use proc_macro2::{Span, TokenStream as TokenStream2};
66
use quote::{format_ident, quote};
@@ -471,24 +471,5 @@ fn derive_label(input: DeriveInput, label_type: Ident) -> TokenStream2 {
471471
}
472472

473473
fn bevy_ecs_path() -> syn::Path {
474-
fn find_in_manifest(manifest: &mut Manifest, dependencies: Dependencies) -> Option<String> {
475-
manifest.dependencies = dependencies;
476-
if let Some(package) = manifest.find(|name| name == "bevy") {
477-
Some(format!("{}::ecs", package.name))
478-
} else if let Some(package) = manifest.find(|name| name == "bevy_internal") {
479-
Some(format!("{}::ecs", package.name))
480-
} else if let Some(package) = manifest.find(|name| name == "bevy_ecs") {
481-
Some(package.name)
482-
} else {
483-
None
484-
}
485-
}
486-
487-
let mut manifest = Manifest::new().unwrap();
488-
let path_str = find_in_manifest(&mut manifest, Dependencies::Release)
489-
.or_else(|| find_in_manifest(&mut manifest, Dependencies::Dev))
490-
.unwrap_or_else(|| "bevy_ecs".to_string());
491-
492-
let path: Path = syn::parse(path_str.parse::<TokenStream>().unwrap()).unwrap();
493-
path
474+
BevyManifest::default().get_path("bevy_ecs")
494475
}

crates/bevy_ecs/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub mod prelude {
3636

3737
#[cfg(test)]
3838
mod tests {
39+
use crate as bevy_ecs;
3940
use crate::{
4041
bundle::Bundle,
4142
component::{Component, ComponentDescriptor, ComponentId, StorageType, TypeInfo},
@@ -78,7 +79,6 @@ mod tests {
7879

7980
#[test]
8081
fn bundle_derive() {
81-
use crate as bevy_ecs;
8282
#[derive(Bundle, PartialEq, Debug)]
8383
struct Foo {
8484
x: &'static str,

crates/bevy_macro_utils/Cargo.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
name = "bevy_macro_utils"
3+
version = "0.5.0"
4+
edition = "2018"
5+
authors = [
6+
"Bevy Contributors <[email protected]>",
7+
"Carter Anderson <[email protected]>",
8+
]
9+
description = "A collection of utils for Bevy Engine"
10+
homepage = "https://bevyengine.org"
11+
repository = "https://github.com/bevyengine/bevy"
12+
license = "MIT"
13+
keywords = ["bevy"]
14+
15+
[dependencies]
16+
cargo-manifest = "0.2.3"
17+
proc-macro2 = "1.0"
18+
syn = "1.0"

crates/bevy_macro_utils/src/lib.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
extern crate proc_macro;
2+
3+
use cargo_manifest::{DepsSet, Manifest};
4+
use proc_macro::TokenStream;
5+
use std::{env, path::PathBuf};
6+
7+
pub struct BevyManifest {
8+
manifest: Manifest,
9+
}
10+
11+
impl Default for BevyManifest {
12+
fn default() -> Self {
13+
Self {
14+
manifest: env::var_os("CARGO_MANIFEST_DIR")
15+
.map(PathBuf::from)
16+
.map(|mut path| {
17+
path.push("Cargo.toml");
18+
Manifest::from_path(path).unwrap()
19+
})
20+
.unwrap(),
21+
}
22+
}
23+
}
24+
25+
impl BevyManifest {
26+
pub fn get_path(&self, name: &str) -> syn::Path {
27+
const BEVY: &str = "bevy";
28+
const BEVY_INTERNAL: &str = "bevy_internal";
29+
30+
let find_in_deps = |deps: &DepsSet| -> Option<syn::Path> {
31+
let package = if let Some(dep) = deps.get(BEVY) {
32+
dep.package().unwrap_or(BEVY)
33+
} else if let Some(dep) = deps.get(BEVY_INTERNAL) {
34+
dep.package().unwrap_or(BEVY_INTERNAL)
35+
} else {
36+
return None;
37+
};
38+
39+
let mut path = get_path(package);
40+
if let Some(module) = name.strip_prefix("bevy_") {
41+
path.segments.push(parse_str(module));
42+
}
43+
Some(path)
44+
};
45+
46+
let deps = self.manifest.dependencies.as_ref();
47+
let deps_dev = self.manifest.dev_dependencies.as_ref();
48+
49+
deps.and_then(find_in_deps)
50+
.or_else(|| deps_dev.and_then(find_in_deps))
51+
.unwrap_or_else(|| get_path(name))
52+
}
53+
}
54+
55+
fn get_path(path: &str) -> syn::Path {
56+
parse_str(path)
57+
}
58+
59+
fn parse_str<T: syn::parse::Parse>(path: &str) -> T {
60+
syn::parse(path.parse::<TokenStream>().unwrap()).unwrap()
61+
}

crates/bevy_reflect/bevy_reflect_derive/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ keywords = ["bevy"]
1616
proc-macro = true
1717

1818
[dependencies]
19+
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.5.0" }
20+
1921
syn = "1.0"
2022
proc-macro2 = "1.0"
2123
quote = "1.0"
22-
find-crate = "0.6"
2324
uuid = { version = "0.8", features = ["v4", "serde"] }

0 commit comments

Comments
 (0)