]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_passes/src/debugger_visualizer.rs
Auto merge of #107574 - compiler-errors:back-to-old-mac-builders-pls, r=pietroalbini
[rust.git] / compiler / rustc_passes / src / debugger_visualizer.rs
1 //! Detecting usage of the `#[debugger_visualizer]` attribute.
2
3 use hir::CRATE_HIR_ID;
4 use rustc_data_structures::fx::FxHashSet;
5 use rustc_expand::base::resolve_path;
6 use rustc_hir as hir;
7 use rustc_hir::def_id::CrateNum;
8 use rustc_hir::HirId;
9 use rustc_middle::ty::query::Providers;
10 use rustc_middle::ty::TyCtxt;
11 use rustc_span::def_id::LOCAL_CRATE;
12 use rustc_span::{sym, DebuggerVisualizerFile, DebuggerVisualizerType};
13
14 use std::sync::Arc;
15
16 use crate::errors::DebugVisualizerUnreadable;
17
18 fn check_for_debugger_visualizer(
19     tcx: TyCtxt<'_>,
20     hir_id: HirId,
21     debugger_visualizers: &mut FxHashSet<DebuggerVisualizerFile>,
22 ) {
23     let attrs = tcx.hir().attrs(hir_id);
24     for attr in attrs {
25         if attr.has_name(sym::debugger_visualizer) {
26             let Some(list) = attr.meta_item_list() else {
27                 continue
28             };
29
30             let meta_item = match list.len() {
31                 1 => match list[0].meta_item() {
32                     Some(meta_item) => meta_item,
33                     _ => continue,
34                 },
35                 _ => continue,
36             };
37
38             let visualizer_type = match meta_item.name_or_empty() {
39                 sym::natvis_file => DebuggerVisualizerType::Natvis,
40                 sym::gdb_script_file => DebuggerVisualizerType::GdbPrettyPrinter,
41                 _ => continue,
42             };
43
44             let file = match meta_item.value_str() {
45                 Some(value) => {
46                     match resolve_path(&tcx.sess.parse_sess, value.as_str(), attr.span) {
47                         Ok(file) => file,
48                         _ => continue,
49                     }
50                 }
51                 None => continue,
52             };
53
54             match std::fs::read(&file) {
55                 Ok(contents) => {
56                     debugger_visualizers
57                         .insert(DebuggerVisualizerFile::new(Arc::from(contents), visualizer_type));
58                 }
59                 Err(error) => {
60                     tcx.sess.emit_err(DebugVisualizerUnreadable {
61                         span: meta_item.span,
62                         file: &file,
63                         error,
64                     });
65                 }
66             }
67         }
68     }
69 }
70
71 /// Traverses and collects the debugger visualizers for a specific crate.
72 fn debugger_visualizers(tcx: TyCtxt<'_>, cnum: CrateNum) -> Vec<DebuggerVisualizerFile> {
73     assert_eq!(cnum, LOCAL_CRATE);
74
75     // Initialize the collector.
76     let mut debugger_visualizers = FxHashSet::default();
77
78     // Collect debugger visualizers in this crate.
79     tcx.hir().for_each_module(|id| {
80         check_for_debugger_visualizer(
81             tcx,
82             tcx.hir().local_def_id_to_hir_id(id),
83             &mut debugger_visualizers,
84         )
85     });
86
87     // Collect debugger visualizers on the crate attributes.
88     check_for_debugger_visualizer(tcx, CRATE_HIR_ID, &mut debugger_visualizers);
89
90     // Extract out the found debugger_visualizer items.
91     let mut visualizers = debugger_visualizers.into_iter().collect::<Vec<_>>();
92
93     // Sort the visualizers so we always get a deterministic query result.
94     visualizers.sort();
95     visualizers
96 }
97
98 pub fn provide(providers: &mut Providers) {
99     providers.debugger_visualizers = debugger_visualizers;
100 }