Skip to content

Commit 2d42a24

Browse files
committed
feat: better error handling in proc-macros
1 parent ea67c62 commit 2d42a24

5 files changed

Lines changed: 70 additions & 45 deletions

File tree

Cargo.lock

Lines changed: 52 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

noshell-macros/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ proc-macro = true
1515

1616
[dependencies]
1717
darling = "0.20.10"
18+
proc-macro-error = "1.0.4"
1819
proc-macro2 = "1.0.94"
1920
quote = "1.0.39"
2021
syn = { version = "2.0.99", features = ["full"] }

noshell-macros/src/derive.rs

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use std::collections::HashSet;
44

5+
use proc_macro_error::abort_call_site;
56
use proc_macro2::TokenStream;
67
use quote::{format_ident, quote, quote_spanned};
78
use syn::ext::IdentExt;
@@ -13,28 +14,24 @@ use syn::{Ident, Type};
1314

1415
use crate::arg::MetaArg;
1516
use crate::attr::{Attr, AttrKind, AttrName, AttrValue};
16-
use crate::helpers::{error, token_stream_with_error};
1717
use crate::ty::{Ty, get_inner_ty};
1818

1919
pub fn run(item: TokenStream) -> TokenStream {
20-
let input: DeriveInput = match syn::parse2(item.clone()) {
20+
let input: DeriveInput = match syn::parse2(item) {
2121
Ok(x) => x,
22-
Err(e) => return token_stream_with_error(item, e),
22+
Err(err) => abort_call_site!("failed to parse input, {}", err),
2323
};
2424

25-
try_run(&input).unwrap_or_else(|err| {
26-
let mut errors = TokenStream::new();
27-
error(&mut errors, &input, err.to_string());
28-
quote! {
29-
#errors
30-
}
31-
})
25+
match try_run(&input) {
26+
Ok(derived) => derived,
27+
Err(err) => abort_call_site!("failed to derive input, {}", err),
28+
}
3229
}
3330

3431
// This is the default value.
3532
const PARSED_ARGS_DEFAULT_CAPACITY: usize = 32;
3633

37-
pub fn try_run(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
34+
pub fn try_run(input: &DeriveInput) -> syn::Result<TokenStream> {
3835
let ident = &input.ident;
3936

4037
match input.data {
@@ -79,7 +76,7 @@ pub fn try_run(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
7976
}
8077
}
8178

82-
fn collect_args_meta(fields: &FieldsNamed) -> Result<Vec<MetaArg>, syn::Error> {
79+
fn collect_args_meta(fields: &FieldsNamed) -> syn::Result<Vec<MetaArg>> {
8380
let meta = fields
8481
.named
8582
.iter()
@@ -92,7 +89,7 @@ fn collect_args_meta(fields: &FieldsNamed) -> Result<Vec<MetaArg>, syn::Error> {
9289
Ok(meta)
9390
}
9491

95-
fn build_args_init(fields: &[MetaArg], ident: Ident) -> Result<TokenStream, syn::Error> {
92+
fn build_args_init(fields: &[MetaArg], ident: Ident) -> syn::Result<TokenStream> {
9693
let args = fields
9794
.iter()
9895
.map(|x| build_arg_parser(x, ident.clone()))
@@ -105,7 +102,7 @@ fn build_args_init(fields: &[MetaArg], ident: Ident) -> Result<TokenStream, syn:
105102
}})
106103
}
107104

108-
fn build_arg_parser(arg: &MetaArg, args_ident: Ident) -> Result<TokenStream, syn::Error> {
105+
fn build_arg_parser(arg: &MetaArg, args_ident: Ident) -> syn::Result<TokenStream> {
109106
let ty = &arg.ty;
110107
let inner_ty = get_inner_ty(ty);
111108

@@ -184,7 +181,7 @@ where
184181
attrs.iter().find(|&x| predicate(x))
185182
}
186183

187-
fn parse_attr_of_literal_string_with<T, P>(attr: &Attr, parser: P) -> Result<Option<T>, syn::Error>
184+
fn parse_attr_of_literal_string_with<T, P>(attr: &Attr, parser: P) -> syn::Result<Option<T>>
188185
where
189186
P: FnOnce(&LitStr) -> Result<T, syn::Error>,
190187
{
@@ -196,7 +193,7 @@ where
196193
parser(lit).map(Some)
197194
}
198195

199-
fn parse_attr_of_literal_expr_with<T, P>(attr: &Attr, parser: P) -> Result<Option<T>, syn::Error>
196+
fn parse_attr_of_literal_expr_with<T, P>(attr: &Attr, parser: P) -> syn::Result<Option<T>>
200197
where
201198
P: FnOnce(&Lit) -> Result<T, syn::Error>,
202199
{
@@ -208,7 +205,7 @@ where
208205
parser(lit).map(Some)
209206
}
210207

211-
fn parse_noshell_attr_limit_arg(attr: &Attr) -> Result<usize, syn::Error> {
208+
fn parse_noshell_attr_limit_arg(attr: &Attr) -> syn::Result<usize> {
212209
parse_attr_of_literal_expr_with(attr, |lit| {
213210
if let Lit::Int(val) = lit {
214211
val.base10_parse()
@@ -230,7 +227,7 @@ fn parse_noshell_attr_limit_arg(attr: &Attr) -> Result<usize, syn::Error> {
230227
})
231228
}
232229

233-
fn get_noshell_attr_limit_arg_value(attrs: &[Attr]) -> Result<Option<usize>, syn::Error> {
230+
fn get_noshell_attr_limit_arg_value(attrs: &[Attr]) -> syn::Result<Option<usize>> {
234231
if let Some(attr) = find_attr_with(attrs, |x| {
235232
x.kind == AttrKind::NoShell && x.name == Some(AttrName::Limit)
236233
}) {
@@ -240,7 +237,7 @@ fn get_noshell_attr_limit_arg_value(attrs: &[Attr]) -> Result<Option<usize>, syn
240237
Ok(None)
241238
}
242239

243-
fn parse_attr_arg_short_arg(attr: &Attr) -> Result<Option<char>, syn::Error> {
240+
fn parse_attr_arg_short_arg(attr: &Attr) -> syn::Result<Option<char>> {
244241
parse_attr_of_literal_expr_with(attr, |lit| {
245242
if let Lit::Char(val) = lit {
246243
Ok(val.value())
@@ -253,7 +250,7 @@ fn parse_attr_arg_short_arg(attr: &Attr) -> Result<Option<char>, syn::Error> {
253250
})
254251
}
255252

256-
fn parse_attr_arg_long_arg(attr: &Attr) -> Result<Option<String>, syn::Error> {
253+
fn parse_attr_arg_long_arg(attr: &Attr) -> syn::Result<Option<String>> {
257254
parse_attr_of_literal_string_with(attr, |lit| Ok(lit.value()))
258255
}
259256

noshell-macros/src/helpers.rs

Lines changed: 0 additions & 13 deletions
This file was deleted.

noshell-macros/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use proc_macro::TokenStream;
77
mod arg;
88
mod attr;
99
mod derive;
10-
mod helpers;
1110
mod ty;
1211

1312
#[cfg(test)]

0 commit comments

Comments
 (0)