mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
fix(formatter,oxfmt): embed only original JSDoc plugin supported languages (#27241)
May support more languages in the future, but for now embed only css / less / scss / json / yaml / html, as original (`parserSynonyms`) does. https://github.com/fardad-dev/prettier-plugin-jsdoc/blob/75825bae4a9e0f74a0539aeeada777d3e54e38d2/src/descriptionFormatter.ts#L16
This commit is contained in:
1 parent
4333fe8da7
commit
267557cfc3
7 files changed
+38
-38
No files matched your search
@@ -107,9 +107,9 @@ Per-language options are NOT built up front: `ResolvedDispatchConfig` maps them
|
||||
|
||||
A separate string-out channel (the session's `string_embedder` service, NOT the dispatcher) carries JSDoc's string-in/string-out consumer:
|
||||
|
||||
- JSDoc fenced code blocks: routing follows ONE rule, the same `dispatcher::route` table
|
||||
- JSDoc fenced code blocks: the host (`oxc_formatter`) embeds only the `prettier-plugin-jsdoc` set (css/less/scss/json/yaml/html), then routing follows ONE rule, the same `dispatcher::route` table
|
||||
- a `Native` fence language formats through `FormatSession::dispatch_to_string` via a thin string adapter (`embed/jsdoc_fence.rs::format_native_fence`, EVERY build, the pure Rust build wires it via `services::for_root`)
|
||||
- md/html/angular fences stay on the Prettier string path (`embed/prettier_string.rs`, napi only; their Doc→IR conversion has unrepresentable cases);
|
||||
- html fences stay on the Prettier string path (`embed/prettier_string.rs`, napi only; its Doc→IR conversion has unrepresentable cases);
|
||||
- everything else stays verbatim
|
||||
- the embedder carries the caller's effective print width; both branches honor it (native via `PrintWidth` override, Prettier via `printWidth` in the options JSON), so a fence prints at the same width a JS/TS snippet in the same position would (see `upstream-jsdoc-bugs.md` #11 for the deliberate divergence from upstream's flat `printWidth - 4`)
|
||||
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
//! - [`services`] (every build): the root `SessionServices` assembly (`for_root`, one definition per build)
|
||||
//! - [`jsdoc_fence`] (every build): the JSDoc native-fence string adapter over the registry
|
||||
//! - [`prettier_doc`] (napi only): Prettier Doc→IR path for the `Route::Prettier` set
|
||||
//! - [`prettier_string`] (napi only): the Prettier string paths of the string-out channel
|
||||
//! (md/html/angular JSDoc fences; results re-embed line-by-line)
|
||||
//! - [`prettier_string`] (napi only): the Prettier string paths of the string-out channel (html JSDoc fences; results re-embed line-by-line)
|
||||
|
||||
#[cfg(feature = "napi")]
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -30,7 +30,7 @@ use crate::core::{
|
||||
/// Build the napi build's string embedder installed on the session.
|
||||
///
|
||||
/// Dispatches by language identifier: the native registry when available, otherwise Prettier via `format_embedded`.
|
||||
/// The JSDoc fenced consumer reaches every language.
|
||||
/// The JSDoc fenced consumer sends only its embedded set (`EMBEDDED_FENCE_LANGUAGES` in `oxc_formatter`).
|
||||
///
|
||||
/// `sort_tailwind` is the SAME pre-bound sorter as the session's Tailwind service
|
||||
/// (options JSON already applied by `services::for_root`), for the `@apply` classes a CSS fence collects.
|
||||
|
||||
@@ -54,7 +54,7 @@ describe("JSDoc", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("should format fenced scss, less and graphql through the native dispatch registry", async () => {
|
||||
it("should format fenced scss and less through the native dispatch registry, keeping graphql verbatim", async () => {
|
||||
const source = `
|
||||
/**
|
||||
* \`\`\`scss
|
||||
@@ -91,19 +91,14 @@ describe("JSDoc", () => {
|
||||
* \`\`\`
|
||||
*
|
||||
* \`\`\`graphql
|
||||
* query Q {
|
||||
* user {
|
||||
* id
|
||||
* name
|
||||
* }
|
||||
* }
|
||||
* query Q { user { id name } }
|
||||
* \`\`\`
|
||||
*/
|
||||
`.trimStart(),
|
||||
);
|
||||
});
|
||||
|
||||
it("should format fenced json, json5 and yaml via the native registry", async () => {
|
||||
it("should format fenced json and yaml via the native registry, keeping json5 verbatim", async () => {
|
||||
const source = `
|
||||
/**
|
||||
* \`\`\`json
|
||||
@@ -132,7 +127,7 @@ describe("JSDoc", () => {
|
||||
* \`\`\`
|
||||
*
|
||||
* \`\`\`json5
|
||||
* { a: 1 }
|
||||
* {a:1,}
|
||||
* \`\`\`
|
||||
*
|
||||
* \`\`\`yaml
|
||||
@@ -148,17 +143,17 @@ describe("JSDoc", () => {
|
||||
it("should print native fences at the fence's effective width, not the full printWidth", async () => {
|
||||
// Effective width at top level = printWidth(100) - " * "(3) - 4 = 93,
|
||||
// the same width JS/TS snippets in the same position already use.
|
||||
// The 94-char field line must break; the 92-char one must not.
|
||||
// The 94-char line must break; the 93-char one must not.
|
||||
// (Upstream `prettier-plugin-jsdoc` uses a flat printWidth - 4, which overflows `printWidth` for indented comments;
|
||||
// see crates/oxc_formatter/tests/jsdoc/upstream-jsdoc-bugs.md)
|
||||
const source = `
|
||||
/**
|
||||
* \`\`\`graphql
|
||||
* query { fieldName(argOne: "value1", argTwo: "value2", argThree: "value3", four: 4444, five: 5555577) }
|
||||
* \`\`\`json
|
||||
* { "argOne": "value1", "argTwo": "value2", "argThree": "value3", "four": 4444, "five": 555555 }
|
||||
* \`\`\`
|
||||
*
|
||||
* \`\`\`graphql
|
||||
* query { fieldName(argOne: "value1", argTwo: "value2", argThree: "value3", four: 4444, five: 55555) }
|
||||
* \`\`\`json
|
||||
* { "argOne": "value1", "argTwo": "value2", "argThree": "value3", "four": 4444, "five": 55555 }
|
||||
* \`\`\`
|
||||
*/
|
||||
`.trim();
|
||||
@@ -168,22 +163,18 @@ describe("JSDoc", () => {
|
||||
expect(result.code).toBe(
|
||||
`
|
||||
/**
|
||||
* \`\`\`graphql
|
||||
* query {
|
||||
* fieldName(
|
||||
* argOne: "value1"
|
||||
* argTwo: "value2"
|
||||
* argThree: "value3"
|
||||
* four: 4444
|
||||
* five: 5555577
|
||||
* )
|
||||
* \`\`\`json
|
||||
* {
|
||||
* "argOne": "value1",
|
||||
* "argTwo": "value2",
|
||||
* "argThree": "value3",
|
||||
* "four": 4444,
|
||||
* "five": 555555
|
||||
* }
|
||||
* \`\`\`
|
||||
*
|
||||
* \`\`\`graphql
|
||||
* query {
|
||||
* fieldName(argOne: "value1", argTwo: "value2", argThree: "value3", four: 4444, five: 55555)
|
||||
* }
|
||||
* \`\`\`json
|
||||
* { "argOne": "value1", "argTwo": "value2", "argThree": "value3", "four": 4444, "five": 55555 }
|
||||
* \`\`\`
|
||||
*/
|
||||
`.trimStart(),
|
||||
|
||||
@@ -45,7 +45,8 @@ After changing AST shapes or the generators, regenerate with `just ast`, never h
|
||||
- See `tests/jsdoc/fixtures` for the covered behavior
|
||||
- See also `tests/jsdoc/upstream-jsdoc-bugs.md`
|
||||
- Implemented in Rust as a comment-text rewrite at print time (`formatter/trivia.rs`), not an IR transform
|
||||
- Non-JS fenced code blocks go through the session's optional `StringEmbedder`; without it (or on failure) they stay verbatim
|
||||
- Non-JS fenced code blocks of the `prettier-plugin-jsdoc` set go through the session's optional `StringEmbedder`;
|
||||
without it (or on failure), and for any other language, they stay verbatim
|
||||
- Covered by plain fixture-pair tests (`--test jsdoc`, committed input/expected pairs);
|
||||
a mismatch is a failing test, not a tracked conformance-report entry
|
||||
|
||||
|
||||
@@ -25,9 +25,11 @@ fn parse_and_build<'a>(
|
||||
Some(code)
|
||||
}
|
||||
|
||||
/// Returns `true` if the fenced code block language is JS/TS/JSX/TSX.
|
||||
/// Returns `true` if the fenced code block language is JS/TS/JSX/TSX (case-insensitive).
|
||||
pub(super) fn is_js_ts_lang(lang: &str) -> bool {
|
||||
matches!(lang, "js" | "javascript" | "jsx" | "ts" | "typescript" | "tsx")
|
||||
["js", "javascript", "jsx", "ts", "typescript", "tsx"]
|
||||
.iter()
|
||||
.any(|name| lang.eq_ignore_ascii_case(name))
|
||||
}
|
||||
|
||||
/// Count unescaped backticks on a line and update template literal depth.
|
||||
|
||||
@@ -743,12 +743,17 @@ fn serialize_code(
|
||||
}
|
||||
}
|
||||
|
||||
/// Non-JS/TS fence languages a description embeds: the `prettier-plugin-jsdoc` set (its `parserSynonyms`),
|
||||
/// matched case-insensitively as there.
|
||||
/// Any other stays verbatim; add one on demand, as long as the host's dispatcher routes it.
|
||||
const EMBEDDED_FENCE_LANGUAGES: [&str; 6] = ["css", "less", "scss", "json", "yaml", "html"];
|
||||
|
||||
/// Format code block content in a JSDoc Markdown description.
|
||||
///
|
||||
/// Routing:
|
||||
/// - JS/TS code (fenced with a JS/TS lang tag, fenced with no lang tag, or indented blocks):
|
||||
/// formatted in-process via [`format_jsdoc_js_snippet`] (`oxc_formatter`'s own parser/formatter).
|
||||
/// - Non-JS/TS fenced code (css, html, graphql, etc.):
|
||||
/// - Non-JS/TS fenced code of [`EMBEDDED_FENCE_LANGUAGES`]:
|
||||
/// when the session carries a string embedder, routed through it (the string channel);
|
||||
/// absent one (Rust-only conformance, or the language has no native branch), preserved verbatim.
|
||||
///
|
||||
@@ -764,8 +769,10 @@ fn format_code_value<'a>(
|
||||
if let Some(l) = lang
|
||||
&& !is_js_ts_lang(l)
|
||||
{
|
||||
if let Some(embed) = opts.session.string_embedder()
|
||||
&& let Ok(formatted) = embed(l, code, width)
|
||||
if let Some(language) =
|
||||
EMBEDDED_FENCE_LANGUAGES.into_iter().find(|name| l.eq_ignore_ascii_case(name))
|
||||
&& let Some(embed) = opts.session.string_embedder()
|
||||
&& let Ok(formatted) = embed(language, code, width)
|
||||
{
|
||||
return Cow::Owned(formatted);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user