summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_passes/src/debugger_visualizer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_passes/src/debugger_visualizer.rs')
-rw-r--r--compiler/rustc_passes/src/debugger_visualizer.rs99
1 files changed, 99 insertions, 0 deletions
diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs
new file mode 100644
index 000000000..e08683fe2
--- /dev/null
+++ b/compiler/rustc_passes/src/debugger_visualizer.rs
@@ -0,0 +1,99 @@
+//! Detecting usage of the `#[debugger_visualizer]` attribute.
+
+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;
+
+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(err) => {
+ tcx.sess
+ .struct_span_err(
+ meta_item.span,
+ &format!("couldn't read {}: {}", file.display(), err),
+ )
+ .emit();
+ }
+ }
+ }
+ }
+}
+
+/// Traverses and collects the debugger visualizers for a specific crate.
+fn debugger_visualizers<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> Vec<DebuggerVisualizerFile> {
+ assert_eq!(cnum, LOCAL_CRATE);
+
+ // Initialize the collector.
+ let mut debugger_visualizers = FxHashSet::default();
+
+ // Collect debugger visualizers in this crate.
+ tcx.hir().for_each_module(|id| {
+ check_for_debugger_visualizer(
+ tcx,
+ tcx.hir().local_def_id_to_hir_id(id),
+ &mut debugger_visualizers,
+ )
+ });
+
+ // Collect debugger visualizers on the crate attributes.
+ check_for_debugger_visualizer(tcx, CRATE_HIR_ID, &mut debugger_visualizers);
+
+ // Extract out the found debugger_visualizer items.
+ let mut visualizers = debugger_visualizers.into_iter().collect::<Vec<_>>();
+
+ // Sort the visualizers so we always get a deterministic query result.
+ visualizers.sort();
+ visualizers
+}
+
+pub fn provide(providers: &mut Providers) {
+ providers.debugger_visualizers = debugger_visualizers;
+}