mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
perf(formatter_yaml): use multiline flag for flow scalars (#28707)
- bump `oxc-yaml-parser` which has `multiline` flag - eliminate all `\n` contains check from formatter Reduce 5~7% CPU instructions.
This commit is contained in:
1 parent
ff7c203711
commit
f680ee1f2e
5 files changed
+36
-27
No files matched your search
Generated
+2
-2
@@ -1738,9 +1738,9 @@ checksum = "f321c22ccee109a6fe0aef08d1521af693e4b178dcb7259137ff08f8ce5388d8"
|
||||
|
||||
[[package]]
|
||||
name = "oxc-yaml-parser"
|
||||
version = "0.0.7"
|
||||
version = "0.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41ca5cfdf8b83491f53dd1fe583f43923100eacf76d3b8e6bce9d24dec93356c"
|
||||
checksum = "f7909b626031c9f06dc94fdcdf16b439196d209399fa094db85148c4098c6fc3"
|
||||
dependencies = [
|
||||
"oxc_allocator",
|
||||
]
|
||||
|
||||
+1
-1
@@ -246,7 +246,7 @@ oxc-graphql-parser = "0.0.9" # GraphQL parser (direct AST; apollo-parser 0.8.6 f
|
||||
oxc-htmlish-parser = "0.0.2" # HTML / Vue / Angular parser (loose, span-faithful AST)
|
||||
oxc-markdown-parser = "0.0.3" # CommonMark + GFM parser (span-faithful, style-preserving typed AST)
|
||||
oxc-toml = "0.15.1" # TOML parser and formatter
|
||||
oxc-yaml-parser = "0.0.7" # YAML 1.2 parser (comment-preserving typed AST, node naming from `yaml-unist-parser`)
|
||||
oxc-yaml-parser = "0.0.8" # YAML 1.2 parser (comment-preserving typed AST, node naming from `yaml-unist-parser`)
|
||||
papaya = { version = "0.2.5", default-features = false } # Concurrent hash map
|
||||
percent-encoding = "2.3.2" # URL encoding
|
||||
petgraph = { version = "0.8.3", default-features = false } # Graph data structures
|
||||
|
||||
@@ -391,14 +391,14 @@ fn is_inline(node: Option<&Node<'_>>) -> bool {
|
||||
|
||||
/// The raw source of a flow scalar (plain/quoted); `None` for aliases,
|
||||
/// collections and block scalars.
|
||||
fn scalar_raw<'a>(node: &Node<'_>, f: &YamlFormatter<'_, 'a>) -> Option<&'a str> {
|
||||
let span = match &node.content {
|
||||
Content::Plain(p) => p.span,
|
||||
Content::QuoteSingle(s) => s.span,
|
||||
Content::QuoteDouble(d) => d.span,
|
||||
fn scalar_raw<'a>(node: &Node<'_>, f: &YamlFormatter<'_, 'a>) -> Option<(&'a str, bool)> {
|
||||
let (span, multiline) = match &node.content {
|
||||
Content::Plain(p) => (p.span, p.multiline),
|
||||
Content::QuoteSingle(s) => (s.span, s.multiline),
|
||||
Content::QuoteDouble(d) => (d.span, d.multiline),
|
||||
_ => return None,
|
||||
};
|
||||
Some(f.context().source_text().text_for(&to_span(span)))
|
||||
Some((f.context().source_text().text_for(&to_span(span)), multiline))
|
||||
}
|
||||
|
||||
/// `isSingleLineNode`: the node occupies one source line.
|
||||
@@ -406,7 +406,7 @@ fn is_single_line(node: Option<&Node<'_>>, f: &YamlFormatter<'_, '_>) -> bool {
|
||||
match node {
|
||||
None => true,
|
||||
Some(node) if matches!(node.content, Content::Alias(_)) => true,
|
||||
Some(node) => scalar_raw(node, f).is_some_and(|raw| !raw.contains('\n')),
|
||||
Some(node) => scalar_raw(node, f).is_some_and(|(_, multiline)| !multiline),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,11 +417,11 @@ fn is_absolutely_single_line(node: Option<&Node<'_>>, f: &YamlFormatter<'_, '_>)
|
||||
if matches!(node.content, Content::Alias(_)) {
|
||||
return true;
|
||||
}
|
||||
let Some(raw) = scalar_raw(node, f) else { return false };
|
||||
let Some((raw, multiline)) = scalar_raw(node, f) else { return false };
|
||||
|
||||
let prose_wrap = f.options().prose_wrap;
|
||||
if prose_wrap == ProseWrap::Preserve {
|
||||
return !raw.contains('\n');
|
||||
return !multiline;
|
||||
}
|
||||
if has_backslash_continuation(raw) {
|
||||
return false;
|
||||
@@ -432,7 +432,7 @@ fn is_absolutely_single_line(node: Option<&Node<'_>>, f: &YamlFormatter<'_, '_>)
|
||||
!has_blank_line(raw)
|
||||
} else {
|
||||
// `always` may wrap at any space
|
||||
!raw.contains('\n') && !raw.contains(' ')
|
||||
!multiline && !raw.contains(' ')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,7 +453,7 @@ fn has_backslash_continuation(raw: &str) -> bool {
|
||||
fn has_forced_break_when_folded(node: Option<&Node<'_>>, f: &YamlFormatter<'_, '_>) -> bool {
|
||||
let Some(node) = node else { return false };
|
||||
// Defensive: non-scalars never re-fold
|
||||
let Some(raw) = scalar_raw(node, f) else { return true };
|
||||
let Some((raw, _)) = scalar_raw(node, f) else { return true };
|
||||
has_blank_line(raw) || has_backslash_continuation(raw)
|
||||
}
|
||||
|
||||
|
||||
@@ -155,12 +155,14 @@ pub fn write_node<'a>(node: &'a Node<'a>, f: &mut YamlFormatter<'_, 'a>) {
|
||||
}
|
||||
|
||||
match content {
|
||||
Content::Plain(scalar) => scalar::write_plain(to_span(scalar.span), f),
|
||||
Content::Plain(scalar) => scalar::write_plain(to_span(scalar.span), scalar.multiline, f),
|
||||
Content::QuoteSingle(scalar) => {
|
||||
scalar::write_quoted(scalar::FlowScalarKind::QuoteSingle, to_span(scalar.span), f);
|
||||
let kind = scalar::FlowScalarKind::QuoteSingle;
|
||||
scalar::write_quoted(kind, to_span(scalar.span), scalar.multiline, f);
|
||||
}
|
||||
Content::QuoteDouble(scalar) => {
|
||||
scalar::write_quoted(scalar::FlowScalarKind::QuoteDouble, to_span(scalar.span), f);
|
||||
let kind = scalar::FlowScalarKind::QuoteDouble;
|
||||
scalar::write_quoted(kind, to_span(scalar.span), scalar.multiline, f);
|
||||
}
|
||||
Content::Alias(alias) => {
|
||||
// Verbatim: `*name` has no layout freedom, and no comment can lie inside
|
||||
|
||||
@@ -23,13 +23,18 @@ pub enum FlowScalarKind {
|
||||
}
|
||||
|
||||
/// Emits a plain scalar: raw slice content, line-folded per `proseWrap`.
|
||||
pub fn write_plain(span: Span, f: &mut YamlFormatter<'_, '_>) {
|
||||
pub fn write_plain(span: Span, multiline: bool, f: &mut YamlFormatter<'_, '_>) {
|
||||
let content = f.context().source_text().text_for(&span);
|
||||
write_flow_scalar_content(FlowScalarKind::Plain, content, f);
|
||||
write_flow_scalar_content(FlowScalarKind::Plain, content, multiline, f);
|
||||
}
|
||||
|
||||
/// Emits a quoted scalar with Prettier's `quoteDouble`/`quoteSingle` case.
|
||||
pub fn write_quoted(kind: FlowScalarKind, span: Span, f: &mut YamlFormatter<'_, '_>) {
|
||||
pub fn write_quoted(
|
||||
kind: FlowScalarKind,
|
||||
span: Span,
|
||||
multiline: bool,
|
||||
f: &mut YamlFormatter<'_, '_>,
|
||||
) {
|
||||
let source = f.context().source_text();
|
||||
// Inner content between the quotes
|
||||
let raw = source.text_for(&Span::new(span.start + 1, span.end - 1));
|
||||
@@ -47,7 +52,7 @@ pub fn write_quoted(kind: FlowScalarKind, span: Span, f: &mut YamlFormatter<'_,
|
||||
if has_unreencodable_escape {
|
||||
let quote = if kind == FlowScalarKind::QuoteDouble { "\"" } else { "'" };
|
||||
write!(f, text(quote));
|
||||
write_flow_scalar_content(kind, raw, f);
|
||||
write_flow_scalar_content(kind, raw, multiline, f);
|
||||
write!(f, text(quote));
|
||||
return;
|
||||
}
|
||||
@@ -60,9 +65,9 @@ pub fn write_quoted(kind: FlowScalarKind, span: Span, f: &mut YamlFormatter<'_,
|
||||
// (The guarding `contains('"')` means the first replace always matches,
|
||||
// so the chain is owned; copy it into the arena once.)
|
||||
let content = raw.cow_replace("\\\"", "\"").cow_replace('\'', "''").into_owned();
|
||||
write_flow_scalar_content(kind, f.allocator().alloc_str(&content), f);
|
||||
write_flow_scalar_content(kind, f.allocator().alloc_str(&content), multiline, f);
|
||||
} else {
|
||||
write_flow_scalar_content(kind, raw, f);
|
||||
write_flow_scalar_content(kind, raw, multiline, f);
|
||||
}
|
||||
write!(f, text("'"));
|
||||
return;
|
||||
@@ -74,9 +79,9 @@ pub fn write_quoted(kind: FlowScalarKind, span: Span, f: &mut YamlFormatter<'_,
|
||||
if kind == FlowScalarKind::QuoteSingle {
|
||||
// `''` unescapes to `'` (nothing else needs escaping in double quotes here)
|
||||
let content = raw.cow_replace("''", "'");
|
||||
write_flow_scalar_content(kind, arena_cow_str(&content, f), f);
|
||||
write_flow_scalar_content(kind, arena_cow_str(&content, f), multiline, f);
|
||||
} else {
|
||||
write_flow_scalar_content(kind, raw, f);
|
||||
write_flow_scalar_content(kind, raw, multiline, f);
|
||||
}
|
||||
write!(f, text("\""));
|
||||
return;
|
||||
@@ -84,22 +89,24 @@ pub fn write_quoted(kind: FlowScalarKind, span: Span, f: &mut YamlFormatter<'_,
|
||||
|
||||
let quote = f.options().single_quote.as_str();
|
||||
write!(f, text(quote));
|
||||
write_flow_scalar_content(kind, raw, f);
|
||||
write_flow_scalar_content(kind, raw, multiline, f);
|
||||
write!(f, text(quote));
|
||||
}
|
||||
|
||||
/// Prettier's `printFlowScalarContent`:
|
||||
/// each reflow group becomes a `fill(join(line, words))`, groups joined by hardlines.
|
||||
/// `multiline` is the parser's flag for the scalar crossing a line break.
|
||||
pub fn write_flow_scalar_content<'a>(
|
||||
kind: FlowScalarKind,
|
||||
content: &'a str,
|
||||
multiline: bool,
|
||||
f: &mut YamlFormatter<'_, 'a>,
|
||||
) {
|
||||
let prose_wrap = f.options().prose_wrap;
|
||||
// Fast path:
|
||||
// a single-line scalar under `preserve` (the default) prints verbatim,
|
||||
// skip the line-contents machinery and its allocations.
|
||||
if prose_wrap == ProseWrap::Preserve && !content.contains('\n') {
|
||||
if prose_wrap == ProseWrap::Preserve && !multiline {
|
||||
if !content.is_empty() {
|
||||
write!(f, text(content));
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user