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