Skip to content

Commit 436f14b

Browse files
author
caozheng
committed
04
1 parent 46b43f7 commit 436f14b

File tree

2 files changed

+32
-15
lines changed

2 files changed

+32
-15
lines changed

sorted/src/lib.rs

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,53 @@
1-
use proc_macro2::TokenStream;
1+
use proc_macro2::{Ident, TokenStream};
22
use quote::quote;
33
use syn::{Item, parse_macro_input};
44
use syn::spanned::Spanned;
55

6-
fn check(args: TokenStream, input: Item) -> TokenStream{
6+
fn check_enum_order(args: &TokenStream, input: &Item) -> syn::Result<()>{
7+
let mut idents = vec![];
78
match input{
89
Item::Enum(ref item) =>{
9-
let mut names: Vec<String> = vec![];
1010
for variant in item.variants.iter() {
11-
let cur_name = variant.ident.to_string();
12-
for name in names.iter() {
13-
if &cur_name < name{
14-
let msg = format!("{} should sort before {}", cur_name, name);
15-
return syn::Error::new(variant.span(), msg).into_compile_error();
16-
}
17-
}
18-
names.push(cur_name);
11+
idents.push(&variant.ident);
1912
}
20-
return quote! { #input }
13+
check_order(idents)
2114
},
2215
_=>{
23-
return syn::Error::new(args.span(), "expected enum or match expression").into_compile_error();
16+
Err(syn::Error::new(args.span(), "expected enum or match expression"))
2417
}
2518
}
2619
}
2720

21+
fn check_order(idents: Vec<&Ident>)-> syn::Result<()> {
22+
if idents.is_empty(){
23+
return Ok(());
24+
}
25+
let mut sorted = idents.clone();
26+
sorted.sort_by(|ident1, ident2| ident1.cmp(ident2));
27+
for (a, b) in idents.iter().zip(sorted.iter()) {
28+
if a.to_string() != b.to_string(){
29+
let msg = format!("{} should sort before {}", b.to_string(), a.to_string());
30+
return Err(syn::Error::new(b.span(), msg));
31+
}
32+
}
33+
34+
Ok(())
35+
}
36+
2837

2938
#[proc_macro_attribute]
3039
pub fn sorted(args: proc_macro::TokenStream, input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3140
let input = parse_macro_input!(input as Item);
3241
let args: TokenStream = args.into();
33-
check(args.into(), input).into()
42+
let mut result = TokenStream::new();
43+
match check_enum_order(&args, &input) {
44+
Ok(_) =>{},
45+
Err(err) => {
46+
result.extend(err.into_compile_error());
47+
}
48+
}
49+
result.extend(quote! { #input });
50+
result.into()
3451
}
3552

3653

sorted/tests/progress.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ fn tests() {
44
t.pass("tests/01-parse-enum.rs");
55
t.compile_fail("tests/02-not-enum.rs");
66
t.compile_fail("tests/03-out-of-order.rs");
7-
//t.compile_fail("tests/04-variants-with-data.rs");
7+
t.compile_fail("tests/04-variants-with-data.rs");
88
//t.compile_fail("tests/05-match-expr.rs");
99
//t.compile_fail("tests/06-pattern-path.rs");
1010
//t.compile_fail("tests/07-unrecognized-pattern.rs");

0 commit comments

Comments
 (0)