Move ident and features fields into Node struct
diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml
index 75e8394..70274fa 100644
--- a/codegen/Cargo.toml
+++ b/codegen/Cargo.toml
@@ -13,8 +13,8 @@
inflections = "1.1"
proc-macro2 = "0.4"
rustfmt-nightly = { git = "https://github.com/rust-lang-nursery/rustfmt" }
-serde = "1.0.87"
-serde_derive = "1.0.87"
+serde = "1.0.88"
+serde_derive = "1.0.88"
serde_json = "1.0.38"
toml = "0.4.10"
diff --git a/codegen/src/gen.rs b/codegen/src/gen.rs
index 58f03fb..83ddc4e 100644
--- a/codegen/src/gen.rs
+++ b/codegen/src/gen.rs
@@ -11,7 +11,6 @@
//! 3. The path to `syn` is hardcoded.
use crate::types;
-use indexmap::IndexMap;
use proc_macro2::TokenStream;
use std::fs::File;
@@ -361,10 +360,10 @@
let mut res = simple_visit(t, kind, name);
- let target = defs.types.iter().find(|ty| ty.ident() == t).unwrap();
+ let target = defs.types.iter().find(|ty| ty.ident == *t).unwrap();
Some(
- if requires_full(target.features()) && !requires_full(features) {
+ if requires_full(&target.features) && !requires_full(features) {
quote! {
full!(#res)
}
@@ -396,9 +395,9 @@
}
pub fn generate(state: &mut State, s: &types::Node, defs: &types::Definitions) {
- let features = visit_features(s.features());
- let under_name = under_name(s.ident());
- let ty = Ident::new(s.ident(), Span::call_site());
+ let features = visit_features(&s.features);
+ let under_name = under_name(&s.ident);
+ let ty = Ident::new(&s.ident, Span::call_site());
let visit_fn = Ident::new(&format!("visit_{}", under_name), Span::call_site());
let visit_mut_fn = Ident::new(&format!("visit_{}_mut", under_name), Span::call_site());
let fold_fn = Ident::new(&format!("fold_{}", under_name), Span::call_site());
@@ -407,13 +406,13 @@
let mut visit_mut_impl = TokenStream::new();
let mut fold_impl = TokenStream::new();
- match s {
- types::Node::Enum(ref e) => {
+ match &s.data {
+ types::Data::Enum(variants) => {
let mut visit_variants = TokenStream::new();
let mut visit_mut_variants = TokenStream::new();
let mut fold_variants = TokenStream::new();
- for variant in &e.variants {
+ for variant in variants {
let variant_ident = Ident::new(&variant.ident, Span::call_site());
if variant.fields.is_empty() {
@@ -455,15 +454,15 @@
let owned_binding = Owned(quote!(#binding));
visit_fields.append_all(
- visit(ty, s.features(), defs, Visit, &borrowed_binding)
+ visit(ty, &s.features, defs, Visit, &borrowed_binding)
.unwrap_or_else(|| noop_visit(Visit, &borrowed_binding)),
);
visit_mut_fields.append_all(
- visit(ty, s.features(), defs, VisitMut, &borrowed_binding)
+ visit(ty, &s.features, defs, VisitMut, &borrowed_binding)
.unwrap_or_else(|| noop_visit(VisitMut, &borrowed_binding)),
);
fold_fields.append_all(
- visit(ty, s.features(), defs, Fold, &owned_binding)
+ visit(ty, &s.features, defs, Fold, &owned_binding)
.unwrap_or_else(|| noop_visit(Fold, &owned_binding)),
);
@@ -512,23 +511,23 @@
}
});
}
- types::Node::Struct(ref v) => {
+ types::Data::Struct(fields) => {
let mut fold_fields = TokenStream::new();
- for (field, ty) in &v.fields {
+ for (field, ty) in fields {
let id = Ident::new(&field, Span::call_site());
let ref_toks = Owned(quote!(_i.#id));
- let visit_field = visit(&ty, &v.features, defs, Visit, &ref_toks)
+ let visit_field = visit(&ty, &s.features, defs, Visit, &ref_toks)
.unwrap_or_else(|| noop_visit(Visit, &ref_toks));
visit_impl.append_all(quote! {
#visit_field;
});
- let visit_mut_field = visit(&ty, &v.features, defs, VisitMut, &ref_toks)
+ let visit_mut_field = visit(&ty, &s.features, defs, VisitMut, &ref_toks)
.unwrap_or_else(|| noop_visit(VisitMut, &ref_toks));
visit_mut_impl.append_all(quote! {
#visit_mut_field;
});
- let fold = visit(&ty, &v.features, defs, Fold, &ref_toks)
+ let fold = visit(&ty, &s.features, defs, Fold, &ref_toks)
.unwrap_or_else(|| noop_visit(Fold, &ref_toks));
fold_fields.append_all(quote! {
@@ -536,7 +535,7 @@
});
}
- if !v.fields.is_empty() {
+ if !fields.is_empty() {
fold_impl.append_all(quote! {
#ty {
#fold_fields
@@ -555,15 +554,25 @@
});
}
}
- }
-
- let mut include_fold_impl = true;
- if let types::Node::Struct(ref data) = s {
- if data.fields.is_empty() && !super::TERMINAL_TYPES.contains(&&s.ident()) {
- include_fold_impl = false;
+ types::Data::Private => {
+ if ty == "Ident" {
+ fold_impl.append_all(quote! {
+ let mut _i = _i;
+ let span = _visitor.fold_span(_i.span());
+ _i.set_span(span);
+ });
+ }
+ fold_impl.append_all(quote! {
+ _i
+ });
}
}
+ let include_fold_impl = match &s.data {
+ types::Data::Private => super::TERMINAL_TYPES.contains(&s.ident.as_str()),
+ types::Data::Struct(_) | types::Data::Enum(_) => true,
+ };
+
state.visit_trait.append_all(quote! {
#features
fn #visit_fn(&mut self, i: &'ast #ty) {
@@ -640,11 +649,11 @@
let mut defs = defs.clone();
for &tt in TERMINAL_TYPES {
- defs.types.push(types::Node::Struct(types::Struct::new(
- tt.to_string(),
- types::Features::default(),
- IndexMap::new(),
- )));
+ defs.types.push(types::Node {
+ ident: tt.to_string(),
+ features: types::Features::default(),
+ data: types::Data::Private,
+ });
}
let mut state = codegen::State::default();
diff --git a/codegen/src/parse.rs b/codegen/src/parse.rs
index e38c1e2..10872ea 100644
--- a/codegen/src/parse.rs
+++ b/codegen/src/parse.rs
@@ -48,33 +48,32 @@
let features = introspect_features(&item.features);
match &item.ast.data {
- Data::Enum(ref data) => types::Node::Enum(introspect_enum(
- &item.ast.ident,
+ Data::Enum(ref data) => types::Node {
+ ident: item.ast.ident.to_string(),
features,
- data,
- items,
- tokens,
- )),
- Data::Struct(ref data) => types::Node::Struct(introspect_struct(
- &item.ast.ident,
+ data: types::Data::Enum(introspect_enum(data, items, tokens)),
+ },
+ Data::Struct(ref data) => types::Node {
+ ident: item.ast.ident.to_string(),
features,
- data,
- items,
- tokens,
- )),
+ data: {
+ if data.fields.iter().all(|f| is_pub(&f.vis)) {
+ types::Data::Struct(introspect_struct(data, items, tokens))
+ } else {
+ types::Data::Private
+ }
+ },
+ },
Data::Union(..) => panic!("Union not supported"),
}
}
fn introspect_enum(
- ident: &Ident,
- features: types::Features,
item: &syn::DataEnum,
items: &ItemLookup,
tokens: &TokenLookup,
-) -> types::Enum {
- let variants = item
- .variants
+) -> Vec<types::Variant> {
+ item.variants
.iter()
.map(|variant| {
let fields = match &variant.fields {
@@ -89,24 +88,15 @@
types::Variant::new(variant.ident.to_string(), fields)
})
- .collect();
-
- types::Enum::new(ident.to_string(), features, variants)
+ .collect()
}
fn introspect_struct(
- ident: &Ident,
- features: types::Features,
item: &syn::DataStruct,
items: &ItemLookup,
tokens: &TokenLookup,
-) -> types::Struct {
- let all_fields_pub = item.fields.iter().all(|field| is_pub(&field.vis));
- if !all_fields_pub {
- return types::Struct::new(ident.to_string(), features, IndexMap::new());
- }
-
- let fields = match &item.fields {
+) -> IndexMap<String, types::Type> {
+ match &item.fields {
syn::Fields::Named(fields) => fields
.named
.iter()
@@ -119,9 +109,7 @@
.collect(),
syn::Fields::Unit => IndexMap::new(),
_ => panic!("Struct representation not supported"),
- };
-
- types::Struct::new(ident.to_string(), features, fields)
+ }
}
fn introspect_type(item: &syn::Type, items: &ItemLookup, tokens: &TokenLookup) -> types::Type {
diff --git a/codegen/src/types.rs b/codegen/src/types.rs
index 3cbc0b2..58ba448 100644
--- a/codegen/src/types.rs
+++ b/codegen/src/types.rs
@@ -1,4 +1,5 @@
use indexmap::IndexMap;
+use serde::{Deserialize, Deserializer};
use std::collections::BTreeMap;
use std::ops;
@@ -10,25 +11,24 @@
}
#[derive(Debug, Clone, Serialize)]
-#[serde(tag = "node", rename_all = "lowercase")]
-pub enum Node {
- Struct(Struct),
- Enum(Enum),
+pub struct Node {
+ pub ident: String,
+ pub features: Features,
+ #[serde(
+ flatten,
+ skip_serializing_if = "is_private",
+ deserialize_with = "de_data"
+ )]
+ pub data: Data,
}
#[derive(Debug, Clone, Serialize)]
-pub struct Struct {
- pub ident: String,
- pub features: Features,
- #[serde(skip_serializing_if = "IndexMap::is_empty")]
- pub fields: IndexMap<String, Type>,
-}
-
-#[derive(Debug, Clone, Serialize)]
-pub struct Enum {
- pub ident: String,
- pub features: Features,
- pub variants: Vec<Variant>,
+pub enum Data {
+ Private,
+ #[serde(rename = "fields")]
+ Struct(IndexMap<String, Type>),
+ #[serde(rename = "variants")]
+ Enum(Vec<Variant>),
}
#[derive(Debug, Clone, Serialize)]
@@ -76,42 +76,6 @@
any: Vec<String>,
}
-impl Node {
- pub fn ident(&self) -> &str {
- match self {
- Node::Struct(i) => &i.ident,
- Node::Enum(i) => &i.ident,
- }
- }
-
- pub fn features(&self) -> &Features {
- match self {
- Node::Struct(i) => &i.features,
- Node::Enum(i) => &i.features,
- }
- }
-}
-
-impl Struct {
- pub fn new(ident: String, features: Features, fields: IndexMap<String, Type>) -> Struct {
- Struct {
- ident,
- features,
- fields,
- }
- }
-}
-
-impl Enum {
- pub fn new(ident: String, features: Features, variants: Vec<Variant>) -> Enum {
- Enum {
- ident,
- features,
- variants,
- }
- }
-}
-
impl Variant {
pub fn new(ident: String, fields: Vec<Type>) -> Variant {
Variant { ident, fields }
@@ -164,3 +128,18 @@
self.any.index(index)
}
}
+
+fn is_private(data: &Data) -> bool {
+ match data {
+ Data::Private => true,
+ Data::Struct(_) | Data::Enum(_) => false,
+ }
+}
+
+fn de_data<'de, D>(deserializer: D) -> Result<Data, D::Error>
+where
+ D: Deserializer<'de>,
+{
+ let option = Option::deserialize(deserializer)?;
+ Ok(option.unwrap_or(Data::Private))
+}