8 releases

0.1.7 Mar 23, 2023
0.1.6 Feb 27, 2023
0.1.4 Oct 11, 2022
0.1.3 Aug 21, 2022
0.1.0 Dec 31, 2021

#111 in Procedural macros

MIT/Apache

27KB
631 lines

rustfmt_if_chain

A wrapper around rustfmt to format inside if_chain invocations

rustfmt_if_chain is not guaranteed to work on all Rust source files, but it should work on most of Clippy's source files.

cargo install rustfmt_if_chain
Usage: rustfmt_if_chain [ARGS]

Arguments ending with `.rs` are considered source files and are
formatted. All other arguments are forwarded to `rustfmt`, with
one exception.

The one argument not forwarded to `rustfmt` is
`--preformat-failure-is-warning`. If this option is passed and
`rustfmt` fails on an unmodified source file, a warning results
instead of an error.

Example

  • Before

    fn main() -> PhilosophicalResult<()> {
        if_chain! { if let Some (it) = tree . falls_in (forest) ; if ! listeners . any (| one | one . around_to_hear (it)) ; if ! it . makes_a_sound () ; then { return Err (PhilosophicalError :: new ()) ; } }
        Ok(())
    }
    
  • After

    fn main() -> PhilosophicalResult<()> {
        if_chain! {
            if let Some(it) = tree.falls_in(forest);
            if !listeners.any(|one| one.around_to_hear(it));
            if !it.makes_a_sound();
            then {
                return Err(PhilosophicalError::new());
            }
        }
        Ok(())
    }
    

How it works

  1. Preformat check: rustfmt is run on the original source file to verify that it can be formatted.*
  2. The if_chain invocations in the original source file are rewritten according to the following rules, where x is an identifier that does not appear elsewhere in the file:
    • if_chain! -> fn x() or |x| (depending on whether the invocation is an item or expression)
    • if ... ; -> if ... { x; }
    • then -> if x
  3. rustfmt is run on the file resulting from step 1.
  4. In the file resulting from step 2, the rewrites of step 1 are undone.

* Step 0 is not strictly necessary, but it helps to identify failures of step 2 caused by the limitations of step 1.

Known problems

  • rustfmt_if_chain --check FILENAME does not work correctly. A workaround is to use rustfmt_if_chain FILENAME && git diff --exit-code.
  • Nested uses of if_chain are not handled correctly: only the outer-most use is formatted.

Dependencies

~4–14MB
~186K SLoC