rigsql_rules/layout/
lt14.rs1use rigsql_core::SegmentType;
2
3use crate::rule::{CrawlType, Rule, RuleContext, RuleGroup};
4use crate::violation::{LintViolation, SourceEdit};
5
6#[derive(Debug, Default)]
8pub struct RuleLT14;
9
10impl Rule for RuleLT14 {
11 fn code(&self) -> &'static str {
12 "LT14"
13 }
14 fn name(&self) -> &'static str {
15 "layout.semicolons"
16 }
17 fn description(&self) -> &'static str {
18 "Statements should not end with multiple semicolons."
19 }
20 fn explanation(&self) -> &'static str {
21 "Each SQL statement should end with exactly one semicolon. Multiple consecutive \
22 semicolons (;;) indicate a redundant terminator that should be removed."
23 }
24 fn groups(&self) -> &[RuleGroup] {
25 &[RuleGroup::Layout]
26 }
27 fn is_fixable(&self) -> bool {
28 true
29 }
30
31 fn crawl_type(&self) -> CrawlType {
32 CrawlType::Segment(vec![SegmentType::Semicolon])
33 }
34
35 fn eval(&self, ctx: &RuleContext) -> Vec<LintViolation> {
36 let mut i = ctx.index_in_parent + 1;
38 while i < ctx.siblings.len() {
39 let seg = &ctx.siblings[i];
40 if seg.segment_type().is_trivia() {
41 i += 1;
42 continue;
43 }
44 if seg.segment_type() == SegmentType::Semicolon {
45 return vec![LintViolation::with_fix(
46 self.code(),
47 "Found multiple consecutive semicolons.",
48 ctx.segment.span(),
49 vec![SourceEdit::delete(ctx.segment.span())],
50 )];
51 }
52 break;
53 }
54
55 vec![]
56 }
57}