]> git.proxmox.com Git - pve-eslint.git/blobdiff - eslint/lib/cli.js
import 8.23.1 source
[pve-eslint.git] / eslint / lib / cli.js
index f09d143d2557851d307047875fe9862616f2a12b..2fca65c1908b04820ac9d43e877a1bb0d146a55c 100644 (file)
@@ -6,7 +6,7 @@
 "use strict";
 
 /*
- * The CLI object should *not* call process.exit() directly. It should only return
+ * NOTE: The CLI object should *not* call process.exit() directly. It should only return
  * exit codes. This allows other programs to use the CLI object and still control
  * when the program exits.
  */
@@ -19,9 +19,14 @@ const fs = require("fs"),
     path = require("path"),
     { promisify } = require("util"),
     { ESLint } = require("./eslint"),
-    CLIOptions = require("./options"),
+    { FlatESLint } = require("./eslint/flat-eslint"),
+    createCLIOptions = require("./options"),
     log = require("./shared/logging"),
     RuntimeInfo = require("./shared/runtime-info");
+const { Legacy: { naming } } = require("@eslint/eslintrc");
+const { findFlatConfigFile } = require("./eslint/flat-eslint");
+const { gitignoreToMinimatch } = require("@humanwhocodes/gitignore-to-minimatch");
+const { ModuleImporter } = require("@humanwhocodes/module-importer");
 
 const debug = require("debug")("eslint:cli");
 
@@ -54,17 +59,20 @@ function quietFixPredicate(message) {
 }
 
 /**
- * Translates the CLI options into the options expected by the CLIEngine.
+ * Translates the CLI options into the options expected by the ESLint constructor.
  * @param {ParsedCLIOptions} cliOptions The CLI options to translate.
- * @returns {ESLintOptions} The options object for the CLIEngine.
+ * @param {"flat"|"eslintrc"} [configType="eslintrc"] The format of the
+ *      config to generate.
+ * @returns {Promise<ESLintOptions>} The options object for the ESLint constructor.
  * @private
  */
