Rewrite the AST to be a bit more user-friendly
This commit is a relatively large rewrite of the AST that `syn` exposes. The
main change is to expose enums-of-structs rather than
enums-with-huge-tuple-variants. The best example of this is `ItemKind::Fn` which
changed from:
enum ItemKind {
Fn(Box<FnDecl>, Unsafety, Constness, Option<Abi>, Generics, Box<Block>),
...
}
to
enum ItemKind {
Fn(ItemFn),
...
}
struct ItemFn {
decl: Box<FnDecl>,
unsafety: Unsafety,
constness: Constness,
abi: Option<Abi>,
generics: Generics,
block: Box<Block>,
}
This change serves a few purposes:
* It's now much easier to add fields to each variant of the ast, ast struct
fields tend to be "by default ignored" in most contexts.
* It's much easier to document what each field is, as each field can have
dedicated documentation.
* There's now canonicalized names for each field (the name of the field) which
can help match `match` statements more consistent across a codebase.
A downside of this representation is that it can be a little more verbose to
work with in `match` statements and during constructions. Overall though I'd
feel at least that the readability improved significantly despite the extra
words required to do various operations.
Closes #136
diff --git a/src/data.rs b/src/data.rs
index 69df303..d01d9e5 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -1,32 +1,34 @@
use super::*;
-/// An enum variant.
-#[derive(Debug, Clone, Eq, PartialEq, Hash)]
-pub struct Variant {
- /// Name of the variant.
- pub ident: Ident,
+ast_struct! {
+ /// An enum variant.
+ pub struct Variant {
+ /// Name of the variant.
+ pub ident: Ident,
- /// Attributes tagged on the variant.
- pub attrs: Vec<Attribute>,
+ /// Attributes tagged on the variant.
+ pub attrs: Vec<Attribute>,
- /// Type of variant.
- pub data: VariantData,
+ /// Type of variant.
+ pub data: VariantData,
- /// Explicit discriminant, e.g. `Foo = 1`
- pub discriminant: Option<ConstExpr>,
+ /// Explicit discriminant, e.g. `Foo = 1`
+ pub discriminant: Option<ConstExpr>,
+ }
}
-/// Data stored within an enum variant or struct.
-#[derive(Debug, Clone, Eq, PartialEq, Hash)]
-pub enum VariantData {
- /// Struct variant, e.g. `Point { x: f64, y: f64 }`.
- Struct(Vec<Field>),
+ast_enum! {
+ /// Data stored within an enum variant or struct.
+ pub enum VariantData {
+ /// Struct variant, e.g. `Point { x: f64, y: f64 }`.
+ Struct(Vec<Field>),
- /// Tuple variant, e.g. `Some(T)`.
- Tuple(Vec<Field>),
+ /// Tuple variant, e.g. `Some(T)`.
+ Tuple(Vec<Field>),
- /// Unit variant, e.g. `None`.
- Unit,
+ /// Unit variant, e.g. `None`.
+ Unit,
+ }
}
impl VariantData {
@@ -49,39 +51,40 @@
}
}
-/// A field of a struct or enum variant.
-#[derive(Debug, Clone, Eq, PartialEq, Hash)]
-pub struct Field {
- /// Name of the field, if any.
- ///
- /// Fields of tuple structs have no names.
- pub ident: Option<Ident>,
+ast_struct! {
+ /// A field of a struct or enum variant.
+ pub struct Field {
+ /// Name of the field, if any.
+ ///
+ /// Fields of tuple structs have no names.
+ pub ident: Option<Ident>,
- /// Visibility of the field.
- pub vis: Visibility,
+ /// Visibility of the field.
+ pub vis: Visibility,
- /// Attributes tagged on the field.
- pub attrs: Vec<Attribute>,
+ /// Attributes tagged on the field.
+ pub attrs: Vec<Attribute>,
- /// Type of the field.
- pub ty: Ty,
+ /// Type of the field.
+ pub ty: Ty,
+ }
}
+ast_enum! {
+ /// Visibility level of an item.
+ pub enum Visibility {
+ /// Public, i.e. `pub`.
+ Public,
-/// Visibility level of an item.
-#[derive(Debug, Clone, Eq, PartialEq, Hash)]
-pub enum Visibility {
- /// Public, i.e. `pub`.
- Public,
+ /// Crate-visible, i.e. `pub(crate)`.
+ Crate,
- /// Crate-visible, i.e. `pub(crate)`.
- Crate,
+ /// Restricted, e.g. `pub(self)` or `pub(super)` or `pub(in some::module)`.
+ Restricted(Box<Path>),
- /// Restricted, e.g. `pub(self)` or `pub(super)` or `pub(in some::module)`.
- Restricted(Box<Path>),
-
- /// Inherited, i.e. private.
- Inherited,
+ /// Inherited, i.e. private.
+ Inherited,
+ }
}
#[cfg(feature = "parsing")]