forked from proxmox-mirrors/proxmox
api-macro: derive descriptions for structs
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
a6f21e7694
commit
4c77a7fece
@ -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<syn::LitStr>,
|
||||
pub description: Option<syn::LitStr>,
|
||||
|
||||
/// The specific schema type (Object, String, ...)
|
||||
item: SchemaItem,
|
||||
|
||||
@ -39,7 +39,7 @@ pub fn handle_method(mut attribs: JSONObject, mut func: syn::ItemFn) -> Result<T
|
||||
.unwrap_or(false);
|
||||
|
||||
let (doc_comment, doc_span) = util::get_doc_comments(&func.attrs)?;
|
||||
derive_descriptions(
|
||||
util::derive_descriptions(
|
||||
&mut input_schema,
|
||||
&mut returns_schema,
|
||||
&doc_comment,
|
||||
@ -98,44 +98,6 @@ pub fn handle_method(mut attribs: JSONObject, mut func: syn::ItemFn) -> Result<T
|
||||
//Ok(quote::quote!(#func))
|
||||
}
|
||||
|
||||
fn derive_descriptions(
|
||||
input_schema: &mut Schema,
|
||||
returns_schema: &mut Option<Schema>,
|
||||
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,
|
||||
|
||||
@ -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<TokenStream, Error> {
|
||||
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
|
||||
|
||||
@ -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<Schema>,
|
||||
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(())
|
||||
}
|
||||
|
||||
@ -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")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user