Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Profile-*.json
.idea
.vs
.zed/*
.opencode/plans/
# Release artifacts
**/target
# Ignore test files that contributors could create locally
Expand Down
50 changes: 50 additions & 0 deletions crates/biome_cli/tests/cases/handle_svelte_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -907,3 +907,53 @@ let isChecked = false;
result,
));
}

#[test]
fn no_comma_operator_triggered_in_svelte_template_expression() {
let fs = MemoryFileSystem::default();
let mut console = BufferConsole::default();

fs.insert(
"biome.json".into(),
r#"{ "html": { "linter": {"enabled": true}, "experimentalFullSupportEnabled": true } }"#
.as_bytes(),
);

let file = Utf8Path::new("file.svelte");
fs.insert(
file.into(),
r#"<script>
let x = 1;
</script>

<!-- Comma operator in template expression - should be flagged -->
<p>{(console.log("side effect"), x)}</p>"#
.as_bytes(),
);

let (fs, result) = run_cli(
fs,
&mut console,
Args::from(["lint", "--only=noCommaOperator", file.as_str()].as_slice()),
);

// The comma operator SHOULD be flagged in Svelte (hack only applies to Vue)
// Result is Ok because it's a warning, but console should contain the diagnostic
assert!(result.is_ok(), "run_cli returned {result:?}");
let has_comma_operator = console.out_buffer.iter().any(|m| {
let content = format!("{:?}", m.content);
content.contains("noCommaOperator")
});
assert!(
has_comma_operator,
"Expected noCommaOperator diagnostic in console output"
);

assert_cli_snapshot(SnapshotPayload::new(
module_path!(),
"no_comma_operator_triggered_in_svelte_template_expression",
fs,
console,
result,
));
}
44 changes: 44 additions & 0 deletions crates/biome_cli/tests/cases/handle_vue_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1570,3 +1570,47 @@ import { mdiSquareOutline } from "@mdi/js";
result,
));
}

#[test]
fn no_comma_operator_not_triggered_in_v_for() {
let fs = MemoryFileSystem::default();
let mut console = BufferConsole::default();

fs.insert(
"biome.json".into(),
r#"{ "html": { "linter": {"enabled": true}, "experimentalFullSupportEnabled": true } }"#
.as_bytes(),
);

let file = Utf8Path::new("file.vue");
fs.insert(
file.into(),
r#"<template>
<v-list-item
v-for="(rate, index) in playbackRate.availablePlaybackRates.value"
:key="index"
:value="rate"
@click="setRate(rate)"
>
<v-list-item-title>{{ formatRate(rate) }}</v-list-item-title>
</v-list-item>
</template>"#
.as_bytes(),
);

let (fs, result) = run_cli(
fs,
&mut console,
Args::from(["lint", "--only=noCommaOperator", file.as_str()].as_slice()),
);

assert!(result.is_ok(), "run_cli returned {result:?}");

assert_cli_snapshot(SnapshotPayload::new(
module_path!(),
"no_comma_operator_not_triggered_in_v_for",
fs,
console,
result,
));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
source: crates/biome_cli/tests/snap_test.rs
expression: redactor(content)
---
## `biome.json`

```json
{
"html": {
"linter": { "enabled": true },
"experimentalFullSupportEnabled": true
}
}
```

## `file.svelte`

```svelte
<script>
let x = 1;
</script>

<!-- Comma operator in template expression - skipped by the hack -->
<p>{(console.log("side effect"), x)}</p>
```

# Emitted Messages

```block
Checked 1 file in <TIME>. No fixes applied.
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
source: crates/biome_cli/tests/snap_test.rs
expression: redactor(content)
---
## `biome.json`

```json
{
"html": {
"linter": { "enabled": true },
"experimentalFullSupportEnabled": true
}
}
```

## `file.svelte`

```svelte
<script>
let x = 1;
</script>

<!-- Comma operator in template expression - should be flagged -->
<p>{(console.log("side effect"), x)}</p>
```

# Emitted Messages

```block
file.svelte:6:32 lint/complexity/noCommaOperator ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

! The comma operator is disallowed.

5 │ <!-- Comma operator in template expression - should be flagged -->
> 6 │ <p>{(console.log("side effect"), x)}</p>
│ ^

i Its use is often confusing and obscures side effects.


```

```block
Checked 1 file in <TIME>. No fixes applied.
Found 1 warning.
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
source: crates/biome_cli/tests/snap_test.rs
expression: redactor(content)
---
## `biome.json`

```json
{
"html": {
"linter": { "enabled": true },
"experimentalFullSupportEnabled": true
}
}
```

## `file.vue`

```vue
<template>
<v-list-item
v-for="(rate, index) in playbackRate.availablePlaybackRates.value"
:key="index"
:value="rate"
@click="setRate(rate)"
>
<v-list-item-title>{{ formatRate(rate) }}</v-list-item-title>
</v-list-item>
</template>
```

# Emitted Messages

```block
Checked 1 file in <TIME>. No fixes applied.
```
11 changes: 10 additions & 1 deletion crates/biome_js_analyze/src/lint/complexity/no_comma_operator.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use biome_analyze::context::RuleContext;
use biome_analyze::{Ast, Rule, RuleDiagnostic, RuleSource, declare_lint_rule};
use biome_diagnostics::Severity;
use biome_js_syntax::{JsForStatement, JsSequenceExpression};
use biome_js_syntax::{JsFileSource, JsForStatement, JsSequenceExpression};
use biome_rowan::AstNode;
use biome_rule_options::no_comma_operator::NoCommaOperatorOptions;

Expand Down Expand Up @@ -66,6 +66,15 @@ impl Rule for NoCommaOperator {
return None;
}
}

// HACK: Skip in Vue template expressions (e.g., v-for="(item, index) in items")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add the issue here too, so we can quickly identify the hack to remove?

// This is a temporary workaround until v-for expressions are parsed correctly
// https://github.com/biomejs/biome/issues/9075
let file_source = ctx.source_type::<JsFileSource>();
if file_source.is_template_expression() && file_source.as_embedding_kind().is_vue() {
return None;
}

Some(())
}

Expand Down