Skip to content

Commit 4ce2e05

Browse files
committed
Catch and format SyntaxErrors as eslint violations
If Prettier can't format a file due not being able to parse the given content it throws a SyntaxError. If that happens then announce the error as an ESLint rule violation instead of crashing.
1 parent e367955 commit 4ce2e05

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

eslint-plugin-prettier.js

+34-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,40 @@ module.exports = {
209209
{ filepath }
210210
);
211211

212-
const prettierSource = prettier.format(source, prettierOptions);
212+
// prettier.format() may throw a SyntaxError if it cannot parse the
213+
// source code it is given. Ususally for JS files this isn't a
214+
// problem as ESLint will report invalid syntax before trying to
215+
// pass it to the prettier plugin. However this might be a problem
216+
// for non-JS languages that are handled by a plugin. Notably Vue
217+
// files throw an error if they contain unclosed elements, such as
218+
// `<template><div></template>. In this case report an error at the
219+
// point at which parsing failed.
220+
let prettierSource;
221+
try {
222+
prettierSource = prettier.format(source, prettierOptions);
223+
} catch (err) {
224+
if (!(err instanceof SyntaxError)) {
225+
throw err;
226+
}
227+
228+
let message = 'Parsing error: ' + err.message;
229+
230+
// Prettier's message contains a codeframe style preview of the
231+
// invalid code and the line/column at which the error occured.
232+
// ESLint shows those pieces of information elsewhere already so
233+
// remove them from the message
234+
if (err.codeFrame) {
235+
message = message.replace(`\n${err.codeFrame}`, '');
236+
}
237+
if (err.loc) {
238+
message = message.replace(/ \(\d+:\d+\)$/, '');
239+
}
240+
241+
context.report({ message, loc: err.loc });
242+
243+
return;
244+
}
245+
213246
if (source !== prettierSource) {
214247
const differences = generateDifferences(source, prettierSource);
215248

test/invalid/vue-syntax-error.txt

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
CODE:
2+
<template>
3+
<div>
4+
</template>
5+
<script>
6+
a();
7+
</script>
8+
9+
OUTPUT:
10+
<template>
11+
<div>
12+
</template>
13+
<script>
14+
a();
15+
</script>
16+
17+
OPTIONS:
18+
[]
19+
20+
ERRORS:
21+
[
22+
{
23+
message: 'Parsing error: Unexpected closing tag "template". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags',
24+
line: 3, column: 2
25+
},
26+
]

test/prettier.js

+3
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ vueRuleTester.run('prettier', rule, {
9999
invalid: [
100100
Object.assign(loadInvalidFixture('vue'), {
101101
filename: 'invalid.vue'
102+
}),
103+
Object.assign(loadInvalidFixture('vue-syntax-error'), {
104+
filename: 'syntax-error.vue'
102105
})
103106
]
104107
});

0 commit comments

Comments
 (0)