Expand description
Visitor generator for the rust language.
There are three variants of visitor in swc. Those are Fold
, VisitMut
,
Visit
.
Comparisons
Fold
vs VisitMut
Fold
and VisitMut
do almost identical tasks, but Fold
is easier to use
while being slower and weak to stack overflow for very deep asts. Fold
is
fast enough for almost all cases so it would be better to start with Fold
.
By very deep asts, I meant code like thousands of a + a + a + a + ...
.
Fold
WARNING:
Fold
is slow, and it’s recommended to use VisitMut if you are experienced.
Fold
takes ownership of value, which means you have to return the new
value. Returning new value means returning ownership of the value. But you
don’t have to care about ownership or about managing memories while using
such visitors. rustc
handles them automatically and all allocations will
be freed when it goes out of the scope.
You can invoke your Fold
implementation like node.fold_with(&mut visitor)
where visitor
is your visitor. Note that as it takes ownership
of value, you have to call node.fold_children_with(self)
in e.g. fn fold_module(&mut self, m: Module) -> Module
if you override the default
behavior. Also you have to store return value from fold_children_with
,
like let node = node.fold_children_with(self)
. Order of execution can be
controlled using this. If there is some logic that should be applied to the
parent first, you can call fold_children_with
after such logic.
VisitMut
VisitMut
uses a mutable reference to AST nodes (e.g. &mut Expr
). You can
use Take
from swc_common::util::take::Take
to get owned value from a
mutable reference.
You will typically use code like
*e = return_value.take();
where e = &mut Expr
and return_value
is also &mut Expr
. take()
is an
extension method defined on MapWithMut
. It’s almost identical to Fold
,
so I’ll skip memory management.
You can invoke your VisitMut
implementation like node.visit_mut_with(&mut visitor)
where visitor
is your visitor. Again, you need to call
node.visit_mut_children_with(self)
in visitor implementation if you want
to modify children nodes. You don’t need to store the return value in this
case.
Visit
Visit
uses non-mutable references to AST nodes. It can be used to see if
an AST node contains a specific node nested deeply in the AST. This is
useful for checking if AST node contains this
. This is useful for lots of
cases - this
in arrow expressions are special and we need to generate
different code if a this
expression is used.
You can use your Visit
implementation like node.visit_with(&Invalid{ span: DUMMY_SP, }, &mut visitor
. I think API is mis-designed, but it works
and there are really lots of code using Visit
already.
Cargo features
You should add
[features]
path = []
If you want to allow using path-aware visitor.
Path-aware visitor
Path-aware visitor is a visitor that can be used to visit AST nodes with current path from the entrypoint.
VisitMutAstPath
and FoldAstPath
can be used to transform AST nodes with
the path to the node.
Modules
Macros
Structs
VisitAll
to Visit
. The type
parameter V
should implement VisitAll
and All<V>
implements Visit
.A
and then B
.enabled
is true.V
again and again if V
modifies the node.Enums
Either
with variants Left
and Right
is a general purpose
sum type with two cases.