-
-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support #[builder(getter(...))]
attribute
#222
Changes from 8 commits
e0c535b
834978e
60eb3e9
8c4940d
710f9ec
2871335
f04525a
9aa0a6a
0fa1ba6
bb484c4
7212fa0
c0cca06
6babf8e
9db3e48
2ed3e51
a6a007b
56ca0cd
a8fc70d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
use crate::util::prelude::Result; | ||
|
||
pub(crate) const DOCS_CONTEXT: &str = "builder struct's impl block"; | ||
|
||
pub(crate) fn parse_docs(meta: &syn::Meta) -> Result<super::SpannedKey<Vec<syn::Attribute>>> { | ||
crate::parsing::parse_docs_without_self_mentions(DOCS_CONTEXT, meta) | ||
} | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
use std::ops::Deref; | ||
|
||
use darling::FromMeta; | ||
use proc_macro2::Span; | ||
use syn::spanned::Spanned; | ||
|
||
use super::{docs_utils::parse_docs, SpannedKey}; | ||
|
||
/// Wrapper around the getter config that allows it to work as both a flag and | ||
/// a config. | ||
#[derive(Debug)] | ||
pub(crate) struct OptionalGetterConfig { | ||
span: Span, | ||
getter_config: Option<GetterConfig>, | ||
} | ||
lazkindness marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
impl OptionalGetterConfig { | ||
pub(crate) fn span(&self) -> Span { | ||
self.span | ||
} | ||
} | ||
|
||
impl FromMeta for OptionalGetterConfig { | ||
fn from_none() -> Option<Self> { | ||
Some(Self { | ||
span: Span::call_site(), | ||
getter_config: None, | ||
}) | ||
} | ||
|
||
fn from_meta(mi: &syn::Meta) -> darling::Result<Self> { | ||
GetterConfig::from_meta(mi).map(|getter_config| Self { | ||
span: mi.span(), | ||
getter_config: Some(getter_config), | ||
}) | ||
} | ||
} | ||
|
||
impl Deref for OptionalGetterConfig { | ||
type Target = Option<GetterConfig>; | ||
|
||
fn deref(&self) -> &Self::Target { | ||
&self.getter_config | ||
} | ||
} | ||
|
||
#[derive(Debug)] | ||
pub(crate) enum GetterConfig { | ||
#[allow(unused)] | ||
Inferred, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should probably clarify what |
||
Specified(SpecifiedGetterConfig), | ||
} | ||
|
||
impl FromMeta for GetterConfig { | ||
fn from_none() -> Option<Self> { | ||
None | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this already the default implementation of this trait method in |
||
|
||
fn from_meta(mi: &syn::Meta) -> darling::Result<Self> { | ||
mi.span(); | ||
lazkindness marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if let syn::Meta::Path(_) = mi { | ||
Ok(Self::Inferred) | ||
} else { | ||
SpecifiedGetterConfig::from_meta(mi).map(Self::Specified) | ||
} | ||
} | ||
} | ||
|
||
impl GetterConfig { | ||
pub(crate) fn name(&self) -> Option<&syn::Ident> { | ||
match self { | ||
Self::Inferred => None, | ||
Self::Specified(config) => config.name.as_ref().map(|n| &n.value), | ||
} | ||
} | ||
|
||
pub(crate) fn vis(&self) -> Option<&syn::Visibility> { | ||
match self { | ||
Self::Inferred => None, | ||
Self::Specified(config) => config.vis.as_ref().map(|v| &v.value), | ||
} | ||
} | ||
|
||
pub(crate) fn docs(&self) -> Option<&[syn::Attribute]> { | ||
match self { | ||
Self::Inferred => None, | ||
Self::Specified(config) => config.docs.as_ref().map(|a| &a.value).map(|a| &**a), | ||
} | ||
} | ||
} | ||
|
||
#[derive(Debug, FromMeta)] | ||
pub(crate) struct SpecifiedGetterConfig { | ||
name: Option<SpannedKey<syn::Ident>>, | ||
vis: Option<SpannedKey<syn::Visibility>>, | ||
|
||
#[darling(rename = "doc", default, with = parse_docs, map = Some)] | ||
docs: Option<SpannedKey<Vec<syn::Attribute>>>, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it makes sense to extract this module. It's okay to just copy this small function into the
getter
module. TheDOCS_CONTEXT
isn't meant to be a cross-module-shared variable with such a generic name, it's meant to be module-local and describe the context where the docs will be pasted for the config param defined in that module