[−][src]Macro visit::visit
visit!() { /* proc-macro */ }
Procedural macro to automatically generate code for the Visitor pattern
Example
use visit::visit; visit! { #![visitor_trait = "Visitor"] struct Bar { a: Child, b: Child, } struct Child {} } struct MyVisitor; impl Visitor for MyVisitor { fn visit_child(&mut self, child: &Child) { // Do something cool } }
Use the accept
method on the data structure you want to visit:
let mut visitor = MyVisitor {}; let root = Bar { a: Child {}, b: Child {} }; root.accept(&mut visitor);
Attributes
#![visitor_trait = "Visitor"]
Set the name of the visitor trait that should be generated.
#![visitor_trait_pub = "Visitor"]
Like #![visitor_trait]
, but the generated trait will be pub
.
Details
visit automatically generates a visitor trait named by the required #![visitor_trait]
attribute:
trait Visitor { fn visit_bar(&mut self, bar: &Bar) {} fn visit_child(&mut self, child: &Child) {} // ... }
This trait specifies visit
methods for all supported items (structs and enums) contained inside the visit!
macro
block.
It also provides empty default implementations for all methods so you only need to implement the visit_*
methods
that are relevant to your current use case.
visit also generates an accept visitor trait. It is named AcceptVisitor
where Visitor
will be replaced by the
name specified using the #![visitor_trait]
attribute.
trait AcceptVisitor { fn accept<V: Visitor>(&self, visitor: &mut V); }
This trait gets automatically implemented for all items contained inside the visit!
macro block. For example, a
trait implementation generated for Bar
could look like this:
impl AcceptVisitor for Bar { fn accept<V: Visitor>(&self, visitor: &mut V) { self.a.accept(visitor); self.b.accept(visitor); visitor.visit_bar(self); } }
visit also generates some default implementations for common collections and Option<T>
. Primitive types are
ignored (visit generates an empty accept trait implementation for them).