use crate::core::hash::{self, CommentStyle};
pub(super) fn strip_trailing_whitespace(content: &str) -> String {
let mut result: String = content
.lines()
.map(|line| line.trim_end())
.collect::<Vec<_>>()
.join("\n");
if !result.ends_with('\n') {
result.push('\n');
}
result
}
pub(super) fn csharp_file_header() -> String {
let mut out = hash::header(CommentStyle::DoubleSlash);
out.push_str("#nullable enable\n\n");
out
}
pub(super) fn gen_directory_build_props() -> String {
"<!-- auto-generated by alef (generate_bindings) -->\n\
<Project>\n \
<PropertyGroup>\n \
<Nullable>enable</Nullable>\n \
<LangVersion>latest</LangVersion>\n \
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>\n \
</PropertyGroup>\n\
</Project>\n"
.to_string()
}
pub(super) fn delete_superseded_visitor_files(base_path: &std::path::Path) -> anyhow::Result<()> {
let superseded = ["IVisitor.cs", "VisitorCallbacks.cs"];
for filename in superseded {
let path = base_path.join(filename);
if path.exists() {
std::fs::remove_file(&path)
.map_err(|e| anyhow::anyhow!("Failed to delete superseded visitor file {}: {}", path.display(), e))?;
}
}
Ok(())
}
pub(super) fn delete_stale_visitor_files(
base_path: &std::path::Path,
config: &crate::core::config::ResolvedCrateConfig,
) -> anyhow::Result<()> {
let mut stale_files = vec!["IVisitor.cs".to_string(), "VisitorCallbacks.cs".to_string()];
stale_files.extend(config.trait_bridges.iter().filter_map(|bridge| {
bridge
.context_type
.as_deref()
.map(|name| format!("{}.cs", crate::codegen::naming::csharp_type_name(name)))
}));
stale_files.extend(config.trait_bridges.iter().filter_map(|bridge| {
bridge
.result_type
.as_deref()
.map(|name| format!("{}.cs", crate::codegen::naming::csharp_type_name(name)))
}));
for filename in stale_files {
let path = base_path.join(filename);
if path.exists() {
std::fs::remove_file(&path)
.map_err(|e| anyhow::anyhow!("Failed to delete stale visitor file {}: {}", path.display(), e))?;
}
}
Ok(())
}