1use std::mem::take;
2use std::str::FromStr;
3use std::sync::Arc;
4
5use ahash::AHashMap;
6use sqruff_lib_core::dialects::init::DialectKind;
7use sqruff_lib_core::errors::{SQLBaseError, SQLFluffUserError};
8
9use crate::cli::formatters::Formatter;
10use crate::core::config::FluffConfig;
11use crate::core::linter::core::Linter;
12
13pub fn get_simple_config(
14 dialect: Option<String>,
15 rules: Option<Vec<String>>,
16 exclude_rules: Option<Vec<String>>,
17 config_path: Option<String>,
18) -> Result<FluffConfig, SQLFluffUserError> {
19 let mut overrides = AHashMap::new();
20 if let Some(dialect) = dialect {
21 DialectKind::from_str(dialect.as_str())
22 .map_err(|error| SQLFluffUserError::new(error.to_string()))?;
23 overrides.insert("dialect".to_owned(), dialect);
24 }
25 if let Some(rules) = rules {
26 overrides.insert("rules".to_owned(), rules.join(","));
27 }
28 if let Some(exclude_rules) = exclude_rules {
29 overrides.insert("exclude_rules".to_owned(), exclude_rules.join(","));
30 }
31
32 FluffConfig::from_root(config_path, true, Some(overrides))
33 .map_err(|err| SQLFluffUserError::new(format!("Error loading config: {:?}", err)))
34}
35
36pub fn lint(
37 sql: String,
38 dialect: String,
39 exclude_rules: Option<Vec<String>>,
40 config_path: Option<String>,
41) -> Result<Vec<SQLBaseError>, SQLFluffUserError> {
42 lint_with_formatter(&sql, dialect, exclude_rules, config_path, None)
43}
44
45pub fn lint_with_formatter(
47 sql: &str,
48 dialect: String,
49 exclude_rules: Option<Vec<String>>,
50 config_path: Option<String>,
51 formatter: Option<Arc<dyn Formatter>>,
52) -> Result<Vec<SQLBaseError>, SQLFluffUserError> {
53 let cfg = get_simple_config(dialect.into(), None, exclude_rules, config_path)?;
54
55 let mut linter = Linter::new(cfg, formatter, None, false);
56
57 let mut result = linter.lint_string_wrapped(sql, None, false);
58
59 Ok(take(&mut result.paths[0].files[0].violations))
60}
61
62pub fn fix(sql: &str) -> String {
63 let cfg = get_simple_config(Some("ansi".into()), None, None, None).unwrap();
64 let mut linter = Linter::new(cfg, None, None, false);
65 let mut result = linter.lint_string_wrapped(sql, None, true);
66 take(&mut result.paths[0].files[0]).fix_string()
67}