use pedant_core::resolution::rust::{
CargoTargetKind, DependencyActivation, PackageId, RustProject, RustResolutionSnapshot,
RustResolutionUnit, RustSnapshotError, RustSnapshotUnitId, RustTargetSnapshot,
SourceClosureFailureKind, TargetId,
};
pub fn target_id(
project: &RustProject,
package: &str,
kind: CargoTargetKind,
name: &str,
) -> TargetId {
project
.targets()
.iter()
.find(|target| {
target.kind() == kind
&& target.name() == name
&& project
.package(target.package())
.is_some_and(|owner| owner.name() == package)
})
.map(|target| target.id())
.unwrap_or_else(|| panic!("{package} declares no {kind:?} target named {name}"))
}
pub fn app_library(project: &RustProject) -> TargetId {
target_id(project, "app", CargoTargetKind::Library, "app")
}
pub fn sole_library(project: &RustProject) -> TargetId {
let libraries: Vec<TargetId> = project
.targets()
.iter()
.filter(|target| target.kind() == CargoTargetKind::Library)
.map(|target| target.id())
.collect();
match libraries.as_slice() {
[only] => *only,
found => panic!("the fixture declares {} library targets", found.len()),
}
}
pub fn package_name(project: &RustProject, id: PackageId) -> &str {
project
.package(id)
.map(|package| package.name())
.unwrap_or("<unknown>")
}
pub fn target_name(project: &RustProject, id: TargetId) -> &str {
project
.target(id)
.map(|target| target.name())
.unwrap_or("<unknown>")
}
pub fn activation_text(activation: &DependencyActivation) -> &str {
match activation {
DependencyActivation::Always => "always",
DependencyActivation::Conditional(condition) => condition,
}
}
#[cfg(feature = "resolution-test-support")]
pub fn observed_paths(paths: &[Box<str>]) -> Vec<&str> {
paths.iter().map(|path| &**path).collect()
}
pub fn closure_kinds(error: &RustSnapshotError) -> Vec<SourceClosureFailureKind> {
closure_of(error)
.failures()
.iter()
.map(|entry| entry.kind())
.collect()
}
pub fn reached_paths(error: &RustSnapshotError) -> Vec<String> {
closure_of(error)
.reached()
.iter()
.map(|path| path.to_string())
.collect()
}
fn closure_of(error: &RustSnapshotError) -> &pedant_core::resolution::rust::SourceClosureError {
match error {
RustSnapshotError::SourceClosure(closure) => closure,
other => panic!("expected a source-closure failure, got {other:?}"),
}
}
pub fn render_scopes(snapshot: &RustResolutionSnapshot, path: &str) -> Vec<String> {
snapshot
.source(path)
.unwrap_or_else(|| panic!("{path} is not a source of this snapshot"))
.ir()
.module_scopes
.iter()
.enumerate()
.map(|(index, scope)| format!("{index}|{}|{:?}", scope.name, scope.parent))
.collect()
}
pub fn source_paths(snapshot: &RustTargetSnapshot) -> Vec<&str> {
snapshot
.sources()
.iter()
.map(|source| source.path())
.collect()
}
pub fn render_modules(unit: &RustResolutionUnit) -> Vec<String> {
unit.modules()
.iter()
.map(|instance| {
format!(
"{:?}|{}|{}|{}|{}|{:?}",
instance.id(),
instance.name(),
instance.path(),
instance.depth(),
instance.is_inline(),
instance.parent(),
)
})
.collect()
}
pub fn root_modules(project: &RustProject, target: TargetId) -> Vec<String> {
let snapshot = project
.snapshot_resolution(target)
.expect("the target resolves against its own unit");
let root = snapshot.unit(snapshot.root_unit()).expect("the root unit");
render_modules(root)
}
pub fn render_units(project: &RustProject, snapshot: &RustResolutionSnapshot) -> Vec<String> {
snapshot
.units()
.iter()
.map(|unit| {
format!(
"{}|{}|{}",
package_name(project, unit.package()),
target_name(project, unit.target()),
activation_text(unit.activation()),
)
})
.collect()
}
pub fn render_edges(project: &RustProject, snapshot: &RustResolutionSnapshot) -> Vec<String> {
snapshot
.edges()
.iter()
.map(|edge| {
format!(
"{}|{}|{}|{:?}|{}",
unit_package(project, snapshot, edge.source()),
edge.name(),
unit_package(project, snapshot, edge.target()),
edge.kind(),
activation_text(edge.activation()),
)
})
.collect()
}
pub fn render_unit_sources(
project: &RustProject,
snapshot: &RustResolutionSnapshot,
) -> Vec<String> {
snapshot
.units()
.iter()
.map(|unit| {
let sources: Vec<&str> = unit.sources().iter().map(|path| &**path).collect();
format!(
"{}|{}",
package_name(project, unit.package()),
sources.join(",")
)
})
.collect()
}
pub fn unit_of<'a>(
project: &RustProject,
snapshot: &'a RustResolutionSnapshot,
package: &str,
) -> &'a RustResolutionUnit {
snapshot
.units()
.iter()
.find(|unit| package_name(project, unit.package()) == package)
.unwrap_or_else(|| panic!("{package} contributes no unit"))
}
fn unit_package<'a>(
project: &'a RustProject,
snapshot: &RustResolutionSnapshot,
unit: RustSnapshotUnitId,
) -> &'a str {
snapshot
.unit(unit)
.map(|found| package_name(project, found.package()))
.unwrap_or("<unknown>")
}