use crate::core::backend::TraitBridgeRegistrationSurface;
use crate::core::config::{BridgeBinding, Language, ResolvedCrateConfig};
use crate::core::ir::ApiSurface;
use heck::ToPascalCase;
pub(crate) fn trait_pascal(trait_name: &str) -> String {
trait_name.to_pascal_case()
}
pub(crate) fn bridge_class_name(trait_pascal: &str) -> String {
format!("{trait_pascal}Bridge")
}
pub(crate) fn register_method_name(trait_pascal: &str) -> String {
format!("register{trait_pascal}")
}
pub(crate) fn unregister_method_name(trait_pascal: &str) -> String {
format!("unregister{trait_pascal}")
}
pub(crate) fn clear_method_name(clear_fn: &str) -> String {
let without_prefix = clear_fn.strip_prefix("clear_").unwrap_or(clear_fn);
let mut camel = String::from("clear");
for word in without_prefix.split('_') {
let mut chars = word.chars();
if let Some(first) = chars.next() {
camel.extend(first.to_uppercase());
camel.push_str(chars.as_str());
}
}
camel
}
pub(crate) fn registration_surface(
api: &ApiSurface,
config: &ResolvedCrateConfig,
has_visitor_pattern: bool,
) -> Vec<TraitBridgeRegistrationSurface> {
let java = Language::Java.to_string();
config
.trait_bridges
.iter()
.filter(|bridge| !bridge.exclude_languages.contains(&java))
.filter(|bridge| !(has_visitor_pattern && bridge.bind_via == BridgeBinding::OptionsField))
.filter_map(|bridge| {
let trait_def = api.types.iter().find(|t| t.name == bridge.trait_name && t.is_trait)?;
let pascal = trait_pascal(&trait_def.name);
let bridge_class = bridge_class_name(&pascal);
Some(TraitBridgeRegistrationSurface {
trait_name: trait_def.name.clone(),
register_symbol: Some(format!("{bridge_class}.{}", register_method_name(&pascal))),
unregister_symbol: bridge
.unregister_fn
.as_ref()
.map(|_| format!("{bridge_class}.{}", unregister_method_name(&pascal))),
clear_symbol: bridge
.clear_fn
.as_deref()
.map(|clear_fn| format!("{bridge_class}.{}", clear_method_name(clear_fn))),
})
})
.collect()
}