[dx] Improve error message from InferReferenceEffects

ghstack-source-id: 06265d9676b671a5b02ca05433a219dd219be4f1
Pull Request resolved: https://github.com/facebook/react-forget/pull/2883
This commit is contained in:
Joe Savona
2024-04-22 08:14:35 -07:00
parent b11074772b
commit 896d1b0027
25 changed files with 37 additions and 35 deletions
@@ -541,8 +541,9 @@ class InferenceState {
error: {
reason,
description:
place.identifier.name !== null
? `Found mutation of ${place.identifier.name}`
place.identifier.name !== null &&
place.identifier.name.kind === "named"
? `Found mutation of \`${place.identifier.name.value}\``
: null,
loc: place.loc,
suggestions: null,
@@ -575,8 +576,9 @@ class InferenceState {
error: {
reason,
description:
place.identifier.name !== null
? `Found mutation of ${place.identifier.name}`
place.identifier.name !== null &&
place.identifier.name.kind === "named"
? `Found mutation of \`${place.identifier.name.value}\``
: null,
loc: place.loc,
suggestions: null,
@@ -1986,18 +1988,18 @@ function areArgumentsImmutableAndNonMutating(
function getWriteErrorReason(abstractValue: AbstractValue): string {
if (abstractValue.reason.has(ValueReason.Global)) {
return "Writing to a variable defined outside a component or hook is not allowed. Consider using an effect.";
return "Writing to a variable defined outside a component or hook is not allowed. Consider using an effect";
} else if (abstractValue.reason.has(ValueReason.JsxCaptured)) {
return "Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX.";
return "Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX";
} else if (abstractValue.reason.has(ValueReason.Context)) {
return `Mutating a value returned from 'useContext()', which should not be mutated.`;
return `Mutating a value returned from 'useContext()', which should not be mutated`;
} else if (abstractValue.reason.has(ValueReason.KnownReturnSignature)) {
return "Mutating a value returned from a function that should not be mutated.";
return "Mutating a value returned from a function whose return value should not be mutated";
} else if (abstractValue.reason.has(ValueReason.ReactiveFunctionArgument)) {
return "Mutating props or hook arguments is not allowed. Consider using a local variable instead.";
return "Mutating component props or hook arguments is not allowed. Consider using a local variable instead";
} else if (abstractValue.reason.has(ValueReason.State)) {
return "Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead.";
return "Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead";
} else {
return "This mutates a variable that React considers immutable.";
return "This mutates a variable that React considers immutable";
}
}
@@ -18,7 +18,7 @@ function Component(props) {
2 | const x = [];
3 | <div>{x}</div>;
> 4 | x.push(props.value);
| ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX. (4:4)
| ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX (4:4)
5 | return x;
6 | }
7 |
@@ -19,7 +19,7 @@ function Component(props) {
3 | // freeze
4 | <div>{x}</div>;
> 5 | x[0] = true;
| ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX. (5:5)
| ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX (5:5)
6 | return x;
7 | }
8 |
@@ -19,7 +19,7 @@ function Component(props) {
3 | // freeze
4 | <div>{x}</div>;
> 5 | delete x[y];
| ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX. (5:5)
| ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX (5:5)
6 | return x;
7 | }
8 |
@@ -19,7 +19,7 @@ function Component(props) {
3 | // freeze
4 | <div>{x}</div>;
> 5 | delete x.y;
| ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX. (5:5)
| ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX (5:5)
6 | return x;
7 | }
8 |
@@ -21,7 +21,7 @@ function Component(props) {
3 | const onChange = (e) => {
4 | // INVALID! should use copy-on-write and pass the new value
> 5 | x.value = e.target.value;
| ^ InvalidReact: Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead.. Found mutation of [object Object] (5:5)
| ^ InvalidReact: Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead. Found mutation of `x` (5:5)
6 | setX(x);
7 | };
8 | return <input value={x.value} onChange={onChange} />;
@@ -28,7 +28,7 @@ function Component(props) {
11 | // y is MaybeFrozen at this point, since it may alias to x
12 | // (which is the above line freezes)
> 13 | y.push(props.p2);
| ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX. (13:13)
| ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX (13:13)
14 |
15 | return <Component x={x} y={y} />;
16 | }
@@ -22,7 +22,7 @@ function Component(props) {
5 |
6 | // x is Frozen at this point
> 7 | x.push(props.p2);
| ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX. (7:7)
| ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX (7:7)
8 |
9 | return <div>{_}</div>;
10 | }
@@ -27,7 +27,7 @@ function Component(props) {
10 | // independently
11 | const onClick = () => {
> 12 | FooContext.current = true;
| ^^^^^^^^^^ InvalidReact: Mutating a value returned from 'useContext()', which should not be mutated.. Found mutation of [object Object] (12:12)
| ^^^^^^^^^^ InvalidReact: Mutating a value returned from 'useContext()', which should not be mutated. Found mutation of `FooContext` (12:12)
13 | };
14 | return <div onClick={onClick} />;
15 | }
@@ -17,7 +17,7 @@ function Component(props) {
1 | function Component(props) {
2 | const context = useContext(FooContext);
> 3 | context.value = props.value;
| ^^^^^^^ InvalidReact: Mutating a value returned from 'useContext()', which should not be mutated. (3:3)
| ^^^^^^^ InvalidReact: Mutating a value returned from 'useContext()', which should not be mutated (3:3)
4 | return context.value;
5 | }
6 |
@@ -28,7 +28,7 @@ function Component(props) {
8 | let y = x;
9 | let mutateProps = () => {
> 10 | y.foo = true;
| ^ InvalidReact: This mutates a variable that React considers immutable.. Found mutation of [object Object] (10:10)
| ^ InvalidReact: This mutates a variable that React considers immutable. Found mutation of `y` (10:10)
11 | };
12 | let mutatePropsIndirect = () => {
13 | mutateProps();
@@ -19,7 +19,7 @@ function useInvalidMutation(options) {
2 | function test() {
3 | foo(options.foo); // error should not point on this line
> 4 | options.foo = "bar";
| ^^^^^^^ InvalidReact: Mutating props or hook arguments is not allowed. Consider using a local variable instead.. Found mutation of [object Object] (4:4)
| ^^^^^^^ InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead. Found mutation of `options` (4:4)
5 | }
6 | return test;
7 | }
@@ -22,7 +22,7 @@ function Component(props) {
2 | let x = cond ? someGlobal : props.foo;
3 | const mutatePhiThatCouldBeProps = () => {
> 4 | x.y = true;
| ^ InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect.. Found mutation of [object Object] (4:4)
| ^ InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect. Found mutation of `x` (4:4)
5 | };
6 | const indirectMutateProps = () => {
7 | mutatePhiThatCouldBeProps();
@@ -21,7 +21,7 @@ function Component(props) {
1 | function Component(props) {
2 | const f = () => {
> 3 | props.value = true;
| ^^^^^ InvalidReact: Mutating props or hook arguments is not allowed. Consider using a local variable instead.. Found mutation of [object Object] (3:3)
| ^^^^^ InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead. Found mutation of `props` (3:3)
4 | };
5 | const g = () => {
6 | f();
@@ -19,7 +19,7 @@ function Component(props) {
3 | // freeze
4 | <div>{x}</div>;
> 5 | x.y = true;
| ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX. (5:5)
| ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX (5:5)
6 | return x;
7 | }
8 |
@@ -21,7 +21,7 @@ function Component(props) {
1 | function Component(props) {
2 | const mutateProps = () => {
> 3 | props.value = true;
| ^^^^^ InvalidReact: Mutating props or hook arguments is not allowed. Consider using a local variable instead.. Found mutation of [object Object] (3:3)
| ^^^^^ InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead. Found mutation of `props` (3:3)
4 | };
5 | const indirectMutateProps = () => {
6 | mutateProps();
@@ -20,7 +20,7 @@ function Foo() {
4 | const [state, setState] = useState({ foo: { bar: 3 } });
5 | const foo = state.foo;
> 6 | foo.bar = 1;
| ^^^ InvalidReact: Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead. (6:6)
| ^^^ InvalidReact: Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead (6:6)
7 | return state;
8 | }
9 |
@@ -19,7 +19,7 @@ function Foo() {
3 | function Foo() {
4 | let [state, setState] = useState({});
> 5 | state.foo = 1;
| ^^^^^ InvalidReact: Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead. (5:5)
| ^^^^^ InvalidReact: Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead (5:5)
6 | return state;
7 | }
8 |
@@ -18,7 +18,7 @@ export function ViewModeSelector(props) {
1 | export function ViewModeSelector(props) {
2 | const renderIcon = () => <AcceptIcon />;
> 3 | renderIcon.displayName = "AcceptIcon";
| ^^^^^^^^^^ InvalidReact: This mutates a variable that React considers immutable. (3:3)
| ^^^^^^^^^^ InvalidReact: This mutates a variable that React considers immutable (3:3)
4 |
5 | return <Dropdown checkableIndicator={{ children: renderIcon }} />;
6 | }
@@ -15,7 +15,7 @@ function useHook(a, b) {
```
1 | function useHook(a, b) {
> 2 | b.test = 1;
| ^ InvalidReact: Mutating props or hook arguments is not allowed. Consider using a local variable instead. (2:2)
| ^ InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead (2:2)
3 | a.test = 2;
4 | }
5 |
@@ -18,7 +18,7 @@ function Foo() {
2 |
3 | function Foo() {
> 4 | delete wat.foo;
| ^^^ InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect. (4:4)
| ^^^ InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect (4:4)
5 | return wat;
6 | }
7 |
@@ -15,7 +15,7 @@ function Foo(props) {
```
1 | function Foo(props) {
> 2 | props.test = 1;
| ^^^^^ InvalidReact: Mutating props or hook arguments is not allowed. Consider using a local variable instead. (2:2)
| ^^^^^ InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead (2:2)
3 | return null;
4 | }
5 |
@@ -20,7 +20,7 @@ function Component(props) {
3 | function Component(props) {
4 | foo(() => {
> 5 | x.a = 10;
| ^ InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect. (5:5)
| ^ InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect (5:5)
6 | x.a = 20;
7 | });
8 | }
@@ -18,7 +18,7 @@ function Foo() {
2 |
3 | function Foo() {
> 4 | wat.test = 1;
| ^^^ InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect. (4:4)
| ^^^ InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect (4:4)
5 | return wat;
6 | }
7 |
@@ -52,7 +52,7 @@ const tests: CompilerTestCases = {
errors: [
{
message:
"Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead.",
"Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead",
line: 7,
},
],