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