use cargo_metadata::{Metadata, MetadataCommand, Package, Target};
use once_cell::sync::{Lazy, OnceCell};
use proc_macro::Span;
pub static CONTEXT: Lazy<Context> = Lazy::new(|| {
let metadata = MetadataCommand::new().exec().unwrap();
Context { metadata }
});
pub struct Context {
pub metadata: Metadata,
}
impl Context {
pub fn packages(&'static self) -> &'static [&'static Package] {
static PACKAGES: OnceCell<Vec<&'static Package>> = OnceCell::new();
PACKAGES
.get_or_init(|| {
self.metadata
.root_package()
.into_iter()
.chain(self.metadata.workspace_packages())
.collect::<Vec<_>>()
})
.as_slice()
}
pub fn get_target_and_package_of(
&'static self,
span: &Span,
) -> (&'static Target, &'static Package) {
let source_path = span.file();
for &package in self.packages() {
for target in &package.targets {
if target.src_path.ends_with(&source_path) {
return (target, package);
}
}
}
unreachable!()
}
}