Skip to content

Commit

Permalink
Feature path proc macro (#5)
Browse files Browse the repository at this point in the history
* Path proc macro resolve basic properties
  • Loading branch information
juhaku authored Jan 2, 2022
1 parent 6847d08 commit 749ccf9
Show file tree
Hide file tree
Showing 11 changed files with 579 additions and 110 deletions.
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ members = [

[features]
swagger_ui = ["rust-embed", "mime_guess"]
debug = ["utoipa-gen/debug"]
actix_gen = ["utoipa-gen/actix_gen"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Expand All @@ -20,4 +22,4 @@ serde_json = "1.0.68"
rust-embed = { version = "6.2.0", optional = true }
actix-web = { version = "3.3.2", optional = true }
mime_guess = { version = "2.0.3", optional = true }
utoipa-gen = { path = "./utoipa-gen" }
utoipa-gen = { path = "./utoipa-gen" }
14 changes: 14 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,17 @@ pub trait OpenApi {
pub trait Component {
fn component() -> openapi::schema::Component;
}

pub trait Path {
fn path() -> &'static str;

fn path_item() -> openapi::path::PathItem;
}

pub trait DefaultTag {
fn tag() -> &'static str;
}

pub trait Tag {
fn tag() -> &'static str;
}
16 changes: 0 additions & 16 deletions src/openapi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,17 +159,6 @@ impl Default for Required {
}
}

#[macro_export]
macro_rules! option {
( $val:expr ) => {
if $val.to_string().is_empty() {
None
} else {
Some($val)
}
};
}

#[cfg(test)]
mod tests {

Expand Down Expand Up @@ -243,9 +232,4 @@ mod tests {
);
Ok(())
}

#[test]
fn option() {
assert_eq!(None, option!(""))
}
}
8 changes: 7 additions & 1 deletion src/openapi/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,13 @@ impl Operation {
}

pub fn with_tag<S: AsRef<str>>(mut self, tag: S) -> Self {
self.tags.as_mut().unwrap().push(tag.as_ref().to_string());
let tag_string = tag.as_ref().to_string();
match self.tags {
Some(ref mut tags) => tags.push(tag_string),
None => {
self.tags = Some(vec![tag_string]);
}
}

self
}
Expand Down
80 changes: 14 additions & 66 deletions tests/utoipa_gen_test.rs
Original file line number Diff line number Diff line change
@@ -1,84 +1,32 @@
use std::collections::HashMap;

use actix_web::{delete, HttpResponse, Responder};
use serde_json::json;
// use utoipa::openapi_spec;
use utoipa::{api_operation, Component, OpenApi};
use utoipa::{path, OpenApi};

// mod api {
// use super::*;

/// Delete foo entity
///
/// Delete foo entity by what
#[api_operation(delete, responses = [
#[crate::path(responses = [
(200, "success", String),
(400, "my bad error", u64),
(404, "vault not found"),
(500, "internal server error")
])]
fn foo_delete() {}
#[delete("/foo")]
async fn foo_delete() -> impl Responder {
HttpResponse::Ok().json(json!({"ok": "OK"}))
}
// }

#[test]
fn derive_openapi() {
// use crate::api::__path_foo_delete;
#[derive(OpenApi, Default)]
#[openapi(handler_files = ["tests/utoipa_gen_test.rs"])]
#[openapi(handler_files = [], handlers = [foo_delete])]
struct ApiDoc;

println!("{:?}", ApiDoc::openapi().to_json())
}

#[test]
fn derive_component_struct() {
/// Mode defines user type
#[derive(Component)]
#[component(default = "Mode1", example = "Mode2")]
enum Mode {
/// Mode1 is admin user
Mode1,
Mode2,
// Mode3(usize),
// Mode4 { x: String },
// Mode5(usize, String),
}

#[derive(Component)]
struct Book {
#[component(default = "crate::random_default", example = "Book 1")]
name: String,

#[component(
default = "test",
example = "base64 text",
format = "ComponentFormat::Byte"
)]
hash: String,
}

