Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d9e6979
test: add safety coverage for CLI, LSP, and path discovery
nikolaevx May 26, 2026
c47d2e8
feat(lib): introduce public engine API
nikolaevx May 26, 2026
39d3e6b
refactor(lsp): migrate diagnostics and formatting to engine API
nikolaevx May 26, 2026
83b75cd
refactor(wasm): migrate lint and format paths to engine API
nikolaevx May 26, 2026
e4028c9
fix(lsp): repair config loading after engine migration
nikolaevx Jul 8, 2026
a0bdb78
refactor(cli): unify lint and fix command runner
nikolaevx May 26, 2026
b45dc9f
refactor(cli): move reporting out of sqruff-lib
nikolaevx May 26, 2026
2f0ef29
fix(cli): repair reporting split fallout
nikolaevx Jul 8, 2026
910b840
refactor(lib): split workspace discovery from engine
nikolaevx May 26, 2026
494f9dd
refactor(api): replace boolean mode flags with enums
nikolaevx May 26, 2026
2d72dc1
fix(lib): use mode enum when checking pending fixes
nikolaevx Jul 8, 2026
a65cf6d
refactor(lib): canonicalize lint diagnostics
nikolaevx May 26, 2026
bb6ec7c
refactor(lib): make templater skip outcomes typed
nikolaevx May 26, 2026
b2db4b7
refactor(lib): introduce static templater runtime dispatch
nikolaevx May 26, 2026
9142ba3
refactor(errors): replace panics/unwraps with explicit Results
nikolaevx May 26, 2026
c6177d0
refactor(lib): deprecate legacy linter API
nikolaevx May 26, 2026
a13fae9
fix(wasm): accept tool selection as string
nikolaevx May 26, 2026
f34eec7
fix(bazel): add wasm deps for api refactor
nikolaevx May 26, 2026
c97b7f2
fix(lib): restore batch templater execution in Engine run
nikolaevx May 26, 2026
8418980
chore: auto-fix formatting
nikolaevx Jul 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 8 additions & 8 deletions MODULE.bazel.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions crates/cli-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ strum.workspace = true
strum_macros.workspace = true
fern = "0.7"
log.workspace = true
ignore = "0.4.26"
anstyle = "1.0"
clap = { version = "4.6.1", features = ["derive"] }
pyo3 = { version = "0.29.0", optional = true }
Expand Down
2 changes: 1 addition & 1 deletion crates/cli-lib/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub struct Cli {
pub dialect: Option<String>,
/// Show parse errors.
#[arg(long, global = true, default_value = "false")]
pub parsing_errors: bool,
pub(crate) parsing_errors: bool,
}

#[derive(Debug, Subcommand)]
Expand Down
113 changes: 52 additions & 61 deletions crates/cli-lib/src/commands_fix.rs
Original file line number Diff line number Diff line change
@@ -1,81 +1,50 @@
use crate::commands::FixArgs;
use crate::commands::Format;
use crate::linter;
use crate::commands_lint::{ApplyFixes, Input, LintCommand, run_lint_command};
use sqruff_lib::api::{Mode, ParseErrors};
use sqruff_lib::core::config::FluffConfig;
use std::path::Path;

pub(crate) fn run_fix(
args: FixArgs,
config: FluffConfig,
ignorer: impl Fn(&Path) -> bool + Send + Sync,
collect_parse_errors: bool,
parse_errors: ParseErrors,
) -> i32 {
let FixArgs { paths, format } = args;
let mut linter = match linter(config, format, collect_parse_errors) {
Ok(l) => l,
Err(e) => {
eprintln!("{}", e);
return 1;
}
};
let result = match linter.lint_paths(paths, true, &ignorer) {
Ok(result) => result,
Err(e) => {
eprintln!("{}", e.value);
return 1;
}
};

if !result.has_violations() {
println!("{} files processed, nothing to fix.", result.len());
0
} else {
let any_unfixable_errors = result.has_unfixable_violations();
let files = result.len();

for mut file in result {
if !file.has_fixes() {
continue;
}
let path = std::mem::take(&mut file.path);
let fixed = file.fix_string();
std::fs::write(path, fixed).unwrap();
}

linter.formatter_mut().unwrap().completion_message(files);

any_unfixable_errors as i32
}
run_lint_command(
LintCommand {
mode: Mode::Fix,
input: Input::Paths(paths),
apply: ApplyFixes::ToDisk,
format,
},
config,
ignorer,
parse_errors,
)
}

pub(crate) fn run_fix_stdin(
config: FluffConfig,
format: Format,
collect_parse_errors: bool,
) -> i32 {
let read_in = crate::stdin::read_std_in().unwrap();

let linter = match linter(config, format, collect_parse_errors) {
Ok(l) => l,
pub(crate) fn run_fix_stdin(config: FluffConfig, format: Format, parse_errors: ParseErrors) -> i32 {
let read_in = match crate::stdin::read_std_in() {
Ok(s) => s,
Err(e) => {
eprintln!("{}", e);
eprintln!("Failed to read stdin: {e}");
return 1;
}
};
let result = match linter.lint_string(&read_in, None, true) {
Ok(result) => result,
Err(e) => {
eprintln!("{}", e.value);
return 1;
}
};

let has_unfixable_errors = result.has_unfixable_violations();

println!("{}", result.fix_string());

// if all fixable violations are fixable, return 0 else return 1
has_unfixable_errors as i32
run_lint_command(
LintCommand {
mode: Mode::Fix,
input: Input::Stdin(read_in),
apply: ApplyFixes::Stdout,
format,
},
config,
|_| false,
parse_errors,
)
}

#[cfg(test)]
Expand Down Expand Up @@ -107,9 +76,31 @@ mod tests {
format: Format::Human,
};
let config = FluffConfig::default();
run_fix(args, config, ignore_none, true);
run_fix(args, config, ignore_none, ParseErrors::Include);

let after = std::fs::metadata(&path).unwrap().modified().unwrap();
assert_eq!(before, after);
}

#[test]
fn run_fix_writes_file_when_changes_exist() {
let mut tmp = NamedTempFile::new().unwrap();
write!(tmp, "SELECT foo bar FROM tabs").unwrap();
tmp.flush().unwrap();
let tmp = tmp.into_temp_path();
let path = tmp.to_path_buf();

let args = FixArgs {
paths: vec![path.clone()],
format: Format::Human,
};
let config = FluffConfig::from_source("[sqruff]\nrules = AL02\n", None);
let exit_code = run_fix(args, config, ignore_none, ParseErrors::Include);

assert_eq!(exit_code, 0);
assert_eq!(
std::fs::read_to_string(&path).unwrap(),
"SELECT foo AS bar FROM tabs"
);
}
}
Loading
Loading