1 //! Detecting usage of the `#[debugger_visualizer]` attribute.
4 use rustc_data_structures
::fx
::FxHashSet
;
5 use rustc_expand
::base
::resolve_path
;
7 use rustc_hir
::def_id
::CrateNum
;
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}
;
16 use crate::errors
::DebugVisualizerUnreadable
;
18 fn check_for_debugger_visualizer
<'tcx
>(
21 debugger_visualizers
: &mut FxHashSet
<DebuggerVisualizerFile
>,
23 let attrs
= tcx
.hir().attrs(hir_id
);
25 if attr
.has_name(sym
::debugger_visualizer
) {
26 let Some(list
) = attr
.meta_item_list() else {
30 let meta_item
= match list
.len() {
31 1 => match list
[0].meta_item() {
32 Some(meta_item
) => meta_item
,
38 let visualizer_type
= match meta_item
.name_or_empty() {
39 sym
::natvis_file
=> DebuggerVisualizerType
::Natvis
,
40 sym
::gdb_script_file
=> DebuggerVisualizerType
::GdbPrettyPrinter
,
44 let file
= match meta_item
.value_str() {
46 match resolve_path(&tcx
.sess
.parse_sess
, value
.as_str(), attr
.span
) {
54 match std
::fs
::read(&file
) {
57 .insert(DebuggerVisualizerFile
::new(Arc
::from(contents
), visualizer_type
));
60 tcx
.sess
.emit_err(DebugVisualizerUnreadable
{
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
);
75 // Initialize the collector.
76 let mut debugger_visualizers
= FxHashSet
::default();
78 // Collect debugger visualizers in this crate.
79 tcx
.hir().for_each_module(|id
| {
80 check_for_debugger_visualizer(
82 tcx
.hir().local_def_id_to_hir_id(id
),
83 &mut debugger_visualizers
,
87 // Collect debugger visualizers on the crate attributes.
88 check_for_debugger_visualizer(tcx
, CRATE_HIR_ID
, &mut debugger_visualizers
);
90 // Extract out the found debugger_visualizer items.
91 let mut visualizers
= debugger_visualizers
.into_iter().collect
::<Vec
<_
>>();
93 // Sort the visualizers so we always get a deterministic query result.
98 pub fn provide(providers
: &mut Providers
) {
99 providers
.debugger_visualizers
= debugger_visualizers
;