Skip to content

Commit 2caa85b

Browse files
committed
[compiler] Add support for diagnostic hints
Hints are meant as additional information to present to the developer about an error. The first use-case here is for the suggestion to name refs with "-Ref" if we encounter a mutation that looks like it might be a ref. The original error printing used a second error detail which printed the source code twice, a hint with just extra text is less noisy.
1 parent 61b605f commit 2caa85b

File tree

3 files changed

+24
-18
lines changed

3 files changed

+24
-18
lines changed

compiler/packages/babel-plugin-react-compiler/src/CompilerError.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,15 @@ export type CompilerDiagnosticDetail =
5858
/**
5959
* A/the source of the error
6060
*/
61-
{
62-
kind: 'error';
63-
loc: SourceLocation | null;
64-
message: string;
65-
};
61+
| {
62+
kind: 'error';
63+
loc: SourceLocation | null;
64+
message: string;
65+
}
66+
| {
67+
kind: 'hint';
68+
message: string;
69+
};
6670

6771
export enum CompilerSuggestionOperation {
6872
InsertBefore,
@@ -134,7 +138,12 @@ export class CompilerDiagnostic {
134138
}
135139

136140
primaryLocation(): SourceLocation | null {
137-
return this.options.details.filter(d => d.kind === 'error')[0]?.loc ?? null;
141+
const firstErrorDetail = this.options.details.filter(
142+
d => d.kind === 'error',
143+
)[0];
144+
return firstErrorDetail != null && firstErrorDetail.kind === 'error'
145+
? firstErrorDetail.loc
146+
: null;
138147
}
139148

140149
printErrorMessage(source: string, options: PrintErrorMessageOptions): string {
@@ -167,9 +176,14 @@ export class CompilerDiagnostic {
167176
buffer.push(codeFrame);
168177
break;
169178
}
179+
case 'hint': {
180+
buffer.push('\n\n');
181+
buffer.push(detail.message);
182+
break;
183+
}
170184
default: {
171185
assertExhaustive(
172-
detail.kind,
186+
detail,
173187
`Unexpected detail kind ${(detail as any).kind}`,
174188
);
175189
}

compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutationAliasingEffects.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -471,8 +471,7 @@ function applySignature(
471471
effect.reason?.kind === 'AssignCurrentProperty'
472472
) {
473473
diagnostic.withDetail({
474-
kind: 'error',
475-
loc: effect.value.loc,
474+
kind: 'hint',
476475
message: `Hint: If this value is a Ref (value returned by \`useRef()\`), rename the variable to end in "Ref".`,
477476
});
478477
}
@@ -1096,8 +1095,7 @@ function applyEffect(
10961095
effect.reason?.kind === 'AssignCurrentProperty'
10971096
) {
10981097
diagnostic.withDetail({
1099-
kind: 'error',
1100-
loc: effect.value.loc,
1098+
kind: 'hint',
11011099
message: `Hint: If this value is a Ref (value returned by \`useRef()\`), rename the variable to end in "Ref".`,
11021100
});
11031101
}

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-assing-to-ref-current-in-render.expect.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,7 @@ Modifying a value returned from a hook is not allowed. Consider moving the modif
3030
7 | }
3131
8 |
3232
33-
3 | component Foo() {
34-
4 | const foo = useFoo();
35-
> 5 | foo.current = true;
36-
| ^^^ Hint: If this value is a Ref (value returned by `useRef()`), rename the variable to end in "Ref".
37-
6 | return <div />;
38-
7 | }
39-
8 |
33+
Hint: If this value is a Ref (value returned by `useRef()`), rename the variable to end in "Ref".
4034
```
4135
4236

0 commit comments

Comments
 (0)