sqrust_rules/layout/
statement_semicolons.rs1use sqrust_core::{Diagnostic, FileContext, Rule};
2
3pub struct StatementSemicolons;
4
5impl Rule for StatementSemicolons {
6 fn name(&self) -> &'static str {
7 "Layout/StatementSemicolons"
8 }
9
10 fn check(&self, ctx: &FileContext) -> Vec<Diagnostic> {
11 if !ctx.parse_errors.is_empty() {
14 return Vec::new();
15 }
16
17 let source = &ctx.source;
18
19 let trimmed = source.trim();
21 if trimmed.is_empty() {
22 return Vec::new();
23 }
24
25 let last_char = trimmed.chars().next_back();
27 if last_char == Some(';') {
28 return Vec::new();
29 }
30
31 let (last_line_no, _) = last_non_empty_line(source);
33
34 vec![Diagnostic {
35 rule: self.name(),
36 message: "SQL statement is missing a trailing semicolon".to_string(),
37 line: last_line_no,
38 col: 1,
39 }]
40 }
41}
42
43fn last_non_empty_line(source: &str) -> (usize, &str) {
47 let mut last = (1usize, "");
48 for (i, line) in source.lines().enumerate() {
49 if !line.trim().is_empty() {
50 last = (i + 1, line);
51 }
52 }
53 last
54}