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