sqruff_lib/rules/layout/
lt11.rs1use 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}