Skip to content

Commit 17c3b0a

Browse files
committed
refactor(linter): move stdout outside LintRunnter
1 parent 10e5920 commit 17c3b0a

File tree

10 files changed

+65
-60
lines changed

10 files changed

+65
-60
lines changed

apps/oxlint/src/lint.rs

+21-15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{
22
env, fs,
3-
io::{BufWriter, ErrorKind, Write},
3+
io::{ErrorKind, Write},
44
path::{Path, PathBuf},
55
process::ExitCode,
66
time::Instant,
@@ -34,16 +34,14 @@ impl Runner for LintRunner {
3434
Self { options, cwd: env::current_dir().expect("Failed to get current working directory") }
3535
}
3636

37-
fn run(self) -> CliRunResult {
37+
fn run(self, stdout: &mut dyn Write) -> CliRunResult {
3838
let format_str = self.options.output_options.format;
39-
let mut output_formatter = OutputFormatter::new(format_str);
40-
41-
// stdio is blocked by LineWriter, use a BufWriter to reduce syscalls.
42-
// See `https://github.com/rust-lang/rust/issues/60673`.
43-
let mut stdout = BufWriter::new(std::io::stdout());
39+
let output_formatter = OutputFormatter::new(format_str);
4440

4541
if self.options.list_rules {
46-
output_formatter.all_rules(&mut stdout);
42+
if let Some(output) = output_formatter.all_rules() {
43+
stdout.write_all(output.as_bytes()).or_else(Self::check_for_writer_error).unwrap();
44+
}
4745
stdout.flush().unwrap();
4846
return CliRunResult::None;
4947
}
@@ -206,7 +204,7 @@ impl Runner for LintRunner {
206204
}
207205
});
208206

209-
let diagnostic_result = diagnostic_service.run(&mut stdout);
207+
let diagnostic_result = diagnostic_service.run(stdout);
210208

211209
let diagnostic_failed = diagnostic_result.max_warnings_exceeded()
212210
|| diagnostic_result.errors_count() > 0
@@ -334,7 +332,9 @@ mod test {
334332
let mut new_args = vec!["--silent"];
335333
new_args.extend(args);
336334
let options = lint_command().run_inner(new_args.as_slice()).unwrap();
337-
match LintRunner::new(options).run() {
335+
let mut output = Vec::new();
336+
337+
match LintRunner::new(options).run(&mut output) {
338338
CliRunResult::LintResult(lint_result) => lint_result,
339339
other => panic!("{other:?}"),
340340
}
@@ -356,8 +356,9 @@ mod test {
356356
};
357357

358358
current_cwd.push(part_cwd);
359+
let mut output = Vec::new();
359360

360-
match LintRunner::new(options).with_cwd(current_cwd).run() {
361+
match LintRunner::new(options).with_cwd(current_cwd).run(&mut output) {
361362
CliRunResult::LintResult(lint_result) => lint_result,
362363
other => panic!("{other:?}"),
363364
}
@@ -367,7 +368,9 @@ mod test {
367368
let mut new_args = vec!["--quiet"];
368369
new_args.extend(args);
369370
let options = lint_command().run_inner(new_args.as_slice()).unwrap();
370-
match LintRunner::new(options).run() {
371+
let mut output = Vec::new();
372+
373+
match LintRunner::new(options).run(&mut output) {
371374
CliRunResult::InvalidOptions { message } => message,
372375
other => {
373376
panic!("Expected InvalidOptions, got {other:?}");
@@ -752,7 +755,8 @@ mod test {
752755
fn test_print_config_ban_all_rules() {
753756
let args = &["-A", "all", "--print-config"];
754757
let options = lint_command().run_inner(args).unwrap();
755-
let ret = LintRunner::new(options).run();
758+
let mut output = Vec::new();
759+
let ret = LintRunner::new(options).run(&mut output);
756760
let CliRunResult::PrintConfigResult { config_file: config } = ret else {
757761
panic!("Expected PrintConfigResult, got {ret:?}")
758762
};
@@ -776,7 +780,8 @@ mod test {
776780
"--print-config",
777781
];
778782
let options = lint_command().run_inner(args).unwrap();
779-
let ret = LintRunner::new(options).run();
783+
let mut output = Vec::new();
784+
let ret = LintRunner::new(options).run(&mut output);
780785
let CliRunResult::PrintConfigResult { config_file: config } = ret else {
781786
panic!("Expected PrintConfigResult, got {ret:?}")
782787
};
@@ -793,7 +798,8 @@ mod test {
793798
fn test_init_config() {
794799
let args = &["--init"];
795800
let options = lint_command().run_inner(args).unwrap();
796-
let ret = LintRunner::new(options).run();
801+
let mut output = Vec::new();
802+
let ret = LintRunner::new(options).run(&mut output);
797803
let CliRunResult::ConfigFileInitResult { message } = ret else {
798804
panic!("Expected configuration file to be created, got {ret:?}")
799805
};

apps/oxlint/src/main.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,19 @@ static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc;
88
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
99

1010
use oxlint::cli::{CliRunResult, LintRunner, Runner};
11+
use std::io::BufWriter;
1112

1213
fn main() -> CliRunResult {
1314
init_tracing();
1415
init_miette();
1516

1617
let command = oxlint::cli::lint_command().run();
1718
command.handle_threads();
18-
LintRunner::new(command).run()
19+
// stdio is blocked by LineWriter, use a BufWriter to reduce syscalls.
20+
// See `https://github.com/rust-lang/rust/issues/60673`.
21+
let mut stdout = BufWriter::new(std::io::stdout());
22+
23+
LintRunner::new(command).run(&mut stdout)
1924
}
2025

2126
// Initialize the data which relies on `is_atty` system calls so they don't block subsequent threads.

apps/oxlint/src/output_formatter/checkstyle.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{borrow::Cow, io::Write};
1+
use std::borrow::Cow;
22

33
use rustc_hash::FxHashMap;
44

@@ -13,8 +13,8 @@ use crate::output_formatter::InternalFormatter;
1313
pub struct CheckStyleOutputFormatter;
1414

1515
impl InternalFormatter for CheckStyleOutputFormatter {
16-
fn all_rules(&mut self, writer: &mut dyn Write) {
17-
writeln!(writer, "flag --rules with flag --format=checkstyle is not allowed").unwrap();
16+
fn all_rules(&self) -> Option<String> {
17+
None
1818
}
1919

2020
fn get_diagnostic_reporter(&self) -> Box<dyn DiagnosticReporter> {

apps/oxlint/src/output_formatter/default.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{io::Write, time::Duration};
1+
use std::time::Duration;
22

33
use oxc_diagnostics::{
44
reporter::{DiagnosticReporter, DiagnosticResult},
@@ -12,13 +12,16 @@ use crate::output_formatter::InternalFormatter;
1212
pub struct DefaultOutputFormatter;
1313

1414
impl InternalFormatter for DefaultOutputFormatter {
15-
fn all_rules(&mut self, writer: &mut dyn Write) {
15+
fn all_rules(&self) -> Option<String> {
16+
let mut output = String::new();
1617
let table = RuleTable::new();
1718
for section in table.sections {
18-
writeln!(writer, "{}", section.render_markdown_table(None)).unwrap();
19+
output.push_str(section.render_markdown_table(None).as_str());
20+
output.push('\n');
1921
}
20-
writeln!(writer, "Default: {}", table.turned_on_by_default_count).unwrap();
21-
writeln!(writer, "Total: {}", table.total).unwrap();
22+
output.push_str(format!("Default: {}\n", table.turned_on_by_default_count).as_str());
23+
output.push_str(format!("Total: {}\n", table.total).as_str());
24+
Some(output)
2225
}
2326

2427
fn lint_command_info(&self, lint_command_info: &super::LintCommandInfo) -> Option<String> {
@@ -125,11 +128,10 @@ mod test {
125128

126129
#[test]
127130
fn all_rules() {
128-
let mut writer = Vec::new();
129-
let mut formatter = DefaultOutputFormatter;
131+
let formatter = DefaultOutputFormatter;
132+
let result = formatter.all_rules();
130133

131-
formatter.all_rules(&mut writer);
132-
assert!(!writer.is_empty());
134+
assert!(result.is_some());
133135
}
134136

135137
#[test]

apps/oxlint/src/output_formatter/github.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{borrow::Cow, io::Write};
1+
use std::borrow::Cow;
22

33
use oxc_diagnostics::{
44
reporter::{DiagnosticReporter, DiagnosticResult, Info},
@@ -11,8 +11,8 @@ use crate::output_formatter::InternalFormatter;
1111
pub struct GithubOutputFormatter;
1212

1313
impl InternalFormatter for GithubOutputFormatter {
14-
fn all_rules(&mut self, writer: &mut dyn Write) {
15-
writeln!(writer, "flag --rules with flag --format=github is not allowed").unwrap();
14+
fn all_rules(&self) -> Option<String> {
15+
None
1616
}
1717

1818
fn get_diagnostic_reporter(&self) -> Box<dyn DiagnosticReporter> {

apps/oxlint/src/output_formatter/json.rs

+10-14
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
use std::io::Write;
2-
3-
use oxc_diagnostics::reporter::DiagnosticResult;
4-
use oxc_diagnostics::{reporter::DiagnosticReporter, Error};
5-
use oxc_linter::rules::RULES;
6-
use oxc_linter::RuleCategory;
1+
use oxc_diagnostics::{
2+
reporter::{DiagnosticReporter, DiagnosticResult},
3+
Error,
4+
};
5+
use oxc_linter::{rules::RULES, RuleCategory};
76

87
use miette::JSONReportHandler;
98

@@ -13,7 +12,7 @@ use crate::output_formatter::InternalFormatter;
1312
pub struct JsonOutputFormatter;
1413

1514
impl InternalFormatter for JsonOutputFormatter {
16-
fn all_rules(&mut self, writer: &mut dyn Write) {
15+
fn all_rules(&self) -> Option<String> {
1716
#[derive(Debug, serde::Serialize)]
1817
struct RuleInfoJson<'a> {
1918
scope: &'a str,
@@ -27,13 +26,10 @@ impl InternalFormatter for JsonOutputFormatter {
2726
category: rule.category(),
2827
});
2928

30-
writer
31-
.write_all(
32-
serde_json::to_string_pretty(&rules_info.collect::<Vec<_>>())
33-
.expect("Failed to serialize")
34-
.as_bytes(),
35-
)
36-
.unwrap();
29+
Some(
30+
serde_json::to_string_pretty(&rules_info.collect::<Vec<_>>())
31+
.expect("Failed to serialize"),
32+
)
3733
}
3834

3935
fn get_diagnostic_reporter(&self) -> Box<dyn DiagnosticReporter> {

apps/oxlint/src/output_formatter/mod.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ mod json;
55
mod stylish;
66
mod unix;
77

8-
use std::io::{BufWriter, Stdout, Write};
98
use std::str::FromStr;
109
use std::time::Duration;
1110

@@ -63,10 +62,7 @@ pub struct LintCommandInfo {
6362
/// The Formatter is then managed by [`OutputFormatter`].
6463
trait InternalFormatter {
6564
/// Print all available rules by oxlint
66-
/// Some Formatter do not know how to output the rules in the style,
67-
/// instead you should print out that this combination of flags is not supported.
68-
/// Example: "flag --rules with flag --format=checkstyle is not allowed"
69-
fn all_rules(&mut self, writer: &mut dyn Write);
65+
fn all_rules(&self) -> Option<String>;
7066

7167
/// At the end of the Lint command the Formatter can output extra information.
7268
fn lint_command_info(&self, _lint_command_info: &LintCommandInfo) -> Option<String> {
@@ -100,8 +96,8 @@ impl OutputFormatter {
10096

10197
/// Print all available rules by oxlint
10298
/// See [`InternalFormatter::all_rules`] for more details.
103-
pub fn all_rules(&mut self, writer: &mut BufWriter<Stdout>) {
104-
self.internal.all_rules(writer);
99+
pub fn all_rules(&self) -> Option<String> {
100+
self.internal.all_rules()
105101
}
106102

107103
/// At the end of the Lint command we may output extra information.

apps/oxlint/src/output_formatter/stylish.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::io::Write;
2-
31
use oxc_diagnostics::{
42
reporter::{DiagnosticReporter, DiagnosticResult, Info},
53
Error, Severity,
@@ -12,8 +10,8 @@ use crate::output_formatter::InternalFormatter;
1210
pub struct StylishOutputFormatter;
1311

1412
impl InternalFormatter for StylishOutputFormatter {
15-
fn all_rules(&mut self, writer: &mut dyn Write) {
16-
writeln!(writer, "flag --rules with flag --format=stylish is not allowed").unwrap();
13+
fn all_rules(&self) -> Option<String> {
14+
None
1715
}
1816

1917
fn get_diagnostic_reporter(&self) -> Box<dyn DiagnosticReporter> {

apps/oxlint/src/output_formatter/unix.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{borrow::Cow, io::Write};
1+
use std::borrow::Cow;
22

33
use oxc_diagnostics::{
44
reporter::{DiagnosticReporter, DiagnosticResult, Info},
@@ -11,8 +11,8 @@ use crate::output_formatter::InternalFormatter;
1111
pub struct UnixOutputFormatter;
1212

1313
impl InternalFormatter for UnixOutputFormatter {
14-
fn all_rules(&mut self, writer: &mut dyn Write) {
15-
writeln!(writer, "flag --rules with flag --format=unix is not allowed").unwrap();
14+
fn all_rules(&self) -> Option<String> {
15+
None
1616
}
1717

1818
fn get_diagnostic_reporter(&self) -> Box<dyn DiagnosticReporter> {

apps/oxlint/src/runner.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::io::Write;
2+
13
use crate::cli::CliRunResult;
24

35
/// A trait for exposing functionality to the CLI.
@@ -7,5 +9,5 @@ pub trait Runner {
79
fn new(matches: Self::Options) -> Self;
810

911
/// Executes the runner, providing some result to the CLI.
10-
fn run(self) -> CliRunResult;
12+
fn run(self, stdout: &mut dyn Write) -> CliRunResult;
1113
}

0 commit comments

Comments
 (0)