Work in progress, i'm experimenting with revamping our diagnostic infra.
Starting with a better format for representing errors, with an ability
to point ot multiple locations, along with better printing of errors. Of
course, Babel still controls the printing in the majority case so this
still needs more work.
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33751).
* #33981
* #33777
* #33767
* #33765
* #33760
* #33759
* #33758
* __->__ #33751
* #33752
* #33753
This rule currently has a few false positives, so let's disable it for
now (just in the eslint rule, it's still enabled in the compiler) while
we iterate on it.
## Summary
In the recommended configuration for `eslint-plugin-react-compiler`,
i.e. `reactCompiler.configs.recommended`, the rule is typed as `string`
rather than `eslint.Linter.RuleEntry` or anything assignable thereto,
which results in the following type error if you type check your eslint
configuration:
```
Property ''react-compiler/react-compiler'' is incompatible with index signature.
Type 'string' is not assignable to type 'RuleEntry | undefined'.
```
Simply adding a const assertion fixes the error.
## How did you test this change?
I emitted declarations for the module and confirmed that the rule is now
typed as the string literal `'error'`
Extracting portions of #32416 for easier review.
This PR contains small formatting fixes.
Co-authored-by: michael faith <michaelfaith@users.noreply.github.com>
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32590).
* #32592
* #32591
* __->__ #32590
* #32589
* #32588
---------
Co-authored-by: michael faith <michaelfaith@users.noreply.github.com>
Currently in the `compiler` workspace, we invoke esbuild directly to
build most packages (with the exception of `snap`). This has been mostly
fine, but does not allow us to do things like generate type declaration
files.
I would like #32416 to be able to consume the merged
eslint-plugin-react-compiler from source rather than via npm, and one of
the things that has come up from my exploration in that stack using the
compiler from source is that babel-plugin-react-compiler is missing type
declarations. This is primarily because React's build process uses
rollup + rollup-plugin-typescript, which runs tsc. So the merged plugin
needs to typecheck properly in order to build. An alternative might be
to migrate to something like babel with rollup instead to simply strip
types rather than typecheck before building. The minor downside of that
approach is that we would need to manually maintain a d.ts file for
eslint-plugin-react-hooks. For now I would like to see if this PR helps
us make progress rather than go for the slightly worse alternative.
[`tsup`](https://github.com/egoist/tsup) is esbuild based so build
performance is comparable. It is slower when generating d.ts files, but
it's still much faster than rollup which we used prior to esbuild. For
now, I have turned off `dts` by default, and it is only passed when
publishing on npm.
If you want to also generate d.ts files you can run `yarn build --dts`.
```
# BEFORE: build all compiler packages (esbuild)
$ time yarn build
✨ Done in 15.61s.
yarn build 13.82s user 1.54s system 96% cpu 15.842 total
# ---
# AFTER: build all compiler packages (tsup)
$ time yarn build
✨ Done in 12.39s.
yarn build 12.58s user 1.68s system 106% cpu 13.350 total
# ---
# AFTER: build all compiler packages and type declarations (tsup)
$ time yarn build --dts
✨ Done in 30.69s.
yarn build 43.57s user 3.20s system 150% cpu 31.061 total
```
I still need to test if this unblocks #32416 but this stack can be
landed independently though as we could probably just release type
declarations on npm. No one should be using the compiler directly, but
if they really wanted to, lack of type declarations would not stop them
(cf React secret internals).
Note that I still kept esbuild as we still use it directly for forgive.
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32550).
* #32551
* __->__ #32550
## Summary
This change fixes a gap in the plugin's support of eslint v9. In one
place that it's using the `SourceCode` api, it's correctly considering
v9's api. But in the other place where `SourceCode` is used, it's only
using the legacy api, which was removed in v9.
Reverts facebook/react#31629
`@babel/plugin-proposal-private-methods` is not compatible with
`@babel/traverse` versions < 7.25 (see
https://github.com/babel/babel/issues/16851). Internally we have
partners that use a less modern babel version, and we expect this to be
an issue for older codebases in OSS as well.
Compiler bailout diagnostics should now highlight only the first line of
the source location span.
(Resubmission of #30423 which was reverted due to invalid column
number.)
This reverts commit b34b750729.
This hack doesn't play well internally so I'm reverting this for now
(but keeping the compilationMode override). I'll audit the locations we
report later and try to make them more accurate so we won't need this
workaround.
ghstack-source-id: b6be29c11d
Pull Request resolved: https://github.com/facebook/react/pull/30792
This PR updates the eslint plugin to report unused opt out directives.
One of the downsides of the opt out directive is that it opts the
component/hook out of compilation forever, even if the underlying issue
was fixed in product code or fixed in the compiler.
ghstack-source-id: 81deb5c11b
Pull Request resolved: https://github.com/facebook/react/pull/30721
Summary:
The change earlier in this stack makes it less safe to have ref enforcement disabled. This diff enables it by default.
ghstack-source-id: d3ab5f1b28b7aed0f0d6d69547bb638a1e326b66
Pull Request resolved: https://github.com/facebook/react/pull/30716
Updates the prettier config to format all `.ts` and `.tsx` files in the
repo using the existing defaults and removing overrides.
The first commit in this PR contains the config changes, the second is
just the result of running `yarn prettier-all`.
---
Adding an experimental / donotuse flag for small Meta internal usecase
ghstack-source-id: 908ef1e150c9fef1347616c9c4dc6bf3316900b0
Pull Request resolved: https://github.com/facebook/react/pull/30342
---
* panicThreshold: `all_errors` -> `none`
* inject an error logger through compiler config (instead of using exceptions)
We currently report at most one lint warning per file, this lets us exhaustively report all available ones (see new
test fixture for example)
ghstack-source-id: 5299315574d11929efc39ee8f6033e3035d1e378
Pull Request resolved: https://github.com/facebook/react/pull/30336
Eslint rules should never throw, so if we fail to parse with Babel or
Hermes, we should just ignore the error. This should fix issues such as
trying to run the eslint rule on non tsx|ts|jsx|js files, Hermes parser
not supporting certain JS syntax, etc.
I didn't add a test for this as our eslint-rule-tester config uses
hermes-eslint parser, so it wasn't possible to add a top level await as
it would crash hermes-eslint before our rule was triggered. Similarly I
couldn't add a test for non-JS files as it would not be parseable by
hermes-eslint.
Fixes#29107
ghstack-source-id: 60afcdb89ab4a8d2e4697cc50c5490803e7cbeac
Pull Request resolved: https://github.com/facebook/react/pull/29631
user's pipeline
When the user app has a babel.config file that is missing the compiler,
strange things happen as babel does some strange merging of options from
the user's config and in various callsites like in our eslint rule and
healthcheck script. To minimize odd behavior, we default to not reading
the user's babel.config
Fixes#29135
ghstack-source-id: d6fdc43c5c
Pull Request resolved: https://github.com/facebook/react/pull/29211
<!--
Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.
Before submitting a pull request, please make sure the following is
done:
1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn test --debug --watch TestName`,
open `chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
10. If you haven't already, complete the CLA.
Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->
## Summary
Use `filename` instead of `context.filename` in eslint compiler.
The problem is that in `react-native` + `typescript` project the context
may not have `filename`:
<img width="384" alt="image"
src="https://github.com/facebook/react/assets/22820318/e5d184fa-5ac9-4512-96b9-644baa3d5f25">
And eslint will crash with:
```bash
TypeError: Error while loading rule 'react-compiler/react-compiler': Cannot read properties of undefined (reading 'endsWith')
```
But in fact we already derive `filename` variable earlier so we can
simply reuse the variable (I guess).
## How did you test this change?
- add `eslint` plugin to RN project;
- run eslint
Previously we would attempt to parse code in the eslint plugin with the
HermesParser first as it can handle some TS syntax. However, this was
leading to a mis-parse of React hook calls with type params (eg,
`useRef<null>()` as a BinaryExpression rather than a CallExpression with
a type param. This triggered our validation that Hooks should not be
used as normal values.
To fix this, we now try to parse with the babel parser (with TS support)
for filenames that end with ts/tsx, and fallback to HermesParser for
regular JS files.
ghstack-source-id: 5b7231031c
Pull Request resolved: https://github.com/facebook/react/pull/29081
During the demo I might show an example of fixing a
CannotPreserveMemoization error. But I don't want to make that
reportable by default, so this PR allows configuration like so
```js
module.exports = {
root: true,
plugins: [
'eslint-plugin-react-compiler',
],
rules: {
'react-compiler/react-compiler': [
'error', {
reportableLevels: new Set([
'InvalidJs',
'InvalidReact',
'CannotPreserveMemoization'
])
}
]
}
}
```
ghstack-source-id: 984c6d3cb7e19c8fea2bb88108dd26335c031573
Pull Request resolved: https://github.com/facebook/react-forget/pull/2936
We control what gets reported via another function anyway so it's better
to raise everything at the compiler config level. This lets us configure
what level of diagnostic is reportable later
ghstack-source-id: 996d3cbb8d8f3e1bbe943210b8d633420e0f3f3b
Pull Request resolved: https://github.com/facebook/react-forget/pull/2935
Exporting the hermes parser breaks the playground
as the hermes parser can not work in the browser.
No one is using this directly anyway -- snap and
others bundle hermes parser on their own, so,
let's remove it.
ghstack-source-id: d448c346eb137f8ba6ada4ad113e41a90b29baff
Pull Request resolved: https://github.com/facebook/react-forget/pull/2890
Fixes a tiny inconsistency with compiler options where one was all
uppercase and one all lowercase by normalizing to lowercase regardless
of the casing of the user's config.
ghstack-source-id: fe60a3259de89a1b3fdd7475950e16e96cc57f6b
Pull Request resolved: https://github.com/facebook/react-forget/pull/2832
This adds a new category of error where the compiler cannot preserve
memoization exactly how as it was originally authored. We're adding a
new category here because it's not an actionable error, and allows us to
more specifically control whether it's reportable or not.
ghstack-source-id: 9693cd42ca64b980248c6202091bdd4c827e1cd4
Pull Request resolved: https://github.com/facebook/react-forget/pull/2824
First attempt at making the linter work with advanced TypeScript syntax
Falls back to the babel parser for some advanced syntax like string template
syntax.
This is pretty hacky as it doesn't take in any parsing options that are
configured for the outer ESLint parser, not sure how that could be handled.