rigsql_rules/layout/
lt03.rs1use rigsql_core::SegmentType;
2
3use crate::rule::{CrawlType, Rule, RuleContext, RuleGroup};
4use crate::violation::{LintViolation, SourceEdit};
5
6#[derive(Debug, Default)]
10pub struct RuleLT03;
11
12impl Rule for RuleLT03 {
13 fn code(&self) -> &'static str {
14 "LT03"
15 }
16 fn name(&self) -> &'static str {
17 "layout.operators"
18 }
19 fn description(&self) -> &'static str {
20 "Operators should be surrounded by single spaces."
21 }
22 fn explanation(&self) -> &'static str {
23 "Binary operators (=, <, >, +, -, etc.) should have a single space on each side \
24 for readability. 'a=b' and 'a = b' are harder to read than 'a = b'."
25 }
26 fn groups(&self) -> &[RuleGroup] {
27 &[RuleGroup::Layout]
28 }
29 fn is_fixable(&self) -> bool {
30 true
31 }
32
33 fn crawl_type(&self) -> CrawlType {
34 CrawlType::Segment(vec![
35 SegmentType::ComparisonOperator,
36 SegmentType::ArithmeticOperator,
37 ])
38 }
39
40 fn eval(&self, ctx: &RuleContext) -> Vec<LintViolation> {
41 let span = ctx.segment.span();
42 let mut violations = Vec::new();
43
44 if ctx.index_in_parent > 0 {
46 let prev = &ctx.siblings[ctx.index_in_parent - 1];
47 if prev.segment_type() != SegmentType::Whitespace {
48 violations.push(LintViolation::with_fix(
49 self.code(),
50 "Missing space before operator.",
51 span,
52 vec![SourceEdit::insert(span.start, " ")],
53 ));
54 }
55 }
56
57 if ctx.index_in_parent + 1 < ctx.siblings.len() {
59 let next = &ctx.siblings[ctx.index_in_parent + 1];
60 if next.segment_type() != SegmentType::Whitespace {
61 violations.push(LintViolation::with_fix(
62 self.code(),
63 "Missing space after operator.",
64 span,
65 vec![SourceEdit::insert(span.end, " ")],
66 ));
67 }
68 }
69
70 violations
71 }
72}