-function translateOptions({
+async function translateOptions({
     cache,
     cacheFile,
     cacheLocation,
     cacheStrategy,
     config,
+    configLookup,
     env,
     errorOnUnmatchedPattern,
     eslintrc,
@@ -85,19 +93,66 @@ function translateOptions({
     resolvePluginsRelativeTo,
     rule,
     rulesdir
-}) {
-    return {
-        allowInlineConfig: inlineConfig,
-        cache,
-        cacheLocation: cacheLocation || cacheFile,
-        cacheStrategy,
-        errorOnUnmatchedPattern,
-        extensions: ext,
-        fix: (fix || fixDryRun) && (quiet ? quietFixPredicate : true),
-        fixTypes: fixType,
-        ignore,
-        ignorePath,
-        overrideConfig: {
+}, configType) {
+
+    let overrideConfig, overrideConfigFile;
+    const importer = new ModuleImporter();
+
+    if (configType === "flat") {
+        overrideConfigFile = (typeof config === "string") ? config : !configLookup;
+        if (overrideConfigFile === false) {
+            overrideConfigFile = void 0;
+        }
+
+        let globals = {};
+
+        if (global) {
+            globals = global.reduce((obj, name) => {
+                if (name.endsWith(":true")) {
+                    obj[name.slice(0, -5)] = "writable";
+                } else {
+                    obj[name] = "readonly";
+                }
+                return obj;
+            }, globals);
+        }
+
+        overrideConfig = [{
+            languageOptions: {
+                globals,
+                parserOptions: parserOptions || {}
+            },
+            rules: rule ? rule : {}
+        }];
+
+        if (parser) {
+            overrideConfig[0].languageOptions.parser = await importer.import(parser);
+        }
+
+        if (plugin) {
+            const plugins = {};
+
+            for (const pluginName of plugin) {
+
+                const shortName = naming.getShorthandName(pluginName, "eslint-plugin");
+                const longName = naming.normalizePackageName(pluginName, "eslint-plugin");
+
+                plugins[shortName] = await importer.import(longName);
+            }
+
+            overrideConfig[0].plugins = plugins;
+        }
+
+        if (ignorePattern) {
+            overrideConfig.push({
+                ignores: ignorePattern.map(gitignoreToMinimatch)
+            });
+        }
+
+    } else {
+        overrideConfigFile = config;
+
+        overrideConfig = {
             env: env && env.reduce((obj, name) => {
                 obj[name] = true;
                 return obj;
@@ -115,13 +170,32 @@ function translateOptions({
             parserOptions,
             plugins: plugin,
             rules: rule
-        },
-        overrideConfigFile: config,
-        reportUnusedDisableDirectives: reportUnusedDisableDirectives ? "error" : void 0,
-        resolvePluginsRelativeTo,
-        rulePaths: rulesdir,
-        useEslintrc: eslintrc
+        };
+    }
+
+    const options = {
+        allowInlineConfig: inlineConfig,
+        cache,
+        cacheLocation: cacheLocation || cacheFile,
+        cacheStrategy,
+        errorOnUnmatchedPattern,
+        fix: (fix || fixDryRun) && (quiet ? quietFixPredicate : true),
+        fixTypes: fixType,
+        ignore,
+        ignorePath,
+        overrideConfig,
+        overrideConfigFile,
+        reportUnusedDisableDirectives: reportUnusedDisableDirectives ? "error" : void 0
     };
+
+    if (configType !== "flat") {
+        options.resolvePluginsRelativeTo = resolvePluginsRelativeTo;
+        options.rulePaths = rulesdir;
+        options.useEslintrc = eslintrc;
+        options.extensions = ext;
+    }
+
+    return options;
 }
 
 /**
@@ -218,19 +292,34 @@ const cli = {
      * Executes the CLI based on an array of arguments that is passed in.
      * @param {string|Array|Object} args The arguments to process.
      * @param {string} [text] The text to lint (used for TTY).
+     * @param {boolean} [allowFlatConfig] Whether or not to allow flat config.
      * @returns {Promise<number>} The exit code for the operation.
      */
-    async execute(args, text) {
+    async execute(args, text, allowFlatConfig) {
         if (Array.isArray(args)) {
             debug("CLI args: %o", args.slice(2));
         }
 
+        /*
+         * Before doing anything, we need to see if we are using a
+         * flat config file. If so, then we need to change the way command
+         * line args are parsed. This is temporary, and when we fully
+         * switch to flat config we can remove this logic.
+         */
+
+        const usingFlatConfig = allowFlatConfig && !!(await findFlatConfigFile(process.cwd()));
+
+        debug("Using flat config?", usingFlatConfig);
+
+        const CLIOptions = createCLIOptions(usingFlatConfig);
+
         /** @type {ParsedCLIOptions} */
         let options;
 
         try {
             options = CLIOptions.parse(args);
         } catch (error) {
+            debug("Error parsing CLI options:", error.message);
             log.error(error.message);
             return 2;
         }
@@ -251,6 +340,7 @@ const cli = {
                 log.info(RuntimeInfo.environment());
                 return 0;
             } catch (err) {
+                debug("Error retrieving environment info");
                 log.error(err.message);
                 return 2;
             }
@@ -266,7 +356,9 @@ const cli = {
                 return 2;
             }
 
-            const engine = new ESLint(translateOptions(options));
+            const engine = usingFlatConfig
+                ? new FlatESLint(await translateOptions(options, "flat"))
+                : new ESLint(await translateOptions(options));
             const fileConfig =
                 await engine.calculateConfigForFile(options.printConfig);
 
@@ -289,7 +381,9 @@ const cli = {
             return 2;
         }
 
-        const engine = new ESLint(translateOptions(options));
+        const ActiveESLint = usingFlatConfig ? FlatESLint : ESLint;
+
+        const engine = new ActiveESLint(await translateOptions(options, usingFlatConfig ? "flat" : "eslintrc"));
         let results;
 
         if (useStdin) {
@@ -303,14 +397,14 @@ const cli = {
 
         if (options.fix) {
             debug("Fix mode enabled - applying fixes");
-            await ESLint.outputFixes(results);
+            await ActiveESLint.outputFixes(results);
         }
 
         let resultsToPrint = results;
 
         if (options.quiet) {
             debug("Quiet mode enabled - filtering out warnings");
-            resultsToPrint = ESLint.getErrorResults(resultsToPrint);
+            resultsToPrint = ActiveESLint.getErrorResults(resultsToPrint);
         }
 
         if (await printResults(engine, resultsToPrint, options.format, options.outputFile)) {