Skip to content

Commit

Permalink
Add capture_docs attribute (#118)
Browse files Browse the repository at this point in the history
* Add capture_docs attribute

* Refactor derive to use a struct for context

* Fmt

* Handle always/never capturing docs

* Use docs feature from tests

* Add tests for capture_docs attribute

* Fmt

* Clippy, you are right

* Clipping

* Reverse always docs logic

* Fix docs always tests

* Docs

* Change capture_docs to enum instead of bool

* Fmt
  • Loading branch information
ascjones authored Jul 28, 2021
1 parent eb28e12 commit 08fc6d4
Show file tree
Hide file tree
Showing 7 changed files with 425 additions and 231 deletions.
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

0 comments on commit 08fc6d4

Please sign in to comment.