1use std::sync::atomic::{AtomicPtr, Ordering};
4
5use rustc_driver::Callbacks;
6use rustc_interface::interface::Config;
7use rustc_lint_defs::RegisteredTools;
8use rustc_middle::ty::TyCtxt;
9use rustc_session::utils::was_invoked_from_cargo;
10use rustc_span::{Ident, Symbol};
11
12static ORIGINAL_REGISTERED_TOOLS: AtomicPtr<()> = {
18 fn default(_: TyCtxt<'_>, _: ()) -> RegisteredTools {
19 unreachable!("This function will be overwritten when `BevyLintCallback::config()` is run.");
20 }
21
22 AtomicPtr::new(default as *mut ())
23};
24
25pub struct BevyLintCallback;
27
28impl Callbacks for BevyLintCallback {
29 fn config(&mut self, config: &mut Config) {
30 crate::config::load_config(config);
31
32 config.crate_cfg.push("bevy_lint".to_string());
34
35 let previous = config.register_lints.take();
38
39 config.register_lints = Some(Box::new(move |session, store| {
40 if let Some(previous) = &previous {
42 (previous)(session, store);
43 }
44
45 crate::lints::register_lints(store);
46 crate::lints::register_passes(store);
47 crate::lints::register_groups(store);
48 }));
49
50 config.override_queries = Some(|_session, providers| {
51 ORIGINAL_REGISTERED_TOOLS.store(
53 providers.queries.registered_tools as *mut (),
54 Ordering::Relaxed,
55 );
56
57 providers.queries.registered_tools = registered_tools;
59 });
60
61 let input = config.input.clone();
63
64 config.psess_created = Some(Box::new(move |psess| {
65 if !was_invoked_from_cargo() {
66 return;
67 }
68
69 let file_depinfo = psess.file_depinfo.get_mut();
70
71 for workspace in [false, true] {
72 let manifest_path = crate::utils::cargo::locate_manifest(&input, workspace);
74
75 if let Ok(path) = manifest_path
78 && let Some(path) = path.to_str()
79 {
80 file_depinfo.insert(Symbol::intern(path));
83 }
84 }
85 }));
86 }
87}
88
89fn registered_tools<'tcx>(tcx: TyCtxt<'tcx>, _: ()) -> RegisteredTools {
92 let original: fn(TyCtxt<'tcx>, ()) -> RegisteredTools =
97 unsafe { std::mem::transmute(ORIGINAL_REGISTERED_TOOLS.load(Ordering::Relaxed)) };
98
99 let mut tools = (original)(tcx, ());
100
101 tools.insert(Ident::from_str("bevy"));
102
103 tools
104}