Skip to content

Conversation

@dyc3
Copy link
Contributor

@dyc3 dyc3 commented Nov 11, 2025

Summary

This adds 5 lint rules that all have to do with validating Vue directives, much like #8060. They are direct ports of the eslint plugin's rules.

I chose to group them all into one PR because they are all pretty trivial, and to reduce the amount of rebasing I would have to do if I put them in 5 PRs.

The initial passes at these rules were written by AI, but I heavily reviewed their behavior and simplified them.

Test Plan

Snapshot tests.

Docs

@changeset-bot
Copy link

changeset-bot bot commented Nov 11, 2025

🦋 Changeset detected

Latest commit: 9febe70

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 13 packages
Name Type
@biomejs/biome Patch
@biomejs/cli-win32-x64 Patch
@biomejs/cli-win32-arm64 Patch
@biomejs/cli-darwin-x64 Patch
@biomejs/cli-darwin-arm64 Patch
@biomejs/cli-linux-x64 Patch
@biomejs/cli-linux-arm64 Patch
@biomejs/cli-linux-x64-musl Patch
@biomejs/cli-linux-arm64-musl Patch
@biomejs/wasm-web Patch
@biomejs/wasm-bundler Patch
@biomejs/wasm-nodejs Patch
@biomejs/backend-jsonrpc Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions bot added A-Project Area: project A-Linter Area: linter A-Diagnostic Area: diagnostocis L-HTML Language: HTML and super languages labels Nov 11, 2025
@dyc3 dyc3 marked this pull request as draft November 11, 2025 19:29
@codspeed-hq
Copy link

codspeed-hq bot commented Nov 11, 2025

CodSpeed Performance Report

Merging #8077 will not alter performance

Comparing dyc3/vue-directive-rules (9febe70) with main (aa55c8d)

Summary

✅ 1 untouched
⏩ 154 skipped1

Footnotes

  1. 154 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 11, 2025

Walkthrough

Adds five new Vue-focused lints to the HTML analyzer: UseVueValidVIf, UseVueValidVElse, UseVueValidVElseIf, UseVueValidVHtml and UseVueValidVOn. Each rule inspects Vue directives for invalid arguments, modifiers, missing or unexpected values, and incorrect conditional chaining; emits specific diagnostics and notes. Corresponding option types were added to biome_rule_options, each rule declared via the lint macro, and comprehensive valid/invalid test fixtures were included.

Possibly related PRs

Suggested reviewers

  • ematipico
  • Conaclos

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.53% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the primary change: adding five Vue directive validation lint rules (useVueValidVIf, useVueValidVElseIf, useVueValidVElse, useVueValidVOn, useVueValidVHtml) to the HTML analyzer.
Description check ✅ Passed The description clearly explains the motivation (porting eslint-plugin-vue rules), the grouping rationale, test approach (snapshot tests), and discloses AI assistance used in the initial implementation.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dyc3/vue-directive-rules

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (4)
.changeset/use-vue-valid-v-else.md (1)

5-5: Incomplete changeset description.

The description only mentions one validation case (missing preceding v-if/v-else-if), but the rule also flags directives with arguments, modifiers, values, or conflicts with v-if/v-else-if on the same element.

Consider expanding to: "This rule reports v-else directives that have arguments, modifiers, values, are not preceded by a v-if or v-else-if directive, or conflict with v-if/v-else-if on the same element."

crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else_if.rs (1)

67-69: Code duplication: AnyHtmlElement is defined in multiple rules.

The AnyHtmlElement union is also declared in use_vue_valid_v_else.rs. Consider extracting this and the shared helper functions (has_v_if_or_else_if_directives, has_previous_sibling_with_v_if_or_else_if) to a common module to reduce duplication.

crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else.rs (1)

74-76: Duplicate AnyHtmlElement declaration.

This union is also declared in use_vue_valid_v_else_if.rs. Extract to a shared module along with the common helper functions.

crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_on.rs (1)

133-137: Consider reflecting custom modifiers in the warning text

Because the options struct lets users whitelist extra modifiers, this hard-coded list risks gaslighting them when the rule is configured. Folding the configured modifiers into the note (or recalculating the list on the fly) would keep the diagnostic honest.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aa55c8d and f0405cf.

