]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_passes/src/debugger_visualizer.rs
New upstream version 1.66.0+dfsg1
[rustc.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<'tcx>(
19 tcx: TyCtxt<'tcx>,
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>(tcx: TyCtxt<'tcx>, 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 }