Skip to content
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

Add capture_docs attribute #118

Merged
merged 14 commits into from
Jul 28, 2021
57 changes: 56 additions & 1 deletion derive/src/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,22 @@ mod keywords {
syn::custom_keyword!(scale_info);
syn::custom_keyword!(bounds);
syn::custom_keyword!(skip_type_params);
syn::custom_keyword!(capture_docs);
}

/// Parsed and validated set of `#[scale_info(...)]` attributes for an item.
pub struct Attributes {
bounds: Option<BoundsAttr>,
skip_type_params: Option<SkipTypeParamsAttr>,
capture_docs: Option<CaptureDocsAttr>,
}

impl Attributes {
/// Extract out `#[scale_info(...)]` attributes from an item.
pub fn from_ast(item: &syn::DeriveInput) -> syn::Result<Self> {
let mut bounds = None;
let mut skip_type_params = None;
let mut capture_docs = None;

let attributes_parser = |input: &ParseBuffer| {
let attrs: Punctuated<ScaleInfoAttr, Token![,]> =
Expand Down Expand Up @@ -75,6 +78,15 @@ impl Attributes {
}
skip_type_params = Some(parsed_skip_type_params);
}
ScaleInfoAttr::CaptureDocs(parsed_capture_docs) => {
if capture_docs.is_some() {
return Err(syn::Error::new(
attr.span(),
"Duplicate `capture_docs` attributes",
))
}
capture_docs = Some(parsed_capture_docs);
}
}
}
}
Expand Down Expand Up @@ -103,6 +115,7 @@ impl Attributes {
Ok(Self {
bounds,
skip_type_params,
capture_docs,
})
}

Expand All @@ -115,6 +128,15 @@ impl Attributes {
pub fn skip_type_params(&self) -> Option<&SkipTypeParamsAttr> {
self.skip_type_params.as_ref()
}

/// Returns the value of `#[scale_info(capture_docs = "..")]`.
///
/// Defaults to `CaptureDocsAttr::Default` if the attribute is not present.
pub fn capture_docs(&self) -> &CaptureDocsAttr {
self.capture_docs
.as_ref()
.unwrap_or(&CaptureDocsAttr::Default)
}
}

/// Parsed representation of the `#[scale_info(bounds(...))]` attribute.
Expand Down Expand Up @@ -180,10 +202,39 @@ impl SkipTypeParamsAttr {
}
}

/// Parsed representation of the `#[scale_info(capture_docs = "..")]` attribute.
#[derive(Clone)]
pub enum CaptureDocsAttr {
Default,
Always,
Never,
}

impl Parse for CaptureDocsAttr {
fn parse(input: &ParseBuffer) -> syn::Result<Self> {
input.parse::<keywords::capture_docs>()?;
input.parse::<syn::Token![=]>()?;
let capture_docs_lit = input.parse::<syn::LitStr>()?;

match capture_docs_lit.value().to_lowercase().as_str() {
"default" => Ok(Self::Default),
"always" => Ok(Self::Always),
"never" => Ok(Self::Never),
_ => {
Err(syn::Error::new_spanned(
capture_docs_lit,
r#"Invalid capture_docs value. Expected one of: "default", "always", "never" "#,
))
}
}
}
}

/// Parsed representation of one of the `#[scale_info(..)]` attributes.
pub enum ScaleInfoAttr {
Bounds(BoundsAttr),
SkipTypeParams(SkipTypeParamsAttr),
CaptureDocs(CaptureDocsAttr),
}

impl Parse for ScaleInfoAttr {
Expand All @@ -195,8 +246,12 @@ impl Parse for ScaleInfoAttr {
} else if lookahead.peek(keywords::skip_type_params) {
let skip_type_params = input.parse()?;
Ok(Self::SkipTypeParams(skip_type_params))
} else if lookahead.peek(keywords::capture_docs) {
let capture_docs = input.parse()?;
Ok(Self::CaptureDocs(capture_docs))
} else {
Err(input.error("Expected either `bounds` or `skip_type_params`"))
Err(input
.error("Expected one of: `bounds`, `skip_type_params` or `capture_docs"))
}
}
}
Loading