use crate::core::config::ResolvedCrateConfig;
use crate::core::ir::{ApiSurface, ParamDef, ServiceDef, TypeRef};
use std::collections::HashSet;
pub(super) fn effective_exclude_types(api: &ApiSurface, config: &ResolvedCrateConfig) -> HashSet<String> {
let mut exclude_types: HashSet<String> = config
.ffi
.as_ref()
.map(|ffi| ffi.exclude_types.iter().cloned().collect())
.unwrap_or_default();
if let Some(java) = &config.java {
exclude_types.extend(java.exclude_types.iter().cloned());
}
exclude_types.extend(api.types.iter().filter(|t| t.binding_excluded).map(|t| t.name.clone()));
exclude_types.extend(
config
.opaque_types
.iter()
.filter(|(_, path)| path.contains('<'))
.map(|(name, _)| name.clone()),
);
exclude_types
}
pub(super) fn lifetime_bound_type_names(api: &ApiSurface) -> HashSet<String> {
api.types
.iter()
.filter(|t| t.has_lifetime_params)
.map(|t| t.name.clone())
.collect()
}
pub(super) fn should_filter_excluded_types(api: &ApiSurface, exclude_types: &HashSet<String>) -> bool {
!exclude_types.is_empty() || !api.services.is_empty()
}
fn references_excluded_type(ty: &TypeRef, exclude_types: &HashSet<String>) -> bool {
exclude_types.iter().any(|name| ty.references_named(name))
}
fn signature_references_excluded_type(
params: &[ParamDef],
return_type: &TypeRef,
exclude_types: &HashSet<String>,
) -> bool {
references_excluded_type(return_type, exclude_types)
|| params
.iter()
.any(|param| references_excluded_type(¶m.ty, exclude_types))
}
fn service_references_excluded_type(service: &ServiceDef, excluded: &HashSet<String>) -> bool {
excluded.contains(&service.name)
|| signature_references_excluded_type(&service.constructor.params, &service.constructor.return_type, excluded)
|| service
.configurators
.iter()
.any(|method| signature_references_excluded_type(&method.params, &method.return_type, excluded))
|| service.registrations.iter().any(|registration| {
signature_references_excluded_type(®istration.metadata_params, ®istration.return_type, excluded)
|| registration.variants.iter().any(|variant| {
variant
.signature_params
.iter()
.any(|param| references_excluded_type(¶m.ty, excluded))
})
})
|| service
.entrypoints
.iter()
.any(|entrypoint| signature_references_excluded_type(&entrypoint.params, &entrypoint.return_type, excluded))
}
pub(super) fn api_without_excluded_types(api: &ApiSurface, exclude_types: &HashSet<String>) -> ApiSurface {
let lifetime_bound_types = lifetime_bound_type_names(api);
let mut filtered = api.clone();
filtered.services.retain(|service| {
!service_references_excluded_type(service, exclude_types)
&& !service_references_excluded_type(service, &lifetime_bound_types)
});
filtered.types.retain(|typ| !exclude_types.contains(&typ.name));
for typ in &mut filtered.types {
typ.fields
.retain(|field| !references_excluded_type(&field.ty, exclude_types));
if !typ.is_trait {
typ.methods.retain(|method| {
!signature_references_excluded_type(&method.params, &method.return_type, exclude_types)
});
}
}
filtered
.enums
.retain(|enum_def| !exclude_types.contains(&enum_def.name));
for enum_def in &mut filtered.enums {
for variant in &mut enum_def.variants {
variant
.fields
.retain(|field| !references_excluded_type(&field.ty, exclude_types));
}
}
filtered
.functions
.retain(|func| !signature_references_excluded_type(&func.params, &func.return_type, exclude_types));
filtered.errors.retain(|error| !exclude_types.contains(&error.name));
filtered
}