Skip to content

Commit 2ae8b3d

Browse files
authored
[compiler] Use new diagnostic printing in playground (facebook#33767)
Per title --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33767). * facebook#33981 * facebook#33777 * __->__ facebook#33767
1 parent 7f51055 commit 2ae8b3d

File tree

6 files changed

+72
-34
lines changed

6 files changed

+72
-34
lines changed

compiler/apps/playground/components/Editor/EditorImpl.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import * as t from '@babel/types';
1111
import BabelPluginReactCompiler, {
1212
CompilerError,
1313
CompilerErrorDetail,
14+
CompilerDiagnostic,
1415
Effect,
1516
ErrorSeverity,
1617
parseConfigPragmaForTests,
@@ -144,7 +145,7 @@ const COMMON_HOOKS: Array<[string, Hook]> = [
144145
function compile(source: string): [CompilerOutput, 'flow' | 'typescript'] {
145146
const results = new Map<string, Array<PrintedCompilerPipelineValue>>();
146147
const error = new CompilerError();
147-
const otherErrors: Array<CompilerErrorDetail> = [];
148+
const otherErrors: Array<CompilerErrorDetail | CompilerDiagnostic> = [];
148149
const upsert: (result: PrintedCompilerPipelineValue) => void = result => {
149150
const entry = results.get(result.name);
150151
if (Array.isArray(entry)) {
@@ -214,7 +215,7 @@ function compile(source: string): [CompilerOutput, 'flow' | 'typescript'] {
214215
debugLogIRs: logIR,
215216
logEvent: (_filename: string | null, event: LoggerEvent) => {
216217
if (event.kind === 'CompileError') {
217-
otherErrors.push(new CompilerErrorDetail(event.detail));
218+
otherErrors.push(event.detail);
218219
}
219220
},
220221
},
@@ -226,7 +227,7 @@ function compile(source: string): [CompilerOutput, 'flow' | 'typescript'] {
226227
* (i.e. object shape that is not CompilerError)
227228
*/
228229
if (err instanceof CompilerError && err.details.length > 0) {
229-
error.details.push(...err.details);
230+
error.merge(err);
230231
} else {
231232
/**
232233
* Handle unexpected failures by logging (to get a stack trace)
@@ -245,7 +246,7 @@ function compile(source: string): [CompilerOutput, 'flow' | 'typescript'] {
245246
}
246247
// Only include logger errors if there weren't other errors
247248
if (!error.hasErrors() && otherErrors.length !== 0) {
248-
otherErrors.forEach(e => error.push(e));
249+
otherErrors.forEach(e => error.details.push(e));
249250
}
250251
if (error.hasErrors()) {
251252
return [{kind: 'err', results, error: error}, language];

compiler/apps/playground/components/Editor/Input.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,18 @@ export default function Input({errors, language}: Props): JSX.Element {
3636
const uri = monaco.Uri.parse(`file:///index.js`);
3737
const model = monaco.editor.getModel(uri);
3838
invariant(model, 'Model must exist for the selected input file.');
39-
renderReactCompilerMarkers({monaco, model, details: errors});
39+
renderReactCompilerMarkers({
40+
monaco,
41+
model,
42+
details: errors,
43+
source: store.source,
44+
});
4045
/**
4146
* N.B. that `tabSize` is a model property, not an editor property.
4247
* So, the tab size has to be set per model.
4348
*/
4449
model.updateOptions({tabSize: 2});
45-
}, [monaco, errors]);
50+
}, [monaco, errors, store.source]);
4651

4752
useEffect(() => {
4853
/**

compiler/apps/playground/components/Editor/Output.tsx

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,17 @@ async function tabify(
142142
</>,
143143
);
144144
}
145+
} else if (compilerOutput.kind === 'err') {
146+
const errors = compilerOutput.error.printErrorMessage(source, {
147+
eslint: false,
148+
});
149+
reorderedTabs.set(
150+
'Errors',
151+
<TextTabContent
152+
output={errors}
153+
diff={null}
154+
showInfoPanel={false}></TextTabContent>,
155+
);
145156
}
146157
tabs.forEach((tab, name) => {
147158
reorderedTabs.set(name, tab);
@@ -166,6 +177,19 @@ function Output({store, compilerOutput}: Props): JSX.Element {
166177
const [tabs, setTabs] = useState<Map<string, React.ReactNode>>(
167178
() => new Map(),
168179
);
180+
181+
/*
182+
* Update the active tab back to the output or errors tab when the compilation state
183+
* changes between success/failure.
184+
*/
185+
const [previousOutputKind, setPreviousOutputKind] = useState(
186+
compilerOutput.kind,
187+
);
188+
if (compilerOutput.kind !== previousOutputKind) {
189+
setPreviousOutputKind(compilerOutput.kind);
190+
setTabsOpen(new Set([compilerOutput.kind === 'ok' ? 'JS' : 'Errors']));
191+
}
192+
169193
useEffect(() => {
170194
tabify(store.source, compilerOutput).then(tabs => {
171195
setTabs(tabs);
@@ -196,20 +220,6 @@ function Output({store, compilerOutput}: Props): JSX.Element {
196220
tabs={tabs}
197221
changedPasses={changedPasses}
198222
/>
199-
{compilerOutput.kind === 'err' ? (
200-
<div
201-
className="flex flex-wrap absolute bottom-0 bg-white grow border-y border-grey-200 transition-all ease-in"
202-
style={{width: 'calc(100vw - 650px)'}}>
203-
<div className="w-full p-4 basis-full border-b">
204-
<h2>COMPILER ERRORS</h2>
205-
</div>
206-
<pre
207-
className="p-4 basis-full text-red-600 overflow-y-scroll whitespace-pre-wrap"
208-
style={{width: 'calc(100vw - 650px)', height: '150px'}}>
209-
<code>{compilerOutput.error.toString()}</code>
210-
</pre>
211-
</div>
212-
) : null}
213223
</>
214224
);
215225
}

compiler/apps/playground/lib/reactCompilerMonacoDiagnostics.ts

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
*/
77

88
import {Monaco} from '@monaco-editor/react';
9-
import {CompilerErrorDetail, ErrorSeverity} from 'babel-plugin-react-compiler';
9+
import {
10+
CompilerDiagnostic,
11+
CompilerErrorDetail,
12+
ErrorSeverity,
13+
} from 'babel-plugin-react-compiler';
1014
import {MarkerSeverity, type editor} from 'monaco-editor';
1115

1216
function mapReactCompilerSeverityToMonaco(
@@ -22,38 +26,46 @@ function mapReactCompilerSeverityToMonaco(
2226
}
2327

2428
function mapReactCompilerDiagnosticToMonacoMarker(
25-
detail: CompilerErrorDetail,
29+
detail: CompilerErrorDetail | CompilerDiagnostic,
2630
monaco: Monaco,
31+
source: string,
2732
): editor.IMarkerData | null {
28-
if (detail.loc == null || typeof detail.loc === 'symbol') {
33+
const loc = detail.primaryLocation();
34+
if (loc == null || typeof loc === 'symbol') {
2935
return null;
3036
}
3137
const severity = mapReactCompilerSeverityToMonaco(detail.severity, monaco);
32-
let message = detail.printErrorMessage();
38+
let message = detail.printErrorMessage(source, {eslint: true});
3339
return {
3440
severity,
3541
message,
36-
startLineNumber: detail.loc.start.line,
37-
startColumn: detail.loc.start.column + 1,
38-
endLineNumber: detail.loc.end.line,
39-
endColumn: detail.loc.end.column + 1,
42+
startLineNumber: loc.start.line,
43+
startColumn: loc.start.column + 1,
44+
endLineNumber: loc.end.line,
45+
endColumn: loc.end.column + 1,
4046
};
4147
}
4248

4349
type ReactCompilerMarkerConfig = {
4450
monaco: Monaco;
4551
model: editor.ITextModel;
46-
details: Array<CompilerErrorDetail>;
52+
details: Array<CompilerErrorDetail | CompilerDiagnostic>;
53+
source: string;
4754
};
4855
let decorations: Array<string> = [];
4956
export function renderReactCompilerMarkers({
5057
monaco,
5158
model,
5259
details,
60+
source,
5361
}: ReactCompilerMarkerConfig): void {
5462
const markers: Array<editor.IMarkerData> = [];
5563
for (const detail of details) {
56-
const marker = mapReactCompilerDiagnosticToMonacoMarker(detail, monaco);
64+
const marker = mapReactCompilerDiagnosticToMonacoMarker(
65+
detail,
66+
monaco,
67+
source,
68+
);
5769
if (marker == null) {
5870
continue;
5971
}

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

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

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ export class CompilerErrorDetail {
262262

263263
export class CompilerError extends Error {
264264
details: Array<CompilerErrorDetail | CompilerDiagnostic> = [];
265+
printedMessage: string | null = null;
265266

266267
static invariant(
267268
condition: unknown,
@@ -347,18 +348,29 @@ export class CompilerError extends Error {
347348
}
348349

349350
override get message(): string {
350-
return this.toString();
351+
return this.printedMessage ?? this.toString();
351352
}
352353

353354
override set message(_message: string) {}
354355

355356
override toString(): string {
357+
if (this.printedMessage) {
358+
return this.printedMessage;
359+
}
356360
if (Array.isArray(this.details)) {
357361
return this.details.map(detail => detail.toString()).join('\n\n');
358362
}
359363
return this.name;
360364
}
361365

366+
withPrintedMessage(
367+
source: string,
368+
options: PrintErrorMessageOptions,
369+
): CompilerError {
370+
this.printedMessage = this.printErrorMessage(source, options);
371+
return this;
372+
}
373+
362374
printErrorMessage(source: string, options: PrintErrorMessageOptions): string {
363375
if (options.eslint && this.details.length === 1) {
364376
return this.details[0].printErrorMessage(source, options);

0 commit comments

Comments
 (0)