aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2022-07-31 13:26:41 +0200
committerHampusM <hampus@hampusmat.com>2022-08-01 15:52:23 +0200
commit3383faeaf8342cf4637b6d9a9dfba30b1684edca (patch)
tree3a4e23d299d077eaf82cb09a093eaaae384e4ec2
parent8d2c6412fec2f35581a48433421db4b03a8d6657 (diff)
feat: add hide impl of Injectable from documentation
This will make it so that by default the impl of Injectable is hidden from user code documentation. This commit also includes a flag for the injectable macro to disable the aforementioned feature
-rw-r--r--macros/src/injectable_impl.rs11
-rw-r--r--macros/src/injectable_macro_args.rs85
-rw-r--r--macros/src/lib.rs21
-rw-r--r--macros/src/util/iterator_ext.rs28
-rw-r--r--macros/src/util/mod.rs1
5 files changed, 134 insertions, 12 deletions
diff --git a/macros/src/injectable_impl.rs b/macros/src/injectable_impl.rs
index f510407..227a8c6 100644
--- a/macros/src/injectable_impl.rs
+++ b/macros/src/injectable_impl.rs
@@ -38,7 +38,7 @@ impl Parse for InjectableImpl
impl InjectableImpl
{
- pub fn expand(&self) -> proc_macro2::TokenStream
+ pub fn expand(&self, no_doc_hidden: bool) -> proc_macro2::TokenStream
{
let Self {
dependency_types,
@@ -51,9 +51,18 @@ impl InjectableImpl
let get_dependencies = Self::_create_get_dependencies(dependency_types);
+ let maybe_doc_hidden = if no_doc_hidden {
+ quote! {}
+ } else {
+ quote! {
+ #[doc(hidden)]
+ }
+ };
+
quote! {
#original_impl
+ #maybe_doc_hidden
impl #generics syrette::interfaces::injectable::Injectable for #self_type {
fn resolve(
#di_container_var: &syrette::DIContainer
diff --git a/macros/src/injectable_macro_args.rs b/macros/src/injectable_macro_args.rs
index 4ef4389..43f8e11 100644
--- a/macros/src/injectable_macro_args.rs
+++ b/macros/src/injectable_macro_args.rs
@@ -1,17 +1,92 @@
use syn::parse::{Parse, ParseStream};
-use syn::TypePath;
+use syn::punctuated::Punctuated;
+use syn::{braced, Ident, LitBool, Token, TypePath};
+
+use crate::util::iterator_ext::IteratorExt;
+
+pub const INJECTABLE_MACRO_FLAGS: &[&str] = &["no_doc_hidden"];
+
+pub struct InjectableMacroFlag
+{
+ pub flag: Ident,
+ pub is_on: LitBool,
+}
+
+impl Parse for InjectableMacroFlag
+{
+ fn parse(input: ParseStream) -> syn::Result<Self>
+ {
+ let input_forked = input.fork();
+
+ let flag: Ident = input_forked.parse()?;
+
+ let flag_str = flag.to_string();
+
+ if !INJECTABLE_MACRO_FLAGS.contains(&flag_str.as_str()) {
+ return Err(input.error(format!(
+ "Unknown flag '{}'. Expected one of [ {} ]",
+ flag_str,
+ INJECTABLE_MACRO_FLAGS.join(",")
+ )));
+ }
+
+ input.parse::<Ident>()?;
+
+ input.parse::<Token![=]>()?;
+
+ let is_on: LitBool = input.parse()?;
+
+ Ok(Self { flag, is_on })
+ }
+}
pub struct InjectableMacroArgs
{
- pub interface: TypePath,
+ pub interface: Option<TypePath>,
+ pub flags: Punctuated<InjectableMacroFlag, Token![,]>,
}
impl Parse for InjectableMacroArgs
{
fn parse(input: ParseStream) -> syn::Result<Self>
{
- Ok(Self {
- interface: input.parse()?,
- })
+ let interface = input.parse::<TypePath>().ok();
+
+ if interface.is_some() {
+ let comma_input_lookahead = input.lookahead1();
+
+ if !comma_input_lookahead.peek(Token![,]) {
+ return Ok(Self {
+ interface,
+ flags: Punctuated::new(),
+ });
+ }
+
+ input.parse::<Token![,]>()?;
+ }
+
+ if input.is_empty() {
+ return Ok(Self {
+ interface,
+ flags: Punctuated::new(),
+ });
+ }
+
+ let braced_content;
+
+ braced!(braced_content in input);
+
+ let flags = braced_content.parse_terminated(InjectableMacroFlag::parse)?;
+
+ let flag_names = flags
+ .iter()
+ .map(|flag| flag.flag.to_string())
+ .collect::<Vec<_>>();
+
+ if let Some(dupe_flag_name) = flag_names.iter().find_duplicate() {
+ return Err(input.error(format!("Duplicate flag '{}'", dupe_flag_name)));
+ }
+
+ Ok(Self { interface, flags })
}
}
diff --git a/macros/src/lib.rs b/macros/src/lib.rs
index aca4007..7dba7d1 100644
--- a/macros/src/lib.rs
+++ b/macros/src/lib.rs
@@ -14,16 +14,21 @@ mod factory_type_alias;
mod injectable_impl;
mod injectable_macro_args;
mod libs;
+mod util;
use declare_interface_args::DeclareInterfaceArgs;
use injectable_impl::InjectableImpl;
use injectable_macro_args::InjectableMacroArgs;
use libs::intertrait_macros::gen_caster::generate_caster;
-/// Makes a struct injectable. Thereby usable with `DIContainer`.
+/// Makes a struct injectable. Thereby usable with [`DIContainer`].
///
/// # Arguments
/// * (Optional) A interface trait the struct implements.
+/// * (Zero or more) Flags wrapped in curly braces. Like `{ a = true, b = false }`
+///
+/// # Flags
+/// - `no_doc_hidden` - Don't hide the impl of the [`Injectable`] trait from documentation.
///
/// # Panics
/// If the attributed item is not a impl.
@@ -53,15 +58,19 @@ use libs::intertrait_macros::gen_caster::generate_caster;
#[proc_macro_attribute]
pub fn injectable(args_stream: TokenStream, impl_stream: TokenStream) -> TokenStream
{
- let should_declare_interface = !args_stream.is_empty();
+ let InjectableMacroArgs { interface, flags } = parse_macro_input!(args_stream);
- let injectable_impl: InjectableImpl = parse(impl_stream).unwrap();
+ let mut flags_iter = flags.iter();
- let expanded_injectable_impl = injectable_impl.expand();
+ let no_doc_hidden = flags_iter
+ .find(|flag| flag.flag.to_string().as_str() == "no_doc_hidden")
+ .map_or(false, |flag| flag.is_on.value);
+
+ let injectable_impl: InjectableImpl = parse(impl_stream).unwrap();
- let maybe_decl_interface = if should_declare_interface {
- let InjectableMacroArgs { interface } = parse_macro_input!(args_stream);
+ let expanded_injectable_impl = injectable_impl.expand(no_doc_hidden);
+ let maybe_decl_interface = if interface.is_some() {
let self_type = &injectable_impl.self_type;
quote! {
diff --git a/macros/src/util/iterator_ext.rs b/macros/src/util/iterator_ext.rs
new file mode 100644
index 0000000..86db6cb
--- /dev/null
+++ b/macros/src/util/iterator_ext.rs
@@ -0,0 +1,28 @@
+use std::collections::HashMap;
+use std::hash::Hash;
+
+pub trait IteratorExt<Item>
+{
+ fn find_duplicate(&mut self) -> Option<Item>;
+}
+
+impl<Iter> IteratorExt<Iter::Item> for Iter
+where
+ Iter: Iterator,
+ Iter::Item: Eq + Hash + Copy,
+{
+ fn find_duplicate(&mut self) -> Option<Iter::Item>
+ {
+ let mut iterated_item_map = HashMap::<Iter::Item, ()>::new();
+
+ for item in self {
+ if iterated_item_map.contains_key(&item) {
+ return Some(item);
+ }
+
+ iterated_item_map.insert(item, ());
+ }
+
+ None
+ }
+}
diff --git a/macros/src/util/mod.rs b/macros/src/util/mod.rs
new file mode 100644
index 0000000..fe2fbbc
--- /dev/null
+++ b/macros/src/util/mod.rs
@@ -0,0 +1 @@
+pub mod iterator_ext;