rigsql_rules/capitalisation/
cp04.rs1use rigsql_core::{Segment, SegmentType, TokenKind};
2
3use crate::rule::{CrawlType, Rule, RuleContext, RuleGroup};
4use crate::violation::{LintViolation, SourceEdit};
5
6#[derive(Debug, Default)]
10pub struct RuleCP04;
11
12impl Rule for RuleCP04 {
13 fn code(&self) -> &'static str {
14 "CP04"
15 }
16 fn name(&self) -> &'static str {
17 "capitalisation.literals"
18 }
19 fn description(&self) -> &'static str {
20 "Boolean/Null literals must be consistently capitalised."
21 }
22 fn explanation(&self) -> &'static str {
23 "Boolean literals (TRUE, FALSE) and NULL should be consistently capitalised. \
24 Using UPPER case for these literals is the most common convention and improves readability."
25 }
26 fn groups(&self) -> &[RuleGroup] {
27 &[RuleGroup::Capitalisation]
28 }
29 fn is_fixable(&self) -> bool {
30 true
31 }
32
33 fn crawl_type(&self) -> CrawlType {
34 CrawlType::Segment(vec![SegmentType::BooleanLiteral, SegmentType::NullLiteral])
35 }
36
37 fn eval(&self, ctx: &RuleContext) -> Vec<LintViolation> {
38 let Segment::Token(t) = ctx.segment else {
39 return vec![];
40 };
41 if t.token.kind != TokenKind::Word {
42 return vec![];
43 }
44
45 let text = t.token.text.as_str();
46 let expected = text.to_ascii_uppercase();
47
48 if text != expected {
49 vec![LintViolation::with_fix(
50 self.code(),
51 format!(
52 "Boolean/Null literals must be upper case. Found '{}' instead of '{}'.",
53 text, expected
54 ),
55 t.token.span,
56 vec![SourceEdit::replace(t.token.span, expected.clone())],
57 )]
58 } else {
59 vec![]
60 }
61 }
62}