sqruff_lib/rules/aliasing/
al02.rs

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