rulewright 0.1.1

Executable engineering standards for Rust workspaces
Documentation
use ra_ap_syntax::ast;

use crate::{AstCtx, Example, Violation};

#[rustfmt::skip]
const EXAMPLES: &[Example] = &[
    Example {
        label: "unwrap in library",
        code: "fn f() { Some(1).unwrap(); }",
        pass: false,
    },
    Example {
        label: "expect passes",
        code: "fn f() { Some(1).expect(\"reason\"); }",
        pass: true,
    },
    Example {
        label: "unwrap in test module",
        code: "#[cfg(test)]\nmod tests {\n    fn t() { Some(1).unwrap(); }\n}",
        pass: true,
    },
];

crate::ast_rule!(
    unwrap_in_lib,
    "Ban `.unwrap()` in library code.",
    "unwrap() in library code panics the caller with no context. Return Result or use expect() with a message.",
    Medium,
);

fn check_unwrap_in_lib(ctx: &AstCtx<'_>) -> Vec<Violation> {
    ctx.nodes::<ast::MethodCallExpr>()
        .filter(|call| !ctx.is_in_test(call))
        .filter_map(|call| {
            let method = call.name_ref()?;

            (method.text() == "unwrap").then(|| {
                ctx.violation(
                    &method,
                    ".unwrap() in library code (use .expect(\"reason\") or propagate with ?)",
                )
            })
        })
        .collect()
}

crate::rulewright_ast_test!(check_unwrap_in_lib, {
    crate::example_tests!(EXAMPLES, check_unwrap_in_lib);
});