Skip to content

Commit

Permalink
Clean up some code
Browse files Browse the repository at this point in the history
  • Loading branch information
viktorlott committed Jan 21, 2023
1 parent f18b836 commit e48c6e6
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 41 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ repository = "https://github.com/viktorlott/typed"
proc-macro2 = "1.0.49"
quote = "1.0.23"
rustfmt = "0.10.0"
syn = { version = "1.0.107", features = [ "visit", "full" ]}
syn = { version = "1.0.107", features = ["visit", "full"] }

[lib]
proc-macro = true
Expand Down
94 changes: 57 additions & 37 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ use syn::{
Attribute, Fields, Generics, Ident, Token, Type, Visibility,
};



struct TypeModule {
attrs: Vec<Attribute>,
vis: Visibility,
Expand Down Expand Up @@ -61,7 +59,7 @@ struct Source {
struct FieldTypeGenerics(HashSet<Ident>);

impl FieldTypeGenerics {
fn get_idents(ty: &Type) -> Self {
fn from(ty: &Type) -> Self {
let mut field_type_generics = FieldTypeGenerics(<_>::default());
visit_type(&mut field_type_generics, ty);
field_type_generics
Expand All @@ -79,25 +77,29 @@ impl<'ast> Visit<'ast> for FieldTypeGenerics {
impl Parse for TypeModule {
fn parse(input: ParseStream) -> syn::Result<Self> {
let code = format_code(input.to_string());
let ident = ident!("core");

let mut attrs: Vec<Attribute> = input.call(Attribute::parse_outer)?;
let vis: Visibility = input.parse()?;
let struct_token: Token![struct] = input.parse()?;
let name: Ident = input.parse()?;
let generics: Generics = input.parse()?;


let source = new!(Source => string[name], code);

let mut type_decls: Vec<TypeAlias> = Vec::new();
let struct_doc = doc_struct(
source.name.as_str(),
source.code.as_str()
);

attrs.push(parse_quote!(#[doc = #struct_doc]));

let mut type_decls: Vec<TypeAlias> = Vec::new();
let fields: Fields = parse_fields(input, |fields|
type_decls = parse_type_decls(fields, &generics, &source)
)?;

let struct_doc = doc_struct(source.name.as_str(), source.code.as_str());
attrs.push(parse_quote!(#[doc = #struct_doc]));

let ident = ident!("core");
let semi_colon = input.peek(Token![;]).then(|| input.parse().ok()).flatten();

let struct_decl = new!({
Expand All @@ -120,7 +122,11 @@ impl Parse for TypeModule {
attrs,
vis,
ident(name),
inner(new!({ type_decls, generic_decl, struct_decl }: TypeModuleInner))
inner(new!({
type_decls,
generic_decl,
struct_decl
}: TypeModuleInner))
}: Self))
}
}
Expand Down Expand Up @@ -153,16 +159,16 @@ impl ToTokens for TypeModuleInner {
let type_decls: &Vec<TypeAlias> = &self.type_decls;

let type_decls = quote!(#(#type_decls)*);

let struct_decl = &self.struct_decl;
let generic_decl = &self.generic_decl;

let inner_decls = quote!(
pub mod fields { #type_decls }
#type_decls
pub mod fields {
#type_decls
}

#type_decls
#struct_decl

#generic_decl
);

Expand All @@ -179,13 +185,19 @@ impl ToTokens for TypeAlias {
generics
} = self;

tokens.append_all(quote!( #[allow(type_alias_bounds)] #docs pub type #ident #generics = #ty;));
let type_alias = quote!( #[allow(type_alias_bounds)] #docs pub type #ident #generics = #ty;);

tokens.append_all(type_alias);
}
}

impl ToTokens for TypeGeneric {
fn to_tokens(&self, tokens: &mut TokenStream2) {
let TypeGeneric { ident: trait_ident, type_struct_ident , .. } = self;
let TypeGeneric {
ident: trait_ident,
type_struct_ident ,
..
} = self;

let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl();

Expand All @@ -195,19 +207,19 @@ impl ToTokens for TypeGeneric {

for type_alias in self.assoc_decls.iter() {
let TypeAlias {
docs, ident, ty, ..
docs,
ident,
ty,
..
} = type_alias;

assoc_decls.push(quote!(#docs type #ident;));
assoc_impl_decls.push(quote!(#docs type #ident = #ty;));
assoc_binds_decls.push(quote!(#ident = Self::#ident))
}

let mut bind_generic: Option<TokenStream2> = None;

if !assoc_binds_decls.is_empty() {
bind_generic = Some(quote!(<#(#assoc_binds_decls,)*>));
}
let bind_generic: Option<TokenStream2> = (!assoc_binds_decls.is_empty())
.then(|| quote!(<#(#assoc_binds_decls,)*>));

tokens.append_all(quote!(
pub trait #trait_ident {
Expand Down Expand Up @@ -268,28 +280,36 @@ where
Ok(Fields::Unit)
}
}
// FIXME: Refactor this please
// FIXME: Refactor this shit
fn parse_type_decls(fields: &mut Fields, generics: &Generics, source: &Source) -> Vec<TypeAlias> {
let mut type_decls: Vec<TypeAlias> = Vec::new();
let mut type_decls = Vec::<TypeAlias>::new();

let param_generics = get_generic_idents(generics);

for (index, field) in fields.iter_mut().enumerate() {
let field_type_generics = FieldTypeGenerics::get_idents(&field.ty);
// FIXME: Umm, fix this shit please
let matches: Vec<_> = param_generics.intersection(&field_type_generics.0).collect();
let hs: HashSet<_> = matches.clone().into_iter().collect();
let gens: Vec<_> = generics.type_params().filter_map(|p| hs.contains(&p.ident).then_some(p)).collect();


let field_ident = publicify_and_docify(field, source.name.as_str(), index);
let type_decl = TypeAlias::new(source.code.as_str(), &field_ident, &field.ty, {
if matches.is_empty() {
None
} else {
Some(parse_quote!(<#(#gens),*>))
let field_type_generics = FieldTypeGenerics::from(&field.ty);
let gens_matches: HashSet<_> = param_generics.intersection(&field_type_generics.0).collect();
let field_ident: Ident = publicify_and_docify(field, source.name.as_str(), index);

let type_decl = TypeAlias::new(
source.code.as_str(),
&field_ident,
&field.ty,
{
if gens_matches.is_empty() {
None
} else {
let gens: Vec<_> = generics
.type_params()
.filter_map(|p|
gens_matches
.contains(&p.ident)
.then_some(p))
.collect();
Some(parse_quote!(<#(#gens),*>))
}
}
});
);

type_decls.push(type_decl);
}
Expand Down
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ mod builder;
/// ```no_run
/// let current: Container::current = 10;
/// let buffer: Container::buffer = vec![current];
/// let another: <Container::core<u8> as Container::proto>::another = 20;
/// let another: <Container::core<u8> as Container::protocol>::another = 20;
/// let container: Container::core<u8> =
/// Container::core {
/// current,
Expand All @@ -32,8 +32,8 @@ mod builder;
/// - It's also possible to use it as following:
/// ```no_run
/// trait Trait: Container::protocol {
/// fn retrieve(&self) -> Container::proto::buffer;
/// fn extend(&mut self, val: Container::proto::another);
/// fn retrieve(&self) -> Container::protocol::buffer;
/// fn extend(&mut self, val: Container::protocol::another);
/// }
/// ```
///
Expand Down

0 comments on commit e48c6e6

Please sign in to comment.