Skip to content

feat(linter): implement unicorn/prefer-switch#19604

Draft
camc314 wants to merge 1 commit intomainfrom
c/02-10-feat_linter_implement_unicorn_prefer-switch
Draft

feat(linter): implement unicorn/prefer-switch#19604
camc314 wants to merge 1 commit intomainfrom
c/02-10-feat_linter_implement_unicorn_prefer-switch

Conversation

@camc314
Copy link
Contributor

@camc314 camc314 commented Feb 21, 2026

No description provided.

Copy link
Contributor Author

camc314 commented Feb 21, 2026


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • 0-merge - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@github-actions github-actions bot added A-linter Area - Linter C-enhancement Category - New feature or request labels Feb 21, 2026
@codspeed-hq
Copy link

codspeed-hq bot commented Feb 21, 2026

Merging this PR will not alter performance

✅ 47 untouched benchmarks
⏩ 3 skipped benchmarks1


Comparing c/02-10-feat_linter_implement_unicorn_prefer-switch (2b0552c) with main (42f78bb)2

Open in CodSpeed

Footnotes

  1. 3 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.

  2. No successful run was found on graphite-base/19604 (d9461a6) during the generation of this report, so main (42f78bb) was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@camc314 camc314 force-pushed the c/02-10-feat_linter_implement_unicorn_prefer-switch branch from 1d74766 to 8bad22c Compare February 21, 2026 13:53
@camc314 camc314 force-pushed the c/02-10-feat_linter_implement_unicorn_prefer-module branch 2 times, most recently from 57ce894 to a52d51a Compare February 21, 2026 16:29
@camc314 camc314 force-pushed the c/02-10-feat_linter_implement_unicorn_prefer-switch branch from cf6c4ff to 318a547 Compare February 21, 2026 16:29
@camc314 camc314 force-pushed the c/02-10-feat_linter_implement_unicorn_prefer-module branch from a315cd5 to 4350365 Compare February 21, 2026 16:37
@camc314 camc314 force-pushed the c/02-10-feat_linter_implement_unicorn_prefer-switch branch 2 times, most recently from 96a2135 to efd8c0f Compare February 21, 2026 17:30
@camc314 camc314 force-pushed the c/02-10-feat_linter_implement_unicorn_prefer-module branch 2 times, most recently from 52f4221 to 4ff8936 Compare February 21, 2026 21:40
@camc314 camc314 force-pushed the c/02-10-feat_linter_implement_unicorn_prefer-switch branch from efd8c0f to 48ca8ca Compare February 21, 2026 21:40
@camc314 camc314 force-pushed the c/02-10-feat_linter_implement_unicorn_prefer-module branch from 4ff8936 to c9f1e32 Compare February 21, 2026 21:42
@camc314 camc314 force-pushed the c/02-10-feat_linter_implement_unicorn_prefer-switch branch from 48ca8ca to 5f45c07 Compare February 21, 2026 21:42
@camc314 camc314 self-assigned this Feb 21, 2026
@camc314 camc314 force-pushed the c/02-10-feat_linter_implement_unicorn_prefer-switch branch from 5f45c07 to 2b0552c Compare February 21, 2026 21:51
@graphite-app graphite-app bot changed the base branch from c/02-10-feat_linter_implement_unicorn_prefer-module to graphite-base/19604 February 21, 2026 21:56
@camc314 camc314 force-pushed the c/02-10-feat_linter_implement_unicorn_prefer-switch branch from 2b0552c to bd929eb Compare February 21, 2026 22:10
@camc314 camc314 force-pushed the graphite-base/19604 branch from d9461a6 to 46177dd Compare February 21, 2026 22:10
@camc314 camc314 changed the base branch from graphite-base/19604 to main February 21, 2026 22:10
@camc314 camc314 marked this pull request as ready for review February 21, 2026 22:10
Copilot AI review requested due to automatic review settings February 21, 2026 22:10
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Implements the eslint-plugin-unicorn(prefer-switch) lint rule in oxc_linter, adding it to the Unicorn rule set and wiring it into the generated rule registries and snapshots.

