Skip to content

[Rust] harden against name collisions while generate cleaner rust code, fix #20337 #20396

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

Merged
merged 5 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public abstract class AbstractRustCodegen extends DefaultCodegen implements Code

private final Logger LOGGER = LoggerFactory.getLogger(AbstractRustCodegen.class);

protected static final String VENDOR_EXTENSION_PARAM_IDENTIFIER = "x-rust-param-identifier";

protected List<String> charactersToAllow = Collections.singletonList("_");
protected Set<String> keywordsThatDoNotSupportRawIdentifiers = new HashSet<>(
Arrays.asList("super", "self", "Self", "extern", "crate"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@
import org.openapitools.codegen.CodegenModel;
import org.openapitools.codegen.CodegenOperation;
import org.openapitools.codegen.CodegenProperty;
import org.openapitools.codegen.CodegenParameter;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.SupportingFile;
import org.openapitools.codegen.VendorExtension;
import org.openapitools.codegen.meta.features.ClientModificationFeature;
import org.openapitools.codegen.meta.features.DocumentationFeature;
import org.openapitools.codegen.meta.features.GlobalFeature;
Expand Down Expand Up @@ -602,6 +604,25 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert
}
}

@Override
public void postProcessParameter(CodegenParameter parameter) {
super.postProcessParameter(parameter);
// in order to avoid name conflicts, we map parameters inside the functions
String inFunctionIdentifier = "";
if (this.useSingleRequestParameter) {
inFunctionIdentifier = "params." + parameter.paramName;
} else {
if (parameter.paramName.startsWith("r#")) {
inFunctionIdentifier = "p_" + parameter.paramName.substring(2);
} else {
inFunctionIdentifier = "p_" + parameter.paramName;
}
}
if (!parameter.vendorExtensions.containsKey(this.VENDOR_EXTENSION_PARAM_IDENTIFIER)) { // allow to overwrite this value
parameter.vendorExtensions.put(this.VENDOR_EXTENSION_PARAM_IDENTIFIER, inFunctionIdentifier);
}
}

