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(
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: TyCtxt<'_>, 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;