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

Skip to content

Conversation

@ematipico
Copy link
Member

@ematipico ematipico commented Nov 19, 2025

Reverts #7684

Closes #8138

@changeset-bot
Copy link

changeset-bot bot commented Nov 19, 2025

🦋 Changeset detected

Latest commit: 1cbd0e4

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 Nov 19, 2025
@codspeed-hq
Copy link

codspeed-hq bot commented Nov 19, 2025

CodSpeed Performance Report

Merging #8173 will not alter performance

Comparing revert-7684-feat/no_unused_private_class_members_dynamic_prop_access (1cbd0e4) with main (0eb08e8)

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 marked this pull request as ready for review November 21, 2025 08:10
@ematipico ematipico changed the title Revert "feat(biome_js_analyze): align no_unused_private_class_members_with_semantic_class and dynamic prop access" fix: revert #7684 Nov 21, 2025
@ematipico ematipico added this pull request to the merge queue Nov 21, 2025
Merged via the queue into main with commit 7fc07c1 Nov 21, 2025
16 of 18 checks passed
@ematipico ematipico deleted the revert-7684-feat/no_unused_private_class_members_dynamic_prop_access branch November 21, 2025 08:15
@github-actions github-actions bot mentioned this pull request Nov 21, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 21, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This pull request reverts an internal refactor of the noUnusedPrivateClassMembers lint rule that introduced a regression where private class members used only in constructors were incorrectly marked as unused (issue #8138). The changes restructure the rule's semantic analysis by shifting from a semantic-class-centric approach to syntax-driven traversal with helper methods, update related public APIs across class member analysis services, and adjust test cases to reflect the corrected behavior.

Possibly related PRs

Suggested reviewers

  • dyc3
✨ 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 revert-7684-feat/no_unused_private_class_members_dynamic_prop_access

📜 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 0eb08e8 and 1cbd0e4.

⛔ Files ignored due to path filters (8)
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid.ts.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid_aligned_with_semantic_class.ts.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid_dynamic_access.ts.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid_issue_7101.ts.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/valid.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/valid_aligned_with_semantic_class.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/valid_dynamic_access.ts.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (13)
  • .changeset/stale-jokes-turn.md (1 hunks)
  • crates/biome_js_analyze/src/lint/correctness/no_unused_private_class_members.rs (14 hunks)
  • crates/biome_js_analyze/src/lint/style/use_readonly_class_properties.rs (13 hunks)
  • crates/biome_js_analyze/src/lint/suspicious/no_class_assign.rs (1 hunks)
  • crates/biome_js_analyze/src/services/semantic_class.rs (38 hunks)
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid.js (1 hunks)
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid.ts (1 hunks)
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid_aligned_with_semantic_class.ts (0 hunks)
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid_dynamic_access.ts (1 hunks)
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid_issue_7101.ts (1 hunks)
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/valid.js (4 hunks)
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/valid_aligned_with_semantic_class.js (0 hunks)
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/valid_dynamic_access.ts (1 hunks)

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 21, 2025

Walkthrough

This patch release reverts an internal refactor that introduced a regression in the noUnusedPrivateClassMembers rule, where private class members accessed exclusively from constructors were incorrectly flagged as unused. The fix involves restructuring the semantic_class service to shift from SemanticClass-based queries to more generic Semantic types, refactoring member traversal logic to use new FunctionThisReferences tracking, and updating related lint rules. Test files have been adjusted to align with the new semantics.

Possibly related PRs

Suggested reviewers

  • dyc3
  • arendjr

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarises the main change: reverting a previous feature that introduced a regression in the noUnusedPrivateClassMembers rule.
Description check ✅ Passed The description is related to the changeset, referencing the reverted PR and the issue being fixed.
Linked Issues check ✅ Passed The PR reverts the problematic changes from PR #7684, directly addressing issue #8138 which required private members accessed in constructors to be recognised as used.
Out of Scope Changes check ✅ Passed All changes are scoped to reverting PR #7684; test files are updated to remove patterns that were part of the reverted feature, remaining in scope.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ 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 revert-7684-feat/no_unused_private_class_members_dynamic_prop_access

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/biome_js_analyze/src/lint/style/use_readonly_class_properties.rs (1)

126-148: Fix ctx.model access: should be ctx.model() method call

Line 141 uses ctx.model.class_member_references(…) as a field access, but RuleContext exposes model as a method. Across all other rules (e.g. no_class_assign.rs, use_static_response_methods.rs, no_var.rs), the pattern is ctx.model() followed by the method call. Change line 141 to:

- let ClassMemberReferences { writes, .. } = ctx.model.class_member_references(&members);
+ let ClassMemberReferences { writes, .. } = ctx.model().class_member_references(&members);

This will not compile as-is.

🧹 Nitpick comments (3)
crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid.ts (1)

9-13: Constructor parameter name looks like a typo.

nusedProperty on Line 10 reads like a slipped u from unusedProperty. The test still does its job, but consider renaming for readability.

crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid.js (1)

41-46: New Foo case neatly covers compound write‑only usage.

this.#usedOnlyInWriteStatement += 42; is a good extra invalid scenario where the private field is only written and the expression value is ignored, complementing the simple assignment case above. If you want clearer test names, you could rename this second Foo, but it is not strictly necessary.

crates/biome_js_analyze/src/lint/style/use_readonly_class_properties.rs (1)

149-179: Avoid cloning writes and AnyPropertyMember in the hot path

The filtering pipeline currently does quite a bit of cloning:

  • Each prop_or_param is cloned several times.
  • writes.clone().into_iter() re‑clones the entire FxHashSet for every candidate.

Functionally this works, but it’s unnecessarily expensive for larger classes.

You can keep the behaviour while reducing allocations by iterating by reference and pattern‑matching directly on AnyPropertyMember, for example:

- constructor_params
-     .clone()
-     .into_iter()
+ constructor_params
+     .iter()
+     .cloned()
      .chain(
-         non_readonly_class_property_members.filter(|class_property_member| {
-             !constructor_params.clone().into_iter().any(|node| {
-                 node.to_trimmed_text() == class_property_member.to_trimmed_text()
-             })
-         }),
+         non_readonly_class_property_members.filter(|class_property_member| {
+             !constructor_params.iter().any(|node| {
+                 node.to_trimmed_text() == class_property_member.to_trimmed_text()
+             })
+         }),
      )
-     .filter_map(|prop_or_param| {
-         if writes
-             .clone()
-             .into_iter()
-             .any(|ClassMemberReference { name, .. }| {
-                 if let Some(TextAndRange { text, .. }) =
-                     extract_property_or_param_range_and_text(&prop_or_param.clone())
-                 {
-                     return name.eq(&text);
-                 }
-                 false
-             })
-         {
-             None
-         } else {
-             Some(prop_or_param.clone())
-         }
-     })
+     .filter_map(|prop_or_param| {
+         let Some(TextAndRange { text, .. }) =
+             extract_property_or_param_range_and_text(&prop_or_param)
+         else {
+             return None;
+         };
+
+         if writes.iter().any(|ClassMemberReference { name, .. }| name == &text) {
+             None
+         } else {
+             Some(prop_or_param)
+         }
+     })

Similarly, extract_property_or_param_range_and_text can be simplified to match directly on &AnyPropertyMember instead of casting from a cloned syntax node:

-fn extract_property_or_param_range_and_text(
-    property_or_param: &AnyPropertyMember,
-) -> Option<TextAndRange> {
-    if let Some(AnyPropertyMember::JsPropertyClassMember(member)) =
-        AnyPropertyMember::cast(property_or_param.clone().into())
-    {
+fn extract_property_or_param_range_and_text(
+    property_or_param: &AnyPropertyMember,
+) -> Option<TextAndRange> {
+    if let AnyPropertyMember::JsPropertyClassMember(member) = property_or_param {
         if let Ok(member_name) = member.name() {
             return Some(TextAndRange {
                 text: member_name.to_trimmed_text(),
                 range: member_name.range(),
             });
         }
         return None;
     }
-
-    if let Some(AnyPropertyMember::TsPropertyParameter(parameter)) =
-        AnyPropertyMember::cast(property_or_param.clone().into())
-    {
+    if let AnyPropertyMember::TsPropertyParameter(parameter) = property_or_param {
         let name = parameter
             .formal_parameter()
             .ok()?
             .as_js_formal_parameter()?
             .binding()
             .ok()?;
         return Some(TextAndRange {
             text: name.to_trimmed_text(),
             range: name.range(),
         });
     }
     None
 }

This keeps the logic as‑is while tightening up allocations and making the intent a bit clearer.

Please sanity‑check that the refactor preserves behaviour for both class properties and TS property parameters, especially around to_trimmed_text() equality.

Also applies to: 285-288, 333-335, 349-354, 398-431

📜 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 0eb08e8 and 1cbd0e4.

⛔ Files ignored due to path filters (8)
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid.ts.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid_aligned_with_semantic_class.ts.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid_dynamic_access.ts.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid_issue_7101.ts.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/valid.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/valid_aligned_with_semantic_class.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/valid_dynamic_access.ts.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (13)
  • .changeset/stale-jokes-turn.md (1 hunks)
  • crates/biome_js_analyze/src/lint/correctness/no_unused_private_class_members.rs (14 hunks)
  • crates/biome_js_analyze/src/lint/style/use_readonly_class_properties.rs (13 hunks)
  • crates/biome_js_analyze/src/lint/suspicious/no_class_assign.rs (1 hunks)
  • crates/biome_js_analyze/src/services/semantic_class.rs (38 hunks)
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid.js (1 hunks)
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid.ts (1 hunks)
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid_aligned_with_semantic_class.ts (0 hunks)
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid_dynamic_access.ts (1 hunks)
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid_issue_7101.ts (1 hunks)
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/valid.js (4 hunks)
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/valid_aligned_with_semantic_class.js (0 hunks)
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/valid_dynamic_access.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/valid_aligned_with_semantic_class.js
  • crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid_aligned_with_semantic_class.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-25T12:32:59.003Z
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.

Applied to files:

  • .changeset/stale-jokes-turn.md
🧬 Code graph analysis (2)
crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/valid_dynamic_access.ts (1)
crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid_dynamic_access.ts (1)
  • Sample (1-13)
crates/biome_js_analyze/src/lint/correctness/no_unused_private_class_members.rs (3)
crates/biome_rowan/src/ast/mod.rs (1)
  • try_cast (182-188)
crates/biome_rowan/src/syntax/node.rs (1)
  • grand_parent (254-256)
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). (13)
  • GitHub Check: Documentation
  • GitHub Check: End-to-end tests
  • GitHub Check: Test (depot-ubuntu-24.04-arm-16)
  • 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: Check Dependencies
  • GitHub Check: Test Node.js API
  • GitHub Check: autofix
  • GitHub Check: Validate rules documentation
  • GitHub Check: Bench (biome_js_analyze)
  • GitHub Check: Bench (biome_js_parser)
  • GitHub Check: Bench (biome_js_formatter)
🔇 Additional comments (9)
.changeset/stale-jokes-turn.md (1)

1-5: Changelog entry accurately describes the regression fix.

Clear that this is a patch for @biomejs/biome, tied to #8138 and explicitly naming noUnusedPrivateClassMembers; reads well for release notes.

crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/valid_dynamic_access.ts (1)

3-13: Dynamic access test still exercises both private members correctly.

This keeps add initialised and remove captured as a private ctor parameter, both invoked via this[action](), which is a solid “no diagnostics expected” case for dynamic access.

crates/biome_js_analyze/src/lint/suspicious/no_class_assign.rs (1)

101-122: Diagnostic builder matches the collected Reference state.

Using the write reference.syntax().text_trimmed_range() as the primary span and the class name binding as a detail is consistent with the rule docs and the run implementation, and the ? chain keeps it safe for odd class forms.

crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid_issue_7101.ts (1)

2-12: Constructor rewrite focuses the test on the unused private properties.

Both unusedProperty and anotherUnusedProperty are now private ctor properties with defaults and no subsequent usage, which cleanly exercises the intended “two unused private ctor members” scenario for this issue. Any TS‑level diagnostics can stay in the remit of the existing CI.

Based on learnings.

crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/valid.js (1)

22-29: New valid patterns nicely broaden “used private member” coverage.

These added classes cover several nuanced usages—accessors updated via +=, setter‑only members appearing in destructuring targets, private fields read through instances captured in inner classes, and simple setter calls from methods—so they collectively help ensure noUnusedPrivateClassMembers does not mis‑fire on legitimate patterns.

Also applies to: 134-140, 154-162, 173-181

crates/biome_js_analyze/tests/specs/correctness/noUnusedPrivateClassMembers/invalid_dynamic_access.ts (1)

2-12: Dynamic-access fixture still looks sound

The minimal Sample shape (private field, #prop, constructor writes, and this[name] lookup) still covers the dynamic-access case without adding noise. Nothing here appears to contradict the intended “invalid” scenario for the rule.

crates/biome_js_analyze/src/lint/correctness/no_unused_private_class_members.rs (2)

244-303: Constructor‑only usages vs write‑only/update detection

The new traverse_members_usage logic removes members from the “unused” set only when it sees a name match that is not:

  • a write‑only assignment (as defined by is_write_only), or
  • part of an update expression whose result isn’t used (is_in_update_expression).

This is deliberate for cases like:

  • this.#usedOnlyInWrite = 212; (still considered unused), and
  • this.count++; as a bare statement.

For the regression in #8138, the key bit is that constructor‑only reads (e.g. console.log(this.#field) or this.#method() from the constructor) should still cause the corresponding member to be dropped from private_members, while constructor‑only writes should keep the current “write‑only” behaviour.

The current logic doesn’t treat constructors specially, so constructor reads should be handled the same as method reads; only pure writes and update‑only uses are filtered out.

Could you re‑run the linked reproducer from issue #8138 (private field and private method only used from the constructor) to confirm that:

  • constructor reads clear the member from unused_members, and
  • constructor‑only write‑only patterns are still intentionally reported?
    If that expectation differs, we may need to relax is_write_only for constructor contexts.

Also applies to: 377-430


97-113: Option passed to RuleDiagnostic::new—needs verification

The review comment correctly identifies a type mismatch: property_range() returns Option<TextRange>, but diagnostic() passes it directly to RuleDiagnostic::new() in three places (lines ~150–181). The code clearly shows property_range can legitimately return None for bogus or metavariable parameters.

I've examined the source code and confirmed the pattern described in the review. However, I cannot run cargo check in the sandbox to definitively confirm whether this causes a compilation error or relies on implicit conversion.

The suggested fix (early return with ? operator) is idiomatic Rust and ensures diagnostics only emit when a valid range is available. Please run a build locally to confirm the type error and apply the fix if needed.

crates/biome_js_analyze/src/services/semantic_class.rs (1)

20-38: Semantic-class service wiring and constructor handling look consistent

The new SemanticClassServices/SemanticClassModel wrapper plus the two visitors give you a cheap, syntax‑only class_member_references API that’s then reused by useReadonlyClassProperties. The way class_member_references delegates constructor analysis to collect_references_from_constructor—which only looks at nested function bodies, not the top‑level constructor body—nicely matches the rule’s intent: treat direct constructor writes as initialisation, but still consider writes in escaping closures as mutations.

The only micro‑nit is that you build an intermediate Vec<ClassMemberReferences> and then fold it; this could be folded directly into the two FxHashSets, but it’s not worth bikeshedding unless this shows up in profiles.

It’s worth re‑running the useReadonlyClassProperties suite for classes that mutate fields only:

  • directly in the constructor;
  • in arrow functions created in the constructor; and
  • in regular methods,
    to make sure the new class_member_references semantics match the documented rule behaviour.

Also applies to: 185-242, 819-837

ryan-m-walker pushed a commit to ryan-m-walker/biome that referenced this pull request Nov 23, 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.

🐛 Private class members used from constructor are incorrectly marked as unused

2 participants