aldrin_parser/error/
duplicate_enum_variant.rs

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