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!: upgrade to prettier v3 #516

Merged
merged 3 commits into from
Sep 2, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/orange-eyes-brush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"eslint-plugin-prettier": major
---

feat!: upgrade to prettier v3
8 changes: 8 additions & 0 deletions .changeset/pre.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"mode": "pre",
"tag": "alpha",
"initialVersions": {
"eslint-plugin-prettier": "4.2.2"
},
"changesets": []
}
158 changes: 30 additions & 128 deletions eslint-plugin-prettier.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
* @typedef {import('eslint').AST.Range} Range
* @typedef {import('eslint').AST.SourceLocation} SourceLocation
* @typedef {import('eslint').ESLint.Plugin} Plugin
* @typedef {import('prettier').FileInfoOptions} FileInfoOptions
* @typedef {import('prettier').Options & { onDiskFilepath: string, parserPath: string, usePrettierrc?: boolean }} Options
*/

'use strict';
Expand All @@ -34,9 +36,9 @@ const { INSERT, DELETE, REPLACE } = generateDifferences;

// Lazily-loaded Prettier.
/**
* @type {typeof import('prettier')}
* @type {(source: string, options: Options, fileInfoOptions: FileInfoOptions) => string}
*/
let prettier;
let prettierFormat;

// ------------------------------------------------------------------------------
// Rule Definition
Expand Down Expand Up @@ -123,7 +125,10 @@ const eslintPluginPrettier = {
create(context) {
const usePrettierrc =
!context.options[1] || context.options[1].usePrettierrc !== false;
const eslintFileInfoOptions =
/**
* @type {FileInfoOptions}
*/
const fileInfoOptions =
(context.options[1] && context.options[1].fileInfoOptions) || {};
const sourceCode = context.getSourceCode();
const filepath = context.getFilename();
Expand All @@ -136,136 +141,19 @@ const eslintPluginPrettier = {
const source = sourceCode.text;

return {
// eslint-disable-next-line sonarjs/cognitive-complexity
Program() {
if (!prettier) {
if (!prettierFormat) {
// Prettier is expensive to load, so only load it if needed.
prettier = require('prettier');
prettierFormat = require('synckit').createSyncFn(
require.resolve('./worker'),
);
}

/**
* @type {{}}
*/
const eslintPrettierOptions = context.options[0] || {};

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

const { ignored, inferredParser } = prettier.getFileInfo.sync(
onDiskFilepath,
{
resolveConfig: false,
withNodeModules: false,
ignorePath: '.prettierignore',
plugins: prettierRcOptions ? prettierRcOptions.plugins : null,
...eslintFileInfoOptions,
},
);

// Skip if file is ignored using a .prettierignore file
if (ignored) {
return;
}

const initialOptions = {};

// ESLint 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
// rules with fragments of JS) instead of guessing the parser
// based off the filename. Otherwise, for instance, on a .md file we
// end up trying to run prettier over a fragment of JS using the
// markdown parser, which throws an error.
// Processors may set virtual filenames for these extracted blocks.
// If they do so then we want to trust the file extension they
// provide, and no override is needed.
// If the processor does not set any virtual filename (signified by
// `filepath` and `onDiskFilepath` being equal) AND we can't
// infer the parser from the filename, either because no filename
// was provided or because there is no parser found for the
// filename, use javascript.
// This is added to the options first, so that
// prettierRcOptions and eslintPrettierOptions can still override
// the parser.
//
// `parserBlocklist` should contain the list of prettier parser
// names for file types where:
// * Prettier supports parsing the file type
// * There is an ESLint processor that extracts JavaScript snippets
// from the file type.
if (filepath === onDiskFilepath) {
// The following list means the plugin process source into js content
// but with same filename, so we need to change the parser to `babel`
// by default.
// Related ESLint plugins are:
// 1. `eslint-plugin-graphql` (replacement: `@graphql-eslint/eslint-plugin`)
// 2. `eslint-plugin-html`
// 3. `eslint-plugin-markdown@1` (replacement: `eslint-plugin-markdown@2+`)
// 4. `eslint-plugin-svelte3` (replacement: `eslint-plugin-svelte@2+`)
const parserBlocklist = [null, 'markdown', 'html'];

let inferParserToBabel = parserBlocklist.includes(inferredParser);

switch (inferredParser) {
// it could be processed by `@graphql-eslint/eslint-plugin` or `eslint-plugin-graphql`
case 'graphql': {
if (
// for `eslint-plugin-graphql`, see https://github.com/apollographql/eslint-plugin-graphql/blob/master/src/index.js#L416
source.startsWith('ESLintPluginGraphQLFile`')
) {
inferParserToBabel = true;
}
break;
}
// it could be processed by `@ota-meshi/eslint-plugin-svelte`, `eslint-plugin-svelte` or `eslint-plugin-svelte3`
case 'svelte': {
// The `source` would be modified by `eslint-plugin-svelte3`
if (!context.parserPath.includes('svelte-eslint-parser')) {
// We do not support `eslint-plugin-svelte3`,
// the users should run `prettier` on `.svelte` files manually
return;
}
}
}

if (inferParserToBabel) {
initialOptions.parser = 'babel';
}
} else {
// Similar to https://github.com/prettier/stylelint-prettier/pull/22
// In all of the following cases ESLint extracts a part of a file to
// be formatted and there exists a prettier parser for the whole file.
// If you're interested in prettier you'll want a fully formatted file so
// you're about to run prettier over the whole file anyway.
// Therefore running prettier over just the style section is wasteful, so
// skip it.
const parserBlocklist = [
'babel',
'babylon',
'flow',
'typescript',
'vue',
'markdown',
'html',
'mdx',
'angular',
'svelte',
];
if (
parserBlocklist.includes(/** @type {string} */ (inferredParser))
) {
return;
}
}

const prettierOptions = {
...initialOptions,
...prettierRcOptions,
...eslintPrettierOptions,
filepath,
};

// prettier.format() may throw a SyntaxError if it cannot parse the
// source code it is given. Usually for JS files this isn't a
// problem as ESLint will report invalid syntax before trying to
Expand All @@ -279,7 +167,17 @@ const eslintPluginPrettier = {
*/
let prettierSource;
try {
prettierSource = prettier.format(source, prettierOptions);
prettierSource = prettierFormat(
source,
{
...eslintPrettierOptions,
filepath,
onDiskFilepath,
parserPath: context.parserPath,
usePrettierrc,
},
fileInfoOptions,
);
} catch (err) {
if (!(err instanceof SyntaxError)) {
throw err;
Expand Down Expand Up @@ -308,6 +206,10 @@ const eslintPluginPrettier = {
return;
}

if (prettierSource == null) {
return;
}

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

Expand Down
6 changes: 2 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
"prettier"
],
"scripts": {
"build": "tsc -b",
"format": "yarn prettier '**/*.{js,json,md,yml}' --write && yarn lint --fix",
"lint": "eslint . --cache -f friendly --max-warnings 10",
"prepare": "simple-git-hooks && yarn-deduplicate --strategy fewer || exit 0",
Expand All @@ -38,7 +37,7 @@
"peerDependencies": {
"@types/eslint": ">=8.0.0",
"eslint": ">=8.0.0",
"prettier": ">=2.0.0"
"prettier": ">=3.0.0"
},
"peerDependenciesMeta": {
"@types/eslint": {
Expand All @@ -49,7 +48,6 @@
}
},
"dependencies": {
"eslint-plugin-prettier": "link:.",
"prettier-linter-helpers": "^1.0.0"
},
"devDependencies": {
Expand All @@ -76,6 +74,6 @@
},
"resolutions": {
"eslint-plugin-prettier": "link:.",
"prettier": "^2.0.0"
"prettier": "^3.0.0-alpha.0"
}
}