#![allow(clippy::pedantic)]
use std::path::{Path, PathBuf};
use std::process::Command;
const TYPO: &str = "definitly";
const SYNTAXES: &[(&str, &str, &str, &str)] = &[
("markdown", "md", "<!-- ", " -->"),
("latex", "tex", "% ", ""),
("typst", "typ", "// ", ""),
];
fn temp_workspace() -> tempfile::TempDir {
tempfile::Builder::new()
.prefix("lang_check_test")
.tempdir()
.expect("a temp workspace")
}
fn flagged_lines(dir: &Path, name: &str, lang: &str) -> Vec<usize> {
let output = Command::new(env!("CARGO_BIN_EXE_language-check"))
.current_dir(dir)
.args(["check", name, "--lang", lang, "--format", "json"])
.output()
.expect("run language-check");
let stdout = String::from_utf8(output.stdout).expect("utf8 stdout");
let parsed: serde_json::Value = serde_json::from_str(&stdout)
.unwrap_or_else(|e| panic!("JSON from {name}: {e}\n--- stdout ---\n{stdout}"));
let mut lines: Vec<usize> = parsed
.as_array()
.unwrap_or_else(|| panic!("unexpected JSON shape from {name}: {parsed}"))
.iter()
.map(|d| {
usize::try_from(
d.get("line")
.and_then(serde_json::Value::as_u64)
.expect("every diagnostic carries a line"),
)
.unwrap()
})
.collect();
lines.sort_unstable();
lines.dedup();
lines
}
fn begin_end_document(open: &str, close: &str) -> String {
format!(
"A {TYPO} sentence here.\n\
\n\
{open}lang-check-begin{close}\n\
Another {TYPO} sentence in the region.\n\
{open}lang-check-end{close}\n\
\n\
A final {TYPO} sentence.\n"
)
}
fn disable_document(open: &str, close: &str) -> String {
format!(
"A {TYPO} sentence here.\n\
\n\
{open}lang-check-disable{close}\n\
Another {TYPO} sentence in the region.\n\
{open}lang-check-enable{close}\n\
\n\
{open}lang-check-disable-next-line{close}\n\
A nextline {TYPO} sentence.\n\
\n\
A final {TYPO} sentence.\n"
)
}
#[test]
fn begin_end_region_is_suppressed_in_every_format() {
let dir = temp_workspace();
for &(lang, ext, open, close) in SYNTAXES {
let name = format!("region.{ext}");
std::fs::write(dir.path().join(&name), begin_end_document(open, close)).unwrap();
assert_eq!(
flagged_lines(dir.path(), &name, lang),
vec![1, 7],
"begin/end region not honoured in {lang}"
);
}
}
#[test]
fn disable_directives_are_honoured_in_every_format() {
let dir = temp_workspace();
for &(lang, ext, open, close) in SYNTAXES {
let name = format!("disable.{ext}");
std::fs::write(dir.path().join(&name), disable_document(open, close)).unwrap();
assert_eq!(
flagged_lines(dir.path(), &name, lang),
vec![1, 10],
"disable directives not honoured in {lang}"
);
}
}
#[test]
fn a_document_without_directives_keeps_every_diagnostic() {
let dir = temp_workspace();
std::fs::write(
dir.path().join("plain.md"),
format!("A {TYPO} sentence here.\n\nA final {TYPO} sentence.\n"),
)
.unwrap();
assert_eq!(
flagged_lines(dir.path(), "plain.md", "markdown"),
vec![1, 3]
);
}