Skip to content

Commit

Permalink
Catch and format SyntaxErrors as eslint violations
Browse files Browse the repository at this point in the history
If Prettier can't format a file due to 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.
  • Loading branch information
BPScott committed Dec 28, 2018
1 parent e367955 commit 76cc084
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 1 deletion.
35 changes: 34 additions & 1 deletion eslint-plugin-prettier.js
Expand Up @@ -209,7 +209,40 @@ module.exports = {
{ filepath }
);

const prettierSource = prettier.format(source, prettierOptions);
// prettier.format() may throw a SyntaxError if it cannot parse the
// source code it is given. Ususally for JS files this isn't a
// problem as ESLint will report invalid syntax before trying to
// pass it to the prettier plugin. However this might be a problem
// for non-JS languages that are handled by a plugin. Notably Vue
// files throw an error if they contain unclosed elements, such as
// `<template><div></template>. In this case report an error at the
// point at which parsing failed.
let prettierSource;
try {
prettierSource = prettier.format(source, prettierOptions);
} catch (err) {
if (!(err instanceof SyntaxError)) {
throw err;
}

let message = 'Parsing error: ' + err.message;

// Prettier's message contains a codeframe style preview of the
// invalid code and the line/column at which the error occured.
// ESLint shows those pieces of information elsewhere already so
// remove them from the message
if (err.codeFrame) {
message = message.replace(`\n${err.codeFrame}`, '');
}
if (err.loc) {
message = message.replace(/ \(\d+:\d+\)$/, '');
}

context.report({ message, loc: err.loc });

return;
}

if (source !== prettierSource) {
const differences = generateDifferences(source, prettierSource);

Expand Down
26 changes: 26 additions & 0 deletions test/invalid/vue-syntax-error.txt
@@ -0,0 +1,26 @@
CODE:
<template>
<div>
</template>
<script>
a();
</script>

OUTPUT:
<template>
<div>
</template>
<script>
a();
</script>

OPTIONS:
[]

ERRORS:
[
{
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',
line: 3, column: 2
},
]
3 changes: 3 additions & 0 deletions test/prettier.js
Expand Up @@ -99,6 +99,9 @@ vueRuleTester.run('prettier', rule, {
invalid: [
Object.assign(loadInvalidFixture('vue'), {
filename: 'invalid.vue'
}),
Object.assign(loadInvalidFixture('vue-syntax-error'), {
filename: 'syntax-error.vue'
})
]
});
Expand Down

0 comments on commit 76cc084

Please sign in to comment.