diff --git a/proxmox-api-macro/src/api.rs b/proxmox-api-macro/src/api.rs index af438ce7..4f511807 100644 --- a/proxmox-api-macro/src/api.rs +++ b/proxmox-api-macro/src/api.rs @@ -40,11 +40,11 @@ pub const NUMBERNAMES: &[&str] = &["Number", "f32", "f64"]; /// ObjectSchema::new("text", &[ ... ]).foo(bar) /// } /// ``` -struct Schema { +pub struct Schema { span: Span, /// Common in all schema entry types: - description: Option, + pub description: Option, /// The specific schema type (Object, String, ...) item: SchemaItem, diff --git a/proxmox-api-macro/src/api/method.rs b/proxmox-api-macro/src/api/method.rs index 12373107..9c7240a7 100644 --- a/proxmox-api-macro/src/api/method.rs +++ b/proxmox-api-macro/src/api/method.rs @@ -39,7 +39,7 @@ pub fn handle_method(mut attribs: JSONObject, mut func: syn::ItemFn) -> Result Result, - doc_comment: &str, - doc_span: Span, -) -> Result<(), Error> { - // If we have a doc comment, allow automatically inferring the description for the input and - // output objects: - if doc_comment.is_empty() { - return Ok(()); - } - - let mut parts = doc_comment.split("\nReturns:"); - - if let Some(first) = parts.next() { - if input_schema.description.is_none() { - input_schema.description = Some(syn::LitStr::new(first.trim(), doc_span)); - } - } - - if let Some(second) = parts.next() { - if let Some(ref mut returns_schema) = returns_schema { - if returns_schema.description.is_none() { - returns_schema.description = Some(syn::LitStr::new(second.trim(), doc_span)); - } - } - - if parts.next().is_some() { - bail!( - doc_span, - "multiple 'Returns:' sections found in doc comment!" - ); - } - } - - Ok(()) -} - enum ParameterType<'a> { Value, ApiMethod, diff --git a/proxmox-api-macro/src/api/structs.rs b/proxmox-api-macro/src/api/structs.rs index 82cac929..97b128c2 100644 --- a/proxmox-api-macro/src/api/structs.rs +++ b/proxmox-api-macro/src/api/structs.rs @@ -6,11 +6,17 @@ use proc_macro2::TokenStream; use quote::quote_spanned; use super::Schema; -use crate::util::JSONObject; +use crate::util::{self, JSONObject}; pub fn handle_struct(attribs: JSONObject, stru: syn::ItemStruct) -> Result { + let mut schema: Schema = attribs.try_into()?; + + if schema.description.is_none() { + let (doc_comment, doc_span) = util::get_doc_comments(&stru.attrs)?; + util::derive_descriptions(&mut schema, &mut None, &doc_comment, doc_span)?; + } + let schema = { - let schema: Schema = attribs.try_into()?; let mut ts = TokenStream::new(); schema.to_schema(&mut ts)?; ts diff --git a/proxmox-api-macro/src/util.rs b/proxmox-api-macro/src/util.rs index 8d1579fe..588739fa 100644 --- a/proxmox-api-macro/src/util.rs +++ b/proxmox-api-macro/src/util.rs @@ -8,6 +8,10 @@ use syn::punctuated::Punctuated; use syn::spanned::Spanned; use syn::Token; +use failure::Error; + +use crate::api::Schema; + /// A more relaxed version of Ident which allows hyphens. /// /// Note that this acts both as an Ident and as a String so that we can easily access an &str @@ -399,3 +403,41 @@ pub fn get_doc_comments(attributes: &[syn::Attribute]) -> Result<(String, Span), Ok((doc_comment, doc_span)) } + +pub fn derive_descriptions( + input_schema: &mut Schema, + returns_schema: &mut Option, + doc_comment: &str, + doc_span: Span, +) -> Result<(), Error> { + // If we have a doc comment, allow automatically inferring the description for the input and + // output objects: + if doc_comment.is_empty() { + return Ok(()); + } + + let mut parts = doc_comment.split("\nReturns:"); + + if let Some(first) = parts.next() { + if input_schema.description.is_none() { + input_schema.description = Some(syn::LitStr::new(first.trim(), doc_span)); + } + } + + if let Some(second) = parts.next() { + if let Some(ref mut returns_schema) = returns_schema { + if returns_schema.description.is_none() { + returns_schema.description = Some(syn::LitStr::new(second.trim(), doc_span)); + } + } + + if parts.next().is_some() { + bail!( + doc_span, + "multiple 'Returns:' sections found in doc comment!" + ); + } + } + + Ok(()) +} diff --git a/proxmox-api-macro/tests/types.rs b/proxmox-api-macro/tests/types.rs index 9400a331..b03d52e4 100644 --- a/proxmox-api-macro/tests/types.rs +++ b/proxmox-api-macro/tests/types.rs @@ -16,6 +16,19 @@ use serde_json::Value; //#[derive(Clone, Debug, Deserialize, Serialize)] pub struct OkString(String); +#[api( + properties: { + test: { + type: String, + description: "Hello", + }, + }, +)] +/// A Foo. +pub struct Foo { + test: String, +} + // generates the following without the '_' prefix in the constant: impl OkString { pub const _API_SCHEMA: &'static schema::Schema = &schema::StringSchema::new("A string")