Skip to main content

sqruff_lib/rules/layout/
lt14.rs

1use hashbrown::HashMap;
2
3use crate::core::config::Value;
4use crate::core::rules::context::RuleContext;
5use crate::core::rules::crawlers::{Crawler, RootOnlyCrawler};
6use crate::core::rules::{Erased, ErasedRule, LintResult, Rule, RuleGroups};
7use crate::utils::reflow::sequence::{RebreakType, ReflowSequence};
8
9#[derive(Debug, Default, Clone)]
10pub struct RuleLT14;
11
12impl Rule for RuleLT14 {
13    fn load_from_config(&self, _config: &HashMap<String, Value>) -> Result<ErasedRule, String> {
14        Ok(RuleLT14.erased())
15    }
16
17    fn name(&self) -> &'static str {
18        "layout.keyword_newline"
19    }
20
21    fn description(&self) -> &'static str {
22        "Keyword clause newline enforcement."
23    }
24
25    fn long_description(&self) -> &'static str {
26        r#"
27This rule checks the following clause types:
28
29- `SELECT`
30- `FROM`
31- `WHERE`
32- `JOIN`
33- `GROUP BY`
34- `ORDER BY`
35- `HAVING`
36- `LIMIT`
37
38**Anti-pattern**
39
40In this example, some clauses share a line while others don't,
41creating inconsistent formatting.
42
43```sql
44SELECT a
45FROM foo WHERE a = 1
46```
47
48**Best practice**
49
50Each clause should start on a new line.
51
52```sql
53SELECT a
54FROM foo
55WHERE a = 1
56```
57"#
58    }
59
60    fn groups(&self) -> &'static [RuleGroups] {
61        &[RuleGroups::All, RuleGroups::Layout]
62    }
63
64    fn eval(&self, context: &RuleContext) -> Vec<LintResult> {
65        ReflowSequence::from_root(&context.segment, context.config)
66            .rebreak(context.tables, RebreakType::Keywords)
67            .results()
68    }
69
70    fn is_fix_compatible(&self) -> bool {
71        true
72    }
73
74    fn crawl_behaviour(&self) -> Crawler {
75        RootOnlyCrawler.into()
76    }
77}