Skip to main content

xidl_parser/versioning/
error.rs

1use std::error::Error;
2use std::fmt;
3
4/// Diagnostics raised while analysing or projecting API versioning annotations.
5#[derive(Debug, Clone)]
6pub enum VersioningError {
7    /// `@version` applied to a declaration that is not an enum.
8    VersionOutsideEnum { target: String },
9    /// Two enums in one specification carry the `@version` marker.
10    DuplicateVersionEnum { first: String, second: String },
11    /// The `@version` enum declares no members.
12    EmptyVersionEnum { ident: String },
13    /// Two version members resolve to the same display value.
14    DuplicateVersionValue {
15        value: String,
16        first: String,
17        second: String,
18    },
19    /// A lifecycle annotation appears without a `@version` enum in the specification.
20    MissingVersionEnum { annotation: String, decl: String },
21    /// A lifecycle annotation argument is not an `Enum::member` reference.
22    MalformedVersionReference { annotation: String, decl: String },
23    /// `@version` carries arguments; the marker takes none.
24    MalformedVersionMarker { decl: String },
25    /// A lifecycle annotation references a version the timeline does not declare.
26    UnknownVersionReference {
27        annotation: String,
28        decl: String,
29        reference: String,
30        declared: String,
31    },
32    /// The projection knows the annotation name but phase 1 does not implement it.
33    UnsupportedVersionAnnotation { name: String, decl: String },
34    /// A lifecycle annotation applied to a declaration that cannot carry it.
35    UnsupportedVersionTarget { annotation: String, target: String },
36    /// The `@version` enum itself carries a lifecycle annotation.
37    VersionedVersionEnum { annotation: String, ident: String },
38    /// The same lifecycle annotation appears twice on one declaration.
39    DuplicateLifecycleAnnotation { annotation: String, decl: String },
40    /// `@added` and `@removed` leave an empty availability interval.
41    EmptyAvailability {
42        decl: String,
43        added: String,
44        removed: String,
45    },
46    /// A child's annotated interval reaches outside its parent's interval.
47    ChildOutsideParent {
48        decl: String,
49        parent: String,
50        version: String,
51    },
52    /// A surviving declaration references a declaration the projection drops.
53    DanglingReference {
54        decl: String,
55        reference: String,
56        version: String,
57    },
58    /// A version selection was requested for a specification without a `@version` enum.
59    UnversionedSpecification { selection: String },
60    /// A requested version is not declared by the timeline.
61    UnknownSelectedVersion { selection: String, declared: String },
62    /// A requested version matches both a member ident and another member's value.
63    AmbiguousSelectedVersion {
64        selection: String,
65        first: String,
66        second: String,
67    },
68    /// The projector received a version position outside the timeline.
69    UnknownVersion { index: usize },
70    /// Both version selection properties were set.
71    ConflictingSelection { first: String, second: String },
72    /// The requested version selection is empty.
73    EmptySelection,
74    /// `api_version` received `*`, which only `api_versions` accepts.
75    SelectionRequiresOneVersion { selection: String },
76    /// The version layout property holds an unknown value.
77    UnknownVersionLayout { value: String },
78}
79
80impl fmt::Display for VersioningError {
81    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82        match self {
83            Self::VersionOutsideEnum { target } => write!(
84                f,
85                "xidl versioning: @version is only valid on an enum declaration, not on {target}"
86            ),
87            Self::DuplicateVersionEnum { first, second } => write!(
88                f,
89                "xidl versioning: multiple @version enums declared: {first} and {second}"
90            ),
91            Self::EmptyVersionEnum { ident } => write!(
92                f,
93                "xidl versioning: the @version enum {ident} declares no versions"
94            ),
95            Self::DuplicateVersionValue {
96                value,
97                first,
98                second,
99            } => write!(
100                f,
101                "xidl versioning: versions {first} and {second} both resolve to value \"{value}\""
102            ),
103            Self::MissingVersionEnum { annotation, decl } => write!(
104                f,
105                "xidl versioning: {annotation} on {decl} requires a @version enum in the specification"
106            ),
107            Self::MalformedVersionReference { annotation, decl } => write!(
108                f,
109                "xidl versioning: {annotation} on {decl} requires a version reference like Versions::v1"
110            ),
111            Self::MalformedVersionMarker { decl } => {
112                write!(f, "xidl versioning: @version on {decl} takes no arguments")
113            }
114            Self::UnknownVersionReference {
115                annotation,
116                decl,
117                reference,
118                declared,
119            } => write!(
120                f,
121                "xidl versioning: {annotation} on {decl} references {reference}, which is not declared ({declared})"
122            ),
123            Self::UnsupportedVersionAnnotation { name, decl } => write!(
124                f,
125                "xidl versioning: {name} on {decl} is not supported yet; phase 1 implements @version, @added and @removed"
126            ),
127            Self::UnsupportedVersionTarget { annotation, target } => write!(
128                f,
129                "xidl versioning: {annotation} cannot be applied to {target}"
130            ),
131            Self::VersionedVersionEnum { annotation, ident } => write!(
132                f,
133                "xidl versioning: the @version enum {ident} cannot carry {annotation}"
134            ),
135            Self::DuplicateLifecycleAnnotation { annotation, decl } => {
136                write!(f, "xidl versioning: duplicate {annotation} on {decl}")
137            }
138            Self::EmptyAvailability {
139                decl,
140                added,
141                removed,
142            } => write!(
143                f,
144                "xidl versioning: {decl} is unavailable in every version (@added({added}) and @removed({removed}) leave an empty interval)"
145            ),
146            Self::ChildOutsideParent {
147                decl,
148                parent,
149                version,
150            } => write!(
151                f,
152                "xidl versioning: {decl} is annotated at {version}, outside the availability of {parent}"
153            ),
154            Self::DanglingReference {
155                decl,
156                reference,
157                version,
158            } => write!(
159                f,
160                "xidl versioning: {decl} references {reference}, which does not exist in {version}"
161            ),
162            Self::UnversionedSpecification { selection } => write!(
163                f,
164                "xidl versioning: version selection {selection} requires a @version enum in the specification"
165            ),
166            Self::UnknownSelectedVersion {
167                selection,
168                declared,
169            } => write!(
170                f,
171                "xidl versioning: version {selection} is not declared ({declared})"
172            ),
173            Self::AmbiguousSelectedVersion {
174                selection,
175                first,
176                second,
177            } => write!(
178                f,
179                "xidl versioning: version {selection} matches both {first} and {second}; use the member ident"
180            ),
181            Self::UnknownVersion { index } => write!(
182                f,
183                "xidl versioning: version position {index} is not part of the declared timeline"
184            ),
185            Self::ConflictingSelection { first, second } => write!(
186                f,
187                "xidl versioning: {first} and {second} cannot both be set"
188            ),
189            Self::EmptySelection => write!(
190                f,
191                "xidl versioning: the version selection is empty; name at least one version or use \"*\""
192            ),
193            Self::SelectionRequiresOneVersion { selection } => write!(
194                f,
195                "xidl versioning: {selection} selects one version; use the plural version property with \"*\" for every version"
196            ),
197            Self::UnknownVersionLayout { value } => write!(
198                f,
199                "xidl versioning: unknown version layout \"{value}\"; expected \"merged\" or \"per_version\""
200            ),
201        }
202    }
203}
204
205impl Error for VersioningError {}