Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support processor virtual filename #401

Merged
merged 2 commits into from
Apr 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 38 additions & 5 deletions eslint-plugin-prettier.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
// Requirements
// ------------------------------------------------------------------------------

const fs = require('fs');
const path = require('path');

const {
showInvisibles,
generateDifferences
Expand All @@ -25,6 +28,9 @@ const { INSERT, DELETE, REPLACE } = generateDifferences;
// ------------------------------------------------------------------------------

// Lazily-loaded Prettier.
/**
* @type {import('prettier')}
*/
let prettier;

// ------------------------------------------------------------------------------
Expand Down Expand Up @@ -55,6 +61,26 @@ function reportDifference(context, difference) {
});
}

/**
* get normalized filepath in case of virtual filename
* @param {string} filepath
* @returns {string}
*/
function normalizeFilepath(filepath) {
try {
if (fs.statSync(filepath).isFile()) {
return filepath;
}
} catch (err) {
// https://github.com/eslint/eslint/issues/11989
if (err.code === 'ENOTDIR') {
return normalizeFilepath(path.dirname(filepath));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be recursive as described at eslint/eslint#14227 (comment)

}
}

return filepath;
}

// ------------------------------------------------------------------------------
// Module Definition
// ------------------------------------------------------------------------------
Expand Down Expand Up @@ -112,6 +138,7 @@ module.exports = {
(context.options[1] && context.options[1].fileInfoOptions) || {};
const sourceCode = context.getSourceCode();
const filepath = context.getFilename();
const normalizedFilepath = normalizeFilepath(filepath);
const source = sourceCode.text;

return {
Expand All @@ -124,13 +151,13 @@ module.exports = {
const eslintPrettierOptions = context.options[0] || {};

const prettierRcOptions = usePrettierrc
? prettier.resolveConfig.sync(filepath, {
? prettier.resolveConfig.sync(normalizedFilepath, {
editorconfig: true
})
: null;

const prettierFileInfo = prettier.getFileInfo.sync(
filepath,
normalizedFilepath,
Object.assign(
{},
{ resolveConfig: true, ignorePath: '.prettierignore' },
Expand All @@ -145,7 +172,8 @@ module.exports = {

const initialOptions = {};

// ESLint suppports processors that let you extract and lint JS
// for ESLint < 6.0
// it supports processors that let you extract and lint JS
// fragments within a non-JS language. In the cases where prettier
// supports the same language as a processor, we want to process
// the provided source code as javascript (as ESLint provides the
Expand All @@ -165,8 +193,13 @@ module.exports = {
// * Prettier supports parsing the file type
// * There is an ESLint processor that extracts JavaScript snippets
// from the file type.
//
// for ESLint >= 6.0
// it supports virtual filename, if filepath is not same as normalizedFilepath,
// it means filepath is virtual name, and we can guess the file type by prettier automatically
const parserBlocklist = [null, 'graphql', 'markdown', 'html'];
if (
filepath === normalizedFilepath &&
parserBlocklist.indexOf(prettierFileInfo.inferredParser) !== -1
) {
// Prettier v1.16.0 renamed the `babylon` parser to `babel`
Expand All @@ -187,7 +220,7 @@ module.exports = {
);

// prettier.format() may throw a SyntaxError if it cannot parse the
// source code it is given. Ususally for JS files this isn't a
// source code it is given. Usually 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
Expand All @@ -205,7 +238,7 @@ module.exports = {
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.
// invalid code and the line/column at which the error occurred.
// ESLint shows those pieces of information elsewhere already so
// remove them from the message
if (err.codeFrame) {
Expand Down
4 changes: 4 additions & 0 deletions test/prettier.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ ruleTester.run('prettier', rule, {
{
code: 'a();;;;;;\n',
filename: 'node_modules/dummy.js'
},
{
code: `('');\n`,
filename: path.join(__filename, '0_fake_virtual_name.js')
}
],
invalid: [
Expand Down