Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@matanshavit
Copy link
Contributor

@matanshavit matanshavit commented Oct 30, 2025

Notice of AI/LLM Use

The code and natural language in this PR was written primarily with Claude Code, including researching the codebase, planning the changes, writing the code, and creating the pull request.

As the human creating this pull request, I take full responsibility for its contents.

See CONTRIBUTING.md#ai-assistance-notice for more information

Summary

Implements a new lint rule noParametersOnlyUsedInRecursion that detects function parameters exclusively used in recursive calls. These parameters are effectively unused and can be removed to simplify function signatures.

Implementation: The rule is inspired by Rust Clippy's only_used_in_recursion lint and adapted for TypeScript. It analyzes function parameters using Biome's semantic model and AST traversal to:

  1. Track all references to each parameter
  2. Identify recursive calls within the function body
  3. Classify whether parameters are used exclusively in recursion
  4. Trace parameters through safe operations (arithmetic, unary operations, field access)

Example:

// Invalid - 'acc' is only used in recursion
function factorial(n, acc) {
    if (n === 0) return 1;
    return factorial(n - 1, acc);  // ❌ acc only appears here
}

// Valid - 'acc' is used in return statement
function factorial(n, acc) {
    if (n === 0) return acc;  // ✅ acc used outside recursion
    return factorial(n - 1, acc * n);
}

Handles:

  • direct recursion (function calling itself)
  • arithmetic operations (e.g., n - 1, acc * n)
  • functions, arrow functions, class methods, object methods
  • method calls with this.method() syntax

Does not handle:

  • indirect recursion (functions calls another function which calls first function)

Actions provided:

  • unsafe code action to prefix parameter with underscore if intentional

Fixes: #6484

Changeset: A changeset has been created documenting this as a minor change with the new rule addition.

Test Plan

Automated Tests

crates/biome_js_analyze/tests/specs/nursery/noParametersOnlyUsedInRecursion/:

Invalid cases (should trigger diagnostics):

  • Simple parameter only in recursion: factorial(n, acc) where acc is unused
  • Multiple parameters: fn(a, b, c) with b and c only in recursion
  • Arithmetic operations: countdown(n - step, step)
  • Unary operations: negate(n - 1, !flag)
  • Method calls: this.count(n - 1, acc) in class methods
  • Arrow functions and object methods

Valid cases (should NOT trigger):

  • Parameters used in return values
  • Parameters used in conditions
  • Parameters used in non-recursive function calls
  • Parameters with underscore prefix (intentionally unused)

Fix tests:

  • Code action adds underscore prefix ("unsafe" fix)
  • All references renamed

Docs

  • Explanation of the rule
  • Valid examples and invalid examples
  • Reference to the Clippy source in sources metadata

The rule is in the nursery group and will appear in generated documentation with the next release.

Add initial scaffolding for the noParametersOnlyUsedInRecursion nursery rule.
This includes the rule structure, options, configuration integration, and test
directory setup.
Implement the core detection logic for the noParametersOnlyUsedInRecursion
rule. The rule now detects parameters that are only used in recursive calls
and have no other usage in the function body.

Key features:
- Skips parameters starting with underscore (intentionally unused)
- Skips TypeScript signatures
- Detects recursive calls in named functions, arrow functions, and methods
- Only reports when ALL parameter references are in recursive calls
- Adds comprehensive test cases for valid and invalid scenarios
…tic operations

Improve the noParametersOnlyUsedInRecursion rule to trace parameters through
safe operations including binary arithmetic, unary operations, parenthesized
expressions, and static member access. This prevents false positives when
parameters are used in expressions like `n - 1`, `!flag`, or `b * 2 + 1`
within recursive calls.

The rule now correctly identifies:
- Parameters used in arithmetic expressions (a + 1, n - step)
- Parameters in unary operations (!flag, -n)
- Parameters accessed through field access (obj.field)
- Parameters in parenthesized expressions

Updated tests include new invalid cases that should trigger the rule and
valid cases that should not.
Enhanced noParametersOnlyUsedInRecursion rule with automatic fix capability
that removes unused recursive parameters. Added Clippy attribution and
improved documentation with additional examples for object methods.
Replace .map().unwrap_or(false) patterns with is_some_and() to address
clippy::map_unwrap_or lints. Also convert one if-let pattern to use
let-chains for improved readability and to satisfy clippy suggestions.
Add changeset documenting the new noParametersOnlyUsedInRecursion
lint rule that detects function parameters exclusively used in
recursive calls.
@changeset-bot
Copy link

changeset-bot bot commented Oct 30, 2025

🦋 Changeset detected

Latest commit: 7beb492

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 L-JavaScript Language: JavaScript and super languages A-Diagnostic Area: diagnostocis labels Oct 30, 2025
@codspeed-hq
Copy link

codspeed-hq bot commented Oct 30, 2025

CodSpeed Performance Report

Merging #7926 will not alter performance