/// This is user component
///
/// User component is being used to store user information
#[derive(Component)]
// #[component()]
struct User {
/// This is a database id of a user
#[component(default = 1)]
id: u64,
// username: String,
/// User authenticated roles
roles: Vec<String>,
/// Foobar hashmap
foobar: HashMap<String, i64>,
/// Optional value is user enabled
enabled: Option<bool>,
// random: Option<Vec<String>>,
// mode: Option<Mode>,
// book: Book,
long_property: String,
}

#[derive(OpenApi, Default)]
#[openapi(handler_files = [], components = [User, Book, Mode])]
struct ApiDoc;

println!("{}", ApiDoc::openapi().to_json().unwrap());
}

fn random_default() -> String {
"random".to_string()
}
4 changes: 4 additions & 0 deletions utoipa-gen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@ proc-macro2 = "1.0.32"
syn = "1.0.81"
quote = "1.0.10"
proc-macro-error = "1.0.4"

[features]
debug = []
actix_gen = []
4 changes: 2 additions & 2 deletions utoipa-gen/src/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ impl CommentAttributes {
}
}

#[cfg_attr(feature = "all-features", derive(Debug))]
#[cfg_attr(feature = "debug", derive(Debug))]
/// AttributeType is parsed representation of `#[component(...)]` attribute values of Component derive.
pub(crate) enum AttributeType {
Default(String, Span),
Expand Down Expand Up @@ -106,7 +106,7 @@ impl ToTokens for AttributeType {
}
}

#[cfg_attr(feature = "all-features", derive(Debug))]
#[cfg_attr(feature = "debug", derive(Debug))]
/// Wrapper struct for containing parsed [`enum@AttributeType`]s. It implements custom parser
/// to parse `#[component(...)]` attribute content of Component derive macro.
pub(crate) struct ComponentAttribute(pub(crate) Vec<AttributeType>);
Expand Down
14 changes: 7 additions & 7 deletions utoipa-gen/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ pub(crate) fn impl_component(data: syn::Data, attrs: Vec<syn::Attribute>) -> Tok
}
}

#[cfg_attr(feature = "all-features", derive(Debug))]
#[cfg_attr(feature = "debug", derive(Debug))]

enum FieldType {
Named,
Unnamed,
}

#[cfg_attr(feature = "all-features", derive(Debug))]
#[cfg_attr(feature = "debug", derive(Debug))]
/// Holds the OpenAPI Component implementation which can be added the Schema.
enum ComponentVariant<'a> {
/// Object variant is rust sturct with Component derive annotation.
Expand Down Expand Up @@ -366,7 +366,7 @@ fn create_complex_property(
}
}

#[cfg_attr(feature = "all-features", derive(Debug))]
#[cfg_attr(feature = "debug", derive(Debug))]
/// Linked list of implementing types of a field in a struct.
struct ComponentPart<'a> {
ident: &'a Ident,
Expand Down Expand Up @@ -500,26 +500,26 @@ impl<'a> Iterator for ComponentPartRef<'a, ComponentPart<'a>> {
}
}

#[cfg_attr(feature = "all-features", derive(Debug))]
#[cfg_attr(feature = "debug", derive(Debug))]
#[derive(Clone, Copy, PartialEq)]
enum ValueType {
Primitive,
Object,
}

#[cfg_attr(feature = "all-features", derive(Debug))]
#[cfg_attr(feature = "debug", derive(Debug))]
#[derive(PartialEq, Clone, Copy)]
enum GenericType {
Vec,
Map,
Option,
}

#[cfg_attr(feature = "all-features", derive(Debug))]
#[cfg_attr(feature = "debug", derive(Debug))]
#[derive(PartialEq)]
struct TypeTuple<'a, T>(T, &'a Ident);

#[cfg_attr(feature = "all-features", derive(Debug))]
#[cfg_attr(feature = "debug", derive(Debug))]
#[derive(Default, PartialEq)]
struct Component<'a> {
option: bool,
Expand Down
Loading

0 comments on commit 749ccf9

Please sign in to comment.