From 2f70254d0c697c42e85077bd15c7394a61c1fb6f Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Wed, 28 Jan 2026 03:42:35 +0000 Subject: [PATCH] fix(formatter): don't add extra semicolon on suppressed class properties (#18631) close: #18595 --- crates/oxc_formatter/src/print/class.rs | 5 +- .../tests/fixtures/js/ignore/issue-18595.js | 30 +++++ .../fixtures/js/ignore/issue-18595.js.snap | 105 ++++++++++++++++++ 3 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 crates/oxc_formatter/tests/fixtures/js/ignore/issue-18595.js create mode 100644 crates/oxc_formatter/tests/fixtures/js/ignore/issue-18595.js.snap diff --git a/crates/oxc_formatter/src/print/class.rs b/crates/oxc_formatter/src/print/class.rs index 5e1b9c0880e39..ff17a4370ff12 100644 --- a/crates/oxc_formatter/src/print/class.rs +++ b/crates/oxc_formatter/src/print/class.rs @@ -613,7 +613,10 @@ impl<'a> Format<'a> for FormatClassElementWithSemicolon<'a, '_> { && match f.options().semicolons { Semicolons::Always => true, Semicolons::AsNeeded => self.needs_semicolon(), - }; + } + // Don't add semicolon if the element is suppressed (has `oxfmt-ignore`), + // because the suppressed source text already includes the original semicolon. + && !f.comments().is_suppressed(self.element.span().start); if needs_semi { write!(f, [FormatNodeWithoutTrailingComments(self.element), ";"]); diff --git a/crates/oxc_formatter/tests/fixtures/js/ignore/issue-18595.js b/crates/oxc_formatter/tests/fixtures/js/ignore/issue-18595.js new file mode 100644 index 0000000000000..3881861698e8e --- /dev/null +++ b/crates/oxc_formatter/tests/fixtures/js/ignore/issue-18595.js @@ -0,0 +1,30 @@ +// prettier-ignore on class property should not add extra semicolon +export class Counter { + // prettier-ignore + 'count' = $state(0); + constructor() { + this['count'] = $state(0); + } +} + +export class Counter2 { + // prettier-ignore + 'count' = $state(0) + constructor() { + this['count'] = $state(0); + } +} + +export class Counter3 { + 'count' = $state(0) + constructor() { + this['count'] = $state(0); + } +} + +export class Counter4 { + 'count' = $state(0);; + constructor() { + this['count'] = $state(0); + } +} diff --git a/crates/oxc_formatter/tests/fixtures/js/ignore/issue-18595.js.snap b/crates/oxc_formatter/tests/fixtures/js/ignore/issue-18595.js.snap new file mode 100644 index 0000000000000..2f44bd441b41f --- /dev/null +++ b/crates/oxc_formatter/tests/fixtures/js/ignore/issue-18595.js.snap @@ -0,0 +1,105 @@ +--- +source: crates/oxc_formatter/tests/fixtures/mod.rs +--- +==================== Input ==================== +// prettier-ignore on class property should not add extra semicolon +export class Counter { + // prettier-ignore + 'count' = $state(0); + constructor() { + this['count'] = $state(0); + } +} + +export class Counter2 { + // prettier-ignore + 'count' = $state(0) + constructor() { + this['count'] = $state(0); + } +} + +export class Counter3 { + 'count' = $state(0) + constructor() { + this['count'] = $state(0); + } +} + +export class Counter4 { + 'count' = $state(0);; + constructor() { + this['count'] = $state(0); + } +} + +==================== Output ==================== +------------------ +{ printWidth: 80 } +------------------ +// prettier-ignore on class property should not add extra semicolon +export class Counter { + // prettier-ignore + 'count' = $state(0); + constructor() { + this["count"] = $state(0); + } +} + +export class Counter2 { + // prettier-ignore + 'count' = $state(0) + constructor() { + this["count"] = $state(0); + } +} + +export class Counter3 { + count = $state(0); + constructor() { + this["count"] = $state(0); + } +} + +export class Counter4 { + count = $state(0); + constructor() { + this["count"] = $state(0); + } +} + +------------------- +{ printWidth: 100 } +------------------- +// prettier-ignore on class property should not add extra semicolon +export class Counter { + // prettier-ignore + 'count' = $state(0); + constructor() { + this["count"] = $state(0); + } +} + +export class Counter2 { + // prettier-ignore + 'count' = $state(0) + constructor() { + this["count"] = $state(0); + } +} + +export class Counter3 { + count = $state(0); + constructor() { + this["count"] = $state(0); + } +} + +export class Counter4 { + count = $state(0); + constructor() { + this["count"] = $state(0); + } +} + +===================== End =====================