Skip to main content

wowlab_tidy/languages/rust/rules/api/
unwrap_in_lib.rs

1use ra_ap_syntax::ast;
2
3use crate::{AstCtx, Example, Violation};
4
5#[rustfmt::skip]
6const EXAMPLES: &[Example] = &[
7    Example {
8        label: "unwrap in library",
9        code: "fn f() { Some(1).unwrap(); }",
10        pass: false,
11    },
12    Example {
13        label: "expect passes",
14        code: "fn f() { Some(1).expect(\"reason\"); }",
15        pass: true,
16    },
17    Example {
18        label: "unwrap in test module",
19        code: "#[cfg(test)]\nmod tests {\n    fn t() { Some(1).unwrap(); }\n}",
20        pass: true,
21    },
22];
23
24crate::ast_rule!(
25    unwrap_in_lib,
26    "Ban `.unwrap()` in library code.",
27    "unwrap() in library code panics the caller with no context. Return Result or use expect() with a message.",
28    Medium,
29);
30
31fn check_unwrap_in_lib(ctx: &AstCtx<'_>) -> Vec<Violation> {
32    ctx.nodes::<ast::MethodCallExpr>()
33        .filter(|call| !ctx.is_in_test(call))
34        .filter_map(|call| {
35            let method = call.name_ref()?;
36
37            (method.text() == "unwrap").then(|| {
38                ctx.violation(
39                    &method,
40                    ".unwrap() in library code (use .expect(\"reason\") or propagate with ?)",
41                )
42            })
43        })
44        .collect()
45}
46
47crate::tidy_ast_test!(check_unwrap_in_lib, {
48    crate::example_tests!(EXAMPLES, check_unwrap_in_lib);
49});