Comparing matanshavit:feat/no-parameters-only-used-in-recursion (7beb492) with main (7165d06)1

Summary

✅ 53 untouched
⏩ 85 skipped2

Footnotes

  1. No successful run was found on main (e27892b) during the generation of this report, so 7165d06 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

  2. 85 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.

Copy link
Contributor Author

@matanshavit matanshavit Oct 30, 2025

Choose a reason for hiding this comment

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

The new rule creates changes down the array because the linter rules should stay alphabatized/ordered

@matanshavit
Copy link
Contributor Author

matanshavit commented Oct 30, 2025

I believe the slowdown in these cases could be the result of needed to walk the AST to determine if recursion is present. I can try to come up with a test to prove that.

Since this appears to be the first rule to detect recursion, is there a need to disclose that these types of rules can be inherently slower?

For reference, here is the source of the algorithm used by rust-clippy -
only_used_in_recursion.rs#L302

@matanshavit matanshavit marked this pull request as ready for review October 30, 2025 18:05
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 30, 2025

Walkthrough

Adds a new JavaScript lint rule noParametersOnlyUsedInRecursion in crates/biome_js_analyze. The rule detects function parameters referenced only inside recursive calls, emits a warning, and provides an unsafe fix that prefixes the parameter with an underscore and renames occurrences. Implements helpers for identifying functions and tracing references, adds tests (invalid, invalidWithFix, valid), a changeset, a NoParametersOnlyUsedInRecursionOptions type, and exports the rule options module. References issue #6484.

Suggested reviewers

  • dyc3
  • ematipico
  • arendjr

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title Check ✅ Passed The title "feat(lint): new rule: no parameters only used in recursion" accurately and concisely summarises the primary change in the pull request. It follows conventional commit formatting with the "feat(lint)" prefix, clearly identifies that a new lint rule is being added, and specifically describes what the rule does. The title is specific enough that a teammate scanning the repository history would immediately understand this PR introduces a new linter rule for detecting parameters used only in recursive calls.
Linked Issues Check ✅ Passed The code changes successfully address the primary objectives from issue #6484. The implementation adds a new lint rule NoParametersOnlyUsedInRecursion that ports the Clippy only_used_in_recursion lint to Biome's JavaScript analyser, detects function parameters used exclusively in recursive calls, and emits diagnostics to report them as effectively unused. The rule handles direct recursion across various function forms (functions, arrow functions, class methods, object methods) and traces parameters through safe operations like arithmetic and unary operations. An options structure has been created to support potential future configuration. The core requirement of detecting and reporting parameters only used in recursion is fully met.
Out of Scope Changes Check ✅ Passed All changes in this pull request are directly scoped to implementing the new lint rule. The additions include the core rule implementation in the nursery group, a dedicated options struct, comprehensive test cases covering invalid, valid, and fix scenarios, the module export registration, and the changeset documentation. No unrelated changes such as bug fixes, refactoring of other rules, or modifications to unrelated features are present in the changeset.
Description Check ✅ Passed The pull request description is detailed and directly related to the code changes. It explains the implementation strategy, provides concrete examples of invalid and valid code, documents what the rule handles and doesn't handle, outlines the test plan with specific test directories and cases, and includes an AI/LLM use notice as required. The description clearly connects the implementation to the Clippy source lint and references issue #6484, making it straightforward to understand the changeset's intent and scope.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent 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 213c001 and 7beb492.

📒 Files selected for processing (1)
  • .changeset/no-parameters-only-used-in-recursion.md (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .changeset/no-parameters-only-used-in-recursion.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). (15)
  • GitHub Check: Test (depot-ubuntu-24.04-arm-16)
  • GitHub Check: Documentation
  • GitHub Check: End-to-end tests
  • GitHub Check: Check Dependencies
  • GitHub Check: Test (depot-windows-2022-16)
  • GitHub Check: Lint project (depot-windows-2022)
  • GitHub Check: Lint project (depot-ubuntu-24.04-arm-16)
  • GitHub Check: Bench (biome_js_analyze)
  • GitHub Check: Bench (biome_js_parser)
  • GitHub Check: Bench (biome_js_formatter)
  • GitHub Check: lint
  • GitHub Check: autofix
  • GitHub Check: Check JS Files
  • GitHub Check: Bench (biome_configuration)
  • GitHub Check: Test Node.js API

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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: 1

📜 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 e27892b and 5192632.

