sqruff_lib/rules/layout/
lt11.rs

1use ahash::AHashMap;
2use sqruff_lib_core::dialects::syntax::{SyntaxKind, SyntaxSet};
3
4use crate::core::config::Value;
5use crate::core::rules::context::RuleContext;
6use crate::core::rules::crawlers::{Crawler, SegmentSeekerCrawler};
7use crate::core::rules::{Erased, ErasedRule, LintResult, Rule, RuleGroups};
8use crate::utils::reflow::sequence::{ReflowSequence, TargetSide};
9
10#[derive(Debug, Default, Clone)]
11pub struct RuleLT11;
12
13impl Rule for RuleLT11 {
14    fn load_from_config(&self, _config: &AHashMap<String, Value>) -> Result<ErasedRule, String> {
15        Ok(RuleLT11.erased())
16    }
17
18    fn name(&self) -> &'static str {
19        "layout.set_operators"
20    }
21
22    fn description(&self) -> &'static str {
23        "Set operators should be surrounded by newlines."
24    }
25
26    fn long_description(&self) -> &'static str {
27        r#"
28**Anti-pattern**
29
30In this example, `UNION ALL` is not on a line itself.
31
32```sql
33SELECT 'a' AS col UNION ALL
34SELECT 'b' AS col
35```
36
37**Best practice**
38
39Place `UNION ALL` on its own line.
40
41```sql
42SELECT 'a' AS col
43UNION ALL
44SELECT 'b' AS col
45```
46"#
47    }
48
49    fn groups(&self) -> &'static [RuleGroups] {
50        &[RuleGroups::All, RuleGroups::Core, RuleGroups::Layout]
51    }
52
53    fn eval(&self, context: &RuleContext) -> Vec<LintResult> {
54        ReflowSequence::from_around_target(
55            &context.segment,
56            context.parent_stack.first().unwrap(),
57            TargetSide::Both,
58            context.config,
59        )
60        .rebreak(context.tables)
61        .results()
62    }
63
64    fn is_fix_compatible(&self) -> bool {
65        true
66    }
67
68    fn crawl_behaviour(&self) -> Crawler {
69        SegmentSeekerCrawler::new(const { SyntaxSet::new(&[SyntaxKind::SetOperator]) }).into()
70    }
71}