(attrs: &mut Attrs<'a>, attr: &'a Attribute)
| 122 | } |
| 123 | |
| 124 | fn parse_error_attribute<'a>(attrs: &mut Attrs<'a>, attr: &'a Attribute) -> Result<()> { |
| 125 | mod kw { |
| 126 | syn::custom_keyword!(transparent); |
| 127 | syn::custom_keyword!(fmt); |
| 128 | } |
| 129 | |
| 130 | attr.parse_args_with(|input: ParseStream| { |
| 131 | let lookahead = input.lookahead1(); |
| 132 | let fmt = if lookahead.peek(LitStr) { |
| 133 | input.parse::<LitStr>()? |
| 134 | } else if lookahead.peek(kw::transparent) { |
| 135 | let kw: kw::transparent = input.parse()?; |
| 136 | if attrs.transparent.is_some() { |
| 137 | return Err(Error::new_spanned( |
| 138 | attr, |
| 139 | "duplicate #[error(transparent)] attribute", |
| 140 | )); |
| 141 | } |
| 142 | attrs.transparent = Some(Transparent { |
| 143 | original: attr, |
| 144 | span: kw.span, |
| 145 | }); |
| 146 | return Ok(()); |
| 147 | } else if lookahead.peek(kw::fmt) { |
| 148 | input.parse::<kw::fmt>()?; |
| 149 | input.parse::<Token![=]>()?; |
| 150 | let path: ExprPath = input.parse()?; |
| 151 | if attrs.fmt.is_some() { |
| 152 | return Err(Error::new_spanned( |
| 153 | attr, |
| 154 | "duplicate #[error(fmt = ...)] attribute", |
| 155 | )); |
| 156 | } |
| 157 | attrs.fmt = Some(Fmt { |
| 158 | original: attr, |
| 159 | path, |
| 160 | }); |
| 161 | return Ok(()); |
| 162 | } else { |
| 163 | return Err(lookahead.error()); |
| 164 | }; |
| 165 | |
| 166 | let args = if input.is_empty() || input.peek(Token![,]) && input.peek2(End) { |
| 167 | input.parse::<Option<Token![,]>>()?; |
| 168 | TokenStream::new() |
| 169 | } else { |
| 170 | parse_token_expr(input, false)? |
| 171 | }; |
| 172 | |
| 173 | let requires_fmt_machinery = !args.is_empty(); |
| 174 | |
| 175 | let display = Display { |
| 176 | original: attr, |
| 177 | fmt, |
| 178 | args, |
| 179 | requires_fmt_machinery, |
| 180 | has_bonus_display: false, |
| 181 | infinite_recursive: false, |
no test coverage detected