From c2a2df63ce4f7f75c179a1b23396352843f4e787 Mon Sep 17 00:00:00 2001 From: Naoki Ikeguchi Date: Sun, 14 Sep 2025 22:00:18 +0900 Subject: [PATCH] fix(lint/useConsistentCurlyBraces): adjust condition to allow removing the braces --- .changeset/little-seals-taste.md | 5 + .changeset/short-cases-think.md | 5 + .../lint/style/use_consistent_curly_braces.rs | 32 ++---- .../useConsistentCurlyBraces/invalid.jsx | 14 +++ .../useConsistentCurlyBraces/invalid.jsx.snap | 101 +++++++++++++++++- .../style/useConsistentCurlyBraces/valid.jsx | 2 + .../useConsistentCurlyBraces/valid.jsx.snap | 2 + 7 files changed, 134 insertions(+), 27 deletions(-) create mode 100644 .changeset/little-seals-taste.md create mode 100644 .changeset/short-cases-think.md diff --git a/.changeset/little-seals-taste.md b/.changeset/little-seals-taste.md new file mode 100644 index 000000000000..f512f9c578d5 --- /dev/null +++ b/.changeset/little-seals-taste.md @@ -0,0 +1,5 @@ +--- +"@biomejs/biome": patch +--- + +Fixed [#7320](https://github.com/biomejs/biome/issues/7320): The [`useConsistentCurlyBraces`](https://biomejs.dev/linter/rules/use-consistent-curly-braces/) rule now correctly detects a string literal including `"` inside a JSX attribute value. diff --git a/.changeset/short-cases-think.md b/.changeset/short-cases-think.md new file mode 100644 index 000000000000..86f1b0fb7de7 --- /dev/null +++ b/.changeset/short-cases-think.md @@ -0,0 +1,5 @@ +--- +"@biomejs/biome": patch +--- + +Fixed [#7256](https://github.com/biomejs/biome/issues/7256): The [`useConsistentCurlyBraces`](https://biomejs.dev/linter/rules/use-consistent-curly-braces/) rule now correctly ignores a string literal with braces that contains only whitespaces. Previously, literals that contains single whitespace were only allowed. diff --git a/crates/biome_js_analyze/src/lint/style/use_consistent_curly_braces.rs b/crates/biome_js_analyze/src/lint/style/use_consistent_curly_braces.rs index aad5751887c6..3a1ecad3c5d1 100644 --- a/crates/biome_js_analyze/src/lint/style/use_consistent_curly_braces.rs +++ b/crates/biome_js_analyze/src/lint/style/use_consistent_curly_braces.rs @@ -339,17 +339,8 @@ fn handle_attr_init_clause( match node { AnyJsxAttributeValue::AnyJsxTag(_) => Some(CurlyBraceResolution::AddBraces), AnyJsxAttributeValue::JsxExpressionAttributeValue(node) => { - if has_curly_braces && contains_single_space(&node) { - None - } else if has_curly_braces && contains_string_literal(&node) { - let expression = node.expression().ok()?; - let literal = expression - .as_any_js_literal_expression()? - .as_js_string_literal_expression()?; - if !contains_forbidden_chars(literal) { - return Some(CurlyBraceResolution::RemoveBraces); - } - None + if has_curly_braces && contains_string_literal(&node) { + Some(CurlyBraceResolution::RemoveBraces) } else if !has_curly_braces && contains_jsx_tag(&node) { Some(CurlyBraceResolution::AddBraces) } else { @@ -368,11 +359,7 @@ fn handle_jsx_child(child: &AnyJsxChild, has_curly_braces: bool) -> Option bool { .is_ok_and(|expr| matches!(expr, AnyJsExpression::JsxTagExpression(_))) } -fn contains_single_space(node: &JsxExpressionAttributeValue) -> bool { - node.expression().is_ok_and(|expr| { - matches!( - expr, - AnyJsExpression::AnyJsLiteralExpression( - AnyJsLiteralExpression::JsStringLiteralExpression(literal) - ) if literal.inner_string_text().is_ok_and(|text| text.text() == " ") - ) - }) +fn contains_only_spaces(literal: &JsStringLiteralExpression) -> bool { + literal + .inner_string_text() + .is_ok_and(|text| text.bytes().all(|b| b == b' ')) } const FORBIDDEN_CHARS: [char; 4] = ['>', '"', '\'', '}']; diff --git a/crates/biome_js_analyze/tests/specs/style/useConsistentCurlyBraces/invalid.jsx b/crates/biome_js_analyze/tests/specs/style/useConsistentCurlyBraces/invalid.jsx index a6b69b1baf42..1928e2231a23 100644 --- a/crates/biome_js_analyze/tests/specs/style/useConsistentCurlyBraces/invalid.jsx +++ b/crates/biome_js_analyze/tests/specs/style/useConsistentCurlyBraces/invalid.jsx @@ -12,4 +12,18 @@ {/*comment*/'Hello world'/*comment*/} {x}{'y'}{z} + + + +{/* https://github.com/biomejs/biome/issues/7320 */} + diff --git a/crates/biome_js_analyze/tests/specs/style/useConsistentCurlyBraces/invalid.jsx.snap b/crates/biome_js_analyze/tests/specs/style/useConsistentCurlyBraces/invalid.jsx.snap index abe7c1672c2f..5f23aa8ebd59 100644 --- a/crates/biome_js_analyze/tests/specs/style/useConsistentCurlyBraces/invalid.jsx.snap +++ b/crates/biome_js_analyze/tests/specs/style/useConsistentCurlyBraces/invalid.jsx.snap @@ -18,6 +18,20 @@ expression: invalid.jsx {/*comment*/'Hello world'/*comment*/} {x}{'y'}{z} + + + +{/* https://github.com/biomejs/biome/issues/7320 */} + ``` @@ -151,8 +165,8 @@ invalid.jsx:14:9 lint/style/useConsistentCurlyBraces FIXABLE ━━━━━ 13 │ > 14 │ {x}{'y'}{z} │ ^^^^^ - 15 │ - 16 │ + 15 │ + 16 │ i JSX child does not need to be wrapped in curly braces. @@ -162,3 +176,86 @@ invalid.jsx:14:9 lint/style/useConsistentCurlyBraces FIXABLE ━━━━━ │ -- -- ``` + +``` +invalid.jsx:16:10 lint/style/useConsistentCurlyBraces FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + i Should not have curly braces around expression. + + 14 │ {x}{'y'}{z} + 15 │ + > 16 │ + │ ^^^^^ + 17 │ + 18 │ {/* https://github.com/biomejs/biome/issues/7320 */} + + i JSX attribute value does not need to be wrapped in curly braces. + + i Unsafe fix: Remove curly braces around the expression. + + 16 │ + │ - - + +``` + +``` +invalid.jsx:22:15 lint/style/useConsistentCurlyBraces FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + i Should not have curly braces around expression. + + 20 │ description1= + 21 │ 'Upload a CSV file containing an "email" column, and optional "first_name" and "last_name" columns' + > 22 │ description2={ + │ ^ + > 23 │ 'Upload a CSV file containing an "email" column, and optional "first_name" and "last_name" columns' + > 24 │ } + │ ^ + 25 │ className={ + 26 │ "d-block" + + i JSX attribute value does not need to be wrapped in curly braces. + + i Unsafe fix: Remove curly braces around the expression. + + 20 20 │ description1= + 21 21 │ 'Upload a CSV file containing an "email" column, and optional "first_name" and "last_name" columns' + 22 │ - → description2={ + 22 │ + → description2= + 23 23 │ 'Upload a CSV file containing an "email" column, and optional "first_name" and "last_name" columns' + 24 │ - → } + 25 24 │ className={ + 26 25 │ "d-block" + + +``` + +``` +invalid.jsx:25:12 lint/style/useConsistentCurlyBraces FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + i Should not have curly braces around expression. + + 23 │ 'Upload a CSV file containing an "email" column, and optional "first_name" and "last_name" columns' + 24 │ } + > 25 │ className={ + │ ^ + > 26 │ "d-block" + > 27 │ } + │ ^ + 28 │ /> + 29 │ + + i JSX attribute value does not need to be wrapped in curly braces. + + i Unsafe fix: Remove curly braces around the expression. + + 23 23 │ 'Upload a CSV file containing an "email" column, and optional "first_name" and "last_name" columns' + 24 24 │ } + 25 │ - → className={ + 25 │ + → className= + 26 26 │ "d-block" + 27 │ - → } + 28 27 │ /> + 29 28 │ + + +``` diff --git a/crates/biome_js_analyze/tests/specs/style/useConsistentCurlyBraces/valid.jsx b/crates/biome_js_analyze/tests/specs/style/useConsistentCurlyBraces/valid.jsx index 5b1619488192..4fe602bf27aa 100644 --- a/crates/biome_js_analyze/tests/specs/style/useConsistentCurlyBraces/valid.jsx +++ b/crates/biome_js_analyze/tests/specs/style/useConsistentCurlyBraces/valid.jsx @@ -22,6 +22,8 @@ let baz = 4; {' '} +{' '} + Invalid closing tag {'}'} {'Invalid closing tag }'} diff --git a/crates/biome_js_analyze/tests/specs/style/useConsistentCurlyBraces/valid.jsx.snap b/crates/biome_js_analyze/tests/specs/style/useConsistentCurlyBraces/valid.jsx.snap index 216c5d16a383..71b86d15b12e 100644 --- a/crates/biome_js_analyze/tests/specs/style/useConsistentCurlyBraces/valid.jsx.snap +++ b/crates/biome_js_analyze/tests/specs/style/useConsistentCurlyBraces/valid.jsx.snap @@ -28,6 +28,8 @@ let baz = 4; {' '} +{' '} + Invalid closing tag {'}'} {'Invalid closing tag }'}