1 | // SPDX-License-Identifier: Apache-2.0 OR MIT |
2 | |
3 | use std::{iter, mem}; |
4 | |
5 | use proc_macro2::TokenStream; |
6 | use syn::{ |
7 | punctuated::Punctuated, token, visit_mut::VisitMut, Arm, Attribute, Block, Expr, ExprBlock, |
8 | ExprCall, ExprPath, ExprTuple, ItemFn, Local, Meta, Path, PathSegment, Stmt, StmtMacro, |
9 | }; |
10 | |
11 | pub(crate) fn path(segments: impl IntoIterator<Item = PathSegment>) -> Path { |
12 | Path { leading_colon: None, segments: segments.into_iter().collect() } |
13 | } |
14 | |
15 | pub(crate) fn block(stmts: Vec<Stmt>) -> Block { |
16 | Block { brace_token: token::Brace::default(), stmts } |
17 | } |
18 | |
19 | pub(crate) fn expr_block(block: Block) -> Expr { |
20 | Expr::Block(ExprBlock { attrs: vec![], label: None, block }) |
21 | } |
22 | |
23 | pub(crate) fn expr_call(attrs: Vec<Attribute>, path: Path, arg: Expr) -> Expr { |
24 | Expr::Call(ExprCall { |
25 | attrs, |
26 | func: Box::new(Expr::Path(ExprPath { attrs: vec![], qself: None, path })), |
27 | paren_token: token::Paren::default(), |
28 | args: iter::once(arg).collect(), |
29 | }) |
30 | } |
31 | |
32 | pub(crate) fn unit() -> Expr { |
33 | Expr::Tuple(ExprTuple { |
34 | attrs: vec![], |
35 | paren_token: token::Paren::default(), |
36 | elems: Punctuated::new(), |
37 | }) |
38 | } |
39 | |
40 | pub(crate) fn replace_expr(this: &mut Expr, f: impl FnOnce(Expr) -> Expr) { |
41 | *this = f(mem::replace(dest:this, src:Expr::Verbatim(TokenStream::new()))); |
42 | } |
43 | |
44 | pub(crate) fn replace_block(this: &mut Block, f: impl FnOnce(Block) -> Expr) { |
45 | // `brace_token` of the block that passed to `f` should have `call_site` span. |
46 | // If `f` generates unused braces containing the span of `this.brace_token`, |
47 | // this will cause confusing warnings: https://github.com/rust-lang/rust/issues/71080 |
48 | let stmts: Vec = mem::take(&mut this.stmts); |
49 | this.stmts = vec![Stmt::Expr(f(block(stmts)), None)]; |
50 | } |
51 | |
52 | pub(crate) fn path_eq(path: &syn::Path, expected_crates: &[&str], expected_path: &[&str]) -> bool { |
53 | if path.segments.len() == 1 && path.segments[0].ident == expected_path.last().unwrap() { |
54 | return true; |
55 | } |
56 | if path.segments.len() == expected_path.len() + 1 { |
57 | if !expected_crates.iter().any(|&c: &str| path.segments[0].ident == c) { |
58 | return false; |
59 | } |
60 | for i: usize in 1..path.segments.len() { |
61 | if path.segments[i].ident != expected_path[i - 1] { |
62 | return false; |
63 | } |
64 | } |
65 | return true; |
66 | } |
67 | false |
68 | } |
69 | |
70 | // ================================================================================================= |
71 | // extension traits |
72 | |
73 | pub(crate) trait VecExt<T> { |
74 | fn find_remove(&mut self, predicate: impl FnMut(&T) -> bool) -> Option<T>; |
75 | } |
76 | |
77 | impl<T> VecExt<T> for Vec<T> { |
78 | fn find_remove(&mut self, predicate: impl FnMut(&T) -> bool) -> Option<T> { |
79 | self.iter().position(predicate).map(|i: usize| self.remove(index:i)) |
80 | } |
81 | } |
82 | |
83 | // ================================================================================================= |
84 | // node |
85 | |
86 | pub(crate) trait Node { |
87 | fn visited(&mut self, visitor: &mut impl VisitMut); |
88 | } |
89 | |
90 | impl Node for Stmt { |
91 | fn visited(&mut self, visitor: &mut impl VisitMut) { |
92 | visitor.visit_stmt_mut(self); |
93 | } |
94 | } |
95 | |
96 | impl Node for Local { |
97 | fn visited(&mut self, visitor: &mut impl VisitMut) { |
98 | visitor.visit_local_mut(self); |
99 | } |
100 | } |
101 | |
102 | impl Node for Expr { |
103 | fn visited(&mut self, visitor: &mut impl VisitMut) { |
104 | visitor.visit_expr_mut(self); |
105 | } |
106 | } |
107 | |
108 | impl Node for Arm { |
109 | fn visited(&mut self, visitor: &mut impl VisitMut) { |
110 | visitor.visit_arm_mut(self); |
111 | } |
112 | } |
113 | |
114 | impl Node for Block { |
115 | fn visited(&mut self, visitor: &mut impl VisitMut) { |
116 | visitor.visit_block_mut(self); |
117 | } |
118 | } |
119 | |
120 | impl Node for ItemFn { |
121 | fn visited(&mut self, visitor: &mut impl VisitMut) { |
122 | visitor.visit_item_fn_mut(self); |
123 | } |
124 | } |
125 | |
126 | // ================================================================================================= |
127 | // helper for handling attributes |
128 | |
129 | pub(crate) trait Attrs { |
130 | fn attrs(&self) -> &[Attribute]; |
131 | |
132 | fn any_attr(&self, ident: &str) -> bool { |
133 | self.attrs().iter().any(|attr: &Attribute| attr.path().is_ident(ident)) |
134 | } |
135 | |
136 | fn any_empty_attr(&self, ident: &str) -> bool { |
137 | self.attrs().iter().any(|attr: &Attribute| matches!(&attr.meta, Meta::Path(p) if p.is_ident(ident))) |
138 | } |
139 | |
140 | fn attrs_mut(&mut self) -> Option<&mut Vec<Attribute>>; |
141 | |
142 | fn find_remove_attr(&mut self, ident: &str) -> Option<Attribute> { |
143 | self.attrs_mut()?.find_remove(|attr: &Attribute| attr.path().is_ident(ident)) |
144 | } |
145 | } |
146 | |
147 | impl Attrs for Arm { |
148 | fn attrs(&self) -> &[Attribute] { |
149 | &self.attrs |
150 | } |
151 | |
152 | fn attrs_mut(&mut self) -> Option<&mut Vec<Attribute>> { |
153 | Some(&mut self.attrs) |
154 | } |
155 | } |
156 | |
157 | impl Attrs for Local { |
158 | fn attrs(&self) -> &[Attribute] { |
159 | &self.attrs |
160 | } |
161 | |
162 | fn attrs_mut(&mut self) -> Option<&mut Vec<Attribute>> { |
163 | Some(&mut self.attrs) |
164 | } |
165 | } |
166 | |
167 | impl Attrs for StmtMacro { |
168 | fn attrs(&self) -> &[Attribute] { |
169 | &self.attrs |
170 | } |
171 | |
172 | fn attrs_mut(&mut self) -> Option<&mut Vec<Attribute>> { |
173 | Some(&mut self.attrs) |
174 | } |
175 | } |
176 | |
177 | impl Attrs for Stmt { |
178 | fn attrs(&self) -> &[Attribute] { |
179 | match self { |
180 | Stmt::Expr(expr: &Expr, _) => expr.attrs(), |
181 | Stmt::Local(local: &Local) => local.attrs(), |
182 | Stmt::Macro(mac: &StmtMacro) => mac.attrs(), |
183 | // Ignore nested items. |
184 | Stmt::Item(_) => &[], |
185 | } |
186 | } |
187 | |
188 | fn attrs_mut(&mut self) -> Option<&mut Vec<Attribute>> { |
189 | match self { |
190 | Stmt::Expr(expr: &mut Expr, _) => expr.attrs_mut(), |
191 | Stmt::Local(local: &mut Local) => local.attrs_mut(), |
192 | Stmt::Macro(mac: &mut StmtMacro) => mac.attrs_mut(), |
193 | // Ignore nested items. |
194 | Stmt::Item(_) => None, |
195 | } |
196 | } |
197 | } |
198 | |
199 | macro_rules! attrs_impl { |
200 | ($($Expr:ident($Struct:ident),)*) => { |
201 | impl Attrs for Expr { |
202 | fn attrs(&self) -> &[Attribute] { |
203 | // #[cfg_attr(test, deny(non_exhaustive_omitted_patterns))] |
204 | match self { |
205 | $(Expr::$Expr(syn::$Struct { attrs, .. }))|* => &attrs, |
206 | _ => &[], |
207 | } |
208 | } |
209 | |
210 | fn attrs_mut(&mut self) -> Option<&mut Vec<Attribute>> { |
211 | // #[cfg_attr(test, deny(non_exhaustive_omitted_patterns))] |
212 | match self { |
213 | $(Expr::$Expr(syn::$Struct { attrs, .. }))|* => Some(attrs), |
214 | _ => None, |
215 | } |
216 | } |
217 | } |
218 | }; |
219 | } |
220 | |
221 | attrs_impl! { |
222 | Array(ExprArray), |
223 | Assign(ExprAssign), |
224 | Async(ExprAsync), |
225 | Await(ExprAwait), |
226 | Binary(ExprBinary), |
227 | Block(ExprBlock), |
228 | Break(ExprBreak), |
229 | Call(ExprCall), |
230 | Cast(ExprCast), |
231 | Closure(ExprClosure), |
232 | Const(ExprConst), |
233 | Continue(ExprContinue), |
234 | Field(ExprField), |
235 | ForLoop(ExprForLoop), |
236 | Group(ExprGroup), |
237 | If(ExprIf), |
238 | Index(ExprIndex), |
239 | Infer(ExprInfer), |
240 | Let(ExprLet), |
241 | Lit(ExprLit), |
242 | Loop(ExprLoop), |
243 | Macro(ExprMacro), |
244 | Match(ExprMatch), |
245 | MethodCall(ExprMethodCall), |
246 | Paren(ExprParen), |
247 | Path(ExprPath), |
248 | Range(ExprRange), |
249 | Reference(ExprReference), |
250 | Repeat(ExprRepeat), |
251 | Return(ExprReturn), |
252 | Struct(ExprStruct), |
253 | Try(ExprTry), |
254 | TryBlock(ExprTryBlock), |
255 | Tuple(ExprTuple), |
256 | Unary(ExprUnary), |
257 | Unsafe(ExprUnsafe), |
258 | While(ExprWhile), |
259 | Yield(ExprYield), |
260 | } |
261 | |