Skip to content

Commit

Permalink
feat: ability to pipe fix and lint code
Browse files Browse the repository at this point in the history
  • Loading branch information
benfdking committed Oct 30, 2024
1 parent 45dc1f1 commit d523997
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 64 deletions.
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 == ["-"]
}

0 comments on commit d523997

Please sign in to comment.