feat(linter): add noReactObjectTypeAsDefaultProp rule - #10634
Conversation
🦋 Changeset detectedLatest commit: d3a0e0e The changes in this PR will be included in the next version bump. This PR includes changesets to release 13 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
✅ Organic activityNo automation signals detected in the analyzed events. This is an automated analysis by AgentScan |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThe PR implements the Suggested reviewers
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
.changeset/add-no-object-type-as-default-prop.md (1)
5-5: ⚡ Quick winAdd a tiny invalid example.
As per coding guidelines, new lint-rule changesets should show an invalid case, not just prose. A single inline example would make this easier to scan.
💡 Suggested tweak
-Added [`noObjectTypeAsDefaultProp`](https://biomejs.dev/linter/rules/no-object-type-as-default-prop/) to the nursery group. This rule disallows reference-type values (arrays, objects, functions, classes, `new` expressions, JSX elements, regular expressions, and `Symbol()`) as default values for destructured props in React function components, because a new instance is created on every render, which can break memoization and cause unnecessary re-renders. It ports [`no-object-type-as-default-prop`](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-object-type-as-default-prop.md) from `eslint-plugin-react`. +Added [`noObjectTypeAsDefaultProp`](https://biomejs.dev/linter/rules/no-object-type-as-default-prop/) to the nursery group. For example, `function Foo({ bar = {} }) {}` is now flagged. This rule disallows reference-type values (arrays, objects, functions, classes, `new` expressions, JSX elements, regular expressions, and `Symbol()`) as default values for destructured props in React function components, because a new instance is created on every render, which can break memoization and cause unnecessary re-renders. It ports [`no-object-type-as-default-prop`](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-object-type-as-default-prop.md) from `eslint-plugin-react`.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.changeset/add-no-object-type-as-default-prop.md at line 5, The changeset file for the noObjectTypeAsDefaultProp rule lacks an invalid code example, which is required per coding guidelines for lint-rule changesets. Add a single inline code example after the prose description that demonstrates invalid usage of the rule, such as a React function component with a destructured prop that has a reference-type default value (like an object literal, array, or function). This will make the changeset easier to scan and understand what the rule disallows.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/biome_rule_options/src/no_object_type_as_default_prop.rs`:
- Line 6: The public struct NoObjectTypeAsDefaultPropOptions is missing rustdoc
documentation. Add a rustdoc comment (using ///) above the struct definition
that briefly describes the purpose of this options type container. Even though
the struct is currently empty, the doc comment should explain what configuration
options it will hold or what the rule option is for, to comply with the
repository's documentation requirements for public types.
---
Nitpick comments:
In @.changeset/add-no-object-type-as-default-prop.md:
- Line 5: The changeset file for the noObjectTypeAsDefaultProp rule lacks an
invalid code example, which is required per coding guidelines for lint-rule
changesets. Add a single inline code example after the prose description that
demonstrates invalid usage of the rule, such as a React function component with
a destructured prop that has a reference-type default value (like an object
literal, array, or function). This will make the changeset easier to scan and
understand what the rule disallows.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f616111a-5e29-48cd-bda9-71c23b563051
⛔ Files ignored due to path filters (7)
crates/biome_configuration/src/analyzer/linter/rules.rsis excluded by!**/rules.rsand included by**crates/biome_configuration/src/generated/linter_options_check.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_diagnostics_categories/src/categories.rsis excluded by!**/categories.rsand included by**crates/biome_js_analyze/tests/specs/nursery/noObjectTypeAsDefaultProp/invalid.jsx.snapis excluded by!**/*.snapand included by**crates/biome_js_analyze/tests/specs/nursery/noObjectTypeAsDefaultProp/valid.jsx.snapis excluded by!**/*.snapand included by**packages/@biomejs/backend-jsonrpc/src/workspace.tsis excluded by!**/backend-jsonrpc/src/workspace.tsand included by**packages/@biomejs/biome/configuration_schema.jsonis excluded by!**/configuration_schema.jsonand included by**
📒 Files selected for processing (7)
.changeset/add-no-object-type-as-default-prop.mdcrates/biome_cli/Cargo.tomlcrates/biome_js_analyze/src/lint/nursery/no_object_type_as_default_prop.rscrates/biome_js_analyze/tests/specs/nursery/noObjectTypeAsDefaultProp/invalid.jsxcrates/biome_js_analyze/tests/specs/nursery/noObjectTypeAsDefaultProp/valid.jsxcrates/biome_rule_options/src/lib.rscrates/biome_rule_options/src/no_object_type_as_default_prop.rs
7b259b2 to
ab86779
Compare
1597b45 to
b0382d3
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.changeset/add-no-object-type-as-default-prop.md:
- Line 5: The changeset description in the
`.changeset/add-no-object-type-as-default-prop.md` file is missing a full stop
at the end of the sentence. Add a period at the end of the description text that
starts with "Added [`noObjectTypeAsDefaultProp`]..." to comply with the coding
guideline that every sentence must end with a full stop.
In `@crates/biome_js_analyze/src/lint/nursery/no_object_type_as_default_prop.rs`:
- Around line 211-233: The `.ok()?` calls at the property extraction (after
iterating in the for loop) and at the initializer expression unwrapping are
causing early returns from the entire function when encountering parse errors,
which prevents checking remaining properties and loses any violations already
found. Replace the `.ok()?` at line 212 (after `let property = property`) with a
`let Some(...) else { continue; }` pattern to skip malformed properties, and
similarly replace the `.ok()?` at line 223 (at `initializer.expression().ok()?`)
with the same pattern to skip missing or invalid initializer expressions. This
keeps the function iterating through all properties and collects all violations
without early termination.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 9320c104-b812-4597-8632-44b64d65667e
⛔ Files ignored due to path filters (7)
crates/biome_configuration/src/analyzer/linter/rules.rsis excluded by!**/rules.rsand included by**crates/biome_configuration/src/generated/linter_options_check.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_diagnostics_categories/src/categories.rsis excluded by!**/categories.rsand included by**crates/biome_js_analyze/tests/specs/nursery/noObjectTypeAsDefaultProp/invalid.jsx.snapis excluded by!**/*.snapand included by**crates/biome_js_analyze/tests/specs/nursery/noObjectTypeAsDefaultProp/valid.jsx.snapis excluded by!**/*.snapand included by**packages/@biomejs/backend-jsonrpc/src/workspace.tsis excluded by!**/backend-jsonrpc/src/workspace.tsand included by**packages/@biomejs/biome/configuration_schema.jsonis excluded by!**/configuration_schema.jsonand included by**
📒 Files selected for processing (7)
.changeset/add-no-object-type-as-default-prop.mdcrates/biome_cli/Cargo.tomlcrates/biome_js_analyze/src/lint/nursery/no_object_type_as_default_prop.rscrates/biome_js_analyze/tests/specs/nursery/noObjectTypeAsDefaultProp/invalid.jsxcrates/biome_js_analyze/tests/specs/nursery/noObjectTypeAsDefaultProp/valid.jsxcrates/biome_rule_options/src/lib.rscrates/biome_rule_options/src/no_object_type_as_default_prop.rs
✅ Files skipped from review due to trivial changes (2)
- crates/biome_cli/Cargo.toml
- crates/biome_rule_options/src/lib.rs
🚧 Files skipped from review as they are similar to previous changes (3)
- crates/biome_rule_options/src/no_object_type_as_default_prop.rs
- crates/biome_js_analyze/tests/specs/nursery/noObjectTypeAsDefaultProp/valid.jsx
- crates/biome_js_analyze/tests/specs/nursery/noObjectTypeAsDefaultProp/invalid.jsx
| "@biomejs/biome": patch | ||
| --- | ||
|
|
||
| Added [`noObjectTypeAsDefaultProp`](https://biomejs.dev/linter/rules/no-object-type-as-default-prop/) to the nursery group. This rule disallows reference-type values (arrays, objects, functions, classes, `new` expressions, JSX elements, regular expressions, and `Symbol()`) as default values for destructured props in React function components, because a new instance is created on every render, which can break memoization and cause unnecessary re-renders. It ports [`no-object-type-as-default-prop`](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-object-type-as-default-prop.md) from `eslint-plugin-react`. |
There was a problem hiding this comment.
Add a full stop at the end.
As per coding guidelines, every sentence in a changeset must end with a full stop.
📝 Proposed fix
-Added [`noObjectTypeAsDefaultProp`](https://biomejs.dev/linter/rules/no-object-type-as-default-prop/) to the nursery group. This rule disallows reference-type values (arrays, objects, functions, classes, `new` expressions, JSX elements, regular expressions, and `Symbol()`) as default values for destructured props in React function components, because a new instance is created on every render, which can break memoization and cause unnecessary re-renders. It ports [`no-object-type-as-default-prop`](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-object-type-as-default-prop.md) from `eslint-plugin-react`
+Added [`noObjectTypeAsDefaultProp`](https://biomejs.dev/linter/rules/no-object-type-as-default-prop/) to the nursery group. This rule disallows reference-type values (arrays, objects, functions, classes, `new` expressions, JSX elements, regular expressions, and `Symbol()`) as default values for destructured props in React function components, because a new instance is created on every render, which can break memoization and cause unnecessary re-renders. It ports [`no-object-type-as-default-prop`](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-object-type-as-default-prop.md) from `eslint-plugin-react`.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Added [`noObjectTypeAsDefaultProp`](https://biomejs.dev/linter/rules/no-object-type-as-default-prop/) to the nursery group. This rule disallows reference-type values (arrays, objects, functions, classes, `new` expressions, JSX elements, regular expressions, and `Symbol()`) as default values for destructured props in React function components, because a new instance is created on every render, which can break memoization and cause unnecessary re-renders. It ports [`no-object-type-as-default-prop`](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-object-type-as-default-prop.md) from `eslint-plugin-react`. | |
| Added [`noObjectTypeAsDefaultProp`](https://biomejs.dev/linter/rules/no-object-type-as-default-prop/) to the nursery group. This rule disallows reference-type values (arrays, objects, functions, classes, `new` expressions, JSX elements, regular expressions, and `Symbol()`) as default values for destructured props in React function components, because a new instance is created on every render, which can break memoization and cause unnecessary re-renders. It ports [`no-object-type-as-default-prop`](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-object-type-as-default-prop.md) from `eslint-plugin-react`. |
🧰 Tools
🪛 LanguageTool
[formatting] ~5-~5: If the ‘because’ clause is essential to the meaning, do not use a comma before the clause.
Context: ...tured props in React function components, because a new instance is created on every rend...
(COMMA_BEFORE_BECAUSE)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.changeset/add-no-object-type-as-default-prop.md at line 5, The changeset
description in the `.changeset/add-no-object-type-as-default-prop.md` file is
missing a full stop at the end of the sentence. Add a period at the end of the
description text that starts with "Added [`noObjectTypeAsDefaultProp`]..." to
comply with the coding guideline that every sentence must end with a full stop.
Source: Coding guidelines
ematipico
left a comment
There was a problem hiding this comment.
This is a new rule, it goes to main
| /// | ||
| pub NoObjectTypeAsDefaultProp { | ||
| version: "next", | ||
| name: "noObjectTypeAsDefaultProp", |
There was a problem hiding this comment.
Since it's a react focused rule, we should name this "noReact..."
There was a problem hiding this comment.
Make sense, and I fixed it.
| use crate::react::components::{AnyPotentialReactComponentDeclaration, ReactComponentInfo}; | ||
|
|
||
| declare_lint_rule! { | ||
| /// Disallow reference-type values as default values for destructured props. |
There was a problem hiding this comment.
Use beginner friendly language. What's reference-type?
There was a problem hiding this comment.
By "reference type" I meant arrays, objects, and functions (values compared by identity), not by value ([] !== []).
I've dropped the term and rewritten the docs in plain language.
| /// Arrays, objects, and functions are compared by reference, not by value. | ||
| /// A default value like `{ items = [] }` runs on every render, so `items` is a | ||
| /// new array every time. React compares by reference, so it thinks the value | ||
| /// changed. This breaks memoization (such as `React.memo`, `useMemo`, or | ||
| /// `useEffect` dependency arrays) and causes extra re-renders. Primitives are | ||
| /// safe because they are compared by value. | ||
| /// | ||
| /// To fix a violation, declare the value as a constant outside the component | ||
| /// and use it as the default. |
There was a problem hiding this comment.
The docs are very, very technical since the beginning and they don't explain very well what this rule is for. Please use a beginning friendly language.
Also the "to fix a violation" part is redundant, it should be explained in the diagnostic of the rule
| let Some(_component) = ReactComponentInfo::from_declaration(node.syntax()) else { | ||
| return vec![]; | ||
| }; |
There was a problem hiding this comment.
I tried is_some() first, but it read worse for an early return (it becomes !is_some(), which clippy also flags), so I went with is_none(). Let me know if you'd prefer otherwise.
There was a problem hiding this comment.
Yeah what clippy says. It's basically pointless having a let-else with a binding you don't use
There was a problem hiding this comment.
Right, the is_none() version drops the binding entirely, which was the real issue. Thanks!
| "Avoid using "{kind}" as the default value of a destructured prop." | ||
| }, | ||
| ) | ||
| .note(markup! { | ||
| "Reference-type defaults create a new value on every render, which can break memoization and may cause unnecessary re-renders or, in some cases, infinite render loops." | ||
| }) | ||
| .note(markup! { | ||
| "Use a constant defined outside the component as the default value instead." | ||
| }), |
There was a problem hiding this comment.
Diagnostics don't follow the rule pillars https://biomejs.dev/linter/#rule-pillars
There was a problem hiding this comment.
Thank you.
Reworked the diagnostic to follow the three pillars (what's wrong (message), why (note), and how to fix (note))
b0382d3 to
b189e6c
Compare
| name: "noReactObjectTypeAsDefaultProp", | ||
| language: "js", | ||
| sources: &[RuleSource::EslintReact("no-object-type-as-default-prop").same()], | ||
| recommended: false, |
There was a problem hiding this comment.
Should we make this recommended? The source rule currently isn't, but however I found jsx-eslint/eslint-plugin-react#3863
What do you think?
There was a problem hiding this comment.
Ah, good point. I'm in favor.
This is an easy mistake to make, and recommending it would help beginners especially. jsx-eslint/eslint-plugin-react#3863 shows the same demand upstream.
There was a problem hiding this comment.
Should I go ahead and set it to recommended?
There was a problem hiding this comment.
♻️ Duplicate comments (1)
crates/biome_js_analyze/src/lint/nursery/no_react_object_type_as_default_prop.rs (1)
213-235:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winEarly return discards violations and skips remaining properties.
Lines 214 and 225 use
.ok()?inside the for loop, causing the entire function to returnNonewhen any property or initialiser expression fails to parse. This discards any violations already collected indefaultsand prevents checking the remaining properties.Replace
.ok()?withlet Ok(...) else { continue }to skip malformed entries whilst continuing to accumulate violations.🔧 Proposed fix
let mut defaults = Vec::new(); for property in object_pattern.properties() { - let property = property.ok()?; + let Ok(property) = property else { + continue; + }; let AnyJsObjectBindingPatternMember::JsObjectBindingPatternShorthandProperty(shorthand) = property else { continue; }; let Some(initializer) = shorthand.init() else { continue; }; - let default_value = initializer.expression().ok()?; + let Ok(default_value) = initializer.expression() else { + continue; + }; let Some(kind) = forbidden_default_kind(&default_value) else { continue; };🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/biome_js_analyze/src/lint/nursery/no_react_object_type_as_default_prop.rs` around lines 213 - 235, In the for loop that iterates through object_pattern.properties(), replace the two `.ok()?` calls with the `let Ok(...) else { continue }` pattern. Specifically, change the line that assigns property from property.ok()? to use let Ok(property) = property else { continue }, and change the line that assigns default_value from initializer.expression().ok()? to use let Ok(default_value) = initializer.expression() else { continue }. This prevents early function return on parse errors and allows the loop to continue accumulating violations in the defaults vector while skipping malformed entries.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In
`@crates/biome_js_analyze/src/lint/nursery/no_react_object_type_as_default_prop.rs`:
- Around line 213-235: In the for loop that iterates through
object_pattern.properties(), replace the two `.ok()?` calls with the `let
Ok(...) else { continue }` pattern. Specifically, change the line that assigns
property from property.ok()? to use let Ok(property) = property else { continue
}, and change the line that assigns default_value from
initializer.expression().ok()? to use let Ok(default_value) =
initializer.expression() else { continue }. This prevents early function return
on parse errors and allows the loop to continue accumulating violations in the
defaults vector while skipping malformed entries.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 23ad1c4d-e2a7-4ea2-ba5c-df362fa50476
📒 Files selected for processing (1)
crates/biome_js_analyze/src/lint/nursery/no_react_object_type_as_default_prop.rs
| "@biomejs/biome": patch | ||
| --- | ||
|
|
||
| Added the new nursery rule [`noReactObjectTypeAsDefaultProp`](https://biomejs.dev/linter/rules/no-react-object-type-as-default-prop/). |
There was a problem hiding this comment.
Could use a little more info on what the rule is about (+ perhaps an example of an invalid case)
There was a problem hiding this comment.
For nursery rules we usually keep the changeset a one-liner, right? (per this thread)
#10634 (comment)
There was a problem hiding this comment.
I think he means that it should start that way (to stay consistent with all new rule changesets). After that you can include a short summary of what the rule does
There was a problem hiding this comment.
Ah I see, I misunderstood. one-liner first, then a short summary. Fixing it now, thanks!
Merging this PR will not alter performance
Comparing Footnotes
|
…-as-default-prop # Conflicts: # crates/biome_diagnostics_categories/src/categories.rs # packages/@biomejs/backend-jsonrpc/src/workspace.ts
|
@ematipico |
|
Hi! |
| use crate::react::components::{AnyPotentialReactComponentDeclaration, ReactComponentInfo}; | ||
|
|
||
| declare_lint_rule! { | ||
| /// Disallow array, object, and function values as default props. |
There was a problem hiding this comment.
| /// Disallow array, object, and function values as default props. | |
| /// Disallow array, object, and function values as default props in React components. |
| /// Numbers, strings, and other primitives are fine, because they stay the same | ||
| /// between renders. |
There was a problem hiding this comment.
| /// Numbers, strings, and other primitives are fine, because they stay the same | |
| /// between renders. | |
| /// Numbers, strings, and other primitives are fine, because they stay the same | |
| /// among renders. |
Use "Between" when you have exactly two parties. For three or more, you use among
| kind: ForbiddenDefaultKind, | ||
| } | ||
|
|
||
| fn forbidden_default_kind(expression: &AnyJsExpression) -> Option<ForbiddenDefaultKind> { |
There was a problem hiding this comment.
It's idiomatic doing
impl ForbiddenDefaultKind {
fn from_expression(expr: &AnyJsExpression) -> Option<Self> {}
}| } | ||
| } | ||
|
|
||
| fn function_parameters(function: &AnyJsFunction) -> Option<JsParameters> { |
There was a problem hiding this comment.
You shoudl add this function here
There was a problem hiding this comment.
@ematipico
Moved it to function_ext.rs in 377f13b.
Could you take another look?
|
@biome-cookie review |
biome-cookie
left a comment
There was a problem hiding this comment.
Review Summary
Review complete. 1 finding was added inline.
Questions
-
The rule uses
severity: Severity::Error, while the similar nursery React rulenoReactStringRefsusesSeverity::Warning. WasErrorchosen intentionally here? -
Is limiting checks to top-level shorthand destructuring a deliberate departure from
eslint-plugin-react/no-object-type-as-default-prop, or should aliased and nested defaults also be reported?
Review Status
-
Scope: 2b5cd1e...2ca4c3a
-
Branch target: main
-
Changeset: add-no-react-object-type-as-default-prop.md
-
Brief: Reviewed; no blocking issues identified.
-
Validation: Static review only; no project code was run.
-
Fetch: git fetch origin 2ca4c3a
| object_pattern | ||
| .properties() | ||
| .into_iter() | ||
| .filter_map(|property| { |
There was a problem hiding this comment.
optional/completeness: Only shorthand destructuring defaults are checked
collect_forbidden_defaults intentionally narrows the rule to JsObjectBindingPatternShorthandProperty. This means aliased defaults (e.g. { a: b = {} }) and nested defaults are skipped. If this is a deliberate departure from upstream, consider adding an explicit valid test case such as function C({ a: b = {} }) {} to lock the behaviour and make the scope unambiguous to future maintainers.
There was a problem hiding this comment.
@subaru-hello, the bot found something that should be addressed. If intentional, it needs to be documented. If not, cover it.
There was a problem hiding this comment.
Not intentional, so I’ll fix it and add a test.
There was a problem hiding this comment.
Fixed in d3a0e0e and added regression tests !
Summary
Ports
no-object-type-as-default-propfromeslint-plugin-reactasnoObjectTypeAsDefaultPropin the nursery group.The rule reports reference-type defaults on destructured props of React function components. These create a new instance on every render, which can break memoization and trigger extra re-renders. Primitive defaults are fine.
It flags the following default value types:
{})[])newexpressionsSymbol()callsCloses #7656
Notes
ReactComponentInfo(name + param count), not return-value analysis. Two cases differ from upstream:export default function NotReturningJsx({ foo = {} }) {}is reported (PascalCase name).({ a = {} }, context) => {}is not reported (two params, so not a component here).memo/forwardRefwrappers, and default-exported functions.Test plan
cargo test -p biome_js_analyze -- no_object_type_as_default_propcargo run -p rules_checkjust gen-analyzerThe committed snapshots (
invalid.jsx.snap/valid.jsx.snap) show the rendered diagnostics for every flagged type.AI usage disclosure
I used an AI assistant (Claude) heavily while writing this PR — for finding the right syntax-tree APIs, writing a lot of the traversal code, fixing compile errors, and polishing the docs. I made the design decisions (how components are detected, which default types to flag, the differences from upstream), wrote the test cases, and reviewed and verified all the code.