mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
refactor(linter): add output formatter (#8436)
I want to start grouping all the different Formats for action X, Y and Z into own place. This is the first step and probably not the best one to be honest :) ~~I prefer that the `OutputFormatter` is a part of `oxlint` and not `oxc_linter`~~ ~~but all `use create::rules::RULES` is not public from outside.~~ EDIT: I pushed a commit with this changes can easily be reverted and move back to `oxc_linter` Also their is a crate `oxc_diagnostics` which has already the concept too but only for the lint part of `oxlint` and not for the other parts. The next goal would be splitting the `DiagnosticService` with its reporters to `oxlint`.
This commit is contained in:
parent
01722f34ff
commit
43ed3e1722
10 changed files with 128 additions and 81 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -2217,6 +2217,8 @@ dependencies = [
|
|||
"oxc_linter",
|
||||
"oxc_span",
|
||||
"rayon",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ bpaf = { workspace = true, features = ["autocomplete", "bright-color", "derive"]
|
|||
ignore = { workspace = true, features = ["simd-accel"] }
|
||||
miette = { workspace = true }
|
||||
rayon = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
tempfile = { workspace = true }
|
||||
tracing-subscriber = { workspace = true, features = [] } # Omit the `regex` feature
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
use std::{path::PathBuf, str::FromStr};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use bpaf::Bpaf;
|
||||
use oxc_linter::{AllowWarnDeny, FixKind, LintPlugins};
|
||||
|
||||
use crate::output_formatter::OutputFormat;
|
||||
|
||||
use super::{
|
||||
ignore::{ignore_options, IgnoreOptions},
|
||||
misc_options, validate_paths, MiscOptions, PATHS_ERROR_MESSAGE, VERSION,
|
||||
|
|
@ -184,32 +186,6 @@ pub struct OutputOptions {
|
|||
pub format: OutputFormat,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum OutputFormat {
|
||||
Default,
|
||||
/// GitHub Check Annotation
|
||||
/// <https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-a-notice-message>
|
||||
Github,
|
||||
Json,
|
||||
Unix,
|
||||
Checkstyle,
|
||||
}
|
||||
|
||||
impl FromStr for OutputFormat {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"json" => Ok(Self::Json),
|
||||
"default" => Ok(Self::Default),
|
||||
"unix" => Ok(Self::Unix),
|
||||
"checkstyle" => Ok(Self::Checkstyle),
|
||||
"github" => Ok(Self::Github),
|
||||
_ => Err(format!("'{s}' is not a known format")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Enable Plugins
|
||||
#[allow(clippy::struct_field_names)]
|
||||
#[derive(Debug, Default, Clone, Bpaf)]
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use bpaf::Bpaf;
|
|||
|
||||
pub use self::{
|
||||
ignore::IgnoreOptions,
|
||||
lint::{lint_command, LintCommand, OutputFormat, OutputOptions, WarningOptions},
|
||||
lint::{lint_command, LintCommand, OutputOptions, WarningOptions},
|
||||
};
|
||||
|
||||
const VERSION: &str = match option_env!("OXC_VERSION") {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
mod command;
|
||||
mod lint;
|
||||
mod output_formatter;
|
||||
mod result;
|
||||
mod runner;
|
||||
mod walk;
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ use oxc_span::VALID_EXTENSIONS;
|
|||
|
||||
use crate::{
|
||||
cli::{
|
||||
CliRunResult, LintCommand, LintResult, MiscOptions, OutputFormat, OutputOptions, Runner,
|
||||
WarningOptions,
|
||||
CliRunResult, LintCommand, LintResult, MiscOptions, OutputOptions, Runner, WarningOptions,
|
||||
},
|
||||
output_formatter::{OutputFormat, OutputFormatter},
|
||||
walk::{Extensions, Walk},
|
||||
};
|
||||
|
||||
|
|
@ -36,13 +36,12 @@ impl Runner for LintRunner {
|
|||
}
|
||||
|
||||
fn run(self) -> CliRunResult {
|
||||
let format_str = self.options.output_options.format;
|
||||
let output_formatter = OutputFormatter::new(format_str);
|
||||
|
||||
if self.options.list_rules {
|
||||
let mut stdout = BufWriter::new(std::io::stdout());
|
||||
if self.options.output_options.format == OutputFormat::Json {
|
||||
Linter::print_rules_json(&mut stdout);
|
||||
} else {
|
||||
Linter::print_rules(&mut stdout);
|
||||
}
|
||||
output_formatter.all_rules(&mut stdout);
|
||||
return CliRunResult::None;
|
||||
}
|
||||
|
||||
|
|
|
|||
29
apps/oxlint/src/output_formatter/default.rs
Normal file
29
apps/oxlint/src/output_formatter/default.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
use std::io::Write;
|
||||
|
||||
use oxc_linter::table::RuleTable;
|
||||
|
||||
pub struct DefaultOutputFormatter;
|
||||
|
||||
impl DefaultOutputFormatter {
|
||||
pub fn all_rules<T: Write>(writer: &mut T) {
|
||||
let table = RuleTable::new();
|
||||
for section in table.sections {
|
||||
writeln!(writer, "{}", section.render_markdown_table(None)).unwrap();
|
||||
}
|
||||
writeln!(writer, "Default: {}", table.turned_on_by_default_count).unwrap();
|
||||
writeln!(writer, "Total: {}", table.total).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::output_formatter::default::DefaultOutputFormatter;
|
||||
|
||||
#[test]
|
||||
fn all_rules() {
|
||||
let mut writer = Vec::new();
|
||||
|
||||
DefaultOutputFormatter::all_rules(&mut writer);
|
||||
assert!(!writer.is_empty());
|
||||
}
|
||||
}
|
||||
31
apps/oxlint/src/output_formatter/json.rs
Normal file
31
apps/oxlint/src/output_formatter/json.rs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
use oxc_linter::rules::RULES;
|
||||
use oxc_linter::RuleCategory;
|
||||
use std::io::Write;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct JsonOutputFormatter;
|
||||
|
||||
impl JsonOutputFormatter {
|
||||
pub fn all_rules<T: Write>(writer: &mut T) {
|
||||
#[derive(Debug, serde::Serialize)]
|
||||
struct RuleInfoJson<'a> {
|
||||
scope: &'a str,
|
||||
value: &'a str,
|
||||
category: RuleCategory,
|
||||
}
|
||||
|
||||
let rules_info = RULES.iter().map(|rule| RuleInfoJson {
|
||||
scope: rule.plugin_name(),
|
||||
value: rule.name(),
|
||||
category: rule.category(),
|
||||
});
|
||||
|
||||
writer
|
||||
.write_all(
|
||||
serde_json::to_string_pretty(&rules_info.collect::<Vec<_>>())
|
||||
.expect("Failed to serialize")
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
50
apps/oxlint/src/output_formatter/mod.rs
Normal file
50
apps/oxlint/src/output_formatter/mod.rs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
mod default;
|
||||
mod json;
|
||||
|
||||
use std::io::Write;
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::output_formatter::{default::DefaultOutputFormatter, json::JsonOutputFormatter};
|
||||
|
||||
pub struct OutputFormatter {
|
||||
format: OutputFormat,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum OutputFormat {
|
||||
Default,
|
||||
/// GitHub Check Annotation
|
||||
/// <https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-a-notice-message>
|
||||
Github,
|
||||
Json,
|
||||
Unix,
|
||||
Checkstyle,
|
||||
}
|
||||
|
||||
impl FromStr for OutputFormat {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"json" => Ok(Self::Json),
|
||||
"default" => Ok(Self::Default),
|
||||
"unix" => Ok(Self::Unix),
|
||||
"checkstyle" => Ok(Self::Checkstyle),
|
||||
"github" => Ok(Self::Github),
|
||||
_ => Err(format!("'{s}' is not a known format")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OutputFormatter {
|
||||
pub fn new(format: OutputFormat) -> Self {
|
||||
Self { format }
|
||||
}
|
||||
// print all rules which are currently supported by oxlint
|
||||
pub fn all_rules<T: Write>(&self, writer: &mut T) {
|
||||
match self.format {
|
||||
OutputFormat::Json => JsonOutputFormatter::all_rules(writer),
|
||||
_ => DefaultOutputFormatter::all_rules(writer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,17 +15,16 @@ mod module_graph_visitor;
|
|||
mod module_record;
|
||||
mod options;
|
||||
mod rule;
|
||||
mod rules;
|
||||
mod service;
|
||||
mod utils;
|
||||
|
||||
pub mod loader;
|
||||
pub mod rules;
|
||||
pub mod table;
|
||||
|
||||
use std::{io::Write, path::Path, rc::Rc, sync::Arc};
|
||||
use std::{path::Path, rc::Rc, sync::Arc};
|
||||
|
||||
use oxc_semantic::{AstNode, Semantic};
|
||||
use rules::RULES;
|
||||
|
||||
pub use crate::{
|
||||
config::{
|
||||
|
|
@ -45,7 +44,6 @@ use crate::{
|
|||
context::ContextHost,
|
||||
fixer::{Fixer, Message},
|
||||
rules::RuleEnum,
|
||||
table::RuleTable,
|
||||
utils::iter_possible_jest_call_node,
|
||||
};
|
||||
|
||||
|
|
@ -183,52 +181,11 @@ impl Linter {
|
|||
|
||||
ctx_host.take_diagnostics()
|
||||
}
|
||||
|
||||
/// # Panics
|
||||
pub fn print_rules<W: Write>(writer: &mut W) {
|
||||
let table = RuleTable::new();
|
||||
for section in table.sections {
|
||||
writeln!(writer, "{}", section.render_markdown_table(None)).unwrap();
|
||||
}
|
||||
writeln!(writer, "Default: {}", table.turned_on_by_default_count).unwrap();
|
||||
writeln!(writer, "Total: {}", table.total).unwrap();
|
||||
}
|
||||
|
||||
/// # Panics
|
||||
pub fn print_rules_json<W: Write>(writer: &mut W) {
|
||||
#[derive(Debug, serde::Serialize)]
|
||||
struct RuleInfoJson<'a> {
|
||||
scope: &'a str,
|
||||
value: &'a str,
|
||||
category: RuleCategory,
|
||||
}
|
||||
|
||||
let rules_info = RULES.iter().map(|rule| RuleInfoJson {
|
||||
scope: rule.plugin_name(),
|
||||
value: rule.name(),
|
||||
category: rule.category(),
|
||||
});
|
||||
|
||||
writer
|
||||
.write_all(
|
||||
serde_json::to_string_pretty(&rules_info.collect::<Vec<_>>())
|
||||
.expect("Failed to serialize")
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{Linter, Oxlintrc};
|
||||
|
||||
#[test]
|
||||
fn print_rules() {
|
||||
let mut writer = Vec::new();
|
||||
Linter::print_rules(&mut writer);
|
||||
assert!(!writer.is_empty());
|
||||
}
|
||||
use super::Oxlintrc;
|
||||
|
||||
#[test]
|
||||
fn test_schema_json() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue