Add derive based AST visitor (#765)

* Add derive based AST visitor

* Fix BigDecimal

* Fix no visitor feature

* Add test

* Rename visit_table to visit_relation

* Review feedback

* Add pre and post visit

Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
Raphael Taylor-Davies 2022-12-28 15:07:12 +00:00 committed by GitHub
parent 3e990466f8
commit dec3c2b818
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 771 additions and 11 deletions

79
derive/README.md Normal file
View file

@ -0,0 +1,79 @@
# SQL Parser Derive Macro
## Visit
This crate contains a procedural macro that can automatically derive implementations of the `Visit` trait
```rust
#[derive(Visit)]
struct Foo {
boolean: bool,
bar: Bar,
}
#[derive(Visit)]
enum Bar {
A(),
B(String, bool),
C { named: i32 },
}
```
Will generate code akin to
```rust
impl Visit for Foo {
fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
self.boolean.visit(visitor)?;
self.bar.visit(visitor)?;
ControlFlow::Continue(())
}
}
impl Visit for Bar {
fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
match self {
Self::A() => {}
Self::B(_1, _2) => {
_1.visit(visitor)?;
_2.visit(visitor)?;
}
Self::C { named } => {
named.visit(visitor)?;
}
}
ControlFlow::Continue(())
}
}
```
Additionally certain types may wish to call a corresponding method on visitor before recursing
```rust
#[derive(Visit)]
#[visit(with = "visit_expr")]
enum Expr {
A(),
B(String, #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName, bool),
}
```
Will generate
```rust
impl Visit for Bar {
fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
visitor.visit_expr(self)?;
match self {
Self::A() => {}
Self::B(_1, _2, _3) => {
_1.visit(visitor)?;
visitor.visit_relation(_3)?;
_2.visit(visitor)?;
_3.visit(visitor)?;
}
}
ControlFlow::Continue(())
}
}
```