2
2
//! attached to trait items.
3
3
4
4
use proc_macro2:: { Delimiter , TokenTree } ;
5
- use proc_macro_error:: { abort, emit_error} ;
6
5
use syn:: {
7
6
spanned:: Spanned ,
8
7
visit_mut:: { visit_item_trait_mut, VisitMut } ,
9
- Attribute , Meta , TraitItem ,
8
+ Attribute , Error , Meta , TraitItem ,
10
9
} ;
11
10
12
11
use crate :: proxy:: { parse_types, ProxyType } ;
13
12
14
13
/// Removes all `#[auto_impl]` attributes that are attached to methods of the
15
14
/// given trait.
16
- pub ( crate ) fn remove_our_attrs ( trait_def : & mut syn:: ItemTrait ) {
17
- struct AttrRemover ;
15
+ pub ( crate ) fn remove_our_attrs ( trait_def : & mut syn:: ItemTrait ) -> syn :: Result < ( ) > {
16
+ struct AttrRemover ( syn :: Result < ( ) > ) ;
18
17
impl VisitMut for AttrRemover {
19
18
fn visit_trait_item_mut ( & mut self , item : & mut TraitItem ) {
20
19
let item_span = item. span ( ) ;
@@ -23,26 +22,46 @@ pub(crate) fn remove_our_attrs(trait_def: &mut syn::ItemTrait) {
23
22
TraitItem :: Const ( c) => ( & mut c. attrs , false ) ,
24
23
TraitItem :: Type ( t) => ( & mut t. attrs , false ) ,
25
24
TraitItem :: Macro ( m) => ( & mut m. attrs , false ) ,
26
- _ => abort ! (
27
- item. span( ) ,
28
- "encountered unexpected `TraitItem`, cannot handle that, sorry!" ;
29
- note = "auto-impl supports only methods, consts, types and macros currently" ;
30
- ) ,
25
+ _ => {
26
+ let err = syn:: Error :: new (
27
+ item. span ( ) ,
28
+ "encountered unexpected `TraitItem`, cannot handle that, sorry!" ,
29
+ ) ;
30
+
31
+ if let Err ( ref mut current_err) = self . 0 {
32
+ current_err. combine ( err) ;
33
+ } else {
34
+ self . 0 = Err ( err) ;
35
+ } ;
36
+
37
+ return ;
38
+ }
31
39
} ;
32
40
33
41
// Make sure non-methods do not have our attributes.
34
42
if !is_method && attrs. iter ( ) . any ( is_our_attr) {
35
- emit_error ! (
43
+ let err = syn :: Error :: new (
36
44
item_span,
37
45
"`#[auto_impl]` attributes are only allowed on methods" ,
38
46
) ;
47
+
48
+ if let Err ( ref mut current_err) = self . 0 {
49
+ current_err. combine ( err) ;
50
+ } else {
51
+ self . 0 = Err ( err) ;
52
+ } ;
53
+
54
+ return ;
39
55
}
40
56
41
57
attrs. retain ( |a| !is_our_attr ( a) ) ;
42
58
}
43
59
}
44
60
45
- visit_item_trait_mut ( & mut AttrRemover , trait_def) ;
61
+ let mut visitor = AttrRemover ( Ok ( ( ) ) ) ;
62
+ visit_item_trait_mut ( & mut visitor, trait_def) ;
63
+
64
+ visitor. 0
46
65
}
47
66
48
67
/// Checks if the given attribute is "our" attribute. That means that it's path
@@ -55,7 +74,7 @@ pub(crate) fn is_our_attr(attr: &Attribute) -> bool {
55
74
/// attributes. If it's invalid, an error is emitted and `Err(())` is returned.
56
75
/// You have to make sure that `attr` is one of our attrs with `is_our_attr`
57
76
/// before calling this function!
58
- pub ( crate ) fn parse_our_attr ( attr : & Attribute ) -> Result < OurAttr , ( ) > {
77
+ pub ( crate ) fn parse_our_attr ( attr : & Attribute ) -> syn :: Result < OurAttr > {
59
78
assert ! ( is_our_attr( attr) ) ;
60
79
61
80
// Get the body of the attribute (which has to be a ground, because we
@@ -64,8 +83,10 @@ pub(crate) fn parse_our_attr(attr: &Attribute) -> Result<OurAttr, ()> {
64
83
let body = match & attr. meta {
65
84
Meta :: List ( list) => list. tokens . clone ( ) ,
66
85
_ => {
67
- emit_error ! ( attr. span( ) , "expected single group delimited by `()`" ) ;
68
- return Err ( ( ) ) ;
86
+ return Err ( Error :: new (
87
+ attr. span ( ) ,
88
+ "expected single group delimited by `()`" ,
89
+ ) ) ;
69
90
}
70
91
} ;
71
92
@@ -75,12 +96,13 @@ pub(crate) fn parse_our_attr(attr: &Attribute) -> Result<OurAttr, ()> {
75
96
let name = match it. next ( ) {
76
97
Some ( TokenTree :: Ident ( x) ) => x,
77
98
Some ( other) => {
78
- emit_error ! ( other. span( ) , "expected ident, found '{}'" , other) ;
79
- return Err ( ( ) ) ;
99
+ return Err ( Error :: new (
100
+ other. span ( ) ,
101
+ format_args ! ( "expected ident, found '{}'" , other) ,
102
+ ) ) ;
80
103
}
81
104
None => {
82
- emit_error ! ( attr. span( ) , "expected ident, found nothing" ) ;
83
- return Err ( ( ) ) ;
105
+ return Err ( Error :: new ( attr. span ( ) , "expected ident, found nothing" ) ) ;
84
106
}
85
107
} ;
86
108
@@ -89,21 +111,22 @@ pub(crate) fn parse_our_attr(attr: &Attribute) -> Result<OurAttr, ()> {
89
111
let params = match it. next ( ) {
90
112
Some ( TokenTree :: Group ( ref g) ) if g. delimiter ( ) == Delimiter :: Parenthesis => g. stream ( ) ,
91
113
Some ( other) => {
92
- emit_error ! (
114
+ return Err ( Error :: new (
93
115
other. span ( ) ,
94
- "expected arguments for '{}' in parenthesis `()`, found `{}`" ,
95
- name ,
96
- other ,
97
- ) ;
98
- return Err ( ( ) ) ;
116
+ format_args ! (
117
+ "expected arguments for '{}' in parenthesis `()`, found `{}`" ,
118
+ name , other
119
+ ) ,
120
+ ) ) ;
99
121
}
100
122
None => {
101
- emit_error ! (
123
+ return Err ( Error :: new (
102
124
body. span ( ) ,
103
- "expected arguments for '{}' in parenthesis `()`, found nothing" ,
104
- name,
105
- ) ;
106
- return Err ( ( ) ) ;
125
+ format_args ! (
126
+ "expected arguments for '{}' in parenthesis `()`, found nothing" ,
127
+ name,
128
+ ) ,
129
+ ) ) ;
107
130
}
108
131
} ;
109
132
@@ -112,11 +135,13 @@ pub(crate) fn parse_our_attr(attr: &Attribute) -> Result<OurAttr, ()> {
112
135
let proxy_types = parse_types ( params. into ( ) ) ;
113
136
OurAttr :: KeepDefaultFor ( proxy_types)
114
137
} else {
115
- emit_error ! (
116
- name. span( ) , "invalid attribute '{}'" , name;
117
- note = "only `keep_default_for` is supported" ;
118
- ) ;
119
- return Err ( ( ) ) ;
138
+ return Err ( Error :: new (
139
+ name. span ( ) ,
140
+ format_args ! (
141
+ "invalid attribute '{}'; only `keep_default_for` is supported" ,
142
+ name
143
+ ) ,
144
+ ) ) ;
120
145
} ;
121
146
122
147
Ok ( out)
0 commit comments