aldrin_parser/error/
missing_import.rs

1use super::Error;
2use crate::ast::SchemaName;
3use crate::diag::{Diagnostic, DiagnosticKind, Formatted, Formatter};
4use crate::validate::Validate;
5use crate::{util, Parsed};
6
7#[derive(Debug)]
8pub struct MissingImport {
9    schema_name: String,
10    extern_schema: SchemaName,
11    candidate: Option<String>,
12}
13
14impl MissingImport {
15    pub(crate) fn validate(schema_name: &SchemaName, validate: &mut Validate) {
16        let schema = validate.get_current_schema();
17        for import in schema.imports() {
18            if import.schema_name().value() == schema_name.value() {
19                return;
20            }
21        }
22
23        let candidates = schema.imports().iter().map(|i| i.schema_name().value());
24        let candidate = util::did_you_mean(candidates, schema_name.value()).map(ToOwned::to_owned);
25
26        validate.add_error(Self {
27            schema_name: validate.schema_name().to_owned(),
28            extern_schema: schema_name.clone(),
29            candidate,
30        });
31    }
32
33    pub fn extern_schema(&self) -> &SchemaName {
34        &self.extern_schema
35    }
36
37    pub fn candidate(&self) -> Option<&str> {
38        self.candidate.as_deref()
39    }
40}
41
42impl Diagnostic for MissingImport {
43    fn kind(&self) -> DiagnosticKind {
44        DiagnosticKind::Error
45    }
46
47    fn schema_name(&self) -> &str {
48        &self.schema_name
49    }
50
51    fn format<'a>(&'a self, parsed: &'a Parsed) -> Formatted<'a> {
52        let mut fmt = Formatter::new(
53            self,
54            format!("missing import `{}`", self.extern_schema.value()),
55        );
56
57        if let Some(schema) = parsed.get_schema(&self.schema_name) {
58            fmt.main_block(
59                schema,
60                self.extern_schema.span().from,
61                self.extern_schema.span(),
62                format!("schema `{}` used here", self.extern_schema.value()),
63            );
64        }
65
66        if let Some(ref candidate) = self.candidate {
67            fmt.help(format!("did you mean `{candidate}`?"));
68        } else {
69            fmt.help(format!(
70                "add `import {};` at the top",
71                self.extern_schema.value()
72            ));
73        };
74
75        fmt.format()
76    }
77}
78
79impl From<MissingImport> for Error {
80    fn from(e: MissingImport) -> Self {
81        Self::MissingImport(e)
82    }
83}