amplify_syn/
error.rs

1// Rust language amplification derive library providing multiple generic trait
2// implementations, type wrappers, derive macros and other language enhancements
3//
4// Written in 2019-2021 by
5//     Dr. Maxim Orlovsky <orlovsky@pandoracore.com>
6//
7// To the extent possible under law, the author(s) have dedicated all
8// copyright and related and neighboring rights to this software to
9// the public domain worldwide. This software is distributed without
10// any warranty.
11//
12// You should have received a copy of the MIT License
13// along with this software.
14// If not, see <https://opensource.org/licenses/MIT>.
15
16#![allow(deprecated)] // We need this at mod level to support rustc 1.26.0
17
18use std::convert::Infallible;
19use std::fmt::{self, Display, Formatter};
20
21use proc_macro2::Span;
22
23/// Errors representing inconsistency in proc macro attribute structure
24#[derive(Clone, Debug)]
25pub enum Error {
26    /// Parse error from a `syn` crate
27    Parse(syn::Error),
28
29    /// Names of two merged attributes must match each other
30    NamesDontMatch(String, String),
31
32    /// Singular argument (of form `#[attr = ...]`) has multiple occurrences
33    /// each assigned value. This is meaningless.
34    MultipleSingularValues(String),
35
36    /// Multiple literal non-string values are given for a parametrized
37    /// attribute in form of `#[attr(literal1, literal2)]`. This is
38    /// meaningless.
39    MultipleLiteralValues(String),
40
41    /// Attribute contains unsupported literal argument
42    UnsupportedLiteral(String),
43
44    /// Attribute must be in a singular form (`#[attr]` or `#[attr = ...]`)
45    SingularAttrRequired(String),
46
47    /// Attribute must be in a parametrized form (`#[attr(...)]`)
48    ParametrizedAttrRequired(String),
49
50    /// Attribute has an unknown argument
51    AttributeUnknownArgument {
52        /// Attribute name
53        attr: String,
54        /// Argument name
55        arg: String,
56    },
57
58    /// Attribute is not allowed to have argument of type `arg`
59    ArgTypeProhibited {
60        /// Attribute name
61        attr: String,
62        /// Argument name
63        arg: String,
64    },
65
66    /// Number of `arg` arguments in attribute `attr` exceeds maximum
67    ArgNumberExceedsMax {
68        /// Attribute name
69        attr: String,
70        /// Argument type name
71        type_name: String,
72        /// Number of arguments
73        no: usize,
74        /// Maximum allowed number of arguments
75        max_no: u8,
76    },
77
78    /// Attribute argument `arg` must not have a value
79    ArgMustNotHaveValue {
80        /// Attribute name
81        attr: String,
82        /// Argument name
83        arg: String,
84    },
85
86    /// Attribute must has an `arg` argument
87    ArgRequired {
88        /// Attribute name
89        attr: String,
90        /// Argument name
91        arg: String,
92    },
93
94    /// Attribute or attribute argument name (in form of `#[attr(arg = ...)]`)
95    /// must be an identifier (like `arg`) and not a path (like `std::io`)
96    ArgNameMustBeIdent,
97
98    /// The same argument name is used multiple times within parametrized
99    /// attribute (like in `#[attr(name1 = value1, name1 = value2)]`)
100    ArgNameMustBeUnique {
101        /// Attribute name
102        attr: String,
103        /// Argument name
104        arg: String,
105    },
106
107    /// Attribute or attribute argument must has a value:
108    /// `#[attr(arg = value)]`
109    ArgValueRequired {
110        /// Attribute name
111        attr: String,
112        /// Argument name
113        arg: String,
114    },
115
116    /// Attribute value type mismatch
117    ArgValueTypeMismatch {
118        /// Attribute name
119        attr: String,
120        /// Argument name
121        arg: String,
122    },
123
124    /// Parametrized attribute argument must have a literal value (string,
125    /// integer etc): `#[attr(arg = "value")]` or `#[arg = 4]`
126    ArgValueMustBeLiteral,
127
128    /// Parametrized attribute argument must be a valid type name:
129    /// `#[attr(arg = u8)]` or `#[arg = String]`
130    ArgValueMustBeType,
131
132    /// Parametrized attribute argument must be a valid rust expression:
133    /// `#[attr(arg = 2 + 2)]` or `#[arg = { u16::MAX as usize }]`
134    ArgValueMustBeExpr,
135
136    /// Parametrized attribute (in form of `#[attr(...)]`) does not
137    /// have a single value
138    ParametrizedAttrHasNoValue(String),
139
140    /// Lists nested within attribute arguments, like `#[attr(arg(...))]`
141    /// are not supported
142    #[deprecated(
143        since = "1.1.0",
144        note = "This error variant is not used anymore after the introduction of custom attribute \
145                parser"
146    )]
147    NestedListsNotSupported(String),
148}
149
150impl From<Infallible> for Error {
151    fn from(_: Infallible) -> Self { unreachable!() }
152}
153
154impl From<syn::Error> for Error {
155    fn from(err: syn::Error) -> Self { Error::Parse(err) }
156}
157
158impl From<Error> for syn::Error {
159    fn from(err: Error) -> Self { syn::Error::new(Span::call_site(), err.to_string()) }
160}
161
162impl Display for Error {
163    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
164        match self {
165            Error::Parse(err) => write!(f, "attribute parse error: {}", err),
166            Error::NamesDontMatch(name1, name2) => {
167                write!(f, "Names of two merged attributes (`{}` and `{}`) must match", name1, name2)
168            }
169            Error::MultipleSingularValues(name) => {
170                write!(f, "Multiple values assigned to `{}` attribute", name)
171            }
172            Error::MultipleLiteralValues(name) => {
173                write!(f, "Multiple literal values provided for `{}` attribute", name)
174            }
175            Error::SingularAttrRequired(name) => write!(
176                f,
177                "Attribute `{}` must be in a singular form (`#[attr]` or `#[attr = ...]`)",
178                name
179            ),
180            Error::ParametrizedAttrRequired(name) => {
181                write!(f, "Attribute `{}` must be in a parametrized form (`#[attr(...)]`)", name)
182            }
183            Error::ArgMustNotHaveValue { attr, arg } => write!(
184                f,
185                "Argument {arg} in `{attr}` attribute must not have a value",
186                attr = attr,
187                arg = arg
188            ),
189            Error::ArgTypeProhibited {
190                attr,
191                arg: type_name,
192            } => write!(f, "Attribute `{}` prohibits arguments of type `{}`", attr, type_name),
193            Error::ArgRequired { attr, arg } => write!(
194                f,
195                "Attribute `{}` requires argument `{}` to be explicitly specified",
196                attr, arg,
197            ),
198            Error::ArgNameMustBeUnique { attr, arg } => write!(
199                f,
200                "Argument names must be unique, while attribute `{}` contains multiple arguments \
201                 with name`{}`",
202                attr, arg,
203            ),
204            Error::ArgNameMustBeIdent => {
205                write!(f, "Attribute arguments must be identifiers, not paths",)
206            }
207            Error::ArgValueRequired { attr, arg } => {
208                write!(f, "Attribute `{}` requires value for argument `{}`", attr, arg)
209            }
210            Error::ArgValueMustBeLiteral => {
211                f.write_str("Attribute argument value must be a literal (string, int etc)")
212            }
213            Error::ArgValueMustBeType => {
214                f.write_str("Attribute value for must be a valid type name")
215            }
216            Error::ArgValueMustBeExpr => {
217                f.write_str("Attribute value for must be a valid expression")
218            }
219            Error::ParametrizedAttrHasNoValue(name) => {
220                write!(f, "Attribute `{name}` must be in a `#[{name} = ...]` form", name = name)
221            }
222            Error::NestedListsNotSupported(name) => write!(
223                f,
224                "Attribute `{name}` must be in `{name} = ...` form and a nested list",
225                name = name,
226            ),
227            Error::UnsupportedLiteral(attr) => write!(
228                f,
229                "Attribute `{}` has an unsupported type of literal as one of its arguments",
230                attr
231            ),
232            Error::AttributeUnknownArgument { attr, arg } => {
233                write!(f, "Attribute `{}` has an unknown argument `{}`", attr, arg)
234            }
235            Error::ArgNumberExceedsMax {
236                attr,
237                type_name,
238                no,
239                max_no,
240            } => write!(
241                f,
242                "Attribute `{}` has excessive number of arguments of type `{}` ({} while only {} \
243                 are allowed)",
244                attr, type_name, no, max_no
245            ),
246            Error::ArgValueTypeMismatch { attr, arg } => {
247                write!(f, "Type mismatch in attribute `{}` argument `{}`", attr, arg)
248            }
249        }
250    }
251}
252
253impl std::error::Error for Error {
254    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
255        match self {
256            Error::Parse(err) => Some(err),
257            Error::NamesDontMatch(_, _) |
258            Error::MultipleSingularValues(_) |
259            Error::MultipleLiteralValues(_) |
260            Error::SingularAttrRequired(_) |
261            Error::ArgMustNotHaveValue { .. } |
262            Error::ArgTypeProhibited { .. } |
263            Error::ArgRequired { .. } |
264            Error::ParametrizedAttrRequired(_) |
265            Error::ArgNameMustBeIdent |
266            Error::ArgNameMustBeUnique { .. } |
267            Error::ArgValueRequired { .. } |
268            Error::ArgValueMustBeLiteral |
269            Error::ArgValueMustBeType |
270            Error::ArgValueMustBeExpr |
271            Error::ParametrizedAttrHasNoValue(_) |
272            Error::UnsupportedLiteral(_) |
273            Error::AttributeUnknownArgument { .. } |
274            Error::ArgNumberExceedsMax { .. } |
275            Error::ArgValueTypeMismatch { .. } => None,
276            Error::NestedListsNotSupported(_) => None,
277        }
278    }
279}