rustc_hir/attrs/
pretty_printing.rs1use std::num::NonZero;
2
3use rustc_abi::Align;
4use rustc_ast::token::CommentKind;
5use rustc_ast::{AttrStyle, IntTy, UintTy};
6use rustc_ast_pretty::pp::Printer;
7use rustc_span::hygiene::Transparency;
8use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
9use thin_vec::ThinVec;
10
11pub trait PrintAttribute {
18 fn should_render(&self) -> bool;
22
23 fn print_attribute(&self, p: &mut Printer);
24}
25
26impl PrintAttribute for u128 {
27 fn should_render(&self) -> bool {
28 true
29 }
30
31 fn print_attribute(&self, p: &mut Printer) {
32 p.word(self.to_string())
33 }
34}
35
36impl<T: PrintAttribute> PrintAttribute for &T {
37 fn should_render(&self) -> bool {
38 T::should_render(self)
39 }
40
41 fn print_attribute(&self, p: &mut Printer) {
42 T::print_attribute(self, p)
43 }
44}
45impl<T: PrintAttribute> PrintAttribute for Option<T> {
46 fn should_render(&self) -> bool {
47 self.as_ref().is_some_and(|x| x.should_render())
48 }
49
50 fn print_attribute(&self, p: &mut Printer) {
51 if let Some(i) = self {
52 T::print_attribute(i, p)
53 }
54 }
55}
56impl<T: PrintAttribute> PrintAttribute for ThinVec<T> {
57 fn should_render(&self) -> bool {
58 self.is_empty() || self[0].should_render()
59 }
60
61 fn print_attribute(&self, p: &mut Printer) {
62 let mut last_printed = false;
63 p.word("[");
64 for i in self {
65 if last_printed {
66 p.word_space(",");
67 }
68 i.print_attribute(p);
69 last_printed = i.should_render();
70 }
71 p.word("]");
72 }
73}
74macro_rules! print_skip {
75 ($($t: ty),* $(,)?) => {$(
76 impl PrintAttribute for $t {
77 fn should_render(&self) -> bool { false }
78 fn print_attribute(&self, _: &mut Printer) { }
79 })*
80 };
81}
82
83macro_rules! print_disp {
84 ($($t: ty),* $(,)?) => {$(
85 impl PrintAttribute for $t {
86 fn should_render(&self) -> bool { true }
87 fn print_attribute(&self, p: &mut Printer) {
88 p.word(format!("{}", self));
89 }
90 }
91 )*};
92}
93macro_rules! print_debug {
94 ($($t: ty),* $(,)?) => {$(
95 impl PrintAttribute for $t {
96 fn should_render(&self) -> bool { true }
97 fn print_attribute(&self, p: &mut Printer) {
98 p.word(format!("{:?}", self));
99 }
100 }
101 )*};
102}
103
104macro_rules! print_tup {
105 (num_should_render $($ts: ident)*) => { 0 $(+ $ts.should_render() as usize)* };
106 () => {};
107 ($t: ident $($ts: ident)*) => {
108 #[allow(non_snake_case, unused)]
109 impl<$t: PrintAttribute, $($ts: PrintAttribute),*> PrintAttribute for ($t, $($ts),*) {
110 fn should_render(&self) -> bool {
111 let ($t, $($ts),*) = self;
112 print_tup!(num_should_render $t $($ts)*) != 0
113 }
114
115 fn print_attribute(&self, p: &mut Printer) {
116 let ($t, $($ts),*) = self;
117 let parens = print_tup!(num_should_render $t $($ts)*) > 1;
118 if parens {
119 p.popen();
120 }
121
122 let mut printed_anything = $t.should_render();
123
124 $t.print_attribute(p);
125
126 $(
127 if $ts.should_render() {
128 if printed_anything {
129 p.word_space(",");
130 }
131 printed_anything = true;
132 }
133 $ts.print_attribute(p);
134 )*
135
136 if parens {
137 p.pclose();
138 }
139 }
140 }
141
142 print_tup!($($ts)*);
143 };
144}
145
146print_tup!(A B C D E F G H);
147print_skip!(Span, (), ErrorGuaranteed);
148print_disp!(u16, bool, NonZero<u32>);
149print_debug!(Symbol, Ident, UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);