sqruff_lib/rules/aliasing/
al02.rs1use ahash::AHashMap;
2use sqruff_lib_core::dialects::syntax::{SyntaxKind, SyntaxSet};
3
4use super::al01::{Aliasing, RuleAL01};
5use crate::core::config::Value;
6use crate::core::rules::context::RuleContext;
7use crate::core::rules::crawlers::{Crawler, SegmentSeekerCrawler};
8use crate::core::rules::{Erased, ErasedRule, LintResult, Rule, RuleGroups};
9
10#[derive(Debug, Clone)]
11pub struct RuleAL02 {
12 base: RuleAL01,
13}
14
15impl Default for RuleAL02 {
16 fn default() -> Self {
17 Self {
18 base: RuleAL01::default()
19 .target_parent_types(const { SyntaxSet::new(&[SyntaxKind::SelectClauseElement]) }),
20 }
21 }
22}
23
24impl RuleAL02 {
25 pub fn aliasing(mut self, aliasing: Aliasing) -> Self {
26 self.base = self.base.aliasing(aliasing);
27 self
28 }
29}
30
31impl Rule for RuleAL02 {
32 fn load_from_config(&self, config: &AHashMap<String, Value>) -> Result<ErasedRule, String> {
33 let aliasing = match config.get("aliasing").unwrap().as_string().unwrap() {
34 "explicit" => Aliasing::Explicit,
35 "implicit" => Aliasing::Implicit,
36 _ => unreachable!(),
37 };
38
39 let mut rule = RuleAL02::default();
40 rule.base = rule.base.aliasing(aliasing);
41
42 Ok(rule.erased())
43 }
44
45 fn is_fix_compatible(&self) -> bool {
46 true
47 }
48
49 fn name(&self) -> &'static str {
50 "aliasing.column"
51 }
52
53 fn description(&self) -> &'static str {
54 "Implicit/explicit aliasing of columns."
55 }
56
57 fn long_description(&self) -> &'static str {
58 r#"
59**Anti-pattern**
60
61In this example, the alias for column `a` is implicit.
62
63```sql
64SELECT
65 a alias_col
66FROM foo
67```
68
69**Best practice**
70
71Add the `AS` keyword to make the alias explicit.
72
73```sql
74SELECT
75 a AS alias_col
76FROM foo
77```
78"#
79 }
80
81 fn groups(&self) -> &'static [RuleGroups] {
82 &[RuleGroups::All, RuleGroups::Core, RuleGroups::Aliasing]
83 }
84
85 fn eval(&self, context: &RuleContext) -> Vec<LintResult> {
86 if matches!(
87 context.segment
88 .child(&SyntaxSet::new(&[SyntaxKind::AliasOperator])),
89 Some(alias_operator) if alias_operator.raw() == "="
90 ) {
91 return Vec::new();
92 }
93
94 self.base.eval(context)
95 }
96
97 fn crawl_behaviour(&self) -> Crawler {
98 SegmentSeekerCrawler::new(const { SyntaxSet::new(&[SyntaxKind::AliasExpression]) }).into()
99 }
100}