rigsql_rules/aliasing/
al02.rs1use rigsql_core::SegmentType;
2
3use crate::rule::{CrawlType, Rule, RuleContext, RuleGroup};
4use crate::utils::{has_as_keyword, insert_as_keyword_fix, is_false_alias};
5use crate::violation::LintViolation;
6
7#[derive(Debug, Default)]
12pub struct RuleAL02;
13
14impl Rule for RuleAL02 {
15 fn code(&self) -> &'static str {
16 "AL02"
17 }
18 fn name(&self) -> &'static str {
19 "aliasing.column"
20 }
21 fn description(&self) -> &'static str {
22 "Implicit column aliasing is not allowed."
23 }
24 fn explanation(&self) -> &'static str {
25 "Column aliases should use the explicit AS keyword. \
26 'SELECT col alias' is harder to read than 'SELECT col AS alias'. \
27 This is especially important for complex expressions."
28 }
29 fn groups(&self) -> &[RuleGroup] {
30 &[RuleGroup::Aliasing]
31 }
32 fn is_fixable(&self) -> bool {
33 true
34 }
35
36 fn crawl_type(&self) -> CrawlType {
37 CrawlType::Segment(vec![SegmentType::AliasExpression])
38 }
39
40 fn eval(&self, ctx: &RuleContext) -> Vec<LintViolation> {
41 let is_in_select = ctx
42 .parent
43 .is_some_and(|p| p.segment_type() == SegmentType::SelectClause);
44 if !is_in_select {
45 return vec![];
46 }
47
48 let children = ctx.segment.children();
49 if is_false_alias(children) || has_as_keyword(children) {
50 return vec![];
51 }
52
53 vec![LintViolation::with_fix(
54 self.code(),
55 "Implicit column aliasing not allowed. Use explicit AS keyword.",
56 ctx.segment.span(),
57 insert_as_keyword_fix(children),
58 )]
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65 use crate::test_utils::lint_sql;
66
67 #[test]
68 fn test_al02_flags_implicit_column_alias() {
69 let violations = lint_sql("SELECT col alias_name FROM t", RuleAL02);
70 assert_eq!(violations.len(), 1);
71 }
72
73 #[test]
74 fn test_al02_accepts_explicit_as() {
75 let violations = lint_sql("SELECT col AS alias_name FROM t", RuleAL02);
76 assert_eq!(violations.len(), 0);
77 }
78
79 #[test]
80 fn test_al02_skips_non_select() {
81 let violations = lint_sql("SELECT * FROM t1 t2", RuleAL02);
82 assert_eq!(violations.len(), 0);
83 }
84}