-
-
Notifications
You must be signed in to change notification settings - Fork 724
feat(linter): implement useVueDefineMacrosOrder
#7712
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
🦋 Changeset detectedLatest commit: 6ad6597 The changes in this PR will be included in the next version bump. This PR includes changesets to release 13 packages
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 |
CodSpeed Performance ReportMerging #7712 will not alter performanceComparing Summary
Footnotes
|
WalkthroughAdds a new nursery lint rule UseVueDefineMacrosOrder that enforces a configurable order for Vue <script setup> compiler macros and provides an autofix to reorder top-level module items. Introduces UseVueDefineMacrosOrderOptions (with a default order) and exports its module. Adds a public MacroOrderIssue type and implements the Rule for UseVueDefineMacrosOrder. Adds a changeset entry and multiple Vue SFC test fixtures covering valid, invalid, and custom-order cases. Suggested labels
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (14)
crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs
is excluded by!**/migrate/eslint_any_rule_to_biome.rs
and included by**
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_js_analyze/src/lint/nursery.rs
is excluded by!**/nursery.rs
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-a.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-b.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-with-defaults.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/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 (14)
.changeset/bright-insects-ring.md
(1 hunks)crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-a.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-b.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.options.json
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-with-defaults.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.options.json
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid.vue
(1 hunks)crates/biome_rule_options/src/lib.rs
(1 hunks)crates/biome_rule_options/src/use_vue_define_macros_order.rs
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
crates/biome_*_{syntax,parser,formatter,analyze,factory,semantic}/**
📄 CodeRabbit inference engine (CLAUDE.md)
Maintain the per-language crate structure: biome_{lang}_{syntax,parser,formatter,analyze,factory,semantic}
Files:
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.options.json
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-with-defaults.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-b.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.options.json
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.vue
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-a.vue
crates/biome_*/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place core crates under /crates/biome_*/
Files:
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.options.json
crates/biome_rule_options/src/lib.rs
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-with-defaults.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-b.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.options.json
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.vue
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-a.vue
crates/biome_rule_options/src/use_vue_define_macros_order.rs
**/tests/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place test files under a tests/ directory in each crate
Files:
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.options.json
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-with-defaults.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-b.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.options.json
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-a.vue
.changeset/**/*.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
.changeset/**/*.md
: Create changesets using thejust new-changeset
command; do not author them manually
In changeset markdown, only use headers #### or #####
Changeset descriptions must end every sentence with a full stop (.)
For bug fixes, start the changeset description with a linked issue reference like “Fixed #1234”
Prefer past tense for what was done and present tense for current behavior in changesets
Files:
.changeset/bright-insects-ring.md
**/*.{rs,toml}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Before committing, format Rust and TOML files (e.g., via
just f
/just format
)
Files:
crates/biome_rule_options/src/lib.rs
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs
crates/biome_rule_options/src/use_vue_define_macros_order.rs
**/*.rs
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Document rules, assists, and options via inline rustdoc in Rust source
Files:
crates/biome_rule_options/src/lib.rs
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs
crates/biome_rule_options/src/use_vue_define_macros_order.rs
🧠 Learnings (3)
📚 Learning: 2025-10-02T12:57:33.209Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-02T12:57:33.209Z
Learning: Applies to crates/biome_analyze/crates/biome_js_analyze/tests/specs/nursery/** : Place snapshot tests for new rules under tests/specs/nursery/<ruleName>/ with files prefixed by invalid* and valid*
Applied to files:
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.options.json
📚 Learning: 2025-08-05T14:43:29.581Z
Learnt from: dyc3
PR: biomejs/biome#7081
File: packages/@biomejs/biome/configuration_schema.json:7765-7781
Timestamp: 2025-08-05T14:43:29.581Z
Learning: The file `packages/biomejs/biome/configuration_schema.json` is auto-generated and should not be manually edited or reviewed for schema issues; any changes should be made at the code generation source.
Applied to files:
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.options.json
📚 Learning: 2025-10-02T12:57:33.209Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-02T12:57:33.209Z
Learning: Applies to crates/biome_analyze/crates/biome_rule_options/lib/*.rs : Define per-rule options in biome_rule_options/lib/<rule>.rs with a dedicated options struct/enum (camelCase serde names, deny_unknown_fields, default) and derive Serialize/Deserialize/Deserializable (and schemars JsonSchema when schema feature is on)
Applied to files:
crates/biome_rule_options/src/use_vue_define_macros_order.rs
🧬 Code graph analysis (2)
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs (3)
packages/@biomejs/backend-jsonrpc/src/workspace.ts (4)
FixKind
(7941-7941)RuleDomain
(904-912)TextRange
(9292-9292)UseVueDefineMacrosOrderOptions
(8297-8302)crates/biome_js_factory/src/generated/node_factory.rs (1)
js_module_item_list
(6976-6987)crates/biome_js_syntax/src/generated/nodes.rs (1)
declarators
(6878-6880)
crates/biome_rule_options/src/use_vue_define_macros_order.rs (1)
packages/@biomejs/backend-jsonrpc/src/workspace.ts (1)
UseVueDefineMacrosOrderOptions
(8297-8302)
🪛 GitHub Actions: Pull request Markdown
.changeset/bright-insects-ring.md
[error] 13-13: markdownlint: MD047/single-trailing-newline. Files should end with a single newline character.
🪛 GitHub Check: lint
.changeset/bright-insects-ring.md
[failure] 13-13: Files should end with a single newline character
.changeset/bright-insects-ring.md:13:3 MD047/single-trailing-newline Files should end with a single newline character https://github.com/DavidAnson/markdownlint/blob/v0.38.0/doc/md047.md
⏰ 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). (14)
- GitHub Check: Test (depot-windows-2022-16)
- GitHub Check: Documentation
- GitHub Check: Test (depot-ubuntu-24.04-arm-16)
- GitHub Check: End-to-end tests
- GitHub Check: Bench (biome_js_analyze)
- GitHub Check: Lint project (depot-windows-2022)
- GitHub Check: Lint project (depot-ubuntu-24.04-arm-16)
- GitHub Check: Bench (biome_js_formatter)
- GitHub Check: Test Node.js API
- GitHub Check: Check Dependencies
- GitHub Check: Bench (biome_js_parser)
- GitHub Check: autofix
- GitHub Check: Check JS Files
- GitHub Check: Bench (biome_configuration)
🔇 Additional comments (7)
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.options.json (1)
1-20
: LGTM!The custom order configuration correctly tests an extended macro sequence including
definePage
.crates/biome_rule_options/src/lib.rs (1)
367-367
: LGTM!Module export follows the established pattern and is correctly positioned alphabetically.
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.options.json (1)
1-20
: LGTM!The configuration matches
invalid-custom.options.json
, which is correct—the validity difference comes from whether the corresponding.vue
fixture follows this order.crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-with-defaults.vue (1)
1-18
: LGTM!Test fixture correctly demonstrates invalid macro ordering with
withDefaults
wrappingdefineProps
.crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid.vue (1)
1-18
: LGTM!Test fixture correctly demonstrates valid macro ordering with
defineProps
beforedefineEmits
.crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid.vue (1)
1-20
: LGTM!Test fixture correctly demonstrates invalid macro ordering and includes comments to test proper handling of interspersed annotations.
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single.vue (1)
1-17
: LGTM!Test fixture correctly demonstrates invalid macro ordering in a comma-separated declaration, covering an important edge case.
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs
Outdated
Show resolved
Hide resolved
de7e548
to
a2748df
Compare
let statement = statements.remove(from); | ||
|
||
// Need to add newline after the moved statement, because it may not have one. | ||
let trailing_trivia = make::token(T![;]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally this would add newline only when needed, but I am not sure how to check for it generally without needing to handle a lot of node types.
Element after moved macro can be any JS statement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (3)
.changeset/bright-insects-ring.md (1)
13-13
: Trailing newline still required.The missing trailing newline has already been flagged and must be fixed before merge.
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs (2)
150-173
: Critical: Call expression branch misses later out-of-order macros.Lines 170-172 do nothing when a macro is in correct order (same/higher
order_index
), meaningfound_macro
is never updated. This causes later out-of-order macros to slip through undetected.Example that fails:
defineModel() // order 0, found_macro = Some(order: 0) defineEmits() // order 2, NOT < 0, so no update (found_macro still order: 0) defineProps() // order 1, NOT < 0, so no update—bug! Should be caught.The declarator branch (lines 201-216) handles this correctly by always updating
found_macro
. Apply the same fix here.- _ => { - // Same/higher order, do nothing + Some(c) => { + let has_violation = c.has_out_of_order_content_prior || non_macro_found; + found_macro = Some(FoundMacro { + order_index, + fixable_statement_index: Some(index), + range: statement.range(), + has_out_of_order_content_prior: has_violation, + }); }
226-236
: Major: Fix placement moves macros to top instead of after last in-order macro.
skippable_top_statements_end_index
(line 138) only tracks skippable pre-content, not the position of previously seen macros. When reordering macros, the fixer moves the out-of-order macro to the top (e.g., index 0 or 1) rather than inserting it after the last correctly ordered macro.Example:
defineModel() // index 0 defineEmits() // index 1, order 2 defineProps() // index 2, order 1—out of orderCurrent fix:
move_from_to = (2, 0)
→ movesdefineProps
to the very top.
Expected fix:move_from_to = (2, 1)
→ insertsdefineProps
afterdefineModel
.Store each seen macro's index and
order_index
as you iterate. When you detect an out-of-order macro, scan backwards through those recorded macros to find the nearest one withorder_index ≤ current_order_index
, and set the target tothat_macro_index + 1
. Fall back toskippable_top_statements_end_index
only if no such macro exists.
🧹 Nitpick comments (1)
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs (1)
278-284
: Optional: Unconditional newline may create double spacing.Lines 278-281 always append a newline to the moved statement, even if trailing trivia already exists. This can result in double newlines.
Check whether the statement already has trailing newline trivia before adding one:
let trailing_trivia = statement.syntax().last_trailing_trivia(); let needs_newline = trailing_trivia .and_then(|t| t.pieces().last()) .map_or(true, |piece| piece.kind() != TriviaPieceKind::Newline); let statement = if needs_newline { let newline_trivia = make::token(T![;]) .with_trailing_trivia([(TriviaPieceKind::Newline, "\n")]) .trailing_trivia() .pieces(); statement.with_trailing_trivia_pieces(newline_trivia)? } else { statement };
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (16)
crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs
is excluded by!**/migrate/eslint_any_rule_to_biome.rs
and included by**
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_js_analyze/src/lint/nursery.rs
is excluded by!**/nursery.rs
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-a.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-b.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-c.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single-a.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-with-defaults.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/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 (16)
.changeset/bright-insects-ring.md
(1 hunks)crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-a.vue
(1 hunks)crates/biome 8000 _js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-b.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-c.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.options.json
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single-a.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-with-defaults.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.options.json
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid.vue
(1 hunks)crates/biome_rule_options/src/lib.rs
(1 hunks)crates/biome_rule_options/src/use_vue_define_macros_order.rs
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
- crates/biome_rule_options/src/lib.rs
- crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.vue
- crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.options.json
- crates/biome_rule_options/src/use_vue_define_macros_order.rs
- crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-with-defaults.vue
- crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-a.vue
- crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-b.vue
🧰 Additional context used
📓 Path-based instructions (6)
crates/biome_*_{syntax,parser,formatter,analyze,factory,semantic}/**
📄 CodeRabbit inference engine (CLAUDE.md)
Maintain the per-language crate structure: biome_{lang}_{syntax,parser,formatter,analyze,factory,semantic}
Files:
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.options.json
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid.vue
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-c.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single-a.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.vue
crates/biome_*/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place core crates under /crates/biome_*/
Files:
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.options.json
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid.vue
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-c.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single-a.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.vue
**/tests/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place test files under a tests/ directory in each crate
Files:
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.options.json
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-c.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single-a.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.vue
.changeset/**/*.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
.changeset/**/*.md
: Create changesets using thejust new-changeset
command; do not author them manually
In changeset markdown, only use headers #### or #####
Changeset descriptions must end every sentence with a full stop (.)
For bug fixes, start the changeset description with a linked issue reference like “Fixed #1234”
Prefer past tense for what was done and present tense for current behavior in changesets
Files:
.changeset/bright-insects-ring.md
**/*.{rs,toml}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Before committing, format Rust and TOML files (e.g., via
just f
/just format
)
Files:
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs
**/*.rs
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Document rules, assists, and options via inline rustdoc in Rust source
Files:
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs
🧠 Learnings (1)
📚 Learning: 2025-10-02T12:57:33.228Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-02T12:57:33.228Z
Learning: Applies to crates/biome_analyze/crates/biome_js_analyze/tests/specs/nursery/** : Place snapshot tests for new rules under tests/specs/nursery/<ruleName>/ with files prefixed by invalid* and valid*
Applied to files:
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.options.json
🧬 Code graph analysis (1)
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs (3)
packages/@biomejs/backend-jsonrpc/src/workspace.ts (4)
FixKind
(7941-7941)RuleDomain
(904-912)TextRange
(9292-9292)UseVueDefineMacrosOrderOptions
(8297-8302)crates/biome_js_factory/src/generated/node_factory.rs (1)
js_module_item_list
(6976-6987)crates/biome_js_syntax/src/generated/nodes.rs (1)
declarators
(6878-6880)
⏰ 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). (1)
- GitHub Check: Lint project (depot-windows-2022)
🔇 Additional comments (9)
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.options.json (1)
1-20
: LGTM!The configuration correctly specifies a custom macro order including
definePage
, which aligns with the exploration mentioned in the PR objectives.crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single.vue (1)
1-17
: LGTM!The test fixture correctly demonstrates an invalid macro order scenario where
defineEmits
precedesdefineProps
on the same line.crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid.vue (1)
1-18
: LGTM!The test fixture correctly demonstrates valid macro ordering with
defineProps
beforedefineEmits
.crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.vue (1)
1-20
: LGTM!The test fixture correctly demonstrates a valid custom macro order including
definePage
, matching the configuration invalid-custom.options.json
(presumably).crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single-a.vue (1)
2-2
: Verify missing ref import is intentional.Similar to
invalid-c.vue
, this test callsref(0)
without importing it from Vue. Vue compiler macros are auto-imported, butref
is not.crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid.vue (1)
1-20
: LGTM!The test fixture correctly demonstrates an invalid macro order scenario with comments interspersed, which will verify that the lint rule preserves comments when reordering.
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-c.vue (1)
2-4
: Missingref
import is intentional in invalid-c.vue nursery fixture. These test cases deliberately omit imports to simulate invalid code paths.crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs (2)
1-108
: LGTM on rule metadata and documentation.The rule declaration, metadata, and examples are clear and well-structured. Good handling of the
withDefaults
wrapper and flexibleorder
configuration.
304-361
: LGTM on helper functions.The helper functions correctly extract macro names from call expressions and declarators, handle
withDefaults(defineProps(...))
, and identify skippable pre-macro content (imports, types, debugger statements, etc.).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good!
Multi script handling is broken
Vue lets you have multiple script blocks? It's certainly an edge case, I'm not aware of any reason why you would want to do that.
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs
Outdated
Show resolved
Hide resolved
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs
Outdated
Show resolved
Hide resolved
1262b48
to
1612ad0
Compare
Macros themselves inside multi script file are rare, but I was more referring into the fact that multi script handling itself is broken. When I tried to add snapshots, only first script would be outputted, second one discarded. In my own codebases I use them a lot, so no idea how this rule would behave. In any case this is temporary issue. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is sufficient to close #7345, unless there's something that I'm not aware of. Could you update the issue link so that it auto closes?
e6afa6f
to
6ad6597
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (3)
.changeset/bright-insects-ring.md (1)
1-13
: Ensure the file ends with a single newline.A previous review flagged that this file must end with exactly one newline character. Please verify the fix has been applied.
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs (2)
232-234
: Verify fix placement for macro reordering.The current logic always moves the out-of-order macro to
skippable_top_statements_end_index
, which doesn't account for correctly-placed macros in between. This can result in moving a macro too far forward.A prior review suggested tracking seen macros and computing the precise insertion slot. Please verify the current behavior meets expectations or address the placement logic.
150-173
: Critical: Rule misses violations when macros are partially ordered.The call-expression branch doesn't update
found_macro
for in-order macros (lines 170-172), which means subsequent out-of-order macros are compared against a stale baseline.Example:
defineModel
(order 0),defineEmits
(order 2),defineProps
(order 1)
- After
defineModel
:found_macro.order_index = 0
- After
defineEmits
: order 2 ≥ 0, no update,found_macro.order_index
still 0- After
defineProps
: order 1 ≥ 0, no update, never detects that Props (1) < Emits (2)The declarator branch (lines 201-216) correctly updates for all macros. Apply the same pattern here.
Apply this diff:
match &found_macro { None => { found_macro = Some(FoundMacro { order_index, fixable_statement_index: Some(index), range: statement.range(), has_out_of_order_content_prior: non_macro_found, }); } Some(c) if order_index < c.order_index => { found_macro = Some(FoundMacro { order_index, fixable_statement_index: Some(index), range: statement.range(), has_out_of_order_content_prior: true, }); } - _ => { - // Same/higher order, do nothing + Some(c) => { + found_macro = Some(FoundMacro { + order_index, + fixable_statement_index: Some(index), + range: statement.range(), + has_out_of_order_content_prior: c.has_out_of_order_content_prior || non_macro_found, + }); } }
🧹 Nitpick comments (1)
crates/biome_rule_options/src/use_vue_define_macros_order.rs (1)
8-8
: Optional: The field-level#[serde(default)]
is redundant.Since the struct already has
#[serde(default)]
at line 5, the field-level attribute at line 8 is unnecessary. The struct-level default handles all fields automatically.Apply this diff to remove the redundant attribute:
/// The order of the Vue define macros. - #[serde(default)] pub order: Box<[Box<str>]>,
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (16)
crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs
is excluded by!**/migrate/eslint_any_rule_to_biome.rs
and included by**
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_js_analyze/src/lint/nursery.rs
is excluded by!**/nursery.rs
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-a.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-b.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-c.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single-a.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-with-defaults.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.vue.snap
is excluded by!**/*.snap
and included by**
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/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 (16)
.changeset/bright-insects-ring.md
(1 hunks)crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-a.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-b.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-c.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.options.json
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single-a.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-with-defaults.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.options.json
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.vue
(1 hunks)crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid.vue
(1 hunks)crates/biome_rule_options/src/lib.rs
(1 hunks)crates/biome_rule_options/src/use_vue_define_macros_order.rs
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
- crates/biome_rule_options/src/lib.rs
- crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-b.vue
- crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-with-defaults.vue
- crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid.vue
- crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.vue
- crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single.vue
- crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.options.json
- crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/valid-custom.vue
- crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid.vue
🧰 Additional context used
📓 Path-based instructions (5)
.changeset/*.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
.changeset/*.md
: In changesets, only use #### or ##### headers; other header levels are not allowed
Changesets should cover user-facing changes only; internal changes do not need changesets
Use past tense for what you did and present tense for current Biome behavior in changesets
When fixing a bug in a changeset, start with an issue link (e.g., “Fixed #1234: …”)
When referencing a rule or assist in a changeset, include a link to its page on the website
Include code blocks in changesets when applicable to illustrate changes
End every sentence in a changeset with a period
Files:
.changeset/bright-insects-ring.md
crates/biome_*/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place core crates under /crates/biome_*/
Files:
crates/biome_rule_options/src/use_vue_define_macros_order.rs
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.options.json
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-a.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single-a.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-c.vue
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs
**/*.rs
📄 CodeRabbit inference engine (CONTRIBUTING.md)
**/*.rs
: Format Rust files before committing (e.g., viajust f
which formats Rust)
Document rules, assists, and options with inline rustdoc in source
Files:
crates/biome_rule_options/src/use_vue_define_macros_order.rs
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs
crates/biome_*_{syntax,parser,formatter,analyze,factory,semantic}/**
📄 CodeRabbit inference engine (CLAUDE.md)
Maintain the per-language crate structure: biome_{lang}_{syntax,parser,formatter,analyze,factory,semantic}
Files:
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.options.json
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-a.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single-a.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-c.vue
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs
**/tests/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place test files under a tests/ directory in each crate
Files:
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.options.json
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-a.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-single-a.vue
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-c.vue
🧠 Learnings (2)
📚 Learning: 2025-10-15T09:20:19.139Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:20:19.139Z
Learning: Applies to crates/biome_analyze/crates/biome_rule_options/lib/**/*.rs : For options types, derive Serialize, Deserialize, Deserializable (and JsonSchema under the schema feature) and use #[serde(rename_all="camelCase", deny_unknown_fields, default)] with skip_serializing_if where appropriate
Applied to files:
crates/biome_rule_options/src/use_vue_define_macros_order.rs
📚 Learning: 2025-08-05T14:43:29.581Z
Learnt from: dyc3
PR: biomejs/biome#7081
File: packages/@biomejs/biome/configuration_schema.json:7765-7781
Timestamp: 2025-08-05T14:43:29.581Z
Learning: The file `packages/biomejs/biome/configuration_schema.json` is auto-generated and should not be manually edited or reviewed for schema issues; any changes should be made at the code generation source.
Applied to files:
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-custom.options.json
🧬 Code graph analysis (2)
crates/biome_rule_options/src/use_vue_define_macros_order.rs (1)
packages/@biomejs/backend-jsonrpc/src/workspace.ts (1)
UseVueDefineMacrosOrderOptions
(8320-8325)
crates/biome_js_analyze/src/lint/nursery/use_vue_define_macros_order.rs (3)
packages/@biomejs/backend-jsonrpc/src/workspace.ts (4)
FixKind
(7958-7958)RuleDomain
(904-912)TextRange
(9316-9316)UseVueDefineMacrosOrderOptions
(8320-8325)crates/biome_js_factory/src/generated/node_factory.rs (1)
js_module_item_list
(6976-6987)crates/biome_js_syntax/src/generated/nodes.rs (1)
declarators
(6878-6880)
⏰ 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). (13)
- GitHub Check: Documentation
- GitHub Check: Check JS Files
- GitHub Check: Check Dependencies
- GitHub Check: Test (depot-ubuntu-24.04-arm-16)
- GitHub Check: Lint project (depot-ubuntu-24.04-arm-16)
- GitHub Check: Test (depot-windows-2022-16)
- GitHub Check: Test Node.js API
- GitHub Check: Lint project (depot-windows-2022)
- GitHub Check: Bench (biome_configuration)
- GitHub Check: Bench (biome_js_analyze)
- GitHub Check: autofix
- GitHub Check: Bench (biome_js_formatter)
- GitHub Check: Bench (biome_js_parser)
🔇 Additional comments (1)
crates/biome_js_analyze/tests/specs/nursery/useVueDefineMacrosOrder/invalid-c.vue (1)
1-5
: Valid test case for macro order violation.This fixture correctly demonstrates the rule violation:
defineEmits
appears after other code (ref(0)
), which should trigger the linter. The missingref
import is expected behaviour in Vue 3<script setup>
(auto-imported).Minor nitpick: Line 4 could use a space before the comment (
// hello
instead of// hello
), but it doesn't affect test validity.
Summary
Closes #7345
Multi script handling is broken, would need for setup attribute information to land first, but since this is nursery rule for now I left it as is.
Changes from Eslint rule:
defineExposeLast
option.defineModel
while original rule does not.defineModel
was added to the Vue much later than the rule itself, but given how common it is and because it combines functionality ofdefineProps
/defineEmits
seems like a good default to have.I almost wonder if
defineOptions
anddefineSlots
should be included as well.Test Plan
Added snapshots