Skip to content

Commit

Permalink
Add doc comments to Rust macro helpers.
Browse files Browse the repository at this point in the history
  • Loading branch information
hdwalters committed Oct 9, 2024
1 parent e40f0f8 commit 1ef6f28
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 11 deletions.
84 changes: 77 additions & 7 deletions meta/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,80 @@ use proc_macro::TokenStream;
use syn::visit::Visit;
use syn::*;

/// To add context manager functions to a struct, annotate the struct
/// itself with `#[derive(ContextManager)`, and required fields with
/// `#[context]`. Creates three functions `with_foo()`, `with_foo_ref()`
/// and `with_foo_fn()`.
/// Derive macro `ContextManager` allows changes to be made to annotated
/// fields on a struct, with automatic reset on early error return.
///
/// In this example, we change some settings on an object, and rely on
/// the context manager to reset those settings when it fails. The context
/// manager creates three functions for each annotated field in the
/// `Amplifier` struct, and we call the following ones here:
///
/// * Function `Amplifier::with_panel_ref()` swaps the existing `panel`
/// field on the `Amplifier` object, passes the `Amplifier` object to
/// the lambda by mutable reference, swaps the old `panel` field on
/// exit, and returns the result.
///
/// * Function `Amplifier::with_power()` sets the `power` field on the
/// `Amplifier` object, and resets the old value on exit. Requires
/// the field being modified to implement the `Copy` and `Clone` traits.
///
/// * Function `Amplifier::with_panel_fn()` sets the `volume` field on
/// the encapsulated `Panel` object, by calling its setter function
/// `Panel::set_volume()`, and resets the old value on exit. Note,
/// the setter function is created by derive macro `ContextHelper`.
///
/// ```rust
/// use amber_meta::{ContextHelper, ContextManager};
///
/// #[derive(ContextManager)]
/// struct Amplifier {
/// #[context]
/// power: bool,
/// #[context]
/// panel: Panel,
/// }
///
/// #[derive(ContextHelper)]
/// struct Panel {
/// #[context]
/// started: bool,
/// #[context]
/// volume: u8,
/// display: Option<String>,
/// }
///
/// impl Panel {
/// fn new() -> Panel {
/// Panel { started: false, volume: 0, display: None }
/// }
/// }
///
/// fn demo_amplifier(amp: &mut Amplifier) -> Result<(), String> {
/// // Install a new control panel.
/// let mut panel = Panel::new();
/// amp.with_panel_ref(&mut panel, |amp| {
/// // Turn the power on.
/// amp.with_power(true, |amp| {
/// // Set the volume to 11.
/// amp.with_panel_fn(Panel::set_volume, 11, |amp| {
/// // Strum a guitar chord.
/// play_guitar(amp)?;
/// Ok(())
/// })?;
/// // Reset the volume on exit.
/// Ok(())
/// })?;
/// // Turn the power off on exit.
/// Ok(())
/// })?;
/// // Reinstall the old control panel on exit.
/// Ok(())
/// }
///
/// fn play_guitar(amp: &Amplifier) -> Result<(), String> {
/// Err(String::from("Blown fuse"))
/// }
/// ```
#[proc_macro_derive(ContextManager, attributes(context))]
pub fn context_manager(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as ItemStruct);
Expand All @@ -21,9 +91,9 @@ pub fn context_manager(input: TokenStream) -> TokenStream {
TokenStream::from(output)
}

/// To add setter functions designed to work with `with_foo_fn()` (see
/// above), annotate the struct itself with `#[derive(ContextHelper)`,
/// and required fields with `#[context]`.
/// Derive macro `ContextHelper` provides support functions for use with
/// context functions created by `ContextManager`; for more information,
/// see documentation for that macro.
#[proc_macro_derive(ContextHelper, attributes(context))]
pub fn context_helper(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as ItemStruct);
Expand Down
4 changes: 2 additions & 2 deletions meta/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ impl ManagerVisitor {
let concat = format!("with_{}", name);
let concat = Ident::new(&concat, name.span());
quote! {
/// Sets the field value (which must implement the Copy and
/// Clone traits) and restores the previous value after the
/// Sets the field value (which must implement the `Copy` and
/// `Clone` traits) and restores the previous value after the
/// body function has returned.
pub fn #concat<T, E, B>(&mut self, #name: #segment, mut body: B) -> Result<T, E>
where
Expand Down
4 changes: 2 additions & 2 deletions src/modules/formatter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::{io::{BufWriter, Write}, process::{Command, Stdio}};
#[derive(Debug, Clone, Copy)]
#[allow(non_camel_case_types)]
pub enum BashFormatter {
/// https://github.com/mvdan/sh
/// <https://github.com/mvdan/sh>
shfmt
}

Expand Down Expand Up @@ -71,4 +71,4 @@ impl BashFormatter {
}
}
}
}
}

0 comments on commit 1ef6f28

Please # to comment.