Changes:

  • Added new rule implementation PreferSwitch with configuration parsing and AST analysis for if/else-if chains.
  • Registered the rule in rules.rs and the generated rules_enum.rs / rule_runner_impls.rs.
  • Added snapshot coverage for rule diagnostics.

Reviewed changes

Copilot reviewed 3 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
crates/oxc_linter/src/rules/unicorn/prefer_switch.rs New rule implementation + unit tests and snapshot generation.
crates/oxc_linter/src/rules.rs Exposes the new Unicorn rule module.
crates/oxc_linter/src/generated/rules_enum.rs Adds the rule to the generated enum/registry plumbing.
crates/oxc_linter/src/generated/rule_runner_impls.rs Registers the rule runner for IfStatement nodes.
crates/oxc_linter/src/snapshots/unicorn_prefer_switch.snap New snapshot output for failing test cases.

Comment on lines +24 to +47
#[derive(Debug, Clone, Copy, Default, Deserialize, JsonSchema)]
#[serde(rename_all = "kebab-case")]
pub enum EmptyDefaultCase {
/// Require a comment in the default case to explain why it's empty.
#[default]
NoDefaultComment,
/// Allow an empty default case.
DoNothingComment,
/// Disallow a default case.
NoDefaultCase,
}

#[derive(Debug, Clone, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
pub struct PreferSwitchConfig {
/// The minimum number of cases required to trigger the rule.
minimum_cases: usize,
/// How to handle an empty default case.
empty_default_case: EmptyDefaultCase,
}

impl Default for PreferSwitchConfig {
fn default() -> Self {
Self { minimum_cases: 3, empty_default_case: EmptyDefaultCase::NoDefaultComment }
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

PreferSwitchConfig defines empty_default_case (and EmptyDefaultCase) but the rule never reads it, so user configuration has no effect and the option-specific tests don’t actually validate behavior. Either implement the intended behavior gated on self.0.empty_default_case or remove this config field/enum until it’s supported to avoid a misleading public config surface.

Suggested change
#[derive(Debug, Clone, Copy, Default, Deserialize, JsonSchema)]
#[serde(rename_all = "kebab-case")]
pub enum EmptyDefaultCase {
/// Require a comment in the default case to explain why it's empty.
#[default]
NoDefaultComment,
/// Allow an empty default case.
DoNothingComment,
/// Disallow a default case.
NoDefaultCase,
}
#[derive(Debug, Clone, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
pub struct PreferSwitchConfig {
/// The minimum number of cases required to trigger the rule.
minimum_cases: usize,
/// How to handle an empty default case.
empty_default_case: EmptyDefaultCase,
}
impl Default for PreferSwitchConfig {
fn default() -> Self {
Self { minimum_cases: 3, empty_default_case: EmptyDefaultCase::NoDefaultComment }
#[derive(Debug, Clone, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
pub struct PreferSwitchConfig {
/// The minimum number of cases required to trigger the rule.
minimum_cases: usize,
}
impl Default for PreferSwitchConfig {
fn default() -> Self {
Self { minimum_cases: 3 }

Copilot uses AI. Check for mistakes.
Comment on lines +467 to +472
("if (foo === 1) {}", None),
(
"if (foo === 1) {}
else if (foo === 2) {}
else if (foo === 3) {}
else if (foo === 4) {}
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

This test case is in the fail list, but with the default minimum_cases of 3 a single if (foo === 1) {} should not trigger the rule (the rule only warns once the chain length reaches minimum_cases). This will cause the test to expect a diagnostic that the current implementation will never emit; move this case to pass or provide a config that lowers minimumCases if you intend it to fail.

Suggested change
("if (foo === 1) {}", None),
(
"if (foo === 1) {}
else if (foo === 2) {}
else if (foo === 3) {}
else if (foo === 4) {}
(
"if (foo === 1) {}
else if (foo === 2) {}
else if (foo === 3) {}",
None,
),

Copilot uses AI. Check for mistakes.
@camc314 camc314 marked this pull request as draft February 21, 2026 22:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-linter Area - Linter C-enhancement Category - New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants