use super::type_infer::{MethodLocation, WorkspaceTypeIndex};
use crate::adapters::analyzers::architecture::layer_rule::LayerDefinitions;
use std::collections::HashSet;
#[derive(Debug, Clone)]
pub(crate) struct AnchorInfo {
pub(crate) impl_layers: HashSet<String>,
pub(crate) impl_method_canonicals: HashSet<String>,
pub(crate) decl_layer: Option<String>,
pub(crate) has_default_body: bool,
pub(crate) trait_visible: bool,
pub(crate) location: Option<MethodLocation>,
}
pub(crate) fn is_anchor_target_capability(
info: &AnchorInfo,
target_layer: &str,
adapter_layers: &[String],
) -> bool {
if !info.trait_visible {
return false;
}
if let Some(decl) = info.decl_layer.as_deref() {
if decl != target_layer && adapter_layers.iter().any(|a| a == decl) {
return false;
}
if decl == target_layer
&& (info.has_default_body || info.impl_layers.contains(target_layer))
{
return true;
}
}
info.impl_layers.contains(target_layer)
}
pub(crate) struct TraitAnchorMeta<'a> {
pub canonical: &'a str,
pub decl_layer: &'a Option<String>,
pub visible: bool,
}
pub(crate) fn build_anchor_info(
type_index: &WorkspaceTypeIndex,
layers: &LayerDefinitions,
trait_meta: &TraitAnchorMeta<'_>,
method: &str,
) -> AnchorInfo {
let overriding = type_index.overriding_impls_for(trait_meta.canonical, method);
let impl_layers: HashSet<String> = overriding
.iter()
.filter_map(|impl_canon| layers.layer_of_crate_path(impl_canon).map(String::from))
.collect();
let impl_method_canonicals: HashSet<String> = overriding
.iter()
.map(|impl_canon| format!("{impl_canon}::{method}"))
.collect();
let location = type_index
.trait_method_location(trait_meta.canonical, method)
.cloned();
let has_default_body = type_index.trait_method_has_default_body(trait_meta.canonical, method);
AnchorInfo {
impl_layers,
impl_method_canonicals,
decl_layer: trait_meta.decl_layer.clone(),
has_default_body,
trait_visible: trait_meta.visible,
location,
}
}