Skip to content

Commit 830c4e9

Browse files
committed
Implement click-to-open for babel syntax errors in build error overlay
1 parent cd3d04b commit 830c4e9

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

packages/react-error-overlay/src/containers/CompileErrorContainer.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,40 @@ import Footer from '../components/Footer';
1212
import Header from '../components/Header';
1313
import CodeBlock from '../components/CodeBlock';
1414
import generateAnsiHTML from '../utils/generateAnsiHTML';
15+
import parseCompileError from '../utils/parseCompileError';
16+
import type { ErrorLocation } from '../utils/parseCompileError';
17+
18+
const codeAnchorStyle = {
19+
cursor: 'pointer',
20+
};
1521

1622
type Props = {|
1723
error: string,
1824
|};
1925

2026
class CompileErrorContainer extends PureComponent<Props, void> {
27+
openInEditor(errorLoc: ErrorLocation): void {
28+
const { filePath, lineNumber } = errorLoc;
29+
fetch(
30+
`/__open-stack-frame-in-editor?fileName=` +
31+
window.encodeURIComponent(filePath) +
32+
'&lineNumber=' +
33+
window.encodeURIComponent(lineNumber || 1)
34+
).then(() => {}, () => {});
35+
}
36+
2137
render() {
2238
const { error } = this.props;
39+
const errLoc = parseCompileError(error);
2340
return (
2441
<ErrorOverlay>
2542
<Header headerText="Failed to compile" />
26-
<CodeBlock main={true} codeHTML={generateAnsiHTML(error)} />
43+
<a
44+
onClick={errLoc ? () => this.openInEditor(errLoc) : null}
45+
style={errLoc ? codeAnchorStyle : null}
46+
>
47+
<CodeBlock main={true} codeHTML={generateAnsiHTML(error)} />
48+
</a>
2749
<Footer line1="This error occurred during the build time and cannot be dismissed." />
2850
</ErrorOverlay>
2951
);
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// @flow
2+
3+
export type ErrorLocation = {|
4+
filePath: string,
5+
lineNumber: number,
6+
|};
7+
8+
const filePathRegex = /^\.(\/[^\/\n ]+)+\.[^\/\n ]+$/;
9+
10+
// Based on syntax error formating of babylon parser
11+
// https://github.com/babel/babylon/blob/v7.0.0-beta.22/src/parser/location.js#L19
12+
const lineNumberRegex = /^.*\((\d+):(\d+)\)$/;
13+
14+
// Based on error formatting of webpack
15+
// https://github.com/webpack/webpack/blob/v3.5.5/lib/Stats.js#L183-L217
16+
function parseCompileError(message: string): ?ErrorLocation {
17+
const lines: Array<string> = message.split('\n');
18+
let filePath: string = '';
19+
let lineNumber: number = 0;
20+
21+
for (let i = 0; i < lines.length; i++) {
22+
const line: string = lines[i];
23+
if (!line) continue;
24+
25+
if (!filePath && line.match(filePathRegex)) {
26+
filePath = line;
27+
}
28+
29+
if (!lineNumber) {
30+
const match: ?Array<string> = line.match(lineNumberRegex);
31+
if (match) {
32+
lineNumber = parseInt(match[1]);
33+
}
34+
}
35+
36+
if (filePath && lineNumber) break;
37+
}
38+
39+
return filePath && lineNumber ? { filePath, lineNumber } : null;
40+
}
41+
42+
export default parseCompileError;

0 commit comments

Comments
 (0)