use super::{pyi_docstring, python_safe_name, substitute_capsule_type};
use crate::backends::pyo3::type_map::python_type;
use crate::core::config::TraitBridgeConfig;
use crate::core::ir::ApiSurface;
pub(super) fn gen_visitor_protocol_stub(
bridge: &TraitBridgeConfig,
api: &ApiSurface,
capsule_names: &std::collections::HashSet<&str>,
emit_docstrings: bool,
) -> Option<String> {
let methods = bridge.resolve_methods(api);
if methods.is_empty() {
return None;
}
let trait_def = api.types.iter().find(|t| t.name == bridge.trait_name)?;
let mut lines = vec![format!("class {}(Protocol):", bridge.trait_name)];
if emit_docstrings {
if let Some(docstring) = pyi_docstring(&trait_def.doc, " ") {
lines.push(docstring);
}
}
let mut body_emitted = false;
for method in methods {
if method.binding_excluded {
continue;
}
body_emitted = true;
let mut params: Vec<String> = vec!["self".to_string()];
for p in &method.params {
let param_type = substitute_capsule_type(&python_type(&p.ty), capsule_names);
params.push(format!("{}: {}", p.name, param_type));
}
let return_type = substitute_capsule_type(&python_type(&method.return_type), capsule_names);
let safe_name = python_safe_name(&method.name);
let def_kw = if method.is_async { "async def" } else { "def" };
let signature = format!(
" {} {}({}) -> {}: ...",
def_kw,
safe_name,
params.join(", "),
return_type
);
lines.push(signature);
}
if !body_emitted {
lines.push(" ...".to_string());
}
Some(lines.join("\n"))
}