Skip to content

Commit

Permalink
Shared module path detection for macroses
Browse files Browse the repository at this point in the history
  • Loading branch information
YohDeadfall committed Apr 25, 2021
1 parent 1f3cd35 commit 9a0eebe
Show file tree
Hide file tree
Showing 17 changed files with 119 additions and 176 deletions.
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 crate::modules::get_modules;
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 = get_modules(&ast.attrs).bevy_core;

let fields = fields
.iter()
Expand Down
60 changes: 14 additions & 46 deletions crates/bevy_derive/src/modules.rs
Original file line number Diff line number Diff line change
@@ -1,62 +1,30 @@
use find_crate::Manifest;
use proc_macro::TokenStream;
use syn::{Attribute, Path};
use bevy_macro_utils::{get_module_path, get_path};
use syn::Attribute;

#[derive(Debug)]
pub struct Modules {
pub bevy_render: String,
pub bevy_asset: String,
pub bevy_core: 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_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_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
}
pub bevy_render: syn::Path,
pub bevy_asset: syn::Path,
pub bevy_core: syn::Path,
pub bevy_app: syn::Path,
}

const AS_CRATE_ATTRIBUTE_NAME: &str = "as_crate";

pub fn get_modules(attributes: &[Attribute]) -> Modules {
let mut modules = get_meta().unwrap_or_else(Modules::external);
let mut modules = Modules {
bevy_render: get_module_path("bevy_render"),
bevy_asset: get_module_path("bevy_asset"),
bevy_core: get_module_path("bevy_core"),
bevy_app: get_module_path("bevy_app"),
};
for attribute in attributes.iter() {
if *attribute.path.get_ident().as_ref().unwrap() == AS_CRATE_ATTRIBUTE_NAME {
let value = attribute.tokens.to_string();
if value[1..value.len() - 1] == modules.bevy_render {
modules.bevy_render = "crate".to_string();
if get_path(&value[1..value.len() - 1]) == modules.bevy_render {
modules.bevy_render = get_path("crate");
}
}
}

modules
}

pub fn get_path(path_str: &str) -> Path {
syn::parse(path_str.parse::<TokenStream>().unwrap()).unwrap()
}
8 changes: 4 additions & 4 deletions crates/bevy_derive/src/render_resource.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::modules::{get_modules, get_path};
use crate::modules::get_modules;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput, Path};
Expand All @@ -7,9 +7,9 @@ pub fn derive_render_resource(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_asset_path: Path = get_path(&modules.bevy_asset);
let bevy_core_path: Path = get_path(&modules.bevy_core);
let bevy_render_path: Path = modules.bevy_render;
let bevy_asset_path: Path = modules.bevy_asset;
let bevy_core_path: Path = modules.bevy_core;
let struct_name = &ast.ident;

TokenStream::from(quote! {
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 crate::modules::get_modules;
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 = get_modules(&ast.attrs).bevy_render;
let attributes = ast
.attrs
.iter()
Expand Down
5 changes: 2 additions & 3 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 crate::modules::get_modules;
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_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 = get_modules(&ast.attrs).bevy_app;

let field_types = fields.iter().map(|field| &field.ty);

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 crate::modules::get_modules;
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 = get_modules(&ast.attrs).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"
27 changes: 4 additions & 23 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::get_module_path;
use proc_macro::TokenStream;
use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::{format_ident, quote};
Expand Down Expand Up @@ -118,13 +118,13 @@ pub fn derive_bundle(input: TokenStream) -> TokenStream {
{
if *is_bundle {
field_type_infos.push(quote! {
type_info.extend(#field_type::type_info());
type_info.extend(<#field_type as #ecs_path::bundle::Bundle>::type_info());
});
field_get_components.push(quote! {
self.#field.get_components(&mut func);
});
field_from_components.push(quote! {
#field: #field_type::from_components(&mut func),
#field: <#field_type as #ecs_path::bundle::Bundle>::from_components(&mut func),
});
} else {
field_type_infos.push(quote! {
Expand Down Expand Up @@ -465,24 +465,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
get_module_path("bevy_ecs")
}
1 change: 0 additions & 1 deletion crates/bevy_ecs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,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"
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"
58 changes: 58 additions & 0 deletions crates/bevy_macro_utils/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
extern crate proc_macro;

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

pub fn get_module_path(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) {
Some(dep.package().unwrap_or(BEVY))
} else if let Some(dep) = deps.get(BEVY_INTERNAL) {
Some(dep.package().unwrap_or(BEVY_INTERNAL))
} else {
None
};

package.map(get_path).map(|mut p| {
if name.starts_with("bevy_") {
p.segments.push(parse_path(&name[5..]));
}
p
})
};

let manifest = env::var_os("CARGO_MANIFEST_DIR")
.map(PathBuf::from)
.map(|mut path| {
path.push("Cargo.toml");
Manifest::from_path(path).unwrap()
})
.unwrap();
let deps = manifest.dependencies;
let deps_dev = manifest.dev_dependencies;

manifest
.package
.and_then(|p| {
if p.name == name {
Some(get_path("crate"))
} else {
None
}
})
.or_else(|| deps.and_then(find_in_deps))
.or_else(|| deps_dev.and_then(find_in_deps))
.unwrap_or_else(|| get_path(name))
}

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

fn parse_path<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"
cargo-manifest = "0.2.3"
uuid = { version = "0.8", features = ["v4", "serde"] }
8 changes: 3 additions & 5 deletions crates/bevy_reflect/bevy_reflect_derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
extern crate proc_macro;

mod modules;
mod reflect_trait;
mod type_uuid;

use modules::{get_modules, get_path};
use bevy_macro_utils::get_module_path;
use proc_macro::TokenStream;
use proc_macro2::Span;
use quote::quote;
Expand Down Expand Up @@ -105,8 +104,7 @@ pub fn derive_reflect(input: TokenStream) -> TokenStream {
.map(|(f, _attr, i)| (*f, *i))
.collect::<Vec<(&Field, usize)>>();

let modules = get_modules();
let bevy_reflect_path = get_path(&modules.bevy_reflect);
let bevy_reflect_path = get_module_path("bevy_reflect");
let type_name = &ast.ident;

let mut reflect_attrs = ReflectAttrs::default();
Expand Down Expand Up @@ -557,7 +555,7 @@ impl Parse for ReflectDef {
pub fn impl_reflect_value(input: TokenStream) -> TokenStream {
let reflect_value_def = parse_macro_input!(input as ReflectDef);

let bevy_reflect_path = get_path(&get_modules().bevy_reflect);
let bevy_reflect_path = get_module_path("bevy_reflect");
let ty = &reflect_value_def.type_name;
let reflect_attrs = reflect_value_def
.attrs
Expand Down
Loading

0 comments on commit 9a0eebe

Please sign in to comment.