@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> allModels) {
OperationMap objectMap = objs.getOperations();
Expand Down Expand Up @@ -699,7 +720,7 @@ public String toDefaultValue(Schema p) {
@Override
protected ImmutableMap.Builder<String, Lambda> addMustacheLambdas() {
return super.addMustacheLambdas()
// Convert variable names to lifetime names.
// Convert variable names to lifetime names.
// Generally they are the same, but `#` is not valid in lifetime names.
// Rust uses `r#` prefix for variables that are also keywords.
.put("lifetimeName", new ReplaceAllLambda("^r#", "r_"));
Expand Down
206 changes: 100 additions & 106 deletions modules/openapi-generator/src/main/resources/rust/reqwest/api.mustache

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,11 @@ paths:
description: To test parameter names in upper case
schema:
type: string
- name: content
in: query
description: To test escaping of parameters in rust code works
schema:
type: string
responses:
'200':
description: successful operation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,26 @@ pub enum ReproError {


pub fn repro(configuration: &configuration::Configuration, ) -> Result<models::Parent, Error<ReproError>> {
let local_var_configuration = configuration;

let local_var_client = &local_var_configuration.client;
let uri_str = format!("{}/repro", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);

let local_var_uri_str = format!("{}/repro", local_var_configuration.base_path);
let mut local_var_req_builder = local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str());

if let Some(ref local_var_user_agent) = local_var_configuration.user_agent {
local_var_req_builder = local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}

let local_var_req = local_var_req_builder.build()?;
let local_var_resp = local_var_client.execute(local_var_req)?;
let req = req_builder.build()?;
let resp = configuration.client.execute(req)?;

let local_var_status = local_var_resp.status();
let status = resp.status();

if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
let local_var_content = local_var_resp.text()?;
serde_json::from_str(&local_var_content).map_err(Error::from)
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text()?;
serde_json::from_str(&content).map_err(Error::from)
} else {
let local_var_content = local_var_resp.text()?;
let local_var_entity: Option<ReproError> = serde_json::from_str(&local_var_content).ok();
let local_var_error = ResponseContent { status: local_var_status, content: local_var_content, entity: local_var_entity };
Err(Error::ResponseError(local_var_error))
let content = resp.text()?;
let entity: Option<ReproError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,27 @@ pub enum DemoColorGetError {


pub async fn demo_color_get(configuration: &configuration::Configuration, color: models::Color) -> Result<(), Error<DemoColorGetError>> {
let local_var_configuration = configuration;
// add a prefix to parameters to efficiently prevent name collisions
let p_color = color;

let local_var_client = &local_var_configuration.client;
let uri_str = format!("{}/demo/{color}", configuration.base_path, color=p_color.to_string());
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

let local_var_uri_str = format!("{}/demo/{color}", local_var_configuration.base_path, color=color.to_string());
let mut local_var_req_builder = local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());

if let Some(ref local_var_user_agent) = local_var_configuration.user_agent {
local_var_req_builder = local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}

let local_var_req = local_var_req_builder.build()?;
let local_var_resp = local_var_client.execute(local_var_req).await?;
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;

let local_var_status = local_var_resp.status();
let status = resp.status();

if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let local_var_content = local_var_resp.text().await?;
let local_var_entity: Option<DemoColorGetError> = serde_json::from_str(&local_var_content).ok();
let local_var_error = ResponseContent { status: local_var_status, content: local_var_content, entity: local_var_entity };
Err(Error::ResponseError(local_var_error))
let content = resp.text().await?;
let entity: Option<DemoColorGetError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -31,58 +31,52 @@ pub enum GetStateError {


pub fn create_state(configuration: &configuration::Configuration, create_state_request: models::CreateStateRequest) -> Result<(), Error<CreateStateError>> {
let local_var_configuration = configuration;
// add a prefix to parameters to efficiently prevent name collisions
let p_create_state_request = create_state_request;

let local_var_client = &local_var_configuration.client;
let uri_str = format!("{}/state", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);

let local_var_uri_str = format!("{}/state", local_var_configuration.base_path);
let mut local_var_req_builder = local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str());

if let Some(ref local_var_user_agent) = local_var_configuration.user_agent {
local_var_req_builder = local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
local_var_req_builder = local_var_req_builder.json(&create_state_request);
req_builder = req_builder.json(&p_create_state_request);

let local_var_req = local_var_req_builder.build()?;
let local_var_resp = local_var_client.execute(local_var_req)?;
let req = req_builder.build()?;
let resp = configuration.client.execute(req)?;

let local_var_status = local_var_resp.status();
let status = resp.status();

if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let local_var_content = local_var_resp.text()?;
let local_var_entity: Option<CreateStateError> = serde_json::from_str(&local_var_content).ok();
let local_var_error = ResponseContent { status: local_var_status, content: local_var_content, entity: local_var_entity };
Err(Error::ResponseError(local_var_error))
let content = resp.text()?;
let entity: Option<CreateStateError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}

pub fn get_state(configuration: &configuration::Configuration, ) -> Result<models::GetState200Response, Error<GetStateError>> {
let local_var_configuration = configuration;

let local_var_client = &local_var_configuration.client;

let local_var_uri_str = format!("{}/state", local_var_configuration.base_path);
let mut local_var_req_builder = local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
let uri_str = format!("{}/state", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

if let Some(ref local_var_user_agent) = local_var_configuration.user_agent {
local_var_req_builder = local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}

let local_var_req = local_var_req_builder.build()?;
let local_var_resp = local_var_client.execute(local_var_req)?;
let req = req_builder.build()?;
let resp = configuration.client.execute(req)?;

let local_var_status = local_var_resp.status();
let status = resp.status();

if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
let local_var_content = local_var_resp.text()?;
serde_json::from_str(&local_var_content).map_err(Error::from)
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text()?;
serde_json::from_str(&content).map_err(Error::from)
} else {
let local_var_content = local_var_resp.text()?;
let local_var_entity: Option<GetStateError> = serde_json::from_str(&local_var_content).ok();
let local_var_error = ResponseContent { status: local_var_status, content: local_var_content, entity: local_var_entity };
Err(Error::ResponseError(local_var_error))
let content = resp.text()?;
let entity: Option<GetStateError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,26 @@ pub enum EndpointGetError {


pub fn endpoint_get(configuration: &configuration::Configuration, ) -> Result<models::EmptyObject, Error<EndpointGetError>> {
let local_var_configuration = configuration;

let local_var_client = &local_var_configuration.client;
let uri_str = format!("{}/endpoint", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

let local_var_uri_str = format!("{}/endpoint", local_var_configuration.base_path);
let mut local_var_req_builder = local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());

if let Some(ref local_var_user_agent) = local_var_configuration.user_agent {
local_var_req_builder = local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}

let local_var_req = local_var_req_builder.build()?;
let local_var_resp = local_var_client.execute(local_var_req)?;
let req = req_builder.build()?;
let resp = configuration.client.execute(req)?;

let local_var_status = local_var_resp.status();
let status = resp.status();

if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
let local_var_content = local_var_resp.text()?;
serde_json::from_str(&local_var_content).map_err(Error::from)
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text()?;
serde_json::from_str(&content).map_err(Error::from)
} else {
let local_var_content = local_var_resp.text()?;
let local_var_entity: Option<EndpointGetError> = serde_json::from_str(&local_var_content).ok();
let local_var_error = ResponseContent { status: local_var_status, content: local_var_content, entity: local_var_entity };
Err(Error::ResponseError(local_var_error))
let content = resp.text()?;
let entity: Option<EndpointGetError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -31,58 +31,52 @@ pub enum TestError {


pub fn root_get(configuration: &configuration::Configuration, ) -> Result<models::Fruit, Error<RootGetError>> {
let local_var_configuration = configuration;

let local_var_client = &local_var_configuration.client;
let uri_str = format!("{}/", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

let local_var_uri_str = format!("{}/", local_var_configuration.base_path);
let mut local_var_req_builder = local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());

if let Some(ref local_var_user_agent) = local_var_configuration.user_agent {
local_var_req_builder = local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}

let local_var_req = local_var_req_builder.build()?;
let local_var_resp = local_var_client.execute(local_var_req)?;
let req = req_builder.build()?;
let resp = configuration.client.execute(req)?;

let local_var_status = local_var_resp.status();
let status = resp.status();

if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
let local_var_content = local_var_resp.text()?;
serde_json::from_str(&local_var_content).map_err(Error::from)
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text()?;
serde_json::from_str(&content).map_err(Error::from)
} else {
let local_var_content = local_var_resp.text()?;
let local_var_entity: Option<RootGetError> = serde_json::from_str(&local_var_content).ok();
let local_var_error = ResponseContent { status: local_var_status, content: local_var_content, entity: local_var_entity };
Err(Error::ResponseError(local_var_error))
let content = resp.text()?;
let entity: Option<RootGetError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}

pub fn test(configuration: &configuration::Configuration, body: Option<serde_json::Value>) -> Result<(), Error<TestError>> {
let local_var_configuration = configuration;

let local_var_client = &local_var_configuration.client;
// add a prefix to parameters to efficiently prevent name collisions
let p_body = body;

let local_var_uri_str = format!("{}/", local_var_configuration.base_path);
let mut local_var_req_builder = local_var_client.request(reqwest::Method::PUT, local_var_uri_str.as_str());
let uri_str = format!("{}/", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::PUT, &uri_str);

if let Some(ref local_var_user_agent) = local_var_configuration.user_agent {
local_var_req_builder = local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
local_var_req_builder = local_var_req_builder.json(&body);
req_builder = req_builder.json(&p_body);

let local_var_req = local_var_req_builder.build()?;
let local_var_resp = local_var_client.execute(local_var_req)?;
let req = req_builder.build()?;
let resp = configuration.client.execute(req)?;

let local_var_status = local_var_resp.status();
let status = resp.status();

if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let local_var_content = local_var_resp.text()?;
let local_var_entity: Option<TestError> = serde_json::from_str(&local_var_content).ok();
let local_var_error = ResponseContent { status: local_var_status, content: local_var_content, entity: local_var_entity };
Err(Error::ResponseError(local_var_error))
let content = resp.text()?;
let entity: Option<TestError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}

Loading
Loading