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

Skip to content

Conversation

@ematipico
Copy link
Member

@ematipico ematipico commented Dec 7, 2025

Summary

Fixes #7927

Follow up of #7935

Test Plan

Docs

harshasiddartha and others added 8 commits November 1, 2025 02:29
Fix issue #7927 where noExtraNonNullAssertion incorrectly triggered for
compound assignments like arr[0]! ^= arr[1]!. The rule should only flag
nested assertions, not separate assertions on different sides of an
assignment expression.

The fix checks if the non-null assertion is actually nested within
the left side expression tree before flagging it as an error.
Address reviewer feedback: ensure nested assertions like arr[0] ^= arr[1]!!
are correctly flagged. The fix now checks for nested assertions first
before checking assignment-specific cases, ensuring all nested assertions
are caught regardless of which side of the assignment they appear on.
@changeset-bot
Copy link

changeset-bot bot commented Dec 7, 2025

🦋 Changeset detected

Latest commit: 6e8a782

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-Linter Area: linter L-JavaScript Language: JavaScript and super languages labels Dec 7, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 7, 2025

Walkthrough

The PR refines the noExtraNonNullAssertion linting rule to distinguish between invalid nested non-null assertions within an assignment's left side and valid separate assertions across different sides of compound assignments. The rule implementation adds logic to skip flagging when assertions are on opposite sides of an assignment, whilst maintaining checks for genuinely nested patterns. Test cases cover both valid and invalid compound assignment scenarios.

Suggested labels

A-Linter, L-JavaScript

