diff options
Diffstat (limited to 'macros/src/lib.rs')
-rw-r--r-- | macros/src/lib.rs | 56 |
1 files changed, 40 insertions, 16 deletions
diff --git a/macros/src/lib.rs b/macros/src/lib.rs index a420d56..42f7565 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs | |||
@@ -8,13 +8,13 @@ use syn::{ | |||
8 | parse::{Parse, ParseStream, Result as ParseResult}, | 8 | parse::{Parse, ParseStream, Result as ParseResult}, |
9 | parse_macro_input, | 9 | parse_macro_input, |
10 | punctuated::Punctuated, | 10 | punctuated::Punctuated, |
11 | Ident, ItemStruct, Lit, Path, Token, | 11 | Expr, Ident, ItemStruct, Lit, Token, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | struct KeyValue { | 14 | struct KeyValue { |
15 | key: Ident, | 15 | key: Ident, |
16 | _eq: Token![=], | 16 | _eq: Token![=], |
17 | value: Lit, | 17 | value: Expr, |
18 | } | 18 | } |
19 | 19 | ||
20 | impl Parse for KeyValue { | 20 | impl Parse for KeyValue { |
@@ -27,7 +27,7 @@ impl Parse for KeyValue { | |||
27 | } | 27 | } |
28 | } | 28 | } |
29 | 29 | ||
30 | struct LintMeta(HashMap<Ident, Lit>); | 30 | struct LintMeta(HashMap<Ident, Expr>); |
31 | 31 | ||
32 | impl Parse for LintMeta { | 32 | impl Parse for LintMeta { |
33 | fn parse(input: ParseStream) -> ParseResult<Self> { | 33 | fn parse(input: ParseStream) -> ParseResult<Self> { |
@@ -54,11 +54,13 @@ fn generate_meta_impl(struct_name: &Ident, meta: &LintMeta) -> TokenStream2 { | |||
54 | let name_fn = generate_name_fn(meta); | 54 | let name_fn = generate_name_fn(meta); |
55 | let note_fn = generate_note_fn(meta); | 55 | let note_fn = generate_note_fn(meta); |
56 | let match_with_fn = generate_match_with_fn(meta); | 56 | let match_with_fn = generate_match_with_fn(meta); |
57 | let match_kind = generate_match_kind(meta); | ||
57 | quote! { | 58 | quote! { |
58 | impl Metadata for #struct_name { | 59 | impl Metadata for #struct_name { |
59 | #name_fn | 60 | #name_fn |
60 | #note_fn | 61 | #note_fn |
61 | #match_with_fn | 62 | #match_with_fn |
63 | #match_kind | ||
62 | } | 64 | } |
63 | } | 65 | } |
64 | } | 66 | } |
@@ -68,11 +70,16 @@ fn generate_name_fn(meta: &LintMeta) -> TokenStream2 { | |||
68 | .0 | 70 | .0 |
69 | .get(&format_ident!("name")) | 71 | .get(&format_ident!("name")) |
70 | .unwrap_or_else(|| panic!("`name` not present")); | 72 | .unwrap_or_else(|| panic!("`name` not present")); |
71 | quote! { | 73 | if let syn::Expr::Lit(name_lit) = name { |
72 | fn name(&self) -> &str { | 74 | if let Lit::Str(name_str) = &name_lit.lit { |
73 | #name | 75 | return quote! { |
76 | fn name(&self) -> &str { | ||
77 | #name_str | ||
78 | } | ||
79 | }; | ||
74 | } | 80 | } |
75 | } | 81 | } |
82 | panic!("Invalid value for `name`"); | ||
76 | } | 83 | } |
77 | 84 | ||
78 | fn generate_note_fn(meta: &LintMeta) -> TokenStream2 { | 85 | fn generate_note_fn(meta: &LintMeta) -> TokenStream2 { |
@@ -80,11 +87,16 @@ fn generate_note_fn(meta: &LintMeta) -> TokenStream2 { | |||
80 | .0 | 87 | .0 |
81 | .get(&format_ident!("note")) | 88 | .get(&format_ident!("note")) |
82 | .unwrap_or_else(|| panic!("`note` not present")); | 89 | .unwrap_or_else(|| panic!("`note` not present")); |
83 | quote! { | 90 | if let syn::Expr::Lit(note_lit) = note { |
84 | fn note(&self) -> &str { | 91 | if let Lit::Str(note_str) = ¬e_lit.lit { |
85 | #note | 92 | return quote! { |
93 | fn note(&self) -> &str { | ||
94 | #note_str | ||
95 | } | ||
96 | }; | ||
86 | } | 97 | } |
87 | } | 98 | } |
99 | panic!("Invalid value for `note`"); | ||
88 | } | 100 | } |
89 | 101 | ||
90 | fn generate_match_with_fn(meta: &LintMeta) -> TokenStream2 { | 102 | fn generate_match_with_fn(meta: &LintMeta) -> TokenStream2 { |
@@ -92,18 +104,30 @@ fn generate_match_with_fn(meta: &LintMeta) -> TokenStream2 { | |||
92 | .0 | 104 | .0 |
93 | .get(&format_ident!("match_with")) | 105 | .get(&format_ident!("match_with")) |
94 | .unwrap_or_else(|| panic!("`match_with` not present")); | 106 | .unwrap_or_else(|| panic!("`match_with` not present")); |
95 | if let Lit::Str(match_with) = match_with_lit { | 107 | if let syn::Expr::Path(match_path) = match_with_lit { |
96 | let path: Path = match_with | ||
97 | .parse() | ||
98 | .ok() | ||
99 | .unwrap_or_else(|| panic!("`match_with` does not contain valid path")); | ||
100 | quote! { | 108 | quote! { |
101 | fn match_with(&self, with: &SyntaxKind) -> bool { | 109 | fn match_with(&self, with: &SyntaxKind) -> bool { |
102 | *with == #path | 110 | #match_path == *with |
111 | } | ||
112 | } | ||
113 | } else { | ||
114 | panic!("`match_with` has non-path value") | ||
115 | } | ||
116 | } | ||
117 | |||
118 | fn generate_match_kind(meta: &LintMeta) -> TokenStream2 { | ||
119 | let match_with_lit = meta | ||
120 | .0 | ||
121 | .get(&format_ident!("match_with")) | ||
122 | .unwrap_or_else(|| panic!("`match_with` not present")); | ||
123 | if let syn::Expr::Path(match_path) = match_with_lit { | ||
124 | quote! { | ||
125 | fn match_kind(&self) -> SyntaxKind { | ||
126 | #match_path | ||
103 | } | 127 | } |
104 | } | 128 | } |
105 | } else { | 129 | } else { |
106 | panic!("`match_with` has non-literal value") | 130 | panic!("`match_with` has non-path value") |
107 | } | 131 | } |
108 | } | 132 | } |
109 | 133 | ||