make-noop 0.1.0

Attribute macros that replace function, method, and impl-block bodies with no-ops, with customizable return values.
Documentation
# make-noop

[![Crates.io](https://img.shields.io/crates/v/make-noop.svg)](https://crates.io/crates/make-noop)
[![Docs.rs](https://docs.rs/make-noop/badge.svg)](https://docs.rs/make-noop)
[![CI](https://github.com/s23b/make-noop/actions/workflows/ci.yml/badge.svg)](https://github.com/s23b/make-noop/actions/workflows/ci.yml)
[![License: MIT OR Apache-2.0](https://img.shields.io/crates/l/make-noop.svg)](#license)

Attribute macros that replace function, method, and `impl`-block bodies with
no-ops, and strip a struct down to a unit struct.

The point is to toggle that no-op'ing on a compile-time condition. Pair any of
these macros with [`cfg_attr`] so that a feature flag (or any `cfg`) decides
whether the real implementation is compiled or quietly replaced with a stub —
no `#[cfg]` blocks duplicating each item, and no runtime branch.

```rust
use make_noop::{make_noop, make_unit, noop_returns};

// With the `dry-run` feature on, this becomes a no-op; otherwise it runs for real.
#[cfg_attr(feature = "dry-run", make_noop)]
fn launch_missiles(hardware: &Hardware) {
    hardware.arm();
    hardware.fire();
}

// In `dry-run`, report success without touching the network.
#[cfg_attr(feature = "dry-run", noop_returns(Ok(())))]
fn upload(client: &Client, blob: &[u8]) -> Result<(), Error> {
    client.put(blob)
}

// In `dry-run`, collapse the telemetry buffer to a zero-sized unit struct.
#[cfg_attr(feature = "dry-run", make_unit)]
struct Telemetry {
    events: Vec<Event>,
}
```

[`cfg_attr`]: https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute

## Highlights

- `#[make_noop]` applies to a free function, a single method, or an entire
  `impl` block (every method becomes a no-op).
- Value-returning functions return `Default::default()` by default; override the
  returned value with `#[noop_returns(EXPR)]`.
- `#[noop_returns(EXPR)]` works standalone on a function/method, **or** on a
  whole `impl` block — where it sets a shared return value for every method,
  except those carrying their own `#[noop_returns(OTHER)]`.
- `#[make_unit]` strips a struct's fields, leaving a unit struct.
- Functions with no return value get an empty body and never return a value.
- The original body is discarded — it is not type-checked or executed. Imports
  or items referenced *only* from a no-op'd body may therefore become unused.

## Installation

```sh
cargo add make-noop
```

## Usage

### Free functions

```rust
use make_noop::{make_noop, noop_returns};

#[make_noop]
fn does_nothing() {
    panic!("skipped");
}

#[make_noop]
fn returns_default() -> Vec<u8> {
    unreachable!() // returns Vec::new()
}

#[noop_returns(String::from("hi"))]
fn greeting() -> String {
    unreachable!() // returns "hi"
}
```

### Impl blocks

`#[make_noop]` on an `impl` block makes every method a no-op. Individual methods
can opt into a custom return value with `#[noop_returns(EXPR)]`:

```rust
use make_noop::{make_noop, noop_returns};

struct Service;

#[make_noop]
impl Service {
    fn code(&self) -> i32 {
        unreachable!() // returns 0 (Default)
    }

    #[noop_returns(String::from("hi"))]
    fn greeting(&self) -> String {
        unreachable!() // returns "hi"
    }
}
```

`#[noop_returns(EXPR)]` can also be applied to the `impl` block itself to set a
shared default for all methods, still overridable per method:

```rust
use make_noop::noop_returns;

struct Codes;

#[noop_returns(3)]
impl Codes {
    fn first(&self) -> i32 {
        unreachable!() // returns 3
    }

    #[noop_returns(42)]
    fn second(&self) -> i32 {
        unreachable!() // returns 42
    }
}
```

### Unit structs

`#[make_unit]` discards a struct's fields, leaving a unit struct. It works on
structs with named fields and on tuple structs; attributes, visibility, and
generics are preserved:

```rust
use make_noop::make_unit;

#[make_unit]
#[derive(Debug, Default)]
pub struct Config {
    verbose: bool,
    retries: u32,
}
// Expands to `pub struct Config;` (still `#[derive(Debug, Default)]`)
```

## Notes

- A function that returns a value must have a return type implementing
  [`Default`] unless you supply `#[noop_returns(EXPR)]`.
- The original body is discarded outright: it is neither type-checked nor
  executed. Anything referenced *only* from inside a no-op'd body (for example an
  import) may consequently be reported as unused.

## Minimum supported Rust version

`make-noop` requires **Rust 1.87** or newer. The MSRV is verified in CI and may
be raised in a minor version bump.

## License

Licensed under either of

- Apache License, Version 2.0 ([LICENSE-APACHE]LICENSE-APACHE or
  <http://www.apache.org/licenses/LICENSE-2.0>)
- MIT license ([LICENSE-MIT]LICENSE-MIT or
  <http://opensource.org/licenses/MIT>)

at your option.

### Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.