| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- /**
- * @fileoverview Translates CLI options into ESLint constructor options.
- * @author Nicholas C. Zakas
- * @author Francesco Trotta
- */
- "use strict";
- //------------------------------------------------------------------------------
- // Requirements
- //------------------------------------------------------------------------------
- const { normalizeSeverityToString } = require("./severity");
- const { getShorthandName, normalizePackageName } = require("./naming");
- const { ModuleImporter } = require("@humanwhocodes/module-importer");
- //------------------------------------------------------------------------------
- // Types
- //------------------------------------------------------------------------------
- /** @typedef {import("../types").ESLint.Options} ESLintOptions */
- /** @typedef {import("../types").ESLint.LegacyOptions} LegacyESLintOptions */
- /** @typedef {import("../types").Linter.LintMessage} LintMessage */
- /** @typedef {import("../options").ParsedCLIOptions} ParsedCLIOptions */
- /** @typedef {import("../types").ESLint.Plugin} Plugin */
- //------------------------------------------------------------------------------
- // Helpers
- //------------------------------------------------------------------------------
- /**
- * Loads plugins with the specified names.
- * @param {{ "import": (name: string) => Promise<any> }} importer An object with an `import` method called once for each plugin.
- * @param {string[]} pluginNames The names of the plugins to be loaded, with or without the "eslint-plugin-" prefix.
- * @returns {Promise<Record<string, Plugin>>} A mapping of plugin short names to implementations.
- */
- async function loadPlugins(importer, pluginNames) {
- const plugins = {};
- await Promise.all(
- pluginNames.map(async pluginName => {
- const longName = normalizePackageName(pluginName, "eslint-plugin");
- const module = await importer.import(longName);
- if (!("default" in module)) {
- throw new Error(
- `"${longName}" cannot be used with the \`--plugin\` option because its default module does not provide a \`default\` export`,
- );
- }
- const shortName = getShorthandName(pluginName, "eslint-plugin");
- plugins[shortName] = module.default;
- }),
- );
- return plugins;
- }
- /**
- * Predicate function for whether or not to apply fixes in quiet mode.
- * If a message is a warning, do not apply a fix.
- * @param {LintMessage} message The lint result.
- * @returns {boolean} True if the lint message is an error (and thus should be
- * autofixed), false otherwise.
- */
- function quietFixPredicate(message) {
- return message.severity === 2;
- }
- /**
- * Predicate function for whether or not to run a rule in quiet mode.
- * If a rule is set to warning, do not run it.
- * @param {{ ruleId: string; severity: number; }} rule The rule id and severity.
- * @returns {boolean} True if the lint rule should run, false otherwise.
- */
- function quietRuleFilter(rule) {
- return rule.severity === 2;
- }
- //------------------------------------------------------------------------------
- // Public Interface
- //------------------------------------------------------------------------------
- /**
- * Translates the CLI options into the options expected by the ESLint constructor.
- * @param {ParsedCLIOptions} cliOptions The CLI options to translate.
- * @param {"flat"|"eslintrc"} [configType="eslintrc"] The format of the config to generate.
- * @returns {Promise<ESLintOptions | LegacyESLintOptions>} The options object for the ESLint constructor.
- */
- async function translateOptions(
- {
- cache,
- cacheFile,
- cacheLocation,
- cacheStrategy,
- concurrency,
- config,
- configLookup,
- env,
- errorOnUnmatchedPattern,
- eslintrc,
- ext,
- fix,
- fixDryRun,
- fixType,
- flag,
- global,
- ignore,
- ignorePath,
- ignorePattern,
- inlineConfig,
- parser,
- parserOptions,
- plugin,
- quiet,
- reportUnusedDisableDirectives,
- reportUnusedDisableDirectivesSeverity,
- reportUnusedInlineConfigs,
- resolvePluginsRelativeTo,
- rule,
- rulesdir,
- stats,
- warnIgnored,
- passOnNoPatterns,
- maxWarnings,
- },
- configType,
- ) {
- let overrideConfig, overrideConfigFile;
- const importer = new ModuleImporter();
- if (configType === "flat") {
- overrideConfigFile =
- typeof config === "string" ? config : !configLookup;
- if (overrideConfigFile === false) {
- overrideConfigFile = void 0;
- }
- const languageOptions = {};
- if (global) {
- languageOptions.globals = global.reduce((obj, name) => {
- if (name.endsWith(":true")) {
- obj[name.slice(0, -5)] = "writable";
- } else {
- obj[name] = "readonly";
- }
- return obj;
- }, {});
- }
- if (parserOptions) {
- languageOptions.parserOptions = parserOptions;
- }
- if (parser) {
- languageOptions.parser = await importer.import(parser);
- }
- overrideConfig = [
- {
- ...(Object.keys(languageOptions).length > 0
- ? { languageOptions }
- : {}),
- rules: rule ? rule : {},
- },
- ];
- if (
- reportUnusedDisableDirectives ||
- reportUnusedDisableDirectivesSeverity !== void 0
- ) {
- overrideConfig[0].linterOptions = {
- reportUnusedDisableDirectives: reportUnusedDisableDirectives
- ? "error"
- : normalizeSeverityToString(
- reportUnusedDisableDirectivesSeverity,
- ),
- };
- }
- if (reportUnusedInlineConfigs !== void 0) {
- overrideConfig[0].linterOptions = {
- ...overrideConfig[0].linterOptions,
- reportUnusedInlineConfigs: normalizeSeverityToString(
- reportUnusedInlineConfigs,
- ),
- };
- }
- if (plugin) {
- overrideConfig[0].plugins = await loadPlugins(importer, plugin);
- }
- if (ext) {
- overrideConfig.push({
- files: ext.map(
- extension =>
- `**/*${extension.startsWith(".") ? "" : "."}${extension}`,
- ),
- });
- }
- } else {
- overrideConfigFile = config;
- overrideConfig = {
- env:
- env &&
- env.reduce((obj, name) => {
- obj[name] = true;
- return obj;
- }, {}),
- globals:
- global &&
- global.reduce((obj, name) => {
- if (name.endsWith(":true")) {
- obj[name.slice(0, -5)] = "writable";
- } else {
- obj[name] = "readonly";
- }
- return obj;
- }, {}),
- ignorePatterns: ignorePattern,
- parser,
- parserOptions,
- plugins: plugin,
- rules: rule,
- };
- }
- const options = {
- allowInlineConfig: inlineConfig,
- cache,
- cacheLocation: cacheLocation || cacheFile,
- cacheStrategy,
- errorOnUnmatchedPattern,
- fix: (fix || fixDryRun) && (quiet ? quietFixPredicate : true),
- fixTypes: fixType,
- ignore,
- overrideConfig,
- overrideConfigFile,
- passOnNoPatterns,
- };
- if (configType === "flat") {
- options.concurrency = concurrency;
- options.flags = flag;
- options.ignorePatterns = ignorePattern;
- options.stats = stats;
- options.warnIgnored = warnIgnored;
- /*
- * For performance reasons rules not marked as 'error' are filtered out in quiet mode. As maxWarnings
- * requires rules set to 'warn' to be run, we only filter out 'warn' rules if maxWarnings is not specified.
- */
- options.ruleFilter =
- quiet && maxWarnings === -1 ? quietRuleFilter : () => true;
- } else {
- options.resolvePluginsRelativeTo = resolvePluginsRelativeTo;
- options.rulePaths = rulesdir;
- options.useEslintrc = eslintrc;
- options.extensions = ext;
- options.ignorePath = ignorePath;
- if (
- reportUnusedDisableDirectives ||
- reportUnusedDisableDirectivesSeverity !== void 0
- ) {
- options.reportUnusedDisableDirectives =
- reportUnusedDisableDirectives
- ? "error"
- : normalizeSeverityToString(
- reportUnusedDisableDirectivesSeverity,
- );
- }
- }
- return options;
- }
- module.exports = translateOptions;
|