Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ability to pipe fix and lint code #909

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
211 changes: 147 additions & 64 deletions crates/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ use commands::{FixArgs, Format, LintArgs};
use sqruff_lib::cli::formatters::OutputStreamFormatter;
use sqruff_lib::core::config::FluffConfig;
use sqruff_lib::core::linter::core::Linter;
use stdin::is_std_in_flag_input;
use std::path::Path;
use std::sync::Arc;
use std::io::Read;

use crate::commands::{Cli, Commands};
#[cfg(feature = "codegen-docs")]
Expand All @@ -15,6 +17,7 @@ mod commands;
mod docs;
mod github_action;
mod ignore;
mod stdin;

#[cfg(all(
not(target_os = "windows"),
Expand Down Expand Up @@ -59,90 +62,170 @@ fn main() {
match cli.command {
Commands::Lint(LintArgs { paths, format }) => {
let mut linter = linter(config, format);
let result = linter.lint_paths(paths, false, &ignorer);
let count: usize = result.paths.iter().map(|path| path.files.len()).sum();

// TODO this should be cleaned up better
if matches!(format, Format::GithubAnnotationNative) {
for path in result.paths {
for file in path.files {
for violation in file.violations {
let line = format!(
"::error title=sqruff,file={},line={},col={}::{}: {}",
file.path,
violation.line_no,
violation.line_pos,
violation.rule.as_ref().unwrap().code,
violation.description
);
eprintln!("{line}");

if is_std_in_flag_input(&paths) {
// Read SQL input from stdin
let mut sql_input = String::new();
std::io::stdin().read_to_string(&mut sql_input).unwrap();
// Lint the input SQL string
let result = linter.lint_string_wrapped(&sql_input, None, false);

if matches!(format, Format::GithubAnnotationNative) {
// Handle GithubAnnotationNative format
for path in result.paths {
for file in path.files {
for violation in file.violations {
let line = format!(
"::error title=sqruff,file={},line={},col={}::{}: {}",
file.path,
violation.line_no,
violation.line_pos,
violation.rule.as_ref().unwrap().code,
violation.description
);
eprintln!("{line}");
}
}
}
} else {
// Use formatter to output results
linter.formatter_mut().unwrap().dispatch_linting_result(&result);
}
}

eprintln!("The linter processed {count} file(s).");
linter.formatter_mut().unwrap().completion_message();
linter.formatter_mut().unwrap().completion_message();

std::process::exit(
if linter
.formatter()
.unwrap()
.has_fail
.load(std::sync::atomic::Ordering::SeqCst)
{
1
} else {
0
},
)
std::process::exit(
if linter
.formatter()
.unwrap()
.has_fail
.load(std::sync::atomic::Ordering::SeqCst)
{
1
} else {
0
},
);
} else {
let result = linter.lint_paths(paths, false, &ignorer);
let count: usize = result.paths.iter().map(|path| path.files.len()).sum();

// TODO this should be cleaned up better
if matches!(format, Format::GithubAnnotationNative) {
for path in result.paths {
for file in path.files {
for violation in file.violations {
let line = format!(
"::error title=sqruff,file={},line={},col={}::{}: {}",
file.path,
violation.line_no,
violation.line_pos,
violation.rule.as_ref().unwrap().code,
violation.description
);
eprintln!("{line}");
}
}
}
}

eprintln!("The linter processed {count} file(s).");
linter.formatter_mut().unwrap().completion_message();

std::process::exit(
if linter
.formatter()
.unwrap()
.has_fail
.load(std::sync::atomic::Ordering::SeqCst)
{
1
} else {
0
},
)
}
}
Commands::Fix(FixArgs {
paths,
force,
format,
}) => {
let mut linter = linter(config, format);
let result = linter.lint_paths(paths, true, &ignorer);

if result
.paths
.iter()
.map(|path| path.files.iter().all(|file| file.violations.is_empty()))
.all(|v| v)
{
let count_files = result

if is_std_in_flag_input(&paths) {
// Read SQL input from stdin
let mut sql_input = String::new();
std::io::stdin().read_to_string(&mut sql_input).unwrap();
// Fix the input SQL string
let result = linter.lint_string_wrapped(&sql_input, None, true);

if !result
.paths
.iter()
.map(|path| path.files.len())
.sum::<usize>();
println!("{} files processed, nothing to fix.", count_files);
return;
}

if !force {
match check_user_input() {
Some(true) => {
eprintln!("Attempting fixes...");
.flat_map(|path| &path.files)
.all(|file| file.violations.is_empty())
{
if !force {
match check_user_input() {
Some(true) => {
eprintln!("Attempting fixes...");
}
Some(false) => return,
None => {
eprintln!("Invalid input, please enter 'Y' or 'N'");
eprintln!("Aborting...");
return;
}
}
}
Some(false) => return,
None => {
eprintln!("Invalid input, please enter 'Y' or 'N'");
eprintln!("Aborting...");
return;
}

// Output the fixed SQL
let fixed_sql = result.paths[0].files[0].fix_string();
println!("{}", fixed_sql);
} else {
let result = linter.lint_paths(paths, true, &ignorer);

if result
.paths
.iter()
.map(|path| path.files.iter().all(|file| file.violations.is_empty()))
.all(|v| v)
{
let count_files = result
.paths
.iter()
.map(|path| path.files.len())
.sum::<usize>();
println!("{} files processed, nothing to fix.", count_files);
return;
}

if !force {
match check_user_input() {
Some(true) => {
eprintln!("Attempting fixes...");
}
Some(false) => return,
None => {
eprintln!("Invalid input, please enter 'Y' or 'N'");
eprintln!("Aborting...");
return;
}
}
}
}

for linted_dir in result.paths {
for mut file in linted_dir.files {
let path = std::mem::take(&mut file.path);
let write_buff = file.fix_string();
std::fs::write(path, write_buff).unwrap();
for linted_dir in result.paths {
for mut file in linted_dir.files {
let path = std::mem::take(&mut file.path);
let write_buff = file.fix_string();
std::fs::write(path, write_buff).unwrap();
}
}
}

linter.formatter_mut().unwrap().completion_message();
linter.formatter_mut().unwrap().completion_message();
}
}
Commands::Lsp => sqruff_lsp::run(),
}
Expand Down
3 changes: 3 additions & 0 deletions crates/cli/src/stdin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub fn is_std_in_flag_input(inputs: &Vec<String>) -> bool {
inputs == ["-"]
}
Loading