use openapiv3::{OpenAPI, Operation};
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
pub fn generate_doc_comment(description: Option<&str>) -> TokenStream2 {
if let Some(desc) = description {
if !desc.trim().is_empty() {
let clean_desc = desc
.lines()
.map(|line| line.trim())
.filter(|line| !line.is_empty())
.collect::<Vec<_>>()
.join(" ");
return quote! {
#[doc = #clean_desc]
};
}
}
quote! {}
}
pub fn generate_client_doc_comment(spec: &OpenAPI, client_name: &str) -> TokenStream2 {
let mut doc_lines = Vec::new();
if !spec.info.title.trim().is_empty() {
doc_lines.push(format!("API Client for {}", spec.info.title.trim()));
} else {
doc_lines.push(format!("Generated API Client: {}", client_name));
}
if let Some(description) = &spec.info.description {
let clean_desc = description.trim();
if !clean_desc.is_empty() {
doc_lines.push("".to_string()); doc_lines.push(clean_desc.to_string());
}
}
if !spec.info.version.trim().is_empty() {
doc_lines.push("".to_string()); doc_lines.push(format!("**API Version:** `{}`", spec.info.version.trim()));
}
if let Some(contact) = &spec.info.contact {
if let Some(email) = &contact.email {
doc_lines.push(format!("**Contact:** {}", email));
}
}
if let Some(license) = &spec.info.license {
if !license.name.trim().is_empty() {
let license_info = if let Some(url) = &license.url {
format!("**License:** [{}]({})", license.name, url)
} else {
format!("**License:** {}", license.name)
};
doc_lines.push(license_info);
}
}
if let Some(terms) = &spec.info.terms_of_service {
if !terms.trim().is_empty() {
doc_lines.push(format!("**Terms of Service:** {}", terms));
}
}
doc_lines.push("".to_string()); doc_lines.push("# Example".to_string());
doc_lines.push("```rust".to_string());
doc_lines.push(format!("let client = {}::new(\"https://api.example.com\");", client_name));
doc_lines.push("let result = client.some_method().await?;".to_string());
doc_lines.push("```".to_string());
let doc_attrs = doc_lines.iter().map(|line| {
quote! { #[doc = #line] }
});
quote! {
#(#doc_attrs)*
}
}
pub fn generate_method_doc_comment(
operation: &Operation,
path: &str,
http_method: &str,
) -> TokenStream2 {
let mut doc_lines = Vec::new();
if let Some(summary) = &operation.summary {
if !summary.trim().is_empty() {
doc_lines.push(summary.trim().to_string());
}
}
if let Some(description) = &operation.description {
let clean_desc = description.trim();
if !clean_desc.is_empty() && Some(clean_desc) != operation.summary.as_deref() {
if !doc_lines.is_empty() {
doc_lines.push("".to_string()); }
doc_lines.push(clean_desc.to_string());
}
}
if !doc_lines.is_empty() {
doc_lines.push("".to_string()); }
doc_lines.push(format!("**HTTP Method:** `{}`", http_method.to_uppercase()));
doc_lines.push(format!("**Path:** `{}`", path));
if let Some(operation_id) = &operation.operation_id {
doc_lines.push(format!("**Operation ID:** `{}`", operation_id));
}
if doc_lines.is_empty() {
return quote! {};
}
let doc_attrs = doc_lines.iter().map(|line| {
quote! { #[doc = #line] }
});
quote! {
#(#doc_attrs)*
}
}