aldrin_parser/error/
missing_import.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use super::Error;
use crate::ast::SchemaName;
use crate::diag::{Diagnostic, DiagnosticKind, Formatted, Formatter};
use crate::validate::Validate;
use crate::{util, Parsed};

#[derive(Debug)]
pub struct MissingImport {
    schema_name: String,
    extern_schema: SchemaName,
    candidate: Option<String>,
}

impl MissingImport {
    pub(crate) fn validate(schema_name: &SchemaName, validate: &mut Validate) {
        let schema = validate.get_current_schema();
        for import in schema.imports() {
            if import.schema_name().value() == schema_name.value() {
                return;
            }
        }

        let candidates = schema.imports().iter().map(|i| i.schema_name().value());
        let candidate = util::did_you_mean(candidates, schema_name.value()).map(ToOwned::to_owned);

        validate.add_error(MissingImport {
            schema_name: validate.schema_name().to_owned(),
            extern_schema: schema_name.clone(),
            candidate,
        });
    }

    pub fn extern_schema(&self) -> &SchemaName {
        &self.extern_schema
    }

    pub fn candidate(&self) -> Option<&str> {
        self.candidate.as_deref()
    }
}

impl Diagnostic for MissingImport {
    fn kind(&self) -> DiagnosticKind {
        DiagnosticKind::Error
    }

    fn schema_name(&self) -> &str {
        &self.schema_name
    }

    fn format<'a>(&'a self, parsed: &'a Parsed) -> Formatted<'a> {
        let mut fmt = Formatter::new(
            self,
            format!("missing import `{}`", self.extern_schema.value()),
        );

        if let Some(schema) = parsed.get_schema(&self.schema_name) {
            fmt.main_block(
                schema,
                self.extern_schema.span().from,
                self.extern_schema.span(),
                format!("schema `{}` used here", self.extern_schema.value()),
            );
        }

        if let Some(ref candidate) = self.candidate {
            fmt.help(format!("did you mean `{candidate}`?"));
        } else {
            fmt.help(format!(
                "add `import {};` at the top",
                self.extern_schema.value()
            ));
        };

        fmt.format()
    }
}

impl From<MissingImport> for Error {
    fn from(e: MissingImport) -> Self {
        Error::MissingImport(e)
    }
}