]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_passes/src/debugger_visualizer.rs
bump version to 1.75.0+dfsg1-1~bpo12+pve1
[rustc.git] / compiler / rustc_passes / src / debugger_visualizer.rs
1 //! Detecting usage of the `#[debugger_visualizer]` attribute.
2
3 use rustc_ast::Attribute;
4 use rustc_data_structures::sync::Lrc;
5 use rustc_expand::base::resolve_path;
6 use rustc_middle::{
7 middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType},
8 query::{LocalCrate, Providers},
9 ty::TyCtxt,
10 };
11 use rustc_session::Session;
12 use rustc_span::sym;
13
14 use crate::errors::{DebugVisualizerInvalid, DebugVisualizerUnreadable};
15
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 });
21 return;
22 };
23
24 let hint = if hints.len() == 1 {
25 &hints[0]
26 } else {
27 self.sess.emit_err(DebugVisualizerInvalid { span: attr.span });
28 return;
29 };
30
31 let Some(meta_item) = hint.meta_item() else {
32 self.sess.emit_err(DebugVisualizerInvalid { span: attr.span });
33 return;
34 };
35
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)
41 }
42 (_, _) => {
43 self.sess.emit_err(DebugVisualizerInvalid { span: meta_item.span });
44 return;
45 }
46 };
47
48 let file =
49 match resolve_path(&self.sess.parse_sess, visualizer_path.as_str(), attr.span) {
50 Ok(file) => file,
51 Err(mut err) => {
52 err.emit();
53 return;
54 }
55 };
56
57 match std::fs::read(&file) {
58 Ok(contents) => {
59 self.visualizers.push(DebuggerVisualizerFile::new(
60 Lrc::from(contents),
61 visualizer_type,
62 file,
63 ));
64 }
65 Err(error) => {
66 self.sess.emit_err(DebugVisualizerUnreadable {
67 span: meta_item.span,
68 file: &file,
69 error,
70 });
71 }
72 }
73 }
74 }
75 }
76
77 struct DebuggerVisualizerCollector<'a> {
78 sess: &'a Session,
79 visualizers: Vec<DebuggerVisualizerFile>,
80 }
81
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);
86 }
87 }
88
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;
93
94 let mut visitor = DebuggerVisualizerCollector { sess: tcx.sess, visualizers: Vec::new() };
95 rustc_ast::visit::Visitor::visit_crate(&mut visitor, krate);
96
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
100 visitor.visualizers
101 }
102
103 pub fn provide(providers: &mut Providers) {
104 providers.debugger_visualizers = debugger_visualizers;
105 }