⛔ Files ignored due to path filters (8)
  • 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/noParametersOnlyUsedInRecursion/invalid.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noParametersOnlyUsedInRecursion/invalidWithFix.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noParametersOnlyUsedInRecursion/valid.js.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 (7)
  • .changeset/no-parameters-only-used-in-recursion.md (1 hunks)
  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noParametersOnlyUsedInRecursion/invalid.js (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noParametersOnlyUsedInRecursion/invalidWithFix.js (1 hunks)
  • crates/biome_js_analyze/tests/specs/nursery/noParametersOnlyUsedInRecursion/valid.js (1 hunks)
  • crates/biome_rule_options/src/lib.rs (1 hunks)
  • crates/biome_rule_options/src/no_parameters_only_used_in_recursion.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{rs,toml}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Format Rust and TOML files before committing (e.g., via just f)

Files:

  • crates/biome_rule_options/src/lib.rs
  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
  • crates/biome_rule_options/src/no_parameters_only_used_in_recursion.rs
**/*.rs

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Document rules, assists, and their options with inline rustdoc in the Rust source

Files:

  • crates/biome_rule_options/src/lib.rs
  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
  • crates/biome_rule_options/src/no_parameters_only_used_in_recursion.rs
.changeset/*.md

📄 CodeRabbit inference engine (CONTRIBUTING.md)

.changeset/*.md: In changeset files, only use #### or ##### headers
Changesets should describe user-facing changes; internal-only changes do not need changesets
Use past tense for what you did in the changeset description and present tense for current behavior
For bug fixes, start the changeset description with a link to the issue (e.g., Fixed #1234: ...)
When referencing a rule or assist in a changeset, include a link to the rule/assist page on the website
Include a code block in the changeset when applicable to illustrate the change
End every sentence in a changeset with a full stop (.)

Files:

  • .changeset/no-parameters-only-used-in-recursion.md
🧠 Learnings (22)
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/biome_rule_options/lib/**/*.rs : Place per-rule options types in biome_rule_options crate under lib/, one file per rule

Applied to files:

  • crates/biome_rule_options/src/lib.rs
  • crates/biome_rule_options/src/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-15T09:23:33.055Z
Learnt from: CR
PR: biomejs/biome#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
PR: biomejs/biome#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,local_inference,resolver,flattening}.rs : Avoid recursive type structures and cross-module Arcs; represent links between types using TypeReference and TypeData::Reference.

Applied to files:

  • crates/biome_rule_options/src/lib.rs
  • crates/biome_rule_options/src/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/biome_rule_options/lib/**/*.rs : Derive Serialize, Deserialize, and Deserializable for rule options; add #[serde(rename_all = "camelCase", deny_unknown_fields, default)]

Applied to files:

  • crates/biome_rule_options/src/lib.rs
  • crates/biome_rule_options/src/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/lint/nursery/**/*.rs : Place all new rules in the nursery group

Applied to files:

  • crates/biome_rule_options/src/lib.rs
  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/biome_rule_options/lib/**/*.rs : When schema feature is enabled, derive schemars::JsonSchema for options and related enums

Applied to files:

  • crates/biome_rule_options/src/lib.rs
  • crates/biome_rule_options/src/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/biome_rule_options/lib/**/*.rs : Prefer Box<[Box<str>]> over Vec<String> for options string lists to reduce memory usage

Applied to files:

  • crates/biome_rule_options/src/lib.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Use options/full_options/use_options code block modifiers as specified to demonstrate configuration in docs; keep modifier order consistent

Applied to files:

  • crates/biome_rule_options/src/lib.rs
  • crates/biome_rule_options/src/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-15T09:23:33.055Z
Learnt from: CR
PR: biomejs/biome#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/js_module_info/scoped_resolver.rs : Do not cache results of full inference; module replacements would stale such caches.

Applied to files:

  • crates/biome_rule_options/src/lib.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : In declare_lint_rule! macros, set version: "next"

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Rule names should use no<Concept> when forbidding a single concept (e.g., noDebugger)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Rule documentation: first paragraph must be a single line summary

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Use rule_category! macro to reference the diagnostic category created by declare_lint_rule!

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : When banning globals (e.g., console), check semantic model to avoid flagging locally shadowed variables

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Set the language field in declare_lint_rule! to the most appropriate dialect (js/jsx/ts/tsx)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Provide informative diagnostics: explain what the error is, why it triggers, and what to do (prefer a code action or a note)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Rule names should use use<Concept> when mandating a single concept (e.g., useValidLang)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : If a rule provides a code action, add fix_kind to declare_lint_rule! (FixKind::Safe or ::Unsafe)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/tests/specs/**/{invalid*,valid*}.* : Name snapshot test files with invalid* and valid* prefixes to indicate reported vs non-reported cases

Applied to files:

  • crates/biome_js_analyze/tests/specs/nursery/noParametersOnlyUsedInRecursion/valid.js
  • crates/biome_js_analyze/tests/specs/nursery/noParametersOnlyUsedInRecursion/invalid.js
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Set associated type Options of the rule to the concrete options type from biome_rule_options when options exist; otherwise use ()

Applied to files:

  • crates/biome_rule_options/src/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/tests/specs/**/*.jsonc : .jsonc snapshot test files must contain an array of code strings and are interpreted as script (no ESM import/export)

Applied to files:

  • crates/biome_js_analyze/tests/specs/nursery/noParametersOnlyUsedInRecursion/invalid.js
  • crates/biome_js_analyze/tests/specs/nursery/noParametersOnlyUsedInRecursion/invalidWithFix.js
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Documentation must include a ## Examples section with ### Invalid before ### Valid

Applied to files:

  • crates/biome_js_analyze/tests/specs/nursery/noParametersOnlyUsedInRecursion/invalid.js
🧬 Code graph analysis (2)
crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs (2)
crates/biome_js_analyze/tests/specs/nursery/noParametersOnlyUsedInRecursion/invalid.js (1)
  • obj (46-51)
crates/biome_rowan/src/ast/mod.rs (1)
  • cast_ref (142-151)
crates/biome_rule_options/src/no_parameters_only_used_in_recursion.rs (1)
packages/@biomejs/backend-jsonrpc/src/workspace.ts (1)
  • NoParametersOnlyUsedInRecursionOptions (8306-8306)

parent_function: &AnyJsParameterParentFunction,
) -> bool {
// Check if this node matches our parent function by comparing text ranges
node.text_trimmed_range() == parent_function.syntax().text_trimmed_range()
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: pretty sure you could just compare the syntax nodes directly?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, true

…sion

Add name extraction for arrow functions to support recursive calls.
The rule now detects named arrow functions (e.g., `const foo = () => ...`)
and properly analyzes their parameters for recursive-only usage.
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

🧹 Nitpick comments (3)
crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs (3)

204-235: Replace .to_string() with TokenText for better performance.

Heap allocations on lines 211, 216, 222, and 228 can be avoided by returning TokenText instead of String. This function should return Option<TokenText> (or similar) to eliminate unnecessary allocations during analysis.

Apply this pattern:

-fn get_function_name(parent_function: &AnyJsParameterParentFunction) -> Option<String> {
+fn get_function_name(parent_function: &AnyJsParameterParentFunction) -> Option<biome_rowan::TokenText> {
     match parent_function {
         AnyJsParameterParentFunction::JsFunctionDeclaration(decl) => decl
             .id()
             .ok()
             .and_then(|any_binding| any_binding.as_js_identifier_binding().cloned())
-            .and_then(|id| id.name_token().ok())
-            .map(|t| t.text_trimmed().to_string()),
+            .and_then(|id| id.name_token().ok().map(|t| t.text_trimmed())),

Note: Update call sites accordingly to work with TokenText instead of &str.


237-275: Arrow function name extraction looks good.

This properly walks the AST to find the binding name for recursive arrow detection. The .to_string() allocation on line 264 should be addressed when refactoring get_function_name to return TokenText.


381-387: Consider comparing syntax nodes directly.

Instead of comparing text ranges, you could compare the nodes themselves for cleaner code:

 fn is_function_boundary(
     node: &biome_rowan::SyntaxNode<biome_js_syntax::JsLanguage>,
     parent_function: &AnyJsParameterParentFunction,
 ) -> bool {
-    // Check if this node matches our parent function by comparing text ranges
-    node.text_trimmed_range() == parent_function.syntax().text_trimmed_range()
+    node == parent_function.syntax()
 }
📜 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 5192632 and 9bfd4e7.

⛔ Files ignored due to path filters (1)
  • crates/biome_js_analyze/tests/specs/nursery/noParametersOnlyUsedInRecursion/invalid.js.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (1)
  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{rs,toml}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Format Rust and TOML files before committing (e.g., via just f)

Files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
**/*.rs

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Document rules, assists, and their options with inline rustdoc in the Rust source

Files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : When banning globals (e.g., console), check semantic model to avoid flagging locally shadowed variables
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Set associated type Options of the rule to the concrete options type from biome_rule_options when options exist; otherwise use ()
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Rule names should use no<Concept> when forbidding a single concept (e.g., noDebugger)
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : If a rule provides a code action, add fix_kind to declare_lint_rule! (FixKind::Safe or ::Unsafe)
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/biome_rule_options/lib/**/*.rs : Place per-rule options types in biome_rule_options crate under lib/, one file per rule
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Rule documentation: first paragraph must be a single line summary
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Set the language field in declare_lint_rule! to the most appropriate dialect (js/jsx/ts/tsx)
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/lint/nursery/**/*.rs : Place all new rules in the nursery group
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : In declare_lint_rule! macros, set version: "next"
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Use rule_category! macro to reference the diagnostic category created by declare_lint_rule!
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/lint/nursery/**/*.rs : Place all new rules in the nursery group

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : In declare_lint_rule! macros, set version: "next"

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : When banning globals (e.g., console), check semantic model to avoid flagging locally shadowed variables

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Use rule_category! macro to reference the diagnostic category created by declare_lint_rule!

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Rule documentation: first paragraph must be a single line summary

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Set the language field in declare_lint_rule! to the most appropriate dialect (js/jsx/ts/tsx)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Rule names should use no<Concept> when forbidding a single concept (e.g., noDebugger)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Provide informative diagnostics: explain what the error is, why it triggers, and what to do (prefer a code action or a note)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : When using semantic/control-flow services with Ast queries, ensure the rule runs in a phase where the services exist (e.g., use Semantic<> or custom visitor in proper phase)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/complexity/**/*.rs : Rules in complexity group must have severity: warn or info (prefer info if unsure)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-09-12T08:06:16.650Z
Learnt from: ematipico
PR: biomejs/biome#7410
File: crates/biome_js_analyze/src/lint/nursery/no_jsx_props_bind.rs:103-149
Timestamp: 2025-09-12T08:06:16.650Z
Learning: In Biome AST traversal, `ancestors().skip(1)` is a reasonable pattern to skip the current node and prevent false positives when searching for ancestor nodes of the same kind.

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
🧬 Code graph analysis (1)
crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs (3)
packages/@biomejs/backend-jsonrpc/src/workspace.ts (2)
  • FixKind (8002-8002)
  • Severity (9355-9355)
crates/biome_rowan/src/ast/mod.rs (1)
  • cast_ref (142-151)
crates/biome_js_analyze/tests/specs/nursery/noParametersOnlyUsedInRecursion/invalid.js (1)
  • obj (46-51)
⏰ 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: Check JS Files
  • GitHub Check: Test (depot-ubuntu-24.04-arm-16)
  • GitHub Check: Test (depot-windows-2022-16)
  • GitHub Check: Lint project (depot-ubuntu-24.04-arm-16)
  • GitHub Check: Check Dependencies
  • GitHub Check: Lint project (depot-windows-2022)
  • GitHub Check: Documentation
  • GitHub Check: Bench (biome_configuration)
  • GitHub Check: autofix
  • GitHub Check: Bench (biome_js_formatter)
  • GitHub Check: Bench (biome_js_analyze)
  • GitHub Check: Bench (biome_js_parser)
  • GitHub Check: Test Node.js API
🔇 Additional comments (9)
crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs (9)

1-13: LGTM!

The imports are appropriate for this rule implementation.


14-81: LGTM!

Rule declaration follows conventions: version "next", appropriate severity, unsafe fix kind, and clear documentation with examples.


83-189: LGTM!

The rule implementation correctly identifies parameters used only in recursion, provides clear diagnostics, and offers an appropriate unsafe fix.


191-202: LGTM!

Correctly extracts the parent function from formal and rest parameters.


277-290: LGTM!

Clean helper function for identifying function boundaries.


292-308: LGTM!

Appropriately skips TypeScript signature types, consistent with existing rules.


310-349: LGTM!

Correctly detects recursive calls including this.method() patterns, and properly uses .omit_parentheses() to handle wrapped expressions.


351-379: LGTM!

Properly uses an iterative approach to walk the AST, avoiding stack overflow concerns.


434-467: Logic is sound, depends on traces_to_parameter fix.

This function correctly identifies recursive calls that use the parameter. Once the unbounded recursion in traces_to_parameter is addressed, this will be robust. The conservative handling of spread arguments is appropriate.

- Use TokenText instead of String for function names to reduce allocations
- Replace text range comparison with direct node comparison in is_function_boundary
- Convert traces_to_parameter from recursive to iterative worklist approach to prevent stack overflow
@matanshavit matanshavit requested a review from dyc3 October 30, 2025 19:14
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

🧹 Nitpick comments (2)
crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs (2)

389-445: Consider tracing through logical and conditional operators.

Whilst the iterative worklist approach nicely addresses stack overflow concerns, traces_to_parameter currently doesn't trace through logical operators (&&, ||, ??) or conditional expressions (?:). This makes the rule more conservative but may miss legitimate recursive-only usage patterns.

Example additions to the worklist loop:

// Logical expressions: a && b, a || b, a ?? b
if let Some(logical) = current_expr.as_js_logical_expression() {
    if let Ok(left) = logical.left() {
        to_check.push(left);
    }
    if let Ok(right) = logical.right() {
        to_check.push(right);
    }
    continue;
}

// Conditional expressions: cond ? a : b
if let Some(cond) = current_expr.as_js_conditional_expression() {
    if let Ok(cons) = cond.consequent() {
        to_check.push(cons);
    }
    if let Ok(alt) = cond.alternate() {
        to_check.push(alt);
    }
    continue;
}

310-349: Optionally handle computed members and optional chaining in recursive calls.

is_recursive_call currently recognises foo() and this.foo() but not this?.foo() (optional chaining) or this[name]() (computed member). Whilst less common, these patterns do represent valid recursion.

To handle optional chaining:

// After checking JsStaticMemberExpression, add:
if let Some(member) = expr.as_js_computed_member_expression() {
    let is_this_call = member
        .object()
        .ok()
        .is_some_and(|obj| obj.as_js_this_expression().is_some());
    
    if is_this_call {
        // For computed members, we'd need to evaluate if the computed
        // expression resolves to the function name (complex)
        // Conservative: skip for now or handle string literals only
    }
}

For optional chaining, you'd need to unwrap the optional chain before checking the member expression.

📜 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 9bfd4e7 and 1f72617.

📒 Files selected for processing (1)
  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{rs,toml}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Format Rust and TOML files before committing (e.g., via just f)

Files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
**/*.rs

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Document rules, assists, and their options with inline rustdoc in the Rust source

Files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : When banning globals (e.g., console), check semantic model to avoid flagging locally shadowed variables
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Set associated type Options of the rule to the concrete options type from biome_rule_options when options exist; otherwise use ()
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Rule names should use no<Concept> when forbidding a single concept (e.g., noDebugger)
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : If a rule provides a code action, add fix_kind to declare_lint_rule! (FixKind::Safe or ::Unsafe)
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/biome_rule_options/lib/**/*.rs : Place per-rule options types in biome_rule_options crate under lib/, one file per rule
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Set the language field in declare_lint_rule! to the most appropriate dialect (js/jsx/ts/tsx)
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : In declare_lint_rule! macros, set version: "next"
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/lint/nursery/**/*.rs : Place all new rules in the nursery group
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Rule documentation: first paragraph must be a single line summary
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Use rule_category! macro to reference the diagnostic category created by declare_lint_rule!
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/lint/nursery/**/*.rs : Place all new rules in the nursery group

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : In declare_lint_rule! macros, set version: "next"

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : When banning globals (e.g., console), check semantic model to avoid flagging locally shadowed variables

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Rule documentation: first paragraph must be a single line summary

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Use rule_category! macro to reference the diagnostic category created by declare_lint_rule!

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Set the language field in declare_lint_rule! to the most appropriate dialect (js/jsx/ts/tsx)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Rule names should use no<Concept> when forbidding a single concept (e.g., noDebugger)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Provide informative diagnostics: explain what the error is, why it triggers, and what to do (prefer a code action or a note)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/complexity/**/*.rs : Rules in complexity group must have severity: warn or info (prefer info if unsure)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : When using semantic/control-flow services with Ast queries, ensure the rule runs in a phase where the services exist (e.g., use Semantic<> or custom visitor in proper phase)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-09-12T08:06:16.650Z
Learnt from: ematipico
PR: biomejs/biome#7410
File: crates/biome_js_analyze/src/lint/nursery/no_jsx_props_bind.rs:103-149
Timestamp: 2025-09-12T08:06:16.650Z
Learning: In Biome AST traversal, `ancestors().skip(1)` is a reasonable pattern to skip the current node and prevent false positives when searching for ancestor nodes of the same kind.

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
🧬 Code graph analysis (1)
crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs (2)
crates/biome_rowan/src/ast/mod.rs (1)
  • cast_ref (142-151)
crates/biome_js_analyze/tests/specs/nursery/noParametersOnlyUsedInRecursion/invalid.js (1)
  • obj (46-51)
⏰ 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-ubuntu-24.04-arm-16)
  • GitHub Check: Lint project (depot-windows-2022)
  • GitHub Check: Test (depot-windows-2022-16)
  • GitHub Check: Lint project (depot-ubuntu-24.04-arm-16)
  • GitHub Check: Documentation
  • GitHub Check: Check Dependencies
  • GitHub Check: End-to-end tests
  • GitHub Check: Check JS Files
  • GitHub Check: autofix
  • GitHub Check: Bench (biome_configuration)
  • GitHub Check: Bench (biome_js_parser)
  • GitHub Check: Test Node.js API
  • GitHub Check: Bench (biome_js_analyze)
  • GitHub Check: Bench (biome_js_formatter)
🔇 Additional comments (2)
crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs (2)

14-81: LGTM!

Rule declaration follows all conventions: proper metadata, clear documentation with examples, and appropriate severity/fix kind.


83-189: LGTM!

The rule implementation correctly leverages the semantic model to classify parameter references and only triggers when all references occur within recursive calls. The unsafe fix appropriately prefixes the parameter with an underscore.

…ecursion

Add support for detecting recursive arrow functions defined via
assignment expressions (e.g., foo = (n) => ...). The rule now
extracts the function name from the left-hand side of assignment
expressions to properly track recursive calls.
@matanshavit
Copy link
Contributor Author

matanshavit commented Oct 30, 2025

I think these comments are worth addressing as well

crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs (2)
389-445: Consider tracing through logical and conditional operators.
Whilst the iterative worklist approach nicely addresses stack overflow concerns, traces_to_parameter currently doesn't trace through logical operators (&&, ||, ??) or conditional expressions (?:). This makes the rule more conservative but may miss legitimate recursive-only usage patterns.

310-349: Optionally handle computed members and optional chaining in recursive calls.
is_recursive_call currently recognises foo() and this.foo() but not this?.foo() (optional chaining) or this[name]() (computed member). Whilst less common, these patterns do represent valid recursion.
For optional chaining, you'd need to unwrap the optional chain before checking the member expression.

Add support for logical AND (&&), OR (||), and nullish coalescing (??)
operators when detecting parameters only used in recursive calls. The
rule now correctly identifies parameters that flow through logical
operations but are never used meaningfully in the function body.
…Recursion

Add support for detecting parameters used only in recursion when they appear
in conditional expressions (ternary operator: cond ? a : b). The rule now
checks all three parts: test, consequent, and alternate.

Added test cases for:
- Parameter in consequent position
- Parameter in alternate position
- Parameter in test condition
- Nested conditional expressions
…etersOnlyUsedInRecursion

Add support for detecting recursive calls through:
- Optional chaining (this?.method())
- Computed member expressions (this["method"])
- Combined optional chaining with computed members (this?.["method"])

The implementation handles string literal property access conservatively,
only matching when the computed member is a string literal that matches
the function name.
…in noParametersOnlyUsedInRecursion

Add documentation examples demonstrating the rule catching parameters
only used in recursion with logical operators and optional chaining.
Replace nested if-let statements with let-chain pattern for better
readability in computed member name checking.
@matanshavit
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 30, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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: 0

🧹 Nitpick comments (1)
crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs (1)

512-516: Minor: Consider adding explicit continue for consistency.

The static member access branch doesn't have an explicit continue statement unlike the other branches (lines 471, 483, 498, 507). Whilst functionally correct, adding one would match the established pattern.

 if let Some(member_expr) = current_expr.as_js_static_member_expression()
     && let Ok(obj) = member_expr.object()
 {
     to_check.push(obj);
+    continue;
 }
📜 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 2eef0e6 and 213c001.

📒 Files selected for processing (1)
  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{rs,toml}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Format Rust and TOML files before committing (e.g., via just f)

Files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
**/*.rs

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Document rules, assists, and their options with inline rustdoc in the Rust source

Files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : When banning globals (e.g., console), check semantic model to avoid flagging locally shadowed variables
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Rule names should use no<Concept> when forbidding a single concept (e.g., noDebugger)
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : If a rule provides a code action, add fix_kind to declare_lint_rule! (FixKind::Safe or ::Unsafe)
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/lint/nursery/**/*.rs : Place all new rules in the nursery group
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Set associated type Options of the rule to the concrete options type from biome_rule_options when options exist; otherwise use ()
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : In declare_lint_rule! macros, set version: "next"
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/complexity/**/*.rs : Rules in complexity group must have severity: warn or info (prefer info if unsure)
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/biome_rule_options/lib/**/*.rs : Place per-rule options types in biome_rule_options crate under lib/, one file per rule
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Rule documentation: first paragraph must be a single line summary
Learnt from: CR
PR: biomejs/biome#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,local_inference,resolver,flattening}.rs : Avoid recursive type structures and cross-module Arcs; represent links between types using TypeReference and TypeData::Reference.
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/lint/nursery/**/*.rs : Place all new rules in the nursery group

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : In declare_lint_rule! macros, set version: "next"

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Rule documentation: first paragraph must be a single line summary

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : When banning globals (e.g., console), check semantic model to avoid flagging locally shadowed variables

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Set the language field in declare_lint_rule! to the most appropriate dialect (js/jsx/ts/tsx)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Rule names should use no<Concept> when forbidding a single concept (e.g., noDebugger)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Use rule_category! macro to reference the diagnostic category created by declare_lint_rule!

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Provide informative diagnostics: explain what the error is, why it triggers, and what to do (prefer a code action or a note)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/complexity/**/*.rs : Rules in complexity group must have severity: warn or info (prefer info if unsure)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : When using semantic/control-flow services with Ast queries, ensure the rule runs in a phase where the services exist (e.g., use Semantic<> or custom visitor in proper phase)

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
📚 Learning: 2025-09-12T08:06:16.650Z
Learnt from: ematipico
PR: biomejs/biome#7410
File: crates/biome_js_analyze/src/lint/nursery/no_jsx_props_bind.rs:103-149
Timestamp: 2025-09-12T08:06:16.650Z
Learning: In Biome AST traversal, `ancestors().skip(1)` is a reasonable pattern to skip the current node and prevent false positives when searching for ancestor nodes of the same kind.

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs
🔇 Additional comments (6)
crates/biome_js_analyze/src/lint/nursery/no_parameters_only_used_in_recursion.rs (6)

14-97: Solid rule declaration and documentation.

The metadata follows Biome conventions correctly, and the documentation provides clear examples. Well done on the thorough examples covering various recursion patterns.


99-205: Core rule logic is well-structured.

The classification approach (counting recursive vs non-recursive references) is correct, and the delegation to noUnusedFunctionParameters for truly unused parameters is sensible. The action implementation properly uses the mutation API.


207-336: Helper functions handle function identification correctly.

The arrow function name extraction now properly handles both variable declarators and assignment expressions with appropriate boundary checking. Good work addressing the previous feedback.


474-499: Excellent expansion of tracing coverage.

Adding logical operators and conditional expressions addresses the feedback from the PR objectives perfectly. This catches more legitimate recursive-only usage patterns.


441-559: Parameter tracing implementation is robust.

The iterative worklist approach avoids recursion depth issues, and the comprehensive handling of expression types ensures accurate detection. Good work on the previous refactoring.


338-401: Original review comment is incorrect.

The optional chaining detection is already working correctly. The test fixtures confirm that this?.count() and this?.["count"]() are both being detected and flagged as expected. The snapshot output shows diagnostics firing for all three optional chaining test cases (lines 699–713, 730–744, and 792–806). The implementation's as_js_static_member_expression() and as_js_computed_member_expression() methods properly capture optional chains as written in the comments—no special unwrapping required.

Copy link
Contributor

@dyc3 dyc3 left a comment

Choose a reason for hiding this comment

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

Great work! just a couple more housekeeping things

@dyc3 dyc3 merged commit 69cecec into biomejs:main Oct 31, 2025
20 checks passed
@github-actions github-actions bot mentioned this pull request Oct 30, 2025
Copy link
Member

@ematipico ematipico left a comment

Choose a reason for hiding this comment

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

Hey @matanshavit

Thank you for implementing this rule. It's a pity that the PR was merged, could you make another one and address my comments?

The problem with this AI thing is that it doesn't fully understand the code base.

Our CST is particular and it contains lot of Result<> the APIs. That's because our parser is recoverable, so some nodes might be buggy while some others don't. As a result, when writing linting rules, it's totally fine writing things like ok()?, and as a side effect, it's expected to have methods that return Option<T>.

Could you please address that with another PR, so the code is inline with the source code of the other rules? Thank you

/// A parameter that is only passed to recursive calls is effectively unused
/// and can be removed or replaced with a constant, simplifying the function.
///
/// This rule is inspired by Rust Clippy's `only_used_in_recursion` lint.
Copy link
Member

Choose a reason for hiding this comment

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

Please remove, it's not needed

Comment on lines +307 to +318
fn is_function_like(node: &biome_rowan::SyntaxNode<biome_js_syntax::JsLanguage>) -> bool {
use biome_js_syntax::JsSyntaxKind::*;
matches!(
node.kind(),
JS_FUNCTION_DECLARATION
| JS_FUNCTION_EXPRESSION
| JS_ARROW_FUNCTION_EXPRESSION
| JS_METHOD_CLASS_MEMBER
| JS_METHOD_OBJECT_MEMBER
| JS_CONSTRUCTOR_CLASS_MEMBER
)
}
Copy link
Member

Choose a reason for hiding this comment

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

We already have a node called AnyFunctionLike. See if you can see it instead

Comment on lines +265 to +269
for ancestor in arrow_syntax.ancestors() {
// Skip the arrow function node itself
if ancestor == *arrow_syntax {
continue;
}
Copy link
Member

Choose a reason for hiding this comment

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

You can remove the first if by using ancestors().skip(1)

)
}

fn is_function_signature(parent_function: &AnyJsParameterParentFunction) -> bool {
Copy link
Member

Choose a reason for hiding this comment

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

Can you please add some docstrings?

)
}

fn is_recursive_call(call: &JsCallExpression, function_name: Option<&TokenText>) -> bool {
Copy link
Member

Choose a reason for hiding this comment

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

Can you please document this method, especially the business logic behind it? Also, document what function_name is, and why we need to pass it.

Also, lines 343-345 don't make sense. Let's just pass a TokenText. Let the caller take care of it

false
}

/// Enhanced version that checks if any argument traces to parameters
Copy link
Member

Choose a reason for hiding this comment

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

Enhanced version of what exactly? Can you please reword the docs and explain the business logic?

/// Enhanced version that checks if any argument traces to parameters
fn is_recursive_call_with_param_usage(
call: &JsCallExpression,
function_name: Option<&TokenText>,
Copy link
Member

Choose a reason for hiding this comment

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

Still, it doesn't make sense to provide an optional function name

}

// Get function name for recursion detection
let function_name = get_function_name(&parent_function);
Copy link
Member

Choose a reason for hiding this comment

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

Here you should use the try operator ?

Comment on lines +129 to +135
// Get all references to this parameter
let all_refs: Vec<_> = binding.all_references(model).collect();

// If no references, let noUnusedFunctionParameters handle it
if all_refs.is_empty() {
return None;
}
Copy link
Member

Choose a reason for hiding this comment

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

This isn't optimal because you allocate a vector even though you don't need to. all_references returns an interator, and if there aren't elements, the loop at line 141 doesn't trigger.

Can you remove the allocation?

function_name: Option<&TokenText>,
parent_function: &AnyJsParameterParentFunction,
param_name: &str,
) -> bool {
Copy link
Member

Choose a reason for hiding this comment

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

This function should return Option<bool>, as well as all the other functions that follow. This will have a chain effect on all other functions, but it removes all the let else return that you have in the code, which can be changed using ok()?.

@matanshavit
Copy link
Contributor Author

Yes, I can definitely address you comments. Let's not close the issue until the code is cleaned up.

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-JavaScript Language: JavaScript and super languages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants