swc_visit/
lib.rs

1//! Visitor generator for the rust language.
2//!
3//!
4//! There are three variants of visitor in swc. Those are `Fold`, `VisitMut`,
5//! `Visit`.
6//!
7//! # Comparisons
8//!
9//! ## `Fold` vs `VisitMut`
10//!
11//! `Fold` and `VisitMut` do almost identical tasks, but `Fold` is easier to use
12//! while being slower and weak to stack overflow for very deep asts. `Fold` is
13//! fast enough for almost all cases so it would be better to start with `Fold`.
14//!
15//! By very deep asts, I meant code like thousands of `a + a + a + a + ...`.
16//!
17//!
18//! # `Fold`
19//!
20//! > WARNING: `Fold` is slow, and it's recommended to use VisitMut if you are
21//! > experienced.
22//!
23//!
24//! `Fold` takes ownership of value, which means you have to return the new
25//! value. Returning new value means returning ownership of the value. But you
26//! don't have to care about ownership or about managing memories while using
27//! such visitors. `rustc` handles them automatically and all allocations will
28//! be freed when it goes out of the scope.
29//!
30//! You can invoke your `Fold` implementation like `node.fold_with(&mut
31//! visitor)` where `visitor` is your visitor. Note that as it takes ownership
32//! of value, you have to call `node.fold_children_with(self)` in e.g. `fn
33//! fold_module(&mut self, m: Module) -> Module` if you override the default
34//! behavior. Also you have to store return value from `fold_children_with`,
35//! like `let node = node.fold_children_with(self)`. Order of execution can be
36//! controlled using this. If there is some logic that should be applied to the
37//! parent first, you can call `fold_children_with` after such logic.
38//!
39//! # `VisitMut`
40//!
41//! `VisitMut` uses a mutable reference to AST nodes (e.g. `&mut Expr`). You can
42//! use `Take` from `swc_common::util::take::Take` to get owned value from a
43//! mutable reference.
44//!
45//! You will typically use code like
46//!
47//! ```ignore
48//! *e = return_value.take();
49//! ```
50//!
51//! where `e = &mut Expr` and `return_value` is also `&mut Expr`. `take()` is an
52//! extension method defined on `MapWithMut`.  It's almost identical to `Fold`,
53//! so I'll skip memory management.
54//!
55//! You can invoke your `VisitMut` implementation like `node.visit_mut_with(&mut
56//! visitor)` where `visitor` is your visitor. Again, you need to call
57//! `node.visit_mut_children_with(self)` in visitor implementation if you want
58//! to modify children nodes. You don't need to store the return value in this
59//! case.
60//!
61//!
62//! # `Visit`
63//!
64//!`Visit` uses non-mutable references to AST nodes. It can be used to see if
65//! an AST node contains a specific node nested deeply in the AST. This is
66//! useful for checking if AST node contains `this`. This is useful for lots of
67//! cases - `this` in arrow expressions are special and we need to generate
68//! different code if a `this` expression is used.
69//!
70//! You can use your `Visit` implementation like  `node.visit_with(&Invalid{
71//! span: DUMMY_SP, }, &mut visitor`. I think API is mis-designed, but it works
72//! and there are really lots of code using `Visit` already.
73//!
74//!
75//!
76//! # Cargo features
77//!
78//! You should add
79//! ```toml
80//! [features]
81//! path = []
82//! ```
83//!
84//! If you want to allow using path-aware visitor.
85//!
86//!
87//! # Path-aware visitor
88//!
89//! Path-aware visitor is a visitor that can be used to visit AST nodes with
90//! current path from the entrypoint.
91//!
92//! `VisitMutAstPath` and `FoldAstPath` can be used to transform AST nodes with
93//! the path to the node.
94
95use std::ops::{Deref, DerefMut};
96
97pub use either::Either;
98
99pub mod util;
100
101/// Visit all children nodes. This converts `VisitAll` to `Visit`. The type
102/// parameter `V` should implement `VisitAll` and `All<V>` implements `Visit`.
103#[derive(Debug, Clone, Copy, PartialEq, Eq)]
104pub struct All<V> {
105    pub visitor: V,
106}
107
108/// A visitor which visits node only if `enabled` is true.
109#[derive(Debug, Clone, Copy, PartialEq, Eq)]
110pub struct Optional<V> {
111    pub enabled: bool,
112    pub visitor: V,
113}
114
115impl<V> Optional<V> {
116    pub const fn new(visitor: V, enabled: bool) -> Self {
117        Self { enabled, visitor }
118    }
119}
120
121/// Trait for a pass which is designed to invoked multiple time to same input.
122///
123/// See [Repeat].
124pub trait Repeated {
125    /// Should run again?
126    fn changed(&self) -> bool;
127
128    /// Reset.
129    fn reset(&mut self);
130}
131
132macro_rules! impl_repeated_for_tuple {
133    (
134        [$idx:tt, $name:ident], $([$idx_rest:tt, $name_rest:ident]),*
135    ) => {
136        impl<$name, $($name_rest),*> Repeated for ($name, $($name_rest),*)
137        where
138            $name: Repeated,
139            $($name_rest: Repeated),*
140        {
141            fn changed(&self) -> bool {
142                self.$idx.changed() || $(self.$idx_rest.changed() ||)* false
143            }
144
145            fn reset(&mut self) {
146                self.$idx.reset();
147                $(self.$idx_rest.reset();)*
148            }
149        }
150    };
151}
152
153impl_repeated_for_tuple!([0, A], [1, B]);
154impl_repeated_for_tuple!([0, A], [1, B], [2, C]);
155impl_repeated_for_tuple!([0, A], [1, B], [2, C], [3, D]);
156impl_repeated_for_tuple!([0, A], [1, B], [2, C], [3, D], [4, E]);
157impl_repeated_for_tuple!([0, A], [1, B], [2, C], [3, D], [4, E], [5, F]);
158impl_repeated_for_tuple!([0, A], [1, B], [2, C], [3, D], [4, E], [5, F], [6, G]);
159impl_repeated_for_tuple!(
160    [0, A],
161    [1, B],
162    [2, C],
163    [3, D],
164    [4, E],
165    [5, F],
166    [6, G],
167    [7, H]
168);
169impl_repeated_for_tuple!(
170    [0, A],
171    [1, B],
172    [2, C],
173    [3, D],
174    [4, E],
175    [5, F],
176    [6, G],
177    [7, H],
178    [8, I]
179);
180impl_repeated_for_tuple!(
181    [0, A],
182    [1, B],
183    [2, C],
184    [3, D],
185    [4, E],
186    [5, F],
187    [6, G],
188    [7, H],
189    [8, I],
190    [9, J]
191);
192impl_repeated_for_tuple!(
193    [0, A],
194    [1, B],
195    [2, C],
196    [3, D],
197    [4, E],
198    [5, F],
199    [6, G],
200    [7, H],
201    [8, I],
202    [9, J],
203    [10, K]
204);
205impl_repeated_for_tuple!(
206    [0, A],
207    [1, B],
208    [2, C],
209    [3, D],
210    [4, E],
211    [5, F],
212    [6, G],
213    [7, H],
214    [8, I],
215    [9, J],
216    [10, K],
217    [11, L]
218);
219impl_repeated_for_tuple!(
220    [0, A],
221    [1, B],
222    [2, C],
223    [3, D],
224    [4, E],
225    [5, F],
226    [6, G],
227    [7, H],
228    [8, I],
229    [9, J],
230    [10, K],
231    [11, L],
232    [12, M]
233);
234
235/// A visitor which applies `V` again and again if `V` modifies the node.
236///
237/// # Note
238/// `V` should return `true` from `changed()` to make the pass run multiple
239/// time.
240///
241/// See: [Repeated]
242#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
243pub struct Repeat<V>
244where
245    V: Repeated,
246{
247    pub pass: V,
248}
249
250impl<V> Repeat<V>
251where
252    V: Repeated,
253{
254    pub fn new(pass: V) -> Self {
255        Self { pass }
256    }
257}
258
259impl<V> Repeated for Repeat<V>
260where
261    V: Repeated,
262{
263    fn changed(&self) -> bool {
264        self.pass.changed()
265    }
266
267    fn reset(&mut self) {
268        self.pass.reset()
269    }
270}
271
272#[derive(Debug, Clone, PartialEq, Eq)]
273pub struct AstKindPath<K>
274where
275    K: ParentKind,
276{
277    path: Vec<K>,
278}
279
280impl<K> std::ops::Deref for AstKindPath<K>
281where
282    K: ParentKind,
283{
284    type Target = Vec<K>;
285
286    fn deref(&self) -> &Self::Target {
287        &self.path
288    }
289}
290
291impl<K> Default for AstKindPath<K>
292where
293    K: ParentKind,
294{
295    fn default() -> Self {
296        Self {
297            path: Default::default(),
298        }
299    }
300}
301
302impl<K> AstKindPath<K>
303where
304    K: ParentKind,
305{
306    pub fn new(path: Vec<K>) -> Self {
307        Self { path }
308    }
309
310    pub fn with_guard(&mut self, kind: K) -> AstKindPathGuard<K> {
311        self.path.push(kind);
312
313        AstKindPathGuard { path: self }
314    }
315
316    pub fn with_index_guard(&mut self, index: usize) -> AstKindPathIndexGuard<K> {
317        self.path.last_mut().unwrap().set_index(index);
318
319        AstKindPathIndexGuard { path: self }
320    }
321
322    #[deprecated = "Use with_guard instead"]
323    pub fn with<Ret>(&mut self, path: K, op: impl FnOnce(&mut Self) -> Ret) -> Ret {
324        self.path.push(path);
325        let ret = op(self);
326        self.path.pop();
327        ret
328    }
329
330    #[deprecated = "Use with_index_guard instead"]
331    pub fn with_index<Ret>(&mut self, index: usize, op: impl FnOnce(&mut Self) -> Ret) -> Ret {
332        self.path.last_mut().unwrap().set_index(index);
333        let res = op(self);
334        self.path.last_mut().unwrap().set_index(usize::MAX);
335        res
336    }
337}
338
339pub struct AstKindPathGuard<'a, K>
340where
341    K: ParentKind,
342{
343    path: &'a mut AstKindPath<K>,
344}
345
346impl<K> Deref for AstKindPathGuard<'_, K>
347where
348    K: ParentKind,
349{
350    type Target = AstKindPath<K>;
351
352    #[inline]
353    fn deref(&self) -> &Self::Target {
354        self.path
355    }
356}
357
358impl<K> DerefMut for AstKindPathGuard<'_, K>
359where
360    K: ParentKind,
361{
362    #[inline]
363    fn deref_mut(&mut self) -> &mut Self::Target {
364        self.path
365    }
366}
367
368impl<K> Drop for AstKindPathGuard<'_, K>
369where
370    K: ParentKind,
371{
372    fn drop(&mut self) {
373        self.path.path.pop();
374    }
375}
376
377pub struct AstKindPathIndexGuard<'a, K>
378where
379    K: ParentKind,
380{
381    path: &'a mut AstKindPath<K>,
382}
383
384impl<K> Deref for AstKindPathIndexGuard<'_, K>
385where
386    K: ParentKind,
387{
388    type Target = AstKindPath<K>;
389
390    #[inline]
391    fn deref(&self) -> &Self::Target {
392        self.path
393    }
394}
395
396impl<K> DerefMut for AstKindPathIndexGuard<'_, K>
397where
398    K: ParentKind,
399{
400    #[inline]
401    fn deref_mut(&mut self) -> &mut Self::Target {
402        self.path
403    }
404}
405
406impl<K> Drop for AstKindPathIndexGuard<'_, K>
407where
408    K: ParentKind,
409{
410    fn drop(&mut self) {
411        self.path.path.last_mut().unwrap().set_index(usize::MAX);
412    }
413}
414
415#[derive(Debug, Clone, PartialEq, Eq)]
416pub struct AstNodePath<N>
417where
418    N: NodeRef,
419{
420    kinds: AstKindPath<N::ParentKind>,
421    path: Vec<N>,
422}
423
424impl<N> std::ops::Deref for AstNodePath<N>
425where
426    N: NodeRef,
427{
428    type Target = Vec<N>;
429
430    fn deref(&self) -> &Self::Target {
431        &self.path
432    }
433}
434
435impl<N> Default for AstNodePath<N>
436where
437    N: NodeRef,
438{
439    fn default() -> Self {
440        Self {
441            kinds: Default::default(),
442            path: Default::default(),
443        }
444    }
445}
446
447impl<N> AstNodePath<N>
448where
449    N: NodeRef,
450{
451    pub fn new(kinds: AstKindPath<N::ParentKind>, path: Vec<N>) -> Self {
452        Self { kinds, path }
453    }
454
455    pub fn kinds(&self) -> &AstKindPath<N::ParentKind> {
456        &self.kinds
457    }
458
459    pub fn with_guard(&mut self, node: N) -> AstNodePathGuard<N> {
460        self.kinds.path.push(node.kind());
461        self.path.push(node);
462
463        AstNodePathGuard { path: self }
464    }
465
466    pub fn with_index_guard(&mut self, index: usize) -> AstNodePathIndexGuard<N> {
467        self.kinds.path.last_mut().unwrap().set_index(index);
468        self.path.last_mut().unwrap().set_index(index);
469
470        AstNodePathIndexGuard { path: self }
471    }
472
473    #[deprecated = "Use with_guard instead"]
474    pub fn with<F, Ret>(&mut self, node: N, op: F) -> Ret
475    where
476        F: for<'aa> FnOnce(&'aa mut AstNodePath<N>) -> Ret,
477    {
478        let kind = node.kind();
479
480        self.kinds.path.push(kind);
481        self.path.push(node);
482        let ret = op(self);
483        self.path.pop();
484        self.kinds.path.pop();
485
486        ret
487    }
488
489    #[deprecated = "Use with_index_guard instead"]
490    pub fn with_index<F, Ret>(&mut self, index: usize, op: F) -> Ret
491    where
492        F: for<'aa> FnOnce(&'aa mut AstNodePath<N>) -> Ret,
493    {
494        self.kinds.path.last_mut().unwrap().set_index(index);
495        self.path.last_mut().unwrap().set_index(index);
496
497        let res = op(self);
498
499        self.path.last_mut().unwrap().set_index(usize::MAX);
500        self.kinds.path.last_mut().unwrap().set_index(usize::MAX);
501        res
502    }
503}
504
505pub trait NodeRef: Copy {
506    type ParentKind: ParentKind;
507
508    fn kind(&self) -> Self::ParentKind;
509
510    fn set_index(&mut self, index: usize);
511}
512
513pub trait ParentKind: Copy {
514    fn set_index(&mut self, index: usize);
515}
516
517pub struct AstNodePathGuard<'a, N>
518where
519    N: NodeRef,
520{
521    path: &'a mut AstNodePath<N>,
522}
523
524impl<N> Deref for AstNodePathGuard<'_, N>
525where
526    N: NodeRef,
527{
528    type Target = AstNodePath<N>;
529
530    #[inline]
531    fn deref(&self) -> &Self::Target {
532        self.path
533    }
534}
535
536impl<N> DerefMut for AstNodePathGuard<'_, N>
537where
538    N: NodeRef,
539{
540    #[inline]
541    fn deref_mut(&mut self) -> &mut Self::Target {
542        self.path
543    }
544}
545
546impl<N> Drop for AstNodePathGuard<'_, N>
547where
548    N: NodeRef,
549{
550    fn drop(&mut self) {
551        self.path.path.pop();
552        self.path.kinds.path.pop();
553    }
554}
555
556pub struct AstNodePathIndexGuard<'a, N>
557where
558    N: NodeRef,
559{
560    path: &'a mut AstNodePath<N>,
561}
562
563impl<N> Deref for AstNodePathIndexGuard<'_, N>
564where
565    N: NodeRef,
566{
567    type Target = AstNodePath<N>;
568
569    #[inline]
570    fn deref(&self) -> &Self::Target {
571        self.path
572    }
573}
574
575impl<N> DerefMut for AstNodePathIndexGuard<'_, N>
576where
577    N: NodeRef,
578{
579    #[inline]
580    fn deref_mut(&mut self) -> &mut Self::Target {
581        self.path
582    }
583}
584
585impl<N> Drop for AstNodePathIndexGuard<'_, N>
586where
587    N: NodeRef,
588{
589    fn drop(&mut self) {
590        self.path.path.last_mut().unwrap().set_index(usize::MAX);
591        self.path
592            .kinds
593            .path
594            .last_mut()
595            .unwrap()
596            .set_index(usize::MAX);
597    }
598}
599
600/// NOT A PUBLIC API
601#[doc(hidden)]
602pub fn wrong_ast_path() {
603    unsafe {
604        debug_unreachable::debug_unreachable!("Wrong ast path");
605    }
606}