summaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2022-10-02 15:53:05 +0200
committerHampusM <hampus@hampusmat.com>2022-10-02 15:53:56 +0200
commitbebd446c2cdb1645be7197fa738a66b73449bfc5 (patch)
treef108476e54ce64de512d1e3636216e6291e86204 /src/lib.rs
parent930769ed7eb2a2b8af849f6c30661823351ae277 (diff)
feat: add feature_specific macroHEADv0.1.0master
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..87d933c
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,88 @@
+//! Utility macros for utilizing cargo features.
+
+#![deny(clippy::all)]
+#![deny(clippy::pedantic)]
+#![deny(missing_docs)]
+
+use proc_macro::TokenStream;
+use quote::quote;
+use syn::{parse2, Item, LitStr};
+
+/// Specifies that a item is only available with a specific feature enabled. This will also
+/// document that item is only available with the specified feature enabled by using
+/// the [`doc_cfg`] feature.
+///
+/// All this macro does is to add the following attributes:
+/// ```text
+/// #[cfg(feature = {FEATURE})]
+/// #[cfg_attr(doc_cfg, doc(cfg(feature = {FEATURE})))]
+/// ```
+///
+/// With `{FEATURE}` being replaced with the feature argument.
+///
+/// # Arguments
+/// - The feature. For example: `"parsing"`
+///
+/// # Panics
+/// If not attributed to a item or if arguments is missing.
+///
+/// # Examples
+/// ```
+/// # use feature_macros::feature_specific;
+/// #
+/// #[feature_specific("cool-things")]
+/// pub fn do_some_cool_thing() {
+/// // ...
+/// }
+/// ```
+///
+/// [`doc_cfg`]: https://doc.rust-lang.org/unstable-book/language-features/doc-cfg.html
+#[proc_macro_attribute]
+pub fn feature_specific(args_stream: TokenStream, item_stream: TokenStream) -> TokenStream {
+ create_feature_specific(args_stream.into(), item_stream.into())
+ .unwrap()
+ .into()
+}
+
+fn create_feature_specific(
+ args_stream: proc_macro2::TokenStream,
+ item_stream: proc_macro2::TokenStream,
+) -> Result<proc_macro2::TokenStream, Box<dyn std::error::Error>> {
+ let item = parse2::<Item>(item_stream)?;
+
+ let feature = parse2::<LitStr>(args_stream).unwrap().value();
+
+ Ok(quote! {
+ #[cfg(feature = #feature)]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = #feature)))]
+ #item
+ })
+}
+
+#[cfg(test)]
+mod tests {
+ use std::error::Error;
+
+ use super::*;
+
+ #[test]
+ fn create_feature_specific_works() -> Result<(), Box<dyn Error>> {
+ assert_eq!(
+ create_feature_specific(
+ quote! {"extra-stuff"},
+ quote! {
+ pub mod extra;
+ },
+ )?
+ .to_string(),
+ quote! {
+ #[cfg(feature = "extra-stuff")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-stuff")))]
+ pub mod extra;
+ }
+ .to_string()
+ );
+
+ Ok(())
+ }
+}