From 03effd7d0511325a1571971bea4b86cf38a1a17f Mon Sep 17 00:00:00 2001 From: Steven Crake Date: Sun, 29 Jun 2025 08:52:55 +0100 Subject: [PATCH] Replace periods with underscores in Rust model names (#21480) 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 4d32067a79e..39e888bae0f 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 abstract class AbstractRustCodegen extends DefaultCodegen implements Code 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 e73753b2a1c..300e0b9566c 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 class AbstractRustCodegenTest { // 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 e515b3eb751..6d35ed812fa 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 5ea45e42377..a3100d49e20 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 00000000000..6719abdbbfd --- /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 0be12ebcc51..6692bd12400 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)), } }