Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pathological naming schemes can create clashing structs #66

Open
clux opened this issue May 2, 2022 · 1 comment
Open

pathological naming schemes can create clashing structs #66

clux opened this issue May 2, 2022 · 1 comment
Labels
bug Something isn't working help wanted Extra attention is needed

Comments

@clux
Copy link
Member

clux commented May 2, 2022

Problem

suppose you have a struct endpoints in the schema with properties:

  • metrics_relabelings (generating EndpointsMetricsRelabelings struct)
  • metrics (generating EndpointsMetrics struct)

suppose further that the metrics property in the schema has further properties:

  • relabelings (generating EndpointsMetricsRelabelings struct - a second time!)

I.e. it is possible to have multiple ways to reach the same struct names, and kopium does not handle this (it will emit multiple structs with the same name).

Potential workarounds

  • use smaller modules (mod Endpoints { mod Metrics {... to create a namespace for each struct level
  • naming disambiguation at insert time (we have the full list of OutputStruct available when adding another)

Leaning towards the latter, even though it will likely just be us suffixing numbers (EndpointsMetricsRelabelings2) to the struct and hoping the users do manual disambiguation where possible.

@clux clux added bug Something isn't working help wanted Extra attention is needed labels May 2, 2022
@clux
Copy link
Member Author

clux commented Mar 16, 2024

no one has actually complained about this happening yet, but if it does happen, it can be solved by us inside the output module by creating an Output wide analogue of Container::rename:

kopium/src/output.rs

Lines 83 to 128 in 561adae

pub fn rename(&mut self) {
let mut seen = vec![]; // track names we output to avoid generating duplicates
for (i, m) in self.members.iter_mut().enumerate() {
let mut new_name = if self.is_enum {
// There are no rust keywords that start uppercase,
// making this name always a valid identifier except if it contains
// or starts with an invalid character.
//
// `` -> `KopiumEmpty`
// `mod` -> `Mod`
// `301` -> `301` -> `r#301` -> `r#_301`
// `!=` -> `!=` -> `r#!=` -> `r#_!=` -> `KopiumVariant{i}`
let name = if m.name.is_empty() {
"KopiumEmpty".to_owned()
} else if m.name == "-" {
"KopiumDash".to_owned()
} else if m.name == "_" {
"KopiumUnderscore".to_owned()
} else {
m.name.to_pascal_case()
};
Container::try_escape_name(name).unwrap_or_else(|| format!("KopiumVariant{i}"))
} else if m.name == "-" {
"kopium_dash".to_owned()
} else if m.name == "_" {
"kopium_underscore".to_owned()
} else {
Container::try_escape_name(m.name.to_snake_case())
.unwrap_or_else(|| panic!("invalid field name '{}' could not be escaped", m.name))
};
// The new, Rust correct name MIGHT clash with existing names in degenerate cases
// such as those in https://github.com/kube-rs/kopium/issues/165
// so if duplicates are seen, we suffix an "X" to disamgiguate (repeatedly if needed)
while seen.contains(&new_name) {
let disambiguation_suffix = if self.is_enum { "X" } else { "_x" };
new_name = format!("{new_name}{disambiguation_suffix}"); // force disambiguate
}
seen.push(new_name.clone());
if new_name != m.name {
m.serde_annot.push(format!("rename = \"{}\"", m.name));
m.name = new_name;
}
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

1 participant