Skip to content

Commit 13c4892

Browse files
committed
[compiler] Cleanup diagnostic messages
Minor sytlistic cleanup
1 parent c5a10aa commit 13c4892

File tree

317 files changed

+614
-652
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

317 files changed

+614
-652
lines changed

compiler/packages/babel-plugin-react-compiler/src/Babel/BabelPlugin.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,9 @@ export default function BabelPluginReactCompiler(
8484
}
8585
} catch (e) {
8686
if (e instanceof CompilerError) {
87-
throw new Error(e.printErrorMessage(pass.file.code));
87+
throw new Error(
88+
e.printErrorMessage(pass.file.code, {eslint: false}),
89+
);
8890
}
8991
throw e;
9092
}

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

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,14 @@ export type CompilerErrorDetailOptions = {
9393
suggestions?: Array<CompilerSuggestion> | null | undefined;
9494
};
9595

96+
export type PrintErrorMessageOptions = {
97+
/**
98+
* ESLint uses 1-indexed columns and prints one error at a time
99+
* So it doesn't require the "Found # error(s)" text
100+
*/
101+
eslint: boolean;
102+
};
103+
96104
export class CompilerDiagnostic {
97105
options: CompilerDiagnosticOptions;
98106

@@ -128,7 +136,7 @@ export class CompilerDiagnostic {
128136
return this.options.details.filter(d => d.kind === 'error')[0]?.loc ?? null;
129137
}
130138

131-
printErrorMessage(source: string): string {
139+
printErrorMessage(source: string, options: PrintErrorMessageOptions): string {
132140
const buffer = [
133141
printErrorSummary(this.severity, this.category),
134142
'\n\n',
@@ -162,9 +170,14 @@ export class CompilerDiagnostic {
162170
} catch (e) {
163171
codeFrame = detail.message;
164172
}
165-
buffer.push(
166-
`\n\n${loc.filename}:${loc.start.line}:${loc.start.column}\n`,
167-
);
173+
buffer.push('\n\n');
174+
if (loc.filename != null) {
175+
const line = loc.start.line;
176+
const column = options.eslint
177+
? loc.start.column + 1
178+
: loc.start.column;
179+
buffer.push(`${loc.filename}:${line}:${column}\n`);
180+
}
168181
buffer.push(codeFrame);
169182
break;
170183
}
@@ -223,7 +236,7 @@ export class CompilerErrorDetail {
223236
return this.loc;
224237
}
225238

226-
printErrorMessage(source: string): string {
239+
printErrorMessage(source: string, options: PrintErrorMessageOptions): string {
227240
const buffer = [printErrorSummary(this.severity, this.reason)];
228241
if (this.description != null) {
229242
buffer.push(`\n\n${this.description}.`);
@@ -251,9 +264,12 @@ export class CompilerErrorDetail {
251264
} catch (e) {
252265
codeFrame = '';
253266
}
254-
buffer.push(
255-
`\n\n${loc.filename}:${loc.start.line}:${loc.start.column}\n`,
256-
);
267+
buffer.push(`\n\n`);
268+
if (loc.filename != null) {
269+
const line = loc.start.line;
270+
const column = options.eslint ? loc.start.column + 1 : loc.start.column;
271+
buffer.push(`${loc.filename}:${line}:${column}\n`);
272+
}
257273
buffer.push(codeFrame);
258274
buffer.push('\n\n');
259275
}
@@ -372,10 +388,15 @@ export class CompilerError extends Error {
372388
return this.name;
373389
}
374390

375-
printErrorMessage(source: string): string {
391+
printErrorMessage(source: string, options: PrintErrorMessageOptions): string {
392+
if (options.eslint && this.details.length === 1) {
393+
return this.details[0].printErrorMessage(source, options);
394+
}
376395
return (
377-
`Found ${this.details.length} error${this.details.length === 1 ? '' : 's'}:\n` +
378-
this.details.map(detail => detail.printErrorMessage(source)).join('\n')
396+
`Found ${this.details.length} error${this.details.length === 1 ? '' : 's'}:\n\n` +
397+
this.details
398+
.map(detail => detail.printErrorMessage(source, options).trim())
399+
.join('\n\n')
379400
);
380401
}
381402

compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,9 @@ export function lower(
107107
if (binding.kind !== 'Identifier') {
108108
builder.errors.pushDiagnostic(
109109
CompilerDiagnostic.create({
110-
category: 'Could not find binding',
111-
description: `[BuildHIR] Could not find binding for param \`${param.node.name}\``,
112110
severity: ErrorSeverity.Invariant,
113-
suggestions: null,
111+
category: 'Could not find binding',
112+
description: `[BuildHIR] Could not find binding for param \`${param.node.name}\`.`,
114113
}).withDetail({
115114
kind: 'error',
116115
loc: param.node.loc ?? null,
@@ -172,10 +171,9 @@ export function lower(
172171
} else {
173172
builder.errors.pushDiagnostic(
174173
CompilerDiagnostic.create({
175-
category: `Handle ${param.node.type} parameters`,
176-
description: `[BuildHIR] Add support for ${param.node.type} parameters`,
177174
severity: ErrorSeverity.Todo,
178-
suggestions: null,
175+
category: `Handle ${param.node.type} parameters`,
176+
description: `[BuildHIR] Add support for ${param.node.type} parameters.`,
179177
}).withDetail({
180178
kind: 'error',
181179
loc: param.node.loc ?? null,
@@ -205,8 +203,7 @@ export function lower(
205203
CompilerDiagnostic.create({
206204
severity: ErrorSeverity.InvalidJS,
207205
category: `Unexpected function body kind`,
208-
description: `Expected function body to be an expression or a block statement, got \`${body.type}\``,
209-
suggestions: null,
206+
description: `Expected function body to be an expression or a block statement, got \`${body.type}\`.`,
210207
}).withDetail({
211208
kind: 'error',
212209
loc: body.node.loc ?? null,

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

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -447,23 +447,22 @@ function applySignature(
447447
reason: value.reason,
448448
context: new Set(),
449449
});
450-
const message =
450+
const variable =
451451
effect.value.identifier.name !== null &&
452452
effect.value.identifier.name.kind === 'named'
453-
? `\`${effect.value.identifier.name.value}\` cannot be modified`
454-
: 'This value cannot be modified';
453+
? `\`${effect.value.identifier.name.value}\``
454+
: 'value';
455455
effects.push({
456456
kind: 'MutateFrozen',
457457
place: effect.value,
458458
error: CompilerDiagnostic.create({
459459
severity: ErrorSeverity.InvalidReact,
460460
category: 'This value cannot be modified',
461-
description: reason,
462-
suggestions: null,
461+
description: `${reason}.`,
463462
}).withDetail({
464463
kind: 'error',
465464
loc: effect.value.loc,
466-
message,
465+
message: `${variable} cannot be modified`,
467466
}),
468467
});
469468
}
@@ -1018,30 +1017,30 @@ function applyEffect(
10181017
effect.value.identifier.declarationId,
10191018
)
10201019
) {
1021-
const description =
1020+
const variable =
10221021
effect.value.identifier.name !== null &&
10231022
effect.value.identifier.name.kind === 'named'
1024-
? `Variable \`${effect.value.identifier.name.value}\``
1025-
: 'This variable';
1023+
? `\`${effect.value.identifier.name.value}\``
1024+
: null;
10261025
const hoistedAccess = context.hoistedContextDeclarations.get(
10271026
effect.value.identifier.declarationId,
10281027
);
10291028
const diagnostic = CompilerDiagnostic.create({
10301029
severity: ErrorSeverity.InvalidReact,
10311030
category: 'Cannot access variable before it is declared',
1032-
description: `${description} is accessed before it is declared, which prevents the earlier access from updating when this value changes over time`,
1031+
description: `${variable ?? 'This variable'} is accessed before it is declared, which prevents the earlier access from updating when this value changes over time.`,
10331032
});
10341033
if (hoistedAccess != null && hoistedAccess.loc != effect.value.loc) {
10351034
diagnostic.withDetail({
10361035
kind: 'error',
10371036
loc: hoistedAccess.loc,
1038-
message: 'Variable accessed before it is declared',
1037+
message: `${variable ?? 'variable'} accessed before it is declared`,
10391038
});
10401039
}
10411040
diagnostic.withDetail({
10421041
kind: 'error',
10431042
loc: effect.value.loc,
1044-
message: 'The variable is declared here',
1043+
message: `${variable ?? 'variable'} is declared here`,
10451044
});
10461045

10471046
applyEffect(
@@ -1061,11 +1060,11 @@ function applyEffect(
10611060
reason: value.reason,
10621061
context: new Set(),
10631062
});
1064-
const message =
1063+
const variable =
10651064
effect.value.identifier.name !== null &&
10661065
effect.value.identifier.name.kind === 'named'
1067-
? `\`${effect.value.identifier.name.value}\` cannot be modified`
1068-
: 'This value cannot be modified';
1066+
? `\`${effect.value.identifier.name.value}\``
1067+
: 'value';
10691068
applyEffect(
10701069
context,
10711070
state,
@@ -1078,11 +1077,11 @@ function applyEffect(
10781077
error: CompilerDiagnostic.create({
10791078
severity: ErrorSeverity.InvalidReact,
10801079
category: 'This value cannot be modified',
1081-
description: reason,
1080+
description: `${reason}.`,
10821081
}).withDetail({
10831082
kind: 'error',
10841083
loc: effect.value.loc,
1085-
message,
1084+
message: `${variable} cannot be modified`,
10861085
}),
10871086
},
10881087
initialized,
@@ -1987,20 +1986,19 @@ function computeSignatureForInstruction(
19871986
break;
19881987
}
19891988
case 'StoreGlobal': {
1989+
const variable = `\`${value.name}\``;
19901990
effects.push({
19911991
kind: 'MutateGlobal',
19921992
place: value.value,
19931993
error: CompilerDiagnostic.create({
19941994
severity: ErrorSeverity.InvalidReact,
19951995
category:
19961996
'Cannot reassign variables declared outside of the component/hook',
1997-
description:
1998-
'Reassigning a variable declared outside of the component/hook is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)',
1999-
suggestions: null,
1997+
description: `Variable ${variable} is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)`,
20001998
}).withDetail({
20011999
kind: 'error',
20022000
loc: instr.loc,
2003-
message: 'Cannot reassign variable',
2001+
message: `${variable} cannot be reassigned`,
20042002
}),
20052003
});
20062004
effects.push({kind: 'Assign', from: value.value, into: lvalue});
@@ -2099,7 +2097,6 @@ function computeEffectsForLegacySignature(
20992097
? `\`${signature.canonicalName}\` is an impure function. `
21002098
: '') +
21012099
'Calling an impure function can produce unstable results that update unpredictably when the component happens to re-render. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)',
2102-
suggestions: null,
21032100
}).withDetail({
21042101
kind: 'error',
21052102
loc,

compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateLocalsNotReassignedAfterRender.ts

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,20 @@ export function validateLocalsNotReassignedAfterRender(fn: HIRFunction): void {
2929
);
3030
if (reassignment !== null) {
3131
const errors = new CompilerError();
32+
const variable =
33+
reassignment.identifier.name != null &&
34+
reassignment.identifier.name.kind === 'named'
35+
? `\`${reassignment.identifier.name.value}\``
36+
: 'variable';
3237
errors.pushDiagnostic(
3338
CompilerDiagnostic.create({
3439
severity: ErrorSeverity.InvalidReact,
35-
category: 'Cannot reassign a variable after render completes',
36-
description: `Reassigning ${reassignment.identifier.name != null && reassignment.identifier.name.kind === 'named' ? `variable \`${reassignment.identifier.name.value}\`` : 'a variable'} after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead`,
40+
category: 'Cannot reassign variable after render completes',
41+
description: `Reassigning ${variable} after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead.`,
3742
}).withDetail({
3843
kind: 'error',
3944
loc: reassignment.loc,
40-
message: 'Cannot reassign variable after render completes',
45+
message: `Cannot reassign ${variable} after render completes`,
4146
}),
4247
);
4348
throw errors;
@@ -78,16 +83,25 @@ function getContextReassignment(
7883
// if the function or its depends reassign, propagate that fact on the lvalue
7984
if (reassignment !== null) {
8085
if (isAsync || value.loweredFunc.func.async) {
81-
CompilerError.throwInvalidReact({
82-
reason:
83-
'Reassigning a variable in an async function can cause inconsistent behavior on subsequent renders. Consider using state instead',
84-
description:
85-
reassignment.identifier.name !== null &&
86-
reassignment.identifier.name.kind === 'named'
87-
? `Variable \`${reassignment.identifier.name.value}\` cannot be reassigned after render`
88-
: '',
89-
loc: reassignment.loc,
90-
});
86+
const errors = new CompilerError();
87+
const variable =
88+
reassignment.identifier.name !== null &&
89+
reassignment.identifier.name.kind === 'named'
90+
? `\`${reassignment.identifier.name.value}\``
91+
: 'variable';
92+
errors.pushDiagnostic(
93+
CompilerDiagnostic.create({
94+
severity: ErrorSeverity.InvalidReact,
95+
category: 'Cannot reassign variable in async function',
96+
description:
97+
'Reassigning a variable in an async function can cause inconsistent behavior on subsequent renders. Consider using state instead',
98+
}).withDetail({
99+
kind: 'error',
100+
loc: reassignment.loc,
101+
message: `Cannot reassign ${variable}`,
102+
}),
103+
);
104+
throw errors;
91105
}
92106
reassigningFunctions.set(lvalue.identifier.id, reassignment);
93107
}

compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoFreezingKnownMutableFunctions.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,22 +57,28 @@ export function validateNoFreezingKnownMutableFunctions(
5757
if (operand.effect === Effect.Freeze) {
5858
const effect = contextMutationEffects.get(operand.identifier.id);
5959
if (effect != null) {
60+
const place = [...effect.places][0];
61+
const variable =
62+
place != null &&
63+
place.identifier.name != null &&
64+
place.identifier.name.kind === 'named'
65+
? `\`${place.identifier.name.value}\``
66+
: 'a local variable';
6067
errors.pushDiagnostic(
6168
CompilerDiagnostic.create({
6269
severity: ErrorSeverity.InvalidReact,
6370
category: 'Cannot modify local variables after render completes',
64-
description: `This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead`,
71+
description: `This argument is a function which may reassign or mutate ${variable} after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.`,
6572
})
6673
.withDetail({
6774
kind: 'error',
6875
loc: operand.loc,
69-
message:
70-
'This function may (indirectly) reassign or modify local variables after render',
76+
message: `This function may (indirectly) reassign or modify ${variable} after render`,
7177
})
7278
.withDetail({
7379
kind: 'error',
7480
loc: effect.loc,
75-
message: 'This modifies a local variable',
81+
message: `This modifies ${variable}`,
7682
}),
7783
);
7884
}

0 commit comments

Comments
 (0)