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    /// Two declarations available in the same version resolve to the same
79    /// effective wire name inside one container.
80    DuplicateWireName {
81        container: String,
82        wire: String,
83        first: String,
84        second: String,
85        version: Option<String>,
86    },
87}
88
89impl fmt::Display for VersioningError {
90    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91        match self {
92            Self::VersionOutsideEnum { target } => write!(
93                f,
94                "xidl versioning: @version is only valid on an enum declaration, not on {target}"
95            ),
96            Self::DuplicateVersionEnum { first, second } => write!(
97                f,
98                "xidl versioning: multiple @version enums declared: {first} and {second}"
99            ),
100            Self::EmptyVersionEnum { ident } => write!(
101                f,
102                "xidl versioning: the @version enum {ident} declares no versions"
103            ),
104            Self::DuplicateVersionValue {
105                value,
106                first,
107                second,
108            } => write!(
109                f,
110                "xidl versioning: versions {first} and {second} both resolve to value \"{value}\""
111            ),
112            Self::MissingVersionEnum { annotation, decl } => write!(
113                f,
114                "xidl versioning: {annotation} on {decl} requires a @version enum in the specification"
115            ),
116            Self::MalformedVersionReference { annotation, decl } => write!(
117                f,
118                "xidl versioning: {annotation} on {decl} requires a version reference like Versions::v1"
119            ),
120            Self::MalformedVersionMarker { decl } => {
121                write!(f, "xidl versioning: @version on {decl} takes no arguments")
122            }
123            Self::UnknownVersionReference {
124                annotation,
125                decl,
126                reference,
127                declared,
128            } => write!(
129                f,
130                "xidl versioning: {annotation} on {decl} references {reference}, which is not declared ({declared})"
131            ),
132            Self::UnsupportedVersionAnnotation { name, decl } => write!(
133                f,
134                "xidl versioning: {name} on {decl} is not supported yet; phase 1 implements @version, @added and @removed"
135            ),
136            Self::UnsupportedVersionTarget { annotation, target } => write!(
137                f,
138                "xidl versioning: {annotation} cannot be applied to {target}"
139            ),
140            Self::VersionedVersionEnum { annotation, ident } => write!(
141                f,
142                "xidl versioning: the @version enum {ident} cannot carry {annotation}"
143            ),
144            Self::DuplicateLifecycleAnnotation { annotation, decl } => {
145                write!(f, "xidl versioning: duplicate {annotation} on {decl}")
146            }
147            Self::EmptyAvailability {
148                decl,
149                added,
150                removed,
151            } => write!(
152                f,
153                "xidl versioning: {decl} is unavailable in every version (@added({added}) and @removed({removed}) leave an empty interval)"
154            ),
155            Self::ChildOutsideParent {
156                decl,
157                parent,
158                version,
159            } => write!(
160                f,
161                "xidl versioning: {decl} is annotated at {version}, outside the availability of {parent}"
162            ),
163            Self::DanglingReference {
164                decl,
165                reference,
166                version,
167            } => write!(
168                f,
169                "xidl versioning: {decl} references {reference}, which does not exist in {version}"
170            ),
171            Self::UnversionedSpecification { selection } => write!(
172                f,
173                "xidl versioning: version selection {selection} requires a @version enum in the specification"
174            ),
175            Self::UnknownSelectedVersion {
176                selection,
177                declared,
178            } => write!(
179                f,
180                "xidl versioning: version {selection} is not declared ({declared})"
181            ),
182            Self::AmbiguousSelectedVersion {
183                selection,
184                first,
185                second,
186            } => write!(
187                f,
188                "xidl versioning: version {selection} matches both {first} and {second}; use the member ident"
189            ),
190            Self::UnknownVersion { index } => write!(
191                f,
192                "xidl versioning: version position {index} is not part of the declared timeline"
193            ),
194            Self::ConflictingSelection { first, second } => write!(
195                f,
196                "xidl versioning: {first} and {second} cannot both be set"
197            ),
198            Self::EmptySelection => write!(
199                f,
200                "xidl versioning: the version selection is empty; name at least one version or use \"*\""
201            ),
202            Self::SelectionRequiresOneVersion { selection } => write!(
203                f,
204                "xidl versioning: {selection} selects one version; use the plural version property with \"*\" for every version"
205            ),
206            Self::UnknownVersionLayout { value } => write!(
207                f,
208                "xidl versioning: unknown version layout \"{value}\"; expected \"merged\" or \"per_version\""
209            ),
210            Self::DuplicateWireName {
211                container,
212                wire,
213                first,
214                second,
215                version,
216            } => match version {
217                Some(version) => write!(
218                    f,
219                    "xidl versioning: {first} and {second} both serialize as \"{wire}\" in version {version}; effective wire names must stay unique inside {container} for every version"
220                ),
221                None => write!(
222                    f,
223                    "xidl versioning: {first} and {second} both serialize as \"{wire}\"; effective wire names must stay unique inside {container}"
224                ),
225            },
226        }
227    }
228}
229
230impl Error for VersioningError {}