1use std::fmt;
6use std::marker::PhantomData;
7
8use crate::tokenstream::LazyAttrTokenStream;
9use crate::{
10 Arm, AssocItem, AttrItem, AttrKind, AttrVec, Attribute, Block, Crate, Expr, ExprField,
11 FieldDef, ForeignItem, GenericParam, Item, NodeId, Param, Pat, PatField, Path, Stmt, StmtKind,
12 Ty, Variant, Visibility, WherePredicate,
13};
14
15pub trait HasNodeId {
17 fn node_id(&self) -> NodeId;
18 fn node_id_mut(&mut self) -> &mut NodeId;
19}
20
21macro_rules! impl_has_node_id {
22 ($($T:ty),+ $(,)?) => {
23 $(
24 impl HasNodeId for $T {
25 fn node_id(&self) -> NodeId {
26 self.id
27 }
28 fn node_id_mut(&mut self) -> &mut NodeId {
29 &mut self.id
30 }
31 }
32 )+
33 };
34}
35
36impl_has_node_id!(
37 Arm,
38 AssocItem,
39 Crate,
40 Expr,
41 ExprField,
42 FieldDef,
43 ForeignItem,
44 GenericParam,
45 Item,
46 Param,
47 Pat,
48 PatField,
49 Stmt,
50 Ty,
51 Variant,
52 WherePredicate,
53);
54
55impl<T: HasNodeId> HasNodeId for Box<T> {
56 fn node_id(&self) -> NodeId {
57 (**self).node_id()
58 }
59 fn node_id_mut(&mut self) -> &mut NodeId {
60 (**self).node_id_mut()
61 }
62}
63
64pub trait HasTokens {
66 fn tokens(&self) -> Option<&LazyAttrTokenStream>;
67 fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>>;
68}
69
70macro_rules! impl_has_tokens {
71 ($($T:ty),+ $(,)?) => {
72 $(
73 impl HasTokens for $T {
74 fn tokens(&self) -> Option<&LazyAttrTokenStream> {
75 self.tokens.as_ref()
76 }
77 fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
78 Some(&mut self.tokens)
79 }
80 }
81 )+
82 };
83}
84
85macro_rules! impl_has_tokens_none {
86 ($($T:ty),+ $(,)?) => {
87 $(
88 impl HasTokens for $T {
89 fn tokens(&self) -> Option<&LazyAttrTokenStream> {
90 None
91 }
92 fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
93 None
94 }
95 }
96 )+
97 };
98}
99
100impl_has_tokens!(AssocItem, AttrItem, Block, Expr, ForeignItem, Item, Pat, Path, Ty, Visibility);
101impl_has_tokens_none!(
102 Arm,
103 ExprField,
104 FieldDef,
105 GenericParam,
106 Param,
107 PatField,
108 Variant,
109 WherePredicate
110);
111
112impl<T: HasTokens> HasTokens for Option<T> {
113 fn tokens(&self) -> Option<&LazyAttrTokenStream> {
114 self.as_ref().and_then(|inner| inner.tokens())
115 }
116 fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
117 self.as_mut().and_then(|inner| inner.tokens_mut())
118 }
119}
120
121impl<T: HasTokens> HasTokens for Box<T> {
122 fn tokens(&self) -> Option<&LazyAttrTokenStream> {
123 (**self).tokens()
124 }
125 fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
126 (**self).tokens_mut()
127 }
128}
129
130impl HasTokens for StmtKind {
131 fn tokens(&self) -> Option<&LazyAttrTokenStream> {
132 match self {
133 StmtKind::Let(local) => local.tokens.as_ref(),
134 StmtKind::Item(item) => item.tokens(),
135 StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.tokens(),
136 StmtKind::Empty => None,
137 StmtKind::MacCall(mac) => mac.tokens.as_ref(),
138 }
139 }
140 fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
141 match self {
142 StmtKind::Let(local) => Some(&mut local.tokens),
143 StmtKind::Item(item) => item.tokens_mut(),
144 StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.tokens_mut(),
145 StmtKind::Empty => None,
146 StmtKind::MacCall(mac) => Some(&mut mac.tokens),
147 }
148 }
149}
150
151impl HasTokens for Stmt {
152 fn tokens(&self) -> Option<&LazyAttrTokenStream> {
153 self.kind.tokens()
154 }
155 fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
156 self.kind.tokens_mut()
157 }
158}
159
160impl HasTokens for Attribute {
161 fn tokens(&self) -> Option<&LazyAttrTokenStream> {
162 match &self.kind {
163 AttrKind::Normal(normal) => normal.tokens.as_ref(),
164 kind @ AttrKind::DocComment(..) => {
165 panic!("Called tokens on doc comment attr {kind:?}")
166 }
167 }
168 }
169 fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
170 Some(match &mut self.kind {
171 AttrKind::Normal(normal) => &mut normal.tokens,
172 kind @ AttrKind::DocComment(..) => {
173 panic!("Called tokens_mut on doc comment attr {kind:?}")
174 }
175 })
176 }
177}
178
179pub trait HasAttrs {
181 const SUPPORTS_CUSTOM_INNER_ATTRS: bool;
189 fn attrs(&self) -> &[Attribute];
190 fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec));
191}
192
193macro_rules! impl_has_attrs {
194 (const SUPPORTS_CUSTOM_INNER_ATTRS: bool = $inner:literal, $($T:ty),+ $(,)?) => {
195 $(
196 impl HasAttrs for $T {
197 const SUPPORTS_CUSTOM_INNER_ATTRS: bool = $inner;
198
199 #[inline]
200 fn attrs(&self) -> &[Attribute] {
201 &self.attrs
202 }
203
204 fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
205 f(&mut self.attrs)
206 }
207 }
208 )+
209 };
210}
211
212macro_rules! impl_has_attrs_none {
213 ($($T:ty),+ $(,)?) => {
214 $(
215 impl HasAttrs for $T {
216 const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false;
217 fn attrs(&self) -> &[Attribute] {
218 &[]
219 }
220 fn visit_attrs(&mut self, _f: impl FnOnce(&mut AttrVec)) {}
221 }
222 )+
223 };
224}
225
226impl_has_attrs!(
227 const SUPPORTS_CUSTOM_INNER_ATTRS: bool = true,
228 AssocItem,
229 ForeignItem,
230 Item,
231);
232impl_has_attrs!(
233 const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false,
234 Arm,
235 Crate,
236 Expr,
237 ExprField,
238 FieldDef,
239 GenericParam,
240 Param,
241 PatField,
242 Variant,
243 WherePredicate,
244);
245impl_has_attrs_none!(Attribute, AttrItem, Block, Pat, Path, Ty, Visibility);
246
247impl<T: HasAttrs> HasAttrs for Box<T> {
248 const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::SUPPORTS_CUSTOM_INNER_ATTRS;
249 fn attrs(&self) -> &[Attribute] {
250 (**self).attrs()
251 }
252 fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
253 (**self).visit_attrs(f);
254 }
255}
256
257impl<T: HasAttrs> HasAttrs for Option<T> {
258 const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::SUPPORTS_CUSTOM_INNER_ATTRS;
259 fn attrs(&self) -> &[Attribute] {
260 self.as_ref().map(|inner| inner.attrs()).unwrap_or(&[])
261 }
262 fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
263 if let Some(inner) = self.as_mut() {
264 inner.visit_attrs(f);
265 }
266 }
267}
268
269impl HasAttrs for StmtKind {
270 const SUPPORTS_CUSTOM_INNER_ATTRS: bool = true;
273
274 fn attrs(&self) -> &[Attribute] {
275 match self {
276 StmtKind::Let(local) => &local.attrs,
277 StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.attrs(),
278 StmtKind::Item(item) => item.attrs(),
279 StmtKind::Empty => &[],
280 StmtKind::MacCall(mac) => &mac.attrs,
281 }
282 }
283
284 fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
285 match self {
286 StmtKind::Let(local) => f(&mut local.attrs),
287 StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_attrs(f),
288 StmtKind::Item(item) => item.visit_attrs(f),
289 StmtKind::Empty => {}
290 StmtKind::MacCall(mac) => f(&mut mac.attrs),
291 }
292 }
293}
294
295impl HasAttrs for Stmt {
296 const SUPPORTS_CUSTOM_INNER_ATTRS: bool = StmtKind::SUPPORTS_CUSTOM_INNER_ATTRS;
297 fn attrs(&self) -> &[Attribute] {
298 self.kind.attrs()
299 }
300 fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
301 self.kind.visit_attrs(f);
302 }
303}
304
305#[repr(transparent)]
307pub struct AstNodeWrapper<Wrapped, Tag> {
308 pub wrapped: Wrapped,
309 pub tag: PhantomData<Tag>,
310}
311
312impl<Wrapped, Tag> AstNodeWrapper<Wrapped, Tag> {
313 pub fn new(wrapped: Wrapped, _tag: Tag) -> AstNodeWrapper<Wrapped, Tag> {
314 AstNodeWrapper { wrapped, tag: Default::default() }
315 }
316
317 pub fn from_mut(wrapped: &mut Wrapped, _tag: Tag) -> &mut AstNodeWrapper<Wrapped, Tag> {
318 unsafe { &mut *<*mut Wrapped>::cast(wrapped) }
320 }
321}
322
323impl<T, Tag> From<AstNodeWrapper<Box<T>, Tag>> for AstNodeWrapper<T, Tag> {
325 fn from(value: AstNodeWrapper<Box<T>, Tag>) -> Self {
326 AstNodeWrapper { wrapped: *value.wrapped, tag: value.tag }
327 }
328}
329
330impl<Wrapped: HasNodeId, Tag> HasNodeId for AstNodeWrapper<Wrapped, Tag> {
331 fn node_id(&self) -> NodeId {
332 self.wrapped.node_id()
333 }
334 fn node_id_mut(&mut self) -> &mut NodeId {
335 self.wrapped.node_id_mut()
336 }
337}
338
339impl<Wrapped: HasAttrs, Tag> HasAttrs for AstNodeWrapper<Wrapped, Tag> {
340 const SUPPORTS_CUSTOM_INNER_ATTRS: bool = Wrapped::SUPPORTS_CUSTOM_INNER_ATTRS;
341 fn attrs(&self) -> &[Attribute] {
342 self.wrapped.attrs()
343 }
344 fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
345 self.wrapped.visit_attrs(f);
346 }
347}
348
349impl<Wrapped: fmt::Debug, Tag> fmt::Debug for AstNodeWrapper<Wrapped, Tag> {
350 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
351 f.debug_struct("AstNodeWrapper")
352 .field("wrapped", &self.wrapped)
353 .field("tag", &self.tag)
354 .finish()
355 }
356}