1 //! Detecting usage of the `#[debugger_visualizer]` attribute.
3 use rustc_ast
::Attribute
;
4 use rustc_data_structures
::sync
::Lrc
;
5 use rustc_expand
::base
::resolve_path
;
7 middle
::debugger_visualizer
::{DebuggerVisualizerFile, DebuggerVisualizerType}
,
8 query
::{LocalCrate, Providers}
,
11 use rustc_session
::Session
;
14 use crate::errors
::{DebugVisualizerInvalid, DebugVisualizerUnreadable}
;
16 impl DebuggerVisualizerCollector
<'_
> {
17 fn check_for_debugger_visualizer(&mut self, attr
: &Attribute
) {
18 if attr
.has_name(sym
::debugger_visualizer
) {
19 let Some(hints
) = attr
.meta_item_list() else {
20 self.sess
.emit_err(DebugVisualizerInvalid { span: attr.span }
);
24 let hint
= if hints
.len() == 1 {
27 self.sess
.emit_err(DebugVisualizerInvalid { span: attr.span }
);
31 let Some(meta_item
) = hint
.meta_item() else {
32 self.sess
.emit_err(DebugVisualizerInvalid { span: attr.span }
);
36 let (visualizer_type
, visualizer_path
) =
37 match (meta_item
.name_or_empty(), meta_item
.value_str()) {
38 (sym
::natvis_file
, Some(value
)) => (DebuggerVisualizerType
::Natvis
, value
),
39 (sym
::gdb_script_file
, Some(value
)) => {
40 (DebuggerVisualizerType
::GdbPrettyPrinter
, value
)
43 self.sess
.emit_err(DebugVisualizerInvalid { span: meta_item.span }
);
49 match resolve_path(&self.sess
.parse_sess
, visualizer_path
.as_str(), attr
.span
) {
57 match std
::fs
::read(&file
) {
59 self.visualizers
.push(DebuggerVisualizerFile
::new(
66 self.sess
.emit_err(DebugVisualizerUnreadable
{
77 struct DebuggerVisualizerCollector
<'a
> {
79 visualizers
: Vec
<DebuggerVisualizerFile
>,
82 impl<'ast
> rustc_ast
::visit
::Visitor
<'ast
> for DebuggerVisualizerCollector
<'_
> {
83 fn visit_attribute(&mut self, attr
: &'ast Attribute
) {
84 self.check_for_debugger_visualizer(attr
);
85 rustc_ast
::visit
::walk_attribute(self, attr
);
89 /// Traverses and collects the debugger visualizers for a specific crate.
90 fn debugger_visualizers(tcx
: TyCtxt
<'_
>, _
: LocalCrate
) -> Vec
<DebuggerVisualizerFile
> {
91 let resolver_and_krate
= tcx
.resolver_for_lowering(()).borrow();
92 let krate
= &*resolver_and_krate
.1;
94 let mut visitor
= DebuggerVisualizerCollector { sess: tcx.sess, visualizers: Vec::new() }
;
95 rustc_ast
::visit
::Visitor
::visit_crate(&mut visitor
, krate
);
97 // We are collecting visualizers in AST-order, which is deterministic,
98 // so we don't need to do any explicit sorting in order to get a
99 // deterministic query result
103 pub fn provide(providers
: &mut Providers
) {
104 providers
.debugger_visualizers
= debugger_visualizers
;