use std::collections::HashMap;
use syn::Ident;
use crate::{
conversion::{api::Api, error_reporter::convert_item_apis, ConvertError},
types::{validate_ident_ok_for_cxx, QualifiedName},
};
use super::fun::FnAnalysis;
pub(crate) fn check_names(apis: Vec<Api<FnAnalysis>>) -> Vec<Api<FnAnalysis>> {
let mut intermediate = Vec::new();
convert_item_apis(apis, &mut intermediate, |api| match api {
Api::Typedef { ref name, .. }
| Api::ForwardDeclaration { ref name, .. }
| Api::Const { ref name, .. }
| Api::Enum { ref name, .. }
| Api::Struct { ref name, .. } => {
validate_all_segments_ok_for_cxx(name.name.segment_iter())?;
if let Some(ref cpp_name) = name.cpp_name {
validate_all_segments_ok_for_cxx(
QualifiedName::new_from_cpp_name(cpp_name).segment_iter(),
)?;
}
Ok(Some(api))
}
Api::Function { ref name, .. } => {
validate_all_segments_ok_for_cxx(name.name.segment_iter())?;
Ok(Some(api))
}
Api::ConcreteType { .. }
| Api::CType { .. }
| Api::StringConstructor { .. }
| Api::IgnoredItem { .. } => Ok(Some(api)),
});
let mut names_found: HashMap<Ident, usize> = HashMap::new();
for api in &intermediate {
let my_name = api.cxxbridge_name();
if let Some(name) = my_name {
let e = names_found.entry(name).or_default();
*e += 1usize;
}
}
let mut results = Vec::new();
convert_item_apis(intermediate, &mut results, |api| {
let my_name = api.cxxbridge_name();
if let Some(name) = my_name {
if *names_found.entry(name).or_default() > 1usize {
Err(ConvertError::DuplicateCxxBridgeName)
} else {
Ok(Some(api))
}
} else {
Ok(Some(api))
}
});
results
}
fn validate_all_segments_ok_for_cxx(
items: impl Iterator<Item = String>,
) -> Result<(), ConvertError> {
for seg in items {
validate_ident_ok_for_cxx(&seg)?;
}
Ok(())
}