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::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}