Skip to content

Commit

Permalink
implement auto-documenting routes
Browse files Browse the repository at this point in the history
  • Loading branch information
ThouCheese committed Apr 29, 2021
1 parent fe23eae commit 6388abd
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 1 deletion.
8 changes: 8 additions & 0 deletions core/codegen/src/attribute/route/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,13 @@ fn codegen_route(route: Route) -> Result<TokenStream> {
let rank = Optional(route.attr.rank);
let format = Optional(route.attr.format.as_ref());

// Get the doc comment
let doc_comment = route
.doc_comment
.as_ref()
.map(|dc| quote! { Some(#dc.to_string()) })
.unwrap_or_else(|| quote! { None });

Ok(quote! {
#handler_fn

Expand Down Expand Up @@ -353,6 +360,7 @@ fn codegen_route(route: Route) -> Result<TokenStream> {
format: #format,
rank: #rank,
sentinels: #sentinels,
doc_comment: #doc_comment,
}
}

Expand Down
19 changes: 18 additions & 1 deletion core/codegen/src/attribute/route/parse.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use devise::{syn, Spanned, SpanWrapped, Result, FromMeta};
use devise::ext::{SpanDiagnosticExt, TypeExt};
use indexmap::{IndexSet, IndexMap};
use syn::{Lit::Str, Meta::NameValue, MetaNameValue};

use crate::proc_macro_ext::Diagnostics;
use crate::http_codegen::{Method, MediaType};
Expand Down Expand Up @@ -29,6 +30,8 @@ pub struct Route {
pub handler: syn::ItemFn,
/// The parsed arguments to the user's function.
pub arguments: Arguments,
/// The doc comment describing this route
pub doc_comment: Option<String>
}

type ArgumentMap = IndexMap<Name, (syn::Ident, syn::Type)>;
Expand Down Expand Up @@ -209,9 +212,23 @@ impl Route {
})
.collect();

let doc_comment = handler
.attrs
.iter()
.filter(|a| a.path.is_ident("doc"))
.filter_map(|attr| attr.parse_meta().ok())
.filter_map(|meta| if let NameValue(MetaNameValue { lit: Str(string), .. }) = meta {
Some(string.value())
} else {
None
})
.flat_map(|string| string.split('\n').map(|s| s.trim().to_owned()).collect::<Vec<_>>())
.fold(String::new(), |acc, elem| acc + &elem + "\n");
let doc_comment = (!doc_comment.is_empty()).then(|| doc_comment);

diags.head_err_or(Route {
attr, path_params, query_params, data_guard, request_guards,
handler, arguments,
handler, arguments, doc_comment
})
}
}
Expand Down
41 changes: 41 additions & 0 deletions core/lib/src/doc/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//! Traits and structs related to automagically generating documentation for your Rocket routes

use std::marker::PhantomData;

#[derive(Default)]
pub struct Docs {
title: Option<String>,
description: Option<String>,
content_type: Option<String>,
}

pub struct Resolve<T: ?Sized>(PhantomData<T>);

pub trait Documented {
fn docs() -> Docs;
}

trait Undocumented {
fn docs() -> Docs {
Docs::default()
}
}

impl<T: ?Sized> Undocumented for T { }

impl<T: Documented + ?Sized> Resolve<T> {
pub const DOCUMENTED: bool = true;

pub fn docs() -> Docs {
T::docs()
}
}

// impl<T: Documented + ?Sized> Documented for Json<T> {
// fn docs() -> Docs {
// Docs {
// content_type: Some("application/json".to_string()),
// ..Self::docs()
// }
// }
// }
1 change: 1 addition & 0 deletions core/lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ pub mod fairing;
pub mod error;
pub mod catcher;
pub mod route;
pub mod doc;

// Reexport of HTTP everything.
pub mod http {
Expand Down
7 changes: 7 additions & 0 deletions core/lib/src/route/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ pub struct Route {
pub format: Option<MediaType>,
/// The discovered sentinels.
pub(crate) sentinels: Vec<Sentry>,
/// The doc comment associated with this route.
pub(crate) doc_comment: Option<String>,
}

impl Route {
Expand Down Expand Up @@ -253,6 +255,7 @@ impl Route {
sentinels: Vec::new(),
handler: Box::new(handler),
rank, uri, method,
doc_comment: None,
}
}

Expand Down Expand Up @@ -345,6 +348,9 @@ pub struct StaticInfo {
/// Route-derived sentinels, if any.
/// This isn't `&'static [SentryInfo]` because `type_name()` isn't `const`.
pub sentinels: Vec<Sentry>,
/// The doc comment associated with this route.
pub doc_comment: Option<String>,

}

#[doc(hidden)]
Expand All @@ -361,6 +367,7 @@ impl From<StaticInfo> for Route {
format: info.format,
sentinels: info.sentinels.into_iter().collect(),
uri,
doc_comment: info.doc_comment,
}
}
}

0 comments on commit 6388abd

Please sign in to comment.