Pull.
J'ai juste update le cutie.js, CONNARD Ah oui, j'ai aussi add le info.js, qui est merdique d'ailleurs
This commit is contained in:
7
node_modules/eslint/README.md
generated
vendored
7
node_modules/eslint/README.md
generated
vendored
@@ -277,6 +277,11 @@ Nitin Kumar
|
||||
The people who review and fix bugs and help triage issues.
|
||||
|
||||
<table><tbody><tr><td align="center" valign="top" width="11%">
|
||||
<a href="https://github.com/DMartens">
|
||||
<img src="https://github.com/DMartens.png?s=75" width="75" height="75" alt="fnx's Avatar"><br />
|
||||
fnx
|
||||
</a>
|
||||
</td><td align="center" valign="top" width="11%">
|
||||
<a href="https://github.com/JoshuaKGoldberg">
|
||||
<img src="https://github.com/JoshuaKGoldberg.png?s=75" width="75" height="75" alt="Josh Goldberg ✨'s Avatar"><br />
|
||||
Josh Goldberg ✨
|
||||
@@ -328,7 +333,7 @@ to get your logo on our READMEs and [website](https://eslint.org/sponsors).
|
||||
<p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="128"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="128"></a></p><h3>Gold Sponsors</h3>
|
||||
<p><a href="https://qlty.sh/"><img src="https://images.opencollective.com/qltysh/33d157d/logo.png" alt="Qlty Software" height="96"></a> <a href="https://trunk.io/"><img src="https://images.opencollective.com/trunkio/fb92d60/avatar.png" alt="trunk.io" height="96"></a> <a href="https://shopify.engineering/"><img src="https://avatars.githubusercontent.com/u/8085" alt="Shopify" height="96"></a></p><h3>Silver Sponsors</h3>
|
||||
<p><a href="https://vite.dev/"><img src="https://images.opencollective.com/vite/e6d15e1/logo.png" alt="Vite" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301" alt="American Express" height="64"></a> <a href="https://stackblitz.com"><img src="https://avatars.githubusercontent.com/u/28635252" alt="StackBlitz" height="64"></a></p><h3>Bronze Sponsors</h3>
|
||||
<p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104" alt="Nx" height="32"></a> <a href="https://opensource.mercedes-benz.com/"><img src="https://avatars.githubusercontent.com/u/34240465" alt="Mercedes-Benz Group" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a> <a href="https://www.lambdatest.com"><img src="https://avatars.githubusercontent.com/u/171592363" alt="LambdaTest" height="32"></a></p>
|
||||
<p><a href="https://syntax.fm"><img src="https://github.com/syntaxfm.png" alt="Syntax" height="32"></a> <a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://sentry.io"><img src="https://github.com/getsentry.png" alt="Sentry" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104" alt="Nx" height="32"></a> <a href="https://opensource.mercedes-benz.com/"><img src="https://avatars.githubusercontent.com/u/34240465" alt="Mercedes-Benz Group" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a> <a href="https://www.lambdatest.com"><img src="https://avatars.githubusercontent.com/u/171592363" alt="LambdaTest" height="32"></a></p>
|
||||
<h3>Technology Sponsors</h3>
|
||||
Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.
|
||||
<p><a href="https://netlify.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/netlify-icon.svg" alt="Netlify" height="32"></a> <a href="https://algolia.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/algolia-icon.svg" alt="Algolia" height="32"></a> <a href="https://1password.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/1password-icon.svg" alt="1Password" height="32"></a></p>
|
||||
|
||||
2
node_modules/eslint/lib/cli-engine/file-enumerator.js
generated
vendored
2
node_modules/eslint/lib/cli-engine/file-enumerator.js
generated
vendored
@@ -51,7 +51,7 @@ const debug = require("debug")("eslint:file-enumerator");
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const minimatchOpts = { dot: true, matchBase: true };
|
||||
const dotfilesPattern = /(?:(?:^\.)|(?:[/\\]\.))[^/\\.].*/u;
|
||||
const dotfilesPattern = /(?:^\.|[/\\]\.)[^/\\.].*/u;
|
||||
const NONE = 0;
|
||||
const IGNORED_SILENTLY = 1;
|
||||
const IGNORED = 2;
|
||||
|
||||
328
node_modules/eslint/lib/cli.js
generated
vendored
328
node_modules/eslint/lib/cli.js
generated
vendored
@@ -16,8 +16,9 @@
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const fs = require("node:fs"),
|
||||
{ mkdir, stat, writeFile } = require("node:fs/promises"),
|
||||
path = require("node:path"),
|
||||
{ promisify } = require("node:util"),
|
||||
{ pathToFileURL } = require("node:url"),
|
||||
{ LegacyESLint } = require("./eslint"),
|
||||
{
|
||||
ESLint,
|
||||
@@ -27,282 +28,23 @@ const fs = require("node:fs"),
|
||||
createCLIOptions = require("./options"),
|
||||
log = require("./shared/logging"),
|
||||
RuntimeInfo = require("./shared/runtime-info"),
|
||||
{ normalizeSeverityToString } = require("./shared/severity");
|
||||
const { ModuleImporter } = require("@humanwhocodes/module-importer");
|
||||
translateOptions = require("./shared/translate-cli-options");
|
||||
const { getCacheFile } = require("./eslint/eslint-helpers");
|
||||
const { SuppressionsService } = require("./services/suppressions-service");
|
||||
const debug = require("debug")("eslint:cli");
|
||||
const {
|
||||
normalizePackageName,
|
||||
getShorthandName,
|
||||
} = require("./shared/naming.js");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @import { ESLintOptions } from "./eslint/eslint.js" */
|
||||
|
||||
/** @typedef {import("./options").ParsedCLIOptions} ParsedCLIOptions */
|
||||
/** @typedef {import("./types").Linter.LintMessage} LintMessage */
|
||||
/** @typedef {import("./types").ESLint.LintResult} LintResult */
|
||||
/** @typedef {import("./types").ESLint.Plugin} Plugin */
|
||||
/** @typedef {import("./types").ESLint.ResultsMeta} ResultsMeta */
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const mkdir = promisify(fs.mkdir);
|
||||
const stat = promisify(fs.stat);
|
||||
const writeFile = promisify(fs.writeFile);
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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>} The options object for the ESLint constructor.
|
||||
* @private
|
||||
*/
|
||||
async function translateOptions(
|
||||
{
|
||||
cache,
|
||||
cacheFile,
|
||||
cacheLocation,
|
||||
cacheStrategy,
|
||||
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.ignorePatterns = ignorePattern;
|
||||
options.stats = stats;
|
||||
options.warnIgnored = warnIgnored;
|
||||
options.flags = flag;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count error messages.
|
||||
* @param {LintResult[]} results The lint results.
|
||||
@@ -322,6 +64,26 @@ function countErrors(results) {
|
||||
return { errorCount, fatalErrorCount, warningCount };
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an options module from the provided CLI options and encodes it as a data URL.
|
||||
* @param {ParsedCLIOptions} options The CLI options.
|
||||
* @returns {URL} The URL of the options module.
|
||||
*/
|
||||
function createOptionsModule(options) {
|
||||
const translateOptionsFileURL = new URL(
|
||||
"./shared/translate-cli-options.js",
|
||||
pathToFileURL(__filename),
|
||||
).href;
|
||||
const optionsSrc =
|
||||
`import translateOptions from ${JSON.stringify(translateOptionsFileURL)};\n` +
|
||||
`export default await translateOptions(${JSON.stringify(options)}, "flat");\n`;
|
||||
|
||||
// Base64 encoding is typically shorter than URL encoding
|
||||
return new URL(
|
||||
`data:text/javascript;base64,${Buffer.from(optionsSrc).toString("base64")}`,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given file path is a directory or not.
|
||||
* @param {string} filePath The path to a file to check.
|
||||
@@ -385,6 +147,30 @@ async function printResults(engine, results, format, outputFile, resultsMeta) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the `--concurrency` flag value.
|
||||
* @param {string} concurrency The `--concurrency` flag value to validate.
|
||||
* @returns {void}
|
||||
* @throws {Error} If the `--concurrency` flag value is invalid.
|
||||
*/
|
||||
function validateConcurrency(concurrency) {
|
||||
if (
|
||||
concurrency === void 0 ||
|
||||
concurrency === "auto" ||
|
||||
concurrency === "off"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const concurrencyValue = Number(concurrency);
|
||||
|
||||
if (!Number.isInteger(concurrencyValue) || concurrencyValue < 1) {
|
||||
throw new Error(
|
||||
`Option concurrency: '${concurrency}' is not a positive integer, 'auto' or 'off'.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -445,6 +231,7 @@ const cli = {
|
||||
|
||||
try {
|
||||
options = CLIOptions.parse(args);
|
||||
validateConcurrency(options.concurrency);
|
||||
} catch (error) {
|
||||
debug("Error parsing CLI options:", error.message);
|
||||
|
||||
@@ -614,11 +401,20 @@ const cli = {
|
||||
}
|
||||
|
||||
const ActiveESLint = usingFlatConfig ? ESLint : LegacyESLint;
|
||||
const eslintOptions = await translateOptions(
|
||||
options,
|
||||
usingFlatConfig ? "flat" : "eslintrc",
|
||||
);
|
||||
const engine = new ActiveESLint(eslintOptions);
|
||||
|
||||
/** @type {ESLint|LegacyESLint} */
|
||||
let engine;
|
||||
|
||||
if (options.concurrency && options.concurrency !== "off") {
|
||||
const optionsURL = createOptionsModule(options);
|
||||
engine = await ESLint.fromOptionsModule(optionsURL);
|
||||
} else {
|
||||
const eslintOptions = await translateOptions(
|
||||
options,
|
||||
usingFlatConfig ? "flat" : "eslintrc",
|
||||
);
|
||||
engine = new ActiveESLint(eslintOptions);
|
||||
}
|
||||
let results;
|
||||
|
||||
if (useStdin) {
|
||||
|
||||
2
node_modules/eslint/lib/config/flat-config-schema.js
generated
vendored
2
node_modules/eslint/lib/config/flat-config-schema.js
generated
vendored
@@ -230,7 +230,7 @@ function assertIsRuleSeverity(ruleId, value) {
|
||||
* @throws {TypeError} If the string isn't in the correct format.
|
||||
*/
|
||||
function assertIsPluginMemberName(value) {
|
||||
if (!/[@a-z0-9-_$]+(?:\/(?:[a-z0-9-_$]+))+$/iu.test(value)) {
|
||||
if (!/[\w\-@$]+(?:\/[\w\-$]+)+$/iu.test(value)) {
|
||||
throw new TypeError(
|
||||
`Expected string in the form "pluginName/objectName" but found "${value}".`,
|
||||
);
|
||||
|
||||
432
node_modules/eslint/lib/eslint/eslint-helpers.js
generated
vendored
432
node_modules/eslint/lib/eslint/eslint-helpers.js
generated
vendored
@@ -11,11 +11,17 @@
|
||||
|
||||
const path = require("node:path");
|
||||
const fs = require("node:fs");
|
||||
const { isMainThread, threadId } = require("node:worker_threads");
|
||||
const fsp = fs.promises;
|
||||
const isGlob = require("is-glob");
|
||||
const hash = require("../cli-engine/hash");
|
||||
const minimatch = require("minimatch");
|
||||
const globParent = require("glob-parent");
|
||||
const { Linter } = require("../linter");
|
||||
const { getShorthandName } = require("../shared/naming");
|
||||
const LintResultCache = require("../cli-engine/lint-result-cache");
|
||||
const { ConfigLoader, LegacyConfigLoader } = require("../config/config-loader");
|
||||
const createDebug = require("debug");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Fixup references
|
||||
@@ -30,11 +36,16 @@ const MINIMATCH_OPTIONS = { dot: true };
|
||||
|
||||
/**
|
||||
* @import { ESLintOptions } from "./eslint.js";
|
||||
* @import { ConfigLoader, LegacyConfigLoader } from "../config/config-loader.js";
|
||||
* @import { Config as CalculatedConfig } from "../config/config.js";
|
||||
* @import { FlatConfigArray } from "../config/flat-config-array.js";
|
||||
* @import { WarningService } from "../services/warning-service.js";
|
||||
* @import { Retrier } from "@humanwhocodes/retry";
|
||||
*/
|
||||
|
||||
/** @typedef {import("../types").Linter.Config} Config */
|
||||
/** @typedef {import("../types").Linter.LintMessage} LintMessage */
|
||||
/** @typedef {import("../types").ESLint.LintResult} LintResult */
|
||||
/** @typedef {import("../types").ESLint.Plugin} Plugin */
|
||||
|
||||
/**
|
||||
* @typedef {Object} GlobSearch
|
||||
@@ -43,6 +54,18 @@ const MINIMATCH_OPTIONS = { dot: true };
|
||||
* before doing any normalization.
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Internal Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const hrtimeBigint = process.hrtime.bigint;
|
||||
|
||||
createDebug.formatters.t = timeDiff =>
|
||||
`${(timeDiff + 500_000n) / 1_000_000n} ms`;
|
||||
const debug = createDebug(
|
||||
`eslint:eslint-helpers${isMainThread ? "" : `:thread-${threadId}`}`,
|
||||
);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Errors
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -137,6 +160,15 @@ function isEmptyArrayOrArrayOfNonEmptyString(value) {
|
||||
return Array.isArray(value) && value.every(isNonEmptyString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given value is a positive integer.
|
||||
* @param {unknown} value The value to check.
|
||||
* @returns {boolean} `true` if `value` is a positive integer.
|
||||
*/
|
||||
function isPositiveInteger(value) {
|
||||
return Number.isInteger(value) && value > 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// File-related Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -537,6 +569,7 @@ async function findFiles({
|
||||
filePaths.map(filePath => fsp.stat(filePath).catch(() => {})),
|
||||
);
|
||||
|
||||
const promises = [];
|
||||
stats.forEach((stat, index) => {
|
||||
const filePath = filePaths[index];
|
||||
const pattern = normalizeToPosix(patterns[index]);
|
||||
@@ -545,6 +578,7 @@ async function findFiles({
|
||||
// files are added directly to the list
|
||||
if (stat.isFile()) {
|
||||
results.push(filePath);
|
||||
promises.push(configLoader.loadConfigArrayForFile(filePath));
|
||||
}
|
||||
|
||||
// directories need extensions attached
|
||||
@@ -590,15 +624,28 @@ async function findFiles({
|
||||
}
|
||||
|
||||
// now we are safe to do the search
|
||||
const globbyResults = await globMultiSearch({
|
||||
searches,
|
||||
configLoader,
|
||||
errorOnUnmatchedPattern,
|
||||
});
|
||||
promises.push(
|
||||
globMultiSearch({
|
||||
searches,
|
||||
configLoader,
|
||||
errorOnUnmatchedPattern,
|
||||
}),
|
||||
);
|
||||
const globbyResults = (await Promise.all(promises)).at(-1);
|
||||
|
||||
return [...new Set([...results, ...globbyResults])];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the absolute path of a file named `"__placeholder__.js"` in a given directory.
|
||||
* This is used as a replacement for a missing file path.
|
||||
* @param {string} cwd An absolute directory path.
|
||||
* @returns {string} The absolute path of a file named `"__placeholder__.js"` in the given directory.
|
||||
*/
|
||||
function getPlaceholderPath(cwd) {
|
||||
return path.join(cwd, "__placeholder__.js");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Results-related Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -758,6 +805,7 @@ function processOptions({
|
||||
cache = false,
|
||||
cacheLocation = ".eslintcache",
|
||||
cacheStrategy = "metadata",
|
||||
concurrency = "off",
|
||||
cwd = process.cwd(),
|
||||
errorOnUnmatchedPattern = true,
|
||||
fix = false,
|
||||
@@ -853,6 +901,15 @@ function processOptions({
|
||||
if (cacheStrategy !== "metadata" && cacheStrategy !== "content") {
|
||||
errors.push('\'cacheStrategy\' must be any of "metadata", "content".');
|
||||
}
|
||||
if (
|
||||
concurrency !== "off" &&
|
||||
concurrency !== "auto" &&
|
||||
!isPositiveInteger(concurrency)
|
||||
) {
|
||||
errors.push(
|
||||
'\'concurrency\' must be a positive integer, "auto", or "off".',
|
||||
);
|
||||
}
|
||||
if (!isNonEmptyString(cwd) || !path.isAbsolute(cwd)) {
|
||||
errors.push("'cwd' must be an absolute path.");
|
||||
}
|
||||
@@ -928,6 +985,7 @@ function processOptions({
|
||||
cache,
|
||||
cacheLocation,
|
||||
cacheStrategy,
|
||||
concurrency,
|
||||
|
||||
// when overrideConfigFile is true that means don't do config file lookup
|
||||
configFile: overrideConfigFile === true ? false : overrideConfigFile,
|
||||
@@ -947,6 +1005,15 @@ function processOptions({
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads ESLint constructor options from an options module.
|
||||
* @param {string} optionsURL The URL string of the options module to load.
|
||||
* @returns {Promise<ESLintOptions>} ESLint constructor options.
|
||||
*/
|
||||
async function loadOptionsFromModule(optionsURL) {
|
||||
return (await import(optionsURL)).default;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Cache-related helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1022,6 +1089,349 @@ function getCacheFile(cacheFile, cwd, { prefix = ".cache_" } = {}) {
|
||||
return resolvedCacheFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new lint result cache.
|
||||
* @param {ESLintOptions} eslintOptions The processed ESLint options.
|
||||
* @param {string} cacheFilePath The path to the cache file.
|
||||
* @returns {?LintResultCache} A new lint result cache or `null`.
|
||||
*/
|
||||
function createLintResultCache({ cache, cacheStrategy }, cacheFilePath) {
|
||||
return cache ? new LintResultCache(cacheFilePath, cacheStrategy) : null;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Lint helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks whether a message's rule type should be fixed.
|
||||
* @param {LintMessage} message The message to check.
|
||||
* @param {CalculatedConfig} config The config for the file that generated the message.
|
||||
* @param {string[]} fixTypes An array of fix types to check.
|
||||
* @returns {boolean} Whether the message should be fixed.
|
||||
*/
|
||||
function shouldMessageBeFixed(message, config, fixTypes) {
|
||||
if (!message.ruleId) {
|
||||
return fixTypes.has("directive");
|
||||
}
|
||||
|
||||
const rule = message.ruleId && config.getRuleDefinition(message.ruleId);
|
||||
|
||||
return Boolean(rule && rule.meta && fixTypes.has(rule.meta.type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a fixer function based on the provided fix, fixTypesSet, and config.
|
||||
* @param {Function|boolean} fix The original fix option.
|
||||
* @param {Set<string>} fixTypesSet A set of fix types to filter messages for fixing.
|
||||
* @param {CalculatedConfig} config The config for the file that generated the message.
|
||||
* @returns {Function|boolean} The fixer function or the original fix value.
|
||||
*/
|
||||
function getFixerForFixTypes(fix, fixTypesSet, config) {
|
||||
if (!fix || !fixTypesSet) {
|
||||
return fix;
|
||||
}
|
||||
|
||||
const originalFix = typeof fix === "function" ? fix : () => true;
|
||||
|
||||
return message =>
|
||||
shouldMessageBeFixed(message, config, fixTypesSet) &&
|
||||
originalFix(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a source code using ESLint.
|
||||
* @param {Object} config The config object.
|
||||
* @param {string} config.text The source code to verify.
|
||||
* @param {string} config.cwd The path to the current working directory.
|
||||
* @param {string|undefined} config.filePath The path to the file of `text`. If this is undefined, it uses `<text>`.
|
||||
* @param {FlatConfigArray} config.configs The config.
|
||||
* @param {boolean} config.fix If `true` then it does fix.
|
||||
* @param {boolean} config.allowInlineConfig If `true` then it uses directive comments.
|
||||
* @param {Function} config.ruleFilter A predicate function to filter which rules should be run.
|
||||
* @param {boolean} config.stats If `true`, then if reports extra statistics with the lint results.
|
||||
* @param {Linter} config.linter The linter instance to verify.
|
||||
* @returns {LintResult} The result of linting.
|
||||
* @private
|
||||
*/
|
||||
function verifyText({
|
||||
text,
|
||||
cwd,
|
||||
filePath: providedFilePath,
|
||||
configs,
|
||||
fix,
|
||||
allowInlineConfig,
|
||||
ruleFilter,
|
||||
stats,
|
||||
linter,
|
||||
}) {
|
||||
const startTime = hrtimeBigint();
|
||||
|
||||
const filePath = providedFilePath || "<text>";
|
||||
|
||||
/*
|
||||
* Verify.
|
||||
* `config.extractConfig(filePath)` requires an absolute path, but `linter`
|
||||
* doesn't know CWD, so it gives `linter` an absolute path always.
|
||||
*/
|
||||
const filePathToVerify =
|
||||
filePath === "<text>" ? getPlaceholderPath(cwd) : filePath;
|
||||
const { fixed, messages, output } = linter.verifyAndFix(text, configs, {
|
||||
allowInlineConfig,
|
||||
filename: filePathToVerify,
|
||||
fix,
|
||||
ruleFilter,
|
||||
stats,
|
||||
|
||||
/**
|
||||
* Check if the linter should adopt a given code block or not.
|
||||
* @param {string} blockFilename The virtual filename of a code block.
|
||||
* @returns {boolean} `true` if the linter should adopt the code block.
|
||||
*/
|
||||
filterCodeBlock(blockFilename) {
|
||||
return configs.getConfig(blockFilename) !== void 0;
|
||||
},
|
||||
});
|
||||
|
||||
// Tweak and return.
|
||||
const result = {
|
||||
filePath: filePath === "<text>" ? filePath : path.resolve(filePath),
|
||||
messages,
|
||||
suppressedMessages: linter.getSuppressedMessages(),
|
||||
...calculateStatsPerFile(messages),
|
||||
};
|
||||
|
||||
if (fixed) {
|
||||
result.output = output;
|
||||
}
|
||||
|
||||
if (
|
||||
result.errorCount + result.warningCount > 0 &&
|
||||
typeof result.output === "undefined"
|
||||
) {
|
||||
result.source = text;
|
||||
}
|
||||
|
||||
if (stats) {
|
||||
result.stats = {
|
||||
times: linter.getTimes(),
|
||||
fixPasses: linter.getFixPassCount(),
|
||||
};
|
||||
}
|
||||
|
||||
const endTime = hrtimeBigint();
|
||||
debug('File "%s" linted in %t', filePath, endTime - startTime);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lints a single file.
|
||||
* @param {string} filePath File path to lint.
|
||||
* @param {FlatConfigArray} configs The config array for the file.
|
||||
* @param {ESLintOptions} eslintOptions The processed ESLint options.
|
||||
* @param {Linter} linter The linter instance to use.
|
||||
* @param {?LintResultCache} lintResultCache The result cache or `null`.
|
||||
* @param {?{ duration: bigint; }} readFileCounter Used to keep track of the time spent reading files.
|
||||
* @param {Retrier} [retrier] Used to retry linting on certain errors.
|
||||
* @param {AbortController} [controller] Used to stop linting when an error occurs.
|
||||
* @returns {Promise<LintResult>} The lint result.
|
||||
*/
|
||||
async function lintFile(
|
||||
filePath,
|
||||
configs,
|
||||
eslintOptions,
|
||||
linter,
|
||||
lintResultCache,
|
||||
readFileCounter,
|
||||
retrier,
|
||||
controller,
|
||||
) {
|
||||
const config = configs.getConfig(filePath);
|
||||
const {
|
||||
allowInlineConfig,
|
||||
cwd,
|
||||
fix,
|
||||
fixTypes,
|
||||
ruleFilter,
|
||||
stats,
|
||||
warnIgnored,
|
||||
} = eslintOptions;
|
||||
const fixTypesSet = fixTypes ? new Set(fixTypes) : null;
|
||||
|
||||
/*
|
||||
* If a filename was entered that cannot be matched
|
||||
* to a config, then notify the user.
|
||||
*/
|
||||
if (!config) {
|
||||
if (warnIgnored) {
|
||||
const configStatus = configs.getConfigStatus(filePath);
|
||||
|
||||
return createIgnoreResult(filePath, cwd, configStatus);
|
||||
}
|
||||
|
||||
return void 0;
|
||||
}
|
||||
|
||||
// Skip if there is cached result.
|
||||
if (lintResultCache) {
|
||||
const cachedResult = lintResultCache.getCachedLintResults(
|
||||
filePath,
|
||||
config,
|
||||
);
|
||||
|
||||
if (cachedResult) {
|
||||
const hadMessages =
|
||||
cachedResult.messages && cachedResult.messages.length > 0;
|
||||
|
||||
if (hadMessages && fix) {
|
||||
debug(`Reprocessing cached file to allow autofix: ${filePath}`);
|
||||
} else {
|
||||
debug(`Skipping file since it hasn't changed: ${filePath}`);
|
||||
return cachedResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set up fixer for fixTypes if necessary
|
||||
const fixer = getFixerForFixTypes(fix, fixTypesSet, config);
|
||||
|
||||
/**
|
||||
* Reads the file and lints its content.
|
||||
* @returns {Promise<LintResult>} A lint result.
|
||||
*/
|
||||
async function readAndVerifyFile() {
|
||||
const readFileEnterTime = hrtimeBigint();
|
||||
const text = await fsp.readFile(filePath, {
|
||||
encoding: "utf8",
|
||||
signal: controller?.signal,
|
||||
});
|
||||
const readFileExitTime = hrtimeBigint();
|
||||
const readFileDuration = readFileExitTime - readFileEnterTime;
|
||||
debug('File "%s" read in %t', filePath, readFileDuration);
|
||||
if (readFileCounter) {
|
||||
readFileCounter.duration += readFileDuration;
|
||||
}
|
||||
|
||||
// fail immediately if an error occurred in another file
|
||||
controller?.signal.throwIfAborted();
|
||||
|
||||
// do the linting
|
||||
return verifyText({
|
||||
text,
|
||||
filePath,
|
||||
configs,
|
||||
cwd,
|
||||
fix: fixer,
|
||||
allowInlineConfig,
|
||||
ruleFilter,
|
||||
stats,
|
||||
linter,
|
||||
});
|
||||
}
|
||||
|
||||
// Use the retrier if provided, otherwise just call the function.
|
||||
const readAndVerifyFilePromise = retrier
|
||||
? retrier.retry(readAndVerifyFile, { signal: controller?.signal })
|
||||
: readAndVerifyFile();
|
||||
|
||||
return readAndVerifyFilePromise.catch(error => {
|
||||
controller?.abort(error);
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves flags from the environment variable ESLINT_FLAGS.
|
||||
* @param {string[]} flags The flags defined via the API.
|
||||
* @returns {string[]} The merged flags to use.
|
||||
*/
|
||||
function mergeEnvironmentFlags(flags) {
|
||||
if (!process.env.ESLINT_FLAGS) {
|
||||
return flags;
|
||||
}
|
||||
|
||||
const envFlags = process.env.ESLINT_FLAGS.trim().split(/\s*,\s*/gu);
|
||||
return Array.from(new Set([...envFlags, ...flags]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new linter instance.
|
||||
* @param {ESLintOptions} eslintOptions The processed ESLint options.
|
||||
* @param {WarningService} warningService The warning service to use.
|
||||
* @returns {Linter} The linter instance.
|
||||
*/
|
||||
function createLinter({ cwd, flags }, warningService) {
|
||||
return new Linter({
|
||||
configType: "flat",
|
||||
cwd,
|
||||
flags: mergeEnvironmentFlags(flags),
|
||||
warningService,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates default configs with the specified plugins.
|
||||
* @param {Record<string, Plugin> | undefined} optionPlugins The plugins specified in the ESLint options.
|
||||
* @returns {Config[]} The default configs.
|
||||
*/
|
||||
function createDefaultConfigs(optionPlugins) {
|
||||
const defaultConfigs = [];
|
||||
|
||||
// Add plugins
|
||||
if (optionPlugins) {
|
||||
const plugins = {};
|
||||
|
||||
for (const [pluginName, plugin] of Object.entries(optionPlugins)) {
|
||||
plugins[getShorthandName(pluginName, "eslint-plugin")] = plugin;
|
||||
}
|
||||
|
||||
defaultConfigs.push({ plugins });
|
||||
}
|
||||
|
||||
return defaultConfigs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a config loader.
|
||||
* @param {ESLintOptions} eslintOptions The processed ESLint options.
|
||||
* @param {Config[]} defaultConfigs The default configs.
|
||||
* @param {Linter} linter The linter instance.
|
||||
* @param {WarningService} warningService The warning service to use.
|
||||
* @returns {ConfigLoader} The config loader.
|
||||
*/
|
||||
function createConfigLoader(
|
||||
{
|
||||
cwd,
|
||||
baseConfig,
|
||||
overrideConfig,
|
||||
configFile,
|
||||
ignore: ignoreEnabled,
|
||||
ignorePatterns,
|
||||
},
|
||||
defaultConfigs,
|
||||
linter,
|
||||
warningService,
|
||||
) {
|
||||
const configLoaderOptions = {
|
||||
cwd,
|
||||
baseConfig,
|
||||
overrideConfig,
|
||||
configFile,
|
||||
ignoreEnabled,
|
||||
ignorePatterns,
|
||||
defaultConfigs,
|
||||
hasUnstableNativeNodeJsTSConfigFlag: linter.hasFlag(
|
||||
"unstable_native_nodejs_ts_config",
|
||||
),
|
||||
warningService,
|
||||
};
|
||||
|
||||
return linter.hasFlag("v10_config_lookup_from_file")
|
||||
? new ConfigLoader(configLoaderOptions)
|
||||
: new LegacyConfigLoader(configLoaderOptions);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exports
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1035,8 +1445,18 @@ module.exports = {
|
||||
createIgnoreResult,
|
||||
isErrorMessage,
|
||||
calculateStatsPerFile,
|
||||
getPlaceholderPath,
|
||||
|
||||
processOptions,
|
||||
loadOptionsFromModule,
|
||||
|
||||
getCacheFile,
|
||||
createLintResultCache,
|
||||
|
||||
getFixerForFixTypes,
|
||||
verifyText,
|
||||
lintFile,
|
||||
createLinter,
|
||||
createDefaultConfigs,
|
||||
createConfigLoader,
|
||||
};
|
||||
|
||||
714
node_modules/eslint/lib/eslint/eslint.js
generated
vendored
714
node_modules/eslint/lib/eslint/eslint.js
generated
vendored
@@ -9,11 +9,13 @@
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const fs = require("node:fs/promises");
|
||||
const { existsSync } = require("node:fs");
|
||||
const fs = require("node:fs/promises");
|
||||
const os = require("node:os");
|
||||
const path = require("node:path");
|
||||
const { pathToFileURL } = require("node:url");
|
||||
const { SHARE_ENV, Worker } = require("node:worker_threads");
|
||||
const { version } = require("../../package.json");
|
||||
const { Linter } = require("../linter");
|
||||
const { defaultConfig } = require("../config/default-config");
|
||||
|
||||
const {
|
||||
@@ -25,14 +27,21 @@ const {
|
||||
|
||||
createIgnoreResult,
|
||||
isErrorMessage,
|
||||
calculateStatsPerFile,
|
||||
getPlaceholderPath,
|
||||
|
||||
processOptions,
|
||||
loadOptionsFromModule,
|
||||
|
||||
getFixerForFixTypes,
|
||||
verifyText,
|
||||
lintFile,
|
||||
createLinter,
|
||||
createLintResultCache,
|
||||
createDefaultConfigs,
|
||||
createConfigLoader,
|
||||
} = require("./eslint-helpers");
|
||||
const { pathToFileURL } = require("node:url");
|
||||
const LintResultCache = require("../cli-engine/lint-result-cache");
|
||||
const { Retrier } = require("@humanwhocodes/retry");
|
||||
const { ConfigLoader, LegacyConfigLoader } = require("../config/config-loader");
|
||||
const { ConfigLoader } = require("../config/config-loader");
|
||||
const { WarningService } = require("../services/warning-service");
|
||||
const { Config } = require("../config/config.js");
|
||||
const {
|
||||
@@ -53,16 +62,14 @@ const { resolve } = require("../shared/relative-module-resolver.js");
|
||||
|
||||
// For VSCode IntelliSense
|
||||
/**
|
||||
* @import { ConfigArray } from "../cli-engine/cli-engine.js";
|
||||
* @import { CLIEngineLintReport } from "./legacy-eslint.js";
|
||||
* @import { Config as CalculatedConfig } from "../config/config.js";
|
||||
* @import { FlatConfigArray } from "../config/flat-config-array.js";
|
||||
* @import { RuleDefinition } from "@eslint/core";
|
||||
* @import { RuleDefinition, RulesMeta } from "@eslint/core";
|
||||
* @import { WorkerLintResults } from "./worker.js";
|
||||
*/
|
||||
|
||||
/** @typedef {ReturnType<ConfigArray.extractConfig>} ExtractedConfig */
|
||||
/** @typedef {import("../types").Linter.Config} Config */
|
||||
/** @typedef {import("../types").ESLint.DeprecatedRuleUse} DeprecatedRuleInfo */
|
||||
/** @typedef {import("../types").Linter.LintMessage} LintMessage */
|
||||
/** @typedef {import("../types").ESLint.LintResult} LintResult */
|
||||
/** @typedef {import("../types").ESLint.Plugin} Plugin */
|
||||
/** @typedef {import("../types").ESLint.ResultsMeta} ResultsMeta */
|
||||
@@ -75,6 +82,7 @@ const { resolve } = require("../shared/relative-module-resolver.js");
|
||||
* @property {boolean} [cache] Enable result caching.
|
||||
* @property {string} [cacheLocation] The cache file to use instead of .eslintcache.
|
||||
* @property {"metadata" | "content"} [cacheStrategy] The strategy used to detect changed files.
|
||||
* @property {number | "auto" | "off"} [concurrency] Maximum number of linting threads, "auto" to choose automatically, "off" for no multithreading.
|
||||
* @property {string} [cwd] The value to use for the current working directory.
|
||||
* @property {boolean} [errorOnUnmatchedPattern] If `false` then `ESLint#lintFiles()` doesn't throw even if no target files found. Defaults to `true`.
|
||||
* @property {boolean|Function} [fix] Execute in autofix mode. If a function, should return a boolean.
|
||||
@@ -87,11 +95,11 @@ const { resolve } = require("../shared/relative-module-resolver.js");
|
||||
* @property {boolean|string} [overrideConfigFile] Searches for default config file when falsy;
|
||||
* doesn't do any config file lookup when `true`; considered to be a config filename
|
||||
* when a string.
|
||||
* @property {boolean} [passOnNoPatterns=false] When set to true, missing patterns cause
|
||||
* the linting operation to short circuit and not report any failures.
|
||||
* @property {Record<string,Plugin>} [plugins] An array of plugin implementations.
|
||||
* @property {boolean} [stats] True enables added statistics on lint results.
|
||||
* @property {boolean} [warnIgnored] Show warnings when the file list includes ignored files
|
||||
* @property {boolean} [passOnNoPatterns=false] When set to true, missing patterns cause
|
||||
* the linting operation to short circuit and not report any failures.
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -111,11 +119,12 @@ const removedFormatters = new Set([
|
||||
"unix",
|
||||
"visualstudio",
|
||||
]);
|
||||
const fileRetryCodes = new Set(["ENFILE", "EMFILE"]);
|
||||
|
||||
/**
|
||||
* Create rulesMeta object.
|
||||
* @param {Map<string,RuleDefinition>} rules a map of rules from which to generate the object.
|
||||
* @returns {Object} metadata for all enabled rules.
|
||||
* @param {Map<string, RuleDefinition>} rules a map of rules from which to generate the object.
|
||||
* @returns {Record<string, RulesMeta>} metadata for all enabled rules.
|
||||
*/
|
||||
function createRulesMeta(rules) {
|
||||
return Array.from(rules).reduce((retVal, [id, rule]) => {
|
||||
@@ -124,17 +133,7 @@ function createRulesMeta(rules) {
|
||||
}, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the absolute path of a file named `"__placeholder__.js"` in a given directory.
|
||||
* This is used as a replacement for a missing file path.
|
||||
* @param {string} cwd An absolute directory path.
|
||||
* @returns {string} The absolute path of a file named `"__placeholder__.js"` in the given directory.
|
||||
*/
|
||||
function getPlaceholderPath(cwd) {
|
||||
return path.join(cwd, "__placeholder__.js");
|
||||
}
|
||||
|
||||
/** @type {WeakMap<ExtractedConfig, DeprecatedRuleInfo[]>} */
|
||||
/** @type {WeakMap<CalculatedConfig, DeprecatedRuleInfo[]>} */
|
||||
const usedDeprecatedRulesCache = new WeakMap();
|
||||
|
||||
/**
|
||||
@@ -193,10 +192,10 @@ function getOrFindUsedDeprecatedRules(eslint, maybeFilePath) {
|
||||
* Processes the linting results generated by a CLIEngine linting report to
|
||||
* match the ESLint class's API.
|
||||
* @param {ESLint} eslint The ESLint instance.
|
||||
* @param {CLIEngineLintReport} report The CLIEngine linting report to process.
|
||||
* @param {LintResult[]} results The linting results to process.
|
||||
* @returns {LintResult[]} The processed linting results.
|
||||
*/
|
||||
function processLintReport(eslint, { results }) {
|
||||
function processLintReport(eslint, results) {
|
||||
const descriptor = {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
@@ -262,147 +261,296 @@ async function locateConfigFileToUse({ configFile, cwd }) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes an source code using ESLint.
|
||||
* @param {Object} config The config object.
|
||||
* @param {string} config.text The source code to verify.
|
||||
* @param {string} config.cwd The path to the current working directory.
|
||||
* @param {string|undefined} config.filePath The path to the file of `text`. If this is undefined, it uses `<text>`.
|
||||
* @param {FlatConfigArray} config.configs The config.
|
||||
* @param {boolean} config.fix If `true` then it does fix.
|
||||
* @param {boolean} config.allowInlineConfig If `true` then it uses directive comments.
|
||||
* @param {Function} config.ruleFilter A predicate function to filter which rules should be run.
|
||||
* @param {boolean} config.stats If `true`, then if reports extra statistics with the lint results.
|
||||
* @param {Linter} config.linter The linter instance to verify.
|
||||
* @returns {LintResult} The result of linting.
|
||||
* @private
|
||||
*/
|
||||
function verifyText({
|
||||
text,
|
||||
cwd,
|
||||
filePath: providedFilePath,
|
||||
configs,
|
||||
fix,
|
||||
allowInlineConfig,
|
||||
ruleFilter,
|
||||
stats,
|
||||
linter,
|
||||
}) {
|
||||
const filePath = providedFilePath || "<text>";
|
||||
|
||||
debug(`Lint ${filePath}`);
|
||||
|
||||
/*
|
||||
* Verify.
|
||||
* `config.extractConfig(filePath)` requires an absolute path, but `linter`
|
||||
* doesn't know CWD, so it gives `linter` an absolute path always.
|
||||
*/
|
||||
const filePathToVerify =
|
||||
filePath === "<text>" ? getPlaceholderPath(cwd) : filePath;
|
||||
const { fixed, messages, output } = linter.verifyAndFix(text, configs, {
|
||||
allowInlineConfig,
|
||||
filename: filePathToVerify,
|
||||
fix,
|
||||
ruleFilter,
|
||||
stats,
|
||||
|
||||
/**
|
||||
* Check if the linter should adopt a given code block or not.
|
||||
* @param {string} blockFilename The virtual filename of a code block.
|
||||
* @returns {boolean} `true` if the linter should adopt the code block.
|
||||
*/
|
||||
filterCodeBlock(blockFilename) {
|
||||
return configs.getConfig(blockFilename) !== void 0;
|
||||
},
|
||||
});
|
||||
|
||||
// Tweak and return.
|
||||
const result = {
|
||||
filePath: filePath === "<text>" ? filePath : path.resolve(filePath),
|
||||
messages,
|
||||
suppressedMessages: linter.getSuppressedMessages(),
|
||||
...calculateStatsPerFile(messages),
|
||||
};
|
||||
|
||||
if (fixed) {
|
||||
result.output = output;
|
||||
}
|
||||
|
||||
if (
|
||||
result.errorCount + result.warningCount > 0 &&
|
||||
typeof result.output === "undefined"
|
||||
) {
|
||||
result.source = text;
|
||||
}
|
||||
|
||||
if (stats) {
|
||||
result.stats = {
|
||||
times: linter.getTimes(),
|
||||
fixPasses: linter.getFixPassCount(),
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a message's rule type should be fixed.
|
||||
* @param {LintMessage} message The message to check.
|
||||
* @param {FlatConfigArray} config The config for the file that generated the message.
|
||||
* @param {string[]} fixTypes An array of fix types to check.
|
||||
* @returns {boolean} Whether the message should be fixed.
|
||||
*/
|
||||
function shouldMessageBeFixed(message, config, fixTypes) {
|
||||
if (!message.ruleId) {
|
||||
return fixTypes.has("directive");
|
||||
}
|
||||
|
||||
const rule = message.ruleId && config.getRuleDefinition(message.ruleId);
|
||||
|
||||
return Boolean(rule && rule.meta && fixTypes.has(rule.meta.type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an error to be thrown when an array of results passed to `getRulesMetaForResults` was not created by the current engine.
|
||||
* @param {Error|undefined} cause The original error that led to this symptom error being thrown. Might not always be available.
|
||||
* @returns {TypeError} An error object.
|
||||
*/
|
||||
function createExtraneousResultsError() {
|
||||
function createExtraneousResultsError(cause) {
|
||||
return new TypeError(
|
||||
"Results object was not created from this ESLint instance.",
|
||||
{
|
||||
cause,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a fixer function based on the provided fix, fixTypesSet, and config.
|
||||
* @param {Function|boolean} fix The original fix option.
|
||||
* @param {Set<string>} fixTypesSet A set of fix types to filter messages for fixing.
|
||||
* @param {FlatConfigArray} config The config for the file that generated the message.
|
||||
* @returns {Function|boolean} The fixer function or the original fix value.
|
||||
* Maximum number of files assumed to be best handled by one worker thread.
|
||||
* This value is a heuristic estimation that can be adjusted if required.
|
||||
*/
|
||||
function getFixerForFixTypes(fix, fixTypesSet, config) {
|
||||
if (!fix || !fixTypesSet) {
|
||||
return fix;
|
||||
const AUTO_FILES_PER_WORKER = 35;
|
||||
|
||||
/**
|
||||
* Calculates the number of workers to run based on the concurrency setting and the number of files to lint.
|
||||
* @param {number | "auto" | "off"} concurrency The normalized concurrency setting.
|
||||
* @param {number} fileCount The number of files to be linted.
|
||||
* @param {{ availableParallelism: () => number }} [os] Node.js `os` module, or a mock for testing.
|
||||
* @returns {number} The effective number of worker threads to be started. A value of zero disables multithread linting.
|
||||
*/
|
||||
function calculateWorkerCount(
|
||||
concurrency,
|
||||
fileCount,
|
||||
{ availableParallelism } = os,
|
||||
) {
|
||||
let workerCount;
|
||||
switch (concurrency) {
|
||||
case "off":
|
||||
return 0;
|
||||
case "auto": {
|
||||
workerCount = Math.min(
|
||||
availableParallelism() >> 1,
|
||||
Math.ceil(fileCount / AUTO_FILES_PER_WORKER),
|
||||
);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
workerCount = Math.min(concurrency, fileCount);
|
||||
break;
|
||||
}
|
||||
return workerCount > 1 ? workerCount : 0;
|
||||
}
|
||||
|
||||
// Used internally. Do not expose.
|
||||
const disableCloneabilityCheck = Symbol(
|
||||
"Do not check for uncloneable options.",
|
||||
);
|
||||
|
||||
/**
|
||||
* The smallest net linting ratio that doesn't trigger a poor concurrency warning.
|
||||
* The net linting ratio is defined as the net linting duration divided by the thread's total runtime,
|
||||
* where the net linting duration is the total linting time minus the time spent on I/O-intensive operations:
|
||||
* **Net Linting Ratio** = (**Linting Time** – **I/O Time**) / **Thread Runtime**.
|
||||
* - **Linting Time**: Total time spent linting files
|
||||
* - **I/O Time**: Portion of linting time spent loading configs and reading files
|
||||
* - **Thread Runtime**: End-to-end execution time of the thread
|
||||
*
|
||||
* This value is a heuristic estimation that can be adjusted if required.
|
||||
*/
|
||||
const LOW_NET_LINTING_RATIO = 0.7;
|
||||
|
||||
/**
|
||||
* Runs worker threads to lint files.
|
||||
* @param {string[]} filePaths File paths to lint.
|
||||
* @param {number} workerCount The number of worker threads to run.
|
||||
* @param {ESLintOptions | string} eslintOptionsOrURL The unprocessed ESLint options or the URL of the options module.
|
||||
* @param {() => void} warnOnLowNetLintingRatio A function to call if the net linting ratio is low.
|
||||
* @returns {Promise<LintResult[]>} Lint results.
|
||||
*/
|
||||
async function runWorkers(
|
||||
filePaths,
|
||||
workerCount,
|
||||
eslintOptionsOrURL,
|
||||
warnOnLowNetLintingRatio,
|
||||
) {
|
||||
const fileCount = filePaths.length;
|
||||
const results = Array(fileCount);
|
||||
const workerURL = pathToFileURL(path.join(__dirname, "./worker.js"));
|
||||
const filePathIndexArray = new Uint32Array(
|
||||
new SharedArrayBuffer(Uint32Array.BYTES_PER_ELEMENT),
|
||||
);
|
||||
const abortController = new AbortController();
|
||||
const abortSignal = abortController.signal;
|
||||
const workerOptions = {
|
||||
env: SHARE_ENV,
|
||||
workerData: {
|
||||
eslintOptionsOrURL,
|
||||
filePathIndexArray,
|
||||
filePaths,
|
||||
},
|
||||
};
|
||||
|
||||
const hrtimeBigint = process.hrtime.bigint;
|
||||
let worstNetLintingRatio = 1;
|
||||
|
||||
/**
|
||||
* A promise executor function that starts a worker thread on each invocation.
|
||||
* @param {() => void} resolve_ Called when the worker thread terminates successfully.
|
||||
* @param {(error: Error) => void} reject Called when the worker thread terminates with an error.
|
||||
* @returns {void}
|
||||
*/
|
||||
function workerExecutor(resolve_, reject) {
|
||||
const workerStartTime = hrtimeBigint();
|
||||
const worker = new Worker(workerURL, workerOptions);
|
||||
worker.once(
|
||||
"message",
|
||||
(/** @type {WorkerLintResults} */ indexedResults) => {
|
||||
const workerDuration = hrtimeBigint() - workerStartTime;
|
||||
|
||||
// The net linting ratio provides an approximate measure of worker thread efficiency, defined as the net linting duration divided by the thread's total runtime.
|
||||
const netLintingRatio =
|
||||
Number(indexedResults.netLintingDuration) /
|
||||
Number(workerDuration);
|
||||
|
||||
worstNetLintingRatio = Math.min(
|
||||
worstNetLintingRatio,
|
||||
netLintingRatio,
|
||||
);
|
||||
for (const result of indexedResults) {
|
||||
const { index } = result;
|
||||
delete result.index;
|
||||
results[index] = result;
|
||||
}
|
||||
resolve_();
|
||||
},
|
||||
);
|
||||
worker.once("error", error => {
|
||||
abortController.abort(error);
|
||||
reject(error);
|
||||
});
|
||||
abortSignal.addEventListener("abort", () => worker.terminate());
|
||||
}
|
||||
|
||||
const originalFix = typeof fix === "function" ? fix : () => true;
|
||||
const promises = Array(workerCount);
|
||||
for (let index = 0; index < workerCount; ++index) {
|
||||
promises[index] = new Promise(workerExecutor);
|
||||
}
|
||||
await Promise.all(promises);
|
||||
|
||||
return message =>
|
||||
shouldMessageBeFixed(message, config, fixTypesSet) &&
|
||||
originalFix(message);
|
||||
if (worstNetLintingRatio < LOW_NET_LINTING_RATIO) {
|
||||
warnOnLowNetLintingRatio();
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves flags from the environment variable ESLINT_FLAGS.
|
||||
* @param {string[]} flags The flags defined via the API.
|
||||
* @returns {string[]} The merged flags to use.
|
||||
* Lint files in multithread mode.
|
||||
* @param {ESLint} eslint ESLint instance.
|
||||
* @param {string[]} filePaths File paths to lint.
|
||||
* @param {number} workerCount The number of worker threads to run.
|
||||
* @param {ESLintOptions | string} eslintOptionsOrURL The unprocessed ESLint options or the URL of the options module.
|
||||
* @param {() => void} warnOnLowNetLintingRatio A function to call if the net linting ratio is low.
|
||||
* @returns {Promise<LintResult[]>} Lint results.
|
||||
*/
|
||||
function mergeEnvironmentFlags(flags) {
|
||||
if (!process.env.ESLINT_FLAGS) {
|
||||
return flags;
|
||||
}
|
||||
async function lintFilesWithMultithreading(
|
||||
eslint,
|
||||
filePaths,
|
||||
workerCount,
|
||||
eslintOptionsOrURL,
|
||||
warnOnLowNetLintingRatio,
|
||||
) {
|
||||
const { configLoader, lintResultCache } = privateMembers.get(eslint);
|
||||
|
||||
const envFlags = process.env.ESLINT_FLAGS.trim().split(/\s*,\s*/gu);
|
||||
return Array.from(new Set([...envFlags, ...flags]));
|
||||
const results = await runWorkers(
|
||||
filePaths,
|
||||
workerCount,
|
||||
eslintOptionsOrURL,
|
||||
warnOnLowNetLintingRatio,
|
||||
);
|
||||
// Persist the cache to disk.
|
||||
if (lintResultCache) {
|
||||
results.forEach((result, index) => {
|
||||
if (result) {
|
||||
const filePath = filePaths[index];
|
||||
const configs =
|
||||
configLoader.getCachedConfigArrayForFile(filePath);
|
||||
const config = configs.getConfig(filePath);
|
||||
|
||||
if (config) {
|
||||
/*
|
||||
* Store the lint result in the LintResultCache.
|
||||
* NOTE: The LintResultCache will remove the file source and any
|
||||
* other properties that are difficult to serialize, and will
|
||||
* hydrate those properties back in on future lint runs.
|
||||
*/
|
||||
lintResultCache.setCachedLintResults(
|
||||
filePath,
|
||||
config,
|
||||
result,
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lint files in single-thread mode.
|
||||
* @param {ESLint} eslint ESLint instance.
|
||||
* @param {string[]} filePaths File paths to lint.
|
||||
* @returns {Promise<LintResult[]>} Lint results.
|
||||
*/
|
||||
async function lintFilesWithoutMultithreading(eslint, filePaths) {
|
||||
const {
|
||||
configLoader,
|
||||
linter,
|
||||
lintResultCache,
|
||||
options: eslintOptions,
|
||||
} = privateMembers.get(eslint);
|
||||
|
||||
const controller = new AbortController();
|
||||
const retrier = new Retrier(error => fileRetryCodes.has(error.code), {
|
||||
concurrency: 100,
|
||||
});
|
||||
|
||||
/*
|
||||
* Because we need to process multiple files, including reading from disk,
|
||||
* it is most efficient to start by reading each file via promises so that
|
||||
* they can be done in parallel. Then, we can lint the returned text. This
|
||||
* ensures we are waiting the minimum amount of time in between lints.
|
||||
*/
|
||||
const results = await Promise.all(
|
||||
filePaths.map(async filePath => {
|
||||
const configs = configLoader.getCachedConfigArrayForFile(filePath);
|
||||
const config = configs.getConfig(filePath);
|
||||
|
||||
const result = await lintFile(
|
||||
filePath,
|
||||
configs,
|
||||
eslintOptions,
|
||||
linter,
|
||||
lintResultCache,
|
||||
null,
|
||||
retrier,
|
||||
controller,
|
||||
);
|
||||
|
||||
if (config) {
|
||||
/*
|
||||
* Store the lint result in the LintResultCache.
|
||||
* NOTE: The LintResultCache will remove the file source and any
|
||||
* other properties that are difficult to serialize, and will
|
||||
* hydrate those properties back in on future lint runs.
|
||||
*/
|
||||
lintResultCache?.setCachedLintResults(filePath, config, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}),
|
||||
);
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an error if the given options are not cloneable.
|
||||
* @param {ESLintOptions} options The options to check.
|
||||
* @returns {void}
|
||||
* @throws {TypeError} If the options are not cloneable.
|
||||
*/
|
||||
function validateOptionCloneability(options) {
|
||||
try {
|
||||
structuredClone(options);
|
||||
return;
|
||||
} catch {
|
||||
// continue
|
||||
}
|
||||
const uncloneableOptionKeys = Object.keys(options)
|
||||
.filter(key => {
|
||||
try {
|
||||
structuredClone(options[key]);
|
||||
} catch {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.sort();
|
||||
const error = new TypeError(
|
||||
`The ${uncloneableOptionKeys.length === 1 ? "option" : "options"} ${new Intl.ListFormat("en-US").format(uncloneableOptionKeys.map(key => `"${key}"`))} cannot be cloned. When concurrency is enabled, all options must be cloneable values (JSON values). Remove uncloneable options or use an options module.`,
|
||||
);
|
||||
error.code = "ESLINT_UNCLONEABLE_OPTIONS";
|
||||
throw error;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -421,51 +569,51 @@ class ESLint {
|
||||
|
||||
/**
|
||||
* The loader to use for finding config files.
|
||||
* @type {ConfigLoader|LegacyConfigLoader}
|
||||
* @type {ConfigLoader}
|
||||
*/
|
||||
#configLoader;
|
||||
|
||||
/**
|
||||
* The unprocessed options or the URL of the options module. Only set when concurrency is enabled.
|
||||
* @type {ESLintOptions | string | undefined}
|
||||
*/
|
||||
#optionsOrURL;
|
||||
|
||||
/**
|
||||
* Creates a new instance of the main ESLint API.
|
||||
* @param {ESLintOptions} options The options for this instance.
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
const defaultConfigs = [];
|
||||
const processedOptions = processOptions(options);
|
||||
if (
|
||||
!options[disableCloneabilityCheck] &&
|
||||
processedOptions.concurrency !== "off"
|
||||
) {
|
||||
validateOptionCloneability(options);
|
||||
|
||||
// Save the unprocessed options in an instance field to pass to worker threads in `lintFiles()`.
|
||||
this.#optionsOrURL = options;
|
||||
}
|
||||
const warningService = new WarningService();
|
||||
const linter = new Linter({
|
||||
cwd: processedOptions.cwd,
|
||||
configType: "flat",
|
||||
flags: mergeEnvironmentFlags(processedOptions.flags),
|
||||
warningService,
|
||||
});
|
||||
const linter = createLinter(processedOptions, warningService);
|
||||
|
||||
const cacheFilePath = getCacheFile(
|
||||
processedOptions.cacheLocation,
|
||||
processedOptions.cwd,
|
||||
);
|
||||
|
||||
const lintResultCache = processedOptions.cache
|
||||
? new LintResultCache(cacheFilePath, processedOptions.cacheStrategy)
|
||||
: null;
|
||||
const lintResultCache = createLintResultCache(
|
||||
processedOptions,
|
||||
cacheFilePath,
|
||||
);
|
||||
const defaultConfigs = createDefaultConfigs(options.plugins);
|
||||
|
||||
const configLoaderOptions = {
|
||||
cwd: processedOptions.cwd,
|
||||
baseConfig: processedOptions.baseConfig,
|
||||
overrideConfig: processedOptions.overrideConfig,
|
||||
configFile: processedOptions.configFile,
|
||||
ignoreEnabled: processedOptions.ignore,
|
||||
ignorePatterns: processedOptions.ignorePatterns,
|
||||
this.#configLoader = createConfigLoader(
|
||||
processedOptions,
|
||||
defaultConfigs,
|
||||
hasUnstableNativeNodeJsTSConfigFlag: linter.hasFlag(
|
||||
"unstable_native_nodejs_ts_config",
|
||||
),
|
||||
linter,
|
||||
warningService,
|
||||
};
|
||||
|
||||
this.#configLoader = linter.hasFlag("v10_config_lookup_from_file")
|
||||
? new ConfigLoader(configLoaderOptions)
|
||||
: new LegacyConfigLoader(configLoaderOptions);
|
||||
);
|
||||
|
||||
debug(`Using config loader ${this.#configLoader.constructor.name}`);
|
||||
|
||||
@@ -477,26 +625,9 @@ class ESLint {
|
||||
defaultConfigs,
|
||||
configs: null,
|
||||
configLoader: this.#configLoader,
|
||||
warningService,
|
||||
});
|
||||
|
||||
/**
|
||||
* If additional plugins are passed in, add that to the default
|
||||
* configs for this instance.
|
||||
*/
|
||||
if (options.plugins) {
|
||||
const plugins = {};
|
||||
|
||||
for (const [pluginName, plugin] of Object.entries(
|
||||
options.plugins,
|
||||
)) {
|
||||
plugins[getShorthandName(pluginName, "eslint-plugin")] = plugin;
|
||||
}
|
||||
|
||||
defaultConfigs.push({
|
||||
plugins,
|
||||
});
|
||||
}
|
||||
|
||||
// Check for the .eslintignore file, and warn if it's present.
|
||||
if (existsSync(path.resolve(processedOptions.cwd, ".eslintignore"))) {
|
||||
warningService.emitESLintIgnoreWarning();
|
||||
@@ -514,7 +645,7 @@ class ESLint {
|
||||
/**
|
||||
* The default configuration that ESLint uses internally. This is provided for tooling that wants to calculate configurations using the same defaults as ESLint.
|
||||
* Keep in mind that the default configuration may change from version to version, so you shouldn't rely on any particular keys or values to be present.
|
||||
* @type {ConfigArray}
|
||||
* @type {FlatConfigArray}
|
||||
*/
|
||||
static get defaultConfig() {
|
||||
return defaultConfig;
|
||||
@@ -530,8 +661,7 @@ class ESLint {
|
||||
throw new Error("'results' must be an array");
|
||||
}
|
||||
|
||||
const retryCodes = new Set(["ENFILE", "EMFILE"]);
|
||||
const retrier = new Retrier(error => retryCodes.has(error.code), {
|
||||
const retrier = new Retrier(error => fileRetryCodes.has(error.code), {
|
||||
concurrency: 100,
|
||||
});
|
||||
|
||||
@@ -581,10 +711,31 @@ class ESLint {
|
||||
return filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ESLint instance using options loaded from a module.
|
||||
* @param {URL} optionsURL The URL of the options module.
|
||||
* @returns {ESLint} The new ESLint instance.
|
||||
*/
|
||||
static async fromOptionsModule(optionsURL) {
|
||||
if (!(optionsURL instanceof URL)) {
|
||||
throw new TypeError("Argument must be a URL object");
|
||||
}
|
||||
const optionsURLString = optionsURL.href;
|
||||
const loadedOptions = await loadOptionsFromModule(optionsURLString);
|
||||
const options = { ...loadedOptions, [disableCloneabilityCheck]: true };
|
||||
const eslint = new ESLint(options);
|
||||
|
||||
if (options.concurrency !== "off") {
|
||||
// Save the options module URL in an instance field to pass to worker threads in `lintFiles()`.
|
||||
eslint.#optionsOrURL = optionsURLString;
|
||||
}
|
||||
return eslint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns meta objects for each rule represented in the lint results.
|
||||
* @param {LintResult[]} results The results to fetch rules meta for.
|
||||
* @returns {Object} A mapping of ruleIds to rule meta objects.
|
||||
* @returns {Record<string, RulesMeta>} A mapping of ruleIds to rule meta objects.
|
||||
* @throws {TypeError} When the results object wasn't created from this ESLint instance.
|
||||
* @throws {TypeError} When a plugin or rule is missing.
|
||||
*/
|
||||
@@ -626,8 +777,8 @@ class ESLint {
|
||||
try {
|
||||
configs =
|
||||
configLoader.getCachedConfigArrayForFile(filePath);
|
||||
} catch {
|
||||
throw createExtraneousResultsError();
|
||||
} catch (err) {
|
||||
throw createExtraneousResultsError(err);
|
||||
}
|
||||
|
||||
const config = configs.getConfig(filePath);
|
||||
@@ -667,8 +818,8 @@ class ESLint {
|
||||
const {
|
||||
cacheFilePath,
|
||||
lintResultCache,
|
||||
linter,
|
||||
options: eslintOptions,
|
||||
warningService,
|
||||
} = privateMembers.get(this);
|
||||
|
||||
/*
|
||||
@@ -709,19 +860,12 @@ class ESLint {
|
||||
debug(`Using file patterns: ${normalizedPatterns}`);
|
||||
|
||||
const {
|
||||
allowInlineConfig,
|
||||
cache,
|
||||
concurrency,
|
||||
cwd,
|
||||
fix,
|
||||
fixTypes,
|
||||
ruleFilter,
|
||||
stats,
|
||||
globInputPaths,
|
||||
errorOnUnmatchedPattern,
|
||||
warnIgnored,
|
||||
} = eslintOptions;
|
||||
const startTime = Date.now();
|
||||
const fixTypesSet = fixTypes ? new Set(fixTypes) : null;
|
||||
|
||||
// Delete cache file; should this be done here?
|
||||
if (!cache && cacheFilePath) {
|
||||
@@ -738,6 +882,7 @@ class ESLint {
|
||||
}
|
||||
}
|
||||
|
||||
const startTime = Date.now();
|
||||
const filePaths = await findFiles({
|
||||
patterns: normalizedPatterns,
|
||||
cwd,
|
||||
@@ -745,119 +890,45 @@ class ESLint {
|
||||
configLoader: this.#configLoader,
|
||||
errorOnUnmatchedPattern,
|
||||
});
|
||||
const controller = new AbortController();
|
||||
const retryCodes = new Set(["ENFILE", "EMFILE"]);
|
||||
const retrier = new Retrier(error => retryCodes.has(error.code), {
|
||||
concurrency: 100,
|
||||
});
|
||||
|
||||
debug(
|
||||
`${filePaths.length} files found in: ${Date.now() - startTime}ms`,
|
||||
);
|
||||
|
||||
/*
|
||||
* Because we need to process multiple files, including reading from disk,
|
||||
* it is most efficient to start by reading each file via promises so that
|
||||
* they can be done in parallel. Then, we can lint the returned text. This
|
||||
* ensures we are waiting the minimum amount of time in between lints.
|
||||
*/
|
||||
const results = await Promise.all(
|
||||
filePaths.map(async filePath => {
|
||||
const configs =
|
||||
await this.#configLoader.loadConfigArrayForFile(filePath);
|
||||
const config = configs.getConfig(filePath);
|
||||
/** @type {LintResult[]} */
|
||||
let results;
|
||||
|
||||
/*
|
||||
* If a filename was entered that cannot be matched
|
||||
* to a config, then notify the user.
|
||||
*/
|
||||
if (!config) {
|
||||
if (warnIgnored) {
|
||||
const configStatus = configs.getConfigStatus(filePath);
|
||||
|
||||
return createIgnoreResult(filePath, cwd, configStatus);
|
||||
}
|
||||
|
||||
return void 0;
|
||||
}
|
||||
|
||||
// Skip if there is cached result.
|
||||
if (lintResultCache) {
|
||||
const cachedResult = lintResultCache.getCachedLintResults(
|
||||
filePath,
|
||||
config,
|
||||
);
|
||||
|
||||
if (cachedResult) {
|
||||
const hadMessages =
|
||||
cachedResult.messages &&
|
||||
cachedResult.messages.length > 0;
|
||||
|
||||
if (hadMessages && fix) {
|
||||
debug(
|
||||
`Reprocessing cached file to allow autofix: ${filePath}`,
|
||||
);
|
||||
} else {
|
||||
debug(
|
||||
`Skipping file since it hasn't changed: ${filePath}`,
|
||||
);
|
||||
return cachedResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set up fixer for fixTypes if necessary
|
||||
const fixer = getFixerForFixTypes(fix, fixTypesSet, config);
|
||||
|
||||
return retrier
|
||||
.retry(
|
||||
() =>
|
||||
fs
|
||||
.readFile(filePath, {
|
||||
encoding: "utf8",
|
||||
signal: controller.signal,
|
||||
})
|
||||
.then(text => {
|
||||
// fail immediately if an error occurred in another file
|
||||
controller.signal.throwIfAborted();
|
||||
|
||||
// do the linting
|
||||
const result = verifyText({
|
||||
text,
|
||||
filePath,
|
||||
configs,
|
||||
cwd,
|
||||
fix: fixer,
|
||||
allowInlineConfig,
|
||||
ruleFilter,
|
||||
stats,
|
||||
linter,
|
||||
});
|
||||
|
||||
/*
|
||||
* Store the lint result in the LintResultCache.
|
||||
* NOTE: The LintResultCache will remove the file source and any
|
||||
* other properties that are difficult to serialize, and will
|
||||
* hydrate those properties back in on future lint runs.
|
||||
*/
|
||||
if (lintResultCache) {
|
||||
lintResultCache.setCachedLintResults(
|
||||
filePath,
|
||||
config,
|
||||
result,
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}),
|
||||
{ signal: controller.signal },
|
||||
)
|
||||
.catch(error => {
|
||||
controller.abort(error);
|
||||
throw error;
|
||||
});
|
||||
}),
|
||||
// The value of `module.exports.calculateWorkerCount` can be overridden in tests.
|
||||
const workerCount = module.exports.calculateWorkerCount(
|
||||
concurrency,
|
||||
filePaths.length,
|
||||
);
|
||||
if (workerCount) {
|
||||
debug(`Linting using ${workerCount} worker thread(s).`);
|
||||
let poorConcurrencyNotice;
|
||||
if (workerCount <= 2) {
|
||||
poorConcurrencyNotice = "disable concurrency";
|
||||
} else {
|
||||
if (concurrency === "auto") {
|
||||
poorConcurrencyNotice =
|
||||
"disable concurrency or use a numeric concurrency setting";
|
||||
} else {
|
||||
poorConcurrencyNotice = "reduce or disable concurrency";
|
||||
}
|
||||
}
|
||||
results = await lintFilesWithMultithreading(
|
||||
this,
|
||||
filePaths,
|
||||
workerCount,
|
||||
this.#optionsOrURL,
|
||||
() =>
|
||||
warningService.emitPoorConcurrencyWarning(
|
||||
poorConcurrencyNotice,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
debug(`Linting in single-thread mode.`);
|
||||
results = await lintFilesWithoutMultithreading(this, filePaths);
|
||||
}
|
||||
|
||||
// Persist the cache to disk.
|
||||
if (lintResultCache) {
|
||||
@@ -866,9 +937,7 @@ class ESLint {
|
||||
|
||||
const finalResults = results.filter(result => !!result);
|
||||
|
||||
return processLintReport(this, {
|
||||
results: finalResults,
|
||||
});
|
||||
return processLintReport(this, finalResults);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -977,9 +1046,7 @@ class ESLint {
|
||||
|
||||
debug(`Linting complete in: ${Date.now() - startTime}ms`);
|
||||
|
||||
return processLintReport(this, {
|
||||
results,
|
||||
});
|
||||
return processLintReport(this, results);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1089,7 +1156,7 @@ class ESLint {
|
||||
* This is the same logic used by the ESLint CLI executable to determine
|
||||
* configuration for each file it processes.
|
||||
* @param {string} filePath The path of the file to retrieve a config object for.
|
||||
* @returns {Promise<Config|undefined>} A configuration object for the file
|
||||
* @returns {Promise<CalculatedConfig|undefined>} A configuration object for the file
|
||||
* or `undefined` if there is no configuration data for the object.
|
||||
*/
|
||||
async calculateConfigForFile(filePath) {
|
||||
@@ -1161,4 +1228,5 @@ module.exports = {
|
||||
ESLint,
|
||||
shouldUseFlatConfig,
|
||||
locateConfigFileToUse,
|
||||
calculateWorkerCount,
|
||||
};
|
||||
|
||||
164
node_modules/eslint/lib/eslint/worker.js
generated
vendored
Normal file
164
node_modules/eslint/lib/eslint/worker.js
generated
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
* @fileoverview Worker thread for multithread linting.
|
||||
* @author Francesco Trotta
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const hrtimeBigint = process.hrtime.bigint;
|
||||
|
||||
const startTime = hrtimeBigint();
|
||||
|
||||
// eslint-disable-next-line n/no-unsupported-features/node-builtins -- enable V8's code cache if supported
|
||||
require("node:module").enableCompileCache?.();
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const { parentPort, threadId, workerData } = require("node:worker_threads");
|
||||
const createDebug = require("debug");
|
||||
const {
|
||||
createConfigLoader,
|
||||
createDefaultConfigs,
|
||||
createLinter,
|
||||
createLintResultCache,
|
||||
getCacheFile,
|
||||
lintFile,
|
||||
loadOptionsFromModule,
|
||||
processOptions,
|
||||
} = require("./eslint-helpers");
|
||||
const { WarningService } = require("../services/warning-service");
|
||||
|
||||
const depsLoadedTime = hrtimeBigint();
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Typedefs
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @typedef {import("../types").ESLint.LintResult} LintResult */
|
||||
/** @typedef {import("../types").ESLint.Options} ESLintOptions */
|
||||
/** @typedef {LintResult & { index?: number; }} IndexedLintResult */
|
||||
/** @typedef {IndexedLintResult[] & { netLintingDuration: bigint; }} WorkerLintResults */
|
||||
/**
|
||||
* @typedef {Object} WorkerData - Data passed to the worker thread.
|
||||
* @property {ESLintOptions | string} eslintOptionsOrURL - The unprocessed ESLint options or the URL of the options module.
|
||||
* @property {Uint32Array<SharedArrayBuffer>} filePathIndexArray - Shared counter used to track the next file to lint.
|
||||
* @property {string[]} filePaths - File paths to lint.
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const debug = createDebug(`eslint:worker:thread-${threadId}`);
|
||||
createDebug.formatters.t = timeDiff =>
|
||||
`${(timeDiff + 500_000n) / 1_000_000n} ms`;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Main
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
debug("Dependencies loaded in %t", depsLoadedTime - startTime);
|
||||
|
||||
(async () => {
|
||||
/** @type {WorkerData} */
|
||||
const { eslintOptionsOrURL, filePathIndexArray, filePaths } = workerData;
|
||||
const eslintOptions =
|
||||
typeof eslintOptionsOrURL === "object"
|
||||
? eslintOptionsOrURL
|
||||
: await loadOptionsFromModule(eslintOptionsOrURL);
|
||||
const processedESLintOptions = processOptions(eslintOptions);
|
||||
|
||||
const warningService = new WarningService();
|
||||
|
||||
// These warnings are always emitted by the controlling thread.
|
||||
warningService.emitEmptyConfigWarning =
|
||||
warningService.emitInactiveFlagWarning = () => {};
|
||||
|
||||
const linter = createLinter(processedESLintOptions, warningService);
|
||||
|
||||
const cacheFilePath = getCacheFile(
|
||||
processedESLintOptions.cacheLocation,
|
||||
processedESLintOptions.cwd,
|
||||
);
|
||||
|
||||
const lintResultCache = createLintResultCache(
|
||||
processedESLintOptions,
|
||||
cacheFilePath,
|
||||
);
|
||||
const defaultConfigs = createDefaultConfigs(eslintOptions.plugins);
|
||||
|
||||
const configLoader = createConfigLoader(
|
||||
processedESLintOptions,
|
||||
defaultConfigs,
|
||||
linter,
|
||||
warningService,
|
||||
);
|
||||
|
||||
/** @type {WorkerLintResults} */
|
||||
const indexedResults = [];
|
||||
let loadConfigTotalDuration = 0n;
|
||||
const readFileCounter = { duration: 0n };
|
||||
|
||||
const lintingStartTime = hrtimeBigint();
|
||||
debug(
|
||||
"Linting started %t after dependencies loaded",
|
||||
lintingStartTime - depsLoadedTime,
|
||||
);
|
||||
|
||||
for (;;) {
|
||||
const fileLintingStartTime = hrtimeBigint();
|
||||
|
||||
// It seems hard to produce an arithmetic overflow under realistic conditions here.
|
||||
const index = Atomics.add(filePathIndexArray, 0, 1);
|
||||
|
||||
const filePath = filePaths[index];
|
||||
if (!filePath) {
|
||||
break;
|
||||
}
|
||||
|
||||
const loadConfigEnterTime = hrtimeBigint();
|
||||
const configs = await configLoader.loadConfigArrayForFile(filePath);
|
||||
const loadConfigExitTime = hrtimeBigint();
|
||||
const loadConfigDuration = loadConfigExitTime - loadConfigEnterTime;
|
||||
debug(
|
||||
'Config array for file "%s" loaded in %t',
|
||||
filePath,
|
||||
loadConfigDuration,
|
||||
);
|
||||
loadConfigTotalDuration += loadConfigDuration;
|
||||
|
||||
/** @type {IndexedLintResult} */
|
||||
const result = await lintFile(
|
||||
filePath,
|
||||
configs,
|
||||
processedESLintOptions,
|
||||
linter,
|
||||
lintResultCache,
|
||||
readFileCounter,
|
||||
);
|
||||
if (result) {
|
||||
result.index = index;
|
||||
indexedResults.push(result);
|
||||
}
|
||||
|
||||
const fileLintingEndTime = hrtimeBigint();
|
||||
debug(
|
||||
'File "%s" processed in %t',
|
||||
filePath,
|
||||
fileLintingEndTime - fileLintingStartTime,
|
||||
);
|
||||
}
|
||||
|
||||
const lintingDuration = hrtimeBigint() - lintingStartTime;
|
||||
|
||||
/*
|
||||
* The net linting duration is the total linting time minus the time spent loading configs and reading files.
|
||||
* It captures the processing time dedicated to computation-intensive tasks that are highly parallelizable and not repeated across threads.
|
||||
*/
|
||||
indexedResults.netLintingDuration =
|
||||
lintingDuration - loadConfigTotalDuration - readFileCounter.duration;
|
||||
|
||||
parentPort.postMessage(indexedResults);
|
||||
})();
|
||||
7
node_modules/eslint/lib/languages/js/source-code/source-code.js
generated
vendored
7
node_modules/eslint/lib/languages/js/source-code/source-code.js
generated
vendored
@@ -1056,7 +1056,7 @@ class SourceCode extends TokenStore {
|
||||
// only certain comment types are supported as line comments
|
||||
return (
|
||||
comment.type !== "Line" ||
|
||||
!!/^eslint-disable-(next-)?line$/u.test(directive.label)
|
||||
!!/^eslint-disable-(?:next-)?line$/u.test(directive.label)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1091,9 +1091,8 @@ class SourceCode extends TokenStore {
|
||||
} = commentParser.parseDirective(comment.value);
|
||||
|
||||
// Step 2: Extract the directive value
|
||||
const lineCommentSupported = /^eslint-disable-(next-)?line$/u.test(
|
||||
label,
|
||||
);
|
||||
const lineCommentSupported =
|
||||
/^eslint-disable-(?:next-)?line$/u.test(label);
|
||||
|
||||
if (comment.type === "Line" && !lineCommentSupported) {
|
||||
return;
|
||||
|
||||
3
node_modules/eslint/lib/linter/esquery.js
generated
vendored
3
node_modules/eslint/lib/linter/esquery.js
generated
vendored
@@ -271,6 +271,9 @@ function tryParseSelector(selector) {
|
||||
) {
|
||||
throw new SyntaxError(
|
||||
`Syntax error in selector "${selector}" at position ${err.location.start.offset}: ${err.message}`,
|
||||
{
|
||||
cause: err,
|
||||
},
|
||||
);
|
||||
}
|
||||
throw err;
|
||||
|
||||
2
node_modules/eslint/lib/linter/interpolate.js
generated
vendored
2
node_modules/eslint/lib/linter/interpolate.js
generated
vendored
@@ -14,7 +14,7 @@
|
||||
* @returns {RegExp} Global regular expression matching placeholders
|
||||
*/
|
||||
function getPlaceholderMatcher() {
|
||||
return /\{\{([^{}]+?)\}\}/gu;
|
||||
return /\{\{([^{}]+)\}\}/gu;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
7
node_modules/eslint/lib/linter/linter.js
generated
vendored
7
node_modules/eslint/lib/linter/linter.js
generated
vendored
@@ -438,9 +438,8 @@ function getDirectiveComments(
|
||||
justification: justificationPart,
|
||||
} = directive;
|
||||
|
||||
const lineCommentSupported = /^eslint-disable-(next-)?line$/u.test(
|
||||
label,
|
||||
);
|
||||
const lineCommentSupported =
|
||||
/^eslint-disable-(?:next-)?line$/u.test(label);
|
||||
|
||||
if (comment.type === "Line" && !lineCommentSupported) {
|
||||
return;
|
||||
@@ -739,7 +738,7 @@ function normalizeEcmaVersionForLanguageOptions(ecmaVersion) {
|
||||
return LATEST_ECMA_VERSION;
|
||||
}
|
||||
|
||||
const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)(?:\*\/|$)/gsu;
|
||||
const eslintEnvPattern = /\/\*\s*eslint-env\s.+?(?:\*\/|$)/gsu;
|
||||
|
||||
/**
|
||||
* Checks whether or not there is a comment which has "eslint-env *" in a given text.
|
||||
|
||||
32
node_modules/eslint/lib/options.js
generated
vendored
32
node_modules/eslint/lib/options.js
generated
vendored
@@ -23,6 +23,7 @@ const optionator = require("optionator");
|
||||
* @property {string} [cacheLocation] Path to the cache file or directory
|
||||
* @property {"metadata" | "content"} cacheStrategy Strategy to use for detecting changed files in the cache
|
||||
* @property {boolean} [color] Force enabling/disabling of color
|
||||
* @property {number | "auto" | "off"} [concurrency] Number of linting threads, "auto" to choose automatically, "off" for no multithreading
|
||||
* @property {string} [config] Use this configuration, overriding .eslintrc.* config options if present
|
||||
* @property {boolean} debug Output debugging information
|
||||
* @property {string[]} [env] Specify environments
|
||||
@@ -46,27 +47,27 @@ const optionator = require("optionator");
|
||||
* @property {string} [outputFile] Specify file to write report to
|
||||
* @property {string} [parser] Specify the parser to be used
|
||||
* @property {Object} [parserOptions] Specify parser options
|
||||
* @property {boolean} [passOnNoPatterns=false] When set to true, missing patterns cause
|
||||
* the linting operation to short circuit and not report any failures.
|
||||
* @property {boolean} [passOnUnprunedSuppressions] Ignore unused suppressions
|
||||
* @property {string[]} [plugin] Specify plugins
|
||||
* @property {string} [printConfig] Print the configuration for the given file
|
||||
* @property {boolean} [pruneSuppressions] Prune unused suppressions
|
||||
* @property {boolean} quiet Report errors only
|
||||
* @property {boolean | undefined} reportUnusedDisableDirectives Adds reported errors for unused eslint-disable and eslint-enable directives
|
||||
* @property {string | undefined} reportUnusedDisableDirectivesSeverity A severity string indicating if and how unused disable and enable directives should be tracked and reported.
|
||||
* @property {string} [resolvePluginsRelativeTo] A folder where plugins should be resolved from, CWD by default
|
||||
* @property {Object} [rule] Specify rules
|
||||
* @property {string[]} [rulesdir] Load additional rules from this directory. Deprecated: Use rules from plugins
|
||||
* @property {boolean} [stats] Report additional statistics
|
||||
* @property {boolean} stdin Lint code provided on <STDIN>
|
||||
* @property {string} [stdinFilename] Specify filename to process STDIN as
|
||||
* @property {boolean} quiet Report errors only
|
||||
* @property {boolean} [suppressAll] Suppress all error violations
|
||||
* @property {string} [suppressionsLocation] Path to the suppressions file or directory
|
||||
* @property {string[]} [suppressRule] Suppress specific rules
|
||||
* @property {boolean} [version] Output the version number
|
||||
* @property {boolean} warnIgnored Show warnings when the file list includes ignored files
|
||||
* @property {boolean} [passOnNoPatterns=false] When set to true, missing patterns cause
|
||||
* the linting operation to short circuit and not report any failures.
|
||||
* @property {string[]} _ Positional filenames or patterns
|
||||
* @property {boolean} [stats] Report additional statistics
|
||||
* @property {boolean} [suppressAll] Suppress all error violations
|
||||
* @property {string[]} [suppressRule] Suppress specific rules
|
||||
* @property {string} [suppressionsLocation] Path to the suppressions file or directory
|
||||
* @property {boolean} [pruneSuppressions] Prune unused suppressions
|
||||
* @property {boolean} [passOnUnprunedSuppressions] Ignore unused suppressions
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -224,6 +225,18 @@ module.exports = function (usingFlatConfig) {
|
||||
};
|
||||
}
|
||||
|
||||
let concurrencyFlag;
|
||||
|
||||
if (usingFlatConfig) {
|
||||
concurrencyFlag = {
|
||||
option: "concurrency",
|
||||
type: "Int|String",
|
||||
default: "off",
|
||||
description:
|
||||
"Number of linting threads, auto to choose automatically, off for no multithreading",
|
||||
};
|
||||
}
|
||||
|
||||
return optionator({
|
||||
prepend: "eslint [options] file.js [file.js] [dir]",
|
||||
defaults: {
|
||||
@@ -517,6 +530,7 @@ module.exports = function (usingFlatConfig) {
|
||||
statsFlag,
|
||||
flagFlag,
|
||||
mcpFlag,
|
||||
concurrencyFlag,
|
||||
].filter(value => !!value),
|
||||
});
|
||||
};
|
||||
|
||||
3
node_modules/eslint/lib/rule-tester/rule-tester.js
generated
vendored
3
node_modules/eslint/lib/rule-tester/rule-tester.js
generated
vendored
@@ -851,6 +851,9 @@ class RuleTester {
|
||||
} catch (err) {
|
||||
throw new Error(
|
||||
`Schema for rule ${ruleName} is invalid: ${err.message}`,
|
||||
{
|
||||
cause: err,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
1
node_modules/eslint/lib/rules/array-callback-return.js
generated
vendored
1
node_modules/eslint/lib/rules/array-callback-return.js
generated
vendored
@@ -233,7 +233,6 @@ module.exports = {
|
||||
url: "https://eslint.org/docs/latest/rules/array-callback-return",
|
||||
},
|
||||
|
||||
// eslint-disable-next-line eslint-plugin/require-meta-has-suggestions -- false positive
|
||||
hasSuggestions: true,
|
||||
|
||||
schema: [
|
||||
|
||||
2
node_modules/eslint/lib/rules/dot-notation.js
generated
vendored
2
node_modules/eslint/lib/rules/dot-notation.js
generated
vendored
@@ -15,7 +15,7 @@ const keywords = require("./utils/keywords");
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/u;
|
||||
const validIdentifier = /^[a-zA-Z_$][\w$]*$/u;
|
||||
|
||||
// `null` literal must be handled separately.
|
||||
const literalTypesToCheck = new Set(["string", "boolean"]);
|
||||
|
||||
15
node_modules/eslint/lib/rules/grouped-accessor-pairs.js
generated
vendored
15
node_modules/eslint/lib/rules/grouped-accessor-pairs.js
generated
vendored
@@ -87,8 +87,6 @@ function isAccessorKind(node) {
|
||||
return node.kind === "get" || node.kind === "set";
|
||||
}
|
||||
|
||||
const DEFAULT_ORDER = "anyOrder";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -98,7 +96,12 @@ module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
defaultOptions: [DEFAULT_ORDER],
|
||||
defaultOptions: [
|
||||
"anyOrder",
|
||||
{
|
||||
enforceForTSTypes: false,
|
||||
},
|
||||
],
|
||||
|
||||
docs: {
|
||||
description:
|
||||
@@ -129,10 +132,8 @@ module.exports = {
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const order = context.options[0] ?? DEFAULT_ORDER;
|
||||
const enforceForTSTypes =
|
||||
context.options[1]?.enforceForTSTypes ?? false;
|
||||
const sourceCode = context.sourceCode;
|
||||
const [order, { enforceForTSTypes }] = context.options;
|
||||
const { sourceCode } = context;
|
||||
|
||||
/**
|
||||
* Reports the given accessor pair.
|
||||
|
||||
2
node_modules/eslint/lib/rules/indent-legacy.js
generated
vendored
2
node_modules/eslint/lib/rules/indent-legacy.js
generated
vendored
@@ -1162,7 +1162,7 @@ module.exports = {
|
||||
* @returns {boolean} the result
|
||||
*/
|
||||
function isWrappedInParenthesis(node) {
|
||||
const regex = /^return\s*?\(\s*?\);*?/u;
|
||||
const regex = /^return\s*\(\s*\)/u;
|
||||
|
||||
const statementWithoutArgument = sourceCode
|
||||
.getText(node)
|
||||
|
||||
1
node_modules/eslint/lib/rules/index.js
generated
vendored
1
node_modules/eslint/lib/rules/index.js
generated
vendored
@@ -293,6 +293,7 @@ module.exports = new LazyLoadingRuleMap(
|
||||
"prefer-rest-params": () => require("./prefer-rest-params"),
|
||||
"prefer-spread": () => require("./prefer-spread"),
|
||||
"prefer-template": () => require("./prefer-template"),
|
||||
"preserve-caught-error": () => require("./preserve-caught-error"),
|
||||
"quote-props": () => require("./quote-props"),
|
||||
quotes: () => require("./quotes"),
|
||||
radix: () => require("./radix"),
|
||||
|
||||
2
node_modules/eslint/lib/rules/no-alert.js
generated
vendored
2
node_modules/eslint/lib/rules/no-alert.js
generated
vendored
@@ -24,7 +24,7 @@ const {
|
||||
* @returns {boolean} Whether or not the name is prohibited.
|
||||
*/
|
||||
function isProhibitedIdentifier(name) {
|
||||
return /^(alert|confirm|prompt)$/u.test(name);
|
||||
return /^(?:alert|confirm|prompt)$/u.test(name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
21
node_modules/eslint/lib/rules/no-empty-function.js
generated
vendored
21
node_modules/eslint/lib/rules/no-empty-function.js
generated
vendored
@@ -105,6 +105,7 @@ module.exports = {
|
||||
meta: {
|
||||
dialects: ["javascript", "typescript"],
|
||||
language: "javascript",
|
||||
hasSuggestions: true,
|
||||
type: "suggestion",
|
||||
|
||||
defaultOptions: [{ allow: [] }],
|
||||
@@ -131,6 +132,7 @@ module.exports = {
|
||||
|
||||
messages: {
|
||||
unexpected: "Unexpected empty {{name}}.",
|
||||
suggestComment: "Add comment inside empty {{name}}.",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -162,7 +164,7 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
|
||||
if (/(g|s)etters|methods$/iu.test(kind)) {
|
||||
if (/(?:g|s)etters|methods$/iu.test(kind)) {
|
||||
if (
|
||||
(node.parent.decorators?.length &&
|
||||
allow.includes("decoratedFunctions")) ||
|
||||
@@ -204,6 +206,23 @@ module.exports = {
|
||||
loc: node.body.loc,
|
||||
messageId: "unexpected",
|
||||
data: { name },
|
||||
suggest: [
|
||||
{
|
||||
messageId: "suggestComment",
|
||||
data: { name },
|
||||
fix(fixer) {
|
||||
const range = [
|
||||
node.body.range[0] + 1,
|
||||
node.body.range[1] - 1,
|
||||
];
|
||||
|
||||
return fixer.replaceTextRange(
|
||||
range,
|
||||
" /* empty */ ",
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
26
node_modules/eslint/lib/rules/no-empty-static-block.js
generated
vendored
26
node_modules/eslint/lib/rules/no-empty-static-block.js
generated
vendored
@@ -11,6 +11,7 @@
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
hasSuggestions: true,
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
@@ -23,6 +24,7 @@ module.exports = {
|
||||
|
||||
messages: {
|
||||
unexpected: "Unexpected empty static block.",
|
||||
suggestComment: "Add comment inside empty static block.",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -32,14 +34,36 @@ module.exports = {
|
||||
return {
|
||||
StaticBlock(node) {
|
||||
if (node.body.length === 0) {
|
||||
const openingBrace = sourceCode.getFirstToken(node, {
|
||||
skip: 1,
|
||||
});
|
||||
const closingBrace = sourceCode.getLastToken(node);
|
||||
|
||||
if (
|
||||
sourceCode.getCommentsBefore(closingBrace).length === 0
|
||||
) {
|
||||
context.report({
|
||||
node,
|
||||
loc: {
|
||||
start: openingBrace.loc.start,
|
||||
end: closingBrace.loc.end,
|
||||
},
|
||||
messageId: "unexpected",
|
||||
suggest: [
|
||||
{
|
||||
messageId: "suggestComment",
|
||||
fix(fixer) {
|
||||
const range = [
|
||||
openingBrace.range[1],
|
||||
closingBrace.range[0],
|
||||
];
|
||||
|
||||
return fixer.replaceTextRange(
|
||||
range,
|
||||
" /* empty */ ",
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
37
node_modules/eslint/lib/rules/no-empty.js
generated
vendored
37
node_modules/eslint/lib/rules/no-empty.js
generated
vendored
@@ -104,10 +104,47 @@ module.exports = {
|
||||
typeof node.cases === "undefined" ||
|
||||
node.cases.length === 0
|
||||
) {
|
||||
const openingBrace = sourceCode.getTokenAfter(
|
||||
node.discriminant,
|
||||
astUtils.isOpeningBraceToken,
|
||||
);
|
||||
|
||||
const closingBrace = sourceCode.getLastToken(node);
|
||||
|
||||
if (
|
||||
sourceCode.commentsExistBetween(
|
||||
openingBrace,
|
||||
closingBrace,
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
context.report({
|
||||
node,
|
||||
loc: {
|
||||
start: openingBrace.loc.start,
|
||||
end: closingBrace.loc.end,
|
||||
},
|
||||
messageId: "unexpected",
|
||||
data: { type: "switch" },
|
||||
suggest: [
|
||||
{
|
||||
messageId: "suggestComment",
|
||||
data: { type: "switch" },
|
||||
fix(fixer) {
|
||||
const range = [
|
||||
openingBrace.range[1],
|
||||
closingBrace.range[0],
|
||||
];
|
||||
|
||||
return fixer.replaceTextRange(
|
||||
range,
|
||||
" /* empty */ ",
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
4
node_modules/eslint/lib/rules/no-eval.js
generated
vendored
4
node_modules/eslint/lib/rules/no-eval.js
generated
vendored
@@ -226,7 +226,9 @@ module.exports = {
|
||||
|
||||
Program(node) {
|
||||
const scope = sourceCode.getScope(node),
|
||||
features = context.parserOptions.ecmaFeatures || {},
|
||||
features =
|
||||
context.languageOptions.parserOptions.ecmaFeatures ||
|
||||
{},
|
||||
strict =
|
||||
scope.isStrict ||
|
||||
node.sourceType === "module" ||
|
||||
|
||||
4
node_modules/eslint/lib/rules/no-irregular-whitespace.js
generated
vendored
4
node_modules/eslint/lib/rules/no-irregular-whitespace.js
generated
vendored
@@ -19,8 +19,8 @@ const astUtils = require("./utils/ast-utils");
|
||||
const ALL_IRREGULARS =
|
||||
/[\f\v\u0085\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000\u2028\u2029]/u;
|
||||
const IRREGULAR_WHITESPACE =
|
||||
/[\f\v\u0085\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000]+/gmu;
|
||||
const IRREGULAR_LINE_TERMINATORS = /[\u2028\u2029]/gmu;
|
||||
/[\f\v\u0085\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000]+/gu;
|
||||
const IRREGULAR_LINE_TERMINATORS = /[\u2028\u2029]/gu;
|
||||
const LINE_BREAK = astUtils.createGlobalLinebreakMatcher();
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
29
node_modules/eslint/lib/rules/no-loss-of-precision.js
generated
vendored
29
node_modules/eslint/lib/rules/no-loss-of-precision.js
generated
vendored
@@ -189,9 +189,32 @@ module.exports = {
|
||||
* @returns {boolean} true if they do not match
|
||||
*/
|
||||
function baseTenLosesPrecision(node) {
|
||||
const normalizedRawNumber = convertNumberToScientificNotation(
|
||||
getRaw(node),
|
||||
);
|
||||
const rawNumber = getRaw(node).toLowerCase();
|
||||
|
||||
/*
|
||||
* If trailing zeros equal the exponent, this is a valid representation
|
||||
* like "9.00e2" where 00 = 2 (meaning 9.00 * 10^2 = 900)
|
||||
* https://github.com/eslint/eslint/issues/19957
|
||||
*/
|
||||
if (rawNumber.includes(".") && rawNumber.includes("e")) {
|
||||
const parts = rawNumber.split("e");
|
||||
const coefficient = parts[0];
|
||||
const exponent = parseInt(parts[1], 10);
|
||||
|
||||
// Count trailing zeros after decimal
|
||||
const decimalParts = coefficient.split(".");
|
||||
if (decimalParts.length === 2) {
|
||||
const decimalPart = decimalParts[1];
|
||||
const trailingZeros = decimalPart.match(/0*$/u)[0].length;
|
||||
|
||||
if (trailingZeros === exponent) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const normalizedRawNumber =
|
||||
convertNumberToScientificNotation(rawNumber);
|
||||
const requestedPrecision = normalizedRawNumber
|
||||
.split("e")[0]
|
||||
.replace(".", "").length;
|
||||
|
||||
9
node_modules/eslint/lib/rules/no-misleading-character-class.js
generated
vendored
9
node_modules/eslint/lib/rules/no-misleading-character-class.js
generated
vendored
@@ -278,6 +278,12 @@ module.exports = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
|
||||
defaultOptions: [
|
||||
{
|
||||
allowEscape: false,
|
||||
},
|
||||
],
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Disallow characters which are made with multiple code points in character class syntax",
|
||||
@@ -293,7 +299,6 @@ module.exports = {
|
||||
properties: {
|
||||
allowEscape: {
|
||||
type: "boolean",
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
@@ -313,7 +318,7 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
create(context) {
|
||||
const allowEscape = context.options[0]?.allowEscape;
|
||||
const [{ allowEscape }] = context.options;
|
||||
const sourceCode = context.sourceCode;
|
||||
const parser = new RegExpParser();
|
||||
const checkedPatternNodes = new Set();
|
||||
|
||||
1
node_modules/eslint/lib/rules/no-mixed-spaces-and-tabs.js
generated
vendored
1
node_modules/eslint/lib/rules/no-mixed-spaces-and-tabs.js
generated
vendored
@@ -99,6 +99,7 @@ module.exports = {
|
||||
* At least one space followed by a tab
|
||||
* before non-tab/-space characters begin.
|
||||
*/
|
||||
// eslint-disable-next-line regexp/no-empty-lookarounds-assertion -- False positive
|
||||
regex = /^(?=(\t*))\1(?=( +))\2\t/u;
|
||||
}
|
||||
|
||||
|
||||
5
node_modules/eslint/lib/rules/no-octal.js
generated
vendored
5
node_modules/eslint/lib/rules/no-octal.js
generated
vendored
@@ -30,10 +30,7 @@ module.exports = {
|
||||
create(context) {
|
||||
return {
|
||||
Literal(node) {
|
||||
if (
|
||||
typeof node.value === "number" &&
|
||||
/^0[0-9]/u.test(node.raw)
|
||||
) {
|
||||
if (typeof node.value === "number" && /^0\d/u.test(node.raw)) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "noOctal",
|
||||
|
||||
3
node_modules/eslint/lib/rules/no-trailing-spaces.js
generated
vendored
3
node_modules/eslint/lib/rules/no-trailing-spaces.js
generated
vendored
@@ -82,7 +82,8 @@ module.exports = {
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
|
||||
const BLANK_CLASS = "[ \t\u00a0\u2000-\u200b\u3000]",
|
||||
const BLANK_CLASS =
|
||||
"[ \t\u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u3000]",
|
||||
SKIP_BLANK = `^${BLANK_CLASS}*$`,
|
||||
NONBLANK = `${BLANK_CLASS}+$`;
|
||||
|
||||
|
||||
2
node_modules/eslint/lib/rules/no-useless-escape.js
generated
vendored
2
node_modules/eslint/lib/rules/no-useless-escape.js
generated
vendored
@@ -387,7 +387,7 @@ module.exports = {
|
||||
const value = isTemplateElement
|
||||
? sourceCode.getText(node)
|
||||
: node.raw;
|
||||
const pattern = /\\[^\d]/gu;
|
||||
const pattern = /\\\D/gu;
|
||||
let match;
|
||||
|
||||
while ((match = pattern.exec(value))) {
|
||||
|
||||
2
node_modules/eslint/lib/rules/prefer-regex-literals.js
generated
vendored
2
node_modules/eslint/lib/rules/prefer-regex-literals.js
generated
vendored
@@ -522,7 +522,7 @@ module.exports = {
|
||||
}
|
||||
|
||||
if (
|
||||
!/^[-a-zA-Z0-9\\[\](){} \t\r\n\v\f!@#$%^&*+^_=/~`.><?,'"|:;]*$/u.test(
|
||||
!/^[-\w\\[\](){} \t\r\n\v\f!@#$%^&*+=/~`.><?,'"|:;]*$/u.test(
|
||||
regexContent,
|
||||
)
|
||||
) {
|
||||
|
||||
539
node_modules/eslint/lib/rules/preserve-caught-error.js
generated
vendored
Normal file
539
node_modules/eslint/lib/rules/preserve-caught-error.js
generated
vendored
Normal file
@@ -0,0 +1,539 @@
|
||||
/**
|
||||
* @fileoverview Rule to preserve caught errors when re-throwing exceptions
|
||||
* @author Amnish Singh Arora
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @typedef {import("estree").Node} ASTNode */
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* This is an indicator of an error cause node, that is too complicated to be detected and fixed.
|
||||
* Eg, when error options is an `Identifier` or a `SpreadElement`.
|
||||
*/
|
||||
const UNKNOWN_CAUSE = Symbol("unknown_cause");
|
||||
|
||||
const BUILT_IN_ERROR_TYPES = new Set([
|
||||
"Error",
|
||||
"EvalError",
|
||||
"RangeError",
|
||||
"ReferenceError",
|
||||
"SyntaxError",
|
||||
"TypeError",
|
||||
"URIError",
|
||||
"AggregateError",
|
||||
]);
|
||||
|
||||
/**
|
||||
* Finds and returns information about the `cause` property of an error being thrown.
|
||||
* @param {ASTNode} throwStatement `ThrowStatement` to be checked.
|
||||
* @returns {{ value: ASTNode; multipleDefinitions: boolean; } | UNKNOWN_CAUSE | null}
|
||||
* Information about the `cause` of the error being thrown, such as the value node and
|
||||
* whether there are multiple definitions of `cause`. `null` if there is no `cause`.
|
||||
*/
|
||||
function getErrorCause(throwStatement) {
|
||||
const throwExpression = throwStatement.argument;
|
||||
/*
|
||||
* Determine which argument index holds the options object
|
||||
* `AggregateError` is a special case as it accepts the `options` object as third argument.
|
||||
*/
|
||||
const optionsIndex =
|
||||
throwExpression.callee.name === "AggregateError" ? 2 : 1;
|
||||
|
||||
/*
|
||||
* Make sure there is no `SpreadElement` at or before the `optionsIndex`
|
||||
* as this messes up the effective order of arguments and makes it complicated
|
||||
* to track where the actual error options need to be at
|
||||
*/
|
||||
const spreadExpressionIndex = throwExpression.arguments.findIndex(
|
||||
arg => arg.type === "SpreadElement",
|
||||
);
|
||||
if (spreadExpressionIndex >= 0 && spreadExpressionIndex <= optionsIndex) {
|
||||
return UNKNOWN_CAUSE;
|
||||
}
|
||||
|
||||
const errorOptions = throwExpression.arguments[optionsIndex];
|
||||
|
||||
if (errorOptions) {
|
||||
if (errorOptions.type === "ObjectExpression") {
|
||||
if (
|
||||
errorOptions.properties.some(
|
||||
prop => prop.type === "SpreadElement",
|
||||
)
|
||||
) {
|
||||
/*
|
||||
* If there is a spread element as part of error options, it is too complicated
|
||||
* to verify if the cause is used properly and auto-fix.
|
||||
*/
|
||||
return UNKNOWN_CAUSE;
|
||||
}
|
||||
|
||||
const causeProperties = errorOptions.properties.filter(
|
||||
prop =>
|
||||
prop.type === "Property" &&
|
||||
prop.key.type === "Identifier" &&
|
||||
prop.key.name === "cause" &&
|
||||
!prop.computed, // It is hard to accurately identify the value of computed props
|
||||
);
|
||||
|
||||
const causeProperty = causeProperties.at(-1);
|
||||
return causeProperty
|
||||
? {
|
||||
value: causeProperty.value,
|
||||
multipleDefinitions: causeProperties.length > 1,
|
||||
}
|
||||
: null;
|
||||
}
|
||||
|
||||
// Error options exist, but too complicated to be analyzed/fixed
|
||||
return UNKNOWN_CAUSE;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and returns the `CatchClause` node, that the `node` is part of.
|
||||
* @param {ASTNode} node The AST node to be evaluated.
|
||||
* @returns {ASTNode | null } The closest parent `CatchClause` node, `null` if the `node` is not in a catch block.
|
||||
*/
|
||||
function findParentCatch(node) {
|
||||
let currentNode = node;
|
||||
|
||||
while (currentNode && currentNode.type !== "CatchClause") {
|
||||
if (
|
||||
[
|
||||
"FunctionDeclaration",
|
||||
"FunctionExpression",
|
||||
"ArrowFunctionExpression",
|
||||
"StaticBlock",
|
||||
].includes(currentNode.type)
|
||||
) {
|
||||
/*
|
||||
* Make sure the ThrowStatement is not made inside a function definition or a static block inside a high level catch.
|
||||
* In such cases, the caught error is not directly related to the Throw.
|
||||
*
|
||||
* For example,
|
||||
* try {
|
||||
* } catch (error) {
|
||||
* foo = {
|
||||
* bar() {
|
||||
* throw new Error();
|
||||
* }
|
||||
* };
|
||||
* }
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
currentNode = currentNode.parent;
|
||||
}
|
||||
|
||||
return currentNode;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
defaultOptions: [
|
||||
{
|
||||
requireCatchParameter: false,
|
||||
},
|
||||
],
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Disallow losing originally caught error when re-throwing custom errors",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/preserve-caught-error", // URL to the documentation page for this rule
|
||||
},
|
||||
/*
|
||||
* TODO: We should allow passing `customErrorTypes` option once something like `typescript-eslint`'s
|
||||
* `TypeOrValueSpecifier` is implemented in core Eslint.
|
||||
* See:
|
||||
* 1. https://typescript-eslint.io/packages/type-utils/type-or-value-specifier/
|
||||
* 2. https://github.com/eslint/eslint/pull/19913#discussion_r2192608593
|
||||
* 3. https://github.com/eslint/eslint/discussions/16540
|
||||
*/
|
||||
schema: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
requireCatchParameter: {
|
||||
type: "boolean",
|
||||
description:
|
||||
"Requires the catch blocks to always have the caught error parameter so it is not discarded.",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
messages: {
|
||||
missingCause:
|
||||
"There is no `cause` attached to the symptom error being thrown.",
|
||||
incorrectCause:
|
||||
"The symptom error is being thrown with an incorrect `cause`.",
|
||||
includeCause:
|
||||
"Include the original caught error as the `cause` of the symptom error.",
|
||||
missingCatchErrorParam:
|
||||
"The caught error is not accessible because the catch clause lacks the error parameter. Start referencing the caught error using the catch parameter.",
|
||||
partiallyLostError:
|
||||
"Re-throws cannot preserve the caught error as a part of it is being lost due to destructuring.",
|
||||
caughtErrorShadowed:
|
||||
"The caught error is being attached as `cause`, but is shadowed by a closer scoped redeclaration.",
|
||||
},
|
||||
hasSuggestions: true,
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
const [{ requireCatchParameter }] = context.options;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Helpers
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks if a `ThrowStatement` is constructing and throwing a new `Error` object.
|
||||
*
|
||||
* Covers all the error types on `globalThis` that support `cause` property:
|
||||
* https://github.com/microsoft/TypeScript/blob/main/src/lib/es2022.error.d.ts
|
||||
* @param {ASTNode} throwStatement The `ThrowStatement` that needs to be checked.
|
||||
* @returns {boolean} `true` if a new "Error" is being thrown, else `false`.
|
||||
*/
|
||||
function isThrowingNewError(throwStatement) {
|
||||
return (
|
||||
(throwStatement.argument.type === "NewExpression" ||
|
||||
throwStatement.argument.type === "CallExpression") &&
|
||||
throwStatement.argument.callee.type === "Identifier" &&
|
||||
BUILT_IN_ERROR_TYPES.has(throwStatement.argument.callee.name) &&
|
||||
/*
|
||||
* Make sure the thrown Error is instance is one of the built-in global error types.
|
||||
* Custom imports could shadow this, which would lead to false positives.
|
||||
* e.g. import { Error } from "./my-custom-error.js";
|
||||
* throw Error("Failed to perform error prone operations");
|
||||
*/
|
||||
sourceCode.isGlobalReference(throwStatement.argument.callee)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts `cause: <caughtErrorName>` into an inline options object expression.
|
||||
* @param {RuleFixer} fixer The fixer object.
|
||||
* @param {ASTNode} optionsNode The options object node.
|
||||
* @param {string} caughtErrorName The name of the caught error (e.g., "err").
|
||||
* @returns {Fix} The fix object.
|
||||
*/
|
||||
function insertCauseIntoOptions(fixer, optionsNode, caughtErrorName) {
|
||||
const properties = optionsNode.properties;
|
||||
|
||||
if (properties.length === 0) {
|
||||
// Insert inside empty braces: `{}` → `{ cause: err }`
|
||||
return fixer.insertTextAfter(
|
||||
sourceCode.getFirstToken(optionsNode),
|
||||
`cause: ${caughtErrorName}`,
|
||||
);
|
||||
}
|
||||
|
||||
const lastProp = properties.at(-1);
|
||||
return fixer.insertTextAfter(
|
||||
lastProp,
|
||||
`, cause: ${caughtErrorName}`,
|
||||
);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Public
|
||||
//----------------------------------------------------------------------
|
||||
return {
|
||||
ThrowStatement(node) {
|
||||
// Check if the throw is inside a catch block
|
||||
const parentCatch = findParentCatch(node);
|
||||
const throwStatement = node;
|
||||
|
||||
// Check if a new error is being thrown in a catch block
|
||||
if (parentCatch && isThrowingNewError(throwStatement)) {
|
||||
if (
|
||||
parentCatch.param &&
|
||||
parentCatch.param.type !== "Identifier"
|
||||
) {
|
||||
/*
|
||||
* When a part of the caught error is being lost at the parameter level, commonly due to destructuring.
|
||||
* e.g. catch({ message, ...rest })
|
||||
*/
|
||||
context.report({
|
||||
messageId: "partiallyLostError",
|
||||
node: parentCatch,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const caughtError =
|
||||
parentCatch.param?.type === "Identifier"
|
||||
? parentCatch.param
|
||||
: null;
|
||||
|
||||
// Check if there are throw statements and caught error is being ignored
|
||||
if (!caughtError) {
|
||||
if (requireCatchParameter) {
|
||||
context.report({
|
||||
node: throwStatement,
|
||||
messageId: "missingCatchErrorParam",
|
||||
});
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if there is a cause attached to the new error
|
||||
const errorCauseInfo = getErrorCause(throwStatement);
|
||||
|
||||
if (errorCauseInfo === UNKNOWN_CAUSE) {
|
||||
// Error options exist, but too complicated to be analyzed/fixed
|
||||
return;
|
||||
}
|
||||
|
||||
if (errorCauseInfo === null) {
|
||||
// If there is no `cause` attached to the error being thrown.
|
||||
context.report({
|
||||
messageId: "missingCause",
|
||||
node: throwStatement,
|
||||
suggest: [
|
||||
{
|
||||
messageId: "includeCause",
|
||||
fix(fixer) {
|
||||
const throwExpression =
|
||||
throwStatement.argument;
|
||||
const args = throwExpression.arguments;
|
||||
const errorType =
|
||||
throwExpression.callee.name;
|
||||
|
||||
// AggregateError: errors, message, options
|
||||
if (errorType === "AggregateError") {
|
||||
const errorsArg = args[0];
|
||||
const messageArg = args[1];
|
||||
const optionsArg = args[2];
|
||||
|
||||
if (!errorsArg) {
|
||||
// Case: `throw new AggregateError()` → insert all arguments
|
||||
const lastToken =
|
||||
sourceCode.getLastToken(
|
||||
throwExpression,
|
||||
);
|
||||
const lastCalleeToken =
|
||||
sourceCode.getLastToken(
|
||||
throwExpression.callee,
|
||||
);
|
||||
const parenToken =
|
||||
sourceCode.getFirstTokenBetween(
|
||||
lastCalleeToken,
|
||||
lastToken,
|
||||
astUtils.isOpeningParenToken,
|
||||
);
|
||||
|
||||
if (parenToken) {
|
||||
return fixer.insertTextAfter(
|
||||
parenToken,
|
||||
`[], "", { cause: ${caughtError.name} }`,
|
||||
);
|
||||
}
|
||||
return fixer.insertTextAfter(
|
||||
throwExpression.callee,
|
||||
`([], "", { cause: ${caughtError.name} })`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!messageArg) {
|
||||
// Case: `throw new AggregateError([])` → insert message and options
|
||||
return fixer.insertTextAfter(
|
||||
errorsArg,
|
||||
`, "", { cause: ${caughtError.name} }`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!optionsArg) {
|
||||
// Case: `throw new AggregateError([], "")` → insert error options only
|
||||
return fixer.insertTextAfter(
|
||||
messageArg,
|
||||
`, { cause: ${caughtError.name} }`,
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
optionsArg.type ===
|
||||
"ObjectExpression"
|
||||
) {
|
||||
return insertCauseIntoOptions(
|
||||
fixer,
|
||||
optionsArg,
|
||||
caughtError.name,
|
||||
);
|
||||
}
|
||||
|
||||
// Complex dynamic options — skip
|
||||
return null;
|
||||
}
|
||||
|
||||
// Normal Error types
|
||||
const messageArg = args[0];
|
||||
const optionsArg = args[1];
|
||||
|
||||
if (!messageArg) {
|
||||
// Case: `throw new Error()` → insert both message and options
|
||||
const lastToken =
|
||||
sourceCode.getLastToken(
|
||||
throwExpression,
|
||||
);
|
||||
const lastCalleeToken =
|
||||
sourceCode.getLastToken(
|
||||
throwExpression.callee,
|
||||
);
|
||||
const parenToken =
|
||||
sourceCode.getFirstTokenBetween(
|
||||
lastCalleeToken,
|
||||
lastToken,
|
||||
astUtils.isOpeningParenToken,
|
||||
);
|
||||
|
||||
if (parenToken) {
|
||||
return fixer.insertTextAfter(
|
||||
parenToken,
|
||||
`"", { cause: ${caughtError.name} }`,
|
||||
);
|
||||
}
|
||||
return fixer.insertTextAfter(
|
||||
throwExpression.callee,
|
||||
`("", { cause: ${caughtError.name} })`,
|
||||
);
|
||||
}
|
||||
if (!optionsArg) {
|
||||
// Case: `throw new Error("Some message")` → insert only options
|
||||
return fixer.insertTextAfter(
|
||||
messageArg,
|
||||
`, { cause: ${caughtError.name} }`,
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
optionsArg.type ===
|
||||
"ObjectExpression"
|
||||
) {
|
||||
return insertCauseIntoOptions(
|
||||
fixer,
|
||||
optionsArg,
|
||||
caughtError.name,
|
||||
);
|
||||
}
|
||||
|
||||
return null; // Identifier or spread — do not fix
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// We don't need to check further
|
||||
return;
|
||||
}
|
||||
|
||||
const { value: thrownErrorCause } = errorCauseInfo;
|
||||
|
||||
// If there is an attached cause, verify that it matches the caught error
|
||||
if (
|
||||
!(
|
||||
thrownErrorCause.type === "Identifier" &&
|
||||
thrownErrorCause.name === caughtError.name
|
||||
)
|
||||
) {
|
||||
const suggest = errorCauseInfo.multipleDefinitions
|
||||
? null // If there are multiple `cause` definitions, a suggestion could be confusing.
|
||||
: [
|
||||
{
|
||||
messageId: "includeCause",
|
||||
fix(fixer) {
|
||||
/*
|
||||
* In case `cause` is attached using object property shorthand or as a method or accessor.
|
||||
* e.g. throw Error("fail", { cause });
|
||||
* throw Error("fail", { cause() { doSomething(); } });
|
||||
* throw Error("fail", { get cause() { return error; } });
|
||||
*/
|
||||
if (
|
||||
thrownErrorCause.parent
|
||||
.method ||
|
||||
thrownErrorCause.parent
|
||||
.shorthand ||
|
||||
thrownErrorCause.parent.kind !==
|
||||
"init"
|
||||
) {
|
||||
return fixer.replaceText(
|
||||
thrownErrorCause.parent,
|
||||
`cause: ${caughtError.name}`,
|
||||
);
|
||||
}
|
||||
|
||||
return fixer.replaceText(
|
||||
thrownErrorCause,
|
||||
caughtError.name,
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
context.report({
|
||||
messageId: "incorrectCause",
|
||||
node: thrownErrorCause,
|
||||
suggest,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the attached cause matches the identifier name of the caught error,
|
||||
* make sure it is not being shadowed by a closer scoped redeclaration.
|
||||
*
|
||||
* e.g. try {
|
||||
* doSomething();
|
||||
* } catch (error) {
|
||||
* if (whatever) {
|
||||
* const error = anotherError;
|
||||
* throw new Error("Something went wrong");
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
let scope = sourceCode.getScope(throwStatement);
|
||||
do {
|
||||
const variable = scope.set.get(caughtError.name);
|
||||
if (variable) {
|
||||
break;
|
||||
}
|
||||
scope = scope.upper;
|
||||
} while (scope);
|
||||
|
||||
if (scope?.block !== parentCatch) {
|
||||
// Caught error is being shadowed
|
||||
context.report({
|
||||
messageId: "caughtErrorShadowed",
|
||||
node: throwStatement,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
4
node_modules/eslint/lib/rules/require-unicode-regexp.js
generated
vendored
4
node_modules/eslint/lib/rules/require-unicode-regexp.js
generated
vendored
@@ -47,6 +47,8 @@ module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
defaultOptions: [{}],
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Enforce the use of `u` or `v` flag on regular expressions",
|
||||
@@ -79,7 +81,7 @@ module.exports = {
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
|
||||
const { requireFlag } = context.options[0] ?? {};
|
||||
const [{ requireFlag }] = context.options;
|
||||
|
||||
return {
|
||||
"Literal[regex]"(node) {
|
||||
|
||||
3
node_modules/eslint/lib/rules/strict.js
generated
vendored
3
node_modules/eslint/lib/rules/strict.js
generated
vendored
@@ -101,7 +101,8 @@ module.exports = {
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const ecmaFeatures = context.parserOptions.ecmaFeatures || {},
|
||||
const ecmaFeatures =
|
||||
context.languageOptions.parserOptions.ecmaFeatures || {},
|
||||
scopes = [],
|
||||
classScopes = [];
|
||||
let [mode] = context.options;
|
||||
|
||||
2
node_modules/eslint/lib/rules/utils/ast-utils.js
generated
vendored
2
node_modules/eslint/lib/rules/utils/ast-utils.js
generated
vendored
@@ -58,7 +58,7 @@ const DECIMAL_INTEGER_PATTERN = /^(?:0|0[0-7]*[89]\d*|[1-9](?:_?\d)*)$/u;
|
||||
|
||||
// Tests the presence of at least one LegacyOctalEscapeSequence or NonOctalDecimalEscapeSequence in a raw string
|
||||
const OCTAL_OR_NON_OCTAL_DECIMAL_ESCAPE_PATTERN =
|
||||
/^(?:[^\\]|\\.)*\\(?:[1-9]|0[0-9])/su;
|
||||
/^(?:[^\\]|\\.)*\\(?:[1-9]|0\d)/su;
|
||||
|
||||
const LOGICAL_ASSIGNMENT_OPERATORS = new Set(["&&=", "||=", "??="]);
|
||||
|
||||
|
||||
2
node_modules/eslint/lib/rules/utils/char-source.js
generated
vendored
2
node_modules/eslint/lib/rules/utils/char-source.js
generated
vendored
@@ -85,7 +85,7 @@ function readHexSequence(reader, length) {
|
||||
* @returns {string} A code unit.
|
||||
*/
|
||||
function readUnicodeSequence(reader) {
|
||||
const regExp = /\{(?<hexDigits>[\dA-Fa-f]+)\}/uy;
|
||||
const regExp = /\{(?<hexDigits>[\dA-F]+)\}/iuy;
|
||||
|
||||
regExp.lastIndex = reader.pos;
|
||||
const match = regExp.exec(reader.source);
|
||||
|
||||
4
node_modules/eslint/lib/rules/yoda.js
generated
vendored
4
node_modules/eslint/lib/rules/yoda.js
generated
vendored
@@ -20,7 +20,7 @@ const astUtils = require("./utils/ast-utils");
|
||||
* @returns {boolean} Whether or not it is a comparison operator.
|
||||
*/
|
||||
function isComparisonOperator(operator) {
|
||||
return /^(==|===|!=|!==|<|>|<=|>=)$/u.test(operator);
|
||||
return /^(?:==|===|!=|!==|<|>|<=|>=)$/u.test(operator);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -29,7 +29,7 @@ function isComparisonOperator(operator) {
|
||||
* @returns {boolean} Whether or not it is an equality operator.
|
||||
*/
|
||||
function isEqualityOperator(operator) {
|
||||
return /^(==|===)$/u.test(operator);
|
||||
return /^(?:==|===)$/u.test(operator);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
3
node_modules/eslint/lib/services/suppressions-service.js
generated
vendored
3
node_modules/eslint/lib/services/suppressions-service.js
generated
vendored
@@ -221,6 +221,9 @@ class SuppressionsService {
|
||||
}
|
||||
throw new Error(
|
||||
`Failed to parse suppressions file at ${this.filePath}`,
|
||||
{
|
||||
cause: err,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
13
node_modules/eslint/lib/services/warning-service.js
generated
vendored
13
node_modules/eslint/lib/services/warning-service.js
generated
vendored
@@ -80,6 +80,19 @@ class WarningService {
|
||||
emitInactiveFlagWarning(flag, message) {
|
||||
this.emitWarning(message, `ESLintInactiveFlag_${flag}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a warning when a suboptimal concurrency setting is detected.
|
||||
* Currently, this is only used to warn when the net linting ratio is low.
|
||||
* @param {string} notice A notice about how to improve performance.
|
||||
* @returns {void}
|
||||
*/
|
||||
emitPoorConcurrencyWarning(notice) {
|
||||
this.emitWarning(
|
||||
`You may ${notice} to improve performance.`,
|
||||
"ESLintPoorConcurrencyWarning",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { WarningService };
|
||||
|
||||
2
node_modules/eslint/lib/shared/naming.js
generated
vendored
2
node_modules/eslint/lib/shared/naming.js
generated
vendored
@@ -4,7 +4,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const NAMESPACE_REGEX = /^@.*\//iu;
|
||||
const NAMESPACE_REGEX = /^@.*\//u;
|
||||
|
||||
/**
|
||||
* Brings package name to correct format based on prefix
|
||||
|
||||
281
node_modules/eslint/lib/shared/translate-cli-options.js
generated
vendored
Normal file
281
node_modules/eslint/lib/shared/translate-cli-options.js
generated
vendored
Normal file
@@ -0,0 +1,281 @@
|
||||
/**
|
||||
* @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;
|
||||
9
node_modules/eslint/lib/types/index.d.ts
generated
vendored
9
node_modules/eslint/lib/types/index.d.ts
generated
vendored
@@ -92,6 +92,8 @@ export namespace Scope {
|
||||
| "block"
|
||||
| "catch"
|
||||
| "class"
|
||||
| "class-field-initializer"
|
||||
| "class-static-block"
|
||||
| "for"
|
||||
| "function"
|
||||
| "function-expression-name"
|
||||
@@ -1966,6 +1968,10 @@ export class ESLint {
|
||||
isPathIgnored(filePath: string): Promise<boolean>;
|
||||
|
||||
loadFormatter(nameOrPath?: string): Promise<ESLint.LoadedFormatter>;
|
||||
|
||||
static fromOptionsModule(optionsURL: {
|
||||
readonly href: string;
|
||||
}): Promise<ESLint>;
|
||||
}
|
||||
|
||||
export namespace ESLint {
|
||||
@@ -2047,6 +2053,7 @@ export namespace ESLint {
|
||||
cacheStrategy?: CacheStrategy | undefined;
|
||||
|
||||
// Other Options
|
||||
concurrency?: number | "auto" | "off" | undefined;
|
||||
flags?: string[] | undefined;
|
||||
}
|
||||
|
||||
@@ -2254,6 +2261,8 @@ export namespace RuleTester {
|
||||
only?: boolean;
|
||||
languageOptions?: Linter.LanguageOptions | undefined;
|
||||
settings?: { [name: string]: any } | undefined;
|
||||
before?: () => void;
|
||||
after?: () => void;
|
||||
}
|
||||
|
||||
interface SuggestionOutput {
|
||||
|
||||
307
node_modules/eslint/lib/types/rules.d.ts
generated
vendored
307
node_modules/eslint/lib/types/rules.d.ts
generated
vendored
@@ -60,25 +60,19 @@ type EitherGroupOrRegEx =
|
||||
// Base type for import name specifiers, ensuring mutual exclusivity
|
||||
type EitherNameSpecifiers =
|
||||
| {
|
||||
importNames: string[];
|
||||
importNames?: string[];
|
||||
importNamePattern?: string;
|
||||
allowImportNames?: never;
|
||||
importNamePattern?: never;
|
||||
allowImportNamePattern?: never;
|
||||
}
|
||||
| {
|
||||
importNamePattern: string;
|
||||
allowImportNames?: never;
|
||||
importNames?: never;
|
||||
allowImportNamePattern?: never;
|
||||
}
|
||||
| {
|
||||
allowImportNames: string[];
|
||||
allowImportNames?: string[];
|
||||
importNames?: never;
|
||||
importNamePattern?: never;
|
||||
allowImportNamePattern?: never;
|
||||
}
|
||||
| {
|
||||
allowImportNamePattern: string;
|
||||
allowImportNamePattern?: string;
|
||||
importNames?: never;
|
||||
allowImportNames?: never;
|
||||
importNamePattern?: never;
|
||||
@@ -90,6 +84,18 @@ type ValidNoRestrictedImportPatternOptions =
|
||||
EitherGroupOrRegEx &
|
||||
EitherNameSpecifiers;
|
||||
|
||||
interface CapitalizedCommentsCommonOptions {
|
||||
ignorePattern?: string;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
ignoreInlineComments?: boolean;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
ignoreConsecutiveComments?: boolean;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Public types
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -117,7 +123,7 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
*/
|
||||
enforceForClassMembers: boolean;
|
||||
/**
|
||||
* @default true
|
||||
* @default false
|
||||
*/
|
||||
enforceForTSTypes: boolean;
|
||||
}>,
|
||||
@@ -402,17 +408,13 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
"capitalized-comments": Linter.RuleEntry<
|
||||
[
|
||||
"always" | "never",
|
||||
Partial<{
|
||||
ignorePattern: string;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
ignoreInlineComments: boolean;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
ignoreConsecutiveComments: boolean;
|
||||
}>,
|
||||
(
|
||||
| CapitalizedCommentsCommonOptions
|
||||
| Partial<{
|
||||
line: CapitalizedCommentsCommonOptions;
|
||||
block: CapitalizedCommentsCommonOptions;
|
||||
}>
|
||||
),
|
||||
]
|
||||
>;
|
||||
|
||||
@@ -1020,6 +1022,7 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
*/
|
||||
properties: "always" | "never";
|
||||
exceptions: string[];
|
||||
exceptionPatterns: string[];
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
@@ -1038,6 +1041,10 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
* @default false
|
||||
*/
|
||||
properties: boolean;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
classFields: boolean;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
@@ -1661,7 +1668,21 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
* @since 5.0.0-alpha.3
|
||||
* @see https://eslint.org/docs/latest/rules/max-classes-per-file
|
||||
*/
|
||||
"max-classes-per-file": Linter.RuleEntry<[number]>;
|
||||
"max-classes-per-file": Linter.RuleEntry<
|
||||
[
|
||||
| number
|
||||
| Partial<{
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
ignoreExpressions: boolean;
|
||||
/**
|
||||
* @default 1
|
||||
*/
|
||||
max: number;
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
|
||||
/**
|
||||
* Rule to enforce a maximum depth that blocks can be nested.
|
||||
@@ -1671,12 +1692,18 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
*/
|
||||
"max-depth": Linter.RuleEntry<
|
||||
[
|
||||
Partial<{
|
||||
/**
|
||||
* @default 4
|
||||
*/
|
||||
max: number;
|
||||
}>,
|
||||
| number
|
||||
| Partial<{
|
||||
/**
|
||||
* @deprecated
|
||||
* @default 4
|
||||
*/
|
||||
maximum: number;
|
||||
/**
|
||||
* @default 4
|
||||
*/
|
||||
max: number;
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
|
||||
@@ -1764,24 +1791,25 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
*/
|
||||
"max-lines-per-function": Linter.RuleEntry<
|
||||
[
|
||||
Partial<{
|
||||
/**
|
||||
* @default 50
|
||||
*/
|
||||
max: number;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
skipBlankLines: boolean;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
skipComments: boolean;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
IIFEs: boolean;
|
||||
}>,
|
||||
| number
|
||||
| Partial<{
|
||||
/**
|
||||
* @default 50
|
||||
*/
|
||||
max: number;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
skipBlankLines: boolean;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
skipComments: boolean;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
IIFEs: boolean;
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
|
||||
@@ -1793,13 +1821,18 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
*/
|
||||
"max-nested-callbacks": Linter.RuleEntry<
|
||||
[
|
||||
| number
|
||||
| Partial<{
|
||||
/**
|
||||
* @deprecated
|
||||
* @default 10
|
||||
*/
|
||||
maximum: number;
|
||||
/**
|
||||
* @default 10
|
||||
*/
|
||||
max: number;
|
||||
}>
|
||||
| number,
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
|
||||
@@ -1811,7 +1844,13 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
*/
|
||||
"max-params": Linter.RuleEntry<
|
||||
[
|
||||
| number
|
||||
| Partial<{
|
||||
/**
|
||||
* @deprecated
|
||||
* @default 3
|
||||
*/
|
||||
maximum: number;
|
||||
/**
|
||||
* @default 3
|
||||
*/
|
||||
@@ -1820,8 +1859,7 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
* @default false
|
||||
*/
|
||||
countVoidThis: boolean;
|
||||
}>
|
||||
| number,
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
|
||||
@@ -1833,17 +1871,26 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
*/
|
||||
"max-statements": Linter.RuleEntry<
|
||||
[
|
||||
| Partial<{
|
||||
/**
|
||||
* @default 10
|
||||
*/
|
||||
max: number;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
ignoreTopLevelFunctions: boolean;
|
||||
}>
|
||||
| number,
|
||||
(
|
||||
| number
|
||||
| Partial<{
|
||||
/**
|
||||
* @deprecated
|
||||
* @default 10
|
||||
*/
|
||||
maximum: number;
|
||||
/**
|
||||
* @default 10
|
||||
*/
|
||||
max: number;
|
||||
}>
|
||||
),
|
||||
Partial<{
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
ignoreTopLevelFunctions: boolean;
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
|
||||
@@ -2020,7 +2067,24 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
"no-bitwise": Linter.RuleEntry<
|
||||
[
|
||||
Partial<{
|
||||
allow: string[];
|
||||
/**
|
||||
* @default []
|
||||
*/
|
||||
allow: Array<
|
||||
| "^"
|
||||
| "|"
|
||||
| "&"
|
||||
| "<<"
|
||||
| ">>"
|
||||
| ">>>"
|
||||
| "^="
|
||||
| "|="
|
||||
| "&="
|
||||
| "<<="
|
||||
| ">>="
|
||||
| ">>>="
|
||||
| "~"
|
||||
>;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
@@ -2172,9 +2236,9 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
[
|
||||
{
|
||||
/**
|
||||
* @default true
|
||||
* @default "allExceptWhileTrue"
|
||||
*/
|
||||
checkLoops: boolean;
|
||||
checkLoops: "all" | "allExceptWhileTrue" | "none" | boolean;
|
||||
},
|
||||
]
|
||||
>;
|
||||
@@ -2401,7 +2465,16 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
* @since 1.7.0
|
||||
* @see https://eslint.org/docs/latest/rules/no-empty-pattern
|
||||
*/
|
||||
"no-empty-pattern": Linter.RuleEntry<[]>;
|
||||
"no-empty-pattern": Linter.RuleEntry<
|
||||
[
|
||||
Partial<{
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
allowObjectPatternsAsParameters: boolean;
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
|
||||
/**
|
||||
* Rule to disallow empty static blocks.
|
||||
@@ -2674,7 +2747,16 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
* @since 2.0.0-alpha-1
|
||||
* @see https://eslint.org/docs/latest/rules/no-implicit-globals
|
||||
*/
|
||||
"no-implicit-globals": Linter.RuleEntry<[]>;
|
||||
"no-implicit-globals": Linter.RuleEntry<
|
||||
[
|
||||
Partial<{
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
lexicalBindings: boolean;
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
|
||||
/**
|
||||
* Rule to disallow the use of `eval()`-like methods.
|
||||
@@ -2701,7 +2783,13 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
* @since 0.10.0
|
||||
* @see https://eslint.org/docs/latest/rules/no-inline-comments
|
||||
*/
|
||||
"no-inline-comments": Linter.RuleEntry<[]>;
|
||||
"no-inline-comments": Linter.RuleEntry<
|
||||
[
|
||||
Partial<{
|
||||
ignorePattern: string;
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
|
||||
/**
|
||||
* Rule to disallow variable or `function` declarations in nested blocks.
|
||||
@@ -2709,7 +2797,17 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
* @since 0.6.0
|
||||
* @see https://eslint.org/docs/latest/rules/no-inner-declarations
|
||||
*/
|
||||
"no-inner-declarations": Linter.RuleEntry<["functions" | "both"]>;
|
||||
"no-inner-declarations": Linter.RuleEntry<
|
||||
[
|
||||
"functions" | "both",
|
||||
Partial<{
|
||||
/**
|
||||
* @default "allow"
|
||||
*/
|
||||
blockScopedFunctions: "allow" | "disallow";
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
|
||||
/**
|
||||
* Rule to disallow invalid regular expression strings in `RegExp` constructors.
|
||||
@@ -2773,6 +2871,10 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
* @default false
|
||||
*/
|
||||
skipTemplates: boolean;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
skipJSXText: boolean;
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
@@ -2861,11 +2963,19 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
/**
|
||||
* @default []
|
||||
*/
|
||||
ignore: number[];
|
||||
ignore: Array<number | string>;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
ignoreArrayIndexes: boolean;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
ignoreDefaultValues: boolean;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
ignoreClassFieldInitialValues: boolean;
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
@@ -2987,7 +3097,16 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
* @since 3.14.0
|
||||
* @see https://eslint.org/docs/latest/rules/no-multi-assign
|
||||
*/
|
||||
"no-multi-assign": Linter.RuleEntry<[]>;
|
||||
"no-multi-assign": Linter.RuleEntry<
|
||||
[
|
||||
Partial<{
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
ignoreNonDeclaration: boolean;
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
|
||||
/**
|
||||
* Rule to disallow multiple spaces.
|
||||
@@ -3441,9 +3560,9 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
paths: Array<
|
||||
string | ValidNoRestrictedImportPathOptions
|
||||
>;
|
||||
patterns: Array<
|
||||
string | ValidNoRestrictedImportPatternOptions
|
||||
>;
|
||||
patterns:
|
||||
| Array<string>
|
||||
| Array<ValidNoRestrictedImportPatternOptions>;
|
||||
}>
|
||||
>,
|
||||
]
|
||||
@@ -3561,7 +3680,16 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
* @since 2.0.0-rc.0
|
||||
* @see https://eslint.org/docs/latest/rules/no-self-assign
|
||||
*/
|
||||
"no-self-assign": Linter.RuleEntry<[]>;
|
||||
"no-self-assign": Linter.RuleEntry<
|
||||
[
|
||||
Partial<{
|
||||
/**
|
||||
* @default true
|
||||
*/
|
||||
props: boolean;
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
|
||||
/**
|
||||
* Rule to disallow comparisons where both sides are exactly the same.
|
||||
@@ -3935,12 +4063,13 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
/**
|
||||
* @default []
|
||||
*/
|
||||
ignore:
|
||||
ignore: Array<
|
||||
| "WhileStatement"
|
||||
| "DoWhileStatement"
|
||||
| "ForStatement"
|
||||
| "ForInStatement"
|
||||
| "ForOfStatement";
|
||||
| "ForOfStatement"
|
||||
>;
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
@@ -4299,7 +4428,7 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
*/
|
||||
"no-warning-comments": Linter.RuleEntry<
|
||||
[
|
||||
{
|
||||
Partial<{
|
||||
/**
|
||||
* @default ["todo", "fixme", "xxx"]
|
||||
*/
|
||||
@@ -4308,7 +4437,8 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
* @default 'start'
|
||||
*/
|
||||
location: "start" | "anywhere";
|
||||
},
|
||||
decoration: string[];
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
|
||||
@@ -4809,6 +4939,23 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
*/
|
||||
"prefer-template": Linter.RuleEntry<[]>;
|
||||
|
||||
/**
|
||||
* Rule to disallow losing originally caught error when re-throwing custom errors.
|
||||
*
|
||||
* @since 9.35.0
|
||||
* @see https://eslint.org/docs/latest/rules/preserve-caught-error
|
||||
*/
|
||||
"preserve-caught-error": Linter.RuleEntry<
|
||||
[
|
||||
Partial<{
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
requireCatchParameter: boolean;
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
|
||||
/**
|
||||
* Rule to require quotes around object literal property names.
|
||||
*
|
||||
@@ -5331,7 +5478,7 @@ export interface ESLintRules extends Linter.RulesRecord {
|
||||
*/
|
||||
enforceForSwitchCase: boolean;
|
||||
/**
|
||||
* @default true
|
||||
* @default false
|
||||
*/
|
||||
enforceForIndexOf: boolean;
|
||||
}>,
|
||||
|
||||
6
node_modules/eslint/package.json
generated
vendored
6
node_modules/eslint/package.json
generated
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "eslint",
|
||||
"version": "9.33.0",
|
||||
"version": "9.36.0",
|
||||
"author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
|
||||
"description": "An AST-based pattern checker for JavaScript.",
|
||||
"type": "commonjs",
|
||||
@@ -104,13 +104,13 @@
|
||||
"homepage": "https://eslint.org",
|
||||
"bugs": "https://github.com/eslint/eslint/issues/",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/eslint-utils": "^4.8.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
"@eslint/config-array": "^0.21.0",
|
||||
"@eslint/config-helpers": "^0.3.1",
|
||||
"@eslint/core": "^0.15.2",
|
||||
"@eslint/eslintrc": "^3.3.1",
|
||||
"@eslint/js": "9.33.0",
|
||||
"@eslint/js": "9.36.0",
|
||||
"@eslint/plugin-kit": "^0.3.5",
|
||||
"@humanfs/node": "^0.16.6",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
|
||||
Reference in New Issue
Block a user