Skip to content

Commit ec6142e

Browse files
committed
feat: optionally collect parsing errors
1 parent 894873f commit ec6142e

File tree

8 files changed

+75
-13
lines changed

8 files changed

+75
-13
lines changed

crates/cli/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ bench = false
2929
name = "fix_return_code"
3030
harness = false
3131

32+
[[test]]
33+
name = "fix_parse_errors"
34+
harness = false
35+
3236
[[test]]
3337
name = "config_not_found"
3438
harness = false

crates/cli/src/commands.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ pub(crate) struct Cli {
1515
/// Path to a configuration file.
1616
#[arg(long, global = true)]
1717
pub config: Option<String>,
18+
/// Show parse errors.
19+
#[arg(long, global = true, default_value = "false")]
20+
pub parsing_errors: bool,
1821
}
1922

2023
#[derive(Debug, Subcommand)]

crates/cli/src/commands_fix.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ pub(crate) fn run_fix(
99
args: FixArgs,
1010
config: FluffConfig,
1111
ignorer: impl Fn(&Path) -> bool + Send + Sync,
12+
collect_parse_errors: bool,
1213
) -> i32 {
1314
let FixArgs {
1415
paths,
1516
force,
1617
format,
1718
} = args;
18-
let mut linter = linter(config, format);
19+
let mut linter = linter(config, format, collect_parse_errors);
1920
let result = linter.lint_paths(paths, true, &ignorer);
2021

2122
if result
@@ -68,10 +69,14 @@ pub(crate) fn run_fix(
6869
}
6970
}
7071

