@samitouri / QOS-React-2 / commits / f850d3b265

Improve remaining InvalidReact error messages

Lauren Tan committed Jun 28, 2023 at 11:43 UTC f850d3b26524db907f51592dcdf5d811e6aefc2e
29 files changed +70 -50
compiler/forget/packages/babel-plugin-react-forget/src/HIR/BuildHIR.ts
+2 -2
@@ -2551,9 +2551,9 @@ function lowerIdentifierForAssignment(
2551 if (kind === InstructionKind.Reassign) {
2552 // Trying to reassign a global is not allowed
2553 builder.errors.push({
2554 - reason: `(BuildHIR::lowerAssignment) Assigning to an identifier defined outside the function scope is not supported.`,
2554 + reason: `This reassigns a variable which was not defined inside of the component. Components should be pure and side-effect free. If this variable is used in rendering, use useState instead. (https://react.dev/learn/keeping-components-pure)`,
2555 severity: ErrorSeverity.InvalidReact,
2556 - loc: path.node.loc ?? null,
2556 + loc: path.parentPath.node.loc ?? null,
2557 suggestions: null,
2558 });
2559 } else {
compiler/forget/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts
+10 -10
@@ -25,11 +25,9 @@ import {
25 } from "../HIR/HIR";
26 import { FunctionSignature } from "../HIR/ObjectShape";
27 import {
28 - printIdentifier,
28 printMixedHIR,
29 printPlace,
30 printSourceLocation,
32 - printType,
31 } from "../HIR/PrintHIR";
32 import {
33 eachInstructionOperand,
@@ -324,10 +322,11 @@ class InferenceState {
322 effect = Effect.Mutate;
323 } else {
324 CompilerError.invalidReact({
327 - reason: `InferReferenceEffects: inferred mutation of known immutable value`,
328 - description: `Found mutation of ${printIdentifier(
329 - place.identifier
330 - )}${printType(place.identifier.type)} (${valueKind})`,
325 + reason: `This mutates a variable after it was passed to React, which means that React cannot observe changes to it`,
326 + description:
327 + place.identifier.name !== null
328 + ? `Found mutation of ${place.identifier.name}`
329 + : null,
330 loc: place.loc,
331 suggestions: null,
332 });
@@ -340,10 +339,11 @@ class InferenceState {
339 valueKind !== ValueKind.Context
340 ) {
341 CompilerError.invalidReact({
343 - reason: `InferReferenceEffects: inferred mutation of known immutable value`,
344 - description: `Found mutation of ${printIdentifier(
345 - place.identifier
346 - )}${printType(place.identifier.type)} (${valueKind})`,
342 + reason: `This mutates a variable after it was passed to React, which means that React cannot observe changes to it`,
343 + description:
344 + place.identifier.name !== null
345 + ? `Found mutation of ${place.identifier.name}`
346 + : null,
347 loc: place.loc,
348 suggestions: null,
349 });
compiler/forget/packages/babel-plugin-react-forget/src/Validation/ValidateFrozenLambdas.ts
+7 -2
@@ -132,11 +132,16 @@ function validateOperand(
132 state.temporaries.get(operand.identifier.id) ?? operand.identifier.id;
133 const lambda = state.lambdas.get(operandId);
134 if (lambda !== undefined) {
135 + // TODO: these seem to always be null, we should try to preserve original names from source
136 + const description =
137 + lambda.name !== null && operand.identifier.name !== null
138 + ? `\`${lambda.name}\` is a function that may mutate \`${operand.identifier.name}\`. If you must mutate \`${operand.identifier.name}\` try using a React API like useState and use its setter function instead`
139 + : null;
140 return new CompilerErrorDetail({
136 - description: null,
141 + description,
142 loc: typeof operand.loc !== "symbol" ? operand.loc : null,
143 reason:
139 - "Cannot use a mutable function where an immutable value is expected",
144 + "This mutates a variable that is managed by React, where an immutable value or a function was expected",
145 severity: ErrorSeverity.InvalidReact,
146 suggestions: null,
147 });
compiler/forget/packages/babel-plugin-react-forget/src/Validation/ValidateNoRefAccesInRender.ts
+2 -2
@@ -107,7 +107,7 @@ function validateNonRefValue(error: CompilerError, operand: Place): void {
107 description: `Cannot access ref value at ${printPlace(operand)}`,
108 loc: typeof operand.loc !== "symbol" ? operand.loc : null,
109 reason:
110 - "Ref values (the `current` property) may not be accessed during render",
110 + "Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)",
111 severity: ErrorSeverity.InvalidReact,
112 suggestions: null,
113 })
@@ -123,7 +123,7 @@ function validateNonRefObject(error: CompilerError, operand: Place): void {
123 description: `Cannot access ref object at ${printPlace(operand)}`,
124 loc: typeof operand.loc !== "symbol" ? operand.loc : null,
125 reason:
126 - "Ref values may not be passed to functions because they could read the ref value (`current` property) during render",
126 + "Ref values may not be passed to functions because they could read the ref value (`current` property) during render. (https://react.dev/reference/react/useRef)",
127 severity: ErrorSeverity.InvalidReact,
128 suggestions: null,
129 })
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-access-ref-during-render.expect.md
+1 -1
@@ -15,7 +15,7 @@ function Component(props) {
15 ## Error
16
17 ```
18 -[ReactForget] InvalidReact: Ref values (the `current` property) may not be accessed during render. Cannot access ref value at freeze $22:TObject<BuiltInRefValue> (5:5)
18 +[ReactForget] InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef). Cannot access ref value at freeze $22:TObject<BuiltInRefValue> (5:5)
19 ```
20
21
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-array-push-frozen.expect.md
+1 -1
@@ -15,7 +15,7 @@ function Component(props) {
15 ## Error
16
17 ```
18 -[ReactForget] InvalidReact: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $19:TObject<BuiltInArray> (frozen) (4:4)
18 +[ReactForget] InvalidReact: This mutates a variable after it was passed to React, which means that React cannot observe changes to it (4:4)
19 ```
20
21
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-capture-func-passed-to-jsx.expect.md
+1 -1
@@ -20,7 +20,7 @@ function component(a, b) {
20 ## Error
21
22 ```
23 -[ReactForget] InvalidReact: Cannot use a mutable function where an immutable value is expected (8:8)
23 +[ReactForget] InvalidReact: This mutates a variable that is managed by React, where an immutable value or a function was expected (8:8)
24 ```
25
26
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-computed-store-to-frozen-value.expect.md
+1 -1
@@ -16,7 +16,7 @@ function Component(props) {
16 ## Error
17
18 ```
19 -[ReactForget] InvalidReact: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $21 (frozen) (5:5)
19 +[ReactForget] InvalidReact: This mutates a variable after it was passed to React, which means that React cannot observe changes to it (5:5)
20 ```
21
22
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-delete-computed-property-of-frozen-value.expect.md
+1 -1
@@ -16,7 +16,7 @@ function Component(props) {
16 ## Error
17
18 ```
19 -[ReactForget] InvalidReact: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $19 (frozen) (5:5)
19 +[ReactForget] InvalidReact: This mutates a variable after it was passed to React, which means that React cannot observe changes to it (5:5)
20 ```
21
22
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-delete-property-of-frozen-value.expect.md
+1 -1
@@ -16,7 +16,7 @@ function Component(props) {
16 ## Error
17
18 ```
19 -[ReactForget] InvalidReact: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $18 (frozen) (5:5)
19 +[ReactForget] InvalidReact: This mutates a variable after it was passed to React, which means that React cannot observe changes to it (5:5)
20 ```
21
22
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-destructure-assignment-to-global.expect.md
+1 -1
@@ -13,7 +13,7 @@ function useFoo(props) {
13 ## Error
14
15 ```
16 -[ReactForget] InvalidReact: (BuildHIR::lowerAssignment) Assigning to an identifier defined outside the function scope is not supported. (2:2)
16 +[ReactForget] InvalidReact: This reassigns a variable which was not defined inside of the component. Components should be pure and side-effect free. If this variable is used in rendering, use useState instead. (https://react.dev/learn/keeping-components-pure) (2:2)
17 ```
18
19
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-destructure-to-local-global-variables.expect.md
+1 -1
@@ -15,7 +15,7 @@ function Component(props) {
15 ## Error
16
17 ```
18 -[ReactForget] InvalidReact: (BuildHIR::lowerAssignment) Assigning to an identifier defined outside the function scope is not supported. (3:3)
18 +[ReactForget] InvalidReact: This reassigns a variable which was not defined inside of the component. Components should be pure and side-effect free. If this variable is used in rendering, use useState instead. (https://react.dev/learn/keeping-components-pure) (3:3)
19 ```
20
21
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-conditionally-mutable-lambda.expect.md
+1 -1
@@ -25,7 +25,7 @@ function Component(props) {
25 ## Error
26
27 ```
28 -[ReactForget] InvalidReact: Cannot use a mutable function where an immutable value is expected (15:15)
28 +[ReactForget] InvalidReact: This mutates a variable that is managed by React, where an immutable value or a function was expected (15:15)
29 ```
30
31
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-mutable-lambda-mutate-local.expect.md
+1 -1
@@ -18,7 +18,7 @@ function Component(props) {
18 ## Error
19
20 ```
21 -[ReactForget] InvalidReact: Cannot use a mutable function where an immutable value is expected (8:8)
21 +[ReactForget] InvalidReact: This mutates a variable that is managed by React, where an immutable value or a function was expected (8:8)
22 ```
23
24
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-mutable-lambda-reassign-local.expect.md
+1 -1
@@ -16,7 +16,7 @@ function Component(props) {
16 ## Error
17
18 ```
19 -[ReactForget] InvalidReact: Cannot use a mutable function where an immutable value is expected (6:6)
19 +[ReactForget] InvalidReact: This mutates a variable that is managed by React, where an immutable value or a function was expected (6:6)
20 ```
21
22
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-function-expression-mutates-immutable-value.expect.md
+1 -1
@@ -18,7 +18,7 @@ function Component(props) {
18 ## Error
19
20 ```
21 -[ReactForget] InvalidReact: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $39 (frozen) (5:5)
21 +[ReactForget] InvalidReact: This mutates a variable after it was passed to React, which means that React cannot observe changes to it (5:5)
22 ```
23
24
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-mutate-after-aliased-freeze.expect.md
+1 -1
@@ -25,7 +25,7 @@ function Component(props) {
25 ## Error
26
27 ```
28 -[ReactForget] InvalidReact: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $44:TObject<BuiltInArray> (frozen) (13:13)
28 +[ReactForget] InvalidReact: This mutates a variable after it was passed to React, which means that React cannot observe changes to it (13:13)
29 ```
30
31
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-mutate-after-freeze.expect.md
+1 -1
@@ -19,7 +19,7 @@ function Component(props) {
19 ## Error
20
21 ```
22 -[ReactForget] InvalidReact: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $26:TObject<BuiltInArray> (frozen) (7:7)
22 +[ReactForget] InvalidReact: This mutates a variable after it was passed to React, which means that React cannot observe changes to it (7:7)
23 ```
24
25
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-pass-ref-to-function.expect.md
+1 -1
@@ -14,7 +14,7 @@ function Component(props) {
14 ## Error
15
16 ```
17 -[ReactForget] InvalidReact: Ref values may not be passed to functions because they could read the ref value (`current` property) during render. Cannot access ref object at mutate? $21[6:8]:TObject<BuiltInUseRefId> (3:3)
17 +[ReactForget] InvalidReact: Ref values may not be passed to functions because they could read the ref value (`current` property) during render. (https://react.dev/reference/react/useRef). Cannot access ref object at mutate? $21[6:8]:TObject<BuiltInUseRefId> (3:3)
18 ```
19
20
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-property-store-to-frozen-value.expect.md
+1 -1
@@ -16,7 +16,7 @@ function Component(props) {
16 ## Error
17
18 ```
19 -[ReactForget] InvalidReact: InferReferenceEffects: inferred mutation of known immutable value. Found mutation of $20 (frozen) (5:5)
19 +[ReactForget] InvalidReact: This mutates a variable after it was passed to React, which means that React cannot observe changes to it (5:5)
20 ```
21
22
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-in-callback-invoked-during-render.expect.md
+1 -1
@@ -18,7 +18,7 @@ function Component(props) {
18 ## Error
19
20 ```
21 -[ReactForget] InvalidReact: Ref values (the `current` property) may not be accessed during render. Cannot access ref value at capture $42[6:16]:TObject<BuiltInRefValue> (5:5)
21 +[ReactForget] InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef). Cannot access ref value at capture $42[6:16]:TObject<BuiltInRefValue> (5:5)
22 ```
23
24
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-value-as-props.expect.md
+1 -1
@@ -13,7 +13,7 @@ function Component(props) {
13 ## Error
14
15 ```
16 -[ReactForget] InvalidReact: Ref values (the `current` property) may not be accessed during render. Cannot access ref value at freeze $19:TObject<BuiltInRefValue> (3:3)
16 +[ReactForget] InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef). Cannot access ref value at freeze $19:TObject<BuiltInRefValue> (3:3)
17 ```
18
19
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-set-and-read-ref-during-render.expect.md
+2 -2
@@ -14,9 +14,9 @@ function Component(props) {
14 ## Error
15
16 ```
17 -[ReactForget] InvalidReact: Ref values may not be passed to functions because they could read the ref value (`current` property) during render. Cannot access ref object at store $21[7:9]:TObject<BuiltInUseRefId> (3:3)
17 +[ReactForget] InvalidReact: Ref values may not be passed to functions because they could read the ref value (`current` property) during render. (https://react.dev/reference/react/useRef). Cannot access ref object at store $21[7:9]:TObject<BuiltInUseRefId> (3:3)
18
19 -[ReactForget] InvalidReact: Ref values (the `current` property) may not be accessed during render. Cannot access ref value at freeze $24:TObject<BuiltInRefValue> (4:4)
19 +[ReactForget] InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef). Cannot access ref value at freeze $24:TObject<BuiltInRefValue> (4:4)
20 ```
21
22
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-use-ref-added-to-dep-without-type-info.expect.md
+1 -1
@@ -21,7 +21,7 @@ function Foo({ a }) {
21 ## Error
22
23 ```
24 -[ReactForget] InvalidReact: Ref values may not be passed to functions because they could read the ref value (`current` property) during render. Cannot access ref object at capture $29:TObject<BuiltInUseRefId> (4:4)
24 +[ReactForget] InvalidReact: Ref values may not be passed to functions because they could read the ref value (`current` property) during render. (https://react.dev/reference/react/useRef). Cannot access ref object at capture $29:TObject<BuiltInUseRefId> (4:4)
25 ```
26
27
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.reassignment-to-global.expect.md new
+22
@@ -0,0 +1,22 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function Component() {
6 + // Cannot assign to globals
7 + someUnknownGlobal = true;
8 + moduleLocal = true;
9 +}
10 +
11 +```
12 +
13 +
14 +## Error
15 +
16 +```
17 +[ReactForget] InvalidReact: This reassigns a variable which was not defined inside of the component. Components should be pure and side-effect free. If this variable is used in rendering, use useState instead. (https://react.dev/learn/keeping-components-pure) (3:3)
18 +
19 +[ReactForget] InvalidReact: This reassigns a variable which was not defined inside of the component. Components should be pure and side-effect free. If this variable is used in rendering, use useState instead. (https://react.dev/learn/keeping-components-pure) (4:4)
20 +```
21 +
22 +
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.reassignment-to-global.js new
+5
@@ -0,0 +1,5 @@
1 +function Component() {
2 + // Cannot assign to globals
3 + someUnknownGlobal = true;
4 + moduleLocal = true;
5 +}
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-kitchensink.expect.md
-8
@@ -64,10 +64,6 @@ function foo([a, b], { c, d, e = "e" }, f = "f", ...args) {
64 }
65 }
66
67 - // Cannot assign to globals
68 - someUnknownGlobal = true;
69 - moduleLocal = true;
70 -
67 function component(a) {
68 // Add support for function declarations once we support `var` hoisting.
69 function t() {}
@@ -126,10 +122,6 @@ let moduleLocal = false;
122 [ReactForget] Todo: (BuildHIR::node.lowerReorderableExpression) Expression type 'CallExpression' cannot be safely reordered (55:55)
123
124 [ReactForget] Todo: (BuildHIR::node.lowerReorderableExpression) Expression type 'BinaryExpression' cannot be safely reordered (53:53)
129 -
130 -[ReactForget] InvalidReact: (BuildHIR::lowerAssignment) Assigning to an identifier defined outside the function scope is not supported. (64:64)
131 -
132 -[ReactForget] InvalidReact: (BuildHIR::lowerAssignment) Assigning to an identifier defined outside the function scope is not supported. (65:65)
125 ```
126
127
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-kitchensink.js
-4
@@ -60,10 +60,6 @@ function foo([a, b], { c, d, e = "e" }, f = "f", ...args) {
60 }
61 }
62
63 - // Cannot assign to globals
64 - someUnknownGlobal = true;
65 - moduleLocal = true;
66 -
63 function component(a) {
64 // Add support for function declarations once we support `var` hoisting.
65 function t() {}
compiler/forget/packages/eslint-plugin-react-forget/__tests__/ReactForgetDiagnostics-test.ts
+1 -1
@@ -72,7 +72,7 @@ const tests: ForgetTestCases = {
72 errors: [
73 {
74 message:
75 - "[ReactForget] InvalidReact: Ref values (the `current` property) may not be accessed during render. Cannot access ref value at freeze $22:TObject<BuiltInRefValue> (6:6)",
75 + "[ReactForget] InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef). Cannot access ref value at freeze $22:TObject<BuiltInRefValue> (6:6)",
76 line: 6,
77 column: 10,
78 endColumn: 15,