make-noop 0.1.0

Attribute macros that replace function, method, and impl-block bodies with no-ops, with customizable return values.
Documentation
use make_noop::{make_noop, make_unit, noop_returns};

#[make_noop]
fn unit_fn() {
    panic!("should never run");
}

#[make_noop]
fn returns_value() -> u32 {
    panic!("should never run");
}

#[make_noop]
fn returns_string() -> String {
    unreachable!()
}

struct Service;

#[make_noop]
impl Service {
    fn no_return(&self) {
        panic!("should never run");
    }

    fn with_return(&self, _x: i32) -> Vec<u8> {
        unreachable!()
    }

    fn associated() -> bool {
        unreachable!()
    }
}

struct Single;

impl Single {
    #[make_noop]
    fn only_this(&self) -> i64 {
        unreachable!()
    }
}

struct Custom;

#[make_noop]
impl Custom {
    // Defaults to `Default::default()`.
    fn defaulted(&self) -> i32 {
        unreachable!()
    }

    // Overrides the default with its own expression.
    #[noop_returns(7)]
    fn overridden(&self) -> i32 {
        unreachable!()
    }
}

#[test]
fn free_functions_are_noops() {
    unit_fn();
    assert_eq!(returns_value(), 0);
    assert_eq!(returns_string(), String::new());
}

#[test]
fn impl_block_methods_are_noops() {
    let s = Service;
    s.no_return();
    assert_eq!(s.with_return(5), Vec::<u8>::new());
    assert!(!Service::associated());
}

#[test]
fn single_method_is_noop() {
    assert_eq!(Single.only_this(), 0);
}

#[test]
fn noop_returns_override_in_impl_block() {
    let c = Custom;
    assert_eq!(c.defaulted(), 0);
    assert_eq!(c.overridden(), 7);
}

#[noop_returns(99)]
fn standalone_fn() -> u32 {
    unreachable!()
}

#[noop_returns(String::from("yo"))]
fn standalone_string() -> String {
    unreachable!()
}

struct Standalone;

impl Standalone {
    #[noop_returns(true)]
    fn method(&self) -> bool {
        unreachable!()
    }
}

struct Shared;

#[noop_returns(3)]
impl Shared {
    // Returns the impl-wide default of `3`.
    fn first(&self) -> i32 {
        unreachable!()
    }

    fn second(&self) -> i32 {
        unreachable!()
    }

    // Overrides the impl-wide default with its own expression.
    #[noop_returns(42)]
    fn third(&self) -> i32 {
        unreachable!()
    }
}

#[test]
fn noop_returns_standalone() {
    assert_eq!(standalone_fn(), 99);
    assert_eq!(standalone_string(), "yo");
    assert!(Standalone.method());
}

#[test]
fn noop_returns_on_impl_block() {
    let s = Shared;
    assert_eq!(s.first(), 3);
    assert_eq!(s.second(), 3);
    assert_eq!(s.third(), 42);
}

#[make_unit]
#[derive(Debug, Clone, PartialEq)]
struct NamedFields {
    verbose: bool,
    retries: u32,
}

#[make_unit]
pub struct TupleFields(i32, String);

#[make_unit]
struct AlreadyUnit;

#[test]
fn make_unit_strips_fields() {
    // All three are now unit structs constructed with no fields, and the
    // preserved `#[derive]` still applies.
    assert_eq!(NamedFields, NamedFields);
    let _ = TupleFields;
    let _ = AlreadyUnit;
}