Skip to main content

rigsql_rules/layout/
lt13.rs

1use crate::rule::{CrawlType, Rule, RuleContext, RuleGroup};
2use crate::violation::{LintViolation, SourceEdit};
3
4/// LT13: Files must not begin with newlines or whitespace.
5#[derive(Debug, Default)]
6pub struct RuleLT13;
7
8impl Rule for RuleLT13 {
9    fn code(&self) -> &'static str {
10        "LT13"
11    }
12    fn name(&self) -> &'static str {
13        "layout.start_of_file"
14    }
15    fn description(&self) -> &'static str {
16        "Files must not begin with newlines or whitespace."
17    }
18    fn explanation(&self) -> &'static str {
19        "Files should start with actual content, not blank lines or whitespace. \
20         Leading whitespace is likely unintentional and should be removed."
21    }
22    fn groups(&self) -> &[RuleGroup] {
23        &[RuleGroup::Layout]
24    }
25    fn is_fixable(&self) -> bool {
26        true
27    }
28
29    fn crawl_type(&self) -> CrawlType {
30        CrawlType::RootOnly
31    }
32
33    fn eval(&self, ctx: &RuleContext) -> Vec<LintViolation> {
34        let source = ctx.source;
35        if source.is_empty() {
36            return vec![];
37        }
38
39        let first_non_ws = source.find(|c: char| !c.is_whitespace());
40
41        match first_non_ws {
42            Some(0) => vec![], // starts with content
43            Some(pos) => {
44                vec![LintViolation::with_fix(
45                    self.code(),
46                    "File starts with whitespace or blank lines.",
47                    rigsql_core::Span::new(0, pos as u32),
48                    vec![SourceEdit::delete(rigsql_core::Span::new(0, pos as u32))],
49                )]
50            }
51            None => vec![], // all whitespace file — other rules handle this
52        }
53    }
54}