71-
pub(crate) fn run_fix_stdin(config: FluffConfig, format: Format) -> i32 {
72+
pub(crate) fn run_fix_stdin(
73+
config: FluffConfig,
74+
format: Format,
75+
collect_parse_errors: bool,
76+
) -> i32 {
7277
let read_in = crate::stdin::read_std_in().unwrap();
7378

74-
let linter = linter(config, format);
79+
let linter = linter(config, format, collect_parse_errors);
7580
let result = linter.lint_string(&read_in, None, true);
7681

7782
// print fixed to std out

crates/cli/src/commands_lint.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ pub(crate) fn run_lint(
77
args: LintArgs,
88
config: FluffConfig,
99
ignorer: impl Fn(&Path) -> bool + Send + Sync,
10+
collect_parse_errors: bool,
1011
) -> i32 {
1112
let LintArgs { paths, format } = args;
12-
let mut linter = linter(config, format);
13+
let mut linter = linter(config, format, collect_parse_errors);
14+
1315
linter.lint_paths(paths, false, &ignorer);
1416

1517
linter.formatter().unwrap().completion_message();
@@ -20,10 +22,14 @@ pub(crate) fn run_lint(
2022
}
2123
}
2224

23-
pub(crate) fn run_lint_stdin(config: FluffConfig, format: Format) -> i32 {
25+
pub(crate) fn run_lint_stdin(
26+
config: FluffConfig,
27+
format: Format,
28+
collect_parse_errors: bool,
29+
) -> i32 {
2430
let read_in = crate::stdin::read_std_in().unwrap();
2531

26-
let linter = linter(config, format);
32+
let linter = linter(config, format, collect_parse_errors);
2733
linter.lint_string(&read_in, None, false);
2834

2935
linter.formatter().unwrap().completion_message();

crates/cli/src/main.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ fn main() {
4747
return codegen_docs();
4848

4949
let cli = Cli::parse();
50+
let collect_parse_errors = cli.parsing_errors;
5051

5152
let config: FluffConfig = if let Some(config) = cli.config.as_ref() {
5253
if !Path::new(config).is_file() {
@@ -77,16 +78,16 @@ fn main() {
7778
eprintln!("{e}");
7879
1
7980
}
80-
Ok(false) => commands_lint::run_lint(args, config, ignorer),
81-
Ok(true) => commands_lint::run_lint_stdin(config, args.format),
81+
Ok(false) => commands_lint::run_lint(args, config, ignorer, collect_parse_errors),
82+
Ok(true) => commands_lint::run_lint_stdin(config, args.format, collect_parse_errors),
8283
},
8384
Commands::Fix(args) => match is_std_in_flag_input(&args.paths) {
8485
Err(e) => {
8586
eprintln!("{e}");
8687
1
8788
}
88-
Ok(false) => commands_fix::run_fix(args, config, ignorer),
89-
Ok(true) => commands_fix::run_fix_stdin(config, args.format),
89+
Ok(false) => commands_fix::run_fix(args, config, ignorer, collect_parse_errors),
90+
Ok(true) => commands_fix::run_fix_stdin(config, args.format, collect_parse_errors),
9091
},
9192
Commands::Lsp => {
9293
sqruff_lsp::run();
@@ -97,7 +98,7 @@ fn main() {
9798
std::process::exit(status_code);
9899
}
99100

100-
pub(crate) fn linter(config: FluffConfig, format: Format) -> Linter {
101+
pub(crate) fn linter(config: FluffConfig, format: Format, collect_parse_errors: bool) -> Linter {
101102
let formatter: Arc<dyn Formatter> = match format {
102103
Format::Human => {
103104
let output_stream = std::io::stderr().into();
@@ -118,7 +119,7 @@ pub(crate) fn linter(config: FluffConfig, format: Format) -> Linter {
118119
}
119120
};
120121

121-
Linter::new(config, Some(formatter), None, false)
122+
Linter::new(config, Some(formatter), None, collect_parse_errors)
122123
}
123124

124125
fn check_user_input() -> Option<bool> {

crates/cli/tests/fix_parse_errors.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use core::str;
2+
use std::path::{Path, PathBuf};
3+
4+
use assert_cmd::Command;
5+
6+
fn main() {
7+
parse_errors();
8+
}
9+
10+
fn parse_errors() {
11+
let profile = if cfg!(debug_assertions) {
12+
"debug"
13+
} else {
14+
"release"
15+
};
16+
17+
let cargo_folder = Path::new(env!("CARGO_MANIFEST_DIR"));
18+
let mut sqruff_path = PathBuf::from(cargo_folder);
19+
sqruff_path.push(format!("../../target/{}/sqruff", profile));
20+
21+
// STDIN - do nothing
22+
let mut cmd = Command::new(sqruff_path.clone());
23+
cmd.env("HOME", PathBuf::from(env!("CARGO_MANIFEST_DIR")));
24+
cmd.arg("fix")
25+
.arg("-f")
26+
.arg("human")
27+
.arg("--parsing-errors")
28+
.arg("-");
29+
cmd.current_dir(cargo_folder);
30+
cmd.write_stdin("SelEc");
31+
32+
let assert = cmd.assert();
33+
let output = assert.get_output();
34+
35+
let stdout_str = str::from_utf8(&output.stdout).unwrap();
36+
let stderr_str = str::from_utf8(&output.stderr).unwrap();
37+
assert_eq!(stdout_str, "SelEc\n\n");
38+
assert_eq!(stderr_str, "== [<string>] FAIL\nL: 1 | P: 1 | ???? | Unparsable section\nL: 1 | P: 1 | LT12 | Files must end with a single trailing newline.\n | [layout.end_of_file]\n");
39+
assert_eq!(output.status.code().unwrap(), 1);
40+
}

crates/lib/src/core/linter/core.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ impl Linter {
480480
);
481481

482482
violations.extend(unparsables.into_iter().map(|segment| SQLParseError {
483-
description: "Found unparsable section".into(),
483+
description: "Unparsable section".into(),
484484
segment: segment.into(),
485485
}));
486486
}

docs/cli.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ sqruff is a sql formatter and linter
2424
###### **Options:**
2525

2626
* `--config <CONFIG>` — Path to a configuration file
27+
* `--parsing-errors` — Show parse errors
28+
29+
Default value: `false`
2730

2831

2932

0 commit comments

Comments
 (0)