aldrin_parser/error/
expected_const_int_found_string.rs

1use super::Error;
2use crate::ast::{ConstValue, NamedRef, NamedRefKind};
3use crate::diag::{Diagnostic, DiagnosticKind, Formatted, Formatter};
4use crate::validate::Validate;
5use crate::{util, Parsed};
6
7#[derive(Debug)]
8pub struct ExpectedConstIntFoundString {
9    schema_name: String,
10    named_ref: NamedRef,
11    candidate: Option<String>,
12}
13
14impl ExpectedConstIntFoundString {
15    pub(crate) fn validate(named_ref: &NamedRef, validate: &mut Validate) {
16        let (schema, ident) = match named_ref.kind() {
17            NamedRefKind::Intern(ident) => (validate.get_current_schema(), ident),
18
19            NamedRefKind::Extern(schema, ident) => {
20                let Some(schema) = validate.get_schema(schema.value()) else {
21                    return;
22                };
23
24                (schema, ident)
25            }
26        };
27
28        let mut found = false;
29        for def in schema.definitions() {
30            if def.name().value() == ident.value() {
31                let Some(const_def) = def.as_const() else {
32                    return;
33                };
34
35                if matches!(const_def.value(), ConstValue::String(_)) {
36                    found = true;
37                } else {
38                    return;
39                }
40            }
41        }
42
43        if found {
44            let candidate =
45                util::did_you_mean_const_int(schema, ident.value()).map(ToOwned::to_owned);
46
47            validate.add_error(Self {
48                schema_name: validate.schema_name().to_owned(),
49                named_ref: named_ref.clone(),
50                candidate,
51            });
52        }
53    }
54
55    pub fn named_ref(&self) -> &NamedRef {
56        &self.named_ref
57    }
58}
59
60impl Diagnostic for ExpectedConstIntFoundString {
61    fn kind(&self) -> DiagnosticKind {
62        DiagnosticKind::Error
63    }
64
65    fn schema_name(&self) -> &str {
66        &self.schema_name
67    }
68
69    fn format<'a>(&'a self, parsed: &'a Parsed) -> Formatted<'a> {
70        let mut fmt = Formatter::new(
71            self,
72            format!(
73                "expected integer constant; found string constant `{}`",
74                self.named_ref.ident().value()
75            ),
76        );
77
78        if let Some(schema) = parsed.get_schema(&self.schema_name) {
79            fmt.main_block(
80                schema,
81                self.named_ref.span().from,
82                self.named_ref.span(),
83                "integer constant expected here",
84            );
85        }
86
87        if let Some(ref candidate) = self.candidate {
88            match self.named_ref.schema() {
89                Some(schema) => {
90                    fmt.help(format!("did you mean `{}::{candidate}`?", schema.value()));
91                }
92
93                None => {
94                    fmt.help(format!("did you mean `{candidate}`?"));
95                }
96            }
97        }
98
99        fmt.format()
100    }
101}
102
103impl From<ExpectedConstIntFoundString> for Error {
104    fn from(e: ExpectedConstIntFoundString) -> Self {
105        Self::ExpectedConstIntFoundString(e)
106    }
107}