use super::Checker;
use crate::{Finding, Severity};
pub(super) fn check(c: &mut Checker<'_>) {
if c.options.scaffold {
return;
}
let dialect = c.host.dialect();
let optional = dialect.spell("optional");
let unclosed = |line: usize| {
(
line,
Severity::Error,
"TLMD_12",
format!("a `{optional}` region opens here and nothing closes it"),
)
};
let mut found = Vec::new();
let mut open: Option<usize> = None;
for (i, raw) in c.doc.text.lines().enumerate() {
let line = i + 1;
if c.doc.body.in_code(line) || c.doc.segments.in_region(line) {
continue;
}
if dialect.is_only_marker(raw) {
found.push((
line,
Severity::Error,
"TLMD_10",
format!(
"a `{}` marker belongs in a scaffold, not a governed document",
dialect.spell("only")
),
));
}
if dialect.is_guidance_marker(raw) {
found.push((
line,
Severity::Error,
"TLMD_158",
format!(
"a `{}` line is left here: write the part it guides, then delete the line",
dialect.spell("guidance")
),
));
}
if dialect.is_optional_marker(raw) {
found.extend(open.map(unclosed));
open = Some(line);
}
if dialect.is_optional_close(raw) {
found.push(match open {
Some(opened) => (
opened,
Severity::Warning,
"TLMD_11",
format!(
"a `{optional}` region is left here: keep what it holds and drop both markers, or drop the region"
),
),
None => (
line,
Severity::Error,
"TLMD_12",
format!("a `{optional}` region closes here and nothing opened it"),
),
});
open = None;
}
}
found.extend(open.map(unclosed));
found.sort_by_key(|(line, ..)| *line);
for (line, severity, criterion, message) in found {
let finding = Finding::new(c.doc.path.clone(), Some(line), severity, criterion, message);
c.out.findings.push(finding);
}
}