]>
Commit | Line | Data |
---|---|---|
1 | //! Render utilities which don't belong anywhere else. | |
2 | use std::fmt::{Display, Formatter, Result}; | |
3 | ||
4 | pub fn as_display<F: Fn(&mut Formatter<'_>) -> Result>(f: F) -> impl Display { | |
5 | struct ClosureDisplay<F: Fn(&mut Formatter<'_>) -> Result>(F); | |
6 | ||
7 | impl<F: Fn(&mut Formatter<'_>) -> Result> Display for ClosureDisplay<F> { | |
8 | fn fmt(&self, f: &mut Formatter<'_>) -> Result { | |
9 | self.0(f) | |
10 | } | |
11 | } | |
12 | ||
13 | ClosureDisplay(f) | |
14 | } | |
15 | ||
16 | macro_rules! write_joined_non_empty_list { | |
17 | ($f:expr,$template:tt,$list:expr,$sep:expr) => {{ | |
18 | let mut x = $list.into_iter().peekable(); | |
19 | if x.peek().is_some() { | |
20 | write!($f, $template, x.format($sep)) | |
21 | } else { | |
22 | Ok(()) | |
23 | } | |
24 | }}; | |
25 | } | |
26 | ||
27 | /// Processes a name given by an [`Interner`][chalk_ir::interner::Interner] debug | |
28 | /// method into something usable by the `display` module. | |
29 | /// | |
30 | /// This is specifically useful when implementing | |
31 | /// [`RustIrDatabase`][crate::RustIrDatabase] `name_*` methods. | |
32 | pub fn sanitize_debug_name(func: impl Fn(&mut Formatter<'_>) -> Option<Result>) -> String { | |
33 | use std::fmt::Write; | |
34 | ||
35 | // First, write the debug method contents to a String. | |
36 | let mut debug_out = String::new(); | |
37 | // ignore if the result is `None`, as we can just as easily tell by looking | |
38 | // to see if anything was written to `debug_out`. | |
39 | write!( | |
40 | debug_out, | |
41 | "{}", | |
42 | as_display(|fmt| { func(fmt).unwrap_or(Ok(())) }) | |
43 | ) | |
44 | .expect("expected writing to a String to succeed"); | |
45 | if debug_out.is_empty() { | |
46 | return "Unknown".to_owned(); | |
47 | } | |
48 | ||
49 | // now the actual sanitization | |
50 | debug_out.replace(|c: char| !c.is_ascii_alphanumeric(), "_") | |
51 | } |