Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 15 additions & 21 deletions tasks/ast_codegen/src/generators/ast_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,32 +94,26 @@ pub fn process_types(def: &TypeDef, _: &LateCtx) -> Vec<(Ident, Type)> {
TypeDef::Enum(enum_) => enum_
.variants
.iter()
// .map(|it| (it, get_visit_markers(&it.attrs).transpose().unwrap()))
.filter(|it| it.markers.visit.as_ref().is_some_and(|mk| mk.visit_as.is_some()))
.filter_map(|var| {
var.markers.visit.as_ref().map(|markers| {
let field = var.fields.first().unwrap();
let type_name = field.typ.name().inner_name();
(
markers.visit_as.clone().expect("Already checked"),
parse_quote!(#type_name<'a>),
)
})
.filter(|it| it.markers.visit.visit_as.is_some())
.map(|var| {
let field = var.fields.first().unwrap();
let type_name = field.typ.name().inner_name();
(
var.markers.visit.visit_as.clone().expect("Already checked"),
parse_quote!(#type_name<'a>),
)
})
.collect_vec(),
TypeDef::Struct(struct_) => struct_
.fields
.iter()
// .map(|it| (it, get_visit_markers(&it.attrs).transpose().unwrap()))
.filter(|it| it.markers.visit.as_ref().is_some_and(|mk| mk.visit_as.is_some()))
.filter_map(|field| {
field.markers.visit.as_ref().map(|markers| {
let type_name = field.typ.name().inner_name().to_ident();
(
markers.visit_as.clone().expect("Already checked"),
parse_quote!(#type_name<'a>),
)
})
.filter(|it| it.markers.visit.visit_as.is_some())
.map(|field| {
let type_name = field.typ.name().inner_name().to_ident();
(
field.markers.visit.visit_as.clone().expect("Already checked"),
parse_quote!(#type_name<'a>),
)
})
.collect_vec(),
};
Expand Down
24 changes: 9 additions & 15 deletions tasks/ast_codegen/src/generators/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use syn::{parse_quote, Ident};
use crate::{
codegen::LateCtx,
generators::ast_kind::BLACK_LIST as KIND_BLACK_LIST,
markers::{ScopeMarkers, VisitArg, VisitMarkers},
markers::VisitArg,
output,
schema::{EnumDef, GetIdent, StructDef, ToType, TypeDef},
util::{StrExt, ToIdent, TokenStreamExt, TypeWrapper},
Expand Down Expand Up @@ -331,7 +331,7 @@ impl<'a> VisitBuilder<'a> {
.variants
.iter()
.filter(|var| {
if var.markers.visit.as_ref().is_some_and(|mk| mk.ignore) {
if var.markers.visit.ignore {
// We are ignoring some variants so the match is no longer exhaustive.
non_exhaustive = true;
false
Expand All @@ -356,10 +356,10 @@ impl<'a> VisitBuilder<'a> {
let (args_def, args) = var
.markers
.visit
.as_ref()
.map(|mk| mk.visit_args.clone().unwrap_or_default())
.visit_args
.clone()
.unwrap_or_default()
.into_iter()
.flatten()
.fold((Vec::new(), Vec::new()), Self::visit_args_fold);
let body = quote!(visitor.#visit(it #(#args)*));
let body = if args_def.is_empty() {
Expand Down Expand Up @@ -507,17 +507,11 @@ impl<'a> VisitBuilder<'a> {
}
let typ_wrapper = &analysis.wrapper;
let markers = &field.markers;
let visit_as = markers.visit.as_ref().and_then(|mk| mk.visit_as.clone());
let visit_args = markers.visit.as_ref().and_then(|mk| mk.visit_args.clone());
let visit_as = markers.visit.visit_as.clone();
let visit_args = markers.visit.visit_args.clone();

let have_enter_scope = markers
.scope
.as_ref()
.is_some_and(|it| matches!(it, ScopeMarkers { enter_before: true }));
let have_enter_node = markers
.visit
.as_ref()
.is_some_and(|it| matches!(it, VisitMarkers { enter_before: true, .. }));
let have_enter_scope = markers.scope.enter_before;
let have_enter_node = markers.visit.enter_before;

let (args_def, args) = visit_args
.map(|it| it.into_iter().fold((Vec::new(), Vec::new()), Self::visit_args_fold))
Expand Down
84 changes: 45 additions & 39 deletions tasks/ast_codegen/src/markers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,20 @@ pub struct VisitMarkers {
}

/// A struct representing `#[scope(...)]` markers
#[derive(Debug)]
#[derive(Default, Debug)]
pub struct ScopeMarkers {
pub enter_before: bool,
}

/// A struct representing the `#[scope(...)]` attribute.
#[derive(Debug, Default)]
pub struct ScopeAttr {
pub struct ScopeAttribute {
pub r#if: Option<Expr>,
pub flags: Option<Expr>,
pub strict_if: Option<Expr>,
}

impl Parse for ScopeAttr {
impl Parse for ScopeAttribute {
fn parse(input: ParseStream) -> Result<Self, syn::Error> {
let parsed = input.parse_terminated(CommonAttribute::parse, Token![,])?;
Ok(parsed.into_iter().fold(Self::default(), |mut acc, CommonAttribute { ident, args }| {
Expand Down Expand Up @@ -110,7 +110,7 @@ impl Parse for CommonAttribute {
}
}

pub fn get_visit_markers<'a, I>(attrs: I) -> Option<crate::Result<VisitMarkers>>
pub fn get_visit_markers<'a, I>(attrs: I) -> crate::Result<VisitMarkers>
where
I: IntoIterator<Item = &'a Attribute>,
{
Expand All @@ -127,36 +127,39 @@ where
"For now we only accept one `#[visit]` marker per field/variant, Please merge them together!"
);

attr.map(|attr| {
let mut visit_as = None;
let mut visit_args = None;
let mut enter_before = false;
let mut ignore = false;
let nested =
attr.parse_args_with(Punctuated::<CommonAttribute, Token![,]>::parse_terminated);
nested
.map(|nested| {
for com in nested {
if com.ident == "args" {
visit_args = Some(parse2(com.args).unwrap());
} else if com.ident == "as" {
visit_as =
Some(parse2(com.args).expect("Invalid `#[visit[as(...)]]` input!"));
} else if com.ident == "enter_before" {
enter_before = true;
} else if com.ident == "ignore" {
ignore = true;
} else {
panic!("Invalid `#[visit(...)]` input!")
attr.map_or_else(
|| Ok(VisitMarkers::default()),
|attr| {
let mut visit_as = None;
let mut visit_args = None;
let mut enter_before = false;
let mut ignore = false;
let nested =
attr.parse_args_with(Punctuated::<CommonAttribute, Token![,]>::parse_terminated);
nested
.map(|nested| {
for com in nested {
if com.ident == "args" {
visit_args = Some(parse2(com.args).unwrap());
} else if com.ident == "as" {
visit_as =
Some(parse2(com.args).expect("Invalid `#[visit[as(...)]]` input!"));
} else if com.ident == "enter_before" {
enter_before = true;
} else if com.ident == "ignore" {
ignore = true;
} else {
panic!("Invalid `#[visit(...)]` input!")
}
}
}
})
.map(|()| VisitMarkers { visit_as, visit_args, enter_before, ignore })
.normalize()
})
})
.map(|()| VisitMarkers { visit_as, visit_args, enter_before, ignore })
.normalize()
},
)
}

pub fn get_scope_markers<'a, I>(attrs: I) -> Option<crate::Result<ScopeMarkers>>
pub fn get_scope_markers<'a, I>(attrs: I) -> crate::Result<ScopeMarkers>
where
I: IntoIterator<Item = &'a Attribute>,
{
Expand All @@ -173,14 +176,17 @@ where
"For now we only accept one `#[scope]` marker per field/variant, Please merge them together!"
);

attr.map(|attr| {
attr.parse_args_with(Ident::parse)
.map(|id| ScopeMarkers { enter_before: id == "enter_before" })
.normalize()
})
attr.map_or_else(
|| Ok(ScopeMarkers::default()),
|attr| {
attr.parse_args_with(Ident::parse)
.map(|id| ScopeMarkers { enter_before: id == "enter_before" })
.normalize()
},
)
}

pub fn get_scope_attr<'a, I>(attrs: I) -> Option<crate::Result<ScopeAttr>>
pub fn get_scope_attribute<'a, I>(attrs: I) -> Option<crate::Result<ScopeAttribute>>
where
I: IntoIterator<Item = &'a Attribute>,
{
Expand All @@ -189,9 +195,9 @@ where
debug_assert!(attr.path().is_ident("scope"));
let result = if matches!(attr.meta, Meta::Path(_)) {
// empty `#[scope]`.
Ok(ScopeAttr::default())
Ok(ScopeAttribute::default())
} else {
attr.parse_args_with(ScopeAttr::parse)
attr.parse_args_with(ScopeAttribute::parse)
};

result.normalize()
Expand Down
8 changes: 4 additions & 4 deletions tasks/ast_codegen/src/schema/defs.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use serde::Serialize;

use crate::{
markers::{ScopeAttr, ScopeMarkers, VisitMarkers},
markers::{ScopeAttribute, ScopeMarkers, VisitMarkers},
util::{ToIdent, TypeAnalysis, TypeWrapper},
TypeId,
};
Expand Down Expand Up @@ -220,15 +220,15 @@ impl TypeRef {

#[derive(Debug)]
pub struct OuterMarkers {
pub scope: Option<ScopeAttr>,
pub scope: Option<ScopeAttribute>,
}

#[derive(Debug, Serialize)]
pub struct InnerMarkers {
/// marker that hints to fold span in here
pub span: bool,
#[serde(skip)]
pub visit: Option<VisitMarkers>,
pub visit: VisitMarkers,
#[serde(skip)]
pub scope: Option<ScopeMarkers>,
pub scope: ScopeMarkers,
}
8 changes: 4 additions & 4 deletions tasks/ast_codegen/src/schema/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use serde::Serialize;
use crate::{
codegen,
layout::KnownLayout,
markers::{get_scope_attr, get_scope_markers, get_visit_markers},
markers::{get_scope_attribute, get_scope_markers, get_visit_markers},
rust_ast as rust,
util::{unexpanded_macro_err, TypeExt},
Result, TypeId,
Expand Down Expand Up @@ -103,14 +103,14 @@ impl<'a> IntoIterator for &'a Schema {
}

fn parse_outer_markers(attrs: &Vec<syn::Attribute>) -> Result<OuterMarkers> {
Ok(OuterMarkers { scope: get_scope_attr(attrs).transpose()? })
Ok(OuterMarkers { scope: get_scope_attribute(attrs).transpose()? })
}

fn parse_inner_markers(attrs: &Vec<syn::Attribute>) -> Result<InnerMarkers> {
Ok(InnerMarkers {
span: attrs.iter().any(|a| a.path().is_ident("span")),
visit: get_visit_markers(attrs).transpose()?,
scope: get_scope_markers(attrs).transpose()?,
visit: get_visit_markers(attrs)?,
scope: get_scope_markers(attrs)?,
})
}

Expand Down