Suggested reviewers

  • dyc3
  • arendjr

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: fixing the lint rule to allow separate non-null assertions on opposite sides of assignments, which directly matches the changeset modifications.
Description check ✅ Passed The description references the related issue (#7927) and previous PR (#7935), clearly connecting to the changeset's purpose of fixing non-null assertion handling in assignments.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/no-extra-non-null-assertion-compound-assignment

📜 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 cc2a62e and 6e8a782.

⛔ Files ignored due to path filters (2)
  • crates/biome_js_analyze/tests/specs/suspicious/noExtraNonNullAssertion/invalid.ts.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/suspicious/noExtraNonNullAssertion/valid.ts.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (4)
  • .changeset/no-extra-non-null-assertion-compound-assign.md (1 hunks)
  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs (3 hunks)
  • crates/biome_js_analyze/tests/specs/suspicious/noExtraNonNullAssertion/invalid.ts (1 hunks)
  • crates/biome_js_analyze/tests/specs/suspicious/noExtraNonNullAssertion/valid.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
.changeset/**/*.md

📄 CodeRabbit inference engine (CONTRIBUTING.md)

.changeset/**/*.md: Create changesets for user-facing changes using just new-changeset; use headers with #### or ##### only; keep descriptions concise (1-3 sentences) and focus on user-facing changes
Use past tense when describing what was done ('Added new feature'), present tense when describing Biome behavior ('Biome now supports'); end sentences with a full stop
For new lint rules, show an example of an invalid case in an inline code snippet or code block; for rule changes, demonstrate what is now invalid or valid; for formatter changes, use a diff code block

Files:

  • .changeset/no-extra-non-null-assertion-compound-assign.md
**/*.ts

📄 CodeRabbit inference engine (CONTRIBUTING.md)

For Node.js package development, build WebAssembly bindings and JSON-RPC bindings; run tests against compiled files after implementing features or bug fixes

Files:

  • crates/biome_js_analyze/tests/specs/suspicious/noExtraNonNullAssertion/invalid.ts
  • crates/biome_js_analyze/tests/specs/suspicious/noExtraNonNullAssertion/valid.ts
**/*.rs

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.rs: Use the dbg!() macro for debugging output during testing, and pass the --show-output flag to cargo to view debug output
Use cargo t or cargo test to run tests; for a single test, pass the test name after the test command
Use snapshot testing with the insta crate; run cargo insta accept, cargo insta reject, or cargo insta review to manage snapshot changes
Write doctests as doc comments with code blocks; the code inside code blocks will be run during the testing phase
Use just f (alias for just format) to format Rust and TOML files before committing

Files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
🧠 Learnings (24)
📓 Common learnings
Learnt from: arendjr
Repo: biomejs/biome PR: 7593
File: crates/biome_service/src/workspace/server.rs:1306-1306
Timestamp: 2025-09-25T12:32:59.003Z
Learning: In the biomejs/biome project, do not flag compilation errors during code review as they are handled by the existing test infrastructure and CI. Focus on other code quality aspects instead.
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-28T09:08:10.091Z
Learning: Disclose any AI assistance used in pull requests, including the extent of usage (e.g., used for docs generation, tests, etc.)
📚 Learning: 2025-11-28T09:08:10.091Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-28T09:08:10.091Z
Learning: Applies to .changeset/**/*.md : For new lint rules, show an example of an invalid case in an inline code snippet or code block; for rule changes, demonstrate what is now invalid or valid; for formatter changes, use a `diff` code block

Applied to files:

  • .changeset/no-extra-non-null-assertion-compound-assign.md
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/tests/specs/**/*.{js,ts,tsx,jsx,json,css} : Test rules using snapshot tests via the `insta` library with test cases in `tests/specs/<group>/<rule_name>/` directories prefixed by `invalid` or `valid`

Applied to files:

  • crates/biome_js_analyze/tests/specs/suspicious/noExtraNonNullAssertion/invalid.ts
  • crates/biome_js_analyze/tests/specs/suspicious/noExtraNonNullAssertion/valid.ts
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/tests/specs/**/*.jsonc : Use `.jsonc` files in test specs with code snippets as array of strings to test rules in script environment (no import/export syntax)

Applied to files:

  • crates/biome_js_analyze/tests/specs/suspicious/noExtraNonNullAssertion/invalid.ts
  • crates/biome_js_analyze/tests/specs/suspicious/noExtraNonNullAssertion/valid.ts
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Check if a variable is global before banning it to avoid false positives when the variable is redeclared in local scope; use the semantic model to verify global scope

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUnsafe` prefix for rules that report code leading to runtime failures (e.g., `noUnsafeOptionalChaining`)

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUndeclared` prefix for rules that report undefined entities (e.g., `noUndeclaredVariables`)

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noExcessive` prefix for rules that report code exceeding configurable limits (e.g., `noExcessiveNestedTestSuites`)

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noInvalid` prefix for rules that report runtime errors from mistyping (e.g., `noInvalidConstructorSuper`)

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noRestricted` prefix for rules that report user-banned entities (e.g., `noRestrictedGlobals`)

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noRedundant` prefix for rules that report redundant code (e.g., `noRedundantUseStrict`)

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUnused` prefix for rules that report unused entities (e.g., `noUnusedVariables`)

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use the `noUnknown` prefix for rules that report mistyped entities in CSS (e.g., `noUnknownUnit`)

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Avoid using `unwrap()` or `expect()` on `Result` and `Option` types; instead use helper functions like `map`, `filter`, `and_then` to maintain code clarity and avoid panics

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : When formatting AST nodes, use mandatory tokens from the AST instead of hardcoding token strings (e.g., use `node.l_paren_token().format()` instead of `token("(")`)

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/src/**/*.rs : Use `ConditionalParsedSyntax` for syntax that is only valid in specific contexts (e.g., strict mode, file types, language versions) and call `or_invalid_to_bogus()` to convert to a bogus node if not supported

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Import the `FormatNode` trait and implement it for your Node when creating formatters in biome_js_formatter

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Do not attempt to 'fix' the code; if a token/node is known to be mandatory but is missing, return `None` instead

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : In rule documentation code blocks, mark invalid examples with the `expect_diagnostic` property and valid examples without it; each invalid example must emit exactly one diagnostic

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : The `diagnostic` function must return a `RuleDiagnostic` that defines the message reported to the user using the `markup!` macro

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use language tags in documentation code blocks (js, ts, tsx, json, css) and order properties consistently as: language, then `expect_diagnostic`, then options modifiers, then `ignore`, then `file=path`

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/*.ungram : Nodes for enclosing syntax errors must have the `Bogus` word, e.g., `HtmlBogusAttribute`, and must be part of a variant

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
📚 Learning: 2025-11-27T23:04:02.022Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-11-27T23:04:02.022Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/lint/**/*.rs : Use `Semantic<T>` query type instead of `Ast<T>` when a rule needs to access the semantic model for binding references and scope information

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/src/**/*.rs : Use `p.eat(token)` for optional tokens, `p.expect(token)` for required tokens, `parse_rule(p).ok(p)` for optional nodes, and `parse_rule(p).or_add_diagnostic(p, error)` for required nodes

Applied to files:

  • crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs
🧬 Code graph analysis (1)
crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs (1)
crates/biome_js_formatter/src/utils/assignment_like.rs (1)
  • left (355-374)
⏰ 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). (12)
  • GitHub Check: End-to-end tests
  • GitHub Check: autofix
  • GitHub Check: Bench (biome_js_parser)
  • GitHub Check: Documentation
  • GitHub Check: Test (depot-windows-2022-16)
  • GitHub Check: Test (depot-ubuntu-24.04-arm-16)
  • GitHub Check: Lint project (depot-ubuntu-24.04-arm-16)
  • GitHub Check: Lint project (depot-windows-2022)
  • GitHub Check: Check Dependencies
  • GitHub Check: Test Node.js API
  • GitHub Check: Bench (biome_js_analyze)
  • GitHub Check: Bench (biome_js_formatter)
🔇 Additional comments (6)
.changeset/no-extra-non-null-assertion-compound-assign.md (1)

1-22: Well-structured changeset.

Clear explanation of the fix with helpful examples demonstrating valid vs invalid cases. Follows the coding guidelines for changesets nicely.

crates/biome_js_analyze/src/lint/suspicious/no_extra_non_null_assertion.rs (3)

5-8: LGTM on imports.

The JsParenthesizedExpression import is needed for the new ancestor traversal logic.


85-100: Solid nested assertion detection.

The ancestor traversal correctly identifies nested non-null assertions (e.g., foo!!) whilst skipping over parenthesised expressions. Early return keeps the logic clean.


115-131: Variable naming is misleading; the logic is correct but could be clearer.

At line 123, the variable desc suggests descendants, but children() returns only immediate children. While this doesn't cause incorrect behavior in practice (both left-side arr1[0]!! and right-side arr2[1]!! cases are correctly flagged by the tests), the code could be clearer. Consider renaming desc to child to accurately reflect what is being checked, or add a comment explaining why only immediate children need to be checked (i.e., TsNonNullAssertionExpression on the left side of assignments is rare due to parser behavior, where it would normally be parsed as TsNonNullAssertionAssignment instead).

crates/biome_js_analyze/tests/specs/suspicious/noExtraNonNullAssertion/valid.ts (1)

22-25: Good test coverage for #7927.

The test case clearly demonstrates that separate non-null assertions on both sides of a compound assignment are now correctly allowed.

crates/biome_js_analyze/tests/specs/suspicious/noExtraNonNullAssertion/invalid.ts (1)

49-55: Comprehensive invalid test coverage.

Both nested assertion scenarios are covered: double assertion on the left side (arr1[0]!!) and on the right side (arr2[1]!!). Together with the valid test, this fully exercises the fix for #7927.


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

@codspeed-hq
Copy link

codspeed-hq bot commented Dec 7, 2025

CodSpeed Performance Report

Merging #8383 will not alter performance

Comparing fix/no-extra-non-null-assertion-compound-assignment (6e8a782) with main (d407efb)

Summary

✅ 58 untouched
⏩ 95 skipped1

Footnotes

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

@ematipico ematipico merged commit 59b2f9a into main Dec 7, 2025
19 checks passed
@ematipico ematipico deleted the fix/no-extra-non-null-assertion-compound-assignment branch December 7, 2025 21:51
@github-actions github-actions bot mentioned this pull request Dec 7, 2025
ematipico added a commit that referenced this pull request Dec 8, 2025
ematipico added a commit that referenced this pull request Dec 8, 2025
This was referenced Dec 15, 2025
l0ngvh pushed a commit to l0ngvh/biome that referenced this pull request Dec 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Linter Area: linter L-JavaScript Language: JavaScript and super languages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

💅 lint/suspicious/noExtraNonNullAssertion triggers for arr[0]! ^= arr[1]!

3 participants