aldrin_parser/error/
duplicate_enum_variant_id.rs1use super::Error;
2use crate::ast::{EnumVariant, Ident, LitPosInt};
3use crate::diag::{Diagnostic, DiagnosticKind, Formatted, Formatter};
4use crate::validate::Validate;
5use crate::{util, Parsed, Span};
6
7#[derive(Debug)]
8pub struct DuplicateEnumVariantId {
9 schema_name: String,
10 duplicate: LitPosInt,
11 first: Span,
12 enum_span: Span,
13 enum_ident: Option<Ident>,
14 free_id: u32,
15}
16
17impl DuplicateEnumVariantId {
18 pub(crate) fn validate(
19 vars: &[EnumVariant],
20 enum_span: Span,
21 ident: Option<&Ident>,
22 validate: &mut Validate,
23 ) {
24 let mut max_id = vars
25 .iter()
26 .fold(0, |cur, var| match var.id().value().parse() {
27 Ok(id) if id > cur => id,
28 _ => cur,
29 });
30
31 util::find_duplicates(
32 vars,
33 |var| var.id().value(),
34 |duplicate, first| {
35 max_id += 1;
36 let free_id = max_id;
37 validate.add_error(Self {
38 schema_name: validate.schema_name().to_owned(),
39 duplicate: duplicate.id().clone(),
40 first: first.id().span(),
41 enum_span,
42 enum_ident: ident.cloned(),
43 free_id,
44 })
45 },
46 );
47 }
48
49 pub fn duplicate(&self) -> &LitPosInt {
50 &self.duplicate
51 }
52
53 pub fn first(&self) -> Span {
54 self.first
55 }
56
57 pub fn enum_span(&self) -> Span {
58 self.enum_span
59 }
60
61 pub fn enum_ident(&self) -> Option<&Ident> {
62 self.enum_ident.as_ref()
63 }
64
65 pub fn free_id(&self) -> u32 {
66 self.free_id
67 }
68}
69
70impl Diagnostic for DuplicateEnumVariantId {
71 fn kind(&self) -> DiagnosticKind {
72 DiagnosticKind::Error
73 }
74
75 fn schema_name(&self) -> &str {
76 &self.schema_name
77 }
78
79 fn format<'a>(&'a self, parsed: &'a Parsed) -> Formatted<'a> {
80 let mut fmt = if let Some(ref ident) = self.enum_ident {
81 Formatter::new(
82 self,
83 format!(
84 "duplicate id `{}` in enum `{}`",
85 self.duplicate.value(),
86 ident.value()
87 ),
88 )
89 } else {
90 Formatter::new(
91 self,
92 format!("duplicate id `{}` in inline enum", self.duplicate.value()),
93 )
94 };
95
96 if let Some(schema) = parsed.get_schema(&self.schema_name) {
97 fmt.main_block(
98 schema,
99 self.duplicate.span().from,
100 self.duplicate.span(),
101 "duplicate defined here",
102 )
103 .info_block(schema, self.first.from, self.first, "first defined here");
104 }
105
106 fmt.help(format!("use a free id, e.g. {}", self.free_id));
107 fmt.format()
108 }
109}
110
111impl From<DuplicateEnumVariantId> for Error {
112 fn from(e: DuplicateEnumVariantId) -> Self {
113 Self::DuplicateEnumVariantId(e)
114 }
115}