mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
parent
ae1f15ac1e
commit
4425b961cd
4 changed files with 81 additions and 19 deletions
|
|
@ -144,6 +144,7 @@ pub struct OutputOptions {
|
|||
pub enum OutputFormat {
|
||||
Default,
|
||||
Json,
|
||||
Unix,
|
||||
}
|
||||
|
||||
impl FromStr for OutputFormat {
|
||||
|
|
@ -152,6 +153,7 @@ impl FromStr for OutputFormat {
|
|||
match s {
|
||||
"json" => Ok(Self::Json),
|
||||
"default" => Ok(Self::Default),
|
||||
"unix" => Ok(Self::Unix),
|
||||
_ => Err(format!("'{s}' is not a known format")),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@ impl LintRunner {
|
|||
match output_options.format {
|
||||
OutputFormat::Default => {}
|
||||
OutputFormat::Json => diagnostic_service.set_json_reporter(),
|
||||
OutputFormat::Unix => diagnostic_service.set_unix_reporter(),
|
||||
}
|
||||
|
||||
diagnostic_service
|
||||
|
|
|
|||
|
|
@ -2,31 +2,37 @@ use std::io::{BufWriter, Stdout, Write};
|
|||
|
||||
use crate::{
|
||||
miette::{Error, JSONReportHandler},
|
||||
GraphicalReportHandler,
|
||||
GraphicalReportHandler, Severity,
|
||||
};
|
||||
|
||||
/// stdio is blocked by LineWriter, use a BufWriter to reduce syscalls.
|
||||
/// See `https://github.com/rust-lang/rust/issues/60673`.
|
||||
fn writer() -> BufWriter<Stdout> {
|
||||
BufWriter::new(std::io::stdout())
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)] // Lerge size is fine because this is a singleton
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum DiagnosticReporter {
|
||||
// stdio is blocked by LineWriter, use a BufWriter to reduce syscalls.
|
||||
// See `https://github.com/rust-lang/rust/issues/60673`.
|
||||
Graphical { handler: GraphicalReportHandler, writer: BufWriter<Stdout> },
|
||||
Json { diagnostics: Vec<Error> },
|
||||
Unix { total: usize, writer: BufWriter<Stdout> },
|
||||
}
|
||||
|
||||
impl DiagnosticReporter {
|
||||
pub fn new_graphical() -> Self {
|
||||
Self::Graphical {
|
||||
handler: GraphicalReportHandler::new(),
|
||||
writer: BufWriter::new(std::io::stdout()),
|
||||
}
|
||||
Self::Graphical { handler: GraphicalReportHandler::new(), writer: writer() }
|
||||
}
|
||||
|
||||
pub fn new_json() -> Self {
|
||||
Self::Json { diagnostics: vec![] }
|
||||
}
|
||||
|
||||
pub fn new_unix() -> Self {
|
||||
Self::Unix { total: 0, writer: writer() }
|
||||
}
|
||||
|
||||
pub fn finish(&mut self) {
|
||||
match self {
|
||||
Self::Graphical { writer, .. } => {
|
||||
|
|
@ -35,24 +41,21 @@ impl DiagnosticReporter {
|
|||
// NOTE: this output does not conform to eslint json format yet
|
||||
// https://eslint.org/docs/latest/use/formatters/#json
|
||||
Self::Json { diagnostics } => {
|
||||
let handler = JSONReportHandler::new();
|
||||
let messages = diagnostics
|
||||
.drain(..)
|
||||
.map(|error| {
|
||||
let mut output = String::from("\t");
|
||||
handler.render_report(&mut output, error.as_ref()).unwrap();
|
||||
output
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(",\n");
|
||||
println!("[\n{messages}\n]");
|
||||
format_json(diagnostics);
|
||||
}
|
||||
Self::Unix { total, writer } => {
|
||||
if *total > 0 {
|
||||
let line = format!("\n{total} problem{}\n", if *total > 1 { "s" } else { "" });
|
||||
writer.write_all(line.as_bytes()).unwrap();
|
||||
}
|
||||
writer.flush().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_diagnostics(&mut self, s: &[u8]) {
|
||||
match self {
|
||||
Self::Graphical { writer, .. } => {
|
||||
Self::Graphical { writer, .. } | Self::Unix { writer, .. } => {
|
||||
writer.write_all(s).unwrap();
|
||||
}
|
||||
Self::Json { .. } => {}
|
||||
|
|
@ -70,6 +73,58 @@ impl DiagnosticReporter {
|
|||
diagnostics.push(error);
|
||||
None
|
||||
}
|
||||
Self::Unix { total: count, .. } => {
|
||||
*count += 1;
|
||||
Some(format_unix(&error))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://github.com/fregante/eslint-formatters/tree/main/packages/eslint-formatter-json>
|
||||
fn format_json(diagnostics: &mut Vec<Error>) {
|
||||
let handler = JSONReportHandler::new();
|
||||
let messages = diagnostics
|
||||
.drain(..)
|
||||
.map(|error| {
|
||||
let mut output = String::from("\t");
|
||||
handler.render_report(&mut output, error.as_ref()).unwrap();
|
||||
output
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(",\n");
|
||||
println!("[\n{messages}\n]");
|
||||
}
|
||||
|
||||
/// <https://github.com/fregante/eslint-formatters/tree/main/packages/eslint-formatter-unix>
|
||||
fn format_unix(diagnostic: &Error) -> String {
|
||||
let mut line = 0;
|
||||
let mut column = 0;
|
||||
let mut filename = String::new();
|
||||
let mut message = String::new();
|
||||
let mut severity = "Warning";
|
||||
let mut rule_id = String::new();
|
||||
if let Some(mut labels) = diagnostic.labels() {
|
||||
if let Some(source) = diagnostic.source_code() {
|
||||
if let Some(label) = labels.next() {
|
||||
if let Ok(span_content) = source.read_span(label.inner(), 0, 0) {
|
||||
line = span_content.line() + 1;
|
||||
column = span_content.column() + 1;
|
||||
if let Some(name) = span_content.name() {
|
||||
filename = name.to_string();
|
||||
};
|
||||
if matches!(diagnostic.severity(), Some(Severity::Error)) {
|
||||
severity = "Warning";
|
||||
}
|
||||
let msg = diagnostic.to_string();
|
||||
// Our messages usually comes with `eslint(rule): message`
|
||||
(rule_id, message) = msg.split_once(':').map_or_else(
|
||||
|| (String::new(), msg.to_string()),
|
||||
|(id, msg)| (id.to_string(), msg.trim().to_string()),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
format!("{filename}:{line}:{column}: {message} [{severity}/{rule_id}]\n")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,10 @@ impl DiagnosticService {
|
|||
self.reporter = DiagnosticReporter::new_json();
|
||||
}
|
||||
|
||||
pub fn set_unix_reporter(&mut self) {
|
||||
self.reporter = DiagnosticReporter::new_unix();
|
||||
}
|
||||
|
||||
pub fn is_graphical_output(&self) -> bool {
|
||||
matches!(self.reporter, DiagnosticReporter::Graphical { .. })
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue