|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- #!/usr/bin/env node
-
- "use strict";
-
- const validators = require("./validators");
- const config = require("..");
- const prettier = require("../prettier");
-
- // Require locally installed eslint, for `npx eslint-config-prettier` support
- // with no local eslint-config-prettier installation.
- const { ESLint } = require(require.resolve("eslint", {
- paths: [process.cwd(), ...require.resolve.paths("eslint")],
- }));
-
- const SPECIAL_RULES_URL =
- "https://github.com/prettier/eslint-config-prettier#special-rules";
-
- const PRETTIER_RULES_URL =
- "https://github.com/prettier/eslint-config-prettier#arrow-body-style-and-prefer-arrow-callback";
-
- if (module === require.main) {
- const args = process.argv.slice(2);
-
- if (args.length === 0) {
- console.error(help());
- process.exit(1);
- }
-
- const eslint = new ESLint();
-
- Promise.all(args.map((file) => eslint.calculateConfigForFile(file)))
- .then((configs) => {
- const rules = [].concat(
- ...configs.map(({ rules }, index) =>
- Object.entries(rules).map((entry) => [...entry, args[index]])
- )
- );
- const result = processRules(rules);
- if (result.stderr) {
- console.error(result.stderr);
- }
- if (result.stdout) {
- console.error(result.stdout);
- }
- process.exit(result.code);
- })
- .catch((error) => {
- console.error(error.message);
- process.exit(1);
- });
- }
-
- function help() {
- return `
- Usage: npx eslint-config-prettier FILE...
-
- Resolves an ESLint configuration for every given FILE and checks if they
- contain rules that are unnecessary or conflict with Prettier. Example:
-
- npx eslint-config-prettier index.js test/index.js other/file/to/check.js
-
- Exit codes:
-
- 0: No automatically detectable problems found.
- 1: General error.
- 2: Conflicting rules found.
-
- For more information, see:
- https://github.com/prettier/eslint-config-prettier#cli-helper-tool
- `.trim();
- }
-
- function processRules(configRules) {
- const regularRules = filterRules(config.rules, (_, value) => value === "off");
- const optionsRules = filterRules(
- config.rules,
- (ruleName, value) => value === 0 && ruleName in validators
- );
- const specialRules = filterRules(
- config.rules,
- (ruleName, value) => value === 0 && !(ruleName in validators)
- );
-
- const enabledRules = configRules
- .map(([ruleName, value, source]) => {
- const arrayValue = Array.isArray(value) ? value : [value];
- const [level, ...options] = arrayValue;
- const isOff = level === "off" || level === 0;
- return isOff ? null : { ruleName, options, source };
- })
- .filter(Boolean);
-
- const flaggedRules = enabledRules.filter(
- ({ ruleName }) => ruleName in config.rules
- );
-
- const regularFlaggedRuleNames = filterRuleNames(
- flaggedRules,
- ({ ruleName }) => ruleName in regularRules
- );
- const optionsFlaggedRuleNames = filterRuleNames(
- flaggedRules,
- ({ ruleName, ...rule }) =>
- ruleName in optionsRules && !validators[ruleName](rule)
- );
- const specialFlaggedRuleNames = filterRuleNames(
- flaggedRules,
- ({ ruleName }) => ruleName in specialRules
- );
- const prettierFlaggedRuleNames = filterRuleNames(
- enabledRules,
- ({ ruleName, source }) =>
- ruleName in prettier.rules &&
- enabledRules.some(
- (rule) =>
- rule.ruleName === "prettier/prettier" && rule.source === source
- )
- );
-
- const regularMessage = [
- "The following rules are unnecessary or might conflict with Prettier:",
- "",
- printRuleNames(regularFlaggedRuleNames),
- ].join("\n");
-
- const optionsMessage = [
- "The following rules are enabled with config that might conflict with Prettier. See:",
- SPECIAL_RULES_URL,
- "",
- printRuleNames(optionsFlaggedRuleNames),
- ].join("\n");
-
- const specialMessage = [
- "The following rules are enabled but cannot be automatically checked. See:",
- SPECIAL_RULES_URL,
- "",
- printRuleNames(specialFlaggedRuleNames),
- ].join("\n");
-
- const prettierMessage = [
- "The following rules can cause issues when using eslint-plugin-prettier at the same time.",
- "Only enable them if you know what you are doing! See:",
- PRETTIER_RULES_URL,
- "",
- printRuleNames(prettierFlaggedRuleNames),
- ].join("\n");
-
- if (
- regularFlaggedRuleNames.length === 0 &&
- optionsFlaggedRuleNames.length === 0
- ) {
- const message =
- specialFlaggedRuleNames.length === 0 &&
- prettierFlaggedRuleNames.length === 0
- ? "No rules that are unnecessary or conflict with Prettier were found."
- : [
- specialFlaggedRuleNames.length === 0 ? null : specialMessage,
- prettierFlaggedRuleNames.length === 0 ? null : prettierMessage,
- "Other than that, no rules that are unnecessary or conflict with Prettier were found.",
- ]
- .filter(Boolean)
- .join("\n\n");
-
- return {
- stdout: message,
- code: 0,
- };
- }
-
- const message = [
- regularFlaggedRuleNames.length === 0 ? null : regularMessage,
- optionsFlaggedRuleNames.length === 0 ? null : optionsMessage,
- specialFlaggedRuleNames.length === 0 ? null : specialMessage,
- prettierFlaggedRuleNames.length === 0 ? null : prettierMessage,
- ]
- .filter(Boolean)
- .join("\n\n");
-
- return {
- stdout: message,
- code: 2,
- };
- }
-
- function filterRules(rules, fn) {
- return Object.entries(rules)
- .filter(([ruleName, value]) => fn(ruleName, value))
- .reduce((obj, [ruleName]) => {
- obj[ruleName] = true;
- return obj;
- }, Object.create(null));
- }
-
- function filterRuleNames(rules, fn) {
- return [
- ...new Set(rules.filter((rule) => fn(rule)).map((rule) => rule.ruleName)),
- ];
- }
-
- function printRuleNames(ruleNames) {
- return ruleNames
- .slice()
- .sort()
- .map((ruleName) => `- ${ruleName}`)
- .join("\n");
- }
-
- exports.processRules = processRules;
|