xtask/tasks/fmt/lints/
cfg_target_arch.rs1use super::Lint;
8use super::LintCtx;
9use super::Lintable;
10use std::path::Path;
11use toml_edit::DocumentMut;
12
13const SUPPRESS: &str = "xtask-fmt allow-target-arch";
14
15const SUPPRESS_REASON_CPU_INTRINSIC: &str = "cpu-intrinsic";
17const SUPPRESS_REASON_SYS_CRATE: &str = "sys-crate";
20const SUPPRESS_REASON_DEPENDENCY: &str = "dependency";
22const SUPPRESS_REASON_ONEOFF_GUEST_ARCH_IMPL: &str = "oneoff-guest-arch-impl";
25const SUPPRESS_REASON_ONEOFF_FLOWEY: &str = "oneoff-flowey";
27const SUPPRESS_REASON_ONEOFF_PETRI_NATIVE_TEST_DEPS: &str = "oneoff-petri-native-test-deps";
29const SUPPRESS_REASON_ONEOFF_PETRI_HOST_ARCH: &str = "oneoff-petri-host-arch";
31
32fn has_suppress(s: &str) -> bool {
33 let Some((_, after)) = s.split_once(SUPPRESS) else {
34 return false;
35 };
36
37 let after = after.trim();
38 let justification = after.split(' ').next().unwrap();
39
40 matches!(
41 justification,
42 SUPPRESS_REASON_CPU_INTRINSIC
43 | SUPPRESS_REASON_SYS_CRATE
44 | SUPPRESS_REASON_DEPENDENCY
45 | SUPPRESS_REASON_ONEOFF_GUEST_ARCH_IMPL
46 | SUPPRESS_REASON_ONEOFF_FLOWEY
47 | SUPPRESS_REASON_ONEOFF_PETRI_NATIVE_TEST_DEPS
48 | SUPPRESS_REASON_ONEOFF_PETRI_HOST_ARCH
49 )
50}
51
52fn is_exempt(path: &Path) -> bool {
54 path.starts_with("guest_test_uefi")
70 || path.starts_with("openhcl/openhcl_boot")
71 || path.starts_with("openhcl/minimal_rt")
72 || path.starts_with("openhcl/minimal_rt_reloc")
73 || path.starts_with("openhcl/sidecar")
74 || path.starts_with("support")
75 || path.starts_with("tmk/simple_tmk")
76 || path.starts_with("tmk/tmk_core")
77 || path.starts_with("vm/whp")
78 || path.starts_with("vm/kvm")
79}
80
81pub struct CfgTargetArch;
82
83impl Lint for CfgTargetArch {
84 fn new(_ctx: &LintCtx) -> Self {
85 CfgTargetArch
86 }
87
88 fn enter_workspace(&mut self, _content: &Lintable<DocumentMut>) {}
89 fn enter_crate(&mut self, _content: &Lintable<DocumentMut>) {}
90
91 fn visit_file(&mut self, content: &mut Lintable<String>) {
92 let path = content.path();
93
94 if path.ends_with(file!()) || is_exempt(path) {
96 return;
97 }
98
99 let mut prev_line = "";
100 for (i, line) in content.lines().enumerate() {
101 if line.contains("target_arch =") || line.contains("CARGO_CFG_TARGET_ARCH") {
102 if !line.trim().starts_with("//") && !has_suppress(line) && !has_suppress(prev_line)
104 {
105 content.unfixable(&format!(
106 "unjustified `cfg(target_arch = ...)` at line {}",
107 i + 1
108 ));
109 }
110 }
111 prev_line = line;
112 }
113 }
114
115 fn exit_crate(&mut self, _content: &mut Lintable<DocumentMut>) {}
116 fn exit_workspace(&mut self, _content: &mut Lintable<DocumentMut>) {}
117}