aldrin_parser/error/
duplicate_struct_field_id.rs1use super::Error;
2use crate::ast::{Ident, LitPosInt, StructField};
3use crate::diag::{Diagnostic, DiagnosticKind, Formatted, Formatter};
4use crate::validate::Validate;
5use crate::{util, Parsed, Span};
6
7#[derive(Debug)]
8pub struct DuplicateStructFieldId {
9 schema_name: String,
10 duplicate: LitPosInt,
11 first: Span,
12 struct_span: Span,
13 struct_ident: Option<Ident>,
14 free_id: u32,
15}
16
17impl DuplicateStructFieldId {
18 pub(crate) fn validate(
19 fields: &[StructField],
20 struct_span: Span,
21 ident: Option<&Ident>,
22 validate: &mut Validate,
23 ) {
24 let mut max_id = fields
25 .iter()
26 .fold(0, |cur, field| match field.id().value().parse() {
27 Ok(id) if id > cur => id,
28 _ => cur,
29 });
30
31 util::find_duplicates(
32 fields,
33 |field| field.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 struct_span,
42 struct_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 struct_span(&self) -> Span {
58 self.struct_span
59 }
60
61 pub fn struct_ident(&self) -> Option<&Ident> {
62 self.struct_ident.as_ref()
63 }
64
65 pub fn free_id(&self) -> u32 {
66 self.free_id
67 }
68}
69
70impl Diagnostic for DuplicateStructFieldId {
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.struct_ident {
81 Formatter::new(
82 self,
83 format!(
84 "duplicate id `{}` in struct `{}`",
85 self.duplicate.value(),
86 ident.value()
87 ),
88 )
89 } else {
90 Formatter::new(
91 self,
92 format!("duplicate id `{}` in inline struct", 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<DuplicateStructFieldId> for Error {
112 fn from(e: DuplicateStructFieldId) -> Self {
113 Self::DuplicateStructFieldId(e)
114 }
115}