Skip to main content

xtask/tasks/fmt/lints/
unsafe_code_comment.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Checks that uses of `expect(unsafe_code)` or `allow(unsafe_code)` are
5//! preceded by an `// UNSAFETY: ` comment explaining the justification.
6
7use super::Lint;
8use super::LintCtx;
9use super::Lintable;
10use toml_edit::DocumentMut;
11
12pub struct UnsafeCodeComment;
13
14impl Lint for UnsafeCodeComment {
15    fn new(_ctx: &LintCtx) -> Self {
16        UnsafeCodeComment
17    }
18
19    fn enter_workspace(&mut self, _content: &Lintable<DocumentMut>) {}
20    fn enter_crate(&mut self, _content: &Lintable<DocumentMut>) {}
21
22    fn visit_file(&mut self, content: &mut Lintable<String>) {
23        // Exclude ourselves from the lint (we mention the patterns in strings).
24        if content.path().ends_with(file!()) {
25            return;
26        }
27
28        let mut in_comment = false;
29        for (i, line) in content.lines().enumerate() {
30            let line = line.trim();
31            if line.starts_with("// UNSAFETY: ") {
32                in_comment = true;
33                continue;
34            }
35
36            if (line.contains("expect(unsafe_code)") || line.contains("allow(unsafe_code)"))
37                && !in_comment
38            {
39                content.unfixable(&format!(
40                    "unjustified `expect(unsafe_code)` at line {}",
41                    i + 1
42                ));
43            }
44
45            if !line.starts_with("//") || (line.len() > 2 && line.as_bytes()[2] != b' ') {
46                in_comment = false;
47            }
48        }
49    }
50
51    fn exit_crate(&mut self, _content: &mut Lintable<DocumentMut>) {}
52    fn exit_workspace(&mut self, _content: &mut Lintable<DocumentMut>) {}
53}