use regex::Regex;
pub(crate) fn normalize_signature(sig: &str) -> String {
let normalized: String = sig.split_whitespace().collect::<Vec<_>>().join(" ");
let normalized = Regex::new(r",\s*\)")
.unwrap()
.replace_all(&normalized, ")")
.to_string();
let normalized = Regex::new(r"\b(?:\w+::)+(\w+)")
.unwrap()
.replace_all(&normalized, "$1")
.to_string();
let normalized = Regex::new(r"\bmut\s+")
.unwrap()
.replace_all(&normalized, "")
.to_string();
normalized
}
pub(crate) fn tokenize_signature(sig: &str) -> Vec<String> {
let sig = normalize_signature(sig);
let mut tokens = Vec::new();
let mut current = String::new();
for ch in sig.chars() {
if ch.is_alphanumeric() || ch == '_' {
current.push(ch);
} else if ch.is_whitespace() {
if !current.is_empty() {
tokens.push(std::mem::take(&mut current));
}
} else {
if !current.is_empty() {
tokens.push(std::mem::take(&mut current));
}
if ch == '-' {
current.push(ch);
} else if ch == '>' && current == "-" {
current.push(ch);
tokens.push(std::mem::take(&mut current));
} else {
if !current.is_empty() {
tokens.push(std::mem::take(&mut current));
}
tokens.push(ch.to_string());
}
}
}
if !current.is_empty() {
tokens.push(current);
}
tokens
}
pub(crate) fn compute_signature_skeleton(
tokenized_sigs: &[Vec<String>],
) -> Option<Vec<Option<String>>> {
if tokenized_sigs.is_empty() {
return None;
}
let expected_len = tokenized_sigs[0].len();
if !tokenized_sigs.iter().all(|t| t.len() == expected_len) {
return None;
}
let mut skeleton = Vec::with_capacity(expected_len);
for i in 0..expected_len {
let first = &tokenized_sigs[0][i];
if tokenized_sigs.iter().all(|t| &t[i] == first) {
skeleton.push(Some(first.clone()));
} else {
skeleton.push(None); }
}
Some(skeleton)
}