mirror of
https://github.com/aphrody-labs/oxc.git
synced 2026-10-15 06:39:17 +00:00
perf(diagnostics): use fixed ANSI styles (#26130)
Replace dynamic diagnostic styles with fixed ANSI prefixes, reducing `oxfmt` and `oxlint` release text size. AI assistance: Codex was used. The contributor remains responsible for this change.
This commit is contained in:
10 files changed
+101
-48
No files matched your search
Generated
-1
@@ -1992,7 +1992,6 @@ dependencies = [
|
||||
"cow-utils",
|
||||
"itoa",
|
||||
"memchr",
|
||||
"owo-colors",
|
||||
"oxc_span",
|
||||
"percent-encoding",
|
||||
"smallvec",
|
||||
|
||||
@@ -243,7 +243,6 @@ oxc-css-parser = "0.0.11" # CSS/SCSS/Less parser (raffia 0.12.3 fork: adds `temp
|
||||
oxc-graphql-parser = "0.0.9" # GraphQL parser (direct AST; apollo-parser 0.8.6 fork aligned with graphql-js 17 syntax)
|
||||
oxc-toml = "0.14.5" # TOML formatter
|
||||
oxc-yaml-parser = "0.0.5" # YAML 1.2 parser (comment-preserving typed AST, node naming from `yaml-unist-parser`)
|
||||
owo-colors = "4.3.0" # Terminal colors
|
||||
papaya = "0.2.4" # Concurrent hash map
|
||||
percent-encoding = "2.3.2" # URL encoding
|
||||
petgraph = { version = "0.8.3", default-features = false } # Graph data structures
|
||||
|
||||
@@ -223,16 +223,16 @@ impl WalkRunner {
|
||||
// Color support is detected the same way as `GraphicalReportHandler` used by `DefaultReporter`,
|
||||
// and when colors are disabled, every style is empty and renders nothing.
|
||||
// `ListDifferent` mode output is meant for piping, keep it style-free.
|
||||
let warning_style = matches!(format_mode, OutputMode::Check)
|
||||
.then(|| GraphicalTheme::default().warning_style());
|
||||
let warning_theme =
|
||||
matches!(format_mode, OutputMode::Check).then(GraphicalTheme::default);
|
||||
let mut output = String::new();
|
||||
for (idx, (path, elapsed)) in changed_paths.into_iter().enumerate() {
|
||||
if idx != 0 {
|
||||
output.push('\n');
|
||||
}
|
||||
match warning_style {
|
||||
match &warning_theme {
|
||||
// Style per line, some log viewers reset ANSI state on line breaks
|
||||
Some(style) => write!(output, "{}", style.style(&path)).unwrap(),
|
||||
Some(theme) => theme.write_warning(&mut output, &path).unwrap(),
|
||||
None => output.push_str(&path),
|
||||
}
|
||||
if let Some(elapsed) = elapsed {
|
||||
|
||||
@@ -23,7 +23,6 @@ bytecount = { workspace = true }
|
||||
cow-utils = { workspace = true }
|
||||
itoa = { workspace = true }
|
||||
memchr = { workspace = true }
|
||||
owo-colors = { workspace = true }
|
||||
percent-encoding = { workspace = true }
|
||||
smallvec = { workspace = true }
|
||||
textwrap = { workspace = true }
|
||||
|
||||
@@ -8,14 +8,13 @@
|
||||
|
||||
use std::fmt::{self, Write};
|
||||
|
||||
use owo_colors::OwoColorize;
|
||||
|
||||
use super::{
|
||||
handler::GraphicalReportHandler,
|
||||
label::write_repeated_char,
|
||||
line::Line,
|
||||
span::{FancySpan, LabelRenderMode},
|
||||
};
|
||||
use crate::handlers::theme::DiagnosticColorize;
|
||||
|
||||
impl GraphicalReportHandler {
|
||||
pub(super) fn write_linum(
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
use std::{cmp::max, fmt};
|
||||
|
||||
use owo_colors::{OwoColorize, Style};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use super::{
|
||||
@@ -17,7 +16,7 @@ use super::{
|
||||
line::Line,
|
||||
span::{FancySpan, LabelRenderMode},
|
||||
};
|
||||
use crate::handlers::theme::ThemeCharacters;
|
||||
use crate::handlers::theme::{DiagnosticColorize, Style, ThemeCharacters};
|
||||
|
||||
struct Underline {
|
||||
padding: usize,
|
||||
@@ -351,7 +350,7 @@ mod tests {
|
||||
let label = LabelText {
|
||||
chars: &theme.characters,
|
||||
label: "plain label",
|
||||
style: Style::new(),
|
||||
style: Style::Plain,
|
||||
render_mode,
|
||||
};
|
||||
output.clear();
|
||||
|
||||
@@ -9,11 +9,10 @@
|
||||
|
||||
use std::fmt::{self, Write as _};
|
||||
|
||||
use owo_colors::OwoColorize;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use super::handler::{GraphicalReportHandler, LinkStyle};
|
||||
use crate::{Diagnostic, Severity, source_impls::SpanScanner};
|
||||
use crate::{Diagnostic, Severity, handlers::theme::DiagnosticColorize, source_impls::SpanScanner};
|
||||
|
||||
struct TitleBuffer(SmallVec<[u8; 128]>);
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
use std::{borrow::Cow, cmp::max, fmt};
|
||||
|
||||
use owo_colors::OwoColorize;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use super::{
|
||||
@@ -20,6 +19,7 @@ use super::{
|
||||
};
|
||||
use crate::{
|
||||
Diagnostic, LabeledSpan,
|
||||
handlers::theme::DiagnosticColorize,
|
||||
source_impls::{SpanContents, SpanScanner},
|
||||
};
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
//! it will be drawn in. Label text stays borrowed and is split into display
|
||||
//! lines only when it is drawn.
|
||||
|
||||
use owo_colors::Style;
|
||||
|
||||
use oxc_span::Span;
|
||||
|
||||
use crate::handlers::theme::Style;
|
||||
|
||||
/// How a label is being drawn on the current output line.
|
||||
///
|
||||
/// A label can be a single trailing line, or a block that spans several output
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
use std::{
|
||||
env,
|
||||
env, fmt,
|
||||
io::{self, IsTerminal},
|
||||
};
|
||||
|
||||
use owo_colors::Style;
|
||||
|
||||
/// Theme used by [`GraphicalReportHandler`](crate::GraphicalReportHandler).
|
||||
///
|
||||
/// Use one of the predefined constructors below.
|
||||
@@ -66,13 +64,82 @@ impl GraphicalTheme {
|
||||
Self { characters: ThemeCharacters::ascii(), styles: ThemeStyles::none() }
|
||||
}
|
||||
|
||||
/// Style used for warning text.
|
||||
#[must_use]
|
||||
pub const fn warning_style(&self) -> Style {
|
||||
self.styles.warning
|
||||
/// Write text using the theme's warning style.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error when writing the text fails.
|
||||
pub fn write_warning(&self, f: &mut impl fmt::Write, value: impl fmt::Display) -> fmt::Result {
|
||||
self.styles.warning.write(f, value)
|
||||
}
|
||||
}
|
||||
|
||||
const ANSI_RESET: &str = "\x1b[0m";
|
||||
const ANSI_PREFIXES: [&str; 9] = [
|
||||
"",
|
||||
"\x1b[38;2;225;80;80;1m",
|
||||
"\x1b[38;2;244;191;117;1m",
|
||||
"\x1b[38;2;106;159;181m",
|
||||
"\x1b[38;2;92;157;255;1m",
|
||||
"\x1b[2m",
|
||||
"\x1b[38;2;246;87;248m",
|
||||
"\x1b[38;2;30;201;212m",
|
||||
"\x1b[38;2;145;246;111m",
|
||||
];
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
#[repr(u8)]
|
||||
pub(super) enum Style {
|
||||
Plain,
|
||||
Error,
|
||||
Warning,
|
||||
Info,
|
||||
Link,
|
||||
LineNumber,
|
||||
Highlight1,
|
||||
Highlight2,
|
||||
Highlight3,
|
||||
}
|
||||
|
||||
impl Style {
|
||||
const fn prefix(self) -> &'static str {
|
||||
ANSI_PREFIXES[self as usize]
|
||||
}
|
||||
|
||||
pub(super) const fn is_plain(self) -> bool {
|
||||
matches!(self, Self::Plain)
|
||||
}
|
||||
|
||||
fn write(self, f: &mut impl fmt::Write, value: impl fmt::Display) -> fmt::Result {
|
||||
let prefix = self.prefix();
|
||||
f.write_str(prefix)?;
|
||||
write!(f, "{value}")?;
|
||||
if self.is_plain() { Ok(()) } else { f.write_str(ANSI_RESET) }
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct Styled<T> {
|
||||
target: T,
|
||||
style: Style,
|
||||
}
|
||||
|
||||
impl<T: fmt::Display> fmt::Display for Styled<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let prefix = self.style.prefix();
|
||||
f.write_str(prefix)?;
|
||||
self.target.fmt(f)?;
|
||||
if self.style.is_plain() { Ok(()) } else { f.write_str(ANSI_RESET) }
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) trait DiagnosticColorize: Sized {
|
||||
fn style(self, style: Style) -> Styled<Self> {
|
||||
Styled { target: self, style }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DiagnosticColorize for T {}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(super) struct ThemeStyles {
|
||||
pub(super) error: Style,
|
||||
@@ -85,38 +152,30 @@ pub(super) struct ThemeStyles {
|
||||
pub(super) highlights: [Style; 3],
|
||||
}
|
||||
|
||||
fn style() -> Style {
|
||||
Style::new()
|
||||
}
|
||||
|
||||
impl ThemeStyles {
|
||||
fn rgb() -> Self {
|
||||
Self {
|
||||
error: style().fg_rgb::<225, 80, 80>().bold(),
|
||||
warning: style().fg_rgb::<244, 191, 117>().bold(),
|
||||
advice: style().fg_rgb::<106, 159, 181>(),
|
||||
help: style().fg_rgb::<106, 159, 181>(),
|
||||
note: style().fg_rgb::<106, 159, 181>(),
|
||||
link: style().fg_rgb::<92, 157, 255>().bold(),
|
||||
linum: style().dimmed(),
|
||||
highlights: [
|
||||
style().fg_rgb::<246, 87, 248>(),
|
||||
style().fg_rgb::<30, 201, 212>(),
|
||||
style().fg_rgb::<145, 246, 111>(),
|
||||
],
|
||||
error: Style::Error,
|
||||
warning: Style::Warning,
|
||||
advice: Style::Info,
|
||||
help: Style::Info,
|
||||
note: Style::Info,
|
||||
link: Style::Link,
|
||||
linum: Style::LineNumber,
|
||||
highlights: [Style::Highlight1, Style::Highlight2, Style::Highlight3],
|
||||
}
|
||||
}
|
||||
|
||||
fn none() -> Self {
|
||||
Self {
|
||||
error: style(),
|
||||
warning: style(),
|
||||
advice: style(),
|
||||
help: style(),
|
||||
note: style(),
|
||||
link: style(),
|
||||
linum: style(),
|
||||
highlights: [style(); 3],
|
||||
error: Style::Plain,
|
||||
warning: Style::Plain,
|
||||
advice: Style::Plain,
|
||||
help: Style::Plain,
|
||||
note: Style::Plain,
|
||||
link: Style::Plain,
|
||||
linum: Style::Plain,
|
||||
highlights: [Style::Plain; 3],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user