Skip to main content

crisp_resolve/
warning.rs

1//! Resolve-time warnings (non-fatal).
2
3use crisp_ast::Span;
4use std::fmt;
5
6/// Non-fatal resolve diagnostics.
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub enum ResolveWarning {
9    /// Bare `use {name}` binds a Crisp module that shares a name with a `rust = true` dep.
10    ModuleShadowsRustDep { name: String, span: Span },
11}
12
13impl ResolveWarning {
14    pub fn code(&self) -> &'static str {
15        match self {
16            Self::ModuleShadowsRustDep { .. } => "W0048",
17        }
18    }
19}
20
21impl fmt::Display for ResolveWarning {
22    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23        match self {
24            Self::ModuleShadowsRustDep { name, .. } => write!(
25                f,
26                "[W0048] `{name}` is both a Crisp module and a Rust dependency; \
27                 bare `use {name}` binds the Crisp module; \
28                 use `use rust.{name} {{ … }}` for the crate (spec §14.2, #41)"
29            ),
30        }
31    }
32}
33
34#[cfg(test)]
35mod tests {
36    use super::*;
37    use crisp_ast::Span;
38
39    #[test]
40    fn w0048_display_mentions_code_and_disambiguation() {
41        let w = ResolveWarning::ModuleShadowsRustDep {
42            name: "config".into(),
43            span: Span::new(0, 1),
44        };
45        assert_eq!(w.code(), "W0048");
46        let msg = w.to_string();
47        assert!(msg.contains("W0048"));
48        assert!(msg.contains("config"));
49        assert!(msg.contains("use rust.config"));
50    }
51}