Skip to content
Open
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
4 changes: 2 additions & 2 deletions utoipa-gen/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@
* Add derive info support for derive OpenApi (https://github.com/juhaku/utoipa/pull/400)
* Add `merge` functionality for `OpenApi` (https://github.com/juhaku/utoipa/pull/397)
* Add derive servers attribute for OpenApi (https://github.com/juhaku/utoipa/pull/395)
* Add support for unit sructs (https://github.com/juhaku/utoipa/pull/392)
* Add support for unit structs (https://github.com/juhaku/utoipa/pull/392)
* Add support for `schema_with` custom fn reference (https://github.com/juhaku/utoipa/pull/390)
* Add support for multiple serde definitions (https://github.com/juhaku/utoipa/pull/389)
* Add support for tuple Path parameters for axum (https://github.com/juhaku/utoipa/pull/388)
Expand Down Expand Up @@ -534,7 +534,7 @@
* Update `ToSchema` documentation
* Chore make `serde_json` mandatory dependency (https://github.com/juhaku/utoipa/pull/378)
* Feature http status codes (https://github.com/juhaku/utoipa/pull/376)
* Refactor some path derive with `IntoParmas` tests
* Refactor some path derive with `IntoParams` tests
* Chore refine description attribute (https://github.com/juhaku/utoipa/pull/373)
* cargo format
* Update to axum 0.6.0 (https://github.com/juhaku/utoipa/pull/369)
1 change: 1 addition & 0 deletions utoipa-gen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ include = [
proc-macro = true

[dependencies]
desynt = "0.1"
utoipa-config = { version = "0.1", path = "../utoipa-config", optional = true }
once_cell = { version = "1.19.0", optional = true }
proc-macro2 = "1.0"
Expand Down
7 changes: 5 additions & 2 deletions utoipa-gen/src/component.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::borrow::Cow;

use desynt::StripRaw;
use proc_macro2::{Ident, Span, TokenStream};
use quote::{quote, quote_spanned, ToTokens};
use syn::punctuated::Punctuated;
Expand Down Expand Up @@ -439,7 +440,7 @@ impl TypeTree<'_> {
return None;
}

match &*segment.ident.to_string() {
match &*segment.ident.strip_raw().to_string() {
"HashMap" | "Map" | "BTreeMap" => Some(GenericType::Map),
#[cfg(feature = "indexmap")]
"IndexMap" => Some(GenericType::Map),
Expand Down Expand Up @@ -568,7 +569,9 @@ impl TypeTree<'_> {
.as_ref()
.and_then(|path| path.segments.iter().last())
.and_then(|last_segment| {
crate::CONFIG.aliases.get(&*last_segment.ident.to_string())
crate::CONFIG
.aliases
.get(&*last_segment.ident.strip_raw().to_string())
})
.map_try(|alias| syn::parse_str::<syn::Type>(alias.as_ref()))
.map_err(|error| Diagnostics::new(error.to_string()))
Expand Down
3 changes: 2 additions & 1 deletion utoipa-gen/src/component/features/attributes.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::mem;

use desynt::StripRaw;
use proc_macro2::{Ident, TokenStream};
use quote::ToTokens;
use syn::parse::ParseStream;
Expand Down Expand Up @@ -682,7 +683,7 @@ impl As {
.path
.segments
.iter()
.map(|segment| segment.ident.to_string())
.map(|segment| segment.ident.strip_raw().to_string())
.collect::<Vec<_>>()
.join(".")
}
Expand Down
9 changes: 3 additions & 6 deletions utoipa-gen/src/component/into_params.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::borrow::Cow;

use desynt::StripRaw;
use proc_macro2::TokenStream;
use quote::{quote, quote_spanned, ToTokens};
use syn::{
Expand Down Expand Up @@ -323,19 +324,15 @@ impl Param {
let mut tokens = TokenStream::new();
let field_serde_params = &field_serde_params;
let ident = &field.ident;
let mut name = &*ident
let name = &*ident
.as_ref()
.map(|ident| ident.to_string())
.map(|ident| ident.strip_raw().to_string())
.or_else(|| container_attributes.name.cloned())
.ok_or_else(||
Diagnostics::with_span(field.span(), "No name specified for unnamed field.")
.help("Try adding #[into_params(names(...))] container attribute to specify the name for this field")
)?;

if name.starts_with("r#") {
name = &name[2..];
}

let (schema_features, mut param_features) =
Param::resolve_field_features(field_features, &container_attributes)
.map_err(Diagnostics::from)?;
Expand Down
14 changes: 6 additions & 8 deletions utoipa-gen/src/component/schema.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::borrow::{Borrow, Cow};

use desynt::StripRaw;
use proc_macro2::{Ident, TokenStream};
use quote::{quote, quote_spanned, ToTokens};
use syn::{
Expand Down Expand Up @@ -347,11 +348,8 @@ impl NamedStructSchema {
let mut fields_vec = fields
.iter()
.filter_map(|field| {
let mut field_name = Cow::Owned(field.ident.as_ref().unwrap().to_string());

if Borrow::<str>::borrow(&field_name).starts_with("r#") {
field_name = Cow::Owned(field_name[2..].to_string());
}
let field_ident = field.ident.as_ref().unwrap();
let field_name: Cow<'_, str> = Cow::Owned(field_ident.strip_raw().to_string());

let field_rules = serde::parse_value(&field.attrs);
let field_rules = match field_rules {
Expand Down Expand Up @@ -500,11 +498,11 @@ impl NamedStructSchema {
Some(flattened_map_field) => {
return Err(Diagnostics::with_span(
fields.span(),
format!("The structure `{}` contains multiple flattened map fields.", root.ident))
format!("The structure `{}` contains multiple flattened map fields.", root.ident.strip_raw()))
.note(
format!("first flattened map field was declared here as `{}`",
flattened_map_field.ident.as_ref().unwrap()))
.note(format!("second flattened map field was declared here as `{}`", field.ident.as_ref().unwrap()))
flattened_map_field.ident.as_ref().unwrap().strip_raw()))
.note(format!("second flattened map field was declared here as `{}`", field.ident.as_ref().unwrap().strip_raw()))
);
}
}
Expand Down
5 changes: 3 additions & 2 deletions utoipa-gen/src/component/schema/enums.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{borrow::Cow, ops::Deref};

use desynt::StripRaw;
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use syn::{punctuated::Punctuated, spanned::Spanned, token::Comma, Fields, TypePath, Variant};
Expand Down Expand Up @@ -103,7 +104,7 @@ impl<'e> PlainEnum<'e> {
.collect::<Result<Vec<_>, Diagnostics>>()?
.into_iter()
.map(|(variant, variant_rules, mut variant_features)| {
let name = &*variant.ident.to_string();
let name = &*variant.ident.strip_raw().to_string();
let renamed = super::rename_enum_variant(
name,
&mut variant_features,
Expand Down Expand Up @@ -398,7 +399,7 @@ impl MixedEnumContent {
mut variant_features: Vec<Feature>,
) -> Result<Self, Diagnostics> {
let mut tokens = TokenStream::new();
let name = variant.ident.to_string();
let name = variant.ident.strip_raw().to_string();
// TODO support `description = ...` attribute via Feature::Description
// let description =
// pop_feature!(variant_features => Feature::Description(_) as Option<Description>);
Expand Down
5 changes: 3 additions & 2 deletions utoipa-gen/src/ext.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::borrow::Cow;

use desynt::StripRaw;
use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::spanned::Spanned;
Expand Down Expand Up @@ -123,7 +124,7 @@ impl ExtSchema<'_> {
} else {
Cow::Borrowed(actual_body)
}
}).expect("ExtSchema must have actual request body resoved from TypeTree of handler fn argument")
}).expect("ExtSchema must have actual request body resolved from TypeTree of handler fn argument")
}

pub fn get_type_tree(&self) -> Result<Option<Cow<'_, TypeTree<'_>>>, Diagnostics> {
Expand Down Expand Up @@ -182,7 +183,7 @@ fn get_actual_body_type<'t>(ty: &'t TypeTree<'t>) -> Option<&'t TypeTree<'t>> {
.expect("RequestBody TypeTree must have syn::Path")
.segments
.iter()
.find_map(|segment| match &*segment.ident.to_string() {
.find_map(|segment| match &*segment.ident.strip_raw().to_string() {
"Json" => Some(
ty.children
.as_deref()
Expand Down
14 changes: 7 additions & 7 deletions utoipa-gen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ static CONFIG: once_cell::sync::Lazy<utoipa_config::Config> =
/// * `min_properties = ...` Can be used to define minimum number of properties this struct can
/// contain. Value must be a number.
///* `no_recursion` Is used to break from recursion in case of looping schema tree e.g. `Pet` ->
/// `Owner` -> `Pet`. _`no_recursion`_ attribute must be used within `Ower` type not to allow
/// `Owner` -> `Pet`. _`no_recursion`_ attribute must be used within `Owner` type not to allow
/// recurring into `Pet`. Failing to do so will cause infinite loop and runtime **panic**. On
/// struct level the _`no_recursion`_ rule will be applied to all of its fields.
///
Expand Down Expand Up @@ -202,7 +202,7 @@ static CONFIG: once_cell::sync::Lazy<utoipa_config::Config> =
///* `ignore` or `ignore = ...` Can be used to skip the field from being serialized to OpenAPI schema. It accepts either a literal `bool` value
/// or a path to a function that returns `bool` (`Fn() -> bool`).
///* `no_recursion` Is used to break from recursion in case of looping schema tree e.g. `Pet` ->
/// `Owner` -> `Pet`. _`no_recursion`_ attribute must be used within `Ower` type not to allow
/// `Owner` -> `Pet`. _`no_recursion`_ attribute must be used within `Owner` type not to allow
/// recurring into `Pet`. Failing to do so will cause infinite loop and runtime **panic**.
///
/// #### Field nullability and required rules
Expand Down Expand Up @@ -267,7 +267,7 @@ static CONFIG: once_cell::sync::Lazy<utoipa_config::Config> =
/// * `content_media_type = ...` Can be used to define MIME type of a string for underlying schema object.
/// See [`Object::content_media_type`][schema_object_media_type]
///* `no_recursion` Is used to break from recursion in case of looping schema tree e.g. `Pet` ->
/// `Owner` -> `Pet`. _`no_recursion`_ attribute must be used within `Ower` type not to allow
/// `Owner` -> `Pet`. _`no_recursion`_ attribute must be used within `Owner` type not to allow
/// recurring into `Pet`. Failing to do so will cause infinite loop and runtime **panic**.
///
/// # Enum Optional Configuration Options for `#[schema(...)]`
Expand Down Expand Up @@ -335,7 +335,7 @@ static CONFIG: once_cell::sync::Lazy<utoipa_config::Config> =
/// field for enums with single unnamed _`ToSchema`_ reference field. See the [discriminator
/// syntax][derive@ToSchema#schemadiscriminator-syntax].
///* `no_recursion` Is used to break from recursion in case of looping schema tree e.g. `Pet` ->
/// `Owner` -> `Pet`. _`no_recursion`_ attribute must be used within `Ower` type not to allow
/// `Owner` -> `Pet`. _`no_recursion`_ attribute must be used within `Owner` type not to allow
/// recurring into `Pet`. Failing to do so will cause infinite loop and runtime **panic**. On
/// enum level the _`no_recursion`_ rule will be applied to all of its variants.
///
Expand Down Expand Up @@ -391,7 +391,7 @@ static CONFIG: once_cell::sync::Lazy<utoipa_config::Config> =
/// * `min_properties = ...` Can be used to define minimum number of properties this struct can
/// contain. Value must be a number.
///* `no_recursion` Is used to break from recursion in case of looping schema tree e.g. `Pet` ->
/// `Owner` -> `Pet`. _`no_recursion`_ attribute must be used within `Ower` type not to allow
/// `Owner` -> `Pet`. _`no_recursion`_ attribute must be used within `Owner` type not to allow
/// recurring into `Pet`. Failing to do so will cause infinite loop and runtime **panic**. On
/// named field variant level the _`no_recursion`_ rule will be applied to all of its fields.
///
Expand Down Expand Up @@ -422,7 +422,7 @@ static CONFIG: once_cell::sync::Lazy<utoipa_config::Config> =
/// not in the code. If you'd like to mark the field as deprecated in the code as well use
/// Rust's own `#[deprecated]` attribute instead.
///* `no_recursion` Is used to break from recursion in case of looping schema tree e.g. `Pet` ->
/// `Owner` -> `Pet`. _`no_recursion`_ attribute must be used within `Ower` type not to allow
/// `Owner` -> `Pet`. _`no_recursion`_ attribute must be used within `Owner` type not to allow
/// recurring into `Pet`. Failing to do so will cause infinite loop and runtime **panic**.
///
/// #### Mixed Enum Unnamed Field Variant's Field Configuration Options
Expand Down Expand Up @@ -3771,7 +3771,7 @@ mod parse_utils {
Punctuated::parse_terminated(&group)
}

pub fn parse_comma_separated_within_parethesis_with<T>(
pub fn parse_comma_separated_within_parenthesis_with<T>(
input: ParseStream,
with: fn(ParseStream) -> syn::Result<T>,
) -> syn::Result<Punctuated<T, Comma>>
Expand Down
9 changes: 5 additions & 4 deletions utoipa-gen/src/openapi.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::borrow::Cow;

use desynt::StripRaw;
use proc_macro2::Ident;
use syn::{
bracketed, parenthesized,
Expand Down Expand Up @@ -440,7 +441,7 @@ impl OpenApi<'_> {
.segments
.iter()
.take(nest_api.path.segments.len() - 1)
.map(|segment| segment.ident.to_string())
.map(|segment| segment.ident.strip_raw().to_string())
.collect::<Vec<_>>()
.join("::");
let tags = &item.tags.iter().collect::<Array<_>>();
Expand Down Expand Up @@ -696,7 +697,7 @@ fn impl_paths(handler_paths: Option<&Punctuated<ExprPath, Comma>>) -> Paths {
let segments = handler.path.segments.iter().collect::<Vec<_>>();
let handler_config_name = segments
.iter()
.map(|segment| segment.ident.to_string())
.map(|segment| segment.ident.strip_raw().to_string())
.collect::<Vec<_>>()
.join("_");
let handler_fn = &segments.last().unwrap().ident;
Expand All @@ -706,7 +707,7 @@ fn impl_paths(handler_paths: Option<&Punctuated<ExprPath, Comma>>) -> Paths {
let tag = segments
.iter()
.take(segments.len() - 1)
.map(|part| part.ident.to_string())
.map(|part| part.ident.strip_raw().to_string())
.collect::<Vec<_>>()
.join("::");

Expand Down Expand Up @@ -759,7 +760,7 @@ fn impl_paths(handler_paths: Option<&Punctuated<ExprPath, Comma>>) -> Paths {
let segments = handler.path.segments.iter().collect::<Vec<_>>();
let handler_config_name = segments
.iter()
.map(|segment| segment.ident.to_string())
.map(|segment| segment.ident.strip_raw().to_string())
.collect::<Vec<_>>()
.join("_");
let handler_ident_config = format_ident!("{}_config", handler_config_name);
Expand Down
12 changes: 6 additions & 6 deletions utoipa-gen/src/openapi/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,19 +412,19 @@ mod tests {
#[test]
fn contact_from_only_name() {
let author = "Suzy Lin";
let contanct = Contact::try_from(author.to_string()).unwrap();
let contact = Contact::try_from(author.to_string()).unwrap();

assert!(contanct.name.is_some(), "Suzy should have name");
assert!(contanct.email.is_none(), "Suzy should not have email");
assert!(contact.name.is_some(), "Suzy should have name");
assert!(contact.email.is_none(), "Suzy should not have email");
}

#[test]
fn contact_from_name_and_email() {
let author = "Suzy Lin <[email protected]>";
let contanct = Contact::try_from(author.to_string()).unwrap();
let contact = Contact::try_from(author.to_string()).unwrap();

assert!(contanct.name.is_some(), "Suzy should have name");
assert!(contanct.email.is_some(), "Suzy should have email");
assert!(contact.name.is_some(), "Suzy should have name");
assert!(contact.email.is_some(), "Suzy should have email");
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion utoipa-gen/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ impl HttpMethod {
.map_err(|error| {
let mut diagnostics = Diagnostics::with_span(ident.span(), error.to_string());
if name == "connect" {
diagnostics = diagnostics.note("HTTP method `CONNET` is not supported by OpenAPI spec <https://spec.openapis.org/oas/latest.html#path-item-object>");
diagnostics = diagnostics.note("HTTP method `CONNECT` is not supported by OpenAPI spec <https://spec.openapis.org/oas/latest.html#path-item-object>");
}

diagnostics
Expand Down
2 changes: 1 addition & 1 deletion utoipa-gen/src/path/request_body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ impl Parse for RequestBodyAttr<'_> {
}

let media_type =
parse_utils::parse_comma_separated_within_parethesis_with(
parse_utils::parse_comma_separated_within_parenthesis_with(
&group,
group_parser,
)?
Expand Down
10 changes: 6 additions & 4 deletions utoipa-gen/src/path/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,10 +313,12 @@ impl<'r> ResponseValue<'r> {
buf.call(MediaTypeAttr::parse)
}

let content =
parse_utils::parse_comma_separated_within_parethesis_with(input, group_parser)?
.into_iter()
.collect::<Vec<_>>();
let content = parse_utils::parse_comma_separated_within_parenthesis_with(
input,
group_parser,
)?
.into_iter()
.collect::<Vec<_>>();

self.content = content;
}
Expand Down
9 changes: 5 additions & 4 deletions utoipa-gen/src/schema_type.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use desynt::StripRaw;
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use syn::spanned::Spanned;
Expand Down Expand Up @@ -68,7 +69,7 @@ impl SchemaType<'_> {
Some(segment) => segment,
None => return false,
};
let name = &*last_segment.ident.to_string();
let name = &*last_segment.ident.strip_raw().to_string();

#[cfg(not(any(
feature = "chrono",
Expand Down Expand Up @@ -233,7 +234,7 @@ impl ToTokensDiagnostics for SchemaType<'_> {
"schema type should have at least one segment in the path",
)
})?;
let name = &*last_segment.ident.to_string();
let name = &*last_segment.ident.strip_raw().to_string();

fn schema_type_tokens(
tokens: &mut TokenStream,
Expand Down Expand Up @@ -373,7 +374,7 @@ impl KnownFormat {
"type should have at least one segment in the path",
)
})?;
let name = &*last_segment.ident.to_string();
let name = &*last_segment.ident.strip_raw().to_string();

let variant = match name {
#[cfg(feature = "non_strict_integers")]
Expand Down Expand Up @@ -688,7 +689,7 @@ impl PrimitiveType {
)
});

let name = &*last_segment.ident.to_string();
let name = &*last_segment.ident.strip_raw().to_string();

let ty: syn::Type = match name {
"String" | "str" | "char" => syn::parse_quote!(#path),
Expand Down
Loading