Skip to main content

backhopper_xref/
display.rs

1// Copyright (C) 2026 Michael S. Klishin and Contributors
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// See LICENSE-APACHE and LICENSE-MIT for details.
4
5//! Human-readable formatting for the typed result structs in `result`.
6//!
7//! Kept separate from `result.rs` so the library data types stay free of
8//! presentation concerns. Consumers who need machine output use
9//! `serde::Serialize`; consumers who want text use these `Display` impls.
10
11use std::fmt;
12
13use crate::result::{
14    AppDependencies, CalleesOf, CallersOf, DeprecatedFunctionCalls, ExportsNotUsed, LocalsNotUsed,
15    ModuleCallers, ModuleDependencies, NonConformance, UndefinedFunctionCalls, UnresolvedCalls,
16};
17
18impl fmt::Display for UndefinedFunctionCalls {
19    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20        for e in &self.entries {
21            writeln!(f, "{} calls undefined {}", e.caller, e.callee)?;
22        }
23        Ok(())
24    }
25}
26
27impl fmt::Display for LocalsNotUsed {
28    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29        for e in &self.entries {
30            writeln!(f, "unused local: {}", e.mfa)?;
31        }
32        Ok(())
33    }
34}
35
36impl fmt::Display for ExportsNotUsed {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        for e in &self.entries {
39            let suffix = if e.satisfies_callback {
40                " (callback)"
41            } else if e.is_on_load {
42                " (on_load)"
43            } else {
44                ""
45            };
46            writeln!(f, "unused export: {}{}", e.mfa, suffix)?;
47        }
48        Ok(())
49    }
50}
51
52impl fmt::Display for DeprecatedFunctionCalls {
53    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54        for e in &self.entries {
55            writeln!(f, "{} calls deprecated {} ({})", e.caller, e.callee, e.tier)?;
56        }
57        Ok(())
58    }
59}
60
61impl fmt::Display for CallersOf {
62    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63        writeln!(f, "callers of {}:", self.target)?;
64        for c in &self.entries {
65            writeln!(f, "  {}", c.caller)?;
66        }
67        Ok(())
68    }
69}
70
71impl fmt::Display for CalleesOf {
72    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73        writeln!(f, "callees of {}:", self.source)?;
74        for c in &self.entries {
75            writeln!(f, "  {}", c.callee)?;
76        }
77        Ok(())
78    }
79}
80
81impl fmt::Display for ModuleCallers {
82    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83        writeln!(f, "callers of {}:", self.target)?;
84        for m in &self.entries {
85            writeln!(f, "  {m}")?;
86        }
87        Ok(())
88    }
89}
90
91impl fmt::Display for ModuleDependencies {
92    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93        writeln!(f, "{} uses:", self.source)?;
94        for m in &self.entries {
95            writeln!(f, "  {m}")?;
96        }
97        Ok(())
98    }
99}
100
101impl fmt::Display for AppDependencies {
102    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103        writeln!(f, "{} reaches:", self.source)?;
104        for a in &self.entries {
105            writeln!(f, "  {a}")?;
106        }
107        Ok(())
108    }
109}
110
111impl fmt::Display for NonConformance {
112    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113        writeln!(
114            f,
115            "{} declares behaviour {} but is missing:",
116            self.implementer, self.behaviour
117        )?;
118        for sig in &self.missing {
119            writeln!(f, "  {sig}")?;
120        }
121        Ok(())
122    }
123}
124
125impl fmt::Display for UnresolvedCalls {
126    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127        for e in &self.entries {
128            writeln!(f, "{} -> {}", e.caller, e.partial)?;
129        }
130        Ok(())
131    }
132}