# What This PR Does
Massively improves all `react-perf` rules
- feat: handle new objects/etc assigned to variables
```tsx
const Foo = () => {
const x = { foo: 'bar' } // <- now reports this new object
return <Bar x={x} />
}
```
- feat: handle new objects/etc in binding patterns
```tsx
const Foo = ({ x = [] }) => {
// ^^^^^^ now reports this new array
return <Bar x={x} />
}
```
-feat: nice and descriptive labels for new objects/etc assigned to intermediate variables
```
⚠ eslint-plugin-react-perf(jsx-no-new-object-as-prop): JSX attribute values should not contain objects created in the same scope.
╭─[jsx_no_new_object_as_prop.tsx:1:27]
1 │ const Foo = () => { const x = {}; return <Bar x={x} /> }
· ┬ ─┬ ┬
· │ │ ╰── And used here
· │ ╰── And assigned a new value here
· ╰── The prop was declared here
╰────
help: simplify props or memoize props in the parent component (https://react.dev/reference/react/memo#my-component-rerenders-when-a-prop-is-an-object-or-array).
```
- feat: consider `Object.assign()` and `Object.create()` as a new object
- feat: consider `arr.[map, filter, concat]` as a new array
- refactor: move shared implementation code to `ReactPerfRule` in `oxc_linter::utils::react_perf`
Consider the following code:
```tsx
import { FC } from 'react'
import { SvgIcon } from '@mui/material'
const StyledIcon = <SvgIcon sx={{ padding: 1, color: '#ff0000' }} />
// reported violation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
export const MyComponent: FC = () => {
return (
<div>
{StyledIcon}
{/* ... */}
</div>
)
}
```
This should not be a violation since the JSX is pre-computed and re-used, which
does not break React's `Object.is()` checks.
### TL;DR
Added a `should_run` function to multiple lint rules to determine if a rule should be executed based on the source type. This change optimizes the linting process by avoiding unnecessary rule checks.
### What changed?
1. **New Method**: Introduced the `should_run` method in the `Rule` trait.
2. **Implementation**: Implemented the `should_run` method for various lint rules, particularly those related to React and TypeScript.
3. **Usage**: Updated the `Linter` to use the `should_run` method to filter rules before execution.
4. **Macro Update**: Modified the `declare_all_lint_rules` macro to incorporate the `should_run` method.
### How to test?
1. Run the linter on a project containing React and TypeScript files.
2. Verify that only relevant rules are executed based on the file type (e.g., JSX rules for React files).
### Why make this change?
This change improves the performance of the linter by ensuring that only applicable rules are run for a given file type, reducing unnecessary computation and potential false positives.
---
> This PR is (unfortunately) quite large, but all changes are needed in tandem for this to work properly.
## What This PR Does
Updates the linter to populate diagnostics reported by rules with error codes statically derived from `RuleMeta` + `RuleEnum`.
Doing so required changing how we handle vitest rules. I know @mysterven was hoping to refactor that part of the code, and I think this approach is an improvement (but could probably be cleaned up further).
## Changes
### 1. Auto-Populate Error Codes
`LintContext` now sets an error code scope + error code number for diagnostics reported by lint rules. `LintContext` will not clobber existing codes set by rules, allowing for rule-specific override behavior (e.g. to use `eslint-plugin-react-hooks` as an error scope).
In order to accomplish this, I had to update every diagnostic factory for every rule. While doing this I found some incorrect error messages, or messages that could be easily improved. This is where a large majority of the snapshot diffs come from. Additionally, I was able to reduce string allocations from `format!` usages in diagnostic factories, especially within jest rules.
### 2. Framework and Library Detection
This PR adds `FrameworkFlags`, which specify what (if any) set of libraries and frameworks are being used by a project and/or file. They are passed in two ways:
1. `LintOptions` can specify a set of `framework_hints` that apply to the entire target codebase. Right now these are always empty, but I'm thinking in the future we could sniff `package.json`. It may be helpful for enabling/disabling default rules.
2. When `Linter` gets run on a file, framework information is sniffed from the `LintContext`. Right now, we are only checking for `vitest` imports in `ModuleRecord` and test path prefixes from `source_path`. It may be useful to do something similar for React/NextJS rules in the future. I know that [next/no-html-link-for-pages](https://nextjs.org/docs/messages/no-html-link-for-pages) could benefit greatly from this.
Added rule for https://typescript-eslint.io/rules/no-extraneous-class/
Also, I chose to make the match the node against the class and derive
the body from the node, rather than matching against the body and using
the context to go back up to the parent class node as in the original
source.
This tweaks the `no-dupe-keys` lint in order to try to optimize it.
The lints reliably shows up in both CPU and memory profiling,
due to the cost of allocating/growing the hashmap and hashing into it.
This PR tries to tackle both by skipping trivial cases and by
pre-allocating a larger hashmap.
We have a strange workaround for `visit_function` where we pass in `ScopeFlags`, to support creating the scope inside `Function`, but setting different flags for `MethodDefinition`s.
Previously `visit_function` took `Option<ScopeFlags>` and then did `flags.unwrap_or(ScopeFlags::empty()) | ScopeFlags::Function` to it. Personally, I found this confusing. When I was looking at `MethodDefinition`, I was wondering "It's a function, why doesn't it set Function flag too?"
This changes makes it more explicit and clear what `ScopeFlags` everything has.
```ts
class Klass <T> extends Root <R> {}
// ^^^^^ ^^^ ^^^^ ^^^ ^^
// id type_paramter super_class super_type_parameters body
```
I reorder fields according to the order above
The class scope is not defined in the spec. But we need to create a scope for `class` to store `TypeParamters`
Part of #4187.
Adds `CompositeFix::None`, which enables fixer functions to decide not to fix some code.
While I was in the area, I took the liberty of adding some doc comments.
Resolves#3870
Hey there, thought I'd give this a try as it's tagged "good first issue"
:) Let me know if there's anything that needs to change
Another part of the code also needs modification:
https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/rules/no-useless-undefined.js#L95
I tried to modify it. If there are any issues with these modifications,
please let me know.
```
fn is_has_function_return_type(node: &AstNode, ctx: &LintContext<'_>) -> bool {
let Some(parent_node) = ctx.nodes().parent_node(node.id()) else {
return false;
};
match parent_node.kind() {
AstKind::ArrowFunctionExpression(arrow_func_express) => {
arrow_func_express.return_type.is_some()
}
AstKind::Function(func) => func.return_type.is_some(),
_ => is_has_function_return_type(parent_node, ctx),
}
}
```
close: #4186
CatchClause has two scopes. The first one is `CatchClause`, which will add a `CatchParameter` to it. The second one is `Block`, which will add binding that declares in the current block scope.
The spec has a syntax error about `CatchParameter`
- It is a Syntax Error if any element of the BoundNames of CatchParameter also occurs in the LexicallyDeclaredNames of Block.