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