-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add derive macro to strip enum of data #39
Merged
Merged
Changes from all commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
030d866
added boilerplate
jewlexx f038775
add heck dep and template
jewlexx 923fe56
fixes
jewlexx 308254d
fixes
jewlexx 8822de7
updated variant ignore
jewlexx 145297a
fixes
jewlexx 50720a8
fixes
jewlexx 107e190
fix
jewlexx 11f1dbb
fix
jewlexx dd3e75b
added test
jewlexx c967b81
fix
jewlexx 71fe83a
fixes
jewlexx 5c56d07
fix
jewlexx 21b0b3e
fixes
jewlexx 4ddac45
fix
jewlexx bc8b714
fixes
jewlexx 5a32040
fix
jewlexx 5103330
fixed ignoring variants
jewlexx 11b45f1
added todo
jewlexx 6cd39ae
added vis support
jewlexx d36d436
updated meta parsing
jewlexx 33bc53a
updated strip enum macro
jewlexx cea85c5
updates and fixes
jewlexx e6bda77
fixed stripped meta passing
jewlexx 29c4b82
fixed missing meta
jewlexx bdd2808
fixed meta parsing
jewlexx 4ab8954
fixed merge conflicts
jewlexx d513acf
updated deps
jewlexx 27a5075
fixes
jewlexx 9d8a461
removed inherited meta
jewlexx 6f634db
handle errors for variant attributes parsing
jewlexx 722cdf5
update error handling in enum strip
jewlexx fd88940
fixes
jewlexx 53cdd70
remove heck dependency
jewlexx File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
use proc_macro2::{Ident, TokenStream}; | ||
use proc_macro_error2::{abort, abort_call_site}; | ||
use quote::{quote, ToTokens}; | ||
use syn::{spanned::Spanned, DeriveInput, Meta, Variant, Visibility}; | ||
|
||
fn ignore_variant(variant: &Variant) -> bool { | ||
variant.attrs.iter().any(|attr| match attr.meta { | ||
syn::Meta::List(ref list) if list.path.is_ident("stripped") => { | ||
let mut ignored = false; | ||
|
||
let list_parser = syn::meta::parser(|meta| { | ||
if meta.path.is_ident("ignore") { | ||
ignored = true; | ||
Ok(()) | ||
} else { | ||
Err(meta.error("unsupported property")) | ||
} | ||
}); | ||
|
||
if let Err(err) = list.parse_args_with(list_parser) { | ||
abort! { | ||
err.span(), | ||
"Failed to parse attribute: {}", err; | ||
help = "Only supported properties on enum variants are `ignore`" | ||
} | ||
} | ||
|
||
ignored | ||
} | ||
_ => abort!( | ||
attr.span(), | ||
"Expected list-style (i.e #[stripped(...)]), found other style attribute macro" | ||
), | ||
}) | ||
} | ||
|
||
struct StrippedData { | ||
ident: Ident, | ||
variants: Vec<TokenStream>, | ||
meta: Vec<Meta>, | ||
vis: Visibility, | ||
} | ||
|
||
// struct MetaArgs { | ||
// meta: Vec<Expr>, | ||
// } | ||
|
||
// impl Parse for MetaArgs { | ||
// fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> { | ||
// input.peek3(token) | ||
// } | ||
// } | ||
|
||
pub fn strip_enum(ast: &mut DeriveInput) -> TokenStream { | ||
let data = &ast.data; | ||
let attrs = &mut ast.attrs; | ||
|
||
let info: StrippedData = match data { | ||
syn::Data::Enum(ref e) => { | ||
let variants = e | ||
.variants | ||
.iter() | ||
.filter_map(|variant| { | ||
if ignore_variant(variant) { | ||
None | ||
} else { | ||
Some(variant.ident.to_token_stream()) | ||
} | ||
}) | ||
.collect::<Vec<_>>(); | ||
|
||
let default_ident = { | ||
let ident = ast.ident.clone(); | ||
let span = ident.span(); | ||
move || Ident::new(&format!("{ident}Stripped"), span) | ||
}; | ||
|
||
let new_ident = if let Some(info_attr_pos) = attrs | ||
.iter() | ||
.position(|attr| attr.path().is_ident("stripped")) | ||
{ | ||
let info_attr = attrs.remove(info_attr_pos); | ||
|
||
let mut new_ident: Option<Ident> = None; | ||
|
||
let ident_parser = syn::meta::parser(|meta| { | ||
if meta.path.is_ident("ident") { | ||
new_ident = Some(meta.value()?.parse()?); | ||
Ok(()) | ||
} else { | ||
Err(meta.error("unsupported property")) | ||
} | ||
}); | ||
|
||
if let Err(err) = info_attr.parse_args_with(ident_parser) { | ||
abort! { | ||
err.span(), | ||
"Failed to parse attribute: {}", err; | ||
help = "Only supported properties on enum definitions are `ident`" | ||
} | ||
} | ||
|
||
new_ident.unwrap_or_else(default_ident) | ||
} else { | ||
default_ident() | ||
}; | ||
|
||
let meta_list: Vec<syn::Meta> = attrs | ||
.iter() | ||
.filter(|attr| attr.path().is_ident("stripped_meta")) | ||
.flat_map(|meta_attr| match &meta_attr.meta { | ||
Meta::List(meta_data) => match meta_data.parse_args::<syn::Meta>() { | ||
Ok(meta) => vec![meta], | ||
Err(err) => { | ||
abort! { | ||
err.span(), | ||
"Failed to parse specified metadata: {}", err; | ||
help = "Make sure the provided arguments are in the form of Rust metadata. (i.e the tokens contained within `#[...]`)" | ||
} | ||
} | ||
}, | ||
// Meta::NameValue(MetaNameValue { | ||
// value: | ||
// syn::Expr::Lit(syn::ExprLit { | ||
// lit: syn::Lit::Str(path), | ||
// .. | ||
// }), | ||
// .. | ||
// }) => { | ||
// if &path.value() == "inherit" { | ||
// attrs | ||
// .iter() | ||
// .filter(|attr| !attr.path().is_ident("stripped_meta")) | ||
// .map(|attr| attr.meta.clone()) | ||
// .collect() | ||
// } else { | ||
// abort!(path.span(), "Expected `inherit`"); | ||
// } | ||
// } | ||
_ => abort!( | ||
meta_attr.span(), | ||
"Expected #[stripped_meta(...)]. Found other style attribute." | ||
), | ||
}) | ||
.collect(); | ||
|
||
StrippedData { | ||
ident: new_ident, | ||
variants, | ||
meta: meta_list, | ||
vis: ast.vis.clone(), | ||
} | ||
} | ||
_ => abort_call_site!("`Strip` can only be derived for enums"), | ||
}; | ||
|
||
let StrippedData { | ||
ident, | ||
variants, | ||
meta, | ||
vis, | ||
} = info; | ||
|
||
// panic!("{:?}", meta); | ||
|
||
quote! { | ||
#(#[#meta])* | ||
#vis enum #ident { | ||
#(#variants),* | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
#![allow(dead_code)] | ||
|
||
use std::fmt::Display; | ||
|
||
use strum::{Display, EnumIter, IntoEnumIterator}; | ||
|
||
use quork_proc::Strip; | ||
|
||
pub fn enum_to_string<T: IntoEnumIterator + Display>() -> String { | ||
T::iter().map(|v| v.to_string()).collect::<String>() | ||
} | ||
|
||
struct DummyStruct; | ||
|
||
#[derive(Strip)] | ||
#[stripped_meta(derive(EnumIter, Display))] | ||
#[stripped_meta(strum(serialize_all = "kebab-case"))] | ||
enum EnumWithData { | ||
Test1(DummyStruct), | ||
Test2(DummyStruct), | ||
} | ||
|
||
#[test] | ||
fn has_all_variants() { | ||
let variants = enum_to_string::<EnumWithDataStripped>(); | ||
|
||
assert_eq!(variants, "test1test2"); | ||
} | ||
|
||
#[derive(Strip)] | ||
#[stripped_meta(derive(EnumIter, Display))] | ||
#[stripped_meta(strum(serialize_all = "kebab-case"))] | ||
enum EnumExclude { | ||
Test1(DummyStruct), | ||
#[stripped(ignore)] | ||
Test2(DummyStruct), | ||
Test3(DummyStruct), | ||
} | ||
|
||
#[derive(Strip)] | ||
#[stripped_meta(derive(EnumIter))] | ||
#[stripped_meta(strum(serialize_all = "kebab-case"))] | ||
enum EnumWithInherit { | ||
Test1(DummyStruct), | ||
} | ||
|
||
#[derive(Strip)] | ||
#[stripped_meta(derive(EnumIter))] | ||
#[stripped_meta(strum(serialize_all = "kebab-case"))] | ||
#[stripped(ident = IChoseThisIdent)] | ||
enum EnumWithCustomIdent { | ||
Test1(DummyStruct), | ||
} | ||
|
||
#[test] | ||
fn excludes_no_hook_variant() { | ||
let variants = enum_to_string::<EnumExcludeStripped>(); | ||
|
||
assert_eq!(variants, "test1test3"); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Inheritance functionality is commented out and needs implementation
Based on the code inspection:
strip_enum.rs
(visible in the commented block containinginherit
logic)EnumWithInherit
expecting this functionalityThis confirms the original review comment's observation. The feature is incomplete as the implementation is commented out while the test exists.
🔗 Analysis chain
Verify inheritance functionality implementation.
The test case exists for enum inheritance, but the corresponding implementation appears to be commented out in
strip_enum.rs
(lines 122-139). Either implement the inheritance functionality or remove the test case.Let me check the implementation details in the
strip_enum.rs
file.Let me check if there are any active implementations or tests related to inheritance functionality.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 48
Script:
Length of output: 915
Script:
Length of output: 780