Skip to content

Commit

Permalink
Add description support for object field. (#492)
Browse files Browse the repository at this point in the history
This commit add description support for `ToSchema` field with
`value_type = Object`.
```rust
 #[derive(ToSchema)]
 struct Value {
     /// This is object value
     #[schema(value_type = Object)]
     object: String,
 }
```
  • Loading branch information
juhaku committed Feb 19, 2023
1 parent e06d1ef commit 3705e4e
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 40 deletions.
68 changes: 28 additions & 40 deletions utoipa-gen/src/component/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1410,6 +1410,24 @@ impl<'a> SchemaProperty<'a> {
fn is_option(&self) -> bool {
matches!(self.type_tree.generic_type, Some(GenericType::Option))
}

fn get_description(&self) -> Option<TokenStream> {
self.comments
.and_then(|comments| {
let comment = CommentAttributes::as_formatted_string(comments);
if comment.is_empty() {
None
} else {
Some(comment)
}
})
.map(|description| quote! { .description(Some(#description)) })
}

fn get_deprecated(&self) -> Option<TokenStream> {
self.deprecated
.map(|deprecated| quote! { .deprecated(Some(#deprecated)) })
}
}

impl ToTokens for SchemaProperty<'_> {
Expand All @@ -1420,20 +1438,8 @@ impl ToTokens for SchemaProperty<'_> {
let mut features = self.features.unwrap_or(&empty_features).clone();
let example = features.pop_by(|feature| matches!(feature, Feature::Example(_)));

let deprecated = self
.deprecated
.map(|deprecated| quote! { .deprecated(Some(#deprecated)) });
let description = self
.comments
.and_then(|comments| {
let comment = CommentAttributes::as_formatted_string(comments);
if comment.is_empty() {
None
} else {
Some(comment)
}
})
.map(|description| quote! { .description(Some(#description)) });
let deprecated = self.get_deprecated();
let description = self.get_description();
// Maps are treated as generic objects with no named properties and
// additionalProperties denoting the type
// maps have 2 child schemas and we are interested the second one of them
Expand Down Expand Up @@ -1472,20 +1478,8 @@ impl ToTokens for SchemaProperty<'_> {
let max_items = pop_feature!(features => Feature::MaxItems(_));
let min_items = pop_feature!(features => Feature::MinItems(_));

let deprecated = self
.deprecated
.map(|deprecated| quote! { .deprecated(Some(#deprecated)) });
let description = self
.comments
.and_then(|comments| {
let comment = CommentAttributes::as_formatted_string(comments);
if comment.is_empty() {
None
} else {
Some(comment)
}
})
.map(|description| quote! { .description(Some(#description)) });
let deprecated = self.get_deprecated();
let description = self.get_description();

let schema_property = SchemaProperty {
type_tree: self
Expand Down Expand Up @@ -1573,17 +1567,8 @@ impl ToTokens for SchemaProperty<'_> {
})
}

if let Some(description) =
self.comments.map(CommentAttributes::as_formatted_string)
{
if !description.is_empty() {
tokens.extend(quote! {.description(Some(#description))})
}
};

if let Some(deprecated) = self.deprecated {
tokens.extend(quote! { .deprecated(Some(#deprecated)) });
}
tokens.extend(self.get_description());
tokens.extend(self.get_deprecated());

if let Some(features) = self.features {
for feature in
Expand All @@ -1601,7 +1586,10 @@ impl ToTokens for SchemaProperty<'_> {
.unwrap_or_default();

if type_tree.is_object() {
tokens.extend(quote! { utoipa::openapi::ObjectBuilder::new() })
let deprecated = self.get_deprecated();
let description = self.get_description();

tokens.extend(quote! { utoipa::openapi::ObjectBuilder::new()#description #deprecated })
} else {
let type_path = &**type_tree.path.as_ref().unwrap();
if is_inline {
Expand Down
25 changes: 25 additions & 0 deletions utoipa-gen/tests/schema_derive_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3821,3 +3821,28 @@ fn derive_struct_with_deprecated_fields() {
})
)
}

#[test]
fn derive_schema_with_object_type_description() {
let value = api_doc! {
struct Value {
/// This is object value
#[schema(value_type = Object)]
object: String,
}
};

assert_json_eq!(
value,
json!({
"properties": {
"object": {
"description": "This is object value",
"type": "object"
},
},
"required": ["object"],
"type": "object"
})
)
}

0 comments on commit 3705e4e

Please sign in to comment.