From 9a9a10b3595590f1aa836d756e5e7793a7e6fcdd Mon Sep 17 00:00:00 2001 From: Steven Crake Date: Sat, 28 Jun 2025 11:28:53 +0100 Subject: [PATCH] Replace periods with underscores in Rust model names Fix issue where period-delimited model names (e.g. microsoft.graph.fido2AuthenticationMethod) were being converted to unwieldy names with "Period" substitutions. Now periods are replaced with underscores like hyphens, resulting in cleaner and more idiomatic Rust identifiers. Fixes #15254 --- .../languages/AbstractRustCodegen.java | 4 +- .../codegen/rust/AbstractRustCodegenTest.java | 4 + .../.openapi-generator/FILES | 2 +- .../README.md | 2 +- ...quareBracketModelNameRightSquareBracket.md | 10 +++ .../src/models.rs | 76 +++++++++---------- 6 files changed, 56 insertions(+), 42 deletions(-) create mode 100644 samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/docs/DollarSpecialLeftSquareBracketModelNameRightSquareBracket.md diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractRustCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractRustCodegen.java index 4d32067a79e4..39e888bae0f7 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractRustCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractRustCodegen.java @@ -183,8 +183,8 @@ public String sanitizeIdentifier(String name, CasingType casingType, String esca throw new IllegalArgumentException("Unknown CasingType"); } - // Replace hyphens with underscores - name = name.replaceAll("-", "_"); + // Replace hyphens and periods with underscores + name = name.replaceAll("[\\.\\-]", "_"); // Apply special character escapes, e.g. "@type" => "At_type" // Remove the trailing underscore if necessary diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/rust/AbstractRustCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/rust/AbstractRustCodegenTest.java index e73753b2a1c7..300e0b9566c3 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/rust/AbstractRustCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/rust/AbstractRustCodegenTest.java @@ -36,6 +36,10 @@ public void testSanitizeIdentifier() { // Hyphens should be replaced (https://github.com/OpenAPITools/openapi-generator/commit/4cb7f1d6135aa3a42ff38cf89771105c40e7e5a9) Assert.assertEquals(sanitizeSnakeCase.apply("pet-name"), "pet_name"); + // Periods should be replaced with underscores (https://github.com/OpenAPITools/openapi-generator/issues/15254) + Assert.assertEquals(sanitizeSnakeCase.apply("microsoft.graph.fido2AuthenticationMethod"), "microsoft_graph_fido2_authentication_method"); + Assert.assertEquals(sanitizeCamelCase.apply("microsoft.graph.user"), "MicrosoftGraphUser"); + // Special character mappings are applied Assert.assertEquals(sanitizeSnakeCase.apply("@type"), "at_type"); Assert.assertEquals(sanitizeCamelCase.apply("@type"), "AtType"); diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/.openapi-generator/FILES b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/.openapi-generator/FILES index e515b3eb7511..6d35ed812fa6 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/.openapi-generator/FILES +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/.openapi-generator/FILES @@ -17,7 +17,7 @@ docs/Category.md docs/ClassModel.md docs/Client.md docs/Dog.md -docs/DollarSpecialLeftSquareBracketModelPeriodNameRightSquareBracket.md +docs/DollarSpecialLeftSquareBracketModelNameRightSquareBracket.md docs/EnumArrays.md docs/EnumArraysArrayArrayEnumInnerInner.md docs/EnumArraysArrayEnumInner.md diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/README.md b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/README.md index 5ea45e423779..a3100d49e208 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/README.md +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/README.md @@ -198,7 +198,7 @@ Method | HTTP request | Description - [ClassModel](docs/ClassModel.md) - [Client](docs/Client.md) - [Dog](docs/Dog.md) - - [DollarSpecialLeftSquareBracketModelPeriodNameRightSquareBracket](docs/DollarSpecialLeftSquareBracketModelPeriodNameRightSquareBracket.md) + - [DollarSpecialLeftSquareBracketModelNameRightSquareBracket](docs/DollarSpecialLeftSquareBracketModelNameRightSquareBracket.md) - [EnumArrays](docs/EnumArrays.md) - [EnumArraysArrayArrayEnumInnerInner](docs/EnumArraysArrayArrayEnumInnerInner.md) - [EnumArraysArrayEnumInner](docs/EnumArraysArrayEnumInner.md) diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/docs/DollarSpecialLeftSquareBracketModelNameRightSquareBracket.md b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/docs/DollarSpecialLeftSquareBracketModelNameRightSquareBracket.md new file mode 100644 index 000000000000..6719abdbbfd6 --- /dev/null +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/docs/DollarSpecialLeftSquareBracketModelNameRightSquareBracket.md @@ -0,0 +1,10 @@ +# DollarSpecialLeftSquareBracketModelNameRightSquareBracket + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**dollar_special_left_square_bracket_property_name_right_square_bracket** | **i64** | | [optional] [default to None] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs index 0be12ebcc514..6692bd124009 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs @@ -2509,33 +2509,33 @@ impl Dog { #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, validator::Validate)] #[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))] #[serde(rename = "$special[model.name]")] -pub struct DollarSpecialLeftSquareBracketModelPeriodNameRightSquareBracket { +pub struct DollarSpecialLeftSquareBracketModelNameRightSquareBracket { #[serde(rename = "$special[property.name]")] #[serde(skip_serializing_if="Option::is_none")] - pub dollar_special_left_square_bracket_property_period_name_right_square_bracket: Option, + pub dollar_special_left_square_bracket_property_name_right_square_bracket: Option, } -impl DollarSpecialLeftSquareBracketModelPeriodNameRightSquareBracket { +impl DollarSpecialLeftSquareBracketModelNameRightSquareBracket { #[allow(clippy::new_without_default)] - pub fn new() -> DollarSpecialLeftSquareBracketModelPeriodNameRightSquareBracket { - DollarSpecialLeftSquareBracketModelPeriodNameRightSquareBracket { - dollar_special_left_square_bracket_property_period_name_right_square_bracket: None, + pub fn new() -> DollarSpecialLeftSquareBracketModelNameRightSquareBracket { + DollarSpecialLeftSquareBracketModelNameRightSquareBracket { + dollar_special_left_square_bracket_property_name_right_square_bracket: None, } } } -/// Converts the DollarSpecialLeftSquareBracketModelPeriodNameRightSquareBracket value to the Query Parameters representation (style=form, explode=false) +/// Converts the DollarSpecialLeftSquareBracketModelNameRightSquareBracket value to the Query Parameters representation (style=form, explode=false) /// specified in https://swagger.io/docs/specification/serialization/ /// Should be implemented in a serde serializer -impl std::string::ToString for DollarSpecialLeftSquareBracketModelPeriodNameRightSquareBracket { +impl std::string::ToString for DollarSpecialLeftSquareBracketModelNameRightSquareBracket { fn to_string(&self) -> String { let params: Vec> = vec![ - self.dollar_special_left_square_bracket_property_period_name_right_square_bracket.as_ref().map(|dollar_special_left_square_bracket_property_period_name_right_square_bracket| { + self.dollar_special_left_square_bracket_property_name_right_square_bracket.as_ref().map(|dollar_special_left_square_bracket_property_name_right_square_bracket| { [ "$special[property.name]".to_string(), - dollar_special_left_square_bracket_property_period_name_right_square_bracket.to_string(), + dollar_special_left_square_bracket_property_name_right_square_bracket.to_string(), ].join(",") }), ]; @@ -2544,10 +2544,10 @@ impl std::string::ToString for DollarSpecialLeftSquareBracketModelPeriodNameRigh } } -/// Converts Query Parameters representation (style=form, explode=false) to a DollarSpecialLeftSquareBracketModelPeriodNameRightSquareBracket value +/// Converts Query Parameters representation (style=form, explode=false) to a DollarSpecialLeftSquareBracketModelNameRightSquareBracket value /// as specified in https://swagger.io/docs/specification/serialization/ /// Should be implemented in a serde deserializer -impl std::str::FromStr for DollarSpecialLeftSquareBracketModelPeriodNameRightSquareBracket { +impl std::str::FromStr for DollarSpecialLeftSquareBracketModelNameRightSquareBracket { type Err = String; fn from_str(s: &str) -> std::result::Result { @@ -2555,7 +2555,7 @@ impl std::str::FromStr for DollarSpecialLeftSquareBracketModelPeriodNameRightSqu #[derive(Default)] #[allow(dead_code)] struct IntermediateRep { - pub dollar_special_left_square_bracket_property_period_name_right_square_bracket: Vec, + pub dollar_special_left_square_bracket_property_name_right_square_bracket: Vec, } let mut intermediate_rep = IntermediateRep::default(); @@ -2567,15 +2567,15 @@ impl std::str::FromStr for DollarSpecialLeftSquareBracketModelPeriodNameRightSqu while key_result.is_some() { let val = match string_iter.next() { Some(x) => x, - None => return std::result::Result::Err("Missing value while parsing DollarSpecialLeftSquareBracketModelPeriodNameRightSquareBracket".to_string()) + None => return std::result::Result::Err("Missing value while parsing DollarSpecialLeftSquareBracketModelNameRightSquareBracket".to_string()) }; if let Some(key) = key_result { #[allow(clippy::match_single_binding)] match key { #[allow(clippy::redundant_clone)] - "$special[property.name]" => intermediate_rep.dollar_special_left_square_bracket_property_period_name_right_square_bracket.push(::from_str(val).map_err(|x| x.to_string())?), - _ => return std::result::Result::Err("Unexpected key while parsing DollarSpecialLeftSquareBracketModelPeriodNameRightSquareBracket".to_string()) + "$special[property.name]" => intermediate_rep.dollar_special_left_square_bracket_property_name_right_square_bracket.push(::from_str(val).map_err(|x| x.to_string())?), + _ => return std::result::Result::Err("Unexpected key while parsing DollarSpecialLeftSquareBracketModelNameRightSquareBracket".to_string()) } } @@ -2584,40 +2584,40 @@ impl std::str::FromStr for DollarSpecialLeftSquareBracketModelPeriodNameRightSqu } // Use the intermediate representation to return the struct - std::result::Result::Ok(DollarSpecialLeftSquareBracketModelPeriodNameRightSquareBracket { - dollar_special_left_square_bracket_property_period_name_right_square_bracket: intermediate_rep.dollar_special_left_square_bracket_property_period_name_right_square_bracket.into_iter().next(), + std::result::Result::Ok(DollarSpecialLeftSquareBracketModelNameRightSquareBracket { + dollar_special_left_square_bracket_property_name_right_square_bracket: intermediate_rep.dollar_special_left_square_bracket_property_name_right_square_bracket.into_iter().next(), }) } } -// Methods for converting between header::IntoHeaderValue and hyper::header::HeaderValue +// Methods for converting between header::IntoHeaderValue and hyper::header::HeaderValue #[cfg(any(feature = "client", feature = "server"))] -impl std::convert::TryFrom> for hyper::header::HeaderValue { +impl std::convert::TryFrom> for hyper::header::HeaderValue { type Error = String; - fn try_from(hdr_value: header::IntoHeaderValue) -> std::result::Result { + fn try_from(hdr_value: header::IntoHeaderValue) -> std::result::Result { let hdr_value = hdr_value.to_string(); match hyper::header::HeaderValue::from_str(&hdr_value) { std::result::Result::Ok(value) => std::result::Result::Ok(value), std::result::Result::Err(e) => std::result::Result::Err( - format!("Invalid header value for DollarSpecialLeftSquareBracketModelPeriodNameRightSquareBracket - value: {} is invalid {}", + format!("Invalid header value for DollarSpecialLeftSquareBracketModelNameRightSquareBracket - value: {} is invalid {}", hdr_value, e)) } } } #[cfg(any(feature = "client", feature = "server"))] -impl std::convert::TryFrom for header::IntoHeaderValue { +impl std::convert::TryFrom for header::IntoHeaderValue { type Error = String; fn try_from(hdr_value: hyper::header::HeaderValue) -> std::result::Result { match hdr_value.to_str() { std::result::Result::Ok(value) => { - match ::from_str(value) { + match ::from_str(value) { std::result::Result::Ok(value) => std::result::Result::Ok(header::IntoHeaderValue(value)), std::result::Result::Err(err) => std::result::Result::Err( - format!("Unable to convert header value '{}' into DollarSpecialLeftSquareBracketModelPeriodNameRightSquareBracket - {}", + format!("Unable to convert header value '{}' into DollarSpecialLeftSquareBracketModelNameRightSquareBracket - {}", value, err)) } }, @@ -2629,10 +2629,10 @@ impl std::convert::TryFrom for header::IntoHeaderVal } #[cfg(feature = "server")] -impl std::convert::TryFrom>> for hyper::header::HeaderValue { +impl std::convert::TryFrom>> for hyper::header::HeaderValue { type Error = String; - fn try_from(hdr_values: header::IntoHeaderValue>) -> std::result::Result { + fn try_from(hdr_values: header::IntoHeaderValue>) -> std::result::Result { let hdr_values : Vec = hdr_values.0.into_iter().map(|hdr_value| { hdr_value.to_string() }).collect(); @@ -2646,21 +2646,21 @@ impl std::convert::TryFrom for header::IntoHeaderValue> { +impl std::convert::TryFrom for header::IntoHeaderValue> { type Error = String; fn try_from(hdr_values: hyper::header::HeaderValue) -> std::result::Result { match hdr_values.to_str() { std::result::Result::Ok(hdr_values) => { - let hdr_values : std::vec::Vec = hdr_values + let hdr_values : std::vec::Vec = hdr_values .split(',') .filter_map(|hdr_value| match hdr_value.trim() { "" => std::option::Option::None, hdr_value => std::option::Option::Some({ - match ::from_str(hdr_value) { + match ::from_str(hdr_value) { std::result::Result::Ok(value) => std::result::Result::Ok(value), std::result::Result::Err(err) => std::result::Result::Err( - format!("Unable to convert header value '{}' into DollarSpecialLeftSquareBracketModelPeriodNameRightSquareBracket - {}", + format!("Unable to convert header value '{}' into DollarSpecialLeftSquareBracketModelNameRightSquareBracket - {}", hdr_value, err)) } }) @@ -2674,7 +2674,7 @@ impl std::convert::TryFrom for header::IntoHeaderVal } } -impl DollarSpecialLeftSquareBracketModelPeriodNameRightSquareBracket { +impl DollarSpecialLeftSquareBracketModelNameRightSquareBracket { /// Helper function to allow us to convert this model to an XML string. /// Will panic if serialisation fails. #[allow(dead_code)] @@ -8445,16 +8445,16 @@ impl TestEnumParametersEnumHeaderStringParameter { #[cfg_attr(feature = "conversion", derive(frunk_enum_derive::LabelledGenericEnum))] pub enum TestEnumParametersEnumQueryDoubleParameter { #[serde(rename = "1.1")] - Variant1Period1, + Variant11, #[serde(rename = "-1.2")] - Variant1Period2, + Variant12, } impl std::fmt::Display for TestEnumParametersEnumQueryDoubleParameter { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match *self { - TestEnumParametersEnumQueryDoubleParameter::Variant1Period1 => write!(f, "1.1"), - TestEnumParametersEnumQueryDoubleParameter::Variant1Period2 => write!(f, "-1.2"), + TestEnumParametersEnumQueryDoubleParameter::Variant11 => write!(f, "1.1"), + TestEnumParametersEnumQueryDoubleParameter::Variant12 => write!(f, "-1.2"), } } } @@ -8464,8 +8464,8 @@ impl std::str::FromStr for TestEnumParametersEnumQueryDoubleParameter { fn from_str(s: &str) -> std::result::Result { match s { - "1.1" => std::result::Result::Ok(TestEnumParametersEnumQueryDoubleParameter::Variant1Period1), - "-1.2" => std::result::Result::Ok(TestEnumParametersEnumQueryDoubleParameter::Variant1Period2), + "1.1" => std::result::Result::Ok(TestEnumParametersEnumQueryDoubleParameter::Variant11), + "-1.2" => std::result::Result::Ok(TestEnumParametersEnumQueryDoubleParameter::Variant12), _ => std::result::Result::Err(format!("Value not valid: {}", s)), } }