mirror of
https://github.com/OMGeeky/confique.git
synced 2026-01-18 01:17:42 +01:00
Add #![visibility = "..."] attribute to specify visibility
This commit is contained in:
@@ -1,8 +1,12 @@
|
||||
//! Definition of the intermediate representation or AST.
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
|
||||
|
||||
/// The parsed input to the `gen_config` macro.
|
||||
pub(crate) struct Input {
|
||||
pub(crate) root: Node,
|
||||
pub(crate) visibility: Option<TokenStream>,
|
||||
}
|
||||
|
||||
/// One node in the tree of the configuration format. Can either be a leaf node
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::ast::{Expr, Input, Node};
|
||||
|
||||
|
||||
pub(crate) fn gen(input: Input) -> TokenStream {
|
||||
let visibility = quote! { pub(crate) };
|
||||
let visibility = input.visibility.clone().unwrap_or(quote! { pub(crate) });
|
||||
let toml = gen_toml(&input);
|
||||
let root_mod = gen_root_mod(&input, &visibility);
|
||||
let raw_mod = gen_raw_mod(&input, &visibility);
|
||||
|
||||
@@ -14,8 +14,14 @@ impl Parse for Input {
|
||||
fn parse(input: ParseStream) -> Result<Self, syn::Error> {
|
||||
let mut outer_attrs = input.call(syn::Attribute::parse_inner)?;
|
||||
let doc = extract_doc(&mut outer_attrs)?;
|
||||
let children = input.call(<Punctuated<_, syn::Token![,]>>::parse_terminated)?;
|
||||
|
||||
// `#![visibility = "..."]`
|
||||
let visibility = extract_single_name_value_attr("visibility", &mut outer_attrs)?
|
||||
.map(|v| Ok::<_, syn::Error>(assert_string_lit(v)?.parse::<TokenStream>()?))
|
||||
.transpose()?;
|
||||
|
||||
assert_no_extra_attrs(&outer_attrs)?;
|
||||
let children = input.call(<Punctuated<_, syn::Token![,]>>::parse_terminated)?;
|
||||
|
||||
let root = Node::Internal {
|
||||
doc,
|
||||
@@ -23,7 +29,7 @@ impl Parse for Input {
|
||||
children: children.into_iter().collect(),
|
||||
};
|
||||
|
||||
Ok(Self { root })
|
||||
Ok(Self { root, visibility })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,3 +147,39 @@ fn extract_doc(attrs: &mut Vec<syn::Attribute>) -> Result<Vec<String>, Error> {
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
fn extract_single_name_value_attr(
|
||||
name: &str,
|
||||
attrs: &mut Vec<syn::Attribute>,
|
||||
) -> Result<Option<syn::Lit>, Error> {
|
||||
let mut filtered = attrs.iter().filter(|attr| attr.path.is_ident(name));
|
||||
let meta = match filtered.next() {
|
||||
None => return Ok(None),
|
||||
Some(attr) => attr.parse_meta()?,
|
||||
};
|
||||
|
||||
let nv = match meta {
|
||||
syn::Meta::NameValue(nv) => nv,
|
||||
other => {
|
||||
let msg = format!(r#"expected `name = "value"` attribute syntax for `{}`"#, name);
|
||||
return Err(Error::new(other.span(), msg));
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(dupe) = filtered.next() {
|
||||
let msg = format!("duplicate `{}` attribute", name);
|
||||
return Err(Error::new(dupe.span(), msg));
|
||||
}
|
||||
|
||||
// Remove the attribute from the vector
|
||||
attrs.retain(|attr| !attr.path.is_ident(name));
|
||||
|
||||
Ok(Some(nv.lit))
|
||||
}
|
||||
|
||||
fn assert_string_lit(lit: syn::Lit) -> Result<String, Error> {
|
||||
match lit {
|
||||
syn::Lit::Str(s) => Ok(s.value()),
|
||||
_ => Err(Error::new(lit.span(), "expected string literal")),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,9 @@ use std::{net::IpAddr, path::PathBuf};
|
||||
use crate as confique;
|
||||
|
||||
crate::config! {
|
||||
//! An example configuration.
|
||||
#![visibility = "pub"]
|
||||
|
||||
dns: {
|
||||
/// The DNS server IP address.
|
||||
#[example = "1.1.1.1"]
|
||||
|
||||
Reference in New Issue
Block a user