⛔ Files ignored due to path filters (17)
  • crates/biome_configuration/src/analyzer/linter/rules.rs is excluded by !**/rules.rs and included by **
  • crates/biome_diagnostics_categories/src/categories.rs is excluded by !**/categories.rs and included by **
  • crates/biome_html_analyze/src/lint/nursery.rs is excluded by !**/nursery.rs and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElse/invalid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElse/valid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/invalid.html.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/invalid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/valid.html.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/valid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/invalid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/valid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVIf/invalid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVIf/valid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVOn/invalid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVOn/valid.vue.snap is excluded by !**/*.snap and included by **
  • packages/@biomejs/backend-jsonrpc/src/workspace.ts is excluded by !**/backend-jsonrpc/src/workspace.ts and included by **
  • packages/@biomejs/biome/configuration_schema.json is excluded by !**/configuration_schema.json and included by **
📒 Files selected for processing (26)
  • .changeset/no-vue-invalid-v-on.md (1 hunks)
  • .changeset/use-vue-valid-v-else-if.md (1 hunks)
  • .changeset/use-vue-valid-v-else.md (1 hunks)
  • .changeset/use-vue-valid-v-html.md (1 hunks)
  • .changeset/use-vue-valid-v-if.md (1 hunks)
  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else.rs (1 hunks)
  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else_if.rs (1 hunks)
  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_html.rs (1 hunks)
  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_if.rs (1 hunks)
  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_on.rs (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElse/invalid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElse/valid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/invalid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/valid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/invalid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/valid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVIf/invalid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVIf/valid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVOn/invalid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVOn/valid.vue (1 hunks)
  • crates/biome_rule_options/src/lib.rs (1 hunks)
  • crates/biome_rule_options/src/use_vue_valid_v_else.rs (1 hunks)
  • crates/biome_rule_options/src/use_vue_valid_v_else_if.rs (1 hunks)
  • crates/biome_rule_options/src/use_vue_valid_v_html.rs (1 hunks)
  • crates/biome_rule_options/src/use_vue_valid_v_if.rs (1 hunks)
  • crates/biome_rule_options/src/use_vue_valid_v_on.rs (1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/specs/html/**/*.html : Place HTML test cases under tests/specs/html as .html files discovered by the test macro

Applied to files:

  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/valid.vue
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/invalid.vue
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/src/lib.rs : Implement FormatLanguage for HtmlFormatLanguage with associated types: SyntaxLanguage=HtmlLanguage, Context=HtmlFormatContext, FormatRule=FormatHtmlSyntaxNode

Applied to files:

  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_html.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/src/cst.rs : Create FormatHtmlSyntaxNode in cst.rs implementing FormatRule<HtmlSyntaxNode> and AsFormat/IntoFormat for HtmlSyntaxNode using the provided plumbing

Applied to files:

  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_html.rs
📚 Learning: 2025-10-15T09:23:33.055Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:23:33.055Z
Learning: Applies to crates/biome_js_type_info/src/type_info.rs : Add new TypeScript type support by extending the TypeData enum rather than introducing parallel structures.

Applied to files:

  • crates/biome_rule_options/src/use_vue_valid_v_else.rs
  • crates/biome_rule_options/src/use_vue_valid_v_if.rs
  • crates/biome_rule_options/src/use_vue_valid_v_else_if.rs
  • crates/biome_rule_options/src/use_vue_valid_v_html.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/src/**/*.rs : After generation, remove usages of `format_verbatim_node` and implement real formatting with biome_formatter utilities

Applied to files:

  • crates/biome_rule_options/src/use_vue_valid_v_if.rs
  • crates/biome_rule_options/src/lib.rs
📚 Learning: 2025-10-15T09:23:33.055Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:23:33.055Z
Learning: Applies to crates/biome_js_type_info/biome_module_graph/src/**/*.rs : Do not copy or clone data between module graph entries (including behind Arc). Each module must avoid holding duplicated data from another module to enable simple invalidation.

Applied to files:

  • crates/biome_rule_options/src/lib.rs
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/crates/biome_*_{syntax,factory}/** : Create per-language crates biome_<lang>_syntax and biome_<lang>_factory under crates/

Applied to files:

  • crates/biome_rule_options/src/lib.rs
🧬 Code graph analysis (5)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_html.rs (3)
crates/biome_analyze/src/rule.rs (1)
  • same (246-251)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else.rs (2)
  • run (84-126)
  • diagnostic (128-183)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_if.rs (2)
  • run (82-120)
  • diagnostic (122-168)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_on.rs (1)
crates/biome_analyze/src/rule.rs (4)
  • recommended (602-605)
  • domains (632-635)
  • sources (617-620)
  • same (246-251)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else.rs (3)
crates/biome_analyze/src/rule.rs (1)
  • same (246-251)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else_if.rs (3)
  • run (77-119)
  • has_v_if_or_else_if_directives (242-265)
  • has_previous_sibling_with_v_if_or_else_if (231-240)
crates/biome_rowan/src/ast/mod.rs (2)
  • cast_ref (143-152)
  • try_cast (182-188)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else_if.rs (3)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else.rs (4)
  • run (84-126)
  • has_previous_sibling_with_v_if_or_else_if (214-224)
  • diagnostic (128-183)
  • has_v_if_or_else_if_directives (186-212)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_if.rs (2)
  • run (82-120)
  • diagnostic (122-168)
crates/biome_rowan/src/ast/mod.rs (2)
  • cast_ref (143-152)
  • try_cast (182-188)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_if.rs (3)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else.rs (2)
  • run (84-126)
  • diagnostic (128-183)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else_if.rs (2)
  • run (77-119)
  • diagnostic (121-195)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_html.rs (2)
  • run (61-105)
  • diagnostic (107-144)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: Test (depot-ubuntu-24.04-arm-16)
  • GitHub Check: Test (depot-windows-2022-16)
  • GitHub Check: End-to-end tests
  • GitHub Check: Check Dependencies
  • GitHub Check: Documentation
  • GitHub Check: Check JS Files
  • GitHub Check: Test Node.js API
  • GitHub Check: Bench (biome_configuration)
  • GitHub Check: autofix
🔇 Additional comments (15)
crates/biome_rule_options/src/use_vue_valid_v_on.rs (1)

1-15: LGTM!

The options struct follows the standard pattern with appropriate derives and serde configuration.

crates/biome_rule_options/src/use_vue_valid_v_else_if.rs (1)

1-6: LGTM!

Standard empty options struct with appropriate derives for a rule without configuration options.

crates/biome_rule_options/src/use_vue_valid_v_else.rs (1)

1-6: LGTM!

Consistent with the other empty options structs in this PR.

crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else_if.rs (2)

77-119: LGTM!

The validation logic correctly checks for arguments, modifiers, missing values, conflicting directives, and proper chaining with predecessors.


242-286: Good validation of predecessor validity.

The rule properly validates that the previous sibling's v-if or v-else-if is itself valid before accepting it as a valid chain predecessor. This prevents false negatives where an invalid predecessor would be considered acceptable.

crates/biome_html_analyze/tests/specs/nursery/useVueValidVIf/valid.vue (1)

1-7: LGTM!

The test cases cover the essential valid scenarios for v-if directives.

.changeset/use-vue-valid-v-else-if.md (1)

1-5: LGTM!

Changeset accurately documents the new rule.

crates/biome_html_analyze/tests/specs/nursery/useVueValidVOn/invalid.vue (1)

1-36: Excellent test coverage!

The test cases comprehensively cover invalid v-on scenarios including missing event names, missing handlers, invalid modifiers, and various syntax combinations.

crates/biome_html_analyze/tests/specs/nursery/useVueValidVElse/valid.vue (1)

1-33: LGTM!

Valid test cases appropriately cover various v-else usage patterns including chains, whitespace handling, and nested templates.

crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/valid.vue (1)

1-25: LGTM!

Valid test cases appropriately demonstrate proper v-html usage with expressions, combinations with other directives, and various element types.

crates/biome_html_analyze/tests/specs/nursery/useVueValidVIf/invalid.vue (1)

1-6: LGTM!

Test cases appropriately cover invalid v-if scenarios including unsupported arguments, modifiers, missing conditions, and conflicting directive combinations.

crates/biome_html_analyze/tests/specs/nursery/useVueValidVElse/invalid.vue (1)

1-30: Thorough test coverage!

Test cases comprehensively cover invalid v-else scenarios including unsupported arguments/modifiers/values, missing preceding conditionals, and conflicting directive combinations.

crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/valid.vue (1)

1-51: Excellent test coverage!

Valid test cases thoroughly demonstrate proper v-else-if usage including proper chaining, complex expressions, whitespace handling, template elements, and multiple sequential conditions.

crates/biome_rule_options/src/use_vue_valid_v_html.rs (1)

1-6: Consistent options surface.

Matches the existing Vue rule options pattern perfectly, so no worries here.

crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_html.rs (1)

61-141: Solid parity with ESLint’s rule.

Nice tidy port: we bail early on non v-html, surface the first bad modifier, and treat empty literals as missing values while letting real expressions through. Cheers for keeping the diagnostics helpful too.

@dyc3 dyc3 force-pushed the dyc3/vue-directive-rules branch 3 times, most recently from 5fcbb6b to 01beada Compare November 11, 2025 19:57
@dyc3 dyc3 marked this pull request as ready for review November 11, 2025 20:05
@dyc3 dyc3 requested review from a team November 11, 2025 20:05
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else.rs (1)

199-207: v-else still trusts dodgy neighbours

We’re only checking the predecessor’s name here, so <div v-if></div><div v-else></div> happily slips through even though the v-if is malformed. ESLint’s valid-v-else rejects that case. Please mirror the guard we use in useVueValidVElseIf and insist the predecessor has no argument/modifiers and does have an initialiser before we bless it.

-            let name = name_token.text();
-            if name == "v-if" || name == "v-else-if" {
-                return true;
-            }
+            let name = name_token.text();
+            if (name == "v-if" || name == "v-else-if")
+                && vue_dir.arg().is_none()
+                && vue_dir.modifiers().into_iter().next().is_none()
+                && vue_dir.initializer().is_some()
+            {
+                return true;
+            }
🧹 Nitpick comments (1)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_if.rs (1)

97-101: Prefer !is_empty() over .len() > 0.

Apply this diff:

-                if vue_directive.modifiers().len() > 0 {
+                if !vue_directive.modifiers().is_empty() {
                     return Some(ViolationKind::HasModifier(
                         vue_directive.modifiers().range(),
                     ));
                 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f0405cf and 01beada.

⛔ Files ignored due to path filters (17)
  • crates/biome_configuration/src/analyzer/linter/rules.rs is excluded by !**/rules.rs and included by **
  • crates/biome_diagnostics_categories/src/categories.rs is excluded by !**/categories.rs and included by **
  • crates/biome_html_analyze/src/lint/nursery.rs is excluded by !**/nursery.rs and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElse/invalid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElse/valid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/invalid.html.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/invalid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/valid.html.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/valid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/invalid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/valid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVIf/invalid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVIf/valid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVOn/invalid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVOn/valid.vue.snap is excluded by !**/*.snap and included by **
  • packages/@biomejs/backend-jsonrpc/src/workspace.ts is excluded by !**/backend-jsonrpc/src/workspace.ts and included by **
  • packages/@biomejs/biome/configuration_schema.json is excluded by !**/configuration_schema.json and included by **
📒 Files selected for processing (26)
  • .changeset/use-vue-valid-v-else-if.md (1 hunks)
  • .changeset/use-vue-valid-v-else.md (1 hunks)
  • .changeset/use-vue-valid-v-html.md (1 hunks)
  • .changeset/use-vue-valid-v-if.md (1 hunks)
  • .changeset/use-vue-valid-v-on.md (1 hunks)
  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else.rs (1 hunks)
  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else_if.rs (1 hunks)
  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_html.rs (1 hunks)
  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_if.rs (1 hunks)
  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_on.rs (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElse/invalid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElse/valid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/invalid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/valid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/invalid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/valid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVIf/invalid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVIf/valid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVOn/invalid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVOn/valid.vue (1 hunks)
  • crates/biome_rule_options/src/lib.rs (1 hunks)
  • crates/biome_rule_options/src/use_vue_valid_v_else.rs (1 hunks)
  • crates/biome_rule_options/src/use_vue_valid_v_else_if.rs (1 hunks)
  • crates/biome_rule_options/src/use_vue_valid_v_html.rs (1 hunks)
  • crates/biome_rule_options/src/use_vue_valid_v_if.rs (1 hunks)
  • crates/biome_rule_options/src/use_vue_valid_v_on.rs (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • .changeset/use-vue-valid-v-else-if.md
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVIf/valid.vue
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVIf/invalid.vue
🚧 Files skipped from review as they are similar to previous changes (10)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElse/valid.vue
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVOn/valid.vue
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElse/invalid.vue
  • crates/biome_rule_options/src/use_vue_valid_v_else_if.rs
  • crates/biome_rule_options/src/use_vue_valid_v_html.rs
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVOn/invalid.vue
  • crates/biome_rule_options/src/use_vue_valid_v_on.rs
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/invalid.vue
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/valid.vue
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/invalid.vue
🧰 Additional context used
🧠 Learnings (6)
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/src/**/*.rs : After generation, remove usages of `format_verbatim_node` and implement real formatting with biome_formatter utilities

Applied to files:

  • crates/biome_rule_options/src/lib.rs
  • crates/biome_rule_options/src/use_vue_valid_v_if.rs
📚 Learning: 2025-10-15T09:23:33.055Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:23:33.055Z
Learning: Applies to crates/biome_js_type_info/biome_module_graph/src/**/*.rs : Do not copy or clone data between module graph entries (including behind Arc). Each module must avoid holding duplicated data from another module to enable simple invalidation.

Applied to files:

  • crates/biome_rule_options/src/lib.rs
📚 Learning: 2025-10-15T09:23:33.055Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:23:33.055Z
Learning: Applies to crates/biome_js_type_info/src/type_info.rs : Add new TypeScript type support by extending the TypeData enum rather than introducing parallel structures.

Applied to files:

  • crates/biome_rule_options/src/use_vue_valid_v_if.rs
  • crates/biome_rule_options/src/use_vue_valid_v_else.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/specs/html/**/*.html : Place HTML test cases under tests/specs/html as .html files discovered by the test macro

Applied to files:

  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/valid.vue
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/src/lib.rs : Implement FormatLanguage for HtmlFormatLanguage with associated types: SyntaxLanguage=HtmlLanguage, Context=HtmlFormatContext, FormatRule=FormatHtmlSyntaxNode

Applied to files:

  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_html.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/src/cst.rs : Create FormatHtmlSyntaxNode in cst.rs implementing FormatRule<HtmlSyntaxNode> and AsFormat/IntoFormat for HtmlSyntaxNode using the provided plumbing

Applied to files:

  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_html.rs
🧬 Code graph analysis (5)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_on.rs (2)
crates/biome_analyze/src/rule.rs (1)
  • same (246-251)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_html.rs (2)
  • run (61-105)
  • diagnostic (107-144)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else.rs (2)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else_if.rs (3)
  • run (77-119)
  • has_v_if_or_else_if_directives (242-265)
  • has_previous_sibling_with_v_if_or_else_if (231-240)
crates/biome_rowan/src/ast/mod.rs (2)
  • cast_ref (143-152)
  • try_cast (182-188)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else_if.rs (3)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else.rs (4)
  • run (84-126)
  • has_previous_sibling_with_v_if_or_else_if (214-224)
  • diagnostic (128-183)
  • has_v_if_or_else_if_directives (186-212)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_if.rs (2)
  • run (82-120)
  • diagnostic (122-168)
crates/biome_rowan/src/ast/mod.rs (2)
  • cast_ref (143-152)
  • try_cast (182-188)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_if.rs (3)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else.rs (2)
  • run (84-126)
  • diagnostic (128-183)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else_if.rs (2)
  • run (77-119)
  • diagnostic (121-195)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_html.rs (2)
  • run (61-105)
  • diagnostic (107-144)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_html.rs (3)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else.rs (2)
  • run (84-126)
  • diagnostic (128-183)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_if.rs (2)
  • run (82-120)
  • diagnostic (122-168)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_on.rs (2)
  • run (62-110)
  • diagnostic (112-150)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Test (depot-windows-2022-16)
  • GitHub Check: Lint project (depot-windows-2022)
  • GitHub Check: Test Node.js API
  • GitHub Check: autofix
🔇 Additional comments (10)
.changeset/use-vue-valid-v-if.md (1)

1-5: LGTM!

The changeset description accurately reflects the rule's behaviour.

.changeset/use-vue-valid-v-html.md (1)

1-5: LGTM!

The changeset now comprehensively describes all violation types the rule detects.

crates/biome_rule_options/src/use_vue_valid_v_if.rs (1)

1-6: LGTM!

Standard options struct pattern with appropriate derives for future extensibility.

crates/biome_rule_options/src/lib.rs (1)

376-380: LGTM!

Module exports are properly structured and follow the existing pattern.

crates/biome_rule_options/src/use_vue_valid_v_else.rs (1)

1-6: LGTM!

Consistent options struct pattern across Vue rules.

crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_if.rs (2)

109-114: Let-chains syntax used.

The if let ... && let ... syntax requires Rust 1.64+. This is likely fine for the project, but worth noting if minimum supported Rust version is a concern.


82-120: Implementation looks correct.

The validation logic properly checks for arguments, modifiers, missing values, and conflicts with v-else/v-else-if directives.

crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_on.rs (2)

62-110: Rule implementation handles both v-on forms correctly.

The logic properly handles both the full v-on:event syntax and the @event shorthand, with appropriate validation for each.


42-48: Good use of LazyLock for static set.

Efficient pattern for compile-time constant set initialisation.

.changeset/use-vue-valid-v-on.md (1)

1-5: LGTM!

Comprehensive description covering both v-on syntaxes and all validation checks.

@dyc3 dyc3 force-pushed the dyc3/vue-directive-rules branch from 01beada to eb7e199 Compare November 12, 2025 13:38
…ueValidVElse`, `useVueValidVOn` and

`useVueValidVHtml`
@dyc3 dyc3 force-pushed the dyc3/vue-directive-rules branch from eb7e199 to 9febe70 Compare November 12, 2025 13:44
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_on.rs (1)

50-54: Missing Debug derive on ViolationKind.

Based on learnings, this enum should derive Debug for consistency with other rules.

Apply this diff:

+#[derive(Debug)]
 pub enum ViolationKind {
     MissingEventName,
     InvalidModifier(TextRange),
     MissingHandler,
 }
🧹 Nitpick comments (2)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_html.rs (2)

49-53: Add Debug derive for consistency.

The ViolationKind enum is missing a #[derive(Debug)] attribute. Whilst not strictly necessary, the equivalent enum in use_vue_valid_v_if.rs (line 68) includes it, and it's good practice for error types.

Apply this diff:

+#[derive(Debug)]
 pub enum ViolationKind {
     UnexpectedArgument(TextRange),
     UnexpectedModifier(TextRange),
     MissingValue,
 }

78-99: Consider simplifying the nested empty-value logic.

The current implementation is correct but quite deeply nested. Whilst functional, it could be more readable with early returns or helper functions.

Example refactor (optional):

if let Some(initializer) = vue_directive.initializer() {
    let is_empty_value = match initializer.value() {
        Ok(AnyHtmlAttributeInitializer::HtmlString(html_string)) => {
            html_string.value_token()
                .map_or(true, |token| token.text().is_empty())
        }
        Ok(_) => false, // Non-string values are valid
        Err(_) => true,
    };
    
    if is_empty_value {
        return Some(ViolationKind::MissingValue);
    }
} else {
    return Some(ViolationKind::MissingValue);
}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 01beada and 9febe70.

⛔ Files ignored due to path filters (17)
  • crates/biome_configuration/src/analyzer/linter/rules.rs is excluded by !**/rules.rs and included by **
  • crates/biome_diagnostics_categories/src/categories.rs is excluded by !**/categories.rs and included by **
  • crates/biome_html_analyze/src/lint/nursery.rs is excluded by !**/nursery.rs and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElse/invalid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElse/valid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/invalid.html.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/invalid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/valid.html.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/valid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/invalid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/valid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVIf/invalid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVIf/valid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVOn/invalid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVOn/valid.vue.snap is excluded by !**/*.snap and included by **
  • packages/@biomejs/backend-jsonrpc/src/workspace.ts is excluded by !**/backend-jsonrpc/src/workspace.ts and included by **
  • packages/@biomejs/biome/configuration_schema.json is excluded by !**/configuration_schema.json and included by **
📒 Files selected for processing (26)
  • .changeset/use-vue-valid-v-else-if.md (1 hunks)
  • .changeset/use-vue-valid-v-else.md (1 hunks)
  • .changeset/use-vue-valid-v-html.md (1 hunks)
  • .changeset/use-vue-valid-v-if.md (1 hunks)
  • .changeset/use-vue-valid-v-on.md (1 hunks)
  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else.rs (1 hunks)
  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else_if.rs (1 hunks)
  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_html.rs (1 hunks)
  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_if.rs (1 hunks)
  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_on.rs (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElse/invalid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElse/valid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/invalid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/valid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/invalid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/valid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVIf/invalid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVIf/valid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVOn/invalid.vue (1 hunks)
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVOn/valid.vue (1 hunks)
  • crates/biome_rule_options/src/lib.rs (1 hunks)
  • crates/biome_rule_options/src/use_vue_valid_v_else.rs (1 hunks)
  • crates/biome_rule_options/src/use_vue_valid_v_else_if.rs (1 hunks)
  • crates/biome_rule_options/src/use_vue_valid_v_html.rs (1 hunks)
  • crates/biome_rule_options/src/use_vue_valid_v_if.rs (1 hunks)
  • crates/biome_rule_options/src/use_vue_valid_v_on.rs (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • .changeset/use-vue-valid-v-else-if.md
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/valid.vue
🚧 Files skipped from review as they are similar to previous changes (13)
  • .changeset/use-vue-valid-v-on.md
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVIf/valid.vue
  • crates/biome_rule_options/src/use_vue_valid_v_else.rs
  • crates/biome_rule_options/src/use_vue_valid_v_html.rs
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElseIf/invalid.vue
  • .changeset/use-vue-valid-v-if.md
  • .changeset/use-vue-valid-v-else.md
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVOn/invalid.vue
  • crates/biome_rule_options/src/use_vue_valid_v_on.rs
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVOn/valid.vue
  • crates/biome_rule_options/src/use_vue_valid_v_if.rs
  • .changeset/use-vue-valid-v-html.md
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVIf/invalid.vue
🧰 Additional context used
🧠 Learnings (9)
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/src/cst.rs : Create FormatHtmlSyntaxNode in cst.rs implementing FormatRule<HtmlSyntaxNode> and AsFormat/IntoFormat for HtmlSyntaxNode using the provided plumbing

Applied to files:

  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_html.rs
📚 Learning: 2025-10-15T09:21:24.116Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:21:24.116Z
Learning: Prefer implementing the Diagnostic trait via `#[derive(Diagnostic)]`

Applied to files:

  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_on.rs
📚 Learning: 2025-10-15T09:21:24.116Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:21:24.116Z
Learning: Types deriving `Diagnostic` must also implement `Debug`

Applied to files:

  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_on.rs
📚 Learning: 2025-10-15T09:21:24.116Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:21:24.116Z
Learning: `#[derive(Diagnostic)]` is supported on enums; each variant must contain a type that is itself a diagnostic

Applied to files:

  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_on.rs
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Use `dbg_write!` to debug and inspect the emitted IR during formatting

Applied to files:

  • crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_on.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/specs/html/**/*.html : Place HTML test cases under tests/specs/html as .html files discovered by the test macro

Applied to files:

  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/invalid.vue
  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVElse/valid.vue
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/spec_tests.rs : In tests/spec_tests.rs, generate tests with `tests_macros::gen_tests! {"tests/specs/html/**/*.html", crate::spec_test::run, ""}`

Applied to files:

  • crates/biome_html_analyze/tests/specs/nursery/useVueValidVHtml/invalid.vue
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/src/**/*.rs : After generation, remove usages of `format_verbatim_node` and implement real formatting with biome_formatter utilities

Applied to files:

  • crates/biome_rule_options/src/lib.rs
📚 Learning: 2025-10-15T09:23:33.055Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:23:33.055Z
Learning: Applies to crates/biome_js_type_info/biome_module_graph/src/**/*.rs : Do not copy or clone data between module graph entries (including behind Arc). Each module must avoid holding duplicated data from another module to enable simple invalidation.

Applied to files:

  • crates/biome_rule_options/src/lib.rs
🧬 Code graph analysis (5)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_html.rs (3)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else.rs (2)
  • run (84-126)
  • diagnostic (128-183)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_if.rs (2)
  • run (82-120)
  • diagnostic (122-168)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_on.rs (2)
  • run (62-110)
  • diagnostic (112-158)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_on.rs (4)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else.rs (2)
  • run (84-126)
  • diagnostic (128-183)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else_if.rs (2)
  • run (77-119)
  • diagnostic (121-195)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_html.rs (2)
  • run (61-105)
  • diagnostic (107-144)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_if.rs (2)
  • run (82-120)
  • diagnostic (122-168)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_if.rs (3)
crates/biome_analyze/src/rule.rs (3)
  • domains (632-635)
  • sources (617-620)
  • same (246-251)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else.rs (2)
  • run (84-126)
  • diagnostic (128-183)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else_if.rs (2)
  • run (77-119)
  • diagnostic (121-195)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else_if.rs (3)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else.rs (4)
  • run (84-126)
  • has_previous_sibling_with_v_if_or_else_if (214-224)
  • diagnostic (128-183)
  • has_v_if_or_else_if_directives (186-212)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_if.rs (2)
  • run (82-120)
  • diagnostic (122-168)
crates/biome_rowan/src/ast/mod.rs (2)
  • cast_ref (143-152)
  • try_cast (182-188)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else.rs (2)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else_if.rs (2)
  • has_v_if_or_else_if_directives (242-265)
  • has_previous_sibling_with_v_if_or_else_if (231-240)
crates/biome_rowan/src/ast/mod.rs (2)
  • cast_ref (143-152)
  • try_cast (182-188)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: Check Dependencies
  • GitHub Check: Test (depot-ubuntu-24.04-arm-16)
  • GitHub Check: Test (depot-windows-2022-16)
  • GitHub Check: Documentation
  • GitHub Check: Lint project (depot-windows-2022)
  • GitHub Check: Test Node.js API
  • GitHub Check: Bench (biome_configuration)
  • GitHub Check: Check JS Files
  • GitHub Check: autofix
🔇 Additional comments (2)
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else.rs (1)

186-212: Inconsistent predecessor validation compared to use_vue_valid_v_else_if.

The has_v_if_or_else_if_directives function only checks for the presence of v-if or v-else-if by name but doesn't validate that those directives are well-formed. Compare with use_vue_valid_v_else_if.rs (lines 242-265) which calls is_valid_chain_directive to ensure predecessors have no argument, no modifiers, and have a value.

This inconsistency means v-else could accept an invalid v-if/v-else-if as a valid predecessor, e.g., <div v-if></div><div v-else></div> (where v-if is missing a value).

Should this rule validate predecessor validity like use_vue_valid_v_else_if does, or is the current behaviour intentional? If validation is needed, consider adding a helper similar to is_valid_chain_directive:

fn has_v_if_or_else_if_directives(element: &AnyHtmlElement) -> bool {
    let attribute_list = match element {
        AnyHtmlElement::HtmlElement(html_element) => {
            let Ok(opening_element) = html_element.opening_element() else {
                return false;
            };
            opening_element.attributes()
        }
        AnyHtmlElement::HtmlSelfClosingElement(self_closing) => self_closing.attributes(),
    };

    for attribute in attribute_list {
        if let Ok(AnyVueDirective::VueDirective(vue_dir)) =
            AnyVueDirective::try_cast(attribute.syntax().clone())
            && let Ok(name_token) = vue_dir.name_token()
        {
            let name = name_token.text();
            if (name == "v-if" || name == "v-else-if") && is_valid_predecessor(&vue_dir) {
                return true;
            }
        }
    }
    false
}

fn is_valid_predecessor(dir: &VueDirective) -> bool {
    dir.arg().is_none() 
        && dir.modifiers().into_iter().next().is_none() 
        && dir.initializer().is_some()
}
crates/biome_html_analyze/src/lint/nursery/use_vue_valid_v_else_if.rs (1)

59-65: Missing Debug derive on ViolationKind.

Based on learnings and consistency with other rules in the codebase, this enum should derive Debug.

Apply this diff:

+#[derive(Debug)]
 pub enum ViolationKind {
     HasArgument,
     HasModifier(TextRange),
     MissingValue,
     MissingPreviousConditional,
     ConflictsWithOtherDirective(TextRange),
 }
⛔ Skipped due to learnings
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/xtask/codegen/*.ungram : Unions of nodes must start with Any* (e.g., AnyHtmlAttribute)

@dyc3 dyc3 merged commit 0170dcb into main Nov 12, 2025
17 checks passed
@dyc3 dyc3 deleted the dyc3/vue-directive-rules branch November 12, 2025 14:08
@github-actions github-actions bot mentioned this pull request Nov 12, 2025
ematipico pushed a commit to hamirmahal/biome that referenced this pull request Nov 19, 2025
…ueValidVElse`, `useVueValidVOn` and `useVueValidVHtml` (biomejs#8077)
l0ngvh pushed a commit to l0ngvh/biome that referenced this pull request Dec 21, 2025
…ueValidVElse`, `useVueValidVOn` and `useVueValidVHtml` (biomejs#8077)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Diagnostic Area: diagnostocis A-Linter Area: linter A-Project Area: project L-HTML Language: HTML and super languages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants