use super::*;
pub(super) fn diag(path: &str, source: &str, span: Span, message: impl Into<String>) -> Diagnostic {
let lines = crate::diagnostics::split_source_lines(source);
Diagnostic::new(
path,
span.line,
span.col,
crate::diagnostics::source_line(&lines, span.line),
message,
)
}
pub(crate) fn unknown_stdlib_module(
path: &str,
source: &str,
name: &str,
span: Span,
) -> Diagnostic {
let hint = if name == "math" {
"much math? such nerd — write so nerd".to_string()
} else {
format!("modules: {}", stdlib::module_names())
};
diag(
path,
source,
span,
format!("doge has no module named {name}"),
)
.with_headline("very import. much unknown.")
.with_hint(hint)
}
pub(super) fn missing_module_diag(path: &str, source: &str, name: &str, span: Span) -> Diagnostic {
let hint = if name == "math" {
"much math? such nerd — write so nerd".to_string()
} else {
format!(
"make {name}.doge next to this file, or import a stdlib module ({})",
stdlib::module_names()
)
};
diag(
path,
source,
span,
format!("doge has no module named {name}"),
)
.with_headline("very import. much unknown.")
.with_hint(hint)
}
pub(super) fn missing_path_module_diag(
path: &str,
source: &str,
raw: &str,
target: &Path,
span: Span,
) -> Diagnostic {
diag(path, source, span, format!("doge found no file at {raw}"))
.with_headline("very import. much unknown.")
.with_hint(format!(
"paths are relative to this file — doge looked at {}",
target.display()
))
}
pub(super) fn entry_import_diag(path: &str, source: &str, span: Span) -> Diagnostic {
diag(
path,
source,
span,
"this import points back at the main script, which is not a module",
)
.with_headline("very import. much self.")
.with_hint("only modules (definitions-only files) can be imported — split the shared code into its own file")
}
pub(super) fn read_error_diag(
path: &str,
source: &str,
name: &str,
target: &Path,
err: &std::io::Error,
span: Span,
) -> Diagnostic {
diag(
path,
source,
span,
format!("doge found {name}.doge but could not read it: {err}"),
)
.with_headline("very import. much unreadable.")
.with_hint(format!("check the file at {}", target.display()))
}
pub(super) fn shadow_diag(path: &str, source: &str, name: &str, span: Span) -> Diagnostic {
diag(
path,
source,
span,
format!("{name}.doge shadows the built-in module {name}"),
)
.with_headline("very shadow. much confuse.")
.with_hint(format!("rename your file — {name} is a doge stdlib module"))
}
pub(super) fn dep_conflict_diag(path: &str, source: &str, name: &str, span: Span) -> Diagnostic {
diag(
path,
source,
span,
format!("{name} is both a declared dependency and a file {name}.doge here"),
)
.with_headline("very ambiguous. much confuse.")
.with_hint(format!(
"rename one — a dependency and a sibling module can't share the name {name}"
))
}
pub(super) fn cycle_diag(
path: &str,
source: &str,
active: &[String],
name: &str,
span: Span,
) -> Diagnostic {
let start = active.iter().position(|m| m == name).unwrap_or(0);
let mut chain: Vec<&str> = active[start..].iter().map(String::as_str).collect();
chain.push(name);
diag(
path,
source,
span,
format!("import cycle: {}", chain.join(" → ")),
)
.with_headline("very loop. much import.")
.with_hint("break the loop — one of these imports has to go")
}