Skip to content

Commit

Permalink
Catch and format SyntaxErrors as eslint violations (#141)
Browse files Browse the repository at this point in the history
* Bump development prettier version to 1.15.3

* Catch and format SyntaxErrors as eslint violations

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 d34daed commit 4a0e57d
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 6 deletions.
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
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -43,7 +43,7 @@
"eslint-plugin-node": "^8.0.0",
"eslint-plugin-self": "^1.1.0",
"mocha": "^5.2.0",
"prettier": "^1.13.0",
"prettier": "^1.15.3",
"vue-eslint-parser": "^4.0.2"
},
"engines": {
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
},
]
5 changes: 4 additions & 1 deletion test/prettier.js
Expand Up @@ -92,13 +92,16 @@ const vueRuleTester = new RuleTester({
vueRuleTester.run('prettier', rule, {
valid: [
{
code: `<template>foo</template>\n<script>\n"";\n</script>\n`,
code: `<template>\n <div>HI</div>\n</template>\n<script>\n3;\n</script>\n`,
filename: 'valid.vue'
}
],
invalid: [
Object.assign(loadInvalidFixture('vue'), {
filename: 'invalid.vue'
}),
Object.assign(loadInvalidFixture('vue-syntax-error'), {
filename: 'syntax-error.vue'
})
]
});
Expand Down
6 changes: 3 additions & 3 deletions yarn.lock
Expand Up @@ -679,9 +679,9 @@ prettier-linter-helpers@^1.0.0:
dependencies:
fast-diff "^1.1.2"

prettier@^1.13.0:
version "1.14.3"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.3.tgz#90238dd4c0684b7edce5f83b0fb7328e48bd0895"
prettier@^1.15.3:
version "1.15.3"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.15.3.tgz#1feaac5bdd181237b54dbe65d874e02a1472786a"

progress@^2.0.0:
version "2.0.0"
Expand Down

0 comments on commit 4a0e57d

Please sign in to comment.